@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
@@ -0,0 +1,156 @@
1
+ export interface OIDCProvider {
2
+ type: 'oidc';
3
+ name: string;
4
+ issuer: string;
5
+ clientId: string;
6
+ clientSecret?: string;
7
+ scopes?: string[];
8
+ }
9
+ export interface NativeProvider {
10
+ type: 'native';
11
+ name: string;
12
+ /** Minimum password length. Default: 8 */
13
+ minPasswordLength?: number;
14
+ /** Allow user registration. Default: true */
15
+ allowRegistration?: boolean;
16
+ /** Require email verification before login. Default: false */
17
+ requireEmailVerification?: boolean;
18
+ }
19
+ /** Auth event types for hooks (email sending, logging, etc.) */
20
+ export type AuthEvent = {
21
+ type: 'verification-email';
22
+ email: string;
23
+ token: string;
24
+ url: string;
25
+ } | {
26
+ type: 'password-reset';
27
+ email: string;
28
+ token: string;
29
+ url: string;
30
+ } | {
31
+ type: 'password-changed';
32
+ email: string;
33
+ userId: string;
34
+ };
35
+ export type AuthProvider = OIDCProvider | NativeProvider;
36
+ export interface AuthConfig {
37
+ /** Single provider (legacy) or array of providers */
38
+ provider?: {
39
+ issuer: string;
40
+ clientId: string;
41
+ clientSecret?: string;
42
+ scopes?: string[];
43
+ };
44
+ /** Multi-provider config (preferred) */
45
+ providers?: AuthProvider[];
46
+ session: {
47
+ secret: string;
48
+ cookieName?: string;
49
+ maxAge?: number;
50
+ secure?: boolean;
51
+ };
52
+ routes?: {
53
+ login?: string;
54
+ loginPage?: string;
55
+ callback?: string;
56
+ logout?: string;
57
+ signup?: string;
58
+ postLogin?: string;
59
+ postLogout?: string;
60
+ me?: string;
61
+ };
62
+ guards?: {
63
+ defaultAuth?: boolean;
64
+ };
65
+ permissions?: {
66
+ enabled?: boolean;
67
+ defaultOwnerGrants?: string[];
68
+ };
69
+ token?: {
70
+ enabled?: boolean;
71
+ /** Access token TTL in seconds. Default: 900 (15 min) */
72
+ accessTokenTTL?: number;
73
+ /** Refresh token TTL in seconds. Default: 604800 (7 days) */
74
+ refreshTokenTTL?: number;
75
+ };
76
+ /** Hook called for auth events (send verification emails, password reset emails, etc.) */
77
+ onEvent?: (event: AuthEvent) => void | Promise<void>;
78
+ }
79
+ export interface ResolvedAuthConfig {
80
+ providers: AuthProvider[];
81
+ session: {
82
+ secret: string;
83
+ cookieName: string;
84
+ maxAge: number;
85
+ secure: boolean;
86
+ };
87
+ routes: {
88
+ login: string;
89
+ loginPage: string;
90
+ callback: string;
91
+ logout: string;
92
+ signup: string;
93
+ postLogin: string;
94
+ postLogout: string;
95
+ };
96
+ guards: {
97
+ defaultAuth: boolean;
98
+ };
99
+ permissions: {
100
+ enabled: boolean;
101
+ defaultOwnerGrants: string[];
102
+ };
103
+ token: {
104
+ enabled: boolean;
105
+ accessTokenTTL: number;
106
+ refreshTokenTTL: number;
107
+ };
108
+ onEvent?: (event: AuthEvent) => void | Promise<void>;
109
+ }
110
+ export interface TokenResponse {
111
+ accessToken: string;
112
+ refreshToken: string;
113
+ expiresIn: number;
114
+ tokenType: 'Bearer';
115
+ user: AuthUser;
116
+ }
117
+ export interface AuthUser {
118
+ sub: string;
119
+ email?: string;
120
+ name?: string;
121
+ preferred_username?: string;
122
+ roles: string[];
123
+ /** Which provider authenticated this user */
124
+ provider?: string;
125
+ [key: string]: unknown;
126
+ }
127
+ export interface SessionData {
128
+ accessToken: string;
129
+ refreshToken?: string;
130
+ idToken?: string;
131
+ expiresAt: number;
132
+ user: AuthUser;
133
+ /** Which provider created this session */
134
+ provider?: string;
135
+ /** Epoch seconds when session was created — used for logout-all invalidation */
136
+ createdAt?: number;
137
+ }
138
+ export interface NkAuth {
139
+ user: AuthUser;
140
+ session: SessionData;
141
+ }
142
+ export interface OIDCMetadata {
143
+ authorization_endpoint: string;
144
+ token_endpoint: string;
145
+ userinfo_endpoint: string;
146
+ end_session_endpoint?: string;
147
+ jwks_uri: string;
148
+ issuer: string;
149
+ }
150
+ export interface TokenSet {
151
+ access_token: string;
152
+ refresh_token?: string;
153
+ id_token?: string;
154
+ expires_in: number;
155
+ token_type: string;
156
+ }
@@ -0,0 +1,2 @@
1
+ // ── Provider Configs ──────────────────────────────────────────────
2
+ export {};
@@ -0,0 +1,15 @@
1
+ import { type UserConfig, type Plugin } from 'vite';
2
+ export interface BuildClientOptions {
3
+ projectDir: string;
4
+ clientDir: string;
5
+ title: string;
6
+ integrations: string[];
7
+ prefetchStrategy: 'hover' | 'viewport' | 'none';
8
+ publicDir: string;
9
+ shared: {
10
+ resolve: UserConfig['resolve'];
11
+ esbuild: UserConfig['esbuild'];
12
+ plugins: Plugin[];
13
+ };
14
+ }
15
+ export declare function buildClient(opts: BuildClientOptions): Promise<void>;
@@ -0,0 +1,45 @@
1
+ import { build as viteBuild } from 'vite';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import { generateIndexHtml } from '../dev-server/index-html.js';
5
+ export async function buildClient(opts) {
6
+ const { projectDir, clientDir, title, integrations, prefetchStrategy, publicDir, shared } = opts;
7
+ console.log('[LumenJS] Building client bundle...');
8
+ // Read optional head.html for blocking scripts (e.g. theme initialization)
9
+ const headHtmlPath = path.join(projectDir, 'head.html');
10
+ const headContent = fs.existsSync(headHtmlPath) ? fs.readFileSync(headHtmlPath, 'utf-8') : undefined;
11
+ // Generate index.html as build entry
12
+ const indexHtml = generateIndexHtml({ title, editorMode: false, integrations, prefetch: prefetchStrategy, headContent });
13
+ const tempIndexPath = path.join(projectDir, '__nk_build_index.html');
14
+ fs.writeFileSync(tempIndexPath, indexHtml);
15
+ try {
16
+ await viteBuild({
17
+ root: projectDir,
18
+ publicDir: fs.existsSync(publicDir) ? publicDir : undefined,
19
+ resolve: shared.resolve,
20
+ plugins: shared.plugins,
21
+ esbuild: shared.esbuild,
22
+ build: {
23
+ outDir: clientDir,
24
+ emptyOutDir: true,
25
+ rollupOptions: {
26
+ input: tempIndexPath,
27
+ external: ['mermaid', 'monaco-editor', 'monacopilot', '@lumenjs/db', '@lumenjs/permissions', '@lumenjs/storage'],
28
+ },
29
+ },
30
+ logLevel: 'warn',
31
+ });
32
+ }
33
+ finally {
34
+ // Clean up temp file
35
+ if (fs.existsSync(tempIndexPath)) {
36
+ fs.unlinkSync(tempIndexPath);
37
+ }
38
+ }
39
+ // Rename the built HTML file from __nk_build_index.html to index.html
40
+ const builtHtmlPath = path.join(clientDir, '__nk_build_index.html');
41
+ const finalHtmlPath = path.join(clientDir, 'index.html');
42
+ if (fs.existsSync(builtHtmlPath)) {
43
+ fs.renameSync(builtHtmlPath, finalHtmlPath);
44
+ }
45
+ }
@@ -0,0 +1,11 @@
1
+ import type { BuildManifest } from '../shared/types.js';
2
+ import type { PageEntry, LayoutEntry } from './scan.js';
3
+ export interface PrerenderOptions {
4
+ serverDir: string;
5
+ clientDir: string;
6
+ pagesDir: string;
7
+ pageEntries: PageEntry[];
8
+ layoutEntries: LayoutEntry[];
9
+ manifest: BuildManifest;
10
+ }
11
+ export declare function prerenderPages(opts: PrerenderOptions): Promise<void>;
@@ -0,0 +1,159 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { pathToFileURL } from 'url';
4
+ import { filePathToTagName, stripOuterLitMarkers, dirToLayoutTagName, isRedirectResponse, patchLoaderDataSpread } from '../shared/utils.js';
5
+ import { installDomShims } from '../shared/dom-shims.js';
6
+ import { getLayoutDirsForPage } from './scan.js';
7
+ export async function prerenderPages(opts) {
8
+ const { serverDir, clientDir, pagesDir, pageEntries, layoutEntries, manifest } = opts;
9
+ const prerenderEntries = pageEntries.filter(e => e.prerender);
10
+ if (prerenderEntries.length === 0)
11
+ return;
12
+ console.log(`[LumenJS] Pre-rendering ${prerenderEntries.length} page(s)...`);
13
+ // Load SSR runtime (installs global DOM shims)
14
+ const ssrRuntimePath = pathToFileURL(path.join(serverDir, 'ssr-runtime.js')).href;
15
+ const ssrRuntime = await import(ssrRuntimePath);
16
+ const { render, html, unsafeStatic } = ssrRuntime;
17
+ // Install additional DOM shims
18
+ installDomShims();
19
+ // Read the built index.html shell
20
+ const indexHtmlShell = fs.readFileSync(path.join(clientDir, 'index.html'), 'utf-8');
21
+ let prerenderCount = 0;
22
+ for (const page of prerenderEntries) {
23
+ // Resolve server module path (Rollup sanitizes brackets in filenames)
24
+ let modulePath = path.join(serverDir, `pages/${page.name}.js`);
25
+ if (!fs.existsSync(modulePath)) {
26
+ modulePath = path.join(serverDir, `pages/${page.name}.js`.replace(/\[/g, '_').replace(/\]/g, '_'));
27
+ }
28
+ if (!fs.existsSync(modulePath)) {
29
+ console.warn(` Skipping ${page.routePath}: server module not found`);
30
+ continue;
31
+ }
32
+ const mod = await import(pathToFileURL(modulePath).href);
33
+ // Determine paths to pre-render
34
+ const isDynamic = page.routePath.includes(':');
35
+ let pathsToRender = [];
36
+ if (isDynamic) {
37
+ // Dynamic route — call prerenderPaths() for param combinations
38
+ if (typeof mod.prerenderPaths === 'function') {
39
+ const paramsList = await mod.prerenderPaths();
40
+ for (const params of paramsList) {
41
+ // Build pathname from route pattern and params
42
+ let pathname = page.routePath;
43
+ for (const [key, value] of Object.entries(params)) {
44
+ // Handle both :param and :...param (catch-all) patterns
45
+ pathname = pathname.replace(`:...${key}`, value).replace(`:${key}`, value);
46
+ }
47
+ pathsToRender.push({ pathname, params: params });
48
+ }
49
+ }
50
+ else {
51
+ console.warn(` Skipping ${page.routePath}: dynamic route without prerenderPaths()`);
52
+ continue;
53
+ }
54
+ }
55
+ else {
56
+ // Static route — render once
57
+ pathsToRender.push({ pathname: page.routePath, params: {} });
58
+ }
59
+ for (const { pathname, params } of pathsToRender) {
60
+ // Run loader if present
61
+ let loaderData = undefined;
62
+ if (mod.loader && typeof mod.loader === 'function') {
63
+ loaderData = await mod.loader({ params, query: {}, url: pathname, headers: {} });
64
+ if (isRedirectResponse(loaderData)) {
65
+ console.warn(` Skipping ${pathname}: loader returned redirect`);
66
+ continue;
67
+ }
68
+ }
69
+ // Get tag name
70
+ const relPath = path.relative(pagesDir, page.filePath).replace(/\\/g, '/');
71
+ const tagName = filePathToTagName(relPath);
72
+ // Load and render layout chain
73
+ const routeLayouts = getLayoutDirsForPage(page.filePath, pagesDir, layoutEntries);
74
+ const layoutModules = [];
75
+ const layoutsData = [];
76
+ for (const dir of routeLayouts) {
77
+ const layout = layoutEntries.find(l => l.dir === dir);
78
+ if (!layout)
79
+ continue;
80
+ let layoutLoaderData = undefined;
81
+ if (layout.hasLoader) {
82
+ const manifestLayout = manifest.layouts.find(l => l.dir === dir);
83
+ if (manifestLayout?.module) {
84
+ const layoutModPath = path.join(serverDir, manifestLayout.module);
85
+ if (fs.existsSync(layoutModPath)) {
86
+ const layoutMod = await import(pathToFileURL(layoutModPath).href);
87
+ if (layoutMod.loader && typeof layoutMod.loader === 'function') {
88
+ layoutLoaderData = await layoutMod.loader({ params: {}, query: {}, url: pathname, headers: {} });
89
+ if (isRedirectResponse(layoutLoaderData))
90
+ continue;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ const layoutTagName = dirToLayoutTagName(dir);
96
+ layoutModules.push({ tagName: layoutTagName, loaderData: layoutLoaderData });
97
+ layoutsData.push({ loaderPath: dir, data: layoutLoaderData });
98
+ }
99
+ // Patch element classes to spread loaderData
100
+ for (const lm of layoutModules) {
101
+ patchLoaderDataSpread(lm.tagName);
102
+ }
103
+ patchLoaderDataSpread(tagName);
104
+ // SSR render page
105
+ const pageTag = unsafeStatic(tagName);
106
+ const pageTemplate = html `<${pageTag} .loaderData=${loaderData}></${pageTag}>`;
107
+ let ssrHtml = '';
108
+ for (const chunk of render(pageTemplate)) {
109
+ ssrHtml += typeof chunk === 'string' ? chunk : String(chunk);
110
+ }
111
+ ssrHtml = stripOuterLitMarkers(ssrHtml);
112
+ // Wrap in layout chain (inside-out, deepest first)
113
+ for (let i = layoutModules.length - 1; i >= 0; i--) {
114
+ const lTag = unsafeStatic(layoutModules[i].tagName);
115
+ const lData = layoutModules[i].loaderData;
116
+ const lTemplate = html `<${lTag} .loaderData=${lData}></${lTag}>`;
117
+ let lHtml = '';
118
+ for (const chunk of render(lTemplate)) {
119
+ lHtml += typeof chunk === 'string' ? chunk : String(chunk);
120
+ }
121
+ if (i > 0) {
122
+ lHtml = stripOuterLitMarkers(lHtml);
123
+ }
124
+ const closingTag = `</${layoutModules[i].tagName}>`;
125
+ const closingIdx = lHtml.lastIndexOf(closingTag);
126
+ if (closingIdx !== -1) {
127
+ ssrHtml = lHtml.slice(0, closingIdx) + ssrHtml + lHtml.slice(closingIdx);
128
+ }
129
+ else {
130
+ ssrHtml = lHtml + ssrHtml;
131
+ }
132
+ }
133
+ // Build SSR data script
134
+ const ssrDataObj = layoutsData.length > 0
135
+ ? { page: loaderData, layouts: layoutsData }
136
+ : loaderData;
137
+ const loaderDataScript = ssrDataObj !== undefined
138
+ ? `<script type="application/json" id="__nk_ssr_data__">${JSON.stringify(ssrDataObj).replace(/</g, '\\u003c')}</script>`
139
+ : '';
140
+ const hydrateScript = `<script type="module">import '@lit-labs/ssr-client/lit-element-hydrate-support.js';</script>`;
141
+ // Build final HTML from the shell
142
+ let htmlOut = indexHtmlShell;
143
+ htmlOut = htmlOut.replace('<script type="module"', `${hydrateScript}\n <script type="module"`);
144
+ htmlOut = htmlOut.replace(/<nk-app><\/nk-app>/, `${loaderDataScript}<nk-app data-nk-ssr><div id="nk-router-outlet">${ssrHtml}</div></nk-app>`);
145
+ // Write pre-rendered HTML file
146
+ const outPath = pathname === '/'
147
+ ? path.join(clientDir, 'index.html')
148
+ : path.join(clientDir, pathname, 'index.html');
149
+ // Don't overwrite the root index.html for non-root pages
150
+ if (pathname !== '/') {
151
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
152
+ }
153
+ fs.writeFileSync(outPath, htmlOut);
154
+ prerenderCount++;
155
+ console.log(` Pre-rendered: ${pathname}`);
156
+ }
157
+ }
158
+ console.log(`[LumenJS] Pre-rendered ${prerenderCount} page(s).`);
159
+ }
@@ -0,0 +1,18 @@
1
+ import { type UserConfig, type Plugin } from 'vite';
2
+ import type { PageEntry, LayoutEntry, ApiEntry, MiddlewareEntry } from './scan.js';
3
+ export interface BuildServerOptions {
4
+ projectDir: string;
5
+ serverDir: string;
6
+ pageEntries: PageEntry[];
7
+ layoutEntries: LayoutEntry[];
8
+ apiEntries: ApiEntry[];
9
+ middlewareEntries: MiddlewareEntry[];
10
+ hasAuthConfig: boolean;
11
+ authConfigPath: string;
12
+ shared: {
13
+ resolve: UserConfig['resolve'];
14
+ esbuild: UserConfig['esbuild'];
15
+ plugins: Plugin[];
16
+ };
17
+ }
18
+ export declare function buildServer(opts: BuildServerOptions): Promise<void>;
@@ -0,0 +1,107 @@
1
+ import { build as viteBuild } from 'vite';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ export async function buildServer(opts) {
5
+ const { projectDir, serverDir, pageEntries, layoutEntries, apiEntries, middlewareEntries, hasAuthConfig, authConfigPath, shared } = opts;
6
+ console.log('[LumenJS] Building server bundle...');
7
+ // Collect server entry points (pages with loaders + layouts with loaders + API routes)
8
+ const serverEntries = {};
9
+ for (const entry of pageEntries) {
10
+ if (entry.hasLoader || entry.hasSubscribe || entry.prerender) {
11
+ serverEntries[`pages/${entry.name}`] = entry.filePath;
12
+ }
13
+ }
14
+ for (const entry of layoutEntries) {
15
+ if (entry.hasLoader || entry.hasSubscribe) {
16
+ const entryName = entry.dir ? `layouts/${entry.dir}/_layout` : 'layouts/_layout';
17
+ serverEntries[entryName] = entry.filePath;
18
+ }
19
+ }
20
+ for (const entry of apiEntries) {
21
+ serverEntries[`api/${entry.name}`] = entry.filePath;
22
+ }
23
+ for (const entry of middlewareEntries) {
24
+ const entryName = entry.dir ? `middleware/${entry.dir}/_middleware` : 'middleware/_middleware';
25
+ serverEntries[entryName] = entry.filePath;
26
+ }
27
+ if (hasAuthConfig) {
28
+ serverEntries['auth-config'] = authConfigPath;
29
+ }
30
+ // If data/seed.ts exists, include it in the server bundle for prod seed support
31
+ const seedPath = path.join(projectDir, 'data', 'seed.ts');
32
+ if (fs.existsSync(seedPath)) {
33
+ serverEntries['seed'] = seedPath;
34
+ }
35
+ // Create SSR runtime entry — bundles @lit-labs/ssr alongside Lit so all
36
+ // server modules share one Lit instance (avoids _$EM mismatches).
37
+ const ssrEntryPath = path.join(projectDir, '__nk_ssr_entry.js');
38
+ const hasPageLoaders = pageEntries.some(e => e.hasLoader);
39
+ const hasLayoutLoaders = layoutEntries.some(e => e.hasLoader);
40
+ const hasPrerenderPages = pageEntries.some(e => e.prerender);
41
+ if (hasPageLoaders || hasLayoutLoaders || hasPrerenderPages) {
42
+ fs.writeFileSync(ssrEntryPath, [
43
+ "import '@lit-labs/ssr/lib/install-global-dom-shim.js';",
44
+ "export { render } from '@lit-labs/ssr';",
45
+ "export { html, unsafeStatic } from 'lit/static-html.js';",
46
+ ].join('\n'));
47
+ serverEntries['ssr-runtime'] = ssrEntryPath;
48
+ }
49
+ try {
50
+ if (Object.keys(serverEntries).length > 0) {
51
+ await viteBuild({
52
+ root: projectDir,
53
+ resolve: shared.resolve,
54
+ plugins: shared.plugins,
55
+ esbuild: shared.esbuild,
56
+ build: {
57
+ outDir: serverDir,
58
+ emptyOutDir: true,
59
+ ssr: true,
60
+ rollupOptions: {
61
+ input: serverEntries,
62
+ output: {
63
+ format: 'esm',
64
+ entryFileNames: '[name].js',
65
+ chunkFileNames: 'assets/[name]-[hash].js',
66
+ manualChunks(id) {
67
+ // Force all Lit packages into a single shared chunk so SSR runtime
68
+ // and page modules use the exact same Lit class instances.
69
+ if (id.includes('/node_modules/lit/') ||
70
+ id.includes('/node_modules/lit-html/') ||
71
+ id.includes('/node_modules/lit-element/') ||
72
+ id.includes('/node_modules/@lit/reactive-element/')) {
73
+ return 'lit-shared';
74
+ }
75
+ },
76
+ },
77
+ external: [
78
+ /^node:/,
79
+ 'os', 'fs', 'path', 'url', 'util', 'crypto', 'http', 'https', 'net',
80
+ 'stream', 'zlib', 'events', 'buffer', 'querystring', 'child_process',
81
+ 'worker_threads', 'cluster', 'dns', 'tls', 'assert', 'constants',
82
+ // Native addons — must not be bundled, loaded from node_modules at runtime
83
+ 'better-sqlite3',
84
+ // AWS SDK — optional peer dep, keep as runtime import so app can provide it
85
+ '@aws-sdk/client-s3',
86
+ '@aws-sdk/s3-request-presigner',
87
+ /^@aws-sdk\//,
88
+ /^@smithy\//,
89
+ ],
90
+ },
91
+ },
92
+ logLevel: 'warn',
93
+ ssr: {
94
+ noExternal: true,
95
+ },
96
+ });
97
+ }
98
+ else {
99
+ fs.mkdirSync(serverDir, { recursive: true });
100
+ }
101
+ }
102
+ finally {
103
+ if (fs.existsSync(ssrEntryPath)) {
104
+ fs.unlinkSync(ssrEntryPath);
105
+ }
106
+ }
107
+ }