@process.co/element-dev-server 0.0.1-test-3 → 0.0.1-test-5
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/.process/index.html +27 -0
- package/.process/index.tsx +285 -0
- package/.process/vite-env.d.ts +18 -0
- package/.process/vite.config.cjs +276 -0
- package/bin/proc-dev +21 -0
- package/package.json +4 -3
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Process.co Element Dev Server</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
12
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
13
|
+
sans-serif;
|
|
14
|
+
-webkit-font-smoothing: antialiased;
|
|
15
|
+
-moz-osx-font-smoothing: grayscale;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#root {
|
|
19
|
+
min-height: 100vh;
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
22
|
+
</head>
|
|
23
|
+
<body>
|
|
24
|
+
<div id="root"></div>
|
|
25
|
+
<script type="module" src="./index.tsx"></script>
|
|
26
|
+
</body>
|
|
27
|
+
</html>
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// This will be dynamically loaded based on the selected element
|
|
7
|
+
interface ElementComponent {
|
|
8
|
+
default?: React.ComponentType<any>;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function DevServer() {
|
|
13
|
+
const [ElementComponent, setElementComponent] = useState<any>(null);
|
|
14
|
+
const [loading, setLoading] = useState(true);
|
|
15
|
+
const [error, setError] = useState<string | null>(null);
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const [readonly, setReadonly] = useState(false);
|
|
19
|
+
const [value, setValue] = useState<any>({});
|
|
20
|
+
|
|
21
|
+
const handleReadonly = () => {
|
|
22
|
+
setReadonly(!readonly);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const loadElement = async () => {
|
|
27
|
+
try {
|
|
28
|
+
|
|
29
|
+
// Get element path and type from environment variables (passed by CLI)
|
|
30
|
+
const elementPath = import.meta.env.VITE_ELEMENT_PATH;
|
|
31
|
+
const elementType = import.meta.env.VITE_ELEMENT_TYPE || 'action';
|
|
32
|
+
const elementName = import.meta.env.VITE_ELEMENT_NAME;
|
|
33
|
+
const actionSignalKey = import.meta.env.VITE_ACTION_SIGNAL_KEY;
|
|
34
|
+
const propertyKey = import.meta.env.VITE_PROPERTY_KEY;
|
|
35
|
+
const propertyType = import.meta.env.VITE_PROPERTY_TYPE;
|
|
36
|
+
const propertyUIPath = import.meta.env.VITE_PROPERTY_UI_PATH;
|
|
37
|
+
const modulePath = import.meta.env.VITE_MODULE_PATH;
|
|
38
|
+
const uiDirectory = import.meta.env.VITE_UI_DIRECTORY;
|
|
39
|
+
|
|
40
|
+
// console.log('Element data:', {
|
|
41
|
+
// elementPath,
|
|
42
|
+
// elementType,
|
|
43
|
+
// elementName,
|
|
44
|
+
// actionSignalKey,
|
|
45
|
+
// propertyKey,
|
|
46
|
+
// propertyType,
|
|
47
|
+
// propertyUIPath,
|
|
48
|
+
// modulePath,
|
|
49
|
+
// uiDirectory
|
|
50
|
+
// });
|
|
51
|
+
|
|
52
|
+
// console.log('Using new module path system:', {
|
|
53
|
+
// hasModulePath: !!modulePath,
|
|
54
|
+
// hasUIDirectory: !!uiDirectory,
|
|
55
|
+
// modulePath,
|
|
56
|
+
// uiDirectory
|
|
57
|
+
// });
|
|
58
|
+
|
|
59
|
+
if (!elementPath) {
|
|
60
|
+
setError('No element path provided. Make sure to run this through the CLI.');
|
|
61
|
+
setLoading(false);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// console.log(`Loading element: ${elementName} (${elementType}) from ${elementPath}`);
|
|
66
|
+
|
|
67
|
+
// debugger;
|
|
68
|
+
|
|
69
|
+
// Use the complete element data from the compatibility module passed via environment variables
|
|
70
|
+
const elementModule = import.meta.env.VITE_ELEMENT_MODULE || {};
|
|
71
|
+
const currentActionSignal = import.meta.env.VITE_CURRENT_ACTION_SIGNAL || {};
|
|
72
|
+
const selectedProperty = import.meta.env.VITE_SELECTED_PROPERTY || {};
|
|
73
|
+
|
|
74
|
+
// console.log('Element module from compatibility:', elementModule);
|
|
75
|
+
// console.log('Current action/signal:', currentActionSignal);
|
|
76
|
+
// console.log('Selected property:', selectedProperty);
|
|
77
|
+
|
|
78
|
+
// Get actions and signals from the element module
|
|
79
|
+
const actions = elementModule.actions || [];
|
|
80
|
+
const signals = elementModule.signals || [];
|
|
81
|
+
const action = actions.find((a: any) => a.key === actionSignalKey);
|
|
82
|
+
const signal = signals.find((s: any) => s.key === actionSignalKey);
|
|
83
|
+
|
|
84
|
+
// console.log('Found action:', action);
|
|
85
|
+
// console.log('Found signal:', signal);
|
|
86
|
+
|
|
87
|
+
// Use the current action/signal info for UI path
|
|
88
|
+
let uiPath: string | null = null;
|
|
89
|
+
if (currentActionSignal && currentActionSignal.ui) {
|
|
90
|
+
uiPath = `/element-ui/${currentActionSignal.ui}/src/index.tsx`;
|
|
91
|
+
// console.log('UI path from current action/signal:', uiPath);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Try to find the component based on type and key
|
|
95
|
+
let component: any = null;
|
|
96
|
+
|
|
97
|
+
// debugger;
|
|
98
|
+
|
|
99
|
+
// console.log(`Looking for ${elementType} with key: ${actionSignalKey}`);
|
|
100
|
+
// console.log(`UI Directory from env: ${uiDirectory}`);
|
|
101
|
+
// console.log(`Current action/signal:`, currentActionSignal);
|
|
102
|
+
|
|
103
|
+
// Check if we have a selected property from the CLI
|
|
104
|
+
if (selectedProperty && selectedProperty.propertyKey) {
|
|
105
|
+
// console.log(`Selected property: ${selectedProperty.propertyKey} (${selectedProperty.type})`);
|
|
106
|
+
|
|
107
|
+
if (selectedProperty.type === 'ui-variant' && selectedProperty.uiPath) {
|
|
108
|
+
// Property has a UI variant - load the UI component
|
|
109
|
+
uiPath = `/element-ui/${selectedProperty.uiPath}/src/index.tsx`;
|
|
110
|
+
// console.log(`🎨 Loading property UI component: ${selectedProperty.propertyKey} from ${uiPath}`);
|
|
111
|
+
} else {
|
|
112
|
+
// Standard property - use the property data as the component
|
|
113
|
+
component = selectedProperty.propertyData;
|
|
114
|
+
// console.log(`📝 Using standard property data for: ${selectedProperty.propertyKey}`, component);
|
|
115
|
+
}
|
|
116
|
+
} else if (currentActionSignal && currentActionSignal.ui) {
|
|
117
|
+
// No specific property selected, but action/signal has UI
|
|
118
|
+
uiPath = `/element-ui/${currentActionSignal.ui}/src/index.tsx`;
|
|
119
|
+
// console.log(`🎯 Action/Signal has UI property: ${currentActionSignal.ui}`);
|
|
120
|
+
// console.log(`🎯 Constructed UI path: ${uiPath}`);
|
|
121
|
+
} else if (elementType === 'action' && actions && actions.length > 0) {
|
|
122
|
+
// Fallback to first action
|
|
123
|
+
const firstAction = actions[0];
|
|
124
|
+
// console.log(`Using first action: ${firstAction?.key}`, firstAction);
|
|
125
|
+
|
|
126
|
+
if (firstAction && firstAction.ui) {
|
|
127
|
+
uiPath = `/element-ui/${firstAction.ui}/src/index.tsx`;
|
|
128
|
+
// console.log(`First action has UI path: ${uiPath}`);
|
|
129
|
+
}
|
|
130
|
+
} else if (elementType === 'signal' && signals && signals.length > 0) {
|
|
131
|
+
// Fallback to first signal
|
|
132
|
+
const firstSignal = signals[0];
|
|
133
|
+
// console.log(`Using first signal: ${firstSignal?.key}`, firstSignal);
|
|
134
|
+
|
|
135
|
+
if (firstSignal && firstSignal.ui) {
|
|
136
|
+
uiPath = `/element-ui/${firstSignal.ui}/src/index.tsx`;
|
|
137
|
+
// console.log(`First signal has UI path: ${uiPath}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// If we found a UI path, try to load the UI component for the entire action/signal
|
|
142
|
+
if (uiPath) {
|
|
143
|
+
try {
|
|
144
|
+
// console.log(`🎨 Loading UI component for entire ${elementType} from: ${uiPath}`);
|
|
145
|
+
// console.log(`🔍 UI path type: ${typeof uiPath}`);
|
|
146
|
+
// console.log(`🔍 UI path length: ${uiPath.length}`);
|
|
147
|
+
|
|
148
|
+
// Import the UI component using the virtual path
|
|
149
|
+
const uiModule = await import(/* @vite-ignore */ uiPath) as ElementComponent;
|
|
150
|
+
// console.log(`📦 UI module loaded:`, uiModule);
|
|
151
|
+
// console.log(`📦 UI module keys:`, Object.keys(uiModule));
|
|
152
|
+
// console.log(`📦 UI module default:`, uiModule.default);
|
|
153
|
+
|
|
154
|
+
component = uiModule.default || uiModule;
|
|
155
|
+
// console.log(`✅ Successfully loaded UI component for entire ${elementType}:`, component);
|
|
156
|
+
// console.log(`✅ Component type:`, typeof component);
|
|
157
|
+
// console.log(`✅ Component is function:`, typeof component === 'function');
|
|
158
|
+
} catch (uiError) {
|
|
159
|
+
console.error('❌ Failed to load UI component:', uiError);
|
|
160
|
+
console.error('❌ Error details:', {
|
|
161
|
+
message: uiError.message,
|
|
162
|
+
stack: uiError.stack,
|
|
163
|
+
name: uiError.name
|
|
164
|
+
});
|
|
165
|
+
// Fallback to the action/signal itself
|
|
166
|
+
if (actionSignalKey) {
|
|
167
|
+
const fallbackAction = actions?.find((a: any) => a.key === actionSignalKey);
|
|
168
|
+
const fallbackSignal = signals?.find((s: any) => s.key === actionSignalKey);
|
|
169
|
+
component = fallbackAction || fallbackSignal;
|
|
170
|
+
// console.log(`🔄 Falling back to action/signal metadata:`, component);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else if (currentActionSignal) {
|
|
174
|
+
// No UI path found, fallback to the current action/signal data
|
|
175
|
+
component = currentActionSignal;
|
|
176
|
+
// console.log('Using current action/signal as component');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (component) {
|
|
180
|
+
setElementComponent(() => component);
|
|
181
|
+
} else {
|
|
182
|
+
setError(`No ${elementType} component found in ${elementName}`);
|
|
183
|
+
}
|
|
184
|
+
} catch (err) {
|
|
185
|
+
console.error('Error loading element:', err);
|
|
186
|
+
setError(`Failed to load element: ${err instanceof Error ? err.message : String(err)}`);
|
|
187
|
+
} finally {
|
|
188
|
+
setLoading(false);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
loadElement();
|
|
193
|
+
}, []);
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if (loading) {
|
|
197
|
+
return (
|
|
198
|
+
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
|
|
199
|
+
<h2>Loading Element...</h2>
|
|
200
|
+
<p>Please wait while the element is being loaded.</p>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (error) {
|
|
206
|
+
return (
|
|
207
|
+
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif', color: 'red' }}>
|
|
208
|
+
<h2>Error Loading Element</h2>
|
|
209
|
+
<p>{error}</p>
|
|
210
|
+
<p>Check the console for more details.</p>
|
|
211
|
+
</div>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!ElementComponent) {
|
|
216
|
+
return (
|
|
217
|
+
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
|
|
218
|
+
<h2>No Component Found</h2>
|
|
219
|
+
<p>The selected element doesn't have a renderable component.</p>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
|
|
226
|
+
<h2>Element Development Server</h2>
|
|
227
|
+
|
|
228
|
+
<h3>Rendered Component</h3>
|
|
229
|
+
<div style={{ marginBottom: '10px' }}>
|
|
230
|
+
<button
|
|
231
|
+
onClick={handleReadonly}
|
|
232
|
+
>
|
|
233
|
+
{readonly ? 'Make Editable' : 'Make Read Only'}
|
|
234
|
+
</button>
|
|
235
|
+
</div>
|
|
236
|
+
<div style={{ border: '2px solid #007acc', padding: '20px', borderRadius: '8px', backgroundColor: '#f8f9fa' }}>
|
|
237
|
+
{typeof ElementComponent === 'function' ? (
|
|
238
|
+
<ElementComponent
|
|
239
|
+
value={value}
|
|
240
|
+
onChange={(newValue: any) => setValue(newValue)}
|
|
241
|
+
onBlur={() => console.log('Component onBlur')}
|
|
242
|
+
readonly={readonly}
|
|
243
|
+
/>
|
|
244
|
+
) : React.isValidElement(ElementComponent) ? (
|
|
245
|
+
ElementComponent
|
|
246
|
+
) : (
|
|
247
|
+
<div style={{ color: '#666', fontStyle: 'italic' }}>
|
|
248
|
+
Component is not a valid React component. Type: {typeof ElementComponent}
|
|
249
|
+
<br />
|
|
250
|
+
<small>This might be the element metadata instead of the UI component.</small>
|
|
251
|
+
</div>
|
|
252
|
+
)}
|
|
253
|
+
</div>
|
|
254
|
+
<div style={{ marginBottom: '10px' }}>
|
|
255
|
+
<h3>Value</h3>
|
|
256
|
+
<pre style={{ backgroundColor: '#f5f5f5', padding: '10px', overflow: 'auto' }}>
|
|
257
|
+
{JSON.stringify(value, null, 2)}
|
|
258
|
+
</pre>
|
|
259
|
+
</div>
|
|
260
|
+
<div style={{ border: '1px solid #ccc', padding: '20px', marginTop: '20px', marginBottom: '20px', backgroundColor: '#f8f9fa' }}>
|
|
261
|
+
<h3>Loaded Component Information</h3>
|
|
262
|
+
<p><strong>Element:</strong> {import.meta.env.VITE_ELEMENT_NAME}</p>
|
|
263
|
+
<p><strong>Type:</strong> {import.meta.env.VITE_ELEMENT_TYPE}</p>
|
|
264
|
+
<p><strong>Action/Signal:</strong> {import.meta.env.VITE_ACTION_SIGNAL_KEY}</p>
|
|
265
|
+
<p><strong>Module Path:</strong> {import.meta.env.VITE_ELEMENT_PATH}</p>
|
|
266
|
+
<p><strong>UI Directory:</strong> {import.meta.env.VITE_UI_DIRECTORY || 'Not available'}</p>
|
|
267
|
+
|
|
268
|
+
<h3>Component Details</h3>
|
|
269
|
+
<pre style={{ backgroundColor: '#f5f5f5', padding: '10px', overflow: 'auto' }}>
|
|
270
|
+
{JSON.stringify(ElementComponent, null, 2)}
|
|
271
|
+
</pre>
|
|
272
|
+
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Render the app
|
|
279
|
+
const container = document.getElementById('root');
|
|
280
|
+
if (container) {
|
|
281
|
+
const root = createRoot(container);
|
|
282
|
+
root.render(<DevServer />);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export default DevServer;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
// readonly VITE_ELEMENT?: string;
|
|
5
|
+
readonly VITE_ELEMENT_PATH?: string;
|
|
6
|
+
readonly VITE_ELEMENT_TYPE?: string;
|
|
7
|
+
readonly VITE_ELEMENT_NAME?: string;
|
|
8
|
+
readonly VITE_ACTION_SIGNAL_KEY?: string;
|
|
9
|
+
readonly VITE_PROPERTY_KEY?: string;
|
|
10
|
+
readonly VITE_PROPERTY_TYPE?: string;
|
|
11
|
+
readonly VITE_PROPERTY_UI_PATH?: string;
|
|
12
|
+
readonly VITE_MODULE_PATH?: string;
|
|
13
|
+
readonly VITE_UI_DIRECTORY?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface ImportMeta {
|
|
17
|
+
readonly env: ImportMetaEnv;
|
|
18
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// process-co/element-dev-server/.process/vite.config.js
|
|
2
|
+
|
|
3
|
+
const { defineConfig } = require('vite');
|
|
4
|
+
const react = require('@vitejs/plugin-react');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
// Access environment variables passed from CLI
|
|
9
|
+
const elementPath = process.env.VITE_ELEMENT_PATH;
|
|
10
|
+
const elementType = process.env.VITE_ELEMENT_TYPE;
|
|
11
|
+
const elementName = process.env.VITE_ELEMENT_NAME;
|
|
12
|
+
const actionSignalKey = process.env.VITE_ACTION_SIGNAL_KEY;
|
|
13
|
+
const propertyKey = process.env.VITE_PROPERTY_KEY;
|
|
14
|
+
const propertyType = process.env.VITE_PROPERTY_TYPE;
|
|
15
|
+
const propertyUIPath = process.env.VITE_PROPERTY_UI_PATH;
|
|
16
|
+
|
|
17
|
+
// console.log('Vite config received:', {
|
|
18
|
+
// elementPath,
|
|
19
|
+
// elementType,
|
|
20
|
+
// elementName,
|
|
21
|
+
// actionSignalKey,
|
|
22
|
+
// propertyKey,
|
|
23
|
+
// propertyType,
|
|
24
|
+
// propertyUIPath
|
|
25
|
+
// });
|
|
26
|
+
|
|
27
|
+
// console.log('Vite config root directory:', __dirname);
|
|
28
|
+
// console.log('Vite config index.html path:', path.resolve(__dirname, 'index.html'));
|
|
29
|
+
// console.log('Vite config index.tsx path:', path.resolve(__dirname, 'index.tsx'));
|
|
30
|
+
|
|
31
|
+
module.exports = defineConfig({
|
|
32
|
+
plugins: [
|
|
33
|
+
react(),
|
|
34
|
+
{
|
|
35
|
+
name: 'element-virtual-modules',
|
|
36
|
+
resolveId(source) {
|
|
37
|
+
// Main element module
|
|
38
|
+
if (source === '/element-main') {
|
|
39
|
+
// Try to find the main app file
|
|
40
|
+
const candidates = [
|
|
41
|
+
path.join(elementPath, `${elementName}.app.mts`),
|
|
42
|
+
path.join(elementPath, `${elementName}.app.mjs`),
|
|
43
|
+
path.join(elementPath, 'process_internal.app.mts'),
|
|
44
|
+
path.join(elementPath, 'process_internal.app.mjs')
|
|
45
|
+
];
|
|
46
|
+
for (const file of candidates) {
|
|
47
|
+
if (fs.existsSync(file)) return file;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Action modules
|
|
51
|
+
if (source.startsWith('/element-action/')) {
|
|
52
|
+
const actionKey = source.replace('/element-action/', '');
|
|
53
|
+
// Look for the action file in the actions directory
|
|
54
|
+
const actionsDir = path.join(elementPath, 'actions');
|
|
55
|
+
if (fs.existsSync(actionsDir)) {
|
|
56
|
+
const subdirs = fs.readdirSync(actionsDir).filter(f => fs.statSync(path.join(actionsDir, f)).isDirectory());
|
|
57
|
+
for (const subdir of subdirs) {
|
|
58
|
+
// Try to match the action key
|
|
59
|
+
if (subdir === actionKey) {
|
|
60
|
+
// Look for index.ts, index.mts, index.js, index.mjs, or {actionKey}.ts, etc.
|
|
61
|
+
const candidates = [
|
|
62
|
+
path.join(actionsDir, subdir, 'index.ts'),
|
|
63
|
+
path.join(actionsDir, subdir, 'index.mts'),
|
|
64
|
+
path.join(actionsDir, subdir, 'index.js'),
|
|
65
|
+
path.join(actionsDir, subdir, 'index.mjs'),
|
|
66
|
+
path.join(actionsDir, subdir, `${subdir}.ts`),
|
|
67
|
+
path.join(actionsDir, subdir, `${subdir}.mts`),
|
|
68
|
+
path.join(actionsDir, subdir, `${subdir}.js`),
|
|
69
|
+
path.join(actionsDir, subdir, `${subdir}.mjs`)
|
|
70
|
+
];
|
|
71
|
+
for (const file of candidates) {
|
|
72
|
+
if (fs.existsSync(file)) return file;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'external-element-loader',
|
|
83
|
+
|
|
84
|
+
configureServer(server) {
|
|
85
|
+
// Set up file watching for the element directory
|
|
86
|
+
if (elementPath) {
|
|
87
|
+
const elementDir = fs.statSync(elementPath).isDirectory()
|
|
88
|
+
? elementPath
|
|
89
|
+
: path.dirname(elementPath);
|
|
90
|
+
|
|
91
|
+
// console.log(`🔍 Setting up file watching for element directory: ${elementDir}`);
|
|
92
|
+
|
|
93
|
+
// Watch the entire element directory for changes
|
|
94
|
+
server.watcher.add(elementDir);
|
|
95
|
+
|
|
96
|
+
// Set up HMR for external files
|
|
97
|
+
server.watcher.on('change', (file) => {
|
|
98
|
+
// console.log(`📝 File changed: ${file}`);
|
|
99
|
+
|
|
100
|
+
// Check if the changed file is in the element directory
|
|
101
|
+
if (file.startsWith(elementDir)) {
|
|
102
|
+
// console.log(`🔄 Element file changed: ${file}`);
|
|
103
|
+
|
|
104
|
+
// Trigger HMR for any modules that depend on this file
|
|
105
|
+
server.moduleGraph.invalidateModule(file);
|
|
106
|
+
|
|
107
|
+
// Notify clients about the change
|
|
108
|
+
server.ws.send({
|
|
109
|
+
type: 'update',
|
|
110
|
+
path: file,
|
|
111
|
+
timestamp: Date.now()
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
resolveId(source, importer) {
|
|
119
|
+
// console.log(`resolveId called with source: ${source}, importer: ${importer}`);
|
|
120
|
+
|
|
121
|
+
// Handle virtual element paths
|
|
122
|
+
if (source.startsWith('/')) {
|
|
123
|
+
const relativePath = source.replace('/element/', '');
|
|
124
|
+
const fullPath = path.join(elementPath ??'', relativePath);
|
|
125
|
+
if (fs.existsSync(fullPath)) {
|
|
126
|
+
// console.log(`Resolving element path: ${source} -> ${fullPath}`);
|
|
127
|
+
return fullPath;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Handle virtual element-ui paths
|
|
132
|
+
if (source.startsWith('/element-ui/')) {
|
|
133
|
+
const relativePath = source.replace('/element-ui/', '');
|
|
134
|
+
const elementDir = fs.statSync(elementPath).isDirectory()
|
|
135
|
+
? elementPath
|
|
136
|
+
: path.dirname(elementPath);
|
|
137
|
+
const uiDir = path.join(elementDir, 'ui');
|
|
138
|
+
const fullPath = path.join(uiDir, relativePath);
|
|
139
|
+
// console.log(`🎨 Trying to resolve element-ui path: ${source} -> ${fullPath}`);
|
|
140
|
+
// console.log(`🎨 Element path: ${elementPath}, Element dir: ${elementDir}, UI dir: ${uiDir}`);
|
|
141
|
+
// console.log(`🎨 Relative path: ${relativePath}`);
|
|
142
|
+
if (fs.existsSync(fullPath)) {
|
|
143
|
+
// console.log(`✅ Resolving element-ui path: ${source} -> ${fullPath}`);
|
|
144
|
+
return fullPath;
|
|
145
|
+
} else {
|
|
146
|
+
// console.log(`❌ Element-ui path not found: ${fullPath}`);
|
|
147
|
+
// console.log(`❌ Checking if UI dir exists: ${fs.existsSync(uiDir)}`);
|
|
148
|
+
// if (fs.existsSync(uiDir)) {
|
|
149
|
+
// console.log(`❌ UI dir contents:`, fs.readdirSync(uiDir));
|
|
150
|
+
// }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Handle external element file imports (absolute paths)
|
|
155
|
+
if (source.startsWith('/') && fs.existsSync(source)) {
|
|
156
|
+
const stats = fs.statSync(source);
|
|
157
|
+
if (stats.isFile()) {
|
|
158
|
+
// console.log(`Resolving external file: ${source}`);
|
|
159
|
+
return source;
|
|
160
|
+
} else if (stats.isDirectory()) {
|
|
161
|
+
// console.log(`Skipping directory in resolveId: ${source}`);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Handle relative imports from the element directory
|
|
167
|
+
if (elementPath && !source.startsWith('/') && !source.startsWith('.')) {
|
|
168
|
+
const elementDir = fs.statSync(elementPath).isDirectory()
|
|
169
|
+
? elementPath
|
|
170
|
+
: path.dirname(elementPath);
|
|
171
|
+
const possiblePath = path.join(elementDir, source);
|
|
172
|
+
if (fs.existsSync(possiblePath)) {
|
|
173
|
+
// console.log(`Resolving relative import: ${source} -> ${possiblePath}`);
|
|
174
|
+
return possiblePath;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return null;
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
load(id) {
|
|
182
|
+
// console.log(`load called with id: ${id}`);
|
|
183
|
+
|
|
184
|
+
// Load external files when they're requested
|
|
185
|
+
if (id.startsWith('/') && fs.existsSync(id)) {
|
|
186
|
+
const stats = fs.statSync(id);
|
|
187
|
+
if (stats.isFile()) {
|
|
188
|
+
const content = fs.readFileSync(id, 'utf-8');
|
|
189
|
+
// console.log(`Loading external file: ${id}`);
|
|
190
|
+
return content;
|
|
191
|
+
} else if (stats.isDirectory()) {
|
|
192
|
+
// console.log(`Skipping directory: ${id}`);
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Load files from element directory
|
|
198
|
+
if (fs.existsSync(id)) {
|
|
199
|
+
const stats = fs.statSync(id);
|
|
200
|
+
if (stats.isFile()) {
|
|
201
|
+
const content = fs.readFileSync(id, 'utf-8');
|
|
202
|
+
// console.log(`✅ Loading element file: ${id}`);
|
|
203
|
+
return content;
|
|
204
|
+
} else {
|
|
205
|
+
// console.log(`❌ Path exists but is not a file: ${id}`);
|
|
206
|
+
}
|
|
207
|
+
} else {
|
|
208
|
+
// console.log(`❌ Path does not exist: ${id}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return null;
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
handleHotUpdate(ctx) {
|
|
215
|
+
// Handle HMR for external files
|
|
216
|
+
const { file, server } = ctx;
|
|
217
|
+
|
|
218
|
+
if (elementPath && file.startsWith(elementPath)) {
|
|
219
|
+
// console.log(`🔥 HMR triggered for element file: ${file}`);
|
|
220
|
+
|
|
221
|
+
// Invalidate the module in the module graph
|
|
222
|
+
const module = server.moduleGraph.getModuleById(file);
|
|
223
|
+
if (module) {
|
|
224
|
+
server.moduleGraph.invalidateModule(module);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Return the modules that need to be updated
|
|
228
|
+
return ctx.modules;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return ctx.modules;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
// root is set programmatically in the CLI
|
|
236
|
+
server: {
|
|
237
|
+
port: 5173,
|
|
238
|
+
open: true,
|
|
239
|
+
host: true,
|
|
240
|
+
fs: {
|
|
241
|
+
// Allow serving files from outside the root
|
|
242
|
+
allow: ['..']
|
|
243
|
+
},
|
|
244
|
+
watch: {
|
|
245
|
+
// Watch external directories for changes
|
|
246
|
+
ignored: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
|
|
247
|
+
usePolling: false
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
build: {
|
|
251
|
+
rollupOptions: {
|
|
252
|
+
input: {
|
|
253
|
+
main: path.resolve(__dirname, 'index.html')
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
resolve: {
|
|
258
|
+
alias: {
|
|
259
|
+
'@': path.resolve(process.cwd(), 'src'),
|
|
260
|
+
// Dynamically map element paths based on the elementPath from CLI
|
|
261
|
+
...(elementPath && {
|
|
262
|
+
// Map the element directory to a virtual path that Vite can resolve
|
|
263
|
+
'/element': elementPath,
|
|
264
|
+
// Also map the element's UI directory if it exists
|
|
265
|
+
'/element-ui': path.join(
|
|
266
|
+
fs.statSync(elementPath).isDirectory() ? elementPath : path.dirname(elementPath),
|
|
267
|
+
'ui'
|
|
268
|
+
)
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
optimizeDeps: {
|
|
273
|
+
include: ['react', 'react-dom']
|
|
274
|
+
},
|
|
275
|
+
// Environment variables will be passed programmatically
|
|
276
|
+
});
|
package/bin/proc-dev
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'node:child_process'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { dirname, resolve } from 'node:path'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
8
|
+
const __dirname = dirname(__filename)
|
|
9
|
+
|
|
10
|
+
const tsxBin = resolve(__dirname, '../node_modules/.bin/tsx')
|
|
11
|
+
const cliEntry = resolve(__dirname, '../src/cli.tsx')
|
|
12
|
+
|
|
13
|
+
// Strip: ["node", "bin/proc-dev", ...args]
|
|
14
|
+
const args = process.argv.slice(2)
|
|
15
|
+
|
|
16
|
+
const child = spawn(tsxBin, [cliEntry, ...args], {
|
|
17
|
+
stdio: 'inherit',
|
|
18
|
+
env: process.env,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
child.on('exit', (code) => process.exit(code ?? 1))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@process.co/element-dev-server",
|
|
3
|
-
"version": "0.0.1-test-
|
|
3
|
+
"version": "0.0.1-test-5",
|
|
4
4
|
"description": "Helper Library for developing elements for Process.co",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
".": "./dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"proc-dev": "
|
|
12
|
+
"proc-dev": "./bin/proc-dev"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"dist/*",
|
|
16
16
|
"src/*",
|
|
17
|
-
"
|
|
17
|
+
".process/*",
|
|
18
|
+
"bin/*"
|
|
18
19
|
],
|
|
19
20
|
"publishConfig": {
|
|
20
21
|
"access": "public",
|