@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
package/dist/build/serve-api.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { readBody } from '../shared/utils.js';
|
|
4
4
|
import { matchRoute } from '../shared/route-matching.js';
|
|
5
|
+
import { useStorage } from '../storage/index.js';
|
|
5
6
|
export async function handleApiRoute(manifest, serverDir, pathname, queryString, method, req, res) {
|
|
6
7
|
const matched = matchRoute(manifest.apiRoutes, pathname);
|
|
7
8
|
if (!matched) {
|
|
@@ -9,7 +10,9 @@ export async function handleApiRoute(manifest, serverDir, pathname, queryString,
|
|
|
9
10
|
res.end(JSON.stringify({ error: 'API route not found' }));
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
// Vite replaces [param] with _param_ in output filenames
|
|
14
|
+
const resolvedModule = matched.route.module.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
15
|
+
const modulePath = path.join(serverDir, resolvedModule);
|
|
13
16
|
if (!fs.existsSync(modulePath)) {
|
|
14
17
|
res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
15
18
|
res.end(JSON.stringify({ error: 'API route module not found' }));
|
|
@@ -43,13 +46,16 @@ export async function handleApiRoute(manifest, serverDir, pathname, queryString,
|
|
|
43
46
|
params: matched.params,
|
|
44
47
|
body,
|
|
45
48
|
headers: req.headers,
|
|
49
|
+
storage: useStorage(),
|
|
50
|
+
nkAuth: req.nkAuth,
|
|
46
51
|
});
|
|
47
52
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
48
53
|
res.end(JSON.stringify(result));
|
|
49
54
|
}
|
|
50
55
|
catch (err) {
|
|
51
56
|
const status = err?.status || 500;
|
|
52
|
-
|
|
57
|
+
// Only expose error messages for client errors (4xx); hide internals for 5xx
|
|
58
|
+
const message = status < 500 ? (err?.message || 'Request error') : 'Internal server error';
|
|
53
59
|
res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
54
60
|
res.end(JSON.stringify({ error: message }));
|
|
55
61
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
import type { BuildManifest } from '../shared/types.js';
|
|
3
|
-
export declare function handleLayoutLoaderRequest(manifest: BuildManifest, serverDir: string, queryString: string | undefined, headers: http.IncomingHttpHeaders, res: http.ServerResponse): Promise<void>;
|
|
4
|
-
export declare function
|
|
3
|
+
export declare function handleLayoutLoaderRequest(manifest: BuildManifest, serverDir: string, queryString: string | undefined, headers: http.IncomingHttpHeaders, res: http.ServerResponse, user?: any): Promise<void>;
|
|
4
|
+
export declare function handleLayoutSubscribeRequest(manifest: BuildManifest, serverDir: string, queryString: string | undefined, headers: http.IncomingHttpHeaders, res: http.ServerResponse, user?: any): Promise<void>;
|
|
5
|
+
export declare function handleSubscribeRequest(manifest: BuildManifest, serverDir: string, pagesDir: string, pathname: string, queryString: string | undefined, headers: http.IncomingHttpHeaders, res: http.ServerResponse, user?: any): Promise<void>;
|
|
6
|
+
export declare function handleLoaderRequest(manifest: BuildManifest, serverDir: string, pagesDir: string, pathname: string, queryString: string | undefined, headers: http.IncomingHttpHeaders, res: http.ServerResponse, user?: any): Promise<void>;
|
|
@@ -2,7 +2,15 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { isRedirectResponse } from '../shared/utils.js';
|
|
4
4
|
import { matchRoute } from '../shared/route-matching.js';
|
|
5
|
-
|
|
5
|
+
import { logger } from '../shared/logger.js';
|
|
6
|
+
/** Resolve a module path, falling back to bracket-sanitized filename (Rollup replaces [] with _) */
|
|
7
|
+
function resolveModulePath(serverDir, moduleName) {
|
|
8
|
+
const p = path.join(serverDir, moduleName);
|
|
9
|
+
if (fs.existsSync(p))
|
|
10
|
+
return p;
|
|
11
|
+
return path.join(serverDir, moduleName.replace(/\[/g, '_').replace(/\]/g, '_'));
|
|
12
|
+
}
|
|
13
|
+
export async function handleLayoutLoaderRequest(manifest, serverDir, queryString, headers, res, user) {
|
|
6
14
|
const query = {};
|
|
7
15
|
if (queryString) {
|
|
8
16
|
for (const pair of queryString.split('&')) {
|
|
@@ -18,7 +26,7 @@ export async function handleLayoutLoaderRequest(manifest, serverDir, queryString
|
|
|
18
26
|
res.end(JSON.stringify({ __nk_no_loader: true }));
|
|
19
27
|
return;
|
|
20
28
|
}
|
|
21
|
-
const modulePath =
|
|
29
|
+
const modulePath = resolveModulePath(serverDir, layout.module);
|
|
22
30
|
if (!fs.existsSync(modulePath)) {
|
|
23
31
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
24
32
|
res.end(JSON.stringify({ __nk_no_loader: true }));
|
|
@@ -34,7 +42,7 @@ export async function handleLayoutLoaderRequest(manifest, serverDir, queryString
|
|
|
34
42
|
// Parse locale from query for layout loader
|
|
35
43
|
const locale = query.__locale;
|
|
36
44
|
delete query.__locale;
|
|
37
|
-
const result = await mod.loader({ params: {}, query: {}, url: `/__layout/${dir}`, headers, locale });
|
|
45
|
+
const result = await mod.loader({ params: {}, query: {}, url: `/__layout/${dir}`, headers, locale, user: user ?? null });
|
|
38
46
|
if (isRedirectResponse(result)) {
|
|
39
47
|
res.writeHead(result.status || 302, { Location: result.location });
|
|
40
48
|
res.end();
|
|
@@ -49,14 +57,124 @@ export async function handleLayoutLoaderRequest(manifest, serverDir, queryString
|
|
|
49
57
|
res.end();
|
|
50
58
|
return;
|
|
51
59
|
}
|
|
52
|
-
|
|
60
|
+
logger.error(`Layout loader error`, { dir, error: err?.message });
|
|
53
61
|
const status = err?.status || 500;
|
|
54
|
-
const message = err?.message || 'Layout loader failed';
|
|
62
|
+
const message = status < 500 ? (err?.message || 'Layout loader failed') : 'Internal server error';
|
|
55
63
|
res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
56
64
|
res.end(JSON.stringify({ error: message }));
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
|
-
export async function
|
|
67
|
+
export async function handleLayoutSubscribeRequest(manifest, serverDir, queryString, headers, res, user) {
|
|
68
|
+
const query = {};
|
|
69
|
+
if (queryString) {
|
|
70
|
+
for (const pair of queryString.split('&')) {
|
|
71
|
+
const [key, val] = pair.split('=');
|
|
72
|
+
query[decodeURIComponent(key)] = decodeURIComponent(val || '');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const dir = query.__dir || '';
|
|
76
|
+
const layout = (manifest.layouts || []).find(l => l.dir === dir);
|
|
77
|
+
if (!layout || !layout.hasSubscribe || !layout.module) {
|
|
78
|
+
res.writeHead(204);
|
|
79
|
+
res.end();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const modulePath = resolveModulePath(serverDir, layout.module);
|
|
83
|
+
if (!fs.existsSync(modulePath)) {
|
|
84
|
+
res.writeHead(204);
|
|
85
|
+
res.end();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const mod = await import(modulePath);
|
|
90
|
+
if (!mod.subscribe || typeof mod.subscribe !== 'function') {
|
|
91
|
+
res.writeHead(204);
|
|
92
|
+
res.end();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
res.writeHead(200, {
|
|
96
|
+
'Content-Type': 'text/event-stream',
|
|
97
|
+
'Cache-Control': 'no-cache',
|
|
98
|
+
'Connection': 'keep-alive',
|
|
99
|
+
});
|
|
100
|
+
const locale = query.__locale;
|
|
101
|
+
const push = (data) => {
|
|
102
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
103
|
+
};
|
|
104
|
+
const cleanup = mod.subscribe({ params: {}, push, headers, locale, user: user ?? null });
|
|
105
|
+
res.on('close', () => {
|
|
106
|
+
if (typeof cleanup === 'function')
|
|
107
|
+
cleanup();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
logger.error(`Layout subscribe error`, { dir, error: err?.message });
|
|
112
|
+
if (!res.headersSent) {
|
|
113
|
+
res.writeHead(500);
|
|
114
|
+
res.end();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export async function handleSubscribeRequest(manifest, serverDir, pagesDir, pathname, queryString, headers, res, user) {
|
|
119
|
+
const pagePath = pathname.replace('/__nk_subscribe', '') || '/';
|
|
120
|
+
const query = {};
|
|
121
|
+
if (queryString) {
|
|
122
|
+
for (const pair of queryString.split('&')) {
|
|
123
|
+
const [key, val] = pair.split('=');
|
|
124
|
+
query[decodeURIComponent(key)] = decodeURIComponent(val || '');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
let params = {};
|
|
128
|
+
if (query.__params) {
|
|
129
|
+
try {
|
|
130
|
+
params = JSON.parse(query.__params);
|
|
131
|
+
}
|
|
132
|
+
catch { /* ignore */ }
|
|
133
|
+
delete query.__params;
|
|
134
|
+
}
|
|
135
|
+
const matched = matchRoute(manifest.routes.filter(r => r.hasSubscribe), pagePath);
|
|
136
|
+
if (!matched || !matched.route.module) {
|
|
137
|
+
res.writeHead(204);
|
|
138
|
+
res.end();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const modulePath = resolveModulePath(serverDir, matched.route.module);
|
|
142
|
+
if (!fs.existsSync(modulePath)) {
|
|
143
|
+
res.writeHead(204);
|
|
144
|
+
res.end();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const mod = await import(modulePath);
|
|
149
|
+
if (!mod.subscribe || typeof mod.subscribe !== 'function') {
|
|
150
|
+
res.writeHead(204);
|
|
151
|
+
res.end();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
res.writeHead(200, {
|
|
155
|
+
'Content-Type': 'text/event-stream',
|
|
156
|
+
'Cache-Control': 'no-cache',
|
|
157
|
+
'Connection': 'keep-alive',
|
|
158
|
+
});
|
|
159
|
+
const locale = query.__locale;
|
|
160
|
+
const push = (data) => {
|
|
161
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
162
|
+
};
|
|
163
|
+
const cleanup = mod.subscribe({ params: matched.params, push, headers, locale, user: user ?? null });
|
|
164
|
+
res.on('close', () => {
|
|
165
|
+
if (typeof cleanup === 'function')
|
|
166
|
+
cleanup();
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
logger.error(`Subscribe error`, { pagePath, error: err?.message });
|
|
171
|
+
if (!res.headersSent) {
|
|
172
|
+
res.writeHead(500);
|
|
173
|
+
res.end();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export async function handleLoaderRequest(manifest, serverDir, pagesDir, pathname, queryString, headers, res, user) {
|
|
60
178
|
const pagePath = pathname.replace('/__nk_loader', '') || '/';
|
|
61
179
|
// Parse query params
|
|
62
180
|
const query = {};
|
|
@@ -81,7 +199,7 @@ export async function handleLoaderRequest(manifest, serverDir, pagesDir, pathnam
|
|
|
81
199
|
res.end(JSON.stringify({ __nk_no_loader: true }));
|
|
82
200
|
return;
|
|
83
201
|
}
|
|
84
|
-
const modulePath =
|
|
202
|
+
const modulePath = resolveModulePath(serverDir, matched.route.module);
|
|
85
203
|
if (!fs.existsSync(modulePath)) {
|
|
86
204
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
87
205
|
res.end(JSON.stringify({ __nk_no_loader: true }));
|
|
@@ -96,7 +214,7 @@ export async function handleLoaderRequest(manifest, serverDir, pagesDir, pathnam
|
|
|
96
214
|
}
|
|
97
215
|
const locale = query.__locale;
|
|
98
216
|
delete query.__locale;
|
|
99
|
-
const result = await mod.loader({ params: matched.params, query, url: pagePath, headers, locale });
|
|
217
|
+
const result = await mod.loader({ params: matched.params, query, url: pagePath, headers, locale, user: user ?? null });
|
|
100
218
|
if (isRedirectResponse(result)) {
|
|
101
219
|
res.writeHead(result.status || 302, { Location: result.location });
|
|
102
220
|
res.end();
|
|
@@ -111,9 +229,9 @@ export async function handleLoaderRequest(manifest, serverDir, pagesDir, pathnam
|
|
|
111
229
|
res.end();
|
|
112
230
|
return;
|
|
113
231
|
}
|
|
114
|
-
|
|
232
|
+
logger.error(`Loader error`, { pagePath, error: err?.message });
|
|
115
233
|
const status = err?.status || 500;
|
|
116
|
-
const message = err?.message || 'Loader failed';
|
|
234
|
+
const message = status < 500 ? (err?.message || 'Loader failed') : 'Internal server error';
|
|
117
235
|
res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
118
236
|
res.end(JSON.stringify({ error: message }));
|
|
119
237
|
}
|
package/dist/build/serve-ssr.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { stripOuterLitMarkers, dirToLayoutTagName, isRedirectResponse } from '../shared/utils.js';
|
|
3
|
+
import { stripOuterLitMarkers, dirToLayoutTagName, isRedirectResponse, patchLoaderDataSpread } from '../shared/utils.js';
|
|
4
4
|
import { matchRoute } from '../shared/route-matching.js';
|
|
5
5
|
import { sendCompressed } from './serve-static.js';
|
|
6
|
+
import { logger } from '../shared/logger.js';
|
|
6
7
|
export async function handlePageRoute(manifest, serverDir, pagesDir, pathname, queryString, indexHtmlShell, title, ssrRuntime, req, res) {
|
|
7
8
|
// Find matching route (any route, not just those with loaders)
|
|
8
9
|
const allMatched = matchRoute(manifest.routes, pathname);
|
|
9
10
|
// Try SSR for routes with loaders
|
|
10
11
|
const matched = matchRoute(manifest.routes.filter(r => r.hasLoader), pathname);
|
|
11
12
|
if (matched && matched.route.module) {
|
|
12
|
-
|
|
13
|
+
// Rollup sanitizes brackets in filenames: [...path] → _...path_
|
|
14
|
+
let modulePath = path.join(serverDir, matched.route.module);
|
|
15
|
+
if (!fs.existsSync(modulePath)) {
|
|
16
|
+
modulePath = path.join(serverDir, matched.route.module.replace(/\[/g, '_').replace(/\]/g, '_'));
|
|
17
|
+
}
|
|
13
18
|
if (fs.existsSync(modulePath)) {
|
|
14
19
|
try {
|
|
15
20
|
const mod = await import(modulePath);
|
|
16
21
|
// Run loader
|
|
17
22
|
let loaderData = undefined;
|
|
18
23
|
if (mod.loader && typeof mod.loader === 'function') {
|
|
19
|
-
loaderData = await mod.loader({ params: matched.params, query: {}, url: pathname, headers: req.headers });
|
|
24
|
+
loaderData = await mod.loader({ params: matched.params, query: {}, url: pathname, headers: req.headers, user: req.nkAuth?.user ?? null });
|
|
20
25
|
if (isRedirectResponse(loaderData)) {
|
|
21
26
|
res.writeHead(loaderData.status || 302, { Location: loaderData.location });
|
|
22
27
|
res.end();
|
|
@@ -39,7 +44,7 @@ export async function handlePageRoute(manifest, serverDir, pagesDir, pathname, q
|
|
|
39
44
|
if (fs.existsSync(layoutModulePath)) {
|
|
40
45
|
const layoutMod = await import(layoutModulePath);
|
|
41
46
|
if (layoutMod.loader && typeof layoutMod.loader === 'function') {
|
|
42
|
-
layoutLoaderData = await layoutMod.loader({ params: {}, query: {}, url: pathname, headers: req.headers });
|
|
47
|
+
layoutLoaderData = await layoutMod.loader({ params: {}, query: {}, url: pathname, headers: req.headers, user: req.nkAuth?.user ?? null });
|
|
43
48
|
if (isRedirectResponse(layoutLoaderData)) {
|
|
44
49
|
res.writeHead(layoutLoaderData.status || 302, { Location: layoutLoaderData.location });
|
|
45
50
|
res.end();
|
|
@@ -52,6 +57,12 @@ export async function handlePageRoute(manifest, serverDir, pagesDir, pathname, q
|
|
|
52
57
|
layoutsData.push({ loaderPath: dir, data: layoutLoaderData });
|
|
53
58
|
layoutModules.push({ tagName: layoutTagName, loaderData: layoutLoaderData });
|
|
54
59
|
}
|
|
60
|
+
// Patch element classes to spread loaderData into individual properties
|
|
61
|
+
for (const lm of layoutModules) {
|
|
62
|
+
patchLoaderDataSpread(lm.tagName);
|
|
63
|
+
}
|
|
64
|
+
if (tagName)
|
|
65
|
+
patchLoaderDataSpread(tagName);
|
|
55
66
|
if (tagName && ssrRuntime) {
|
|
56
67
|
// SSR render with the bundled @lit-labs/ssr runtime
|
|
57
68
|
try {
|
|
@@ -90,14 +101,18 @@ export async function handlePageRoute(manifest, serverDir, pagesDir, pathname, q
|
|
|
90
101
|
const loaderDataScript = ssrDataObj !== undefined
|
|
91
102
|
? `<script type="application/json" id="__nk_ssr_data__">${JSON.stringify(ssrDataObj).replace(/</g, '\\u003c')}</script>`
|
|
92
103
|
: '';
|
|
93
|
-
|
|
104
|
+
// Auth: inline user data for client hydration
|
|
105
|
+
const authUser = req.nkAuth?.user ?? null;
|
|
106
|
+
const authScript = authUser
|
|
107
|
+
? `<script type="application/json" id="__nk_auth__">${JSON.stringify(authUser).replace(/</g, '\\u003c')}</script>`
|
|
108
|
+
: '';
|
|
94
109
|
let html_out = indexHtmlShell;
|
|
95
|
-
html_out = html_out.replace(/<nk-app><\/nk-app>/, `${loaderDataScript}<nk-app data-nk-ssr><div id="nk-router-outlet">${ssrHtml}</div></nk-app
|
|
110
|
+
html_out = html_out.replace(/<nk-app><\/nk-app>/, `${authScript}${loaderDataScript}<nk-app data-nk-ssr><div id="nk-router-outlet">${ssrHtml}</div></nk-app>`);
|
|
96
111
|
sendCompressed(req, res, 200, 'text/html; charset=utf-8', html_out);
|
|
97
112
|
return;
|
|
98
113
|
}
|
|
99
114
|
catch (ssrErr) {
|
|
100
|
-
|
|
115
|
+
logger.warn('SSR render failed, falling back to CSR', { error: ssrErr?.message });
|
|
101
116
|
}
|
|
102
117
|
}
|
|
103
118
|
// Fallback: inject loader data without SSR HTML
|
|
@@ -106,16 +121,28 @@ export async function handlePageRoute(manifest, serverDir, pagesDir, pathname, q
|
|
|
106
121
|
? { page: loaderData, layouts: layoutsData }
|
|
107
122
|
: loaderData;
|
|
108
123
|
const loaderDataScript = `<script type="application/json" id="__nk_ssr_data__">${JSON.stringify(ssrDataObj).replace(/</g, '\\u003c')}</script>`;
|
|
109
|
-
|
|
124
|
+
const authUserFb = req.nkAuth?.user ?? null;
|
|
125
|
+
const authScriptFb = authUserFb
|
|
126
|
+
? `<script type="application/json" id="__nk_auth__">${JSON.stringify(authUserFb).replace(/</g, '\\u003c')}</script>`
|
|
127
|
+
: '';
|
|
128
|
+
let html_out = indexHtmlShell.replace('<nk-app>', `${authScriptFb}${loaderDataScript}<nk-app>`);
|
|
110
129
|
sendCompressed(req, res, 200, 'text/html; charset=utf-8', html_out);
|
|
111
130
|
return;
|
|
112
131
|
}
|
|
113
132
|
}
|
|
114
133
|
catch (err) {
|
|
115
|
-
|
|
134
|
+
logger.error('Page handler error', { error: err?.message });
|
|
116
135
|
}
|
|
117
136
|
}
|
|
118
137
|
}
|
|
119
|
-
// SPA fallback — serve the built index.html
|
|
120
|
-
|
|
138
|
+
// SPA fallback — serve the built index.html with auth data injected
|
|
139
|
+
const fallbackUser = req.nkAuth?.user ?? null;
|
|
140
|
+
if (fallbackUser) {
|
|
141
|
+
const authTag = `<script type="application/json" id="__nk_auth__">${JSON.stringify(fallbackUser).replace(/</g, '\\u003c')}</script>`;
|
|
142
|
+
const html = indexHtmlShell.replace('<nk-app>', `${authTag}<nk-app>`);
|
|
143
|
+
sendCompressed(req, res, 200, 'text/html; charset=utf-8', html);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
sendCompressed(req, res, 200, 'text/html; charset=utf-8', indexHtmlShell);
|
|
147
|
+
}
|
|
121
148
|
}
|
|
@@ -52,9 +52,9 @@ export function sendCompressed(req, res, statusCode, contentType, body) {
|
|
|
52
52
|
}
|
|
53
53
|
export function serveStaticFile(clientDir, pathname, req, res) {
|
|
54
54
|
// Prevent directory traversal
|
|
55
|
-
const
|
|
56
|
-
const filePath = path.
|
|
57
|
-
if (!filePath.startsWith(
|
|
55
|
+
const resolvedClientDir = path.resolve(clientDir);
|
|
56
|
+
const filePath = path.resolve(resolvedClientDir, pathname.replace(/^\/+/, ''));
|
|
57
|
+
if (!filePath.startsWith(resolvedClientDir + path.sep) && filePath !== resolvedClientDir) {
|
|
58
58
|
return false;
|
|
59
59
|
}
|
|
60
60
|
if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
|