Exécutez des serveurs Web dans des navigateurs Web via WebRTC
Smoke permet aux navigateurs d'exécuter des micro-serveurs Web via WebRTC
import { Network } from '@sinclair/smoke'
// ------------------------------------------------------------------
//
// Create a Virtual Network
//
// ------------------------------------------------------------------
const { Http } = new Network ( )
// ------------------------------------------------------------------
//
// Create a Http Listener on a Virtual Port
//
// ------------------------------------------------------------------
Http . listen ( { port : 5000 } , request => new Response ( 'hello webrtc' ) )
// ------------------------------------------------------------------
//
// Fetch data over WebRTC
//
// ------------------------------------------------------------------
const text = Http . fetch ( 'http://localhost:5000' ) . then ( r => r . text ( ) )
$ npm install @sinclair/smoke
Smoke est un cadre expérimental de mise en réseau et de stockage de navigateur qui fournit une émulation Http, Tcp et WebSocket sur WebRTC et un stockage de fichiers volumineux via IndexedDB. Il constitue la base du développement de services Web peer to peer dans le navigateur, chaque navigateur étant accessible via un réseau virtuel contrôlé par une application.
Smoke remodèle WebRTC en interfaces compatibles WinterCG permettant aux applications de serveur Web traditionnelles d'être portables entre les environnements de serveur et de navigateur. Il est développé pour prendre en charge des architectures logicielles alternatives dans lesquelles les services centrés sur l'utilisateur peuvent être éloignés du cloud et exécutés peer to peer dans le navigateur.
Licence MIT
Les API de mise en réseau Smoke sont fournies au moyen d'objets réseau. Un objet Réseau représente une connexion active à un Hub de signalisation partagé et expose les fonctionnalités Http, Net et Media utilisées pour communiquer avec d'autres objets Réseau connectés au même Hub.
import { Network , Hubs } from '@sinclair/smoke'
const { Http , Net , Media , Hub } = new Network ( { hub : new Hubs . Private ( ) } )
const address = await Hub . address ( ) // The address of this Network object.
Un hub privé est un relais en mémoire qui transmet les messages WebRTC ICE via l'API BroadcastChannel du navigateur. Un hub privé ne peut relayer les messages que vers la page et les autres onglets exécutés au sein du même processus de navigateur. Étant donné que les hubs privés ne peuvent pas faciliter les connexions établies en dehors de la page actuelle, celle-ci est considérée comme privée. Ce hub est la valeur par défaut.
import { Network , Hubs } from '@sinclair/smoke'
const { Http } = new Network ( { hub : new Hubs . Private ( ) } )
La mise en œuvre de ce hub est actuellement en attente.
import { Network , Hubs } from '@sinclair/smoke'
const { Http } = new Network ( { hub : new Hubs . Public ( 'ws://server/hub' ) } )
L'API HTTP prend en charge l'écoute et la récupération HTTP via WebRTC. Il fournit également une émulation WebSocket.
const { Http } = new Network ( )
Utilisez la fonction d'écoute pour recevoir des requêtes HTTP de homologues distants.
Http . listen ( { port : 5000 } , request => new Response ( 'hello' ) )
Utilisez la fonction fetch pour envoyer une requête HTTP à des homologues distants.
const response = await Http . fetch ( 'http://localhost:5000' )
const message = await response . text ( )
Utilisez la fonction de mise à niveau pour convertir une requête Http en WebSocket
Http . listen ( { port : 5000 } , request => Http . upgrade ( request , ( socket ) => socket . send ( 'hello' ) ) )
Utilisez la fonction de connexion pour vous connecter à un serveur WebSocket distant.
const socket = await Http . connect ( 'ws://localhost:5000' )
socket . on ( 'message' , ( event ) => console . log ( event . data ) )
socket . on ( 'error' , ( event ) => console . log ( event ) )
socket . on ( 'close' , ( event ) => console . log ( event ) )
L'API Net fournit une émulation TCP sur RTCDataChannel
const { Net } = new Network ( )
Utilisez la fonction d'écoute pour accepter une socket entrante.
Net . listen ( { port : 5000 } , async socket => {
const data = await socket . read ( )
await socket . write ( data )
await socket . close ( )
} )
Utilisez la fonction de connexion pour établir une connexion Internet avec un écouteur distant.
const socket = await Net . connect ( { hostname : 'localhost' , port : 5000 } )
await socket . write ( new Uint8Array ( 1000 ) )
const data = await socket . read ( ) // Uint8Array()
const end = await socket . read ( ) // null
L'API Media fournit des fonctionnalités pour envoyer et recevoir des objets MediaStream via WebRTC.
const { Media } = new Network ( )
Utilisez la fonction d'écoute pour écouter les objets MediaStream entrants
Media . listen ( { port : 6000 } , ( receiver ) => {
const video = document . createElement ( 'video' )
video . srcObject = receiver . mediastream
video . play ( )
document . body . appendChild ( video )
receiver . on ( 'close' , ( ) => document . removeChild ( video ) )
} )
Utilisez la fonction d'envoi pour envoyer un MediaStream à un auditeur
const sender = await Media . send ( { hostname : 'localhost' , port : 6000 } , new MediaStream ( [ ... ] ) )
sender . close ( ) // stop sending live media
Utilisez la fonction audio pour créer une source audio diffusable.
const audio = Media . audio ( { src : './audio.mp3' } )
const sender = Media . send ( { hostname : 'localhost' , port : 6000 } , audio . mediastream )
Utilisez la fonction vidéo pour créer une source vidéo diffusable.
const video = Media . video ( { src : './video.mp4' } )
const sender = Media . send ( { hostname : 'localhost' , port : 6000 } , video . mediastream )
Utilisez la fonction pattern pour générer un modèle de test MediaStream. Cette fonction peut être utile pour tester la diffusion multimédia en direct sans caméras Web ni autres sources multimédias.
const pattern = Media . pattern ( )
const sender = Media . send ( { port : 5000 } , pattern . mediastream )
Smoke fournit un système de fichiers hiérarchique capable de stocker des fichiers volumineux dans le navigateur. Le système de fichiers est soutenu par IndexedDB et prend en charge la lecture et l'écriture en streaming, l'énumération de répertoires, la copie, le déplacement, le renommage ainsi que les événements de surveillance de fichiers et de répertoires. Il est conçu pour agir comme un magasin de fichiers statiques pour les services réseau, mais peut être utilisé comme système de fichiers à usage général pour les applications nécessitant de stocker des fichiers volumineux dans le navigateur.
Utilisez la fonction open pour ouvrir un système de fichiers avec le nom de base de données donné. Si la base de données n'existe pas, elle est créée.
import { FileSystem } from '@sinclair/smoke'
const Fs = await FileSystem . open ( '<database-name>' )
Utilisez la fonction stat pour renvoyer des informations sur un fichier ou un répertoire.
const stat = await Fs . write ( '/path/file.txt' )
Utilisez la fonction exist pour vérifier qu'un chemin existe.
const exists = await Fs . exists ( '/path/file.txt' )
Utilisez la fonction mkdir pour créer un répertoire.
await Fs . mkdir ( '/media/videos' )
Utilisez la fonction readdir pour renvoyer des objets statistiques pour le chemin de répertoire donné.
const stats = await Fs . readdir ( '/media/videos' )
Utilisez la fonction blob pour renvoyer un objet Blob vers un chemin de fichier.
const blob = await Fs . readdir ( '/video.mp4' )
const url = URL . createObjectUrl ( blob )
Utilisez les fonctions write et writeText pour écrire le contenu du fichier.
await Fs . write ( '/path/file.dat' , new Uint8Array ( [ 1 , 2 , 3 , 4 ] ) )
await Fs . writeText ( '/path/file.txt' , 'hello world' )
Utilisez les fonctions read et readText pour lire le contenu d'un fichier.
const buffer = await fs . read ( '/path/file.dat' )
const content = await Fs . readText ( '/path/file.txt' )
Utilisez la fonction de suppression pour supprimer un fichier ou un répertoire.
await Fs . delete ( '/path/file.txt' )
Utilisez la fonction renommer pour renommer un fichier ou un répertoire.
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . rename ( '/path/fileA.txt' , 'fileB.txt' )
Utilisez la fonction de copie pour copier un fichier ou un répertoire dans un répertoire cible.
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . copy ( '/path/fileA.txt' , '/backup' )
Utilisez la fonction move pour déplacer un fichier ou un répertoire vers un répertoire cible.
await Fs . writeText ( '/path/fileA.txt' , '...' )
await Fs . move ( '/path/fileA.txt' , '/backup' )
Utilisez la fonction de surveillance pour surveiller les événements de fichiers et de répertoires.
Fs . watch ( '/dir' , event => console . log ( event ) )
Smoke est ouvert à la contribution de la communauté. Veuillez vous assurer de soumettre un problème ouvert avant de soumettre votre demande de tirage. Le projet Smoke préfère une discussion communautaire ouverte avant d'accepter de nouvelles fonctionnalités.