@rozenite/vite-plugin 1.12.0 → 2.0.0
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 +12 -0
- package/dist/bundle-dts.d.ts.map +1 -1
- package/dist/client-plugin.d.ts.map +1 -1
- package/dist/dev-config-module.d.ts.map +1 -1
- package/dist/dev-host/assets/index-DU3zXL2c.css +1 -0
- package/dist/dev-host/assets/index-Xsb6uYhI.js +13 -0
- package/dist/dev-host/index.html +3 -3
- package/dist/dev-host/manifest.json +2 -2
- package/dist/index.cjs +24 -8
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/react-native-plugin.d.ts.map +1 -1
- package/dist/sdk-plugin.d.ts.map +1 -1
- package/dist/server-plugin.d.ts.map +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/bundle-dts.ts +126 -0
- package/src/client-plugin.ts +394 -0
- package/src/dev-config-module.ts +32 -0
- package/src/dev-host/App.tsx +373 -0
- package/src/dev-host/components/DispatchForm.tsx +155 -0
- package/src/dev-host/components/FlowList.tsx +122 -0
- package/src/dev-host/components/MessageDetailsPane.tsx +82 -0
- package/src/dev-host/components/MessageLogPane.tsx +102 -0
- package/src/dev-host/components/PanelTabs.tsx +41 -0
- package/src/dev-host/config.ts +111 -0
- package/src/dev-host/constants.ts +12 -0
- package/src/dev-host/flow-runtime.ts +318 -0
- package/src/dev-host/index.html +12 -0
- package/src/dev-host/main.tsx +22 -0
- package/src/dev-host/server.ts +61 -0
- package/src/dev-host/styles.css +301 -0
- package/src/dev-host/types.ts +56 -0
- package/src/dev-host/utils.ts +99 -0
- package/src/dev-host/vite.config.mts +22 -0
- package/src/index.ts +124 -0
- package/src/load-config.ts +117 -0
- package/src/package-json.ts +16 -0
- package/src/react-native-plugin.ts +52 -0
- package/src/require-plugin.ts +221 -0
- package/src/sdk-plugin.ts +47 -0
- package/src/server-plugin.ts +39 -0
- package/src/utils.ts +31 -0
- package/src/virtual-modules.d.ts +7 -0
- package/dist/dev-host/assets/index-CkxvBMpp.css +0 -1
- package/dist/dev-host/assets/index-cNKHRwej.js +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rozenite/vite-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Vite plugin for developing React Native DevTools plugins with hot reload and development tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
+
"src",
|
|
11
12
|
"templates"
|
|
12
13
|
],
|
|
13
14
|
"keywords": [
|
|
@@ -40,10 +41,13 @@
|
|
|
40
41
|
},
|
|
41
42
|
"dependencies": {
|
|
42
43
|
"@microsoft/api-extractor": "^7.50.1",
|
|
44
|
+
"@tailwindcss/vite": "4.2.2",
|
|
43
45
|
"@vitejs/plugin-react": "^4.3.4",
|
|
44
46
|
"ejs": "^3.1.9",
|
|
45
47
|
"vite-plugin-dts": "~4.5.0",
|
|
46
|
-
"vite-plugin-react-native-web": "^2.1.1"
|
|
48
|
+
"vite-plugin-react-native-web": "^2.1.1",
|
|
49
|
+
"lucide-react": "^0.263.1",
|
|
50
|
+
"@rozenite/ui": "2.0.0"
|
|
47
51
|
},
|
|
48
52
|
"peerDependencies": {
|
|
49
53
|
"react": "*",
|
|
@@ -52,14 +56,10 @@
|
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
54
58
|
"@types/ejs": "^3.1.5",
|
|
55
|
-
"@types/react": "~19.2.
|
|
56
|
-
"@types/react-dom": "~19.
|
|
57
|
-
"
|
|
58
|
-
"react-
|
|
59
|
-
"react": "19.2.0",
|
|
60
|
-
"react-dom": "19.2.0",
|
|
61
|
-
"styletron-engine-monolithic": "^1.0.0",
|
|
62
|
-
"styletron-react": "^6.1.1"
|
|
59
|
+
"@types/react": "~19.2.3",
|
|
60
|
+
"@types/react-dom": "~19.2.3",
|
|
61
|
+
"react": "19.2.3",
|
|
62
|
+
"react-dom": "19.2.3"
|
|
63
63
|
},
|
|
64
64
|
"engines": {
|
|
65
65
|
"node": ">=20"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
Extractor,
|
|
5
|
+
ExtractorConfig,
|
|
6
|
+
ExtractorLogLevel,
|
|
7
|
+
} from '@microsoft/api-extractor';
|
|
8
|
+
|
|
9
|
+
type Target = 'react-native' | 'metro' | 'sdk';
|
|
10
|
+
|
|
11
|
+
export const normalizeRolledUpDeclarations = (content: string) => {
|
|
12
|
+
const valueDeclarationNames = new Set<string>();
|
|
13
|
+
|
|
14
|
+
content.replace(
|
|
15
|
+
/^\s*declare\s+(?:const|let|var|function)\s+([A-Za-z_$][\w$]*)\b/gm,
|
|
16
|
+
(_, name: string) => {
|
|
17
|
+
valueDeclarationNames.add(name);
|
|
18
|
+
return _;
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const normalizeTypeReference = (name: string) =>
|
|
23
|
+
valueDeclarationNames.has(name) ? `typeof ${name}` : name;
|
|
24
|
+
|
|
25
|
+
return content
|
|
26
|
+
.replace(
|
|
27
|
+
/^(\s*(?:export\s+)?declare\s+(?:const|let|var)\s+[A-Za-z_$][\w$]*\s*:\s*)([A-Za-z_$][\w$]*)(\s*;)$/gm,
|
|
28
|
+
(_, prefix: string, name: string, suffix: string) => {
|
|
29
|
+
return `${prefix}${normalizeTypeReference(name)}${suffix}`;
|
|
30
|
+
},
|
|
31
|
+
)
|
|
32
|
+
.replace(
|
|
33
|
+
/^(\s*(?:export\s+)?declare\s+type\s+[A-Za-z_$][\w$]*\s*=\s*)([A-Za-z_$][\w$]*)(\s*;)$/gm,
|
|
34
|
+
(_, prefix: string, name: string, suffix: string) => {
|
|
35
|
+
return `${prefix}${normalizeTypeReference(name)}${suffix}`;
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const bundleTargetDeclarations = async (
|
|
41
|
+
projectRoot: string,
|
|
42
|
+
target: Target,
|
|
43
|
+
) => {
|
|
44
|
+
const targetRoot = path.join(projectRoot, 'dist', target);
|
|
45
|
+
const publicEntryPath = path.join(targetRoot, 'index.d.ts');
|
|
46
|
+
const bundleEntryPath =
|
|
47
|
+
target === 'sdk'
|
|
48
|
+
? path.join(targetRoot, `${target}.d.ts`)
|
|
49
|
+
: publicEntryPath;
|
|
50
|
+
const entryPath = await fs
|
|
51
|
+
.access(bundleEntryPath)
|
|
52
|
+
.then(() => bundleEntryPath)
|
|
53
|
+
.catch(() => publicEntryPath);
|
|
54
|
+
const tempOutputPath = path.join(targetRoot, 'index.public.d.ts');
|
|
55
|
+
const srcDeclarationsPath = path.join(targetRoot, 'src');
|
|
56
|
+
const configObjectFullPath = path.join(projectRoot, 'api-extractor.json');
|
|
57
|
+
const packageJsonFullPath = path.join(projectRoot, 'package.json');
|
|
58
|
+
const tsconfigFilePath = path.join(projectRoot, 'tsconfig.json');
|
|
59
|
+
|
|
60
|
+
const extractorConfig = ExtractorConfig.prepare({
|
|
61
|
+
configObject: {
|
|
62
|
+
projectFolder: projectRoot,
|
|
63
|
+
mainEntryPointFilePath: entryPath,
|
|
64
|
+
compiler: {
|
|
65
|
+
tsconfigFilePath,
|
|
66
|
+
overrideTsconfig: {
|
|
67
|
+
$schema: 'http://json.schemastore.org/tsconfig',
|
|
68
|
+
compilerOptions: {
|
|
69
|
+
skipLibCheck: true,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
apiReport: {
|
|
74
|
+
enabled: false,
|
|
75
|
+
},
|
|
76
|
+
docModel: {
|
|
77
|
+
enabled: false,
|
|
78
|
+
},
|
|
79
|
+
dtsRollup: {
|
|
80
|
+
enabled: true,
|
|
81
|
+
publicTrimmedFilePath: tempOutputPath,
|
|
82
|
+
},
|
|
83
|
+
tsdocMetadata: {
|
|
84
|
+
enabled: false,
|
|
85
|
+
},
|
|
86
|
+
messages: {
|
|
87
|
+
compilerMessageReporting: {
|
|
88
|
+
default: {
|
|
89
|
+
logLevel: ExtractorLogLevel.None,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
extractorMessageReporting: {
|
|
93
|
+
default: {
|
|
94
|
+
logLevel: ExtractorLogLevel.None,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
configObjectFullPath,
|
|
100
|
+
packageJsonFullPath,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const result = Extractor.invoke(extractorConfig, {
|
|
104
|
+
localBuild: true,
|
|
105
|
+
showVerboseMessages: false,
|
|
106
|
+
showDiagnostics: false,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (!result.succeeded) {
|
|
110
|
+
throw new Error(`Failed to bundle ${target} declaration files.`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (entryPath !== publicEntryPath) {
|
|
114
|
+
await fs.rm(publicEntryPath, { force: true });
|
|
115
|
+
}
|
|
116
|
+
await fs.rm(entryPath, { force: true });
|
|
117
|
+
await fs.rename(tempOutputPath, publicEntryPath);
|
|
118
|
+
const bundledContent = await fs.readFile(publicEntryPath, 'utf8');
|
|
119
|
+
const normalizedContent = normalizeRolledUpDeclarations(bundledContent);
|
|
120
|
+
|
|
121
|
+
if (normalizedContent !== bundledContent) {
|
|
122
|
+
await fs.writeFile(publicEntryPath, normalizedContent);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await fs.rm(srcDeclarationsPath, { recursive: true, force: true });
|
|
126
|
+
};
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import type { Plugin, ViteDevServer } from 'vite';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import ejs from 'ejs';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { normalizePath } from 'vite';
|
|
8
|
+
import { loadConfig, RozeniteConfig } from './load-config.js';
|
|
9
|
+
import { getPackageJSON } from './package-json.js';
|
|
10
|
+
import {
|
|
11
|
+
DEV_HOST_CONFIG_GLOBAL_KEY,
|
|
12
|
+
DEV_HOST_STATE_ELEMENT_ID,
|
|
13
|
+
} from './dev-host/constants.js';
|
|
14
|
+
import {
|
|
15
|
+
getBuiltDevHostAssets,
|
|
16
|
+
getDevHostHtmlTemplate,
|
|
17
|
+
getDevHostSourceEntryFile,
|
|
18
|
+
} from './dev-host/server.js';
|
|
19
|
+
import {
|
|
20
|
+
ROZENITE_DEV_CONFIG_MODULE_ID,
|
|
21
|
+
getRozeniteConfigPath,
|
|
22
|
+
loadRozeniteDevConfigModule,
|
|
23
|
+
resolveRozeniteDevConfigModuleId,
|
|
24
|
+
} from './dev-config-module.js';
|
|
25
|
+
|
|
26
|
+
type PanelEntry = {
|
|
27
|
+
name: string;
|
|
28
|
+
label: string;
|
|
29
|
+
sourceFile: string;
|
|
30
|
+
htmlFile: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type ManifestPanelEntry = {
|
|
34
|
+
name: string;
|
|
35
|
+
source: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type DevHostPanelEntry = {
|
|
39
|
+
label: string;
|
|
40
|
+
source: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type DevHostState = {
|
|
44
|
+
packageName: string;
|
|
45
|
+
packageDescription: string;
|
|
46
|
+
panels: DevHostPanelEntry[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const TEMPLATES_DIR = path.resolve(
|
|
50
|
+
fileURLToPath(import.meta.url),
|
|
51
|
+
'..',
|
|
52
|
+
'..',
|
|
53
|
+
'templates',
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const PACKAGE_DIR = path.resolve(fileURLToPath(import.meta.url), '..', '..');
|
|
57
|
+
|
|
58
|
+
const DEV_HOST_SOURCE_ENTRY_FILE = getDevHostSourceEntryFile(PACKAGE_DIR);
|
|
59
|
+
|
|
60
|
+
const PANELS_DIR = './panels';
|
|
61
|
+
const DEVTOOLS_DIR = 'devtools';
|
|
62
|
+
const DEV_HOST_ROUTE = '/';
|
|
63
|
+
|
|
64
|
+
export const rozeniteClientPlugin = (): Plugin => {
|
|
65
|
+
let projectRoot = process.cwd();
|
|
66
|
+
let viteServer: ViteDevServer | null = null;
|
|
67
|
+
let rozeniteConfig: RozeniteConfig | null = null;
|
|
68
|
+
|
|
69
|
+
const getRozeniteConfig = (): RozeniteConfig => {
|
|
70
|
+
if (!rozeniteConfig) {
|
|
71
|
+
throw new Error('rozenite.config.ts not found');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return rozeniteConfig;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const getPanels = (): PanelEntry[] => {
|
|
78
|
+
return getRozeniteConfig().panels.map((entry) => {
|
|
79
|
+
const name = path.basename(entry.source, path.extname(entry.source));
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
name,
|
|
83
|
+
label: entry.name,
|
|
84
|
+
sourceFile: path.resolve(projectRoot, entry.source),
|
|
85
|
+
htmlFile: `${name}.html`,
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const PANEL_TEMPLATE = path.join(TEMPLATES_DIR, 'panel.ejs');
|
|
91
|
+
|
|
92
|
+
const getManifestPanels = (): ManifestPanelEntry[] => {
|
|
93
|
+
return getPanels().map((panel) => ({
|
|
94
|
+
name: panel.label,
|
|
95
|
+
source: `/${DEVTOOLS_DIR}/` + panel.htmlFile,
|
|
96
|
+
}));
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const getDevHostPanels = (): DevHostPanelEntry[] => {
|
|
100
|
+
return getPanels().map((panel) => ({
|
|
101
|
+
label: panel.label,
|
|
102
|
+
source: `/${DEVTOOLS_DIR}/` + panel.htmlFile,
|
|
103
|
+
}));
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const generatePanelHtmlContent = (panel: PanelEntry): string => {
|
|
107
|
+
const template = fs.readFileSync(PANEL_TEMPLATE, 'utf-8');
|
|
108
|
+
const relativePath = path.relative(projectRoot, panel.sourceFile);
|
|
109
|
+
return ejs.render(template, {
|
|
110
|
+
panelName: panel.name,
|
|
111
|
+
panelFile: relativePath,
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const getDevHostState = async (): Promise<DevHostState> => {
|
|
116
|
+
const packageJSON = await getPackageJSON(projectRoot);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
packageName: packageJSON.name,
|
|
120
|
+
packageDescription: packageJSON.description,
|
|
121
|
+
panels: getDevHostPanels(),
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const serializeDevHostState = (state: DevHostState): string => {
|
|
126
|
+
return JSON.stringify(state).replace(/</g, '\\u003c');
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const toFsUrl = (filePath: string) => {
|
|
130
|
+
return `/@fs${normalizePath(filePath)}`;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const getDevHostAssetTags = () => {
|
|
134
|
+
const builtAssets = getBuiltDevHostAssets(PACKAGE_DIR);
|
|
135
|
+
|
|
136
|
+
if (!builtAssets) {
|
|
137
|
+
return [
|
|
138
|
+
{
|
|
139
|
+
tag: 'script',
|
|
140
|
+
attrs: {
|
|
141
|
+
type: 'module',
|
|
142
|
+
src: toFsUrl(DEV_HOST_SOURCE_ENTRY_FILE),
|
|
143
|
+
},
|
|
144
|
+
injectTo: 'body' as const,
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return [
|
|
150
|
+
...builtAssets.styles.map((stylePath) => ({
|
|
151
|
+
tag: 'link',
|
|
152
|
+
attrs: {
|
|
153
|
+
rel: 'stylesheet',
|
|
154
|
+
href: toFsUrl(stylePath),
|
|
155
|
+
},
|
|
156
|
+
injectTo: 'head' as const,
|
|
157
|
+
})),
|
|
158
|
+
{
|
|
159
|
+
tag: 'script',
|
|
160
|
+
attrs: {
|
|
161
|
+
type: 'module',
|
|
162
|
+
src: toFsUrl(builtAssets.script),
|
|
163
|
+
},
|
|
164
|
+
injectTo: 'body' as const,
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
name: 'rozenite-client-plugin',
|
|
171
|
+
async config(config) {
|
|
172
|
+
if (config.root) {
|
|
173
|
+
projectRoot = config.root;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
rozeniteConfig = await loadConfig(getRozeniteConfigPath(projectRoot));
|
|
177
|
+
const panels = getPanels();
|
|
178
|
+
|
|
179
|
+
config.server ??= {};
|
|
180
|
+
config.server.open =
|
|
181
|
+
config.server.open === true
|
|
182
|
+
? DEV_HOST_ROUTE
|
|
183
|
+
: (config.server.open ?? DEV_HOST_ROUTE);
|
|
184
|
+
// Keep in sync with `DEV_SERVER_URL` in packages/runtime/src/dev-mode.ts
|
|
185
|
+
config.server.port = 8888;
|
|
186
|
+
|
|
187
|
+
config.build ??= {};
|
|
188
|
+
if (process.env.ROZENITE_BUILD === '1') {
|
|
189
|
+
config.build.emptyOutDir = false;
|
|
190
|
+
}
|
|
191
|
+
config.build.rollupOptions ??= {};
|
|
192
|
+
config.build.rollupOptions.input = {
|
|
193
|
+
...(config.build.rollupOptions.input as Record<string, string>),
|
|
194
|
+
...Object.fromEntries(
|
|
195
|
+
panels.map((panel) => [
|
|
196
|
+
panel.name,
|
|
197
|
+
`${DEVTOOLS_DIR}/${panel.htmlFile}`,
|
|
198
|
+
]),
|
|
199
|
+
),
|
|
200
|
+
};
|
|
201
|
+
config.build.rollupOptions.output = {
|
|
202
|
+
assetFileNames: `${DEVTOOLS_DIR}/assets/[name]-[hash][extname]`,
|
|
203
|
+
chunkFileNames: `${DEVTOOLS_DIR}/assets/[name]-[hash].js`,
|
|
204
|
+
entryFileNames: `${DEVTOOLS_DIR}/assets/[name]-[hash].js`,
|
|
205
|
+
...(config.build.rollupOptions.output ?? {}),
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
resolveId(id) {
|
|
210
|
+
const devConfigModuleId = resolveRozeniteDevConfigModuleId(id);
|
|
211
|
+
|
|
212
|
+
if (devConfigModuleId) {
|
|
213
|
+
return devConfigModuleId;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const isPanel = getPanels().some(
|
|
217
|
+
(panel) => `${DEVTOOLS_DIR}/${panel.htmlFile}` === id,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
if (isPanel) {
|
|
221
|
+
return id;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return null;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
load(id) {
|
|
228
|
+
const devConfigModule = loadRozeniteDevConfigModule(id, projectRoot);
|
|
229
|
+
|
|
230
|
+
if (devConfigModule) {
|
|
231
|
+
return devConfigModule;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const panel = getPanels().find(
|
|
235
|
+
(panel) => `${DEVTOOLS_DIR}/${panel.htmlFile}` === id,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (panel) {
|
|
239
|
+
return generatePanelHtmlContent(panel);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return null;
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
async transformIndexHtml(_html, context) {
|
|
246
|
+
const pathname = context?.path ?? DEV_HOST_ROUTE;
|
|
247
|
+
|
|
248
|
+
if (pathname !== DEV_HOST_ROUTE) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const state = await getDevHostState();
|
|
253
|
+
|
|
254
|
+
return [
|
|
255
|
+
{
|
|
256
|
+
tag: 'script',
|
|
257
|
+
attrs: {
|
|
258
|
+
id: DEV_HOST_STATE_ELEMENT_ID,
|
|
259
|
+
type: 'application/json',
|
|
260
|
+
},
|
|
261
|
+
children: serializeDevHostState(state),
|
|
262
|
+
injectTo: 'body',
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
tag: 'script',
|
|
266
|
+
attrs: {
|
|
267
|
+
type: 'module',
|
|
268
|
+
},
|
|
269
|
+
children: `import rozeniteConfig from ${JSON.stringify('/@id/' + ROZENITE_DEV_CONFIG_MODULE_ID)}; window[${JSON.stringify(DEV_HOST_CONFIG_GLOBAL_KEY)}] = rozeniteConfig.dev ?? {};`,
|
|
270
|
+
injectTo: 'body',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
tag: 'meta',
|
|
274
|
+
attrs: {
|
|
275
|
+
name: 'rozenite-dev-host',
|
|
276
|
+
content: 'true',
|
|
277
|
+
},
|
|
278
|
+
injectTo: 'head',
|
|
279
|
+
},
|
|
280
|
+
...getDevHostAssetTags(),
|
|
281
|
+
];
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
async configureServer(server: ViteDevServer) {
|
|
285
|
+
viteServer = server;
|
|
286
|
+
const packageJSON = await getPackageJSON(projectRoot);
|
|
287
|
+
|
|
288
|
+
server.middlewares.use((req, res, next) => {
|
|
289
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
290
|
+
res.setHeader(
|
|
291
|
+
'Access-Control-Allow-Methods',
|
|
292
|
+
'GET, POST, PUT, DELETE, OPTIONS',
|
|
293
|
+
);
|
|
294
|
+
res.setHeader(
|
|
295
|
+
'Access-Control-Allow-Headers',
|
|
296
|
+
'Content-Type, Authorization',
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
if (req.method === 'OPTIONS') {
|
|
300
|
+
res.statusCode = 200;
|
|
301
|
+
res.end();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const panels = getPanels();
|
|
306
|
+
const requestUrl = req.url || '/';
|
|
307
|
+
const url = new URL(requestUrl, 'http://localhost').pathname;
|
|
308
|
+
|
|
309
|
+
if (url === DEV_HOST_ROUTE) {
|
|
310
|
+
server
|
|
311
|
+
.transformIndexHtml(requestUrl, getDevHostHtmlTemplate())
|
|
312
|
+
.then((html) => {
|
|
313
|
+
res.setHeader('Content-Type', 'text/html');
|
|
314
|
+
res.end(html);
|
|
315
|
+
})
|
|
316
|
+
.catch((err) => {
|
|
317
|
+
next(err);
|
|
318
|
+
});
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (url === '/rozenite.json') {
|
|
323
|
+
res.setHeader('Content-Type', 'application/json');
|
|
324
|
+
res.end(
|
|
325
|
+
JSON.stringify(
|
|
326
|
+
{
|
|
327
|
+
name: packageJSON.name,
|
|
328
|
+
version: packageJSON.version,
|
|
329
|
+
description: packageJSON.description,
|
|
330
|
+
panels: getManifestPanels(),
|
|
331
|
+
},
|
|
332
|
+
null,
|
|
333
|
+
2,
|
|
334
|
+
),
|
|
335
|
+
);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const panel = panels.find(
|
|
340
|
+
(panel) => `/${DEVTOOLS_DIR}/` + panel.htmlFile === url,
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
if (panel) {
|
|
344
|
+
const htmlContent = generatePanelHtmlContent(panel);
|
|
345
|
+
|
|
346
|
+
server
|
|
347
|
+
.transformIndexHtml(requestUrl, htmlContent)
|
|
348
|
+
.then((html) => {
|
|
349
|
+
res.setHeader('Content-Type', 'text/html');
|
|
350
|
+
res.end(html);
|
|
351
|
+
})
|
|
352
|
+
.catch((err) => {
|
|
353
|
+
next(err);
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
next();
|
|
359
|
+
});
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
watchChange(id, change) {
|
|
363
|
+
if (change.event !== 'create' && change.event !== 'delete') {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const relativePath = path.relative(projectRoot, id);
|
|
368
|
+
|
|
369
|
+
if (!relativePath.startsWith(PANELS_DIR)) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
viteServer?.ws.send({
|
|
374
|
+
type: 'full-reload',
|
|
375
|
+
path: '/',
|
|
376
|
+
});
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
async generateBundle() {
|
|
380
|
+
const packageJSON = await getPackageJSON(projectRoot);
|
|
381
|
+
|
|
382
|
+
this.emitFile({
|
|
383
|
+
type: 'asset',
|
|
384
|
+
fileName: 'rozenite.json',
|
|
385
|
+
source: JSON.stringify({
|
|
386
|
+
name: packageJSON.name,
|
|
387
|
+
version: packageJSON.version,
|
|
388
|
+
description: packageJSON.description,
|
|
389
|
+
panels: getManifestPanels(),
|
|
390
|
+
}),
|
|
391
|
+
});
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { normalizePath } from 'vite';
|
|
3
|
+
|
|
4
|
+
export const ROZENITE_CONFIG_FILE_NAME = 'rozenite.config.ts';
|
|
5
|
+
export const ROZENITE_DEV_CONFIG_MODULE_ID = 'virtual:rozenite-dev-config';
|
|
6
|
+
|
|
7
|
+
const RESOLVED_ROZENITE_DEV_CONFIG_MODULE_ID = `\0${ROZENITE_DEV_CONFIG_MODULE_ID}`;
|
|
8
|
+
|
|
9
|
+
export const getRozeniteConfigPath = (projectRoot: string) => {
|
|
10
|
+
return path.resolve(projectRoot, ROZENITE_CONFIG_FILE_NAME);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const resolveRozeniteDevConfigModuleId = (id: string) => {
|
|
14
|
+
if (id === ROZENITE_DEV_CONFIG_MODULE_ID) {
|
|
15
|
+
return RESOLVED_ROZENITE_DEV_CONFIG_MODULE_ID;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const loadRozeniteDevConfigModule = (
|
|
22
|
+
id: string,
|
|
23
|
+
projectRoot: string,
|
|
24
|
+
) => {
|
|
25
|
+
if (id !== RESOLVED_ROZENITE_DEV_CONFIG_MODULE_ID) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const configPath = normalizePath(getRozeniteConfigPath(projectRoot));
|
|
30
|
+
|
|
31
|
+
return `export { default } from ${JSON.stringify(`/@fs${configPath}`)};`;
|
|
32
|
+
};
|