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 " Start development mode with watchers"
|
||||||
echo
|
echo
|
||||||
echo -e " ${BLUE}start${NC}"
|
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 " ${YELLOW}Options:${NC} --prod Start in production mode"
|
||||||
echo -e " ${NC} --ci Start in CI mode"
|
echo -e " ${NC} --ci Start in CI mode"
|
||||||
echo
|
echo
|
||||||
@ -376,10 +376,10 @@ add_common_dev_commands() {
|
|||||||
CMD_COLORS+=("bgRed.white")
|
CMD_COLORS+=("bgRed.white")
|
||||||
CMD_COMMANDS+=("npm --prefix $OV_COMPONENTS_DIR install && npm --prefix $OV_COMPONENTS_DIR run lib:serve")
|
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_NAMES+=("typings-ce")
|
||||||
CMD_COLORS+=("bgGreen.black")
|
CMD_COLORS+=("bgGreen.black")
|
||||||
CMD_COMMANDS+=("./scripts/dev/watch-typings.sh")
|
CMD_COMMANDS+=("./scripts/dev/watch-typings-ce.sh")
|
||||||
|
|
||||||
# shared-meet-components watcher
|
# shared-meet-components watcher
|
||||||
CMD_NAMES+=("shared-meet-components")
|
CMD_NAMES+=("shared-meet-components")
|
||||||
@ -410,12 +410,12 @@ add_pro_commands() {
|
|||||||
|
|
||||||
# Run backend-pro
|
# Run backend-pro
|
||||||
CMD_NAMES+=("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'")
|
CMD_COMMANDS+=("node ./scripts/dev/watch-with-typings-guard.mjs 'pnpm run dev:pro-backend'")
|
||||||
|
|
||||||
# Watch backend-ce
|
# Watch backend-ce
|
||||||
CMD_NAMES+=("backend-ce-watch")
|
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'")
|
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
|
# Run frontend-pro after components-angular and shared-meet-components are ready
|
||||||
@ -423,10 +423,10 @@ add_pro_commands() {
|
|||||||
CMD_COLORS+=("magenta")
|
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'")
|
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_NAMES+=("typings-pro")
|
||||||
CMD_COLORS+=("brightGreen")
|
CMD_COLORS+=("bgGreen.black")
|
||||||
CMD_COMMANDS+=("pnpm --filter @openvidu-meet-pro/typings run build:watch")
|
CMD_COMMANDS+=("./scripts/dev/watch-typings-pro.sh")
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper: Add REST API docs and browser-sync commands
|
# Helper: Add REST API docs and browser-sync commands
|
||||||
@ -543,8 +543,8 @@ dev() {
|
|||||||
launch_dev_watchers "$edition" "$components_path"
|
launch_dev_watchers "$edition" "$components_path"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start services
|
# Start OpenVidu Meet services in prod or ci mode
|
||||||
start_services() {
|
start() {
|
||||||
MODE=""
|
MODE=""
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
@ -820,7 +820,7 @@ main() {
|
|||||||
dev
|
dev
|
||||||
;;
|
;;
|
||||||
start)
|
start)
|
||||||
start_services "$@"
|
start "$@"
|
||||||
;;
|
;;
|
||||||
start-testapp)
|
start-testapp)
|
||||||
start_testapp
|
start_testapp
|
||||||
|
|||||||
@ -6,6 +6,7 @@ packages:
|
|||||||
- meet-ce/backend
|
- meet-ce/backend
|
||||||
- meet-pro/frontend
|
- meet-pro/frontend
|
||||||
- meet-pro/backend
|
- meet-pro/backend
|
||||||
|
- meet-pro/typings
|
||||||
- testapp
|
- testapp
|
||||||
|
|
||||||
ignoredBuiltDependencies:
|
ignoredBuiltDependencies:
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Path to the flag file indicating typings are ready
|
||||||
FLAG_PATH="./meet-ce/typings/dist/typings-ready.flag"
|
FLAG_PATH="./meet-ce/typings/dist/typings-ready.flag"
|
||||||
|
|
||||||
# Remove the flag file if it exists
|
# 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
|
// Configuration
|
||||||
const CE_TYPINGS_FLAG_PATH = resolve(__dirname, '../../meet-ce/typings/dist/typings-ready.flag');
|
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 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 DEBOUNCE_MS = 500; // Wait 500ms after flag appears before restarting
|
||||||
const KILL_TIMEOUT_MS = 5000; // Max time to wait for process to die
|
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
|
// Get command from arguments
|
||||||
const command = process.argv.slice(2).join(' ');
|
const command = process.argv.slice(2).join(' ');
|
||||||
@ -25,7 +28,8 @@ if (!command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let childProcess = null;
|
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 pendingRestart = null;
|
||||||
let hasStartedOnce = false;
|
let hasStartedOnce = false;
|
||||||
let isKilling = false;
|
let isKilling = false;
|
||||||
@ -34,9 +38,12 @@ let isKilling = false;
|
|||||||
* Start the child process
|
* Start the child process
|
||||||
*/
|
*/
|
||||||
async function startProcess() {
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,86 +162,174 @@ function scheduleRestart() {
|
|||||||
* Check if typings are ready
|
* Check if typings are ready
|
||||||
*/
|
*/
|
||||||
function checkTypingsReady() {
|
function checkTypingsReady() {
|
||||||
const wasReady = isTypingsReady;
|
let changed = false;
|
||||||
isTypingsReady = existsSync(CE_TYPINGS_FLAG_PATH);
|
for (const t of targets) {
|
||||||
|
const wasReady = t.isReady;
|
||||||
if (!wasReady && isTypingsReady) {
|
t.isReady = existsSync(t.flagPath);
|
||||||
console.log('✅ Typings are ready!');
|
if (!wasReady && t.isReady) {
|
||||||
scheduleRestart();
|
console.log(`✅ Typings ready for ${t.name}!`);
|
||||||
} else if (wasReady && !isTypingsReady) {
|
changed = true;
|
||||||
console.log('Typings recompiling... (process will restart when ready)');
|
} 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
|
* 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
|
// Initial check
|
||||||
checkTypingsReady();
|
checkTypingsReady();
|
||||||
|
|
||||||
// Watch the parent directory of the flag
|
const flagDir = dirname(target.flagPath);
|
||||||
const flagDir = dirname(CE_TYPINGS_FLAG_PATH);
|
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') {
|
if (filename === 'typings-ready.flag') {
|
||||||
checkTypingsReady();
|
checkTypingsReady();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watcher.on('error', (error) => {
|
target.flagWatcher.on('error', (error) => {
|
||||||
console.error('❌ Watcher 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)
|
* Watch typings/dist for changes (to trigger restart when ready)
|
||||||
*/
|
*/
|
||||||
function watchTypingsDist() {
|
// Setup targets depending on the provided command. If command mentions meet-pro we include PRO
|
||||||
console.log(`Watching typings dist: ${CE_TYPINGS_DIST}`);
|
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) => {
|
// Always include CE by default unless the command explicitly targets only pro and not CE.
|
||||||
// Ignore the flag file itself (handled by watchFlag)
|
// If both are mentioned include both.
|
||||||
if (filename === 'typings-ready.flag') {
|
const includeCE = true; // keep CE by default
|
||||||
return;
|
|
||||||
|
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
|
if (usePro) {
|
||||||
// Restart will happen when flag is recreated (via checkTypingsReady)
|
targets.push({
|
||||||
if (childProcess && isTypingsReady) {
|
name: 'PRO',
|
||||||
console.log(`Detected change in typings: ${filename} (will restart when compilation finishes)`);
|
flagPath: PRO_TYPINGS_FLAG_PATH,
|
||||||
|
distPath: PRO_TYPINGS_DIST,
|
||||||
|
isReady: false,
|
||||||
|
flagWatcher: null,
|
||||||
|
distWatcher: null,
|
||||||
|
poller: null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
watcher.on('error', (error) => {
|
// If the command only mentions PRO and you don't want CE, you could tweak logic here.
|
||||||
console.error('❌ Watcher error:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
return watcher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start watching
|
// Setup targets based on command
|
||||||
const flagWatcher = watchFlag();
|
setupTargetsFromCommand(command);
|
||||||
const distWatcher = watchTypingsDist();
|
|
||||||
|
// 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
|
// Cleanup on exit
|
||||||
process.on('SIGINT', async () => {
|
async function doCleanupAndExit(code = 0) {
|
||||||
console.log('\n🛑 Stopping...');
|
console.log('\n🛑 Stopping...');
|
||||||
await killProcess();
|
await killProcess();
|
||||||
flagWatcher.close();
|
for (const fn of cleanupFns) {
|
||||||
distWatcher.close();
|
try { fn(); } catch (e) {}
|
||||||
process.exit(0);
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
await doCleanupAndExit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGTERM', async () => {
|
process.on('SIGTERM', async () => {
|
||||||
await killProcess();
|
await doCleanupAndExit(0);
|
||||||
flagWatcher.close();
|
|
||||||
distWatcher.close();
|
|
||||||
process.exit(0);
|
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user