@nuraly/lumenjs 0.1.3 → 0.2.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 (306) hide show
  1. package/README.md +62 -282
  2. package/dist/auth/config.d.ts +23 -0
  3. package/dist/auth/config.js +115 -0
  4. package/dist/auth/guard.d.ts +12 -0
  5. package/dist/auth/guard.js +28 -0
  6. package/dist/auth/index.d.ts +3 -0
  7. package/dist/auth/index.js +1 -0
  8. package/dist/auth/middleware.d.ts +23 -0
  9. package/dist/auth/middleware.js +89 -0
  10. package/dist/auth/native-auth.d.ts +82 -0
  11. package/dist/auth/native-auth.js +340 -0
  12. package/dist/auth/oidc-client.d.ts +17 -0
  13. package/dist/auth/oidc-client.js +123 -0
  14. package/dist/auth/providers/google.d.ts +23 -0
  15. package/dist/auth/providers/google.js +25 -0
  16. package/dist/auth/providers/index.d.ts +2 -0
  17. package/dist/auth/providers/index.js +1 -0
  18. package/dist/auth/routes/login.d.ts +8 -0
  19. package/dist/auth/routes/login.js +121 -0
  20. package/dist/auth/routes/logout.d.ts +4 -0
  21. package/dist/auth/routes/logout.js +79 -0
  22. package/dist/auth/routes/oidc-callback.d.ts +3 -0
  23. package/dist/auth/routes/oidc-callback.js +70 -0
  24. package/dist/auth/routes/password.d.ts +5 -0
  25. package/dist/auth/routes/password.js +149 -0
  26. package/dist/auth/routes/signup.d.ts +3 -0
  27. package/dist/auth/routes/signup.js +81 -0
  28. package/dist/auth/routes/token.d.ts +4 -0
  29. package/dist/auth/routes/token.js +70 -0
  30. package/dist/auth/routes/totp.d.ts +22 -0
  31. package/dist/auth/routes/totp.js +232 -0
  32. package/dist/auth/routes/utils.d.ts +7 -0
  33. package/dist/auth/routes/utils.js +35 -0
  34. package/dist/auth/routes/verify.d.ts +3 -0
  35. package/dist/auth/routes/verify.js +26 -0
  36. package/dist/auth/routes.d.ts +8 -0
  37. package/dist/auth/routes.js +124 -0
  38. package/dist/auth/session.d.ts +8 -0
  39. package/dist/auth/session.js +54 -0
  40. package/dist/auth/token.d.ts +33 -0
  41. package/dist/auth/token.js +90 -0
  42. package/dist/auth/types.d.ts +156 -0
  43. package/dist/auth/types.js +2 -0
  44. package/dist/build/build-client.d.ts +15 -0
  45. package/dist/build/build-client.js +45 -0
  46. package/dist/build/build-prerender.d.ts +11 -0
  47. package/dist/build/build-prerender.js +159 -0
  48. package/dist/build/build-server.d.ts +18 -0
  49. package/dist/build/build-server.js +107 -0
  50. package/dist/build/build.js +60 -123
  51. package/dist/build/scan.d.ts +18 -0
  52. package/dist/build/scan.js +77 -6
  53. package/dist/build/serve-api.js +8 -2
  54. package/dist/build/serve-loaders.d.ts +4 -4
  55. package/dist/build/serve-loaders.js +26 -18
  56. package/dist/build/serve-ssr.js +38 -11
  57. package/dist/build/serve-static.js +3 -3
  58. package/dist/build/serve.js +341 -18
  59. package/dist/cli.js +37 -6
  60. package/dist/communication/encryption.d.ts +35 -0
  61. package/dist/communication/encryption.js +90 -0
  62. package/dist/communication/handlers/context.d.ts +27 -0
  63. package/dist/communication/handlers/context.js +1 -0
  64. package/dist/communication/handlers/conversation.d.ts +24 -0
  65. package/dist/communication/handlers/conversation.js +113 -0
  66. package/dist/communication/handlers/file-upload.d.ts +17 -0
  67. package/dist/communication/handlers/file-upload.js +62 -0
  68. package/dist/communication/handlers/messaging.d.ts +30 -0
  69. package/dist/communication/handlers/messaging.js +237 -0
  70. package/dist/communication/handlers/presence.d.ts +15 -0
  71. package/dist/communication/handlers/presence.js +76 -0
  72. package/dist/communication/handlers.d.ts +5 -0
  73. package/dist/communication/handlers.js +5 -0
  74. package/dist/communication/index.d.ts +9 -0
  75. package/dist/communication/index.js +7 -0
  76. package/dist/communication/link-preview.d.ts +18 -0
  77. package/dist/communication/link-preview.js +115 -0
  78. package/dist/communication/schema.d.ts +10 -0
  79. package/dist/communication/schema.js +101 -0
  80. package/dist/communication/server.d.ts +86 -0
  81. package/dist/communication/server.js +212 -0
  82. package/dist/communication/signaling.d.ts +43 -0
  83. package/dist/communication/signaling.js +271 -0
  84. package/dist/communication/store.d.ts +71 -0
  85. package/dist/communication/store.js +289 -0
  86. package/dist/communication/types.d.ts +454 -0
  87. package/dist/communication/types.js +1 -0
  88. package/dist/create.d.ts +1 -0
  89. package/dist/create.js +55 -0
  90. package/dist/db/auto-migrate.d.ts +3 -0
  91. package/dist/db/auto-migrate.js +100 -0
  92. package/dist/db/client.d.ts +3 -0
  93. package/dist/db/client.js +18 -0
  94. package/dist/db/index.d.ts +17 -13
  95. package/dist/db/index.js +205 -26
  96. package/dist/db/seed.d.ts +12 -0
  97. package/dist/db/seed.js +88 -0
  98. package/dist/db/table.d.ts +10 -0
  99. package/dist/db/table.js +12 -0
  100. package/dist/dev-server/config.d.ts +11 -0
  101. package/dist/dev-server/config.js +40 -20
  102. package/dist/dev-server/index-html.d.ts +4 -0
  103. package/dist/dev-server/index-html.js +21 -6
  104. package/dist/dev-server/nuralyui-aliases.d.ts +0 -4
  105. package/dist/dev-server/nuralyui-aliases.js +115 -94
  106. package/dist/dev-server/plugins/vite-plugin-api-routes.js +29 -5
  107. package/dist/dev-server/plugins/vite-plugin-auth.d.ts +6 -0
  108. package/dist/dev-server/plugins/vite-plugin-auth.js +223 -0
  109. package/dist/dev-server/plugins/vite-plugin-auto-define.d.ts +16 -0
  110. package/dist/dev-server/plugins/vite-plugin-auto-define.js +111 -0
  111. package/dist/dev-server/plugins/vite-plugin-communication.d.ts +6 -0
  112. package/dist/dev-server/plugins/vite-plugin-communication.js +205 -0
  113. package/dist/dev-server/plugins/vite-plugin-editor-api.d.ts +6 -0
  114. package/dist/dev-server/plugins/vite-plugin-editor-api.js +318 -0
  115. package/dist/dev-server/plugins/vite-plugin-i18n.js +69 -2
  116. package/dist/dev-server/plugins/vite-plugin-lit-dedup.d.ts +6 -0
  117. package/dist/dev-server/plugins/vite-plugin-lit-dedup.js +78 -34
  118. package/dist/dev-server/plugins/vite-plugin-lit-hmr.js +44 -2
  119. package/dist/dev-server/plugins/vite-plugin-llms.d.ts +2 -0
  120. package/dist/dev-server/plugins/vite-plugin-llms.js +92 -0
  121. package/dist/dev-server/plugins/vite-plugin-loaders.js +146 -13
  122. package/dist/dev-server/plugins/vite-plugin-routes.js +16 -5
  123. package/dist/dev-server/plugins/vite-plugin-socketio.d.ts +2 -0
  124. package/dist/dev-server/plugins/vite-plugin-socketio.js +51 -0
  125. package/dist/dev-server/plugins/vite-plugin-source-annotator.d.ts +2 -0
  126. package/dist/dev-server/plugins/vite-plugin-source-annotator.js +26 -3
  127. package/dist/dev-server/plugins/vite-plugin-storage.d.ts +10 -0
  128. package/dist/dev-server/plugins/vite-plugin-storage.js +126 -0
  129. package/dist/dev-server/plugins/vite-plugin-virtual-modules.js +140 -3
  130. package/dist/dev-server/server.js +242 -70
  131. package/dist/dev-server/ssr-render.d.ts +2 -1
  132. package/dist/dev-server/ssr-render.js +117 -50
  133. package/dist/editor/ai/backend.d.ts +20 -0
  134. package/dist/editor/ai/backend.js +113 -0
  135. package/dist/editor/ai/claude-code-client.d.ts +20 -0
  136. package/dist/editor/ai/claude-code-client.js +145 -0
  137. package/dist/editor/ai/deepseek-client.d.ts +7 -0
  138. package/dist/editor/ai/deepseek-client.js +113 -0
  139. package/dist/editor/ai/opencode-client.d.ts +14 -0
  140. package/dist/editor/ai/opencode-client.js +99 -0
  141. package/dist/editor/ai/snapshot-store.d.ts +22 -0
  142. package/dist/editor/ai/snapshot-store.js +35 -0
  143. package/dist/editor/ai/types.d.ts +30 -0
  144. package/dist/editor/ai/types.js +136 -0
  145. package/dist/editor/ai-chat-panel.d.ts +13 -0
  146. package/dist/editor/ai-chat-panel.js +613 -0
  147. package/dist/editor/ai-markdown.d.ts +10 -0
  148. package/dist/editor/ai-markdown.js +70 -0
  149. package/dist/editor/ai-project-panel.d.ts +11 -0
  150. package/dist/editor/ai-project-panel.js +332 -0
  151. package/dist/editor/ast-modification.d.ts +11 -0
  152. package/dist/editor/ast-modification.js +1 -0
  153. package/dist/editor/ast-service.d.ts +30 -0
  154. package/dist/editor/ast-service.js +180 -0
  155. package/dist/editor/css-rules.d.ts +54 -0
  156. package/dist/editor/css-rules.js +423 -0
  157. package/dist/editor/editor-api-client.d.ts +51 -0
  158. package/dist/editor/editor-api-client.js +162 -0
  159. package/dist/editor/editor-bridge.d.ts +1 -0
  160. package/dist/editor/editor-bridge.js +18 -8
  161. package/dist/editor/editor-toolbar.d.ts +14 -0
  162. package/dist/editor/editor-toolbar.js +115 -0
  163. package/dist/editor/file-editor.d.ts +9 -0
  164. package/dist/editor/file-editor.js +236 -0
  165. package/dist/editor/file-service.d.ts +16 -0
  166. package/dist/editor/file-service.js +52 -0
  167. package/dist/editor/i18n-key-gen.d.ts +1 -0
  168. package/dist/editor/i18n-key-gen.js +7 -0
  169. package/dist/editor/inline-text-edit.d.ts +5 -0
  170. package/dist/editor/inline-text-edit.js +173 -92
  171. package/dist/editor/overlay-events.d.ts +5 -0
  172. package/dist/editor/overlay-events.js +364 -0
  173. package/dist/editor/overlay-hmr.d.ts +2 -0
  174. package/dist/editor/overlay-hmr.js +76 -0
  175. package/dist/editor/overlay-selection.d.ts +29 -0
  176. package/dist/editor/overlay-selection.js +148 -0
  177. package/dist/editor/overlay-utils.d.ts +12 -0
  178. package/dist/editor/overlay-utils.js +59 -0
  179. package/dist/editor/properties-panel-persist.d.ts +14 -0
  180. package/dist/editor/properties-panel-persist.js +70 -0
  181. package/dist/editor/properties-panel-rows.d.ts +10 -0
  182. package/dist/editor/properties-panel-rows.js +349 -0
  183. package/dist/editor/properties-panel-styles.d.ts +4 -0
  184. package/dist/editor/properties-panel-styles.js +174 -0
  185. package/dist/editor/properties-panel.d.ts +4 -0
  186. package/dist/editor/properties-panel.js +148 -0
  187. package/dist/editor/property-registry.d.ts +16 -0
  188. package/dist/editor/property-registry.js +303 -0
  189. package/dist/editor/standalone-file-panel.d.ts +0 -0
  190. package/dist/editor/standalone-file-panel.js +1 -0
  191. package/dist/editor/standalone-overlay-dom.d.ts +0 -0
  192. package/dist/editor/standalone-overlay-dom.js +1 -0
  193. package/dist/editor/standalone-overlay-styles.d.ts +0 -0
  194. package/dist/editor/standalone-overlay-styles.js +1 -0
  195. package/dist/editor/standalone-overlay.d.ts +1 -0
  196. package/dist/editor/standalone-overlay.js +76 -0
  197. package/dist/editor/syntax-highlighter.d.ts +4 -0
  198. package/dist/editor/syntax-highlighter.js +81 -0
  199. package/dist/editor/text-toolbar.d.ts +11 -0
  200. package/dist/editor/text-toolbar.js +327 -0
  201. package/dist/editor/toolbar-styles.d.ts +4 -0
  202. package/dist/editor/toolbar-styles.js +198 -0
  203. package/dist/email/index.d.ts +32 -0
  204. package/dist/email/index.js +154 -0
  205. package/dist/email/providers/resend.d.ts +2 -0
  206. package/dist/email/providers/resend.js +24 -0
  207. package/dist/email/providers/sendgrid.d.ts +2 -0
  208. package/dist/email/providers/sendgrid.js +31 -0
  209. package/dist/email/providers/smtp.d.ts +13 -0
  210. package/dist/email/providers/smtp.js +125 -0
  211. package/dist/email/template-engine.d.ts +18 -0
  212. package/dist/email/template-engine.js +116 -0
  213. package/dist/email/templates/base.d.ts +9 -0
  214. package/dist/email/templates/base.js +65 -0
  215. package/dist/email/templates/password-reset.d.ts +5 -0
  216. package/dist/email/templates/password-reset.js +15 -0
  217. package/dist/email/templates/verify-email.d.ts +5 -0
  218. package/dist/email/templates/verify-email.js +15 -0
  219. package/dist/email/templates/welcome.d.ts +5 -0
  220. package/dist/email/templates/welcome.js +13 -0
  221. package/dist/email/types.d.ts +49 -0
  222. package/dist/email/types.js +1 -0
  223. package/dist/llms/generate.d.ts +46 -0
  224. package/dist/llms/generate.js +185 -0
  225. package/dist/permissions/guard.d.ts +28 -0
  226. package/dist/permissions/guard.js +30 -0
  227. package/dist/permissions/index.d.ts +6 -0
  228. package/dist/permissions/index.js +3 -0
  229. package/dist/permissions/service.d.ts +80 -0
  230. package/dist/permissions/service.js +210 -0
  231. package/dist/permissions/tables.d.ts +5 -0
  232. package/dist/permissions/tables.js +68 -0
  233. package/dist/permissions/types.d.ts +33 -0
  234. package/dist/permissions/types.js +1 -0
  235. package/dist/runtime/app-shell.d.ts +1 -1
  236. package/dist/runtime/app-shell.js +164 -0
  237. package/dist/runtime/auth.d.ts +10 -0
  238. package/dist/runtime/auth.js +30 -0
  239. package/dist/runtime/communication.d.ts +137 -0
  240. package/dist/runtime/communication.js +228 -0
  241. package/dist/runtime/error-boundary.d.ts +23 -0
  242. package/dist/runtime/error-boundary.js +120 -0
  243. package/dist/runtime/i18n.d.ts +6 -1
  244. package/dist/runtime/i18n.js +42 -21
  245. package/dist/runtime/island.d.ts +16 -0
  246. package/dist/runtime/island.js +80 -0
  247. package/dist/runtime/router-data.d.ts +3 -0
  248. package/dist/runtime/router-data.js +102 -17
  249. package/dist/runtime/router-hydration.js +34 -2
  250. package/dist/runtime/router.d.ts +19 -2
  251. package/dist/runtime/router.js +237 -43
  252. package/dist/runtime/socket-client.d.ts +2 -0
  253. package/dist/runtime/socket-client.js +30 -0
  254. package/dist/runtime/webrtc.d.ts +91 -0
  255. package/dist/runtime/webrtc.js +428 -0
  256. package/dist/shared/dom-shims.js +4 -2
  257. package/dist/shared/graceful-shutdown.d.ts +8 -0
  258. package/dist/shared/graceful-shutdown.js +36 -0
  259. package/dist/shared/health.d.ts +8 -0
  260. package/dist/shared/health.js +25 -0
  261. package/dist/shared/llms-txt.d.ts +31 -0
  262. package/dist/shared/llms-txt.js +85 -0
  263. package/dist/shared/logger.d.ts +32 -0
  264. package/dist/shared/logger.js +93 -0
  265. package/dist/shared/meta.d.ts +27 -0
  266. package/dist/shared/meta.js +71 -0
  267. package/dist/shared/middleware-runner.d.ts +9 -0
  268. package/dist/shared/middleware-runner.js +29 -0
  269. package/dist/shared/rate-limit.d.ts +18 -0
  270. package/dist/shared/rate-limit.js +71 -0
  271. package/dist/shared/request-id.d.ts +5 -0
  272. package/dist/shared/request-id.js +18 -0
  273. package/dist/shared/route-matching.js +16 -1
  274. package/dist/shared/security-headers.d.ts +18 -0
  275. package/dist/shared/security-headers.js +38 -0
  276. package/dist/shared/socket-io-setup.d.ts +11 -0
  277. package/dist/shared/socket-io-setup.js +51 -0
  278. package/dist/shared/types.d.ts +15 -0
  279. package/dist/shared/utils.d.ts +33 -7
  280. package/dist/shared/utils.js +164 -27
  281. package/dist/storage/adapters/local.d.ts +44 -0
  282. package/dist/storage/adapters/local.js +85 -0
  283. package/dist/storage/adapters/s3.d.ts +32 -0
  284. package/dist/storage/adapters/s3.js +119 -0
  285. package/dist/storage/adapters/types.d.ts +53 -0
  286. package/dist/storage/adapters/types.js +1 -0
  287. package/dist/storage/index.d.ts +76 -0
  288. package/dist/storage/index.js +83 -0
  289. package/package.json +45 -7
  290. package/templates/blog/api/posts.ts +4 -18
  291. package/templates/blog/data/migrations/001_init.sql +6 -5
  292. package/templates/blog/lumenjs.config.ts +3 -0
  293. package/templates/blog/package.json +14 -0
  294. package/templates/blog/pages/_layout.ts +25 -0
  295. package/templates/blog/pages/index.ts +48 -22
  296. package/templates/blog/pages/posts/[slug].ts +45 -20
  297. package/templates/blog/pages/tag/[tag].ts +44 -0
  298. package/templates/dashboard/api/stats.ts +8 -5
  299. package/templates/dashboard/lumenjs.config.ts +3 -0
  300. package/templates/dashboard/package.json +14 -0
  301. package/templates/dashboard/pages/_layout.ts +25 -0
  302. package/templates/dashboard/pages/index.ts +54 -23
  303. package/templates/dashboard/pages/settings/index.ts +29 -0
  304. package/templates/default/lumenjs.config.ts +3 -0
  305. package/templates/default/package.json +14 -0
  306. package/templates/default/pages/index.ts +24 -0
