@mochabug/adaptkit 1.0.0-beta.2 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,7 @@
1
1
  import { build } from 'esbuild';
2
+ import { sync as glob } from 'glob';
2
3
  import fs from 'node:fs';
4
+ import path from 'node:path';
3
5
 
4
6
  if (!process.env.PLUGINS_CDN) {
5
7
  console.error('PLUGINS_CDN is required');
@@ -13,34 +15,93 @@ if (!manifest.organization || !manifest.name || !manifest.version) {
13
15
  }
14
16
  const CDN_PATH = `${process.env.PLUGINS_CDN}/${manifest.organization}/${manifest.name}/${manifest.version}`;
15
17
 
16
- if (fs.existsSync('cdn')) {
17
- fs.rmSync('cdn', { recursive: true, force: true })
18
- }
18
+ fs.rmSync('./cdn', { recursive: true });
19
19
 
20
- build({
21
- entryPoints: [___ENTRYPOINTS___],
20
+ // Build the client and place all the assets onto the corresponding CDN for the plugin
21
+ const loader = {
22
+ '.css': 'css',
23
+ '.woff': 'file',
24
+ '.woff2': 'file',
25
+ '.png': 'file',
26
+ '.jpg': 'file',
27
+ '.jpeg': 'file',
28
+ '.gif': 'file',
29
+ '.svg': 'file',
30
+ '.ttf': 'file',
31
+ '.otf': 'file',
32
+ };
33
+ const result = await build({
34
+ entryPoints: glob('./src/vertices/**/ui/*.main.tsx'),
22
35
  outdir: 'cdn',
23
36
  bundle: true,
24
37
  minify: true,
25
- sourcemap: true,
26
38
  platform: 'browser',
27
39
  splitting: true,
40
+ tsconfig: 'tsconfig.json',
28
41
  format: 'esm',
29
- publicPath: CDN_PATH,
30
42
  metafile: true,
31
- loader: {
32
- '.css': 'css',
33
- '.woff': 'file',
34
- '.woff2': 'file',
35
- '.png': 'file',
36
- '.jpg': 'file',
37
- '.jpeg': 'file',
38
- '.gif': 'file',
39
- '.svg': 'file',
40
- '.ttf': 'file',
41
- '.otf': 'file',
43
+ publicPath: CDN_PATH,
44
+ loader,
45
+ });
46
+
47
+ const entrypoints = {
48
+ configurators: {},
49
+ executors: {},
50
+ vertices: [],
51
+ };
52
+ for (const [outputPath, outputMeta] of Object.entries(result.metafile.outputs)) {
53
+ if (!outputMeta.entryPoint) {
54
+ continue;
55
+ }
56
+ let vertex = path.dirname(path.dirname(path.relative('./src/vertices', outputMeta.entryPoint)));
57
+ if (entrypoints.vertices.findIndex((v) => v === vertex) === -1 && manifest.vertices.find((v) => v.name === vertex)) {
58
+ entrypoints.vertices.push(vertex);
59
+ }
60
+ if (outputMeta.entryPoint.endsWith('executor.main.tsx')) {
61
+ entrypoints.executors[vertex] = { js: `${CDN_PATH}/${outputPath.substring(4)}` };
62
+ if (outputMeta.cssBundle) {
63
+ entrypoints.executors[vertex].css = `${CDN_PATH}/${outputMeta.cssBundle.substring(4)}`;
64
+ }
65
+ } else if (outputMeta.entryPoint.endsWith('configurator.main.tsx')) {
66
+ entrypoints.configurators[vertex] = { js: `${CDN_PATH}/${outputPath.substring(4)}` };
67
+ if (outputMeta.cssBundle) {
68
+ entrypoints.configurators[vertex].css = `${CDN_PATH}/${outputMeta.cssBundle.substring(4)}`;
69
+ }
70
+ }
71
+ }
72
+
73
+ // Build the static site, make sure that we have the CDN as the public path for the assets
74
+ await build({
75
+ entryPoints: glob('./src/vertices/**/*.ssg.tsx'),
76
+ outdir: 'dist',
77
+ tsconfig: 'tsconfig.json',
78
+ bundle: true,
79
+ platform: 'node',
80
+ format: 'cjs',
81
+ target: 'esnext',
82
+ publicPath: CDN_PATH,
83
+ loader,
84
+ outExtension: {
85
+ '.js': '.cjs',
42
86
  },
43
- }).catch((err) => {
44
- console.error(err);
45
- process.exit(1);
46
- });
87
+ });
88
+
89
+ const configIndices = {};
90
+ for (const file of glob('./dist/**/configurator.ssg.cjs')) {
91
+ const { default: render } = await import(`file://${path.resolve(file)}`);
92
+ const vertex = entrypoints.vertices.length === 1 ? entrypoints.vertices[0] : path.dirname(path.dirname(path.relative('./dist', file)));
93
+ const entrypoint = entrypoints.configurators[vertex];
94
+ if (entrypoint) {
95
+ configIndices[vertex] = render.default(entrypoint.js, entrypoint.css);
96
+ }
97
+ }
98
+ fs.writeFileSync('./dist/configurator-index-html.json', JSON.stringify(configIndices));
99
+ const execIndices = {};
100
+ for (const file of glob('./dist/**/executor.ssg.cjs')) {
101
+ const { default: render } = await import(`file://${path.resolve(file)}`);
102
+ const vertex = entrypoints.vertices.length === 1 ? entrypoints.vertices[0] : path.dirname(path.dirname(path.relative('./dist', file)));
103
+
104
+ const entrypoint = entrypoints.executors[vertex];
105
+ execIndices[vertex] = render.default(entrypoint.js, entrypoint.css);
106
+ }
107
+ fs.writeFileSync('./dist/executor-index-html.json', JSON.stringify(execIndices));
package/assets/build.js CHANGED
@@ -17,20 +17,31 @@ const CDN_PATH = `${process.env.PLUGINS_CDN}/${manifest.organization}/${manifest
17
17
 
18
18
  const { env } = defineEnv({ nodeCompat: true, presets: [cloudflare] });
19
19
 
20
- if (fs.existsSync('dist')) {
21
- fs.rmSync('dist', { recursive: true, force: true })
22
- }
23
20
  const entryPoints = ['./src/executors']
24
21
  if (fs.existsSync('./src/configurators.ts')) {
25
22
  entryPoints.push('./src/configurators')
26
23
  }
27
24
 
28
- build({
25
+ // Set up the defines, this will automatically load ssg index.html files if they exists
26
+ const define = {
27
+ PLUGINS_CDN: JSON.stringify(CDN_PATH)
28
+ };
29
+ if (fs.existsSync('./dist/configurator-index-html.json')) {
30
+ const CONFIGURATOR_INDEX_HTML = fs.readFileSync('./dist/configurator-index-html.json', 'utf8');
31
+ define.CONFIGURATOR_INDEX_HTML = CONFIGURATOR_INDEX_HTML;
32
+ }
33
+ if (fs.existsSync('./dist/executor-index-html.json')) {
34
+ const EXECUTOR_INDEX_HTML = fs.readFileSync('./dist/executor-index-html.json', 'utf8');
35
+ define.EXECUTOR_INDEX_HTML = EXECUTOR_INDEX_HTML;
36
+ }
37
+
38
+ await build({
29
39
  entryPoints,
30
40
  outdir: 'dist',
31
41
  bundle: true,
32
42
  minify: true,
33
43
  treeShaking: true,
44
+ sourcemap: false,
34
45
  splitting: false,
35
46
  format: 'esm',
36
47
  platform: 'node',
@@ -41,10 +52,6 @@ build({
41
52
  conditions: ["workerd"],
42
53
  external: env.external,
43
54
  alias: env.alias,
44
- define: {
45
- PLUGINS_CDN: JSON.stringify(CDN_PATH),
46
- }
47
- }).catch((error) => {
48
- console.error(error)
49
- process.exit(1)
55
+ publicPath: CDN_PATH,
56
+ define,
50
57
  });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * This file serves as the main entry point for the React application. It uses
3
+ * `hydrateRoot` from `react-dom/client` to attach the React component tree, starting
4
+ * with the `<App />` component, to the DOM element with the ID of "root".
5
+ *
6
+ * When server-side rendering (SSR) or static site generation (SSG) is used,
7
+ * `hydrateRoot` reuses existing markup on the page, preserving performance and
8
+ * maintaining any server-rendered content. If you are not using SSR, you may see
9
+ * `createRoot` used in a similar manner instead.
10
+ *
11
+ * The `<App />` component is the root component of the application, where all
12
+ * child components are nested. This setup ensures that the React application is
13
+ * rendered and managed within the specified DOM node.
14
+ */
15
+ import React from 'react';
16
+ import { hydrateRoot } from 'react-dom/client';
17
+ import App from './configurator.App';
18
+
19
+ hydrateRoot(document.getElementById('root')!, <App />);
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This file demonstrates the generation of HTML from a React application on the server
3
+ * (or ahead of time). It exports a single function that takes a CDN base path as an
4
+ * argument and returns an HTML string. Within that HTML, the `<App>` component is
5
+ * rendered to a string via `renderToString` and injected into the `<div id="root">`.
6
+ *
7
+ * This approach can be used for server-side rendering (SSR) or static site generation
8
+ * (SSG). By pre-rendering the React component, you can improve performance and
9
+ * provide faster initial page loads.
10
+ */
11
+ import React from 'react';
12
+ import { renderToString } from 'react-dom/server';
13
+ import App from './configurator.App';
14
+
15
+ export default function (js: string, css?: string) {
16
+ return `
17
+ <!DOCTYPE html>
18
+ <html lang="en">
19
+ <head>
20
+ <meta charset="utf-8" />
21
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
22
+ <title>Title</title>
23
+ ${css ? `<link rel="stylesheet" href="${css}" />` : ''}
24
+ </head>
25
+ <body>
26
+ <div id="root">${renderToString(<App />)}</div>
27
+ <script type="module" src="${js}"></script>
28
+ </body>
29
+ </html>
30
+ `;
31
+ }
@@ -6,9 +6,6 @@ import {
6
6
  ExternalConfiguratorRouter,
7
7
  InternalConfiguratorRouter
8
8
  } from '@mochabug/adapt-plugin-toolkit/router';
9
- import React from 'react';
10
- import { renderToString } from 'react-dom/server';
11
- import App from './../../frontend/___APP_IMPORT___';
12
9
 
13
10
  export default {
14
11
  external: new ExternalConfiguratorRouter()
@@ -33,25 +30,9 @@ export default {
33
30
  });
34
31
  })
35
32
  .add('GET', '{*any}', async () => {
36
- return new Response(readIndexHtml(), {
37
- headers: {
38
- 'Content-Type': 'text/html; charset=utf-8'
39
- }
33
+ return new Response(CONFIGURATOR_INDEX_HTML['___VERTEX_NAME___'], {
34
+ headers: { 'Content-Type': 'text/html' }
40
35
  });
41
36
  }),
42
37
  internal: new InternalConfiguratorRouter()
43
38
  };
44
- function readIndexHtml() {
45
- return `
46
- <!DOCTYPE html>
47
- <html>
48
- <head>
49
- <title>My SSR App</title>
50
- </head>
51
- <body>
52
- <div id="root">${renderToString(<App />)}</div>
53
- <script type="module" src="${PLUGINS_CDN}/___CLIENT__NAME___.js"></script>
54
- </body>
55
- </html>
56
- `;
57
- }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * This file serves as the main entry point for the React application. It uses
3
+ * `hydrateRoot` from `react-dom/client` to attach the React component tree, starting
4
+ * with the `<App />` component, to the DOM element with the ID of "root".
5
+ *
6
+ * When server-side rendering (SSR) or static site generation (SSG) is used,
7
+ * `hydrateRoot` reuses existing markup on the page, preserving performance and
8
+ * maintaining any server-rendered content. If you are not using SSR, you may see
9
+ * `createRoot` used in a similar manner instead.
10
+ *
11
+ * The `<App />` component is the root component of the application, where all
12
+ * child components are nested. This setup ensures that the React application is
13
+ * rendered and managed within the specified DOM node.
14
+ */
15
+ import React from 'react';
16
+ import { hydrateRoot } from 'react-dom/client';
17
+ import App from './executor.App';
18
+
19
+ hydrateRoot(document.getElementById('root')!, <App />);
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This file demonstrates the generation of HTML from a React application on the server
3
+ * (or ahead of time). It exports a single function that takes a CDN base path as an
4
+ * argument and returns an HTML string. Within that HTML, the `<App>` component is
5
+ * rendered to a string via `renderToString` and injected into the `<div id="root">`.
6
+ *
7
+ * This approach can be used for server-side rendering (SSR) or static site generation
8
+ * (SSG). By pre-rendering the React component, you can improve performance and
9
+ * provide faster initial page loads.
10
+ */
11
+ import React from 'react';
12
+ import { renderToString } from 'react-dom/server';
13
+ import App from './executor.App';
14
+
15
+ export default function (js: string, css?: string) {
16
+ return `
17
+ <!DOCTYPE html>
18
+ <html lang="en">
19
+ <head>
20
+ <meta charset="utf-8" />
21
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
22
+ <title>Title</title>
23
+ ${css ? `<link rel="stylesheet" href="${css}" />` : ''}
24
+ </head>
25
+ <body>
26
+ <div id="root">${renderToString(<App />)}</div>
27
+ <script type="module" src="${js}"></script>
28
+ </body>
29
+ </html>
30
+ `;
31
+ }
@@ -6,9 +6,6 @@ import {
6
6
  ExternalExecutorRouter,
7
7
  InternalExecutorRouter
8
8
  } from '@mochabug/adapt-plugin-toolkit/router';
9
- import React from 'react';
10
- import { renderToString } from 'react-dom/server';
11
- import App from './../../frontend/___APP_IMPORT___';
12
9
 
13
10
  export default {
14
11
  external: new ExternalExecutorRouter()
@@ -30,10 +27,8 @@ export default {
30
27
  return new Response();
31
28
  })
32
29
  .add('GET', '{*any}', async () => {
33
- return new Response(readIndexHtml(), {
34
- headers: {
35
- 'Content-Type': 'text/html; charset=utf-8'
36
- }
30
+ return new Response(EXECUTOR_INDEX_HTML['___VERTEX_NAME___'], {
31
+ headers: { 'Content-Type': 'text/html' }
37
32
  });
38
33
  }),
39
34
  internal: new InternalExecutorRouter()
@@ -54,17 +49,3 @@ export default {
54
49
  console.log(res);
55
50
  })
56
51
  };
57
- function readIndexHtml() {
58
- return `
59
- <!DOCTYPE html>
60
- <html>
61
- <head>
62
- <title>My SSR App</title>
63
- </head>
64
- <body>
65
- <div id="root">${renderToString(<App />)}</div>
66
- <script type="module" src="${PLUGINS_CDN}/___CLIENT__NAME___.js"></script>
67
- </body>
68
- </html>
69
- `;
70
- }
@@ -1,5 +1,7 @@
1
1
  declare global {
2
2
  const PLUGINS_CDN: string;
3
+ const CONFIGURATOR_INDEX_HTML: Record<string, string>;
4
+ const EXECUTOR_INDEX_HTML: Record<string, string>;
3
5
  }
4
6
 
5
7
  export {};