You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

jw-gate

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jw-gate

Creates a "gate" with "locks." When all locks are open, the gate is open, useful for dealing with semi-random async events.

2.0.0
latest
Source
npmnpm
Version published
Weekly downloads
3
-40%
Maintainers
1
Weekly downloads
 
Created
Source

jw-gate

A reactive coordination library that manages multiple conditions through an event-driven "Gate" with independent "locks". Perfect for two key scenarios:

  • UI State Management - Track multiple async operations and show progress as each completes
  • Dynamic Condition Monitoring - React to conditions that change over time (IoT, sensors, resources)

Unlike promise-based coordination, jw-gate lets you respond immediately to individual condition changes rather than waiting for everything to complete at once.

Why jw-gate?

For UI Progress Tracking: Promise.all() only tells you when everything is done - you can't show individual completions. jw-gate lets you update your UI as each operation finishes.

For Dynamic Conditions: Traditional promises are one-shot, but real-world conditions change over time. jw-gate provides reactive coordination that responds immediately when conditions shift.

Features

  • 🎯 Track multiple async operations with individual progress updates
  • 🚪 Reactive coordination of changing conditions over time
  • 🔄 Event-driven architecture - respond immediately to state changes
  • ⏱️ Automatic timeout support for temporary conditions
  • 🔍 Comprehensive state monitoring and introspection
  • 🛡️ Error handling through events (no crashes)
  • 🌐 Works in both Node.js and browser environments
  • 📦 Zero dependencies

Installation

npm install jw-gate

Quick Start

UI Progress Tracking

const Gate = require('jw-gate');

// Track multiple file uploads
const uploadGate = new Gate(['file1', 'file2', 'file3'], true);

// Update UI when all files are complete
uploadGate.on('unlocked', () => {
  updateUI('All uploads complete! 🎉');
});

// Start uploads and update progress individually
uploadFile1().then(() => {
  updateUI('File 1 complete ✓');
  uploadGate.setLock('file1', false);
});

uploadFile2().then(() => {
  updateUI('File 2 complete ✓');
  uploadGate.setLock('file2', false);
});

uploadFile3().then(() => {
  updateUI('File 3 complete ✓');
  uploadGate.setLock('file3', false);
});

Dynamic Condition Monitoring

// Monitor changing conditions
const systemGate = new Gate(['network', 'power', 'sensors'], true);

// React immediately when all conditions are met
systemGate.on('unlocked', () => {
  console.log('System ready - starting operation');
  startOperation();
});

systemGate.on('locked', () => {
  console.log('Conditions changed - pausing operation');
  pauseOperation();
});

// Conditions change independently over time
networkMonitor.on('connected', () => systemGate.setLock('network', false));
networkMonitor.on('disconnected', () => systemGate.setLock('network', true));

powerMonitor.on('stable', () => systemGate.setLock('power', false));
powerMonitor.on('unstable', () => systemGate.setLock('power', true));

Common Examples

UI Progress Tracking

File Upload Dashboard

const uploadGate = new Gate(['validation', 'upload', 'processing'], true);

// Show progress as each step completes
uploadGate.on('unlocked', () => {
  showMessage('Upload complete! File is ready to use.');
  enableDownloadButton();
});

// Validate file
validateFile(file).then(valid => {
  if (valid) {
    showProgress('Validation complete ✓');
    uploadGate.setLock('validation', false);
  }
});

// Upload to server  
uploadToServer(file).then(() => {
  showProgress('Upload complete ✓');
  uploadGate.setLock('upload', false);
});

// Server processing
processOnServer(file).then(() => {
  showProgress('Processing complete ✓');
  uploadGate.setLock('processing', false);
});

Multi-Step Form Validation

const formGate = new Gate(['email', 'password', 'terms'], true);

formGate.on('unlocked', () => {
  enableSubmitButton();
  showMessage('Form ready for submission');
});

formGate.on('locked', () => {
  disableSubmitButton();
});

