@nuraly/lumenjs 0.1.2 → 0.1.4
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.
- package/README.md +76 -235
- package/dist/auth/config.d.ts +23 -0
- package/dist/auth/config.js +115 -0
- package/dist/auth/guard.d.ts +12 -0
- package/dist/auth/guard.js +28 -0
- package/dist/auth/index.d.ts +3 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/middleware.d.ts +23 -0
- package/dist/auth/middleware.js +89 -0
- package/dist/auth/native-auth.d.ts +73 -0
- package/dist/auth/native-auth.js +293 -0
- package/dist/auth/oidc-client.d.ts +17 -0
- package/dist/auth/oidc-client.js +123 -0
- package/dist/auth/providers/google.d.ts +23 -0
- package/dist/auth/providers/google.js +25 -0
- package/dist/auth/providers/index.d.ts +2 -0
- package/dist/auth/providers/index.js +1 -0
- package/dist/auth/routes/login.d.ts +8 -0
- package/dist/auth/routes/login.js +98 -0
- package/dist/auth/routes/logout.d.ts +4 -0
- package/dist/auth/routes/logout.js +79 -0
- package/dist/auth/routes/oidc-callback.d.ts +3 -0
- package/dist/auth/routes/oidc-callback.js +70 -0
- package/dist/auth/routes/password.d.ts +5 -0
- package/dist/auth/routes/password.js +149 -0
- package/dist/auth/routes/signup.d.ts +3 -0
- package/dist/auth/routes/signup.js +81 -0
- package/dist/auth/routes/token.d.ts +4 -0
- package/dist/auth/routes/token.js +70 -0
- package/dist/auth/routes/utils.d.ts +7 -0
- package/dist/auth/routes/utils.js +35 -0
- package/dist/auth/routes/verify.d.ts +3 -0
- package/dist/auth/routes/verify.js +26 -0
- package/dist/auth/routes.d.ts +8 -0
- package/dist/auth/routes.js +110 -0
- package/dist/auth/session.d.ts +8 -0
- package/dist/auth/session.js +54 -0
- package/dist/auth/token.d.ts +33 -0
- package/dist/auth/token.js +90 -0
- package/dist/auth/types.d.ts +156 -0
- package/dist/auth/types.js +2 -0
- package/dist/build/build-client.d.ts +15 -0
- package/dist/build/build-client.js +45 -0
- package/dist/build/build-prerender.d.ts +11 -0
- package/dist/build/build-prerender.js +159 -0
- package/dist/build/build-server.d.ts +17 -0
- package/dist/build/build-server.js +98 -0
- package/dist/build/build.js +52 -120
- package/dist/build/scan.d.ts +19 -0
- package/dist/build/scan.js +77 -6
- package/dist/build/serve-api.js +8 -2
- package/dist/build/serve-loaders.d.ts +4 -2
- package/dist/build/serve-loaders.js +128 -10
- package/dist/build/serve-ssr.js +38 -11
- package/dist/build/serve-static.js +3 -3
- package/dist/build/serve.js +229 -14
- package/dist/cli.js +37 -6
- package/dist/communication/encryption.d.ts +35 -0
- package/dist/communication/encryption.js +90 -0
- package/dist/communication/handlers/context.d.ts +27 -0
- package/dist/communication/handlers/context.js +1 -0
- package/dist/communication/handlers/conversation.d.ts +24 -0
- package/dist/communication/handlers/conversation.js +113 -0
- package/dist/communication/handlers/file-upload.d.ts +17 -0
- package/dist/communication/handlers/file-upload.js +62 -0
- package/dist/communication/handlers/messaging.d.ts +30 -0
- package/dist/communication/handlers/messaging.js +237 -0
- package/dist/communication/handlers/presence.d.ts +15 -0
- package/dist/communication/handlers/presence.js +76 -0
- package/dist/communication/handlers.d.ts +5 -0
- package/dist/communication/handlers.js +5 -0
- package/dist/communication/index.d.ts +9 -0
- package/dist/communication/index.js +7 -0
- package/dist/communication/link-preview.d.ts +18 -0
- package/dist/communication/link-preview.js +115 -0
- package/dist/communication/schema.d.ts +10 -0
- package/dist/communication/schema.js +101 -0
- package/dist/communication/server.d.ts +86 -0
- package/dist/communication/server.js +212 -0
- package/dist/communication/signaling.d.ts +43 -0
- package/dist/communication/signaling.js +271 -0
- package/dist/communication/store.d.ts +71 -0
- package/dist/communication/store.js +289 -0
- package/dist/communication/types.d.ts +454 -0
- package/dist/communication/types.js +1 -0
- package/dist/create.d.ts +1 -0
- package/dist/create.js +55 -0
- package/dist/db/auto-migrate.d.ts +3 -0
- package/dist/db/auto-migrate.js +100 -0
- package/dist/db/client.d.ts +3 -0
- package/dist/db/client.js +18 -0
- package/dist/db/context.d.ts +2 -0
- package/dist/db/context.js +9 -0
- package/dist/db/index.d.ts +23 -0
- package/dist/db/index.js +258 -0
- package/dist/db/seed.d.ts +12 -0
- package/dist/db/seed.js +88 -0
- package/dist/db/table.d.ts +10 -0
- package/dist/db/table.js +12 -0
- package/dist/dev-server/config.d.ts +14 -0
- package/dist/dev-server/config.js +26 -9
- package/dist/dev-server/index-html.d.ts +3 -0
- package/dist/dev-server/index-html.js +18 -6
- package/dist/dev-server/nuralyui-aliases.d.ts +0 -4
- package/dist/dev-server/nuralyui-aliases.js +115 -94
- package/dist/dev-server/plugins/vite-plugin-api-routes.js +29 -5
- package/dist/dev-server/plugins/vite-plugin-auth.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-auth.js +223 -0
- package/dist/dev-server/plugins/vite-plugin-auto-define.d.ts +16 -0
- package/dist/dev-server/plugins/vite-plugin-auto-define.js +111 -0
- package/dist/dev-server/plugins/vite-plugin-communication.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-communication.js +205 -0
- package/dist/dev-server/plugins/vite-plugin-editor-api.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-editor-api.js +318 -0
- package/dist/dev-server/plugins/vite-plugin-i18n.js +69 -2
- package/dist/dev-server/plugins/vite-plugin-lit-dedup.d.ts +6 -0
- package/dist/dev-server/plugins/vite-plugin-lit-dedup.js +78 -34
- package/dist/dev-server/plugins/vite-plugin-lit-hmr.js +44 -2
- package/dist/dev-server/plugins/vite-plugin-llms.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-llms.js +92 -0
- package/dist/dev-server/plugins/vite-plugin-loaders.d.ts +0 -1
- package/dist/dev-server/plugins/vite-plugin-loaders.js +311 -42
- package/dist/dev-server/plugins/vite-plugin-routes.js +18 -6
- package/dist/dev-server/plugins/vite-plugin-socketio.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-socketio.js +51 -0
- package/dist/dev-server/plugins/vite-plugin-source-annotator.d.ts +2 -0
- package/dist/dev-server/plugins/vite-plugin-source-annotator.js +26 -3
- package/dist/dev-server/plugins/vite-plugin-storage.d.ts +10 -0
- package/dist/dev-server/plugins/vite-plugin-storage.js +126 -0
- package/dist/dev-server/plugins/vite-plugin-virtual-modules.js +111 -2
- package/dist/dev-server/server.js +128 -12
- package/dist/dev-server/ssr-render.d.ts +2 -1
- package/dist/dev-server/ssr-render.js +107 -48
- package/dist/editor/ai/backend.d.ts +20 -0
- package/dist/editor/ai/backend.js +104 -0
- package/dist/editor/ai/claude-code-client.d.ts +20 -0
- package/dist/editor/ai/claude-code-client.js +145 -0
- package/dist/editor/ai/opencode-client.d.ts +14 -0
- package/dist/editor/ai/opencode-client.js +125 -0
- package/dist/editor/ai/snapshot-store.d.ts +22 -0
- package/dist/editor/ai/snapshot-store.js +35 -0
- package/dist/editor/ai/types.d.ts +30 -0
- package/dist/editor/ai/types.js +136 -0
- package/dist/editor/ai-chat-panel.d.ts +13 -0
- package/dist/editor/ai-chat-panel.js +587 -0
- package/dist/editor/ai-markdown.d.ts +10 -0
- package/dist/editor/ai-markdown.js +70 -0
- package/dist/editor/ai-project-panel.d.ts +11 -0
- package/dist/editor/ai-project-panel.js +332 -0
- package/dist/editor/ast-modification.d.ts +11 -0
- package/dist/editor/ast-modification.js +1 -0
- package/dist/editor/ast-service.d.ts +30 -0
- package/dist/editor/ast-service.js +180 -0
- package/dist/editor/css-rules.d.ts +54 -0
- package/dist/editor/css-rules.js +423 -0
- package/dist/editor/editor-api-client.d.ts +51 -0
- package/dist/editor/editor-api-client.js +162 -0
- package/dist/editor/editor-bridge.d.ts +1 -0
- package/dist/editor/editor-bridge.js +17 -8
- package/dist/editor/editor-toolbar.d.ts +14 -0
- package/dist/editor/editor-toolbar.js +115 -0
- package/dist/editor/file-editor.d.ts +9 -0
- package/dist/editor/file-editor.js +236 -0
- package/dist/editor/file-service.d.ts +16 -0
- package/dist/editor/file-service.js +52 -0
- package/dist/editor/i18n-key-gen.d.ts +1 -0
- package/dist/editor/i18n-key-gen.js +7 -0
- package/dist/editor/inline-text-edit.d.ts +5 -0
- package/dist/editor/inline-text-edit.js +173 -92
- package/dist/editor/overlay-events.d.ts +5 -0
- package/dist/editor/overlay-events.js +364 -0
- package/dist/editor/overlay-hmr.d.ts +2 -0
- package/dist/editor/overlay-hmr.js +75 -0
- package/dist/editor/overlay-selection.d.ts +29 -0
- package/dist/editor/overlay-selection.js +148 -0
- package/dist/editor/overlay-utils.d.ts +12 -0
- package/dist/editor/overlay-utils.js +59 -0
- package/dist/editor/properties-panel-persist.d.ts +14 -0
- package/dist/editor/properties-panel-persist.js +70 -0
- package/dist/editor/properties-panel-rows.d.ts +10 -0
- package/dist/editor/properties-panel-rows.js +349 -0
- package/dist/editor/properties-panel-styles.d.ts +4 -0
- package/dist/editor/properties-panel-styles.js +174 -0
- package/dist/editor/properties-panel.d.ts +4 -0
- package/dist/editor/properties-panel.js +148 -0
- package/dist/editor/property-registry.d.ts +16 -0
- package/dist/editor/property-registry.js +303 -0
- package/dist/editor/standalone-file-panel.d.ts +0 -0
- package/dist/editor/standalone-file-panel.js +1 -0
- package/dist/editor/standalone-overlay-dom.d.ts +0 -0
- package/dist/editor/standalone-overlay-dom.js +1 -0
- package/dist/editor/standalone-overlay-styles.d.ts +0 -0
- package/dist/editor/standalone-overlay-styles.js +1 -0
- package/dist/editor/standalone-overlay.d.ts +1 -0
- package/dist/editor/standalone-overlay.js +76 -0
- package/dist/editor/syntax-highlighter.d.ts +4 -0
- package/dist/editor/syntax-highlighter.js +81 -0
- package/dist/editor/text-toolbar.d.ts +11 -0
- package/dist/editor/text-toolbar.js +327 -0
- package/dist/editor/toolbar-styles.d.ts +4 -0
- package/dist/editor/toolbar-styles.js +198 -0
- package/dist/email/index.d.ts +32 -0
- package/dist/email/index.js +154 -0
- package/dist/email/providers/resend.d.ts +2 -0
- package/dist/email/providers/resend.js +24 -0
- package/dist/email/providers/sendgrid.d.ts +2 -0
- package/dist/email/providers/sendgrid.js +31 -0
- package/dist/email/providers/smtp.d.ts +13 -0
- package/dist/email/providers/smtp.js +125 -0
- package/dist/email/template-engine.d.ts +18 -0
- package/dist/email/template-engine.js +116 -0
- package/dist/email/templates/base.d.ts +9 -0
- package/dist/email/templates/base.js +65 -0
- package/dist/email/templates/password-reset.d.ts +5 -0
- package/dist/email/templates/password-reset.js +15 -0
- package/dist/email/templates/verify-email.d.ts +5 -0
- package/dist/email/templates/verify-email.js +15 -0
- package/dist/email/templates/welcome.d.ts +5 -0
- package/dist/email/templates/welcome.js +13 -0
- package/dist/email/types.d.ts +49 -0
- package/dist/email/types.js +1 -0
- package/dist/llms/generate.d.ts +46 -0
- package/dist/llms/generate.js +185 -0
- package/dist/permissions/guard.d.ts +28 -0
- package/dist/permissions/guard.js +30 -0
- package/dist/permissions/index.d.ts +6 -0
- package/dist/permissions/index.js +3 -0
- package/dist/permissions/service.d.ts +80 -0
- package/dist/permissions/service.js +210 -0
- package/dist/permissions/tables.d.ts +5 -0
- package/dist/permissions/tables.js +68 -0
- package/dist/permissions/types.d.ts +33 -0
- package/dist/permissions/types.js +1 -0
- package/dist/runtime/app-shell.js +163 -0
- package/dist/runtime/auth.d.ts +10 -0
- package/dist/runtime/auth.js +30 -0
- package/dist/runtime/communication.d.ts +137 -0
- package/dist/runtime/communication.js +228 -0
- package/dist/runtime/error-boundary.d.ts +23 -0
- package/dist/runtime/error-boundary.js +120 -0
- package/dist/runtime/i18n.d.ts +6 -1
- package/dist/runtime/i18n.js +42 -21
- package/dist/runtime/router-data.d.ts +5 -0
- package/dist/runtime/router-data.js +121 -16
- package/dist/runtime/router-hydration.js +25 -0
- package/dist/runtime/router.d.ts +21 -1
- package/dist/runtime/router.js +221 -39
- package/dist/runtime/socket-client.d.ts +2 -0
- package/dist/runtime/socket-client.js +30 -0
- package/dist/runtime/webrtc.d.ts +47 -0
- package/dist/runtime/webrtc.js +178 -0
- package/dist/shared/graceful-shutdown.d.ts +8 -0
- package/dist/shared/graceful-shutdown.js +36 -0
- package/dist/shared/health.d.ts +8 -0
- package/dist/shared/health.js +25 -0
- package/dist/shared/llms-txt.d.ts +31 -0
- package/dist/shared/llms-txt.js +85 -0
- package/dist/shared/logger.d.ts +32 -0
- package/dist/shared/logger.js +93 -0
- package/dist/shared/meta.d.ts +27 -0
- package/dist/shared/meta.js +71 -0
- package/dist/shared/middleware-runner.d.ts +9 -0
- package/dist/shared/middleware-runner.js +29 -0
- package/dist/shared/rate-limit.d.ts +18 -0
- package/dist/shared/rate-limit.js +71 -0
- package/dist/shared/request-id.d.ts +5 -0
- package/dist/shared/request-id.js +18 -0
- package/dist/shared/route-matching.js +16 -1
- package/dist/shared/security-headers.d.ts +18 -0
- package/dist/shared/security-headers.js +38 -0
- package/dist/shared/socket-io-setup.d.ts +11 -0
- package/dist/shared/socket-io-setup.js +51 -0
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/utils.d.ts +37 -7
- package/dist/shared/utils.js +175 -26
- package/dist/storage/adapters/local.d.ts +44 -0
- package/dist/storage/adapters/local.js +85 -0
- package/dist/storage/adapters/s3.d.ts +32 -0
- package/dist/storage/adapters/s3.js +116 -0
- package/dist/storage/adapters/types.d.ts +53 -0
- package/dist/storage/adapters/types.js +1 -0
- package/dist/storage/index.d.ts +76 -0
- package/dist/storage/index.js +83 -0
- package/package.json +20 -1
- package/templates/blog/api/posts.ts +6 -0
- package/templates/blog/data/migrations/001_init.sql +13 -0
- package/templates/blog/lumenjs.config.ts +3 -0
- package/templates/blog/package.json +14 -0
- package/templates/blog/pages/_layout.ts +25 -0
- package/templates/blog/pages/index.ts +65 -0
- package/templates/blog/pages/posts/[slug].ts +60 -0
- package/templates/blog/pages/tag/[tag].ts +44 -0
- package/templates/dashboard/api/stats.ts +10 -0
- package/templates/dashboard/data/migrations/001_init.sql +13 -0
- package/templates/dashboard/lumenjs.config.ts +3 -0
- package/templates/dashboard/package.json +14 -0
- package/templates/dashboard/pages/_layout.ts +25 -0
- package/templates/dashboard/pages/index.ts +72 -0
- package/templates/dashboard/pages/settings/index.ts +29 -0
- package/templates/default/lumenjs.config.ts +3 -0
- package/templates/default/package.json +14 -0
- package/templates/default/pages/index.ts +24 -0
- package/templates/social/api/posts/[id].ts +14 -0
- package/templates/social/api/posts.ts +11 -0
- package/templates/social/api/profile/[username].ts +10 -0
- package/templates/social/api/upload.ts +19 -0
- package/templates/social/data/migrations/001_init.sql +78 -0
- package/templates/social/data/migrations/002_add_image_url.sql +1 -0
- package/templates/social/data/migrations/003_auth.sql +7 -0
- package/templates/social/docs/architecture.md +76 -0
- package/templates/social/docs/components.md +100 -0
- package/templates/social/docs/data.md +89 -0
- package/templates/social/docs/pages.md +96 -0
- package/templates/social/docs/theming.md +52 -0
- package/templates/social/lib/media.ts +130 -0
- package/templates/social/lumenjs.auth.ts +21 -0
- package/templates/social/lumenjs.config.ts +3 -0
- package/templates/social/package.json +5 -0
- package/templates/social/pages/_layout.ts +239 -0
- package/templates/social/pages/apps/[id].ts +173 -0
- package/templates/social/pages/apps/index.ts +116 -0
- package/templates/social/pages/auth/login.ts +92 -0
- package/templates/social/pages/bookmarks.ts +57 -0
- package/templates/social/pages/explore.ts +73 -0
- package/templates/social/pages/index.ts +351 -0
- package/templates/social/pages/messages.ts +298 -0
- package/templates/social/pages/new.ts +77 -0
- package/templates/social/pages/notifications.ts +73 -0
- package/templates/social/pages/post/[id].ts +124 -0
- package/templates/social/pages/profile/[username].ts +100 -0
- package/templates/social/pages/settings/accessibility.ts +153 -0
- package/templates/social/pages/settings/account.ts +260 -0
- package/templates/social/pages/settings/help.ts +141 -0
- package/templates/social/pages/settings/language.ts +103 -0
- package/templates/social/pages/settings/privacy.ts +183 -0
- package/templates/social/pages/settings/security.ts +133 -0
- package/templates/social/pages/settings.ts +185 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <nk-error-boundary> — Client-side error boundary for Lit/web component pages.
|
|
3
|
+
*
|
|
4
|
+
* Wraps page content via <slot>. If a child throws during render or in an
|
|
5
|
+
* event handler, catches the error and displays a fallback UI.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* <nk-error-boundary>
|
|
9
|
+
* <my-page></my-page>
|
|
10
|
+
* </nk-error-boundary>
|
|
11
|
+
*
|
|
12
|
+
* Attributes:
|
|
13
|
+
* fallback-message — Custom message shown on error (default: "Something went wrong")
|
|
14
|
+
*/
|
|
15
|
+
declare class NkErrorBoundary extends HTMLElement {
|
|
16
|
+
private hasError;
|
|
17
|
+
private caughtError;
|
|
18
|
+
connectedCallback(): void;
|
|
19
|
+
disconnectedCallback(): void;
|
|
20
|
+
private handleError;
|
|
21
|
+
private showFallback;
|
|
22
|
+
private recover;
|
|
23
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* <nk-error-boundary> — Client-side error boundary for Lit/web component pages.
|
|
4
|
+
*
|
|
5
|
+
* Wraps page content via <slot>. If a child throws during render or in an
|
|
6
|
+
* event handler, catches the error and displays a fallback UI.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* <nk-error-boundary>
|
|
10
|
+
* <my-page></my-page>
|
|
11
|
+
* </nk-error-boundary>
|
|
12
|
+
*
|
|
13
|
+
* Attributes:
|
|
14
|
+
* fallback-message — Custom message shown on error (default: "Something went wrong")
|
|
15
|
+
*/
|
|
16
|
+
class NkErrorBoundary extends HTMLElement {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.hasError = false;
|
|
20
|
+
this.caughtError = null;
|
|
21
|
+
this.handleError = (event) => {
|
|
22
|
+
event.stopPropagation();
|
|
23
|
+
this.showFallback(event.error || new Error(event.message));
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
connectedCallback() {
|
|
27
|
+
// Listen for unhandled errors from slotted children
|
|
28
|
+
this.addEventListener('error', this.handleError);
|
|
29
|
+
// Create a slot for normal content
|
|
30
|
+
if (!this.shadowRoot) {
|
|
31
|
+
const shadow = this.attachShadow({ mode: 'open' });
|
|
32
|
+
shadow.innerHTML = `
|
|
33
|
+
<style>
|
|
34
|
+
:host { display: contents; }
|
|
35
|
+
.nk-error-fallback {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
padding: 2rem;
|
|
41
|
+
min-height: 200px;
|
|
42
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
43
|
+
color: #dc2626;
|
|
44
|
+
text-align: center;
|
|
45
|
+
}
|
|
46
|
+
.nk-error-fallback h2 {
|
|
47
|
+
margin: 0 0 0.5rem;
|
|
48
|
+
font-size: 1.25rem;
|
|
49
|
+
font-weight: 600;
|
|
50
|
+
}
|
|
51
|
+
.nk-error-fallback p {
|
|
52
|
+
margin: 0 0 1rem;
|
|
53
|
+
color: #6b7280;
|
|
54
|
+
font-size: 0.875rem;
|
|
55
|
+
}
|
|
56
|
+
.nk-error-fallback button {
|
|
57
|
+
padding: 0.5rem 1rem;
|
|
58
|
+
border: 1px solid #d1d5db;
|
|
59
|
+
border-radius: 0.375rem;
|
|
60
|
+
background: white;
|
|
61
|
+
color: #374151;
|
|
62
|
+
font-size: 0.875rem;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
}
|
|
65
|
+
.nk-error-fallback button:hover {
|
|
66
|
+
background: #f9fafb;
|
|
67
|
+
}
|
|
68
|
+
.nk-error-hidden { display: none; }
|
|
69
|
+
</style>
|
|
70
|
+
<slot></slot>
|
|
71
|
+
<div class="nk-error-fallback nk-error-hidden">
|
|
72
|
+
<h2></h2>
|
|
73
|
+
<p></p>
|
|
74
|
+
<button>Try again</button>
|
|
75
|
+
</div>
|
|
76
|
+
`;
|
|
77
|
+
const button = shadow.querySelector('button');
|
|
78
|
+
button.addEventListener('click', () => this.recover());
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
disconnectedCallback() {
|
|
82
|
+
this.removeEventListener('error', this.handleError);
|
|
83
|
+
}
|
|
84
|
+
showFallback(error) {
|
|
85
|
+
this.hasError = true;
|
|
86
|
+
this.caughtError = error;
|
|
87
|
+
const shadow = this.shadowRoot;
|
|
88
|
+
if (!shadow)
|
|
89
|
+
return;
|
|
90
|
+
const slot = shadow.querySelector('slot');
|
|
91
|
+
const fallback = shadow.querySelector('.nk-error-fallback');
|
|
92
|
+
const message = this.getAttribute('fallback-message') || 'Something went wrong';
|
|
93
|
+
slot.classList.add('nk-error-hidden');
|
|
94
|
+
fallback.classList.remove('nk-error-hidden');
|
|
95
|
+
fallback.querySelector('h2').textContent = message;
|
|
96
|
+
fallback.querySelector('p').textContent = error.message || 'An unexpected error occurred.';
|
|
97
|
+
// Dispatch custom event for external error tracking
|
|
98
|
+
this.dispatchEvent(new CustomEvent('nk-error', {
|
|
99
|
+
bubbles: true,
|
|
100
|
+
composed: true,
|
|
101
|
+
detail: { error },
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
recover() {
|
|
105
|
+
this.hasError = false;
|
|
106
|
+
this.caughtError = null;
|
|
107
|
+
const shadow = this.shadowRoot;
|
|
108
|
+
if (!shadow)
|
|
109
|
+
return;
|
|
110
|
+
const slot = shadow.querySelector('slot');
|
|
111
|
+
const fallback = shadow.querySelector('.nk-error-fallback');
|
|
112
|
+
fallback.classList.add('nk-error-hidden');
|
|
113
|
+
slot.classList.remove('nk-error-hidden');
|
|
114
|
+
// Re-trigger the current route to re-render
|
|
115
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!customElements.get('nk-error-boundary')) {
|
|
119
|
+
customElements.define('nk-error-boundary', NkErrorBoundary);
|
|
120
|
+
}
|
package/dist/runtime/i18n.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LumenJS i18n runtime — provides translation lookup, locale management,
|
|
3
3
|
* and translation loading for both SSR and client-side navigation.
|
|
4
|
+
*
|
|
5
|
+
* State is stored on globalThis so that it survives Vite's SSR module
|
|
6
|
+
* invalidation. During dev SSR, page and layout modules may each get a
|
|
7
|
+
* separate copy of this module after cache invalidation — globalThis
|
|
8
|
+
* ensures they all read from the same translation map.
|
|
4
9
|
*/
|
|
5
10
|
/**
|
|
6
11
|
* Look up a translation key. Returns the translated string, or the key itself
|
|
@@ -31,7 +36,7 @@ export declare function initI18n(config: {
|
|
|
31
36
|
}, locale: string, trans: Record<string, string>): void;
|
|
32
37
|
/**
|
|
33
38
|
* Load translations for a locale from the server and swap them in.
|
|
34
|
-
* Used during client-side locale switches.
|
|
39
|
+
* Used during client-side locale switches and HMR updates.
|
|
35
40
|
*/
|
|
36
41
|
export declare function loadTranslations(locale: string): Promise<void>;
|
|
37
42
|
/**
|
package/dist/runtime/i18n.js
CHANGED
|
@@ -1,31 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LumenJS i18n runtime — provides translation lookup, locale management,
|
|
3
3
|
* and translation loading for both SSR and client-side navigation.
|
|
4
|
+
*
|
|
5
|
+
* State is stored on globalThis so that it survives Vite's SSR module
|
|
6
|
+
* invalidation. During dev SSR, page and layout modules may each get a
|
|
7
|
+
* separate copy of this module after cache invalidation — globalThis
|
|
8
|
+
* ensures they all read from the same translation map.
|
|
4
9
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
const G = globalThis;
|
|
11
|
+
if (!G.__nk_i18n) {
|
|
12
|
+
G.__nk_i18n = { locale: 'en', translations: {}, config: null };
|
|
13
|
+
}
|
|
14
|
+
const state = G.__nk_i18n;
|
|
8
15
|
/**
|
|
9
16
|
* Look up a translation key. Returns the translated string, or the key itself
|
|
10
17
|
* if no translation is found.
|
|
11
18
|
*/
|
|
12
19
|
export function t(key) {
|
|
13
|
-
return translations[key] ?? key;
|
|
20
|
+
return state.translations[key] ?? key;
|
|
14
21
|
}
|
|
15
22
|
/** Returns the current locale. */
|
|
16
23
|
export function getLocale() {
|
|
17
|
-
return
|
|
24
|
+
return state.locale;
|
|
18
25
|
}
|
|
19
26
|
/** Returns the i18n config, or null if i18n is not enabled. */
|
|
20
27
|
export function getI18nConfig() {
|
|
21
|
-
return
|
|
28
|
+
return state.config;
|
|
22
29
|
}
|
|
23
30
|
/**
|
|
24
31
|
* Switch to a new locale. Navigates to the same pathname under the new
|
|
25
32
|
* locale prefix and sets the `nk-locale` cookie.
|
|
26
33
|
*/
|
|
27
34
|
export function setLocale(locale) {
|
|
28
|
-
if (!
|
|
35
|
+
if (!state.config || !state.config.locales.includes(locale))
|
|
29
36
|
return;
|
|
30
37
|
document.cookie = `nk-locale=${locale};path=/;max-age=${60 * 60 * 24 * 365};SameSite=Lax`;
|
|
31
38
|
const pathname = stripLocalePrefix(location.pathname);
|
|
@@ -37,13 +44,13 @@ export function setLocale(locale) {
|
|
|
37
44
|
* Called during hydration (from SSR data) or on first load.
|
|
38
45
|
*/
|
|
39
46
|
export function initI18n(config, locale, trans) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
translations = trans;
|
|
47
|
+
state.config = config;
|
|
48
|
+
state.locale = locale;
|
|
49
|
+
state.translations = trans;
|
|
43
50
|
}
|
|
44
51
|
/**
|
|
45
52
|
* Load translations for a locale from the server and swap them in.
|
|
46
|
-
* Used during client-side locale switches.
|
|
53
|
+
* Used during client-side locale switches and HMR updates.
|
|
47
54
|
*/
|
|
48
55
|
export async function loadTranslations(locale) {
|
|
49
56
|
const res = await fetch(`/__nk_i18n/${locale}.json`);
|
|
@@ -51,8 +58,22 @@ export async function loadTranslations(locale) {
|
|
|
51
58
|
console.error(`[i18n] Failed to load translations for locale "${locale}"`);
|
|
52
59
|
return;
|
|
53
60
|
}
|
|
54
|
-
translations = await res.json();
|
|
55
|
-
|
|
61
|
+
state.translations = await res.json();
|
|
62
|
+
state.locale = locale;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Register the HMR reload handler on the global scope.
|
|
66
|
+
* The i18n Vite plugin injects an inline script that calls this function
|
|
67
|
+
* when a locale file changes — ensuring translations are updated in this
|
|
68
|
+
* module instance (not a duplicate created by Vite's cache-busting).
|
|
69
|
+
*/
|
|
70
|
+
if (typeof window !== 'undefined') {
|
|
71
|
+
window.__lumenjs_i18n_reload = async (locale) => {
|
|
72
|
+
if (locale !== state.locale)
|
|
73
|
+
return false;
|
|
74
|
+
await loadTranslations(locale);
|
|
75
|
+
return true;
|
|
76
|
+
};
|
|
56
77
|
}
|
|
57
78
|
/**
|
|
58
79
|
* Strip the locale prefix from a pathname.
|
|
@@ -60,10 +81,10 @@ export async function loadTranslations(locale) {
|
|
|
60
81
|
* /about → /about
|
|
61
82
|
*/
|
|
62
83
|
export function stripLocalePrefix(pathname) {
|
|
63
|
-
if (!
|
|
84
|
+
if (!state.config)
|
|
64
85
|
return pathname;
|
|
65
|
-
for (const loc of
|
|
66
|
-
if (loc ===
|
|
86
|
+
for (const loc of state.config.locales) {
|
|
87
|
+
if (loc === state.config.defaultLocale && !state.config.prefixDefault)
|
|
67
88
|
continue;
|
|
68
89
|
if (pathname === `/${loc}` || pathname.startsWith(`/${loc}/`)) {
|
|
69
90
|
return pathname.slice(loc.length + 1) || '/';
|
|
@@ -77,9 +98,9 @@ export function stripLocalePrefix(pathname) {
|
|
|
77
98
|
* (en, /about) → /about (when prefixDefault=false)
|
|
78
99
|
*/
|
|
79
100
|
export function buildLocalePath(locale, pathname) {
|
|
80
|
-
if (!
|
|
101
|
+
if (!state.config)
|
|
81
102
|
return pathname;
|
|
82
|
-
if (locale ===
|
|
103
|
+
if (locale === state.config.defaultLocale && !state.config.prefixDefault) {
|
|
83
104
|
return pathname;
|
|
84
105
|
}
|
|
85
106
|
return `/${locale}${pathname === '/' ? '' : pathname}` || `/${locale}`;
|
|
@@ -89,12 +110,12 @@ export function buildLocalePath(locale, pathname) {
|
|
|
89
110
|
* Returns the locale and the pathname with the prefix stripped.
|
|
90
111
|
*/
|
|
91
112
|
export function detectLocaleFromPath(pathname) {
|
|
92
|
-
if (!
|
|
113
|
+
if (!state.config)
|
|
93
114
|
return { locale: 'en', pathname };
|
|
94
|
-
for (const loc of
|
|
115
|
+
for (const loc of state.config.locales) {
|
|
95
116
|
if (pathname === `/${loc}` || pathname.startsWith(`/${loc}/`)) {
|
|
96
117
|
return { locale: loc, pathname: pathname.slice(loc.length + 1) || '/' };
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
|
-
return { locale:
|
|
120
|
+
return { locale: state.config.defaultLocale, pathname };
|
|
100
121
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export declare function getCachedLoaderData(key: string): any | undefined;
|
|
2
|
+
export declare function prefetchLoaderData(pathname: string, params: Record<string, string>): Promise<any>;
|
|
3
|
+
export declare function prefetchLayoutLoaderData(dir: string): Promise<any>;
|
|
1
4
|
export declare function fetchLoaderData(pathname: string, params: Record<string, string>): Promise<any>;
|
|
2
5
|
export declare function fetchLayoutLoaderData(dir: string): Promise<any>;
|
|
6
|
+
export declare function connectSubscribe(pathname: string, params: Record<string, string>): EventSource;
|
|
7
|
+
export declare function connectLayoutSubscribe(dir: string): EventSource;
|
|
3
8
|
export declare function render404(pathname: string): string;
|
|
@@ -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,38 +68,83 @@ export async function fetchLoaderData(pathname, params) {
|
|
|
8
68
|
if (config) {
|
|
9
69
|
url.searchParams.set('__locale', getLocale());
|
|
10
70
|
}
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
28
|
-
|
|
29
|
-
|
|
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;
|
|
116
|
+
}
|
|
117
|
+
export function connectSubscribe(pathname, params) {
|
|
118
|
+
const url = new URL(`/__nk_subscribe${pathname}`, location.origin);
|
|
119
|
+
if (Object.keys(params).length > 0) {
|
|
120
|
+
url.searchParams.set('__params', JSON.stringify(params));
|
|
30
121
|
}
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
122
|
+
const config = getI18nConfig();
|
|
123
|
+
if (config) {
|
|
124
|
+
url.searchParams.set('__locale', getLocale());
|
|
125
|
+
}
|
|
126
|
+
return new EventSource(url.toString());
|
|
127
|
+
}
|
|
128
|
+
export function connectLayoutSubscribe(dir) {
|
|
129
|
+
const url = new URL('/__nk_subscribe/__layout/', location.origin);
|
|
130
|
+
url.searchParams.set('__dir', dir);
|
|
131
|
+
const config = getI18nConfig();
|
|
132
|
+
if (config) {
|
|
133
|
+
url.searchParams.set('__locale', getLocale());
|
|
134
|
+
}
|
|
135
|
+
return new EventSource(url.toString());
|
|
136
|
+
}
|
|
137
|
+
function escapeHtml(text) {
|
|
138
|
+
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
35
139
|
}
|
|
36
140
|
export function render404(pathname) {
|
|
141
|
+
const safe = escapeHtml(pathname);
|
|
37
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">
|
|
38
143
|
<div style="text-align:center;max-width:400px">
|
|
39
144
|
<div style="font-size:5rem;font-weight:200;letter-spacing:-2px;color:#cbd5e1;line-height:1">404</div>
|
|
40
145
|
<div style="width:32px;height:2px;background:#e2e8f0;border-radius:1px;margin:1.25rem auto"></div>
|
|
41
146
|
<h1 style="font-size:1rem;font-weight:500;color:#334155;margin:1.25rem 0 .5rem">Page not found</h1>
|
|
42
|
-
<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">${
|
|
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>
|
|
43
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">
|
|
44
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>
|
|
45
150
|
Back to home
|
|
@@ -15,6 +15,16 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
|
|
|
15
15
|
catch { /* ignore */ }
|
|
16
16
|
i18nScript.remove();
|
|
17
17
|
}
|
|
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
|
+
}
|
|
18
28
|
// Strip locale prefix for route matching (routes are locale-agnostic)
|
|
19
29
|
const config = getI18nConfig();
|
|
20
30
|
const matchPath = config ? stripLocalePrefix(location.pathname) : location.pathname;
|
|
@@ -45,6 +55,19 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
|
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
}
|
|
58
|
+
/** Spread loader data as individual properties on an element. */
|
|
59
|
+
const BLOCKED = new Set(['__proto__', 'constructor', 'prototype',
|
|
60
|
+
'innerHTML', 'outerHTML', 'textContent',
|
|
61
|
+
'render', 'connectedCallback', 'disconnectedCallback']);
|
|
62
|
+
function spreadData(el, data) {
|
|
63
|
+
if (data && typeof data === 'object') {
|
|
64
|
+
for (const [key, value] of Object.entries(data)) {
|
|
65
|
+
if (!BLOCKED.has(key)) {
|
|
66
|
+
el[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
48
71
|
// Load each layout module and immediately set loaderData on the
|
|
49
72
|
// existing DOM element BEFORE the next await yields to microtasks.
|
|
50
73
|
for (const layout of layouts) {
|
|
@@ -53,6 +76,7 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
|
|
|
53
76
|
const data = layoutDataMap.get(layout.loaderPath ?? '');
|
|
54
77
|
if (data !== undefined) {
|
|
55
78
|
existingLayout.loaderData = data;
|
|
79
|
+
spreadData(existingLayout, data);
|
|
56
80
|
}
|
|
57
81
|
}
|
|
58
82
|
if (layout.load && !customElements.get(layout.tagName)) {
|
|
@@ -66,6 +90,7 @@ export async function hydrateInitialRoute(routes, outlet, matchRoute, onHydrated
|
|
|
66
90
|
const existingPage = outlet?.querySelector(match.route.tagName);
|
|
67
91
|
if (existingPage && pageData !== undefined) {
|
|
68
92
|
existingPage.loaderData = pageData;
|
|
93
|
+
spreadData(existingPage, pageData);
|
|
69
94
|
}
|
|
70
95
|
// Load the page module (registers element, triggers hydration microtask)
|
|
71
96
|
if (match.route.load && !customElements.get(match.route.tagName)) {
|
package/dist/runtime/router.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface LayoutInfo {
|
|
2
2
|
tagName: string;
|
|
3
3
|
hasLoader?: boolean;
|
|
4
|
+
hasSubscribe?: boolean;
|
|
4
5
|
load?: () => Promise<any>;
|
|
5
6
|
loaderPath?: string;
|
|
6
7
|
}
|
|
@@ -8,6 +9,8 @@ export interface Route {
|
|
|
8
9
|
path: string;
|
|
9
10
|
tagName: string;
|
|
10
11
|
hasLoader?: boolean;
|
|
12
|
+
hasSubscribe?: boolean;
|
|
13
|
+
hasMeta?: boolean;
|
|
11
14
|
load?: () => Promise<any>;
|
|
12
15
|
layouts?: LayoutInfo[];
|
|
13
16
|
pattern?: RegExp;
|
|
@@ -23,17 +26,34 @@ export declare class NkRouter {
|
|
|
23
26
|
private outlet;
|
|
24
27
|
private currentTag;
|
|
25
28
|
private currentLayoutTags;
|
|
29
|
+
private subscriptions;
|
|
30
|
+
private siteTitle;
|
|
26
31
|
params: Record<string, string>;
|
|
27
32
|
constructor(routes: Route[], outlet: HTMLElement, hydrate?: boolean);
|
|
28
33
|
private compilePattern;
|
|
29
|
-
|
|
34
|
+
private cleanupSubscriptions;
|
|
35
|
+
navigate(fullPath: string, pushState?: boolean): Promise<void>;
|
|
36
|
+
private setupSubscriptions;
|
|
30
37
|
private matchRoute;
|
|
31
38
|
private renderRoute;
|
|
32
39
|
private buildLayoutTree;
|
|
40
|
+
/** Spread loader data as individual properties on an element. */
|
|
41
|
+
private spreadData;
|
|
33
42
|
private createPageElement;
|
|
43
|
+
private findPageElement;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the page title from the route's meta export and update
|
|
46
|
+
* document.title, the aria-live announcer, and focus.
|
|
47
|
+
*/
|
|
48
|
+
private updatePageMeta;
|
|
34
49
|
private handleLinkClick;
|
|
50
|
+
prefetch(fullPath: string): Promise<void>;
|
|
35
51
|
/** Strip locale prefix from a path for internal route matching. */
|
|
36
52
|
private stripLocale;
|
|
37
53
|
/** Prepend locale prefix for browser-facing URLs. */
|
|
38
54
|
private withLocale;
|
|
39
55
|
}
|
|
56
|
+
/** Navigate via the client-side router. Falls back to full reload for unknown routes. */
|
|
57
|
+
export declare function navigate(href: string): void;
|
|
58
|
+
/** Programmatically prefetch a route's JS chunks and loader data. */
|
|
59
|
+
export declare function prefetch(href: string): void;
|