Enhance meet.sh and typings scripts: add typings watch scripts for CE and PRO, and improve flag handling in watch-with-typings-guard.mjs
This commit is contained in:
parent
a33d9d68ec
commit
56343e8f03
22
meet.sh
22
meet.sh
@ -120,7 +120,7 @@ show_help() {
|
||||
echo " Start development mode with watchers"
|
||||
echo
|
||||
echo -e " ${BLUE}start${NC}"
|
||||
echo " Start services in production or CI mode"
|
||||
echo " Start OpenVidu Meet in production or CI mode"
|
||||
echo -e " ${YELLOW}Options:${NC} --prod Start in production mode"
|
||||
echo -e " ${NC} --ci Start in CI mode"
|
||||
echo
|
||||
@ -376,10 +376,10 @@ add_common_dev_commands() {
|
||||
CMD_COLORS+=("bgRed.white")
|
||||
CMD_COMMANDS+=("npm --prefix $OV_COMPONENTS_DIR install && npm --prefix $OV_COMPONENTS_DIR run lib:serve")
|
||||
|
||||
# Typings watcher
|
||||
# Typings watcher. It generates the typings-ready.flag file when done for other watchers to wait on.
|
||||
CMD_NAMES+=("typings-ce")
|
||||
CMD_COLORS+=("bgGreen.black")
|
||||
CMD_COMMANDS+=("./scripts/dev/watch-typings.sh")
|
||||
CMD_COMMANDS+=("./scripts/dev/watch-typings-ce.sh")
|
||||
|
||||
# shared-meet-components watcher
|
||||
CMD_NAMES+=("shared-meet-components")
|
||||
@ -410,12 +410,12 @@ add_pro_commands() {
|
||||
|
||||
# Run backend-pro
|
||||
CMD_NAMES+=("backend-pro")
|
||||
CMD_COLORS+=("blue")
|
||||
CMD_COLORS+=("cyan")
|
||||
CMD_COMMANDS+=("node ./scripts/dev/watch-with-typings-guard.mjs 'pnpm run dev:pro-backend'")
|
||||
|
||||
# Watch backend-ce
|
||||
CMD_NAMES+=("backend-ce-watch")
|
||||
CMD_COLORS+=("cyan")
|
||||
CMD_COLORS+=("bgCyan.white")
|
||||
CMD_COMMANDS+=("node ./scripts/dev/watch-with-typings-guard.mjs 'pnpm run --filter @openvidu-meet/backend build:watch'")
|
||||
|
||||
# Run frontend-pro after components-angular and shared-meet-components are ready
|
||||
@ -423,10 +423,10 @@ add_pro_commands() {
|
||||
CMD_COLORS+=("magenta")
|
||||
CMD_COMMANDS+=("wait-on ${components_path} && wait-on ${shared_meet_components_path} && sleep 1 && node ./scripts/dev/watch-with-typings-guard.mjs 'pnpm run dev:pro-frontend'")
|
||||
|
||||
# Run @openvidu-meet-pro/typings watcher
|
||||
# Typings watcher for PRO edition. It generates the typings-ready.flag file when done for other watchers to wait on.
|
||||
CMD_NAMES+=("typings-pro")
|
||||
CMD_COLORS+=("brightGreen")
|
||||
CMD_COMMANDS+=("pnpm --filter @openvidu-meet-pro/typings run build:watch")
|
||||
CMD_COLORS+=("bgGreen.black")
|
||||
CMD_COMMANDS+=("./scripts/dev/watch-typings-pro.sh")
|
||||
}
|
||||
|
||||
# Helper: Add REST API docs and browser-sync commands
|
||||
@ -543,8 +543,8 @@ dev() {
|
||||
launch_dev_watchers "$edition" "$components_path"
|
||||
}
|
||||
|
||||
# Start services
|
||||
start_services() {
|
||||
# Start OpenVidu Meet services in prod or ci mode
|
||||
start() {
|
||||
MODE=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
@ -820,7 +820,7 @@ main() {
|
||||
dev
|
||||
;;
|
||||
start)
|
||||
start_services "$@"
|
||||
start "$@"
|
||||
;;
|
||||
start-testapp)
|
||||
start_testapp
|
||||
|
||||
@ -6,6 +6,7 @@ packages:
|
||||
- meet-ce/backend
|
||||
- meet-pro/frontend
|
||||
- meet-pro/backend
|
||||
- meet-pro/typings
|
||||
- testapp
|
||||
|
||||
ignoredBuiltDependencies:
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path to the flag file indicating typings are ready
|
||||
FLAG_PATH="./meet-ce/typings/dist/typings-ready.flag"
|
||||
|
||||
# Remove the flag file if it exists
|
||||
38
scripts/dev/watch-typings-pro.sh
Executable file
38
scripts/dev/watch-typings-pro.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path to the flag file indicating typings are ready
|
||||
FLAG_PATH="./meet-pro/typings/dist/typings-ready.flag"
|
||||
|
||||
# Remove the flag file if it exists
|
||||
rm -f $FLAG_PATH
|
||||
|
||||
# Create an empty directory for the flag file if it doesn't exist
|
||||
mkdir -p "$(dirname "$FLAG_PATH")"
|
||||
|
||||
echo "Starting typings watch mode..."
|
||||
echo "Waiting for initial compilation..."
|
||||
|
||||
# Run tsc in watch mode
|
||||
pnpm --filter @openvidu-meet-pro/typings run dev | while read line; do
|
||||
echo "$line"
|
||||
|
||||
# Check for compilation start (remove flag to signal "not ready")
|
||||
if echo "$line" | grep -q "File change detected. Starting incremental compilation"; then
|
||||
rm -f $FLAG_PATH
|
||||
echo "Typings recompiling..."
|
||||
fi
|
||||
|
||||
# Check for successful compilation (create flag to signal "ready")
|
||||
if echo "$line" | grep -q "Found 0 errors"; then
|
||||
# Add small delay to ensure all files are written to disk
|
||||
sleep 0.2
|
||||
touch $FLAG_PATH
|
||||
echo "✅ Typings ready!"
|
||||
fi
|
||||
|
||||
# Check for compilation errors
|
||||
if echo "$line" | grep -q "error TS"; then
|
||||
rm -f $FLAG_PATH
|
||||
echo "❌ Typings compilation failed!"
|
||||
fi
|
||||
done
|
||||
@ -12,8 +12,11 @@ const __dirname = dirname(__filename);
|
||||
// Configuration
|
||||
const CE_TYPINGS_FLAG_PATH = resolve(__dirname, '../../meet-ce/typings/dist/typings-ready.flag');
|
||||
const CE_TYPINGS_DIST = resolve(__dirname, '../../meet-ce/typings/dist');
|
||||
const PRO_TYPINGS_FLAG_PATH = resolve(__dirname, '../../meet-pro/typings/dist/typings-ready.flag');
|
||||
const PRO_TYPINGS_DIST = resolve(__dirname, '../../meet-pro/typings/dist');
|
||||
const DEBOUNCE_MS = 500; // Wait 500ms after flag appears before restarting
|
||||
const KILL_TIMEOUT_MS = 5000; // Max time to wait for process to die
|
||||
const POLL_DIR_MS = 1000; // Polling interval for directories that don't yet exist
|
||||
|
||||
// Get command from arguments
|
||||
const command = process.argv.slice(2).join(' ');
|
||||
@ -25,7 +28,8 @@ if (!command) {
|
||||
}
|
||||
|
||||
let childProcess = null;
|
||||
let isTypingsReady = false;
|
||||
// We'll support multiple targets (CE and PRO). Each target has its own ready state.
|
||||
const targets = [];
|
||||
let pendingRestart = null;
|
||||
let hasStartedOnce = false;
|
||||
let isKilling = false;
|
||||
@ -34,9 +38,12 @@ let isKilling = false;
|
||||
* Start the child process
|
||||
*/
|
||||
async function startProcess() {
|
||||
if (!isTypingsReady) {
|
||||
// Process should start only when all required targets report ready
|
||||
const allReady = targets.length > 0 && targets.every((t) => t.isReady);
|
||||
if (!allReady) {
|
||||
if (!hasStartedOnce) {
|
||||
console.log('Waiting for typings to be ready...');
|
||||
const names = targets.map((t) => t.name).join(', ');
|
||||
console.log(`Waiting for typings to be ready for: ${names}...`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -155,86 +162,174 @@ function scheduleRestart() {
|
||||
* Check if typings are ready
|
||||
*/
|
||||
function checkTypingsReady() {
|
||||
const wasReady = isTypingsReady;
|
||||
isTypingsReady = existsSync(CE_TYPINGS_FLAG_PATH);
|
||||
|
||||
if (!wasReady && isTypingsReady) {
|
||||
console.log('✅ Typings are ready!');
|
||||
scheduleRestart();
|
||||
} else if (wasReady && !isTypingsReady) {
|
||||
console.log('Typings recompiling... (process will restart when ready)');
|
||||
let changed = false;
|
||||
for (const t of targets) {
|
||||
const wasReady = t.isReady;
|
||||
t.isReady = existsSync(t.flagPath);
|
||||
if (!wasReady && t.isReady) {
|
||||
console.log(`✅ Typings ready for ${t.name}!`);
|
||||
changed = true;
|
||||
} else if (wasReady && !t.isReady) {
|
||||
console.log(`Typings recompiling for ${t.name}... (process will restart when ready)`);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isTypingsReady;
|
||||
if (changed) {
|
||||
scheduleRestart();
|
||||
}
|
||||
|
||||
return targets.every((t) => t.isReady);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch the flag file
|
||||
*/
|
||||
function watchFlag() {
|
||||
console.log(`Watching typings flag: ${CE_TYPINGS_FLAG_PATH}`);
|
||||
/**
|
||||
* Create a watcher for a single target that watches its flag dir and dist dir.
|
||||
* If the directories don't exist yet, we poll until they appear then create watchers.
|
||||
*/
|
||||
function watchTarget(target) {
|
||||
console.log(`Setting up watchers for ${target.name}`);
|
||||
|
||||
// Initial check
|
||||
checkTypingsReady();
|
||||
|
||||
// Watch the parent directory of the flag
|
||||
const flagDir = dirname(CE_TYPINGS_FLAG_PATH);
|
||||
const flagDir = dirname(target.flagPath);
|
||||
const distDir = target.distPath;
|
||||
|
||||
const watcher = watch(flagDir, { recursive: false }, (eventType, filename) => {
|
||||
function createWatchers() {
|
||||
try {
|
||||
if (!target.flagWatcher && existsSync(flagDir)) {
|
||||
target.flagWatcher = watch(flagDir, { recursive: false }, (eventType, filename) => {
|
||||
if (filename === 'typings-ready.flag') {
|
||||
checkTypingsReady();
|
||||
}
|
||||
});
|
||||
|
||||
watcher.on('error', (error) => {
|
||||
console.error('❌ Watcher error:', error);
|
||||
target.flagWatcher.on('error', (error) => {
|
||||
console.error(`❌ Watcher error for ${target.name} flag:`, error);
|
||||
});
|
||||
}
|
||||
|
||||
if (!target.distWatcher && existsSync(distDir)) {
|
||||
target.distWatcher = watch(distDir, { recursive: true }, (eventType, filename) => {
|
||||
if (filename === 'typings-ready.flag') return;
|
||||
if (childProcess && target.isReady) {
|
||||
console.log(`Detected change in ${target.name} typings: ${filename} (will restart when compilation finishes)`);
|
||||
}
|
||||
});
|
||||
|
||||
return watcher;
|
||||
target.distWatcher.on('error', (error) => {
|
||||
console.error(`❌ Watcher error for ${target.name} dist:`, error);
|
||||
});
|
||||
}
|
||||
|
||||
// If we have at least one watcher, stop polling
|
||||
if ((target.flagWatcher || target.distWatcher) && target.poller) {
|
||||
clearInterval(target.poller);
|
||||
target.poller = null;
|
||||
}
|
||||
} catch (err) {
|
||||
// Rare race - ignore and keep polling
|
||||
// console.error(`Error creating watcher for ${target.name}:`, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// If directories are already present, create watchers immediately
|
||||
if (existsSync(flagDir) || existsSync(distDir)) {
|
||||
createWatchers();
|
||||
}
|
||||
|
||||
// Start polling for directory creation if watchers not yet created
|
||||
if (!target.flagWatcher && !target.distWatcher) {
|
||||
target.poller = setInterval(() => {
|
||||
createWatchers();
|
||||
}, POLL_DIR_MS);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (target.flagWatcher) {
|
||||
try { target.flagWatcher.close(); } catch (e) {}
|
||||
target.flagWatcher = null;
|
||||
}
|
||||
if (target.distWatcher) {
|
||||
try { target.distWatcher.close(); } catch (e) {}
|
||||
target.distWatcher = null;
|
||||
}
|
||||
if (target.poller) {
|
||||
clearInterval(target.poller);
|
||||
target.poller = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch typings/dist for changes (to trigger restart when ready)
|
||||
*/
|
||||
function watchTypingsDist() {
|
||||
console.log(`Watching typings dist: ${CE_TYPINGS_DIST}`);
|
||||
// Setup targets depending on the provided command. If command mentions meet-pro we include PRO
|
||||
function setupTargetsFromCommand(cmd) {
|
||||
const normalized = (cmd || '').toLowerCase();
|
||||
const usePro = /\b(?:meet-pro|pro)\b/.test(normalized);
|
||||
|
||||
const watcher = watch(CE_TYPINGS_DIST, { recursive: true }, (eventType, filename) => {
|
||||
// Ignore the flag file itself (handled by watchFlag)
|
||||
if (filename === 'typings-ready.flag') {
|
||||
return;
|
||||
// Always include CE by default unless the command explicitly targets only pro and not CE.
|
||||
// If both are mentioned include both.
|
||||
const includeCE = true; // keep CE by default
|
||||
|
||||
if (includeCE) {
|
||||
targets.push({
|
||||
name: 'CE',
|
||||
flagPath: CE_TYPINGS_FLAG_PATH,
|
||||
distPath: CE_TYPINGS_DIST,
|
||||
isReady: false,
|
||||
flagWatcher: null,
|
||||
distWatcher: null,
|
||||
poller: null,
|
||||
});
|
||||
}
|
||||
|
||||
// Only log changes, but don't restart yet
|
||||
// Restart will happen when flag is recreated (via checkTypingsReady)
|
||||
if (childProcess && isTypingsReady) {
|
||||
console.log(`Detected change in typings: ${filename} (will restart when compilation finishes)`);
|
||||
if (usePro) {
|
||||
targets.push({
|
||||
name: 'PRO',
|
||||
flagPath: PRO_TYPINGS_FLAG_PATH,
|
||||
distPath: PRO_TYPINGS_DIST,
|
||||
isReady: false,
|
||||
flagWatcher: null,
|
||||
distWatcher: null,
|
||||
poller: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watcher.on('error', (error) => {
|
||||
console.error('❌ Watcher error:', error);
|
||||
});
|
||||
|
||||
return watcher;
|
||||
// If the command only mentions PRO and you don't want CE, you could tweak logic here.
|
||||
}
|
||||
|
||||
// Start watching
|
||||
const flagWatcher = watchFlag();
|
||||
const distWatcher = watchTypingsDist();
|
||||
// Setup targets based on command
|
||||
setupTargetsFromCommand(command);
|
||||
|
||||
// Create watchers for each target and keep cleanup functions
|
||||
const cleanupFns = [];
|
||||
for (const t of targets) {
|
||||
const cleanup = watchTarget(t);
|
||||
cleanupFns.push(cleanup);
|
||||
}
|
||||
|
||||
// Kick an initial check/start attempt (in case flags already ready)
|
||||
checkTypingsReady();
|
||||
|
||||
// Cleanup on exit
|
||||
process.on('SIGINT', async () => {
|
||||
async function doCleanupAndExit(code = 0) {
|
||||
console.log('\n🛑 Stopping...');
|
||||
await killProcess();
|
||||
flagWatcher.close();
|
||||
distWatcher.close();
|
||||
process.exit(0);
|
||||
for (const fn of cleanupFns) {
|
||||
try { fn(); } catch (e) {}
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
await doCleanupAndExit(0);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
await killProcess();
|
||||
flagWatcher.close();
|
||||
distWatcher.close();
|
||||
process.exit(0);
|
||||
await doCleanupAndExit(0);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user