emailField.on('validated', () => {
  showCheckmark('email');
  formGate.setLock('email', false);
});

passwordField.on('validated', () => {
  showCheckmark('password');
  formGate.setLock('password', false);
});

termsCheckbox.on('checked', () => {
  showCheckmark('terms');
  formGate.setLock('terms', false);
});

Dynamic Condition Monitoring

Smart Device Control

const deviceGate = new Gate(['safety', 'network', 'power'], true);

deviceGate.on('unlocked', () => {
  console.log('Device activated - all systems go');
  device.start();
  statusLight.setGreen();
});

deviceGate.on('locked', () => {
  console.log('Safety conditions changed - device stopped');
  device.emergencyStop();
  statusLight.setRed();
});

// Sensors update conditions independently
safetySystem.on('safe', () => deviceGate.setLock('safety', false));
safetySystem.on('unsafe', () => deviceGate.setLock('safety', true));

networkMonitor.on('connected', () => deviceGate.setLock('network', false));
networkMonitor.on('disconnected', () => deviceGate.setLock('network', true));

powerMonitor.on('stable', () => deviceGate.setLock('power', false));
powerMonitor.on('fluctuation', () => deviceGate.setLock('power', true));

Resource-Aware Processing

const processingGate = new Gate(['cpu', 'memory', 'disk'], true);

processingGate.on('unlocked', () => {
  console.log('Resources available - starting batch job');
  startBatchProcessing();
});

processingGate.on('locked', () => {
  console.log('Resource constraints - pausing batch job');  
  pauseBatchProcessing();
});

// Resource monitors update conditions
cpuMonitor.on('available', () => processingGate.setLock('cpu', false));
cpuMonitor.on('busy', () => processingGate.setLock('cpu', true));

memoryMonitor.on('sufficient', () => processingGate.setLock('memory', false));
memoryMonitor.on('low', () => processingGate.setLock('memory', true));

diskMonitor.on('space', () => processingGate.setLock('disk', false));
diskMonitor.on('full', () => processingGate.setLock('disk', true));

API Reference

Constructor

new Gate(lockNames, initialState = false)
  • lockNames: Array of strings representing lock names
  • initialState: Boolean indicating initial state of locks (default: false = unlocked)

Event Management

gate.on(event, callback)    // Register event listener
gate.off(event, callback)   // Remove event listener

Events:

  • 'locked': Emitted when gate becomes locked (one or more locks engaged)
  • 'unlocked': Emitted when gate becomes unlocked (all locks disengaged)
  • 'error': Emitted when an error occurs

Lock Management

gate.setLock(lockName, state)              // Set lock state (true = locked)
gate.setLockWithTimeout(lock, state, ms)   // Set lock with automatic timeout
gate.resetAll(state)                       // Set all locks to same state

State Inspection

gate.getState()        // Get complete state object
gate.isUnlocked()      // Check if gate is currently unlocked
gate.getLockedCount()  // Count of currently locked locks
gate.getTotalLocks()   // Total number of locks

State Object

The getState() method returns:

{
  state: 'locked' | 'unlocked',
  locks: {
    [lockName: string]: boolean  // true = locked, false = unlocked
  },
  isLocked: boolean
}

Error Handling

All errors are emitted as events rather than thrown, preventing crashes:

gate.on('error', (errorMessage) => {
  console.error('Gate error:', errorMessage);
  // Handle error appropriately
});

Browser Support

Works in both Node.js and browser environments:

<script src="jw-gate.js"></script>
<script>
  const gate = new Gate(['condition1', 'condition2']);
  // Use normally
</script>

When NOT to Use jw-gate

  • Simple one-time coordination: Use Promise.all() if you don't need individual progress updates
  • Single async operation: Use async/await instead
  • Static boolean logic: Use regular conditionals instead

jw-gate excels when you need immediate feedback on individual condition changes or reactive coordination of changing conditions.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Keywords

async

FAQs

Package last updated on 23 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts