@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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { transformWithEsbuild } from 'vite';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
|
|
5
|
+
export type PanelEntry = {
|
|
6
|
+
name: string;
|
|
7
|
+
source: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type DevPresetEntry = {
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
payload: unknown;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type DevFlowMessage = {
|
|
17
|
+
id: string;
|
|
18
|
+
direction: 'in' | 'out';
|
|
19
|
+
date: string;
|
|
20
|
+
type: string;
|
|
21
|
+
payload: unknown;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type DevFlowMessageMatcher =
|
|
25
|
+
| string
|
|
26
|
+
| ((message: DevFlowMessage) => boolean)
|
|
27
|
+
| {
|
|
28
|
+
type?: string;
|
|
29
|
+
direction?: DevFlowMessage['direction'];
|
|
30
|
+
predicate?: (message: DevFlowMessage) => boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type DevFlowSubscription = {
|
|
34
|
+
remove: () => void;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type DevFlowContext = {
|
|
38
|
+
signal: AbortSignal;
|
|
39
|
+
send: (type: string, payload: unknown) => void;
|
|
40
|
+
onMessage: (
|
|
41
|
+
matcher: DevFlowMessageMatcher,
|
|
42
|
+
listener: (message: DevFlowMessage) => void,
|
|
43
|
+
) => DevFlowSubscription;
|
|
44
|
+
waitForMessage: (
|
|
45
|
+
matcher: DevFlowMessageMatcher,
|
|
46
|
+
options?: {
|
|
47
|
+
timeoutMs?: number;
|
|
48
|
+
},
|
|
49
|
+
) => Promise<DevFlowMessage>;
|
|
50
|
+
getMessages: (matcher?: DevFlowMessageMatcher) => DevFlowMessage[];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type DevFlowEntry = {
|
|
54
|
+
name?: string;
|
|
55
|
+
autoRun?: boolean;
|
|
56
|
+
run: (context: DevFlowContext) => unknown | Promise<unknown>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type DevConfig = {
|
|
60
|
+
presets?: DevPresetEntry[];
|
|
61
|
+
flows?: DevFlowEntry[];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type RozeniteConfig = {
|
|
65
|
+
panels: PanelEntry[];
|
|
66
|
+
dev?: DevConfig;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const loadConfig = async (
|
|
70
|
+
configPath: string,
|
|
71
|
+
): Promise<RozeniteConfig> => {
|
|
72
|
+
const absoluteConfigPath = path.resolve(process.cwd(), configPath);
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(absoluteConfigPath)) {
|
|
75
|
+
throw new Error(`Configuration file not found: ${absoluteConfigPath}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const configContent = await fs.promises.readFile(
|
|
80
|
+
absoluteConfigPath,
|
|
81
|
+
'utf-8',
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const result = await transformWithEsbuild(
|
|
85
|
+
configContent,
|
|
86
|
+
absoluteConfigPath,
|
|
87
|
+
{
|
|
88
|
+
loader: 'ts',
|
|
89
|
+
format: 'cjs',
|
|
90
|
+
target: 'esnext',
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const moduleExports: { default?: unknown } = {};
|
|
95
|
+
const module = { exports: moduleExports };
|
|
96
|
+
const exports = moduleExports;
|
|
97
|
+
|
|
98
|
+
const moduleFunction = new Function('module', 'exports', result.code);
|
|
99
|
+
moduleFunction(module, exports);
|
|
100
|
+
|
|
101
|
+
const configModule = module.exports;
|
|
102
|
+
const config = configModule.default || configModule;
|
|
103
|
+
|
|
104
|
+
if (!config || typeof config !== 'object') {
|
|
105
|
+
throw new Error('Configuration must export an object');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return config as RozeniteConfig;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (error instanceof Error) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Failed to load configuration from ${configPath}: ${error.message}`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`Failed to load configuration from ${configPath}`);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
export type PackageJSON = {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
version: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const getPackageJSON = async (
|
|
11
|
+
projectRoot: string,
|
|
12
|
+
): Promise<PackageJSON> => {
|
|
13
|
+
const packageJSONPath = path.join(projectRoot, 'package.json');
|
|
14
|
+
const packageJSON = await fs.readFile(packageJSONPath, 'utf8');
|
|
15
|
+
return JSON.parse(packageJSON);
|
|
16
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const rozeniteReactNativePlugin = (): Plugin => {
|
|
5
|
+
return {
|
|
6
|
+
name: 'rozenite-react-native-plugin',
|
|
7
|
+
config(config) {
|
|
8
|
+
const projectRoot = config.root ?? process.cwd();
|
|
9
|
+
|
|
10
|
+
config.build ??= {};
|
|
11
|
+
if (process.env.ROZENITE_BUILD === '1') {
|
|
12
|
+
config.build.emptyOutDir = false;
|
|
13
|
+
}
|
|
14
|
+
config.build.rollupOptions ??= {};
|
|
15
|
+
|
|
16
|
+
config.build.lib = {
|
|
17
|
+
entry: path.resolve(projectRoot, 'react-native.ts'),
|
|
18
|
+
fileName: (format) =>
|
|
19
|
+
`react-native/index.${format === 'es' ? 'js' : 'cjs'}`,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
config.build.rollupOptions.external = (id) => {
|
|
23
|
+
if (id.startsWith('node:')) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return !id.startsWith('.') && !path.isAbsolute(id);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
config.build.rollupOptions.output = [
|
|
31
|
+
{
|
|
32
|
+
format: 'es',
|
|
33
|
+
exports: 'named',
|
|
34
|
+
interop: 'auto',
|
|
35
|
+
entryFileNames: 'react-native/index.js',
|
|
36
|
+
chunkFileNames: 'react-native/chunks/[name].js',
|
|
37
|
+
...(config.build.rollupOptions.output ?? {}),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
format: 'cjs',
|
|
41
|
+
exports: 'named',
|
|
42
|
+
interop: 'auto',
|
|
43
|
+
entryFileNames: 'react-native/index.cjs',
|
|
44
|
+
chunkFileNames: 'react-native/chunks/[name].cjs',
|
|
45
|
+
...(config.build.rollupOptions.output ?? {}),
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
delete config.build.rollupOptions.input;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { normalizePath, Plugin } from 'vite';
|
|
5
|
+
|
|
6
|
+
const REQUIRE_REGEX = /require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
|
|
7
|
+
const IMPORT_PREFIX = '__import_';
|
|
8
|
+
const VIRTUAL_REQUIRE_PREFIX = '\0virtual:rozenite-rn-require:';
|
|
9
|
+
const REQUIRE_WRAPPER_SUFFIX = '.require';
|
|
10
|
+
|
|
11
|
+
interface ModuleInfo {
|
|
12
|
+
referenceId: string;
|
|
13
|
+
virtualId: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TransformResult {
|
|
17
|
+
code: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const extractModuleName = (filePath: string): string => {
|
|
21
|
+
return path.basename(filePath).replace(/\.[^/.]+$/, '');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const sanitizeChunkName = (value: string): string => {
|
|
25
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const findRequireStatements = (code: string): Set<string> => {
|
|
29
|
+
const requires = new Set<string>();
|
|
30
|
+
let match: RegExpExecArray | null;
|
|
31
|
+
|
|
32
|
+
REQUIRE_REGEX.lastIndex = 0;
|
|
33
|
+
|
|
34
|
+
while ((match = REQUIRE_REGEX.exec(code)) !== null) {
|
|
35
|
+
const moduleName = match[1];
|
|
36
|
+
if (moduleName && moduleName.trim()) {
|
|
37
|
+
requires.add(moduleName.trim());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return requires;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const transformRequireToImports = (
|
|
45
|
+
code: string,
|
|
46
|
+
moduleInfoMap: Map<string, ModuleInfo>,
|
|
47
|
+
): TransformResult => {
|
|
48
|
+
const imports: string[] = [];
|
|
49
|
+
const importMap = new Map<string, string>();
|
|
50
|
+
const requires = findRequireStatements(code);
|
|
51
|
+
|
|
52
|
+
requires.forEach((moduleName, index) => {
|
|
53
|
+
const moduleInfo = moduleInfoMap.get(moduleName);
|
|
54
|
+
|
|
55
|
+
if (!moduleInfo) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const importName = `${IMPORT_PREFIX}${index}`;
|
|
60
|
+
importMap.set(moduleName, importName);
|
|
61
|
+
imports.push(`import * as ${importName} from '${moduleInfo.virtualId}';`);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
let transformedCode = code.replace(REQUIRE_REGEX, (match, moduleName) => {
|
|
65
|
+
const importName = importMap.get(moduleName.trim());
|
|
66
|
+
return importName || match;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (imports.length > 0) {
|
|
70
|
+
transformedCode = imports.join('\n') + '\n' + transformedCode;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { code: transformedCode };
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const transformRequireToChunkReferences = (
|
|
77
|
+
code: string,
|
|
78
|
+
moduleInfoMap: Map<string, ModuleInfo>,
|
|
79
|
+
getFileName: (referenceId: string) => string,
|
|
80
|
+
): string => {
|
|
81
|
+
return code.replace(REQUIRE_REGEX, (match, moduleName) => {
|
|
82
|
+
const moduleInfo = moduleInfoMap.get(moduleName.trim());
|
|
83
|
+
|
|
84
|
+
if (!moduleInfo) {
|
|
85
|
+
return match;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const outFileName = getFileName(moduleInfo.referenceId);
|
|
89
|
+
const relPath = normalizePath(
|
|
90
|
+
path.posix.relative('react-native', outFileName),
|
|
91
|
+
);
|
|
92
|
+
const requirePath = relPath.startsWith('.') ? relPath : `./${relPath}`;
|
|
93
|
+
|
|
94
|
+
return `require('${requirePath}')`;
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default function requirePlugin(): Plugin {
|
|
99
|
+
let input = '';
|
|
100
|
+
let inputName = '';
|
|
101
|
+
let isDevMode = false;
|
|
102
|
+
|
|
103
|
+
const moduleInfoMap = new Map<string, ModuleInfo>();
|
|
104
|
+
const virtualModuleSources = new Map<string, string>();
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
name: 'vite-require-plugin',
|
|
108
|
+
|
|
109
|
+
configResolved(config) {
|
|
110
|
+
isDevMode = config.command === 'serve';
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
resolveId(id) {
|
|
114
|
+
if (virtualModuleSources.has(id)) {
|
|
115
|
+
return id;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return null;
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
load(id) {
|
|
122
|
+
return virtualModuleSources.get(id) ?? null;
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
transform(code, id) {
|
|
126
|
+
if (!isDevMode || id !== input) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const result = transformRequireToImports(code, moduleInfoMap);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
code: result.code,
|
|
135
|
+
map: null,
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Error transforming require statements:', error);
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
async buildStart(options) {
|
|
144
|
+
try {
|
|
145
|
+
assert(Array.isArray(options.input), 'input must be an array');
|
|
146
|
+
assert(
|
|
147
|
+
options.input.length === 1,
|
|
148
|
+
'input must be an array with one entry',
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
input = options.input[0];
|
|
152
|
+
inputName = extractModuleName(input);
|
|
153
|
+
moduleInfoMap.clear();
|
|
154
|
+
virtualModuleSources.clear();
|
|
155
|
+
|
|
156
|
+
const code = readFileSync(input, 'utf-8');
|
|
157
|
+
const requires = findRequireStatements(code);
|
|
158
|
+
|
|
159
|
+
for (const req of requires) {
|
|
160
|
+
try {
|
|
161
|
+
const resolved = await this.resolve(req, input, { skipSelf: true });
|
|
162
|
+
|
|
163
|
+
if (!resolved) {
|
|
164
|
+
console.warn(`Could not resolve module: ${req}`);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
this.addWatchFile(resolved.id);
|
|
169
|
+
|
|
170
|
+
const exportName = sanitizeChunkName(
|
|
171
|
+
extractModuleName(resolved.id),
|
|
172
|
+
);
|
|
173
|
+
const wrapperName = `${exportName}${REQUIRE_WRAPPER_SUFFIX}`;
|
|
174
|
+
const virtualId = `${VIRTUAL_REQUIRE_PREFIX}${wrapperName}`;
|
|
175
|
+
|
|
176
|
+
virtualModuleSources.set(
|
|
177
|
+
virtualId,
|
|
178
|
+
`export * from ${JSON.stringify(req)};`,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const referenceId = this.emitFile({
|
|
182
|
+
type: 'chunk',
|
|
183
|
+
id: virtualId,
|
|
184
|
+
name: wrapperName,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
moduleInfoMap.set(req, {
|
|
188
|
+
referenceId,
|
|
189
|
+
virtualId,
|
|
190
|
+
});
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error(`Error resolving module ${req}:`, error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Error in buildStart:', error);
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
renderChunk(code, chunk) {
|
|
202
|
+
try {
|
|
203
|
+
if (chunk.name !== inputName) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
code: transformRequireToChunkReferences(
|
|
209
|
+
code,
|
|
210
|
+
moduleInfoMap,
|
|
211
|
+
(referenceId) => normalizePath(this.getFileName(referenceId)),
|
|
212
|
+
),
|
|
213
|
+
map: null,
|
|
214
|
+
};
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error('Error in renderChunk:', error);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const rozeniteSdkPlugin = (): Plugin => {
|
|
5
|
+
return {
|
|
6
|
+
name: 'rozenite-sdk-plugin',
|
|
7
|
+
config(config) {
|
|
8
|
+
const projectRoot = config.root ?? process.cwd();
|
|
9
|
+
|
|
10
|
+
config.build ??= {};
|
|
11
|
+
if (process.env.ROZENITE_BUILD === '1') {
|
|
12
|
+
config.build.emptyOutDir = false;
|
|
13
|
+
}
|
|
14
|
+
config.build.lib = {
|
|
15
|
+
entry: path.resolve(projectRoot, 'sdk.ts'),
|
|
16
|
+
formats: ['es' as const, 'cjs' as const],
|
|
17
|
+
fileName: (format) => `sdk/index.${format === 'es' ? 'js' : 'cjs'}`,
|
|
18
|
+
};
|
|
19
|
+
config.build.rollupOptions ??= {};
|
|
20
|
+
config.build.rollupOptions.external = (id) => {
|
|
21
|
+
if (id.startsWith('node:')) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return !id.startsWith('.') && !path.isAbsolute(id);
|
|
26
|
+
};
|
|
27
|
+
config.build.rollupOptions.output = [
|
|
28
|
+
{
|
|
29
|
+
format: 'es',
|
|
30
|
+
exports: 'named',
|
|
31
|
+
interop: 'auto',
|
|
32
|
+
entryFileNames: 'sdk/index.js',
|
|
33
|
+
chunkFileNames: 'sdk/chunks/[name].js',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
format: 'cjs',
|
|
37
|
+
exports: 'named',
|
|
38
|
+
interop: 'auto',
|
|
39
|
+
entryFileNames: 'sdk/index.cjs',
|
|
40
|
+
chunkFileNames: 'sdk/chunks/[name].cjs',
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
delete config.build.rollupOptions.input;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
export const rozeniteServerPlugin = (): Plugin => {
|
|
6
|
+
return {
|
|
7
|
+
name: 'rozenite-server-plugin',
|
|
8
|
+
|
|
9
|
+
config(config) {
|
|
10
|
+
const projectRoot = config.root ?? process.cwd();
|
|
11
|
+
|
|
12
|
+
config.build ??= {};
|
|
13
|
+
if (process.env.ROZENITE_BUILD === '1') {
|
|
14
|
+
config.build.emptyOutDir = false;
|
|
15
|
+
}
|
|
16
|
+
config.build.lib = {
|
|
17
|
+
entry: path.resolve(projectRoot, 'metro.ts'),
|
|
18
|
+
formats: ['es' as const, 'cjs' as const],
|
|
19
|
+
fileName: (format) => `metro/index.${format === 'es' ? 'js' : 'cjs'}`,
|
|
20
|
+
};
|
|
21
|
+
config.build.ssr = true;
|
|
22
|
+
config.build.rollupOptions ??= {};
|
|
23
|
+
config.build.rollupOptions.output = [
|
|
24
|
+
{
|
|
25
|
+
format: 'es',
|
|
26
|
+
entryFileNames: 'metro/index.js',
|
|
27
|
+
exports: 'named',
|
|
28
|
+
interop: 'auto',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
format: 'cjs',
|
|
32
|
+
entryFileNames: 'metro/index.cjs',
|
|
33
|
+
exports: 'named',
|
|
34
|
+
interop: 'auto',
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
};
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const resolveFileWithExtensions = (
|
|
5
|
+
directory: string,
|
|
6
|
+
baseName: string,
|
|
7
|
+
): string | null => {
|
|
8
|
+
const extensions = ['.tsx', '.ts', '.jsx', '.js'];
|
|
9
|
+
|
|
10
|
+
for (const ext of extensions) {
|
|
11
|
+
const filePath = path.join(directory, baseName + ext);
|
|
12
|
+
|
|
13
|
+
if (fs.existsSync(filePath)) {
|
|
14
|
+
return filePath;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const memo = <T>(fn: () => T): (() => T) => {
|
|
22
|
+
let result: T | null = null;
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
if (result === null) {
|
|
26
|
+
result = fn();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
:root{color-scheme:dark;font-family:Switzer Variable,Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;background:#000;color:#fff}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{overflow:hidden;background:#000}button,input,textarea,select{font:inherit}.rz-shell{display:flex;height:100dvh;flex-direction:column;overflow:hidden;background:#000}.rz-topbar{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:52px;padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.08);overflow:hidden;background:#0a0a0a}.rz-topbar-brand{display:inline-flex;align-items:center;flex:0 0 auto}.rz-topbar-brand svg{display:block;width:auto;height:20px}.rz-topbar-panel-picker{display:flex;align-items:center;min-width:0;justify-content:flex-end}.rz-workspace{flex:1;min-height:0;display:grid;grid-template-rows:minmax(0,1fr) 12px minmax(180px,var(--rz-devtools-height, 288px));overflow:hidden}.rz-card{min-height:0;overflow:hidden;border-top:1px solid rgba(255,255,255,.08)}.rz-card:first-child{border-top:0}.rz-iframe{display:block;width:100%;height:100%;border:0;background:#fff}.rz-iframe[data-resizing=true]{pointer-events:none}.rz-devtools{display:grid;min-height:0;grid-template-columns:minmax(0,1fr) var(--rz-command-splitter-width, 6px) minmax(260px,var(--rz-command-width, 320px))}.rz-devtools-mobile{display:flex;min-height:0;height:100%;width:100%;overflow:hidden}.rz-log-workspace{display:grid;min-height:0;position:relative;grid-template-columns:minmax(0,1fr) var(--rz-details-splitter-width, 0px) var(--rz-details-width, 0px)}.rz-resize-handle{position:relative;cursor:row-resize;background:#0a0a0a;-webkit-user-select:none;user-select:none;touch-action:none}.rz-resize-handle:before{content:"";position:absolute;top:50%;left:50%;width:72px;height:2px;border-radius:999px;background:#fff3;transform:translate(-50%,-50%)}.rz-resize-handle:after{content:"";position:absolute;inset:0;border-top:1px solid rgba(255,255,255,.08);border-bottom:1px solid rgba(255,255,255,.08)}.rz-resize-handle[data-dragging=true]:before,.rz-resize-handle:hover:before{background:#fff}.rz-column-resize-handle{position:relative;width:6px;min-width:6px;cursor:col-resize;background:#0a0a0a;-webkit-user-select:none;user-select:none;touch-action:none}.rz-column-resize-handle:before{content:"";position:absolute;top:50%;left:50%;width:2px;height:72px;border-radius:999px;background:#fff3;transform:translate(-50%,-50%)}.rz-column-resize-handle:after{content:"";position:absolute;inset:0;border-left:1px solid rgba(255,255,255,.08);border-right:1px solid rgba(255,255,255,.08)}.rz-column-resize-handle[data-dragging=true]:before,.rz-column-resize-handle:hover:before{background:#fff}.rz-column-resize-handle[data-dragging=true]:after,.rz-column-resize-handle:hover:after{border-left-color:#ffffff14;border-right-color:#ffffff14}.rz-pane{display:flex;flex-direction:column;min-height:0;overflow:hidden}.rz-pane+.rz-pane{border-left:1px solid rgba(255,255,255,.08)}.rz-pane[data-hidden=true],.rz-column-resize-handle[data-hidden=true]{display:none}.rz-devtools-mobile-tabs{display:grid;grid-template-rows:auto minmax(0,1fr);gap:8px;min-height:0;height:100%;width:100%;padding-top:8px}.rz-devtools-mobile-toggle{display:flex;align-items:flex-start;padding:0 8px}.rz-devtools-mobile-panel{display:flex;min-height:0;width:100%;overflow:hidden}.rz-devtools-mobile-panel>.rz-pane{flex:1;width:100%}.rz-tabs-root{width:100%;min-width:0}.rz-tabs-list{display:inline-flex;min-height:26px;max-width:100%;align-items:center;gap:2px;overflow:auto hidden;border:1px solid rgba(255,255,255,.08);border-radius:4px;background:#ffffff0a;padding:2px;scrollbar-width:none}.rz-tabs-list::-webkit-scrollbar{display:none}.rz-tabs-trigger{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap;border:0;border-radius:2px;background:transparent;min-height:22px;padding:3px 9px;color:#fff9;font-size:12px;font-weight:500;line-height:1.2;letter-spacing:0;transition:background-color .12s ease,color .12s ease}.rz-tabs-trigger:hover{color:#fff}.rz-tabs-trigger[data-state=active]{background:#fff;color:#000}.rz-tabs-trigger:focus-visible,.rz-input:focus-visible,.rz-textarea:focus-visible,.rz-sidebar-close:focus-visible{outline:2px solid rgba(130,50,255,.95);outline-offset:-2px}.rz-scroll-area{position:relative;height:100%;width:100%;overflow:hidden}.rz-scroll-viewport{height:100%;width:100%;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.18) transparent}.rz-scroll-viewport::-webkit-scrollbar{width:12px}.rz-scroll-viewport::-webkit-scrollbar-track{background:transparent}.rz-scroll-viewport::-webkit-scrollbar-thumb{border:3px solid transparent;border-radius:999px;background:#ffffff2e;background-clip:padding-box}.rz-message-list{min-width:100%;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace}.rz-log-pane{display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0;background:#050505}.rz-message-list-header,.rz-message-row{display:grid;grid-template-columns:40px 168px minmax(120px,180px) minmax(0,1fr);gap:0;align-items:center}.rz-message-list-header{position:sticky;top:0;z-index:1;background:#0a0a0a;color:#fff6;font-size:11px;line-height:16px;letter-spacing:.06em;text-transform:uppercase;border-bottom:1px solid rgba(255,255,255,.08)}.rz-message-header-cell,.rz-message-cell{min-width:0;padding:8px 12px}.rz-message-header-cell:first-child,.rz-message-cell:first-child{text-align:center}.rz-message-header-cell+.rz-message-header-cell,.rz-message-cell+.rz-message-cell{border-left:1px solid rgba(255,255,255,.04)}.rz-message-row{width:100%;border:0;background:transparent;color:inherit;text-align:left;padding:0;border-bottom:1px solid rgba(255,255,255,.06);cursor:pointer;transition:background-color .12s ease,box-shadow .12s ease}.rz-message-row:last-child{border-bottom:0}.rz-message-row:hover{background:#ffffff09}.rz-message-row[data-selected=true]{background:#3b82f624;box-shadow:inset 2px 0 #4da3ff}.rz-message-direction{display:flex;align-items:center;justify-content:center;color:#ffffffb3;font-size:12px;line-height:18px}.rz-message-arrow{display:inline-flex;width:16px;justify-content:center;font-size:14px;font-weight:700}.rz-message-dir-in .rz-message-arrow{color:#22c55e}.rz-message-dir-out .rz-message-arrow{color:#f59e0b}.rz-message-type{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#ffffffeb;font-size:12px;font-weight:500;line-height:18px}.rz-message-date{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#ffffff85;font-size:12px;line-height:18px}.rz-message-preview{margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#ffffff85;font-size:12px;line-height:18px}.rz-sidebar{display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0;background:#050505;flex-grow:1}.rz-message-detail{display:flex;flex-direction:column;gap:16px;padding:16px;min-height:100%}.rz-sidebar-header{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:53px;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.08);background:#ffffff05}.rz-sidebar-scroll{min-height:0}.rz-sidebar-scroll>.rz-scroll-viewport>*{min-height:100%}.rz-sidebar-title{color:#ffffffe0;font-size:12px;font-weight:600;line-height:18px;letter-spacing:.04em;text-transform:uppercase;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace}.rz-header-actions{display:flex;align-items:center;gap:8px}.rz-sidebar-close{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:0;border-radius:4px;background:transparent;color:#ffffff8f;cursor:pointer}.rz-sidebar-close:hover{background:#ffffff0f;color:#fff}.rz-sidebar-close:disabled{cursor:default;opacity:.4}.rz-sidebar-close:disabled:hover{background:transparent;color:#ffffff8f}.rz-sidebar-action-primary{background:#fff;color:#000}.rz-sidebar-action-primary:hover{background:#ffffffe0;color:#000}.rz-sidebar-action-primary:disabled:hover{background:#fff;color:#000}.rz-detail-section{display:grid;align-content:start;gap:8px;min-width:0}.rz-detail-value{min-width:0;border:1px solid rgba(255,255,255,.08);border-radius:4px;background:#ffffff08;padding:10px 12px;color:#ffffffe6;font-size:13px;line-height:1.5;letter-spacing:-.02em}.rz-detail-mono{font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5}.rz-detail-payload{display:flex;border:1px solid rgba(255,255,255,.08);border-radius:4px;background:#ffffff08;padding:12px}.rz-detail-pre{margin:0;white-space:pre-wrap;word-break:break-word}.rz-detail-json-tree{font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5}.rz-detail-json-tree ul,.rz-detail-json-tree li,.rz-detail-json-tree label,.rz-detail-json-tree span{font-size:inherit}.rz-command-form{display:flex;flex-direction:column;gap:12px;padding:16px;min-height:100%}.rz-action-tabs{min-height:100%}.rz-action-tabs-header{display:flex;align-items:center;justify-content:space-between;gap:12px}.rz-action-tab-panel{min-height:0}.rz-action-form{display:flex;flex-direction:column;gap:12px;min-height:100%}.rz-field{display:grid;gap:6px}.rz-template-list{display:flex;flex-wrap:wrap;gap:8px}.rz-preset-menu{position:relative}.rz-preset-icon-button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid rgba(255,255,255,.08);border-radius:6px;background:#ffffff0a;color:#ffffffe0;cursor:pointer;flex-shrink:0}.rz-preset-icon-button:hover{background:#ffffff14;color:#fff}.rz-baseui-preset-menu{min-width:220px;max-width:min(320px,calc(100vw - 24px))}.rz-template-button{border:1px solid rgba(255,255,255,.08);border-radius:999px;background:#ffffff0a;color:#ffffffdb;padding:6px 10px;font-size:12px;line-height:1.4;cursor:pointer}.rz-template-button:hover{background:#ffffff1a;color:#fff}.rz-template-button:focus-visible{outline:2px solid rgba(130,50,255,.95);outline-offset:1px}.rz-template-button:disabled{cursor:default;opacity:.4}.rz-template-button[data-active=true]{background:#8232ff2e;border-color:#8232ff80;color:#fff}.rz-flow-panel{display:grid;gap:16px}.rz-flow-list{display:grid;gap:8px}.rz-flow-list-button{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;border:1px solid rgba(255,255,255,.08);border-radius:8px;background:#ffffff08;color:#ffffffe0;padding:10px 12px;text-align:left;cursor:pointer}.rz-flow-list-button:hover{background:#ffffff0f;color:#fff}.rz-flow-list-button:focus-visible{outline:2px solid rgba(130,50,255,.95);outline-offset:1px}.rz-flow-list-button:disabled{cursor:default;opacity:.4}.rz-flow-list-button[data-active=true]{background:#8232ff24;border-color:#8232ff73}.rz-flow-list-name{display:inline-flex;align-items:center;gap:6px;font-size:13px;line-height:1.4}.rz-flow-list-badge,.rz-flow-state-badge{display:inline-flex;align-items:center;justify-content:center;min-height:18px;padding:0 6px;border-radius:999px;background:#8232ff29;color:#c9a9ff;font-size:10px;line-height:1;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.rz-flow-list-action{color:#ffffff8f;font-size:11px;line-height:1.4;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.rz-flow-empty-state{border:1px dashed rgba(255,255,255,.12);border-radius:8px;padding:12px;color:#fff9;font-size:13px;line-height:1.5}.rz-flow-runs{display:grid;gap:12px}.rz-flow-state{display:grid;gap:8px;padding:12px;border:1px solid rgba(255,255,255,.08);border-radius:8px;background:#ffffff08}.rz-flow-state[data-status=running]{border-color:#8232ff73}.rz-flow-state[data-status=failed]{border-color:#ff787866}.rz-flow-state-header{display:flex;align-items:center;justify-content:space-between;gap:8px}.rz-flow-state-title{display:inline-flex;align-items:center;gap:6px;color:#ffffffe6;font-size:13px;line-height:1.4}.rz-flow-state-status{color:#fff9;font-size:12px;line-height:1.4;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase}.rz-flow-state-error,.rz-flow-state-result{margin:0;border-radius:4px;background:#ffffff0a;padding:10px 12px;color:#ffffffd6;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word}.rz-flow-state-error{color:#ffb4b4}.rz-flow-stop-button{flex-shrink:0}.rz-label{color:#fff9;font-size:12px;line-height:20px;letter-spacing:-.04em;font-family:Geist Mono,ui-monospace,SFMono-Regular,Menlo,monospace}.rz-input,.rz-textarea{width:100%;border:1px solid rgba(255,255,255,.08);border-radius:4px;background:#ffffff0a;color:#fff;padding:10px 12px;font-size:14px;line-height:1.5;letter-spacing:-.02em}.rz-textarea{min-height:112px;resize:none}.rz-button-row{display:flex;justify-content:flex-end;gap:8px;margin-top:auto}.rz-empty-state{display:flex;height:100%;align-items:center;justify-content:center;color:#ffffffb3;padding:24px;text-align:center;font-size:16px;line-height:1.5;letter-spacing:-.02em}@media(max-width:960px){.rz-topbar{padding-left:8px;padding-right:8px}.rz-topbar-brand svg{height:18px}.rz-topbar-panel-picker{overflow:hidden}.rz-workspace{grid-template-rows:minmax(0,1fr) 12px minmax(180px,var(--rz-devtools-height, 272px))}.rz-devtools-mobile-tabs{padding-top:8px}.rz-column-resize-handle{width:100%;min-width:0;min-height:6px;cursor:row-resize}.rz-column-resize-handle:before{width:72px;height:2px}.rz-column-resize-handle:after{border-left:0;border-right:0;border-top:1px solid rgba(255,255,255,.08);border-bottom:1px solid rgba(255,255,255,.08)}.rz-column-resize-handle[data-dragging=true]:after,.rz-column-resize-handle:hover:after{border-top-color:#ffffff14;border-bottom-color:#ffffff14}.rz-action-tabs-header{flex-wrap:wrap;align-items:flex-start}}@media(max-width:640px){.rz-message-list-header,.rz-message-row{grid-template-columns:36px 136px minmax(92px,136px) minmax(0,1fr)}.rz-message-header-cell,.rz-message-cell{padding:8px 10px}}
|