@coherent.js/adapters 1.0.0-beta.6 → 1.0.0-beta.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/adapters",
3
- "version": "1.0.0-beta.6",
3
+ "version": "1.0.0-beta.7",
4
4
  "description": "Framework adapters for Coherent.js (Astro, Remix, SvelteKit)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -28,8 +28,8 @@
28
28
  ],
29
29
  "author": "Coherent.js Team",
30
30
  "license": "MIT",
31
- "dependencies": {
32
- "@coherent.js/core": "1.0.0-beta.6"
31
+ "peerDependencies": {
32
+ "@coherent.js/core": "1.0.0-beta.7"
33
33
  },
34
34
  "devDependencies": {
35
35
  "vitest": "^4.0.8"
@@ -38,10 +38,17 @@
38
38
  "type": "git",
39
39
  "url": "git+https://github.com/Tomdrouv1/coherent.js.git"
40
40
  },
41
+ "homepage": "https://github.com/Tomdrouv1/coherent.js",
42
+ "bugs": {
43
+ "url": "https://github.com/Tomdrouv1/coherent.js/issues"
44
+ },
41
45
  "publishConfig": {
42
46
  "access": "public",
43
47
  "registry": "https://registry.npmjs.org/"
44
48
  },
49
+ "engines": {
50
+ "node": ">=20.0.0"
51
+ },
45
52
  "sideEffects": false,
46
53
  "scripts": {
47
54
  "build": "node build.mjs",
package/src/astro.js CHANGED
@@ -1,23 +1,84 @@
1
1
  /**
2
2
  * Astro Integration for Coherent.js
3
+ *
4
+ * Provides server-side rendering of Coherent.js components within Astro projects.
3
5
  */
4
6
 
5
7
  import { render } from '@coherent.js/core';
6
8
 
7
- export function createAstroIntegration(_options = {}) {
9
+ /**
10
+ * Create an Astro integration for Coherent.js
11
+ *
12
+ * @param {Object} [options] - Integration options
13
+ * @param {boolean} [options.hydrate] - Enable client-side hydration
14
+ * @param {string} [options.hydrateScript] - Custom hydration script path
15
+ * @returns {Object} Astro integration configuration
16
+ *
17
+ * @example
18
+ * // astro.config.mjs
19
+ * import { createAstroIntegration } from '@coherent.js/adapters/astro';
20
+ * export default { integrations: [createAstroIntegration()] };
21
+ */
22
+ export function createAstroIntegration(options = {}) {
8
23
  return {
9
24
  name: 'coherent',
10
25
  hooks: {
11
- 'astro:config:setup': ({ addRenderer }) => {
26
+ 'astro:config:setup': ({ addRenderer, updateConfig }) => {
12
27
  addRenderer({
13
28
  name: '@coherent.js/adapters/astro',
14
- serverEntrypoint: '@coherent.js/adapters/astro/server.js',
29
+ serverEntrypoint: '@coherent.js/adapters/astro',
15
30
  });
31
+
32
+ if (options.hydrate) {
33
+ updateConfig({
34
+ vite: {
35
+ optimizeDeps: {
36
+ include: ['@coherent.js/client']
37
+ }
38
+ }
39
+ });
40
+ }
41
+ },
42
+ 'astro:build:done': ({ logger }) => {
43
+ logger?.info('Coherent.js components built successfully');
16
44
  }
17
45
  }
18
46
  };
19
47
  }
20
48
 
21
- export async function renderComponent(Component, props) {
22
- return render(Component, props);
49
+ /**
50
+ * Render a Coherent.js component to HTML string
51
+ *
52
+ * @param {Function|Object} Component - Coherent.js component
53
+ * @param {Object} [props] - Component props
54
+ * @param {Object} [renderOptions] - Rendering options
55
+ * @returns {string} Rendered HTML
56
+ */
57
+ export function renderComponent(Component, props = {}, renderOptions = {}) {
58
+ const componentDef = typeof Component === 'function'
59
+ ? Component(props)
60
+ : Component;
61
+
62
+ return render(componentDef, renderOptions);
63
+ }
64
+
65
+ /**
66
+ * Create a server-side component renderer for Astro
67
+ *
68
+ * @param {Object} [options] - Renderer options
69
+ * @returns {Object} Astro renderer configuration
70
+ */
71
+ export function createRenderer(options = {}) {
72
+ return {
73
+ name: '@coherent.js/astro-renderer',
74
+ check(Component) {
75
+ // Check if this looks like a Coherent.js component (function or plain object with tag keys)
76
+ return typeof Component === 'function' ||
77
+ (typeof Component === 'object' && Component !== null && !Array.isArray(Component));
78
+ },
79
+ renderToStaticMarkup(Component, props) {
80
+ const html = renderComponent(Component, props, options);
81
+ return { html };
82
+ }
83
+ };
23
84
  }
package/src/index.js CHANGED
@@ -3,6 +3,6 @@
3
3
  * Integrations for modern web frameworks
4
4
  */
5
5
 
6
- export { createAstroIntegration } from './astro.js';
7
- export { createRemixAdapter } from './remix.js';
8
- export { createSvelteKitAdapter } from './sveltekit.js';
6
+ export { createAstroIntegration, renderComponent, createRenderer } from './astro.js';
7
+ export { createRemixAdapter, withCoherent } from './remix.js';
8
+ export { createSvelteKitAdapter, createPreprocessor, createHandle } from './sveltekit.js';
package/src/remix.js CHANGED
@@ -1,25 +1,82 @@
1
1
  /**
2
2
  * Remix Adapter for Coherent.js
3
+ *
4
+ * Provides SSR integration and loader utilities for Remix projects.
3
5
  */
4
6
 
5
7
  import { render } from '@coherent.js/core';
6
8
 
7
- export function createRemixAdapter(_options = {}) {
9
+ /**
10
+ * Create a Remix adapter for Coherent.js
11
+ *
12
+ * @param {Object} [options] - Adapter options
13
+ * @param {boolean} [options.hydrate] - Enable client-side hydration
14
+ * @returns {Object} Remix adapter utilities
15
+ *
16
+ * @example
17
+ * const adapter = createRemixAdapter();
18
+ * const html = adapter.renderComponent(MyComponent, { title: 'Hello' });
19
+ */
20
+ export function createRemixAdapter(options = {}) {
8
21
  return {
9
- renderComponent: (component, props) => render(component, props),
10
- createLoader: (component) => {
11
- return async ({ request, params }) => {
12
- return {
13
- component,
14
- props: { request, params }
15
- };
22
+ /**
23
+ * Render a Coherent.js component to HTML
24
+ */
25
+ renderComponent(component, props = {}) {
26
+ const def = typeof component === 'function' ? component(props) : component;
27
+ return render(def);
28
+ },
29
+
30
+ /**
31
+ * Create a Remix loader that renders a Coherent.js component
32
+ */
33
+ createLoader(component, getProps) {
34
+ return async ({ request, params, context }) => {
35
+ const props = getProps
36
+ ? await getProps({ request, params, context })
37
+ : { request, params };
38
+
39
+ const def = typeof component === 'function' ? component(props) : component;
40
+ const html = render(def);
41
+
42
+ return new Response(html, {
43
+ headers: { 'Content-Type': 'text/html; charset=utf-8' }
44
+ });
45
+ };
46
+ },
47
+
48
+ /**
49
+ * Create a Remix action handler that processes form data
50
+ * and renders a Coherent.js component with the result
51
+ */
52
+ createAction(component, handler) {
53
+ return async ({ request, params, context }) => {
54
+ const formData = await request.formData();
55
+ const data = Object.fromEntries(formData);
56
+ const result = await handler({ data, request, params, context });
57
+
58
+ if (result instanceof Response) return result;
59
+
60
+ const def = typeof component === 'function' ? component(result) : component;
61
+ const html = render(def);
62
+
63
+ return new Response(html, {
64
+ headers: { 'Content-Type': 'text/html; charset=utf-8' }
65
+ });
16
66
  };
17
67
  }
18
68
  };
19
69
  }
20
70
 
71
+ /**
72
+ * HOC: Wrap a Coherent.js component for use in Remix routes
73
+ *
74
+ * @param {Function} Component - Coherent.js component function
75
+ * @returns {Function} Remix-compatible component
76
+ */
21
77
  export function withCoherent(Component) {
22
78
  return function CoherentRemixComponent(props) {
23
- return render(Component, props);
79
+ const def = typeof Component === 'function' ? Component(props) : Component;
80
+ return render(def);
24
81
  };
25
82
  }
package/src/sveltekit.js CHANGED
@@ -1,24 +1,117 @@
1
1
  /**
2
2
  * SvelteKit Adapter for Coherent.js
3
+ *
4
+ * Provides server-side rendering and preprocessor integration for SvelteKit projects.
3
5
  */
4
6
 
5
7
  import { render } from '@coherent.js/core';
6
8
 
7
- export function createSvelteKitAdapter(_options = {}) {
9
+ /**
10
+ * Create a SvelteKit adapter for Coherent.js
11
+ *
12
+ * @param {Object} [options] - Adapter options
13
+ * @returns {Object} SvelteKit adapter utilities
14
+ *
15
+ * @example
16
+ * const adapter = createSvelteKitAdapter();
17
+ * const html = adapter.renderComponent(MyComponent, { title: 'Hello' });
18
+ */
19
+ export function createSvelteKitAdapter(options = {}) {
8
20
  return {
9
21
  name: '@coherent.js/sveltekit',
10
- renderComponent: (component, props) => render(component, props)
22
+
23
+ /**
24
+ * Render a Coherent.js component to HTML
25
+ */
26
+ renderComponent(component, props = {}) {
27
+ const def = typeof component === 'function' ? component(props) : component;
28
+ return render(def);
29
+ },
30
+
31
+ /**
32
+ * Create a SvelteKit server load function
33
+ */
34
+ createLoad(component, getProps) {
35
+ return async ({ params, url, fetch }) => {
36
+ const props = getProps
37
+ ? await getProps({ params, url, fetch })
38
+ : { params };
39
+
40
+ const def = typeof component === 'function' ? component(props) : component;
41
+ const html = render(def);
42
+
43
+ return { html, props };
44
+ };
45
+ },
46
+
47
+ /**
48
+ * Create a SvelteKit form action handler
49
+ */
50
+ createAction(handler) {
51
+ return async ({ request, params }) => {
52
+ const formData = await request.formData();
53
+ const data = Object.fromEntries(formData);
54
+ return handler({ data, params });
55
+ };
56
+ }
11
57
  };
12
58
  }
13
59
 
14
- export function createPreprocessor(_options = {}) {
60
+ /**
61
+ * Create a Svelte preprocessor for Coherent.js templates
62
+ *
63
+ * Transforms inline Coherent.js object syntax within Svelte components.
64
+ *
65
+ * @param {Object} [options] - Preprocessor options
66
+ * @param {string} [options.tag] - Custom tag to process (default: 'coherent')
67
+ * @returns {Object} Svelte preprocessor
68
+ */
69
+ export function createPreprocessor(options = {}) {
70
+ const tag = options.tag || 'coherent';
71
+
15
72
  return {
16
73
  name: 'coherent-preprocessor',
17
- markup({ content, _filename }) {
18
- // Basic preprocessor logic
74
+ markup({ content, filename }) {
75
+ // Find <coherent> blocks and render them to HTML
76
+ const regex = new RegExp(`<${tag}>(.*?)</${tag}>`, 'gs');
77
+ let transformed = content;
78
+ let match;
79
+
80
+ while ((match = regex.exec(content)) !== null) {
81
+ try {
82
+ // The content inside <coherent> tags should be a JS object literal
83
+ // This is a basic transform — production use should handle more cases
84
+ const objectStr = match[1].trim();
85
+ transformed = transformed.replace(match[0], `{@html coherentRender(${objectStr})}`);
86
+ } catch {
87
+ // Leave unchanged if parsing fails
88
+ }
89
+ }
90
+
19
91
  return {
20
- code: content
92
+ code: transformed,
93
+ map: null
21
94
  };
22
95
  }
23
96
  };
24
97
  }
98
+
99
+ /**
100
+ * SvelteKit hooks integration
101
+ *
102
+ * @param {Object} [options] - Hook options
103
+ * @returns {Object} SvelteKit handle function
104
+ */
105
+ export function createHandle(options = {}) {
106
+ return async ({ event, resolve }) => {
107
+ // Add Coherent.js render function to locals
108
+ event.locals.coherent = {
109
+ render(component, props = {}) {
110
+ const def = typeof component === 'function' ? component(props) : component;
111
+ return render(def);
112
+ }
113
+ };
114
+
115
+ return resolve(event);
116
+ };
117
+ }