@buenojs/bueno 0.8.4 → 0.8.6
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 +264 -17
- package/dist/cli/{index.js → bin.js} +413 -332
- package/dist/container/index.js +273 -0
- package/dist/context/index.js +219 -0
- package/dist/database/index.js +493 -0
- package/dist/frontend/index.js +7697 -0
- package/dist/graphql/index.js +2156 -0
- package/dist/health/index.js +364 -0
- package/dist/i18n/index.js +345 -0
- package/dist/index.js +9694 -5047
- package/dist/jobs/index.js +819 -0
- package/dist/lock/index.js +367 -0
- package/dist/logger/index.js +281 -0
- package/dist/metrics/index.js +289 -0
- package/dist/middleware/index.js +77 -0
- package/dist/migrations/index.js +571 -0
- package/dist/modules/index.js +3411 -0
- package/dist/notification/index.js +484 -0
- package/dist/observability/index.js +331 -0
- package/dist/openapi/index.js +795 -0
- package/dist/orm/index.js +1356 -0
- package/dist/router/index.js +886 -0
- package/dist/rpc/index.js +691 -0
- package/dist/schema/index.js +400 -0
- package/dist/telemetry/index.js +595 -0
- package/dist/template/index.js +640 -0
- package/dist/templates/index.js +640 -0
- package/dist/testing/index.js +1111 -0
- package/dist/types/index.js +60 -0
- package/llms.txt +231 -0
- package/package.json +125 -27
- package/src/cache/index.ts +2 -1
- package/src/cli/ARCHITECTURE.md +3 -3
- package/src/cli/bin.ts +2 -2
- package/src/cli/commands/build.ts +183 -165
- package/src/cli/commands/dev.ts +96 -89
- package/src/cli/commands/generate.ts +142 -111
- package/src/cli/commands/help.ts +20 -16
- package/src/cli/commands/index.ts +3 -6
- package/src/cli/commands/migration.ts +124 -105
- package/src/cli/commands/new.ts +294 -232
- package/src/cli/commands/start.ts +81 -79
- package/src/cli/core/args.ts +68 -50
- package/src/cli/core/console.ts +89 -95
- package/src/cli/core/index.ts +4 -4
- package/src/cli/core/prompt.ts +65 -62
- package/src/cli/core/spinner.ts +23 -20
- package/src/cli/index.ts +46 -38
- package/src/cli/templates/database/index.ts +37 -18
- package/src/cli/templates/database/mysql.ts +3 -3
- package/src/cli/templates/database/none.ts +2 -2
- package/src/cli/templates/database/postgresql.ts +3 -3
- package/src/cli/templates/database/sqlite.ts +3 -3
- package/src/cli/templates/deploy.ts +29 -26
- package/src/cli/templates/docker.ts +41 -30
- package/src/cli/templates/frontend/index.ts +33 -15
- package/src/cli/templates/frontend/none.ts +2 -2
- package/src/cli/templates/frontend/react.ts +18 -18
- package/src/cli/templates/frontend/solid.ts +15 -15
- package/src/cli/templates/frontend/svelte.ts +17 -17
- package/src/cli/templates/frontend/vue.ts +15 -15
- package/src/cli/templates/generators/index.ts +29 -29
- package/src/cli/templates/generators/types.ts +21 -21
- package/src/cli/templates/index.ts +6 -6
- package/src/cli/templates/project/api.ts +37 -36
- package/src/cli/templates/project/default.ts +25 -25
- package/src/cli/templates/project/fullstack.ts +28 -26
- package/src/cli/templates/project/index.ts +55 -16
- package/src/cli/templates/project/minimal.ts +17 -12
- package/src/cli/templates/project/types.ts +10 -5
- package/src/cli/templates/project/website.ts +15 -15
- package/src/cli/utils/fs.ts +55 -41
- package/src/cli/utils/index.ts +3 -3
- package/src/cli/utils/strings.ts +47 -33
- package/src/cli/utils/version.ts +14 -8
- package/src/config/env-validation.ts +100 -0
- package/src/config/env.ts +169 -41
- package/src/config/index.ts +28 -20
- package/src/config/loader.ts +25 -16
- package/src/config/merge.ts +21 -10
- package/src/config/types.ts +566 -25
- package/src/config/validation.ts +215 -7
- package/src/container/forward-ref.ts +22 -22
- package/src/container/index.ts +34 -12
- package/src/context/index.ts +11 -1
- package/src/database/index.ts +7 -190
- package/src/database/orm/builder.ts +457 -0
- package/src/database/orm/casts/index.ts +130 -0
- package/src/database/orm/casts/types.ts +25 -0
- package/src/database/orm/compiler.ts +304 -0
- package/src/database/orm/hooks/index.ts +114 -0
- package/src/database/orm/index.ts +61 -0
- package/src/database/orm/model-registry.ts +59 -0
- package/src/database/orm/model.ts +821 -0
- package/src/database/orm/relationships/base.ts +146 -0
- package/src/database/orm/relationships/belongs-to-many.ts +179 -0
- package/src/database/orm/relationships/belongs-to.ts +56 -0
- package/src/database/orm/relationships/has-many.ts +45 -0
- package/src/database/orm/relationships/has-one.ts +41 -0
- package/src/database/orm/relationships/index.ts +11 -0
- package/src/database/orm/scopes/index.ts +55 -0
- package/src/events/__tests__/event-system.test.ts +235 -0
- package/src/events/config.ts +238 -0
- package/src/events/example-usage.ts +185 -0
- package/src/events/index.ts +278 -0
- package/src/events/manager.ts +385 -0
- package/src/events/registry.ts +182 -0
- package/src/events/types.ts +124 -0
- package/src/frontend/api-routes.ts +65 -23
- package/src/frontend/bundler.ts +76 -34
- package/src/frontend/console-client.ts +2 -2
- package/src/frontend/console-stream.ts +94 -38
- package/src/frontend/dev-server.ts +94 -46
- package/src/frontend/file-router.ts +61 -19
- package/src/frontend/frameworks/index.ts +37 -10
- package/src/frontend/frameworks/react.ts +10 -8
- package/src/frontend/frameworks/solid.ts +11 -9
- package/src/frontend/frameworks/svelte.ts +15 -9
- package/src/frontend/frameworks/vue.ts +13 -11
- package/src/frontend/hmr-client.ts +12 -10
- package/src/frontend/hmr.ts +146 -103
- package/src/frontend/index.ts +14 -5
- package/src/frontend/islands.ts +41 -22
- package/src/frontend/isr.ts +59 -37
- package/src/frontend/layout.ts +36 -21
- package/src/frontend/ssr/react.ts +74 -27
- package/src/frontend/ssr/solid.ts +54 -20
- package/src/frontend/ssr/svelte.ts +48 -14
- package/src/frontend/ssr/vue.ts +50 -18
- package/src/frontend/ssr.ts +83 -39
- package/src/frontend/types.ts +91 -56
- package/src/graphql/built-in-engine.ts +598 -0
- package/src/graphql/context-builder.ts +110 -0
- package/src/graphql/decorators.ts +358 -0
- package/src/graphql/execution-pipeline.ts +227 -0
- package/src/graphql/graphql-module.ts +563 -0
- package/src/graphql/index.ts +101 -0
- package/src/graphql/metadata.ts +237 -0
- package/src/graphql/schema-builder.ts +319 -0
- package/src/graphql/subscription-handler.ts +283 -0
- package/src/graphql/types.ts +324 -0
- package/src/health/index.ts +21 -9
- package/src/i18n/engine.ts +305 -0
- package/src/i18n/index.ts +38 -0
- package/src/i18n/loader.ts +218 -0
- package/src/i18n/middleware.ts +164 -0
- package/src/i18n/negotiator.ts +162 -0
- package/src/i18n/types.ts +158 -0
- package/src/index.ts +182 -27
- package/src/jobs/drivers/memory.ts +315 -0
- package/src/jobs/drivers/redis.ts +459 -0
- package/src/jobs/index.ts +30 -0
- package/src/jobs/queue.ts +281 -0
- package/src/jobs/types.ts +295 -0
- package/src/jobs/worker.ts +380 -0
- package/src/logger/index.ts +1 -3
- package/src/logger/transports/index.ts +62 -22
- package/src/metrics/index.ts +25 -16
- package/src/migrations/index.ts +9 -0
- package/src/modules/filters.ts +13 -17
- package/src/modules/guards.ts +49 -26
- package/src/modules/index.ts +457 -299
- package/src/modules/interceptors.ts +58 -20
- package/src/modules/lazy.ts +11 -19
- package/src/modules/lifecycle.ts +15 -7
- package/src/modules/metadata.ts +15 -5
- package/src/modules/pipes.ts +94 -72
- package/src/notification/channels/base.ts +68 -0
- package/src/notification/channels/email.ts +105 -0
- package/src/notification/channels/push.ts +104 -0
- package/src/notification/channels/sms.ts +105 -0
- package/src/notification/channels/whatsapp.ts +104 -0
- package/src/notification/index.ts +48 -0
- package/src/notification/service.ts +354 -0
- package/src/notification/types.ts +344 -0
- package/src/observability/__tests__/observability.test.ts +483 -0
- package/src/observability/breadcrumbs.ts +114 -0
- package/src/observability/index.ts +136 -0
- package/src/observability/interceptor.ts +85 -0
- package/src/observability/service.ts +303 -0
- package/src/observability/trace.ts +37 -0
- package/src/observability/types.ts +196 -0
- package/src/openapi/__tests__/decorators.test.ts +335 -0
- package/src/openapi/__tests__/document-builder.test.ts +285 -0
- package/src/openapi/__tests__/route-scanner.test.ts +334 -0
- package/src/openapi/__tests__/schema-generator.test.ts +275 -0
- package/src/openapi/decorators.ts +328 -0
- package/src/openapi/document-builder.ts +274 -0
- package/src/openapi/index.ts +112 -0
- package/src/openapi/metadata.ts +112 -0
- package/src/openapi/route-scanner.ts +289 -0
- package/src/openapi/schema-generator.ts +256 -0
- package/src/openapi/swagger-module.ts +166 -0
- package/src/openapi/types.ts +398 -0
- package/src/orm/index.ts +10 -0
- package/src/rpc/index.ts +3 -1
- package/src/schema/index.ts +9 -0
- package/src/security/index.ts +15 -6
- package/src/ssg/index.ts +9 -8
- package/src/telemetry/index.ts +76 -22
- package/src/template/index.ts +7 -0
- package/src/templates/engine.ts +224 -0
- package/src/templates/index.ts +9 -0
- package/src/templates/loader.ts +331 -0
- package/src/templates/renderers/markdown.ts +212 -0
- package/src/templates/renderers/simple.ts +269 -0
- package/src/templates/types.ts +154 -0
- package/src/testing/index.ts +100 -27
- package/src/types/optional-deps.d.ts +347 -187
- package/src/validation/index.ts +92 -2
- package/src/validation/schemas.ts +536 -0
- package/tests/integration/cli.test.ts +19 -19
- package/tests/integration/fullstack.test.ts +4 -4
- package/tests/unit/cli.test.ts +1 -1
- package/tests/unit/database.test.ts +2 -72
- package/tests/unit/env-validation.test.ts +166 -0
- package/tests/unit/events.test.ts +910 -0
- package/tests/unit/graphql.test.ts +991 -0
- package/tests/unit/i18n.test.ts +455 -0
- package/tests/unit/jobs.test.ts +493 -0
- package/tests/unit/notification.test.ts +988 -0
- package/tests/unit/observability.test.ts +453 -0
- package/tests/unit/orm/builder.test.ts +323 -0
- package/tests/unit/orm/casts.test.ts +179 -0
- package/tests/unit/orm/compiler.test.ts +220 -0
- package/tests/unit/orm/eager-loading.test.ts +285 -0
- package/tests/unit/orm/hooks.test.ts +191 -0
- package/tests/unit/orm/model.test.ts +373 -0
- package/tests/unit/orm/relationships.test.ts +303 -0
- package/tests/unit/orm/scopes.test.ts +74 -0
- package/tests/unit/templates-simple.test.ts +53 -0
- package/tests/unit/templates.test.ts +454 -0
- package/tests/unit/validation.test.ts +18 -24
- package/tsconfig.json +11 -3
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type {
|
|
11
|
+
FrameworkSSRRenderer,
|
|
11
12
|
SSRContext,
|
|
12
13
|
SSRElement,
|
|
13
|
-
SSRPage,
|
|
14
|
-
FrameworkSSRRenderer,
|
|
15
14
|
SSRHydrationData,
|
|
15
|
+
SSRPage,
|
|
16
16
|
} from "../types.js";
|
|
17
17
|
|
|
18
18
|
// React types (dynamically imported)
|
|
@@ -22,9 +22,7 @@ interface ReactElement {
|
|
|
22
22
|
key: string | null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
(props: Record<string, unknown>): ReactElement | null;
|
|
27
|
-
}
|
|
25
|
+
type ReactComponent = (props: Record<string, unknown>) => ReactElement | null;
|
|
28
26
|
|
|
29
27
|
// Head element storage (similar to React Helmet)
|
|
30
28
|
let headElements: SSRElement[] = [];
|
|
@@ -54,7 +52,11 @@ export function addHeadElement(element: SSRElement): void {
|
|
|
54
52
|
* Create a title element for head
|
|
55
53
|
*/
|
|
56
54
|
export function title(text: string): SSRElement {
|
|
57
|
-
return {
|
|
55
|
+
return {
|
|
56
|
+
tag: "title",
|
|
57
|
+
attrs: {},
|
|
58
|
+
children: [{ tag: "#text", attrs: {}, innerHTML: text }],
|
|
59
|
+
};
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
/**
|
|
@@ -74,14 +76,20 @@ export function link(attrs: Record<string, string>): SSRElement {
|
|
|
74
76
|
/**
|
|
75
77
|
* Create a script element for head
|
|
76
78
|
*/
|
|
77
|
-
export function script(
|
|
79
|
+
export function script(
|
|
80
|
+
attrs: Record<string, string>,
|
|
81
|
+
innerHTML?: string,
|
|
82
|
+
): SSRElement {
|
|
78
83
|
return { tag: "script", attrs, innerHTML };
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
/**
|
|
82
87
|
* Create a style element for head
|
|
83
88
|
*/
|
|
84
|
-
export function style(
|
|
89
|
+
export function style(
|
|
90
|
+
innerHTML: string,
|
|
91
|
+
attrs?: Record<string, string>,
|
|
92
|
+
): SSRElement {
|
|
85
93
|
return { tag: "style", attrs: attrs || {}, innerHTML };
|
|
86
94
|
}
|
|
87
95
|
|
|
@@ -107,7 +115,7 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
107
115
|
this.initialized = true;
|
|
108
116
|
} catch (error) {
|
|
109
117
|
throw new Error(
|
|
110
|
-
"React is not installed. Install it with: bun add react react-dom"
|
|
118
|
+
"React is not installed. Install it with: bun add react react-dom",
|
|
111
119
|
);
|
|
112
120
|
}
|
|
113
121
|
}
|
|
@@ -115,7 +123,10 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
115
123
|
/**
|
|
116
124
|
* Render a component to HTML string
|
|
117
125
|
*/
|
|
118
|
-
async renderToString(
|
|
126
|
+
async renderToString(
|
|
127
|
+
component: unknown,
|
|
128
|
+
context: SSRContext,
|
|
129
|
+
): Promise<string> {
|
|
119
130
|
await this.init();
|
|
120
131
|
|
|
121
132
|
if (!this.reactDomServer) {
|
|
@@ -126,11 +137,16 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
126
137
|
|
|
127
138
|
try {
|
|
128
139
|
// Use renderToString for non-streaming
|
|
129
|
-
const renderToStringFn = (
|
|
140
|
+
const renderToStringFn = (
|
|
141
|
+
this.reactDomServer as unknown as {
|
|
142
|
+
renderToString: (el: unknown) => string;
|
|
143
|
+
}
|
|
144
|
+
).renderToString;
|
|
130
145
|
const html = renderToStringFn(component as ReactElement);
|
|
131
146
|
return html;
|
|
132
147
|
} catch (error) {
|
|
133
|
-
const errorMessage =
|
|
148
|
+
const errorMessage =
|
|
149
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
134
150
|
throw new Error(`React renderToString failed: ${errorMessage}`);
|
|
135
151
|
}
|
|
136
152
|
}
|
|
@@ -138,7 +154,10 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
138
154
|
/**
|
|
139
155
|
* Render a component to a stream
|
|
140
156
|
*/
|
|
141
|
-
renderToStream(
|
|
157
|
+
renderToStream(
|
|
158
|
+
component: unknown,
|
|
159
|
+
context: SSRContext,
|
|
160
|
+
): ReadableStream<Uint8Array> {
|
|
142
161
|
// Create a promise-based initialization
|
|
143
162
|
const encoder = new TextEncoder();
|
|
144
163
|
|
|
@@ -163,7 +182,7 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
163
182
|
onError: (error: Error) => {
|
|
164
183
|
console.error("React streaming error:", error);
|
|
165
184
|
},
|
|
166
|
-
}
|
|
185
|
+
},
|
|
167
186
|
);
|
|
168
187
|
|
|
169
188
|
const reader = stream.getReader();
|
|
@@ -178,13 +197,18 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
178
197
|
}
|
|
179
198
|
} else {
|
|
180
199
|
// Fallback to renderToString for older React versions
|
|
181
|
-
const html = this.reactDomServer.renderToString(
|
|
200
|
+
const html = this.reactDomServer.renderToString(
|
|
201
|
+
component as ReactElement,
|
|
202
|
+
);
|
|
182
203
|
controller.enqueue(encoder.encode(html));
|
|
183
204
|
controller.close();
|
|
184
205
|
}
|
|
185
206
|
} catch (error) {
|
|
186
|
-
const errorMessage =
|
|
187
|
-
|
|
207
|
+
const errorMessage =
|
|
208
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
209
|
+
controller.error(
|
|
210
|
+
new Error(`React renderToStream failed: ${errorMessage}`),
|
|
211
|
+
);
|
|
188
212
|
}
|
|
189
213
|
},
|
|
190
214
|
});
|
|
@@ -214,7 +238,7 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
214
238
|
async renderWithSuspense(
|
|
215
239
|
component: unknown,
|
|
216
240
|
context: SSRContext,
|
|
217
|
-
fallback
|
|
241
|
+
fallback = "<div>Loading...</div>",
|
|
218
242
|
): Promise<string> {
|
|
219
243
|
await this.init();
|
|
220
244
|
|
|
@@ -229,13 +253,14 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
229
253
|
const suspenseWrapper = this.react.createElement(
|
|
230
254
|
this.react.Suspense,
|
|
231
255
|
{ fallback },
|
|
232
|
-
component as ReactElement
|
|
256
|
+
component as ReactElement,
|
|
233
257
|
);
|
|
234
258
|
|
|
235
259
|
const html = this.reactDomServer.renderToString(suspenseWrapper);
|
|
236
260
|
return html;
|
|
237
261
|
} catch (error) {
|
|
238
|
-
const errorMessage =
|
|
262
|
+
const errorMessage =
|
|
263
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
239
264
|
throw new Error(`React renderWithSuspense failed: ${errorMessage}`);
|
|
240
265
|
}
|
|
241
266
|
}
|
|
@@ -251,7 +276,7 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
251
276
|
onShellReady?: () => void;
|
|
252
277
|
onShellError?: (error: Error) => void;
|
|
253
278
|
onError?: (error: Error) => void;
|
|
254
|
-
} = {}
|
|
279
|
+
} = {},
|
|
255
280
|
): Promise<ReadableStream<Uint8Array>> {
|
|
256
281
|
await this.init();
|
|
257
282
|
|
|
@@ -275,7 +300,7 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
275
300
|
options.onError?.(error);
|
|
276
301
|
console.error("React streaming error:", error);
|
|
277
302
|
},
|
|
278
|
-
}
|
|
303
|
+
},
|
|
279
304
|
);
|
|
280
305
|
|
|
281
306
|
// Wait for shell to be ready
|
|
@@ -294,13 +319,16 @@ export class ReactSSRRenderer implements FrameworkSSRRenderer {
|
|
|
294
319
|
}
|
|
295
320
|
} else {
|
|
296
321
|
// Fallback
|
|
297
|
-
const html = this.reactDomServer!.renderToString(
|
|
322
|
+
const html = this.reactDomServer!.renderToString(
|
|
323
|
+
component as ReactElement,
|
|
324
|
+
);
|
|
298
325
|
options.onAllReady?.();
|
|
299
326
|
controller.enqueue(encoder.encode(html));
|
|
300
327
|
controller.close();
|
|
301
328
|
}
|
|
302
329
|
} catch (error) {
|
|
303
|
-
const err =
|
|
330
|
+
const err =
|
|
331
|
+
error instanceof Error ? error : new Error("Unknown error");
|
|
304
332
|
options.onShellError?.(err);
|
|
305
333
|
controller.error(err);
|
|
306
334
|
}
|
|
@@ -340,7 +368,22 @@ export function ssrElementToString(element: SSRElement): string {
|
|
|
340
368
|
}
|
|
341
369
|
|
|
342
370
|
// Self-closing tags
|
|
343
|
-
const voidElements = [
|
|
371
|
+
const voidElements = [
|
|
372
|
+
"area",
|
|
373
|
+
"base",
|
|
374
|
+
"br",
|
|
375
|
+
"col",
|
|
376
|
+
"embed",
|
|
377
|
+
"hr",
|
|
378
|
+
"img",
|
|
379
|
+
"input",
|
|
380
|
+
"link",
|
|
381
|
+
"meta",
|
|
382
|
+
"param",
|
|
383
|
+
"source",
|
|
384
|
+
"track",
|
|
385
|
+
"wbr",
|
|
386
|
+
];
|
|
344
387
|
if (voidElements.includes(element.tag)) {
|
|
345
388
|
return attrs ? `<${element.tag} ${attrs}>` : `<${element.tag}>`;
|
|
346
389
|
}
|
|
@@ -380,7 +423,11 @@ export class ReactHelmet {
|
|
|
380
423
|
|
|
381
424
|
setTitle(title: string): this {
|
|
382
425
|
this.title = title;
|
|
383
|
-
addHeadElement({
|
|
426
|
+
addHeadElement({
|
|
427
|
+
tag: "title",
|
|
428
|
+
attrs: {},
|
|
429
|
+
children: [{ tag: "#text", attrs: {}, innerHTML: title }],
|
|
430
|
+
});
|
|
384
431
|
return this;
|
|
385
432
|
}
|
|
386
433
|
|
|
@@ -443,4 +490,4 @@ export class ReactHelmet {
|
|
|
443
490
|
*/
|
|
444
491
|
export function helmet(): ReactHelmet {
|
|
445
492
|
return ReactHelmet.getInstance();
|
|
446
|
-
}
|
|
493
|
+
}
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type {
|
|
11
|
+
FrameworkSSRRenderer,
|
|
11
12
|
SSRContext,
|
|
12
13
|
SSRElement,
|
|
13
14
|
SSRPage,
|
|
14
|
-
FrameworkSSRRenderer,
|
|
15
15
|
} from "../types.js";
|
|
16
16
|
|
|
17
17
|
// Solid types (dynamically imported)
|
|
@@ -20,9 +20,7 @@ interface SolidElement {
|
|
|
20
20
|
props: Record<string, unknown>;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
(props: Record<string, unknown>): SolidElement | null;
|
|
25
|
-
}
|
|
23
|
+
type SolidComponent = (props: Record<string, unknown>) => SolidElement | null;
|
|
26
24
|
|
|
27
25
|
interface SolidRenderResult {
|
|
28
26
|
html: string;
|
|
@@ -74,7 +72,7 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
74
72
|
this.initialized = true;
|
|
75
73
|
} catch (error) {
|
|
76
74
|
throw new Error(
|
|
77
|
-
"Solid is not installed. Install it with: bun add solid-js"
|
|
75
|
+
"Solid is not installed. Install it with: bun add solid-js",
|
|
78
76
|
);
|
|
79
77
|
}
|
|
80
78
|
}
|
|
@@ -82,7 +80,10 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
82
80
|
/**
|
|
83
81
|
* Render a component to HTML string
|
|
84
82
|
*/
|
|
85
|
-
async renderToString(
|
|
83
|
+
async renderToString(
|
|
84
|
+
component: unknown,
|
|
85
|
+
context: SSRContext,
|
|
86
|
+
): Promise<string> {
|
|
86
87
|
await this.init();
|
|
87
88
|
|
|
88
89
|
if (!this.solidWeb) {
|
|
@@ -101,7 +102,8 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
101
102
|
const html = renderToString(() => wrappedComponent);
|
|
102
103
|
return html;
|
|
103
104
|
} catch (error) {
|
|
104
|
-
const errorMessage =
|
|
105
|
+
const errorMessage =
|
|
106
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
105
107
|
throw new Error(`Solid renderToString failed: ${errorMessage}`);
|
|
106
108
|
}
|
|
107
109
|
}
|
|
@@ -109,7 +111,10 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
109
111
|
/**
|
|
110
112
|
* Render a component to a stream
|
|
111
113
|
*/
|
|
112
|
-
renderToStream(
|
|
114
|
+
renderToStream(
|
|
115
|
+
component: unknown,
|
|
116
|
+
context: SSRContext,
|
|
117
|
+
): ReadableStream<Uint8Array> {
|
|
113
118
|
const encoder = new TextEncoder();
|
|
114
119
|
|
|
115
120
|
return new ReadableStream<Uint8Array>({
|
|
@@ -154,8 +159,11 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
154
159
|
controller.close();
|
|
155
160
|
}
|
|
156
161
|
} catch (error) {
|
|
157
|
-
const errorMessage =
|
|
158
|
-
|
|
162
|
+
const errorMessage =
|
|
163
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
164
|
+
controller.error(
|
|
165
|
+
new Error(`Solid renderToStream failed: ${errorMessage}`),
|
|
166
|
+
);
|
|
159
167
|
}
|
|
160
168
|
},
|
|
161
169
|
});
|
|
@@ -181,7 +189,10 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
181
189
|
/**
|
|
182
190
|
* Wrap component with context provider
|
|
183
191
|
*/
|
|
184
|
-
private wrapWithContext(
|
|
192
|
+
private wrapWithContext(
|
|
193
|
+
component: unknown,
|
|
194
|
+
context: SSRContext,
|
|
195
|
+
): () => unknown {
|
|
185
196
|
return () => {
|
|
186
197
|
// In a real implementation, this would use Solid's context API
|
|
187
198
|
// to provide the SSR context to child components
|
|
@@ -216,7 +227,8 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
216
227
|
const html = await renderToStringAsync(() => wrappedComponent);
|
|
217
228
|
return html;
|
|
218
229
|
} catch (error) {
|
|
219
|
-
const errorMessage =
|
|
230
|
+
const errorMessage =
|
|
231
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
220
232
|
throw new Error(`Solid renderAsync failed: ${errorMessage}`);
|
|
221
233
|
}
|
|
222
234
|
}
|
|
@@ -227,7 +239,7 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
227
239
|
async renderWithSuspense(
|
|
228
240
|
component: unknown,
|
|
229
241
|
context: SSRContext,
|
|
230
|
-
fallback
|
|
242
|
+
fallback = "<div>Loading...</div>",
|
|
231
243
|
): Promise<string> {
|
|
232
244
|
await this.init();
|
|
233
245
|
|
|
@@ -258,7 +270,8 @@ export class SolidSSRRenderer implements FrameworkSSRRenderer {
|
|
|
258
270
|
const html = await renderToStringAsync(wrappedComponent);
|
|
259
271
|
return html;
|
|
260
272
|
} catch (error) {
|
|
261
|
-
const errorMessage =
|
|
273
|
+
const errorMessage =
|
|
274
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
262
275
|
throw new Error(`Solid renderWithSuspense failed: ${errorMessage}`);
|
|
263
276
|
}
|
|
264
277
|
}
|
|
@@ -291,7 +304,11 @@ export class SolidMeta {
|
|
|
291
304
|
|
|
292
305
|
setTitle(title: string): this {
|
|
293
306
|
this.title = title;
|
|
294
|
-
addHeadElement({
|
|
307
|
+
addHeadElement({
|
|
308
|
+
tag: "title",
|
|
309
|
+
attrs: {},
|
|
310
|
+
children: [{ tag: "#text", attrs: {}, innerHTML: title }],
|
|
311
|
+
});
|
|
295
312
|
return this;
|
|
296
313
|
}
|
|
297
314
|
|
|
@@ -380,7 +397,22 @@ export function ssrElementToString(element: SSRElement): string {
|
|
|
380
397
|
}
|
|
381
398
|
|
|
382
399
|
// Self-closing tags
|
|
383
|
-
const voidElements = [
|
|
400
|
+
const voidElements = [
|
|
401
|
+
"area",
|
|
402
|
+
"base",
|
|
403
|
+
"br",
|
|
404
|
+
"col",
|
|
405
|
+
"embed",
|
|
406
|
+
"hr",
|
|
407
|
+
"img",
|
|
408
|
+
"input",
|
|
409
|
+
"link",
|
|
410
|
+
"meta",
|
|
411
|
+
"param",
|
|
412
|
+
"source",
|
|
413
|
+
"track",
|
|
414
|
+
"wbr",
|
|
415
|
+
];
|
|
384
416
|
if (voidElements.includes(element.tag)) {
|
|
385
417
|
return attrs ? `<${element.tag} ${attrs}>` : `<${element.tag}>`;
|
|
386
418
|
}
|
|
@@ -405,7 +437,7 @@ function escapeHtml(str: string): string {
|
|
|
405
437
|
*/
|
|
406
438
|
export function createSolidSSRContext(
|
|
407
439
|
request: Request,
|
|
408
|
-
initialState: Record<string, unknown> = {}
|
|
440
|
+
initialState: Record<string, unknown> = {},
|
|
409
441
|
): SSRContext {
|
|
410
442
|
const url = new URL(request.url);
|
|
411
443
|
|
|
@@ -432,7 +464,7 @@ export function createRouteData<T>(
|
|
|
432
464
|
options: {
|
|
433
465
|
key?: () => unknown[];
|
|
434
466
|
deferStream?: boolean;
|
|
435
|
-
} = {}
|
|
467
|
+
} = {},
|
|
436
468
|
): {
|
|
437
469
|
data: T | undefined;
|
|
438
470
|
loading: boolean;
|
|
@@ -500,7 +532,9 @@ export class SolidResource<T> {
|
|
|
500
532
|
/**
|
|
501
533
|
* Create a Solid resource
|
|
502
534
|
*/
|
|
503
|
-
export function createSolidResource<T>(
|
|
535
|
+
export function createSolidResource<T>(
|
|
536
|
+
fetcher: () => Promise<T>,
|
|
537
|
+
): SolidResource<T> {
|
|
504
538
|
return new SolidResource(fetcher);
|
|
505
539
|
}
|
|
506
540
|
|
|
@@ -520,4 +554,4 @@ export function noHydrate(element: SSRElement): SSRElement {
|
|
|
520
554
|
[NO_HYDRATE]: "",
|
|
521
555
|
},
|
|
522
556
|
};
|
|
523
|
-
}
|
|
557
|
+
}
|
|
@@ -8,16 +8,21 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type {
|
|
11
|
+
FrameworkSSRRenderer,
|
|
11
12
|
SSRContext,
|
|
12
13
|
SSRElement,
|
|
13
14
|
SSRPage,
|
|
14
|
-
FrameworkSSRRenderer,
|
|
15
15
|
} from "../types.js";
|
|
16
16
|
|
|
17
17
|
// Svelte types (dynamically imported)
|
|
18
18
|
interface SvelteComponent {
|
|
19
19
|
render(props?: Record<string, unknown>): SvelteRenderResult;
|
|
20
|
-
$$render(
|
|
20
|
+
$$render(
|
|
21
|
+
result: string,
|
|
22
|
+
props: Record<string, unknown>,
|
|
23
|
+
bindings: unknown,
|
|
24
|
+
context: unknown,
|
|
25
|
+
): string;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
interface SvelteRenderResult {
|
|
@@ -99,7 +104,7 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
99
104
|
this.initialized = true;
|
|
100
105
|
} catch (error) {
|
|
101
106
|
throw new Error(
|
|
102
|
-
"Svelte is not installed. Install it with: bun add svelte"
|
|
107
|
+
"Svelte is not installed. Install it with: bun add svelte",
|
|
103
108
|
);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
@@ -107,7 +112,10 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
107
112
|
/**
|
|
108
113
|
* Render a component to HTML string
|
|
109
114
|
*/
|
|
110
|
-
async renderToString(
|
|
115
|
+
async renderToString(
|
|
116
|
+
component: unknown,
|
|
117
|
+
context: SSRContext,
|
|
118
|
+
): Promise<string> {
|
|
111
119
|
await this.init();
|
|
112
120
|
|
|
113
121
|
resetHead();
|
|
@@ -146,7 +154,8 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
146
154
|
|
|
147
155
|
throw new Error("Invalid Svelte component");
|
|
148
156
|
} catch (error) {
|
|
149
|
-
const errorMessage =
|
|
157
|
+
const errorMessage =
|
|
158
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
150
159
|
throw new Error(`Svelte renderToString failed: ${errorMessage}`);
|
|
151
160
|
}
|
|
152
161
|
}
|
|
@@ -154,7 +163,10 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
154
163
|
/**
|
|
155
164
|
* Render a component to a stream
|
|
156
165
|
*/
|
|
157
|
-
renderToStream(
|
|
166
|
+
renderToStream(
|
|
167
|
+
component: unknown,
|
|
168
|
+
context: SSRContext,
|
|
169
|
+
): ReadableStream<Uint8Array> {
|
|
158
170
|
const encoder = new TextEncoder();
|
|
159
171
|
|
|
160
172
|
return new ReadableStream<Uint8Array>({
|
|
@@ -177,8 +189,11 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
177
189
|
|
|
178
190
|
controller.close();
|
|
179
191
|
} catch (error) {
|
|
180
|
-
const errorMessage =
|
|
181
|
-
|
|
192
|
+
const errorMessage =
|
|
193
|
+
error instanceof Error ? error.message : "Unknown error";
|
|
194
|
+
controller.error(
|
|
195
|
+
new Error(`Svelte renderToStream failed: ${errorMessage}`),
|
|
196
|
+
);
|
|
182
197
|
}
|
|
183
198
|
},
|
|
184
199
|
});
|
|
@@ -272,7 +287,7 @@ export class SvelteSSRRenderer implements FrameworkSSRRenderer {
|
|
|
272
287
|
*/
|
|
273
288
|
async renderWithCSS(
|
|
274
289
|
component: unknown,
|
|
275
|
-
context: SSRContext
|
|
290
|
+
context: SSRContext,
|
|
276
291
|
): Promise<{
|
|
277
292
|
html: string;
|
|
278
293
|
head: string;
|
|
@@ -349,7 +364,11 @@ export class SvelteHead {
|
|
|
349
364
|
|
|
350
365
|
setTitle(title: string): this {
|
|
351
366
|
this.title = title;
|
|
352
|
-
addHeadElement({
|
|
367
|
+
addHeadElement({
|
|
368
|
+
tag: "title",
|
|
369
|
+
attrs: {},
|
|
370
|
+
children: [{ tag: "#text", attrs: {}, innerHTML: title }],
|
|
371
|
+
});
|
|
353
372
|
return this;
|
|
354
373
|
}
|
|
355
374
|
|
|
@@ -438,7 +457,22 @@ export function ssrElementToString(element: SSRElement): string {
|
|
|
438
457
|
}
|
|
439
458
|
|
|
440
459
|
// Self-closing tags
|
|
441
|
-
const voidElements = [
|
|
460
|
+
const voidElements = [
|
|
461
|
+
"area",
|
|
462
|
+
"base",
|
|
463
|
+
"br",
|
|
464
|
+
"col",
|
|
465
|
+
"embed",
|
|
466
|
+
"hr",
|
|
467
|
+
"img",
|
|
468
|
+
"input",
|
|
469
|
+
"link",
|
|
470
|
+
"meta",
|
|
471
|
+
"param",
|
|
472
|
+
"source",
|
|
473
|
+
"track",
|
|
474
|
+
"wbr",
|
|
475
|
+
];
|
|
442
476
|
if (voidElements.includes(element.tag)) {
|
|
443
477
|
return attrs ? `<${element.tag} ${attrs}>` : `<${element.tag}>`;
|
|
444
478
|
}
|
|
@@ -462,7 +496,7 @@ function escapeHtml(str: string): string {
|
|
|
462
496
|
* Load a Svelte component from file path
|
|
463
497
|
*/
|
|
464
498
|
export async function loadSvelteComponent(
|
|
465
|
-
filePath: string
|
|
499
|
+
filePath: string,
|
|
466
500
|
): Promise<SvelteComponentConstructor> {
|
|
467
501
|
try {
|
|
468
502
|
// Dynamic import of the compiled Svelte component
|
|
@@ -478,7 +512,7 @@ export async function loadSvelteComponent(
|
|
|
478
512
|
*/
|
|
479
513
|
export function createSvelteSSRContext(
|
|
480
514
|
request: Request,
|
|
481
|
-
initialState: Record<string, unknown> = {}
|
|
515
|
+
initialState: Record<string, unknown> = {},
|
|
482
516
|
): SSRContext {
|
|
483
517
|
const url = new URL(request.url);
|
|
484
518
|
|
|
@@ -543,4 +577,4 @@ export class SveltePageStore {
|
|
|
543
577
|
*/
|
|
544
578
|
export function getPageStore(): SveltePageStore {
|
|
545
579
|
return SveltePageStore.getInstance();
|
|
546
|
-
}
|
|
580
|
+
}
|