@@ -1,5 +1,65 @@
1
1
  import { getI18nConfig, getLocale } from './i18n.js';
2
+ const PREFETCH_TTL = 30_000; // 30 seconds
3
+ const MAX_PREFETCH_CACHE_SIZE = 50;
4
+ const prefetchCache = new Map();
5
+ const inflightRequests = new Map();
6
+ // Periodic sweep of expired prefetch entries (every 60s)
7
+ if (typeof setInterval !== 'undefined') {
8
+ setInterval(() => {
9
+ const now = Date.now();
10
+ for (const [key, entry] of prefetchCache) {
11
+ if (now - entry.timestamp > PREFETCH_TTL)
12
+ prefetchCache.delete(key);
13
+ }
14
+ }, 60_000);
15
+ }
16
+ export function getCachedLoaderData(key) {
17
+ const entry = prefetchCache.get(key);
18
+ if (!entry)
19
+ return undefined;
20
+ if (Date.now() - entry.timestamp > PREFETCH_TTL) {
21
+ prefetchCache.delete(key);
22
+ return undefined;
23
+ }
24
+ return entry.data;
25
+ }
26
+ function setCachedLoaderData(key, data) {
27
+ // Evict oldest entry if cache is full
28
+ if (prefetchCache.size >= MAX_PREFETCH_CACHE_SIZE) {
29
+ const firstKey = prefetchCache.keys().next().value;
30
+ if (firstKey)
31
+ prefetchCache.delete(firstKey);
32
+ }
33
+ prefetchCache.set(key, { data, timestamp: Date.now() });
34
+ }
35
+ export async function prefetchLoaderData(pathname, params) {
36
+ const cacheKey = `page:${pathname}`;
37
+ const cached = getCachedLoaderData(cacheKey);
38
+ if (cached !== undefined)
39
+ return cached;
40
+ const data = await fetchLoaderDataRaw(pathname, params);
41
+ setCachedLoaderData(cacheKey, data);
42
+ return data;
43
+ }
44
+ export async function prefetchLayoutLoaderData(dir) {
45
+ const cacheKey = `layout:${dir}`;
46
+ const cached = getCachedLoaderData(cacheKey);
47
+ if (cached !== undefined)
48
+ return cached;
49
+ const data = await fetchLayoutLoaderDataRaw(dir);
50
+ setCachedLoaderData(cacheKey, data);
51
+ return data;
52
+ }
2
53
  export async function fetchLoaderData(pathname, params) {
54
+ const cacheKey = `page:${pathname}`;
55
+ const cached = getCachedLoaderData(cacheKey);
56
+ if (cached !== undefined) {
57
+ prefetchCache.delete(cacheKey);
58
+ return cached;
59
+ }
60
+ return fetchLoaderDataRaw(pathname, params);
61
+ }
62
+ async function fetchLoaderDataRaw(pathname, params) {
3
63
  const url = new URL(`/__nk_loader${pathname}`, location.origin);
4
64
  if (Object.keys(params).length > 0) {
5
65
  url.searchParams.set('__params', JSON.stringify(params));
@@ -8,30 +68,51 @@ export async function fetchLoaderData(pathname, params) {
8
68
  if (config) {
9
69
  url.searchParams.set('__locale', getLocale());
10
70
  }
11
- const res = await fetch(url.toString());
12
- if (!res.ok) {
13
- throw new Error(`Loader returned ${res.status}`);
14
- }
15
- const data = await res.json();
16
- if (data?.__nk_no_loader)
17
- return undefined;
18
- return data;
71
+ const key = url.toString();
72
+ const inflight = inflightRequests.get(key);
73
+ if (inflight)
74
+ return inflight;
75
+ const promise = fetch(key)
76
+ .then(async (res) => {
77
+ if (!res.ok)
78
+ throw new Error(`Loader returned ${res.status}`);
79
+ const data = await res.json();
80
+ return data?.__nk_no_loader ? undefined : data;
81
+ })
82
+ .finally(() => inflightRequests.delete(key));
83
+ inflightRequests.set(key, promise);
84
+ return promise;
19
85
  }
20
86
  export async function fetchLayoutLoaderData(dir) {
87
+ const cacheKey = `layout:${dir}`;
88
+ const cached = getCachedLoaderData(cacheKey);
89
+ if (cached !== undefined) {
90
+ prefetchCache.delete(cacheKey);
91
+ return cached;
92
+ }
93
+ return fetchLayoutLoaderDataRaw(dir);
94
+ }
95
+ async function fetchLayoutLoaderDataRaw(dir) {
21
96
  const url = new URL(`/__nk_loader/__layout/`, location.origin);
22
97
  url.searchParams.set('__dir', dir);
23
98
  const config = getI18nConfig();
24
99
  if (config) {
25
100
  url.searchParams.set('__locale', getLocale());
26
101
  }
27
- const res = await fetch(url.toString());
28
- if (!res.ok) {
29
- throw new Error(`Layout loader returned ${res.status}`);
30
- }
31
- const data = await res.json();
32
- if (data?.__nk_no_loader)
33
- return undefined;
34
- return data;
102
+ const key = url.toString();
103
+ const inflight = inflightRequests.get(key);
104
+ if (inflight)
105
+ return inflight;
106
+ const promise = fetch(key)
107
+ .then(async (res) => {
108
+ if (!res.ok)
109
+ throw new Error(`Layout loader returned ${res.status}`);
110
+ const data = await res.json();
111
+ return data?.__nk_no_loader ? undefined : data;
112
+ })
113
+ .finally(() => inflightRequests.delete(key));
114
+ inflightRequests.set(key, promise);
115
+ return promise;
35
116
  }
36
117
  export function connectSubscribe(pathname, params) {
37
118
  const url = new URL(`/__nk_subscribe${pathname}`, location.origin);
@@ -53,13 +134,17 @@ export function connectLayoutSubscribe(dir) {
53
134
  }
54
135
  return new EventSource(url.toString());
55
136
  }
137
+ function escapeHtml(text) {
138
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
139
+ }
56
140
  export function render404(pathname) {
141
+ const safe = escapeHtml(pathname);
57
142
  return `<div style="display:flex;align-items:center;justify-content:center;min-height:80vh;font-family:system-ui,-apple-system,sans-serif;padding:2rem">
58
143
  <div style="text-align:center;max-width:400px">
59
144
  <div style="font-size:5rem;font-weight:200;letter-spacing:-2px;color:#cbd5e1;line-height:1">404</div>
60
145
  <div style="width:32px;height:2px;background:#e2e8f0;border-radius:1px;margin:1.25rem auto"></div>
61
146
  <h1 style="font-size:1rem;font-weight:500;color:#334155;margin:1.25rem 0 .5rem">Page not found</h1>
62
- <p style="color:#94a3b8;font-size:.8125rem;line-height:1.5;margin:0 0 2rem"><code style="background:#f8fafc;padding:.125rem .375rem;border-radius:3px;font-size:.75rem;color:#64748b;border:1px solid #f1f5f9">${pathname}</code> doesn't exist</p>
147
+ <p style="color:#94a3b8;font-size:.8125rem;line-height:1.5;margin:0 0 2rem"><code style="background:#f8fafc;padding:.125rem .375rem;border-radius:3px;font-size:.75rem;color:#64748b;border:1px solid #f1f5f9">${safe}</code> doesn't exist</p>
63
148
  <a href="/" style="display:inline-flex;align-items:center;gap:.375rem;padding:.4375rem 1rem;background:#f8fafc;color:#475569;border:1px solid #e2e8f0;border-radius:6px;font-size:.8125rem;font-weight:400;text-decoration:none;transition:all .15s">
64
149
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>
65
150
  Back to home
@@ -15,9 +15,26 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
15
15
  catch { /* ignore */ }
16
16
  i18nScript.remove();
17
17
  }
18
- // Strip locale prefix for route matching (routes are locale-agnostic)
18
+ // Read auth data and init before route matching
19
+ const authScript = document.getElementById('__nk_auth__');
20
+ if (authScript) {
21
+ try {
22
+ const { initAuth } = await import('@lumenjs/auth');
23
+ initAuth(JSON.parse(authScript.textContent || ''));
24
+ }
25
+ catch { }
26
+ authScript.remove();
27
+ }
28
+ // Strip Vite base path and locale prefix for route matching
29
+ let matchPath = location.pathname;
30
+ const base = import.meta.env?.BASE_URL;
31
+ if (base && base !== '/' && matchPath.startsWith(base)) {
32
+ matchPath = '/' + matchPath.slice(base.length);
33
+ }
19
34
  const config = getI18nConfig();
20
- const matchPath = config ? stripLocalePrefix(location.pathname) : location.pathname;
35
+ if (config) {
36
+ matchPath = stripLocalePrefix(matchPath);
37
+ }
21
38
  const match = matchRoute(matchPath);
22
39
  if (!match)
23
40
  return;
@@ -45,6 +62,19 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
45
62
  }
46
63
  }
47
64
  }
65
+ /** Spread loader data as individual properties on an element. */
66
+ const BLOCKED = new Set(['__proto__', 'constructor', 'prototype',
67
+ 'innerHTML', 'outerHTML', 'textContent',
68
+ 'render', 'connectedCallback', 'disconnectedCallback']);
69
+ function spreadData(el, data) {
70
+ if (data && typeof data === 'object') {
71
+ for (const [key, value] of Object.entries(data)) {
72
+ if (!BLOCKED.has(key)) {
73
+ el[key] = value;
74
+ }
75
+ }
76
+ }
77
+ }
48
78
  // Load each layout module and immediately set loaderData on the
49
79
  // existing DOM element BEFORE the next await yields to microtasks.
50
80
  for (const layout of layouts) {
@@ -53,6 +83,7 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
53
83
  const data = layoutDataMap.get(layout.loaderPath ?? '');
54
84
  if (data !== undefined) {
55
85
  existingLayout.loaderData = data;
86
+ spreadData(existingLayout, data);
56
87
  }
57
88
  }
58
89
  if (layout.load && !customElements.get(layout.tagName)) {
@@ -66,6 +97,7 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
66
97
  const existingPage = outlet?.querySelector(match.route.tagName);
67
98
  if (existingPage && pageData !== undefined) {
68
99
  existingPage.loaderData = pageData;
100
+ spreadData(existingPage, pageData);
69
101
  }
70
102
  // Load the page module (registers element, triggers hydration microtask)
71
103
  if (match.route.load && !customElements.get(match.route.tagName)) {
@@ -10,6 +10,8 @@ export interface Route {
10
10
  tagName: string;
11
11
  hasLoader?: boolean;
12
12
  hasSubscribe?: boolean;
13
+ hasSocket?: boolean;
14
+ hasMeta?: boolean;
13
15
  load?: () => Promise<any>;
14
16
  layouts?: LayoutInfo[];
15
17
  pattern?: RegExp;
@@ -26,19 +28,34 @@ export declare class NkRouter {
26
28
  private currentTag;
27
29
  private currentLayoutTags;
28
30
  private subscriptions;
31
+ private _sockets;
32
+ private siteTitle;
29
33
  params: Record<string, string>;
30
34
  constructor(routes: Route[], outlet: HTMLElement, hydrate?: boolean);
31
35
  private compilePattern;
32
36
  private cleanupSubscriptions;
33
- navigate(pathname: string, pushState?: boolean): Promise<void>;
37
+ navigate(fullPath: string, pushState?: boolean): Promise<void>;
38
+ private setupSubscriptions;
34
39
  private matchRoute;
35
40
  private renderRoute;
36
41
  private buildLayoutTree;
42
+ /** Spread loader data as individual properties on an element. */
43
+ private spreadData;
37
44
  private createPageElement;
38
45
  private findPageElement;
46
+ /**
47
+ * Resolve the page title from the route's meta export and update
48
+ * document.title, the aria-live announcer, and focus.
49
+ */
50
+ private updatePageMeta;
39
51
  private handleLinkClick;
40
- /** Strip locale prefix from a path for internal route matching. */
52
+ prefetch(fullPath: string): Promise<void>;
53
+ /** Strip base and locale prefix from a path for internal route matching. */
41
54
  private stripLocale;
42
55
  /** Prepend locale prefix for browser-facing URLs. */
43
56
  private withLocale;
44
57
  }
58
+ /** Navigate via the client-side router. Falls back to full reload for unknown routes. */
59
+ export declare function navigate(href: string): void;
60
+ /** Programmatically prefetch a route's JS chunks and loader data. */
61
+ export declare function prefetch(href: string): void;
@@ -1,6 +1,6 @@
1
- import { fetchLoaderData, fetchLayoutLoaderData, connectSubscribe, connectLayoutSubscribe, render404 } from './router-data.js';
1
+ import { fetchLoaderData, fetchLayoutLoaderData, prefetchLoaderData, prefetchLayoutLoaderData, connectSubscribe, connectLayoutSubscribe, render404 } from './router-data.js';
2
2
  import { hydrateInitialRoute } from './router-hydration.js';
3
- import { getI18nConfig, getLocale, stripLocalePrefix, buildLocalePath } from './i18n.js';
3
+ import { getI18nConfig, getLocale, initI18n, stripLocalePrefix, buildLocalePath } from './i18n.js';
4
4
  /**
5
5
  * Simple client-side router for LumenJS pages.
6
6
  * Handles popstate and link clicks for SPA navigation.
@@ -13,27 +13,79 @@ export class NkRouter {
13
13
  this.currentTag = null;
14
14
  this.currentLayoutTags = [];
15
15
  this.subscriptions = [];
16
+ this._sockets = new Map();
16
17
  this.params = {};
17
18
  this.outlet = outlet;
19
+ this.siteTitle = document.title || 'LumenJS App';
18
20
  this.routes = routes.map(r => ({
19
21
  ...r,
20
22
  ...this.compilePattern(r.path),
21
23
  }));
24
+ // Initialize i18n from inlined data before any rendering
25
+ const i18nScript = document.getElementById('__nk_i18n__');
26
+ if (i18nScript) {
27
+ try {
28
+ const i18nData = JSON.parse(i18nScript.textContent || '');
29
+ initI18n(i18nData.config, i18nData.locale, i18nData.translations);
30
+ }
31
+ catch { /* ignore */ }
32
+ if (!hydrate)
33
+ i18nScript.remove();
34
+ }
22
35
  window.addEventListener('popstate', () => {
23
36
  const path = this.stripLocale(location.pathname);
24
37
  this.navigate(path, false);
25
38
  });
39
+ // Re-run loader when page is restored from bfcache (back/forward on mobile Safari, etc.)
40
+ window.addEventListener('pageshow', (e) => {
41
+ if (e.persisted) {
42
+ const path = this.stripLocale(location.pathname);
43
+ this.navigate(path, false);
44
+ }
45
+ });
26
46
  document.addEventListener('click', (e) => this.handleLinkClick(e));
47
+ window.__nk_navigate = (href) => {
48
+ const path = this.stripLocale(href);
49
+ if (this.matchRoute(path.split('?')[0])) {
50
+ this.navigate(path);
51
+ }
52
+ else {
53
+ window.location.href = href;
54
+ }
55
+ };
56
+ window.__nk_prefetch = (href) => {
57
+ const path = this.stripLocale(href);
58
+ this.prefetch(path);
59
+ };
27
60
  if (hydrate) {
28
61
  hydrateInitialRoute(this.routes, this.outlet, (p) => this.matchRoute(p), (tag, layoutTags, params) => {
29
62
  this.currentTag = tag;
30
63
  this.currentLayoutTags = layoutTags;
31
64
  this.params = params;
32
65
  });
66
+ // Wire up SSE subscriptions after hydration
67
+ const path = this.stripLocale(location.pathname);
68
+ this.setupSubscriptions(path);
33
69
  }
34
70
  else {
35
- const path = this.stripLocale(location.pathname);
36
- this.navigate(path, false);
71
+ // Initialize auth from inlined data before navigating (CSR path)
72
+ const authScript = document.getElementById('__nk_auth__');
73
+ if (authScript) {
74
+ import('@lumenjs/auth').then(({ initAuth }) => {
75
+ try {
76
+ initAuth(JSON.parse(authScript.textContent || ''));
77
+ }
78
+ catch { }
79
+ authScript.remove();
80
+ }).catch(() => { }).finally(() => {
81
+ const path = this.stripLocale(location.pathname);
82
+ this.navigate(path, false);
83
+ });
84
+ }
85
+ else {
86
+ const path = this.stripLocale(location.pathname);
87
+ this.navigate(path, false);
88
+ }
37
89
  }
38
90
  }
39
91
  compilePattern(path) {
@@ -49,9 +101,14 @@ export class NkRouter {
49
101
  es.close();
50
102
  }
51
103
  this.subscriptions = [];
104
+ // Disconnect any active socket.io connections
105
+ for (const [, sock] of this._sockets)
106
+ sock.disconnect();
107
+ this._sockets.clear();
52
108
  }
53
- async navigate(pathname, pushState = true) {
109
+ async navigate(fullPath, pushState = true) {
54
110
  this.cleanupSubscriptions();
111
+ const pathname = fullPath.split('?')[0];
55
112
  const match = this.matchRoute(pathname);
56
113
  if (!match) {
57
114
  if (this.outlet)
@@ -61,51 +118,53 @@ export class NkRouter {
61
118
  return;
62
119
  }
63
120
  if (pushState) {
64
- const localePath = this.withLocale(pathname);
121
+ const localePath = this.withLocale(fullPath);
65
122
  history.pushState(null, '', localePath);
66
123
  window.scrollTo(0, 0);
67
124
  }
68
125
  this.params = match.params;
69
- // Lazy-load the page component if not yet registered
70
- if (match.route.load && !customElements.get(match.route.tagName)) {
71
- await match.route.load();
72
- }
73
- // Load layout components
74
- const layouts = match.route.layouts || [];
75
- for (const layout of layouts) {
76
- if (layout.load && !customElements.get(layout.tagName)) {
77
- await layout.load();
78
- }
79
- }
80
- // Fetch loader data for page
81
- let loaderData = undefined;
82
- if (match.route.hasLoader) {
126
+ // Auth guard: SPA-navigate unauthenticated users to login page
127
+ if (match.route.__nk_has_auth) {
83
128
  try {
84
- loaderData = await fetchLoaderData(pathname, match.params);
85
- }
86
- catch (err) {
87
- console.error('[NkRouter] Loader fetch failed:', err);
88
- }
89
- }
90
- // Fetch loader data for layouts
91
- const layoutDataList = [];
92
- for (const layout of layouts) {
93
- if (layout.hasLoader) {
94
- try {
95
- const data = await fetchLayoutLoaderData(layout.loaderPath || '');
96
- layoutDataList.push(data);
97
- }
98
- catch (err) {
99
- console.error('[NkRouter] Layout loader fetch failed:', err);
100
- layoutDataList.push(undefined);
129
+ const { isAuthenticated } = await import('@lumenjs/auth');
130
+ if (!isAuthenticated()) {
131
+ const loginPath = '/auth/login';
132
+ const loginUrl = `${loginPath}?returnTo=${encodeURIComponent(pathname)}`;
133
+ history.pushState(null, '', loginUrl);
134
+ this.navigate(loginPath, false);
135
+ return;
101
136
  }
102
137
  }
103
- else {
104
- layoutDataList.push(undefined);
105
- }
138
+ catch { }
106
139
  }
140
+ const layouts = match.route.layouts || [];
141
+ // Load all component JS chunks in parallel
142
+ await Promise.all([
143
+ match.route.load && !customElements.get(match.route.tagName) ? match.route.load() : undefined,
144
+ ...layouts.map(l => l.load && !customElements.get(l.tagName) ? l.load() : undefined),
145
+ ]);
146
+ // Fetch all loader data in parallel
147
+ const loaderPromises = [
148
+ match.route.hasLoader
149
+ ? fetchLoaderData(pathname, match.params).catch(err => { console.error('[NkRouter] Loader fetch failed:', err); return undefined; })
150
+ : Promise.resolve(undefined),
151
+ ...layouts.map(layout => layout.hasLoader
152
+ ? fetchLayoutLoaderData(layout.loaderPath || '').catch(err => { console.error('[NkRouter] Layout loader fetch failed:', err); return undefined; })
153
+ : Promise.resolve(undefined)),
154
+ ];
155
+ const [loaderData, ...layoutDataList] = await Promise.all(loaderPromises);
107
156
  this.renderRoute(match.route, loaderData, layouts, layoutDataList);
108
- // Set up SSE subscriptions for page
157
+ // Update document.title and announce route change for screen readers
158
+ this.updatePageMeta(match.route, loaderData);
159
+ // Set up SSE subscriptions
160
+ this.setupSubscriptions(pathname);
161
+ }
162
+ setupSubscriptions(pathname) {
163
+ const match = this.matchRoute(pathname);
164
+ if (!match)
165
+ return;
166
+ const layouts = match.route.layouts || [];
167
+ // Page subscription
109
168
  if (match.route.hasSubscribe) {
110
169
  const es = connectSubscribe(pathname, match.params);
111
170
  es.onmessage = (e) => {
@@ -115,7 +174,43 @@ export class NkRouter {
115
174
  };
116
175
  this.subscriptions.push(es);
117
176
  }
118
- // Set up SSE subscriptions for layouts
177
+ // Page socket (bidirectional via Socket.IO)
178
+ if (match.route.hasSocket) {
179
+ import('socket.io-client').then(({ io }) => {
180
+ const ns = `/nk${pathname === '/' ? '/index' : pathname}`;
181
+ const query = {};
182
+ if (Object.keys(match.params).length > 0)
183
+ query.__params = JSON.stringify(match.params);
184
+ try {
185
+ const locale = getLocale();
186
+ if (locale)
187
+ query.__locale = locale;
188
+ }
189
+ catch { }
190
+ const existing = this._sockets.get(pathname);
191
+ if (existing)
192
+ existing.disconnect();
193
+ const socket = io(ns, { path: '/__nk_socketio/', query });
194
+ this._sockets.set(pathname, socket);
195
+ const injectEmit = () => {
196
+ const pageEl = this.findPageElement(match.route.tagName);
197
+ if (pageEl) {
198
+ pageEl.emit = (event, payload) => {
199
+ socket.emit(`nk:${event}`, payload);
200
+ };
201
+ }
202
+ };
203
+ injectEmit();
204
+ socket.on('nk:data', (data) => {
205
+ const pageEl = this.findPageElement(match.route.tagName);
206
+ if (pageEl) {
207
+ pageEl.liveData = data;
208
+ injectEmit();
209
+ }
210
+ });
211
+ }).catch(err => console.error('[NkRouter] Socket connection failed:', err));
212
+ }
213
+ // Layout subscriptions
119
214
  for (const layout of layouts) {
120
215
  if (layout.hasSubscribe) {
121
216
  const es = connectLayoutSubscribe(layout.loaderPath || '');
@@ -177,6 +272,7 @@ export class NkRouter {
177
272
  }
178
273
  if (layoutDataList && layoutDataList[i] !== undefined) {
179
274
  layoutEl.loaderData = layoutDataList[i];
275
+ this.spreadData(layoutEl, layoutDataList[i]);
180
276
  }
181
277
  parentEl = layoutEl;
182
278
  }
@@ -201,12 +297,14 @@ export class NkRouter {
201
297
  const outerLayout = document.createElement(layouts[0].tagName);
202
298
  if (layoutDataList[0] !== undefined) {
203
299
  outerLayout.loaderData = layoutDataList[0];
300
+ this.spreadData(outerLayout, layoutDataList[0]);
204
301
  }
205
302
  let current = outerLayout;
206
303
  for (let i = 1; i < layouts.length; i++) {
207
304
  const inner = document.createElement(layouts[i].tagName);
208
305
  if (layoutDataList[i] !== undefined) {
209
306
  inner.loaderData = layoutDataList[i];
307
+ this.spreadData(inner, layoutDataList[i]);
210
308
  }
211
309
  current.appendChild(inner);
212
310
  current = inner;
@@ -215,6 +313,19 @@ export class NkRouter {
215
313
  current.appendChild(pageEl);
216
314
  return outerLayout;
217
315
  }
316
+ /** Spread loader data as individual properties on an element. */
317
+ spreadData(el, data) {
318
+ if (data && typeof data === 'object') {
319
+ const BLOCKED = new Set(['__proto__', 'constructor', 'prototype',
320
+ 'innerHTML', 'outerHTML', 'textContent',
321
+ 'render', 'connectedCallback', 'disconnectedCallback']);
322
+ for (const [key, value] of Object.entries(data)) {
323
+ if (!BLOCKED.has(key)) {
324
+ el[key] = value;
325
+ }
326
+ }
327
+ }
328
+ }
218
329
  createPageElement(route, loaderData) {
219
330
  const el = document.createElement(route.tagName);
220
331
  for (const [key, value] of Object.entries(this.params)) {
@@ -222,6 +333,7 @@ export class NkRouter {
222
333
  }
223
334
  if (loaderData !== undefined) {
224
335
  el.loaderData = loaderData;
336
+ this.spreadData(el, loaderData);
225
337
  }
226
338
  return el;
227
339
  }
@@ -230,6 +342,49 @@ export class NkRouter {
230
342
  return null;
231
343
  return this.outlet.querySelector(tagName) ?? this.outlet.querySelector(`${tagName}:last-child`);
232
344
  }
345
+ /**
346
+ * Resolve the page title from the route's meta export and update
347
+ * document.title, the aria-live announcer, and focus.
348
+ */
349
+ async updatePageMeta(route, loaderData) {
350
+ let pageTitle;
351
+ if (route.hasMeta && route.load) {
352
+ try {
353
+ const mod = await route.load();
354
+ if (mod) {
355
+ let meta;
356
+ if (typeof mod.meta === 'function') {
357
+ meta = mod.meta({ data: loaderData, params: this.params });
358
+ }
359
+ else if (mod.meta && typeof mod.meta === 'object') {
360
+ meta = mod.meta;
361
+ }
362
+ if (meta?.title) {
363
+ pageTitle = `${meta.title} | ${this.siteTitle}`;
364
+ }
365
+ }
366
+ }
367
+ catch { /* fall back to site title */ }
368
+ }
369
+ const title = pageTitle || this.siteTitle;
370
+ document.title = title;
371
+ // Let layout components adjust title (e.g. prepend badge counts)
372
+ window.dispatchEvent(new CustomEvent('nk-title-updated'));
373
+ // Announce route change to screen readers
374
+ const announcer = document.getElementById('nk-route-announcer');
375
+ if (announcer) {
376
+ announcer.textContent = '';
377
+ // Use a microtask delay so aria-live picks up the change
378
+ requestAnimationFrame(() => { announcer.textContent = title; });
379
+ }
380
+ // Move focus to the router outlet for keyboard/screen reader users
381
+ if (this.outlet) {
382
+ if (!this.outlet.hasAttribute('tabindex')) {
383
+ this.outlet.setAttribute('tabindex', '-1');
384
+ }
385
+ this.outlet.focus({ preventScroll: true });
386
+ }
387
+ }
233
388
  handleLinkClick(event) {
234
389
  const path = event.composedPath();
235
390
  const anchor = path.find((el) => el instanceof HTMLElement && el.tagName === 'A');
@@ -238,11 +393,34 @@ export class NkRouter {
238
393
  const href = anchor.getAttribute('href');
239
394
  if (!href || href.startsWith('http') || href.startsWith('#') || anchor.hasAttribute('target'))
240
395
  return;
396
+ // Allow modifier-key clicks to behave normally (Ctrl+Click = new tab, etc.)
397
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
398
+ return;
241
399
  event.preventDefault();
242
400
  this.navigate(this.stripLocale(href));
243
401
  }
244
- /** Strip locale prefix from a path for internal route matching. */
402
+ async prefetch(fullPath) {
403
+ const pathname = fullPath.split('?')[0];
404
+ const match = this.matchRoute(pathname);
405
+ if (!match)
406
+ return;
407
+ const layouts = match.route.layouts || [];
408
+ await Promise.all([
409
+ // Preload component JS chunks
410
+ match.route.load && !customElements.get(match.route.tagName) ? match.route.load() : undefined,
411
+ ...layouts.map(l => l.load && !customElements.get(l.tagName) ? l.load() : undefined),
412
+ // Prefetch loader data (cached)
413
+ match.route.hasLoader ? prefetchLoaderData(pathname, match.params).catch(() => { }) : undefined,
414
+ ...layouts.map(l => l.hasLoader ? prefetchLayoutLoaderData(l.loaderPath || '').catch(() => { }) : undefined),
415
+ ]);
416
+ }
417
+ /** Strip base and locale prefix from a path for internal route matching. */
245
418
  stripLocale(path) {
419
+ // Strip Vite base path (e.g. /__app_dev/{id}/) before route matching
420
+ const base = import.meta.env?.BASE_URL;
421
+ if (base && base !== '/' && path.startsWith(base)) {
422
+ path = '/' + path.slice(base.length);
423
+ }
246
424
  const config = getI18nConfig();
247
425
  return config ? stripLocalePrefix(path) : path;
248
426
  }
@@ -252,3 +430,19 @@ export class NkRouter {
252
430
  return config ? buildLocalePath(getLocale(), path) : path;
253
431
  }
254
432
  }
433
+ /** Navigate via the client-side router. Falls back to full reload for unknown routes. */
434
+ export function navigate(href) {
435
+ const nav = window.__nk_navigate;
436
+ if (nav) {
437
+ nav(href);
438
+ }
439
+ else {
440
+ window.location.href = href;
441
+ }
442
+ }
443
+ /** Programmatically prefetch a route's JS chunks and loader data. */
444
+ export function prefetch(href) {
445
+ const pf = window.__nk_prefetch;
446
+ if (pf)
447
+ pf(href);
448
+ }
@@ -0,0 +1,2 @@
1
+ export declare function connectSocket(routePath: string, params: Record<string, string>): Promise<any>;
2
+ export declare function disconnectAllSockets(): void;