@ecopages/kitajs 0.2.0-alpha.3 → 0.2.0-alpha.31
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/CHANGELOG.md +7 -7
- package/README.md +24 -6
- package/package.json +2 -2
- package/src/kitajs-renderer.d.ts +2 -1
- package/src/kitajs-renderer.js +25 -47
- package/src/kitajs.constants.d.ts +1 -0
- package/src/kitajs.constants.js +4 -0
- package/src/kitajs.plugin.js +3 -1
- package/src/kitajs-renderer.ts +0 -130
- package/src/kitajs.plugin.ts +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -6,16 +6,16 @@ All notable changes to `@ecopages/kitajs` are documented here.
|
|
|
6
6
|
|
|
7
7
|
## [UNRELEASED] — TBD
|
|
8
8
|
|
|
9
|
-
###
|
|
9
|
+
### Bug Fixes
|
|
10
10
|
|
|
11
|
-
-
|
|
11
|
+
- Fixed Kita full-route and direct `ctx.render()` rendering to stay on the renderer-owned page/layout/document path while resolving mixed boundaries inside the owning renderer.
|
|
12
|
+
- Fixed Kita foreign-subtree payload compatibility coverage and removed the plugin/renderer integration-name import cycle.
|
|
12
13
|
|
|
13
|
-
###
|
|
14
|
+
### Documentation
|
|
14
15
|
|
|
15
|
-
-
|
|
16
|
-
- Ambient module declarations cleaned up (`5f46ecc5`).
|
|
17
|
-
- Updated test suite for esbuild adapter and Node.js runtime compatibility (`31a44458`).
|
|
16
|
+
- Updated the README to document `.kita.tsx` route ownership and Kita's role as an outer shell in mixed-renderer apps.
|
|
18
17
|
|
|
19
18
|
### Tests
|
|
20
19
|
|
|
21
|
-
- Updated integration
|
|
20
|
+
- Updated integration coverage for explicit foreign-subtree composition and Node and esbuild compatibility.
|
|
21
|
+
- Added renderer-level coverage for the foreign-subtree payload compatibility contract.
|
package/README.md
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ecopages/kitajs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Integration plugin for [KitaJS](https://kitajs.org/html/) HTML in Ecopages. Use it when Kita should own `.kita.tsx` routes, page shells, and document shells in HTML-first apps.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
bun add @ecopages/kitajs @kitajs/html @kitajs/ts-html-plugin
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
`@kitajs/html` and `@kitajs/ts-html-plugin` are required peer dependencies for this package.
|
|
12
|
+
|
|
11
13
|
## Usage
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
Import and register the `kitajsPlugin` in your `eco.config.ts`.
|
|
14
16
|
|
|
15
17
|
```ts
|
|
16
|
-
import { ConfigBuilder } from '@ecopages/core';
|
|
18
|
+
import { ConfigBuilder } from '@ecopages/core/config-builder';
|
|
17
19
|
import { kitajsPlugin } from '@ecopages/kitajs';
|
|
18
20
|
|
|
19
21
|
const config = await new ConfigBuilder()
|
|
@@ -23,3 +25,19 @@ const config = await new ConfigBuilder()
|
|
|
23
25
|
|
|
24
26
|
export default config;
|
|
25
27
|
```
|
|
28
|
+
|
|
29
|
+
## What This Integration Owns
|
|
30
|
+
|
|
31
|
+
- `.kita.tsx` route files.
|
|
32
|
+
- Page, layout, and document shells rendered by `@kitajs/html`.
|
|
33
|
+
- HTML-first outer shells that host nested foreign subtrees from other integrations.
|
|
34
|
+
|
|
35
|
+
## Mixed Rendering
|
|
36
|
+
|
|
37
|
+
Kita works well as the outer renderer in mixed apps. When a Kita-owned page encounters a nested foreign child from another integration, Ecopages resolves that foreign subtree with its owning renderer and inserts the resulting HTML back into the Kita shell.
|
|
38
|
+
|
|
39
|
+
Important:
|
|
40
|
+
|
|
41
|
+
- Components that may render foreign children must declare those children in `config.dependencies.components`.
|
|
42
|
+
- Ecopages validates mixed-renderer ownership from declared dependencies during render preparation instead of inferring every foreign child from rendered HTML.
|
|
43
|
+
- Kita remains an HTML-first outer shell. Same-integration Kita children do not go through a separate universal child serialization contract.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/kitajs",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.31",
|
|
4
4
|
"description": "Kitajs plugin for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"directory": "packages/integrations/kitajs"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@ecopages/core": "0.2.0-alpha.
|
|
20
|
+
"@ecopages/core": "0.2.0-alpha.31",
|
|
21
21
|
"@kitajs/html": "^4.1.0",
|
|
22
22
|
"@kitajs/ts-html-plugin": "^4.0.1"
|
|
23
23
|
}
|
package/src/kitajs-renderer.d.ts
CHANGED
|
@@ -10,8 +10,9 @@ import { IntegrationRenderer, type RenderToResponseContext } from '@ecopages/cor
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class KitaRenderer extends IntegrationRenderer<EcoPagesElement> {
|
|
12
12
|
name: string;
|
|
13
|
+
private isFunctionComponent;
|
|
13
14
|
/**
|
|
14
|
-
* Renders a Kita
|
|
15
|
+
* Renders a Kita-owned foreign subtree for component-level orchestration.
|
|
15
16
|
*
|
|
16
17
|
* Includes component-scoped dependency assets when declared.
|
|
17
18
|
*/
|
package/src/kitajs-renderer.js
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
import { IntegrationRenderer } from "@ecopages/core/route-renderer/integration-renderer";
|
|
2
|
-
import {
|
|
2
|
+
import { KITAJS_PLUGIN_NAME } from "./kitajs.constants.js";
|
|
3
3
|
class KitaRenderer extends IntegrationRenderer {
|
|
4
|
-
name =
|
|
4
|
+
name = KITAJS_PLUGIN_NAME;
|
|
5
|
+
isFunctionComponent(component) {
|
|
6
|
+
return typeof component === "function";
|
|
7
|
+
}
|
|
5
8
|
/**
|
|
6
|
-
* Renders a Kita
|
|
9
|
+
* Renders a Kita-owned foreign subtree for component-level orchestration.
|
|
7
10
|
*
|
|
8
11
|
* Includes component-scoped dependency assets when declared.
|
|
9
12
|
*/
|
|
10
13
|
async renderComponent(input) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const hasDependencies = Boolean(input.component.config?.dependencies);
|
|
16
|
-
const canResolveAssets = typeof this.assetProcessingService?.processDependencies === "function";
|
|
17
|
-
const assets = hasDependencies && canResolveAssets ? await this.processComponentDependencies([input.component]) : void 0;
|
|
18
|
-
return {
|
|
19
|
-
html,
|
|
20
|
-
canAttachAttributes: true,
|
|
21
|
-
rootTag: this.getRootTagName(html),
|
|
22
|
-
integrationName: this.name,
|
|
23
|
-
assets
|
|
24
|
-
};
|
|
14
|
+
if (!this.isFunctionComponent(input.component)) {
|
|
15
|
+
throw new TypeError("Kita renderer expected a callable component.");
|
|
16
|
+
}
|
|
17
|
+
return this.renderStringComponentWithQueuedForeignSubtrees(input, input.component);
|
|
25
18
|
}
|
|
26
19
|
async render({
|
|
27
20
|
params,
|
|
@@ -35,46 +28,31 @@ class KitaRenderer extends IntegrationRenderer {
|
|
|
35
28
|
HtmlTemplate
|
|
36
29
|
}) {
|
|
37
30
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
return await this.renderPageWithDocumentShell({
|
|
32
|
+
page: {
|
|
33
|
+
component: Page,
|
|
34
|
+
props: { params, query, ...props, locals: pageLocals }
|
|
35
|
+
},
|
|
36
|
+
layout: Layout ? {
|
|
37
|
+
component: Layout,
|
|
38
|
+
props: locals ? { locals } : {}
|
|
39
|
+
} : void 0,
|
|
40
|
+
htmlTemplate: HtmlTemplate,
|
|
41
41
|
metadata,
|
|
42
|
-
pageProps: props ?? {}
|
|
43
|
-
children
|
|
42
|
+
pageProps: props ?? {}
|
|
44
43
|
});
|
|
45
|
-
return this.DOC_TYPE + body;
|
|
46
44
|
} catch (error) {
|
|
47
45
|
throw this.createRenderError("Error rendering page", error);
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
async renderToResponse(view, props, ctx) {
|
|
51
49
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const pageContent = await viewFn(props);
|
|
55
|
-
if (ctx.partial) {
|
|
56
|
-
return this.createHtmlResponse(pageContent, ctx);
|
|
57
|
-
}
|
|
58
|
-
const children = Layout ? await Layout({ children: pageContent }) : pageContent;
|
|
59
|
-
const HtmlTemplate = await this.getHtmlTemplate();
|
|
60
|
-
const metadata = view.metadata ? await view.metadata({
|
|
61
|
-
params: {},
|
|
62
|
-
query: {},
|
|
50
|
+
return await this.renderViewWithDocumentShell({
|
|
51
|
+
view,
|
|
63
52
|
props,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
await this.prepareViewDependencies(view, Layout);
|
|
67
|
-
const html = this.DOC_TYPE + await HtmlTemplate({
|
|
68
|
-
metadata,
|
|
69
|
-
pageProps: props,
|
|
70
|
-
children: children ?? ""
|
|
53
|
+
ctx,
|
|
54
|
+
layout: view.config?.layout
|
|
71
55
|
});
|
|
72
|
-
const transformedResponse = await this.htmlTransformer.transform(
|
|
73
|
-
new Response(html, {
|
|
74
|
-
headers: { "Content-Type": "text/html" }
|
|
75
|
-
})
|
|
76
|
-
);
|
|
77
|
-
return this.createHtmlResponse(transformedResponse.body ?? "", ctx);
|
|
78
56
|
} catch (error) {
|
|
79
57
|
throw this.createRenderError("Error rendering view", error);
|
|
80
58
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const KITAJS_PLUGIN_NAME = "kitajs";
|
package/src/kitajs.plugin.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { IntegrationPlugin } from "@ecopages/core/plugins/integration-plugin";
|
|
2
2
|
import { KitaRenderer } from "./kitajs-renderer.js";
|
|
3
|
-
|
|
3
|
+
import { KITAJS_PLUGIN_NAME } from "./kitajs.constants.js";
|
|
4
|
+
const PLUGIN_NAME = KITAJS_PLUGIN_NAME;
|
|
4
5
|
class KitaHtmlPlugin extends IntegrationPlugin {
|
|
5
6
|
renderer = KitaRenderer;
|
|
6
7
|
constructor(options) {
|
|
7
8
|
super({
|
|
8
9
|
name: PLUGIN_NAME,
|
|
9
10
|
extensions: [".kita.tsx"],
|
|
11
|
+
jsxImportSource: "@kitajs/html",
|
|
10
12
|
...options
|
|
11
13
|
});
|
|
12
14
|
}
|
package/src/kitajs-renderer.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This module contains the Kita.js renderer
|
|
3
|
-
* @module
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ComponentRenderInput,
|
|
8
|
-
ComponentRenderResult,
|
|
9
|
-
EcoComponent,
|
|
10
|
-
EcoPagesElement,
|
|
11
|
-
IntegrationRendererRenderOptions,
|
|
12
|
-
RouteRendererBody,
|
|
13
|
-
} from '@ecopages/core';
|
|
14
|
-
import { IntegrationRenderer, type RenderToResponseContext } from '@ecopages/core/route-renderer/integration-renderer';
|
|
15
|
-
import { PLUGIN_NAME } from './kitajs.plugin.ts';
|
|
16
|
-
|
|
17
|
-
/** Narrows an EcoComponent to its KitaJS callable signature. */
|
|
18
|
-
type KitaViewFn<P> = (props: P) => Promise<EcoPagesElement> | EcoPagesElement;
|
|
19
|
-
|
|
20
|
-
/** KitaJS layout function signature. */
|
|
21
|
-
type KitaLayoutFn = (props: { children: EcoPagesElement } & Record<string, unknown>) => Promise<EcoPagesElement>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* A renderer for the Kita.js integration.
|
|
25
|
-
* It renders a page using the HtmlTemplate and Page components.
|
|
26
|
-
*/
|
|
27
|
-
export class KitaRenderer extends IntegrationRenderer<EcoPagesElement> {
|
|
28
|
-
name = PLUGIN_NAME;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Renders a Kita component boundary for component-level orchestration.
|
|
32
|
-
*
|
|
33
|
-
* Includes component-scoped dependency assets when declared.
|
|
34
|
-
*/
|
|
35
|
-
override async renderComponent(input: ComponentRenderInput): Promise<ComponentRenderResult> {
|
|
36
|
-
const component = input.component as KitaViewFn<Record<string, unknown>>;
|
|
37
|
-
const props = input.children === undefined ? input.props : { ...input.props, children: input.children };
|
|
38
|
-
const content = await component(props);
|
|
39
|
-
const html = String(content);
|
|
40
|
-
const hasDependencies = Boolean(input.component.config?.dependencies);
|
|
41
|
-
const canResolveAssets = typeof this.assetProcessingService?.processDependencies === 'function';
|
|
42
|
-
const assets =
|
|
43
|
-
hasDependencies && canResolveAssets
|
|
44
|
-
? await this.processComponentDependencies([input.component])
|
|
45
|
-
: undefined;
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
html,
|
|
49
|
-
canAttachAttributes: true,
|
|
50
|
-
rootTag: this.getRootTagName(html),
|
|
51
|
-
integrationName: this.name,
|
|
52
|
-
assets,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async render({
|
|
57
|
-
params,
|
|
58
|
-
query,
|
|
59
|
-
props,
|
|
60
|
-
locals,
|
|
61
|
-
pageLocals,
|
|
62
|
-
metadata,
|
|
63
|
-
Page,
|
|
64
|
-
Layout,
|
|
65
|
-
HtmlTemplate,
|
|
66
|
-
}: IntegrationRendererRenderOptions): Promise<RouteRendererBody> {
|
|
67
|
-
try {
|
|
68
|
-
const pageContent = await Page({ params, query, ...props, locals: pageLocals });
|
|
69
|
-
const children =
|
|
70
|
-
Layout && typeof Layout === 'function' ? await Layout({ children: pageContent, locals }) : pageContent;
|
|
71
|
-
const body = await HtmlTemplate({
|
|
72
|
-
metadata,
|
|
73
|
-
pageProps: props ?? {},
|
|
74
|
-
children,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return this.DOC_TYPE + body;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
throw this.createRenderError('Error rendering page', error);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async renderToResponse<P = Record<string, unknown>>(
|
|
84
|
-
view: EcoComponent<P>,
|
|
85
|
-
props: P,
|
|
86
|
-
ctx: RenderToResponseContext,
|
|
87
|
-
): Promise<Response> {
|
|
88
|
-
try {
|
|
89
|
-
const Layout = view.config?.layout as KitaLayoutFn | undefined;
|
|
90
|
-
|
|
91
|
-
const viewFn = view as KitaViewFn<P>;
|
|
92
|
-
const pageContent = await viewFn(props);
|
|
93
|
-
|
|
94
|
-
if (ctx.partial) {
|
|
95
|
-
return this.createHtmlResponse(pageContent, ctx);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const children = Layout ? await Layout({ children: pageContent }) : pageContent;
|
|
99
|
-
|
|
100
|
-
const HtmlTemplate = await this.getHtmlTemplate();
|
|
101
|
-
const metadata = view.metadata
|
|
102
|
-
? await view.metadata({
|
|
103
|
-
params: {},
|
|
104
|
-
query: {},
|
|
105
|
-
props: props as Record<string, unknown>,
|
|
106
|
-
appConfig: this.appConfig,
|
|
107
|
-
})
|
|
108
|
-
: this.appConfig.defaultMetadata;
|
|
109
|
-
await this.prepareViewDependencies(view, Layout as EcoComponent | undefined);
|
|
110
|
-
|
|
111
|
-
const html =
|
|
112
|
-
this.DOC_TYPE +
|
|
113
|
-
(await HtmlTemplate({
|
|
114
|
-
metadata,
|
|
115
|
-
pageProps: props as Record<string, unknown>,
|
|
116
|
-
children: children ?? '',
|
|
117
|
-
}));
|
|
118
|
-
|
|
119
|
-
const transformedResponse = await this.htmlTransformer.transform(
|
|
120
|
-
new Response(html, {
|
|
121
|
-
headers: { 'Content-Type': 'text/html' },
|
|
122
|
-
}),
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
return this.createHtmlResponse(transformedResponse.body ?? '', ctx);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
throw this.createRenderError('Error rendering view', error);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
package/src/kitajs.plugin.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { IntegrationPlugin, type IntegrationPluginConfig } from '@ecopages/core/plugins/integration-plugin';
|
|
2
|
-
import { KitaRenderer } from './kitajs-renderer.ts';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The name of the Kita.js plugin
|
|
6
|
-
*/
|
|
7
|
-
export const PLUGIN_NAME = 'kitajs';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The Kita.js plugin class
|
|
11
|
-
* This plugin provides support for Kita.js components in Ecopages
|
|
12
|
-
*/
|
|
13
|
-
export class KitaHtmlPlugin extends IntegrationPlugin {
|
|
14
|
-
renderer = KitaRenderer;
|
|
15
|
-
|
|
16
|
-
constructor(options?: Omit<IntegrationPluginConfig, 'name'>) {
|
|
17
|
-
super({
|
|
18
|
-
name: PLUGIN_NAME,
|
|
19
|
-
extensions: ['.kita.tsx'],
|
|
20
|
-
...options,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Factory function to create a Kita.js plugin instance.
|
|
27
|
-
* @param options Configuration options for the Kita.js plugin
|
|
28
|
-
* @returns A new KitaHtmlPlugin instance
|
|
29
|
-
*/
|
|
30
|
-
export function kitajsPlugin(options?: Omit<IntegrationPluginConfig, 'name'>): KitaHtmlPlugin {
|
|
31
|
-
return new KitaHtmlPlugin(options);
|
|
32
|
-
}
|