@mochabug/adaptkit 0.14.5 → 1.0.0-beta.10
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/assets/build-client.js +107 -0
- package/assets/build.js +57 -0
- package/assets/configurator.App.tsx +123 -0
- package/assets/configurator.main.tsx +19 -0
- package/assets/configurator.ssg.tsx +31 -0
- package/assets/{configurator.ts → configurator_none.ts} +1 -1
- package/assets/configurator_react.tsx +38 -0
- package/assets/executor.App.tsx +103 -0
- package/assets/executor.main.tsx +19 -0
- package/assets/executor.ssg.tsx +31 -0
- package/assets/{executor_browser.ts → executor_browser_none.ts} +1 -1
- package/assets/executor_browser_react.tsx +51 -0
- package/assets/gitignore +3 -0
- package/assets/global.d.ts +7 -0
- package/assets/inject.js +15 -0
- package/assets/tsconf.json +9 -3
- package/bin/index.js +12 -3243
- package/bin/index.js.map +7 -0
- package/package.json +11 -23
- package/assets/rollup.config.ts +0 -40
- package/bin/add.d.ts +0 -3
- package/bin/add.d.ts.map +0 -1
- package/bin/genproto/buf/validate/validate.d.ts +0 -4657
- package/bin/genproto/buf/validate/validate.d.ts.map +0 -1
- package/bin/genproto/google/api/client.d.ts +0 -785
- package/bin/genproto/google/api/client.d.ts.map +0 -1
- package/bin/genproto/google/api/http.d.ts +0 -452
- package/bin/genproto/google/api/http.d.ts.map +0 -1
- package/bin/genproto/google/api/launch_stage.d.ts +0 -78
- package/bin/genproto/google/api/launch_stage.d.ts.map +0 -1
- package/bin/genproto/google/protobuf/descriptor.d.ts +0 -2337
- package/bin/genproto/google/protobuf/descriptor.d.ts.map +0 -1
- package/bin/genproto/google/protobuf/duration.d.ts +0 -113
- package/bin/genproto/google/protobuf/duration.d.ts.map +0 -1
- package/bin/genproto/google/protobuf/struct.d.ts +0 -185
- package/bin/genproto/google/protobuf/struct.d.ts.map +0 -1
- package/bin/genproto/google/protobuf/timestamp.d.ts +0 -156
- package/bin/genproto/google/protobuf/timestamp.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/exchange.d.ts +0 -50
- package/bin/genproto/mochabugapis/adapt/graph/exchange.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/jtd_schema.d.ts +0 -129
- package/bin/genproto/mochabugapis/adapt/graph/jtd_schema.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/receiver.d.ts +0 -46
- package/bin/genproto/mochabugapis/adapt/graph/receiver.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/signal_binding.d.ts +0 -93
- package/bin/genproto/mochabugapis/adapt/graph/signal_binding.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/signal_descriptor.d.ts +0 -56
- package/bin/genproto/mochabugapis/adapt/graph/signal_descriptor.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/transceiver.d.ts +0 -44
- package/bin/genproto/mochabugapis/adapt/graph/transceiver.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/transmitter.d.ts +0 -50
- package/bin/genproto/mochabugapis/adapt/graph/transmitter.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/graph/vertex_config.d.ts +0 -68
- package/bin/genproto/mochabugapis/adapt/graph/vertex_config.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/plugins/v1/plugins.client.d.ts +0 -46
- package/bin/genproto/mochabugapis/adapt/plugins/v1/plugins.client.d.ts.map +0 -1
- package/bin/genproto/mochabugapis/adapt/plugins/v1/plugins.d.ts +0 -840
- package/bin/genproto/mochabugapis/adapt/plugins/v1/plugins.d.ts.map +0 -1
- package/bin/index.d.ts +0 -2
- package/bin/index.d.ts.map +0 -1
- package/bin/init.d.ts +0 -2
- package/bin/init.d.ts.map +0 -1
- package/bin/oauth2.d.ts +0 -2
- package/bin/oauth2.d.ts.map +0 -1
- package/bin/publish.d.ts +0 -4
- package/bin/publish.d.ts.map +0 -1
- package/bin/utils.d.ts +0 -6
- package/bin/utils.d.ts.map +0 -1
- package/bin/vertices.d.ts +0 -3
- package/bin/vertices.d.ts.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { build } from 'esbuild';
|
|
2
|
+
import { sync as glob } from 'glob';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
if (!process.env.PLUGINS_CDN) {
|
|
7
|
+
console.error('PLUGINS_CDN is required');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Load the manifest.json file and read organization, name and version of the plugin
|
|
12
|
+
const manifest = JSON.parse(fs.readFileSync('./manifest.json', 'utf8'));
|
|
13
|
+
if (!manifest.organization || !manifest.name || !manifest.version) {
|
|
14
|
+
throw new Error('Manifest file is missing organization, name or version');
|
|
15
|
+
}
|
|
16
|
+
const CDN_PATH = `${process.env.PLUGINS_CDN}/${manifest.organization}/${manifest.name}/${manifest.version}`;
|
|
17
|
+
|
|
18
|
+
fs.rmSync('./cdn', { recursive: true });
|
|
19
|
+
|
|
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'),
|
|
35
|
+
outdir: 'cdn',
|
|
36
|
+
bundle: true,
|
|
37
|
+
minify: true,
|
|
38
|
+
platform: 'browser',
|
|
39
|
+
splitting: true,
|
|
40
|
+
tsconfig: 'tsconfig.json',
|
|
41
|
+
format: 'esm',
|
|
42
|
+
metafile: true,
|
|
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',
|
|
86
|
+
},
|
|
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
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { cloudflare } from "@cloudflare/unenv-preset";
|
|
2
|
+
import { build } from 'esbuild';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { defineEnv } from 'unenv';
|
|
5
|
+
|
|
6
|
+
if (!process.env.PLUGINS_CDN) {
|
|
7
|
+
console.error('PLUGINS_CDN is required');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Load the manifest.json file and read organization, name and version of the plugin
|
|
12
|
+
const manifest = JSON.parse(fs.readFileSync('./manifest.json', 'utf8'));
|
|
13
|
+
if (!manifest.organization || !manifest.name || !manifest.version) {
|
|
14
|
+
throw new Error('Manifest file is missing organization, name or version');
|
|
15
|
+
}
|
|
16
|
+
const CDN_PATH = `${process.env.PLUGINS_CDN}/${manifest.organization}/${manifest.name}/${manifest.version}`;
|
|
17
|
+
|
|
18
|
+
const { env } = defineEnv({ nodeCompat: true, presets: [cloudflare] });
|
|
19
|
+
|
|
20
|
+
const entryPoints = ['./src/executors']
|
|
21
|
+
if (fs.existsSync('./src/configurators.ts')) {
|
|
22
|
+
entryPoints.push('./src/configurators')
|
|
23
|
+
}
|
|
24
|
+
|
|
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({
|
|
39
|
+
entryPoints,
|
|
40
|
+
outdir: 'dist',
|
|
41
|
+
bundle: true,
|
|
42
|
+
minify: true,
|
|
43
|
+
treeShaking: true,
|
|
44
|
+
sourcemap: false,
|
|
45
|
+
splitting: false,
|
|
46
|
+
format: 'esm',
|
|
47
|
+
platform: 'node',
|
|
48
|
+
target: 'esnext',
|
|
49
|
+
tsconfig: 'tsconfig.json',
|
|
50
|
+
inject: ['./inject.js'],
|
|
51
|
+
mainFields: ["module", "main"],
|
|
52
|
+
conditions: ["workerd"],
|
|
53
|
+
external: env.external,
|
|
54
|
+
alias: env.alias,
|
|
55
|
+
publicPath: CDN_PATH,
|
|
56
|
+
define,
|
|
57
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React, { useState, type CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
function App() {
|
|
4
|
+
const [config, setConfig] = useState<Record<string, unknown> | null>(null);
|
|
5
|
+
const [error, setError] = useState<string | null>(null);
|
|
6
|
+
const [isHovering, setIsHovering] = useState(false);
|
|
7
|
+
|
|
8
|
+
async function handleFetchConfig() {
|
|
9
|
+
setError(null);
|
|
10
|
+
try {
|
|
11
|
+
const hash = window.location.hash.substring(1).trim();
|
|
12
|
+
const token = decodeURIComponent(hash);
|
|
13
|
+
const response = await fetch('/api/config', {
|
|
14
|
+
headers: {
|
|
15
|
+
Authorization: `Bearer ${token}`,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(`Request failed with status ${response.status}`);
|
|
20
|
+
}
|
|
21
|
+
const data = (await response.json()) as Record<string, unknown>;
|
|
22
|
+
setConfig(data);
|
|
23
|
+
} catch (err: unknown) {
|
|
24
|
+
if (err instanceof Error) {
|
|
25
|
+
setError(err.message);
|
|
26
|
+
} else {
|
|
27
|
+
setError('An unknown error occurred.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Black & yellow theme
|
|
33
|
+
const containerStyle: CSSProperties = {
|
|
34
|
+
display: 'flex',
|
|
35
|
+
flexDirection: 'column',
|
|
36
|
+
justifyContent: 'center',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
height: '100vh',
|
|
39
|
+
margin: 0,
|
|
40
|
+
background: 'linear-gradient(to bottom, #000000, #1c1c1c)',
|
|
41
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
42
|
+
color: '#ffd700',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const cardStyle: CSSProperties = {
|
|
46
|
+
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
47
|
+
padding: '2rem',
|
|
48
|
+
borderRadius: '8px',
|
|
49
|
+
textAlign: 'center',
|
|
50
|
+
boxShadow: '0 4px 20px rgba(0, 0, 0, 0.7)',
|
|
51
|
+
maxWidth: '600px',
|
|
52
|
+
width: '90%',
|
|
53
|
+
border: '2px solid #ffd700',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const headingStyle: CSSProperties = {
|
|
57
|
+
marginBottom: '1rem',
|
|
58
|
+
textShadow: '0 0 6px rgba(255, 215, 0, 0.5)',
|
|
59
|
+
fontSize: '2rem',
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const buttonStyle: CSSProperties = {
|
|
63
|
+
cursor: 'pointer',
|
|
64
|
+
marginTop: '1rem',
|
|
65
|
+
padding: '0.75rem 1.5rem',
|
|
66
|
+
fontSize: '1rem',
|
|
67
|
+
borderRadius: '4px',
|
|
68
|
+
border: '2px solid #ffd700',
|
|
69
|
+
backgroundColor: '#000',
|
|
70
|
+
color: '#ffd700',
|
|
71
|
+
transition: 'transform 0.3s, box-shadow 0.3s',
|
|
72
|
+
outline: 'none',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const buttonHoverStyle: CSSProperties = {
|
|
76
|
+
...buttonStyle,
|
|
77
|
+
transform: 'scale(1.05)',
|
|
78
|
+
boxShadow: '0 4px 10px rgba(255, 215, 0, 0.4)',
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<div style={containerStyle}>
|
|
83
|
+
<h1 style={headingStyle}>Spectacular Mochabug Placeholder</h1>
|
|
84
|
+
<div style={cardStyle}>
|
|
85
|
+
<p style={{ marginBottom: '1rem' }}>
|
|
86
|
+
Click the button below to fetch configuration data!
|
|
87
|
+
</p>
|
|
88
|
+
<button
|
|
89
|
+
style={isHovering ? buttonHoverStyle : buttonStyle}
|
|
90
|
+
onMouseEnter={() => setIsHovering(true)}
|
|
91
|
+
onMouseLeave={() => setIsHovering(false)}
|
|
92
|
+
onClick={handleFetchConfig}
|
|
93
|
+
>
|
|
94
|
+
Fetch Config
|
|
95
|
+
</button>
|
|
96
|
+
|
|
97
|
+
{error && (
|
|
98
|
+
<p style={{ color: '#ff4c4c', marginTop: '1rem' }}>
|
|
99
|
+
{error}
|
|
100
|
+
</p>
|
|
101
|
+
)}
|
|
102
|
+
{config && (
|
|
103
|
+
<pre
|
|
104
|
+
style={{
|
|
105
|
+
textAlign: 'left',
|
|
106
|
+
backgroundColor: 'rgba(255, 215, 0, 0.1)',
|
|
107
|
+
color: '#ffd700',
|
|
108
|
+
padding: '1rem',
|
|
109
|
+
borderRadius: '4px',
|
|
110
|
+
marginTop: '1rem',
|
|
111
|
+
overflowX: 'auto',
|
|
112
|
+
border: '1px solid #ffd700',
|
|
113
|
+
}}
|
|
114
|
+
>
|
|
115
|
+
{JSON.stringify(config, null, 2)}
|
|
116
|
+
</pre>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export default App;
|
|
@@ -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
|
+
}
|
|
@@ -106,7 +106,7 @@ const helloWorldPage = `
|
|
|
106
106
|
<pre id="jsonOutput"></pre>
|
|
107
107
|
<script>
|
|
108
108
|
document.getElementById('assimilateButton').addEventListener('click', function() {
|
|
109
|
-
const hash = window.location.hash.
|
|
109
|
+
const hash = window.location.hash.substring(1).trim();
|
|
110
110
|
const token = decodeURIComponent(hash);
|
|
111
111
|
fetch('/api/config', {
|
|
112
112
|
method: 'GET',
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mapErrorToHttpError,
|
|
3
|
+
RpcError
|
|
4
|
+
} from '@mochabug/adapt-plugin-toolkit/api';
|
|
5
|
+
import {
|
|
6
|
+
ExternalConfiguratorRouter,
|
|
7
|
+
InternalConfiguratorRouter
|
|
8
|
+
} from '@mochabug/adapt-plugin-toolkit/router';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
external: new ExternalConfiguratorRouter()
|
|
12
|
+
.useRequestLogging()
|
|
13
|
+
.useBearerAuthorization(['/api'])
|
|
14
|
+
.useErrorHandling(async (e) => {
|
|
15
|
+
console.error(e);
|
|
16
|
+
if (e instanceof RpcError) {
|
|
17
|
+
return new Response(null, { status: mapErrorToHttpError(e.code) });
|
|
18
|
+
}
|
|
19
|
+
return new Response(null, {
|
|
20
|
+
status: 500,
|
|
21
|
+
statusText: 'Internal server error'
|
|
22
|
+
});
|
|
23
|
+
})
|
|
24
|
+
.add('GET', '/api/config', async (_req, api) => {
|
|
25
|
+
const res = await api.getVertexConfig();
|
|
26
|
+
return new Response(JSON.stringify(res.metadata), {
|
|
27
|
+
headers: {
|
|
28
|
+
'Content-Type': 'application/json'
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
})
|
|
32
|
+
.add('GET', '{*any}', async () => {
|
|
33
|
+
return new Response(CONFIGURATOR_INDEX_HTML['___VERTEX_NAME___'], {
|
|
34
|
+
headers: { 'Content-Type': 'text/html' }
|
|
35
|
+
});
|
|
36
|
+
}),
|
|
37
|
+
internal: new InternalConfiguratorRouter()
|
|
38
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React, { useState, type CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
function App() {
|
|
4
|
+
const [error, setError] = useState<string | null>(null);
|
|
5
|
+
const [isHovering, setIsHovering] = useState(false);
|
|
6
|
+
|
|
7
|
+
async function handleFetchConfig() {
|
|
8
|
+
setError(null);
|
|
9
|
+
try {
|
|
10
|
+
const hash = window.location.hash.substring(1).trim();
|
|
11
|
+
const token = decodeURIComponent(hash);
|
|
12
|
+
const response = await fetch('/api/done', {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
Authorization: `Bearer ${token}`
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(`Request failed with status ${response.status}`);
|
|
20
|
+
}
|
|
21
|
+
} catch (err: unknown) {
|
|
22
|
+
if (err instanceof Error) {
|
|
23
|
+
setError(err.message);
|
|
24
|
+
} else {
|
|
25
|
+
setError('An unknown error occurred.');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Black & yellow theme
|
|
31
|
+
const containerStyle: CSSProperties = {
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'column',
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
height: '100vh',
|
|
37
|
+
margin: 0,
|
|
38
|
+
background: 'linear-gradient(to bottom, #000000, #1c1c1c)',
|
|
39
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
40
|
+
color: '#ffd700'
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const cardStyle: CSSProperties = {
|
|
44
|
+
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
45
|
+
padding: '2rem',
|
|
46
|
+
borderRadius: '8px',
|
|
47
|
+
textAlign: 'center',
|
|
48
|
+
boxShadow: '0 4px 20px rgba(0, 0, 0, 0.7)',
|
|
49
|
+
maxWidth: '600px',
|
|
50
|
+
width: '90%',
|
|
51
|
+
border: '2px solid #ffd700'
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const headingStyle: CSSProperties = {
|
|
55
|
+
marginBottom: '1rem',
|
|
56
|
+
textShadow: '0 0 6px rgba(255, 215, 0, 0.5)',
|
|
57
|
+
fontSize: '2rem'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const buttonStyle: CSSProperties = {
|
|
61
|
+
cursor: 'pointer',
|
|
62
|
+
marginTop: '1rem',
|
|
63
|
+
padding: '0.75rem 1.5rem',
|
|
64
|
+
fontSize: '1rem',
|
|
65
|
+
borderRadius: '4px',
|
|
66
|
+
border: '2px solid #ffd700',
|
|
67
|
+
backgroundColor: '#000',
|
|
68
|
+
color: '#ffd700',
|
|
69
|
+
transition: 'transform 0.3s, box-shadow 0.3s',
|
|
70
|
+
outline: 'none'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const buttonHoverStyle: CSSProperties = {
|
|
74
|
+
...buttonStyle,
|
|
75
|
+
transform: 'scale(1.05)',
|
|
76
|
+
boxShadow: '0 4px 10px rgba(255, 215, 0, 0.4)'
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<div style={containerStyle}>
|
|
81
|
+
<h1 style={headingStyle}>Spectacular Mochabug Placeholder</h1>
|
|
82
|
+
<div style={cardStyle}>
|
|
83
|
+
<p style={{ marginBottom: '1rem' }}>
|
|
84
|
+
Click below to finalize execution
|
|
85
|
+
</p>
|
|
86
|
+
<button
|
|
87
|
+
style={isHovering ? buttonHoverStyle : buttonStyle}
|
|
88
|
+
onMouseEnter={() => setIsHovering(true)}
|
|
89
|
+
onMouseLeave={() => setIsHovering(false)}
|
|
90
|
+
onClick={handleFetchConfig}
|
|
91
|
+
>
|
|
92
|
+
Done
|
|
93
|
+
</button>
|
|
94
|
+
|
|
95
|
+
{error && (
|
|
96
|
+
<p style={{ color: '#ff4c4c', marginTop: '1rem' }}>{error}</p>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default App;
|
|
@@ -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
|
+
}
|
|
@@ -97,7 +97,7 @@ const helloWorld = `
|
|
|
97
97
|
<button id="doneButton">Done</button>
|
|
98
98
|
<script>
|
|
99
99
|
document.getElementById('doneButton').addEventListener('click', function() {
|
|
100
|
-
const hash = window.location.hash.
|
|
100
|
+
const hash = window.location.hash.substring(1).trim();
|
|
101
101
|
const token = decodeURIComponent(hash);
|
|
102
102
|
fetch('/api/done', {
|
|
103
103
|
method: 'POST',
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mapErrorToHttpError,
|
|
3
|
+
RpcError
|
|
4
|
+
} from '@mochabug/adapt-plugin-toolkit/api';
|
|
5
|
+
import {
|
|
6
|
+
ExternalExecutorRouter,
|
|
7
|
+
InternalExecutorRouter
|
|
8
|
+
} from '@mochabug/adapt-plugin-toolkit/router';
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
external: new ExternalExecutorRouter()
|
|
12
|
+
.useRequestLogging()
|
|
13
|
+
.useBearerAuthorization(['/api'])
|
|
14
|
+
.useErrorHandling(async (e) => {
|
|
15
|
+
console.error(e);
|
|
16
|
+
if (e instanceof RpcError) {
|
|
17
|
+
return new Response(null, { status: mapErrorToHttpError(e.code) });
|
|
18
|
+
}
|
|
19
|
+
return new Response(null, {
|
|
20
|
+
status: 500,
|
|
21
|
+
statusText: 'Internal server error'
|
|
22
|
+
});
|
|
23
|
+
})
|
|
24
|
+
.add('POST', '/api/done', async (req, api, _route, ctx) => {
|
|
25
|
+
const sapi = api.getSessionApi(req.headers.get('Authorization')!);
|
|
26
|
+
ctx.waitUntil(sapi.complete('output', {}));
|
|
27
|
+
return new Response();
|
|
28
|
+
})
|
|
29
|
+
.add('GET', '{*any}', async () => {
|
|
30
|
+
return new Response(EXECUTOR_INDEX_HTML['___VERTEX_NAME___'], {
|
|
31
|
+
headers: { 'Content-Type': 'text/html' }
|
|
32
|
+
});
|
|
33
|
+
}),
|
|
34
|
+
internal: new InternalExecutorRouter()
|
|
35
|
+
.onStart(async (start, _api) => {
|
|
36
|
+
console.log('Start has been called');
|
|
37
|
+
console.log(start);
|
|
38
|
+
})
|
|
39
|
+
.onStop(async (stop, _api) => {
|
|
40
|
+
console.log('Stop has been called');
|
|
41
|
+
console.log(stop);
|
|
42
|
+
})
|
|
43
|
+
.onStream(async (res, _api, name) => {
|
|
44
|
+
console.log(`Stream ${name} has been called`);
|
|
45
|
+
console.log(res);
|
|
46
|
+
})
|
|
47
|
+
.onProcedure(async (res, _api, name) => {
|
|
48
|
+
console.log(`Procedure ${name} has been called`);
|
|
49
|
+
console.log(res);
|
|
50
|
+
})
|
|
51
|
+
};
|
package/assets/gitignore
CHANGED
package/assets/inject.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import 'unenv/runtime/polyfill/node-global'
|
|
2
|
+
import 'unenv/runtime/polyfill/process'
|
|
3
|
+
import 'unenv/runtime/polyfill/performance'
|
|
4
|
+
import processModule from '@cloudflare/unenv-preset/runtime/node/process/index'
|
|
5
|
+
if (typeof globalThis.process === 'undefined') {
|
|
6
|
+
globalThis.process = processModule
|
|
7
|
+
}
|
|
8
|
+
import consoleModule from '@cloudflare/unenv-preset/runtime/node/console/index'
|
|
9
|
+
if (typeof globalThis.console === 'undefined') {
|
|
10
|
+
globalThis.console = consoleModule
|
|
11
|
+
}
|
|
12
|
+
import perfModule from 'unenv/runtime/polyfill/performance'
|
|
13
|
+
if (typeof globalThis.performance === 'undefined') {
|
|
14
|
+
globalThis.performance = perfModule
|
|
15
|
+
}
|
package/assets/tsconf.json
CHANGED
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
"target": "esnext",
|
|
6
6
|
"module": "esnext",
|
|
7
7
|
"lib": [
|
|
8
|
-
"esnext"
|
|
8
|
+
"esnext",
|
|
9
|
+
"dom"
|
|
9
10
|
],
|
|
10
11
|
"moduleResolution": "Bundler",
|
|
11
12
|
"types": [
|
|
13
|
+
"node",
|
|
12
14
|
"@mochabug/adapt-plugin-typings"
|
|
13
15
|
],
|
|
14
16
|
"resolveJsonModule": true,
|
|
15
17
|
"allowJs": true,
|
|
16
18
|
"checkJs": false,
|
|
17
19
|
"noEmit": true,
|
|
20
|
+
"esModuleInterop": true,
|
|
18
21
|
"isolatedModules": true,
|
|
19
22
|
"allowSyntheticDefaultImports": true,
|
|
20
23
|
"forceConsistentCasingInFileNames": true,
|
|
@@ -30,7 +33,10 @@
|
|
|
30
33
|
},
|
|
31
34
|
"exclude": [
|
|
32
35
|
"dist/**",
|
|
36
|
+
"cdn/**",
|
|
33
37
|
"assets/**",
|
|
34
|
-
"
|
|
35
|
-
|
|
38
|
+
"build.js",
|
|
39
|
+
"inject.js",
|
|
40
|
+
"build-client.js"
|
|
41
|
+
],
|
|
36
42
|
}
|