aotrautils 0.0.1476 → 0.0.1477

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- /*utils COMMONS library associated with aotra version : «1_29072022-2359 (26/04/2025-13:40:57)»*/
3
+ /*utils COMMONS library associated with aotra version : «1_29072022-2359 (26/04/2025-16:15:49)»*/
4
4
  /*-----------------------------------------------------------------------------*/
5
5
 
6
6
 
@@ -4894,7 +4894,7 @@ AOTRAUTILS_LIB_IS_LOADED=true;
4894
4894
 
4895
4895
 
4896
4896
 
4897
- /*utils CLIENT library associated with aotra version : «1_29072022-2359 (26/04/2025-13:40:57)»*/
4897
+ /*utils CLIENT library associated with aotra version : «1_29072022-2359 (26/04/2025-16:15:49)»*/
4898
4898
  /*-----------------------------------------------------------------------------*/
4899
4899
  /* ## Utility global methods in a browser (htmljs) client environment.
4900
4900
  *
@@ -13466,7 +13466,7 @@ getAORTACClient=function(clientId=getUUID(), serverNodeOrigin="ws://127.0.0.1:40
13466
13466
 
13467
13467
 
13468
13468
 
13469
- /*utils GEOMETRY library associated with aotra version : «1_29072022-2359 (26/04/2025-13:40:57)»*/
13469
+ /*utils GEOMETRY library associated with aotra version : «1_29072022-2359 (26/04/2025-16:15:49)»*/
13470
13470
  /*-----------------------------------------------------------------------------*/
13471
13471
 
13472
13472
 
@@ -14705,7 +14705,7 @@ function rayVsUnitSphereClosestPoint(p, r) {
14705
14705
  // MUST REMAIN AT THE END OF THIS LIBRARY FILE !
14706
14706
 
14707
14707
  AOTRAUTILS_GEOMETRY_LIB_IS_LOADED=true;
14708
- /*utils AI library associated with aotra version : «1_29072022-2359 (26/04/2025-13:40:57)»*/
14708
+ /*utils AI library associated with aotra version : «1_29072022-2359 (26/04/2025-16:15:49)»*/
14709
14709
  /*-----------------------------------------------------------------------------*/
14710
14710
 
14711
14711
 
@@ -14851,11 +14851,11 @@ getOpenAIAPIClient=(modelName, apiURL, agentRole, defaultPrompt)=>{
14851
14851
 
14852
14852
 
14853
14853
 
14854
- /*utils SERVER library associated with aotra version : «1_29072022-2359 (26/04/2025-13:40:57)»*/
14854
+ /*utils CONSOLE library associated with aotra version : «1_29072022-2359 (26/04/2025-16:15:49)»*/
14855
14855
  /*-----------------------------------------------------------------------------*/
14856
14856
 
14857
14857
 
14858
- /* ## Utility global methods in a javascript, console (nodejs) server, or vanilla javascript with no browser environment.
14858
+ /* ## Utility global methods in a javascript, console (nodejs) or vanilla javascript with no browser environment.
14859
14859
  *
14860
14860
  * This set of methods gathers utility generic-purpose methods usable in any JS project.
14861
14861
  * Several authors of snippets published freely on the Internet contributed to this library.
@@ -15189,7 +15189,6 @@ WebsocketImplementation={
15189
15189
  throw new Error("ERROR : SERVER : Server launch is not supported in a non-nodejs context for any implementation.");
15190
15190
  }
15191
15191
 
15192
-
15193
15192
 
15194
15193
  // TODO : FIXME : Use one single interface !
15195
15194
  // NODE SERVER MODE ONLY :
@@ -15215,322 +15214,20 @@ WebsocketImplementation={
15215
15214
  }
15216
15215
 
15217
15216
  serverSocket.on("error",(error)=>{
15218
-
15219
15217
  // TRACE
15220
15218
  lognow("ERROR : An error occurred when trying to start the server : ",error);
15221
15219
 
15222
15220
  });
15223
15221
 
15224
15222
  // NODE SERVER INSTANCE :
15225
- const nodeServerInstance={
15226
-
15227
- onClientLostListeners:[],
15228
-
15229
- clientPingIntervalMillis:5000,
15230
- setPingPongTimeout:(clientPingIntervalMillis)=>{
15231
- nodeServerInstance.clientPingIntervalMillis=clientPingIntervalMillis;
15232
- return nodeServerInstance;
15233
- },
15234
-
15235
- // clientsSockets:[],
15236
- serverSocket:serverSocket,
15237
- listenableServer:listenableServer,
15238
-
15239
- receptionEntryPoints:[],
15240
-
15241
- close:(doOnCloseServer)=>{
15242
- if(!nodeServerInstance.serverSocket) return;
15243
- nodeServerInstance.serverSocket.close(()=>{
15244
- if(!nodeServerInstance.listenableServer) return;
15245
- nodeServerInstance.listenableServer.close(doOnCloseServer);
15246
- });
15247
- },
15248
-
15249
- receive:(channelNameParam, doOnIncomingMessage, clientsRoomsTag=null)=>{
15250
-
15251
- // DBG
15252
- lognow("(SERVER) Registering receive for «"+channelNameParam+"»...");
15253
-
15254
-
15255
-
15256
- const receptionEntryPoint={
15257
- channelName:channelNameParam,
15258
- clientsRoomsTag:clientsRoomsTag,
15259
- execute:(eventOrMessage, clientSocketParam)=>{
15260
-
15261
- // With «ws» library we have no choive than register message events inside a «connection» event !
15262
-
15263
- // // DBG
15264
- // lognow("(SERVER) RECEIVED SOMETHING FROM CLIENT...", eventOrMessage.data);
15265
-
15266
- // dataWrapped=parseJSON(dataWrapped);
15267
- // dataWrapped=getAt(dataWrapped,0);// We get the root element
15268
-
15269
-
15270
- const dataWrapped=WebsocketImplementation.getMessageDataBothImplementations(eventOrMessage);
15271
-
15272
-
15273
- // Channel information is stored in exchanged data :
15274
- if(dataWrapped.channelName!==receptionEntryPoint.channelName) return;
15275
-
15276
-
15277
- // // DBG
15278
- // lognow("(SERVER) ENTRY POINT IS OF THE RIGHT CHANNEL:", receptionEntryPoint.channelName);
15279
-
15280
-
15281
- // TODO : FIXME : Use one single interface !
15282
- // Room information is stored in client socket object :
15283
- const isClientInRoom=WebsocketImplementation.isInRoom(clientSocketParam, receptionEntryPoint.clientsRoomsTag);
15284
-
15285
- // DBG
15286
- lognow("(SERVER) isClientInRoom:",isClientInRoom);
15287
-
15288
- if(!isClientInRoom) return;
15289
-
15290
- if(doOnIncomingMessage){
15291
- // DBG
15292
- lognow("(SERVER) doOnIncomingMessage:");
15293
- doOnIncomingMessage(dataWrapped.data, clientSocketParam);
15294
- }
15295
-
15296
- },
15297
- };
15298
-
15299
-
15300
- ///!!!
15301
- nodeServerInstance.receptionEntryPoints.push(receptionEntryPoint);
15302
-
15303
- // SPECIAL FOR THE SOCKETIO IMPLEMENTATION :
15304
- if(WebsocketImplementation.useSocketIOImplementation){
15305
- const channelName=receptionEntryPoint.channelName;
15306
- clientSocket.on(channelName, (eventOrMessage)=>{
15307
- receptionEntryPoint.execute(eventOrMessage, clientSocket);
15308
- });
15309
- }
15310
-
15311
-
15312
- // // DBG
15313
- // console.log("ADD RECEPTION ENTRY POINT channelName:«"+channelName+"»! nodeServerInstance.receptionEntryPoints.length:",nodeServerInstance.receptionEntryPoints.length);
15314
-
15315
-
15316
- return nodeServerInstance;
15317
- },
15318
-
15319
-
15320
- send:(channelName, data, clientsRoomsTag=null, clientSocketParam=null)=>{
15321
-
15322
- // DBG
15323
- lognow("(SERVER) SERVER TRIES TO SEND !");
15324
-
15325
-
15326
- if(!clientSocketParam){
15327
-
15328
- // DBG
15329
- lognow("(SERVER) (server sends to all clients)");
15330
-
15331
- // TODO : FIXME : Use one single interface !
15332
- let serverClients;
15333
- if(!WebsocketImplementation.useSocketIOImplementation) serverClients=nodeServerInstance.serverSocket.clients;
15334
- // OLD: else serverClients=nodeServerInstance.serverSocket.sockets.clients();
15335
- else serverClients=nodeServerInstance.serverSocket.sockets.sockets;
15336
-
15337
-
15338
-
15339
- serverClients.forEach((clientSocket)=>{
15340
-
15341
-
15342
- if(!isConnected(clientSocket)) return;
15343
-
15344
-
15345
- // Room information is stored in client socket object :
15346
- if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
15347
-
15348
- // Channel information is stored in exchanged data :
15349
- let dataWrapped={channelName:channelName, data:data};
15350
-
15351
-
15352
- dataWrapped=stringifyObject(dataWrapped);
15353
-
15354
- // TODO : FIXME : Use one single interface !
15355
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
15356
- else clientSocket.emit(channelName,dataWrapped);
15357
-
15358
- });
15359
-
15360
- }else{
15361
-
15362
- // DBG
15363
- lognow("(SERVER) (server sends to a client)");
15364
-
15365
-
15366
- // TODO : FIXME : Use one single interface !
15367
- let clientSocket=clientSocketParam;
15368
- if(!WebsocketImplementation.useSocketIOImplementation) if(clientSocket.readyState!==WebSocket.OPEN) return;
15369
- else if(clientSocket.connected) return;
15370
-
15371
-
15372
- // Room information is stored in client socket object :
15373
- if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
15374
-
15375
- // Channel information is stored in exchanged data :
15376
- let dataWrapped={channelName:channelName, data:data};
15377
- dataWrapped=stringifyObject(dataWrapped);
15378
-
15379
-
15380
- // DBG
15381
- lognow("(SERVER) WebsocketImplementation.useSocketIOImplementation:"+WebsocketImplementation.useSocketIOImplementation);
15382
- // lognow("(SERVER) dataWrapped:"+dataWrapped);
15383
-
15384
-
15385
- // TODO : FIXME : Use one single interface !
15386
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
15387
- else clientSocket.emit(channelName,dataWrapped);
15388
-
15389
-
15390
- }
15391
-
15392
-
15393
- return nodeServerInstance;
15394
- },
15395
-
15396
-
15397
- onConnectionToClient:(doOnConnection)=>{
15398
-
15399
- // «connection» is the only event fired by the serverSocket :
15400
- nodeServerInstance.serverSocket.on("connection", (clientSocket)=>{
15401
-
15402
- // DBG
15403
- console.log("SERVER : ON CONNECTION !");
15404
-
15405
-
15406
- // if(contains(nodeServerInstance.clientsSockets, clientSocket)) return;
15407
- // nodeServerInstance.clientsSockets.push(clientSocket);
15408
-
15409
-
15410
- const clientId="autogeneratedid_"+getUUID();
15411
-
15412
-
15413
- clientSocket.clientId=clientId;
15414
-
15415
-
15416
-
15417
- const doOnMessage=(eventOrMessage)=>{
15418
- // We execute the events registration listeners entry points:
15419
- foreach(nodeServerInstance.receptionEntryPoints,(receptionEntryPoint,i)=>{
15420
- receptionEntryPoint.execute(eventOrMessage, clientSocket);
15421
- });
15422
- };
15423
-
15424
- if(!WebsocketImplementation.useSocketIOImplementation){ clientSocket.addEventListener("message", doOnMessage);
15425
- // NO: else clientSocket.on("message", doOnMessage);
15426
- }
15427
-
15428
- doOnConnection(nodeServerInstance, clientSocket);
15429
-
15430
-
15431
- // DBG
15432
- lognow("DEBUG : Starting ping-pong with client : clientSocket.clientId:",clientSocket.clientId);
15433
- lognow("DEBUG : WebsocketImplementation.useSocketIOImplementation:",WebsocketImplementation.useSocketIOImplementation);
15434
- lognow("DEBUG : clientSocket.readyState:",clientSocket.readyState);
15435
-
15436
-
15437
- // To make the server aware of the clients connections states :
15438
- clientSocket.isConnectionAlive=true;
15439
- clientSocket.stateCheckInterval=setInterval(()=>{
15440
-
15441
-
15442
- if (clientSocket.isConnectionAlive===false){
15443
-
15444
-
15445
- // On today, this method is named as same for the two implementations :
15446
- // TRACE
15447
- lognow("(SERVER) Removing all listeners for client socket «"+clientSocket.clientId+"».");
15448
-
15449
- clientSocket.removeAllListeners();
15450
-
15451
-
15452
- // TODO : FIXME : Use one single interface !
15453
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.terminate();
15454
- else clientSocket.emit("endConnection");
15455
-
15456
- if(!empty(nodeServerInstance.onClientLostListeners))
15457
- foreach(nodeServerInstance.onClientLostListeners,l=>{l.execute(clientSocket);});
15458
-
15459
- // DBG
15460
- lognow("DEBUG : (SERVER) Connection closed for failed ping-pong.");
15461
-
15462
-
15463
- clearInterval(clientSocket.stateCheckInterval);
15464
- return;
15465
- }
15466
-
15467
- clientSocket.isConnectionAlive=false;
15468
-
15469
- // // DBG
15470
- // lognow("(SERVER) DEBUG : SENDING PING");
15471
-
15472
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.ping();
15473
- // OLD :
15474
- // else clientSocket.emit("ping");
15475
- else nodeServerInstance.send("protocol",{type:"ping"}, null, clientSocket);
15476
-
15477
-
15478
- }, nodeServerInstance.clientPingIntervalMillis);
15479
-
15480
-
15481
- if(!WebsocketImplementation.useSocketIOImplementation){
15482
- clientSocket.on("pong",()=>{
15483
- clientSocket.isConnectionAlive=true;
15484
- });
15485
- }else{
15486
- // // OLD :
15487
- // clientSocket.on("ping",()=>{
15488
- // clientSocket.isConnectionAlive=true;
15489
- // });
15490
-
15491
- nodeServerInstance.receive("protocol",(message)=>{
15492
- if(message.type!=="pong") return;
15493
- clientSocket.isConnectionAlive=true;
15494
- });
15495
-
15496
- }
15497
-
15498
-
15499
-
15500
- });
15501
-
15502
-
15503
- return nodeServerInstance;
15504
- },
15505
-
15506
- onFinalize:(doOnFinalizeServer)=>{
15507
-
15508
- doOnFinalizeServer(nodeServerInstance);
15509
-
15510
- // TRACE
15511
- console.log("INFO : SERVER : Node server setup complete.");
15512
-
15513
- return nodeServerInstance;
15514
- },
15515
-
15516
- addToRoom:(clientSocket,clientRoomTag)=>{
15517
- clientSocket.clientRoomTag=clientRoomTag;
15518
- },
15519
-
15520
-
15521
-
15522
- };
15223
+ const nodeServerInstance=new NodeServerInstance(serverSocket, listenableServer);
15523
15224
 
15524
15225
  // Join room server part protocol :
15525
15226
  nodeServerInstance.receive("protocol",(message, clientSocket)=>{
15526
-
15527
15227
  if(message.type!=="joinRoom" || !clientSocket) return;
15528
15228
  nodeServerInstance.addToRoom(clientSocket, message.clientRoomTag);
15529
-
15530
15229
  });
15531
15230
 
15532
-
15533
-
15534
15231
  // To make the server aware of the clients connections states :
15535
15232
  nodeServerInstance.serverSocket.on("close", function close() {
15536
15233
 
@@ -15543,8 +15240,6 @@ WebsocketImplementation={
15543
15240
  clearInterval(clientSocket.stateCheckInterval);
15544
15241
  });
15545
15242
  });
15546
-
15547
-
15548
15243
 
15549
15244
  return nodeServerInstance;
15550
15245
  },
@@ -15562,14 +15257,12 @@ WebsocketImplementation={
15562
15257
  return WebsocketImplementation.connectToServerFromBrowser(serverURL, port, isSecure, timeout);
15563
15258
  },
15564
15259
 
15565
-
15566
15260
 
15567
15261
  //
15568
15262
  // NODE CLIENT
15569
15263
  //
15570
15264
  /*private*/connectToServerFromNode:(serverURL, port, isSecure, timeout)=>{
15571
15265
 
15572
-
15573
15266
  // NODE CLIENT MODE ONLY :
15574
15267
  let clientSocket;
15575
15268
  if(!WebsocketImplementation.useSocketIOImplementation){
@@ -15598,219 +15291,13 @@ WebsocketImplementation={
15598
15291
  // DBG
15599
15292
  lognow("DEBUG : CLIENT : clientSocket created:");
15600
15293
 
15601
-
15602
- // NODE CLIENT INSTANCE :
15603
- const nodeClientInstance={
15604
- clientSocket:clientSocket,
15605
-
15606
- receptionEntryPoints:[],
15607
-
15608
- receive:(channelNameParam, doOnIncomingMessage, clientsRoomsTag=null)=>{
15609
-
15610
- const receptionEntryPoint={
15611
- channelName:channelNameParam,
15612
- clientsRoomsTag:clientsRoomsTag,
15613
- execute:(eventOrMessage)=>{
15614
-
15615
- // dataWrapped=parseJSON(dataWrapped);
15616
- // dataWrapped=getAt(dataWrapped,0);// We get the root element
15617
- // const dataWrapped=(WebsocketImplementation.useFlatStrings?parseJSON(eventOrMessage):eventOrMessage);
15618
-
15619
- const dataWrapped=WebsocketImplementation.getMessageDataBothImplementations(eventOrMessage);
15620
-
15621
- // Channel information is stored in exchanged data :
15622
- if(dataWrapped.channelName && dataWrapped.channelName!==channelNameParam) return;
15623
-
15624
- const clientSocket=nodeClientInstance.clientSocket;
15625
-
15626
- // Room information is stored in client socket object :
15627
- if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
15628
-
15629
- if(doOnIncomingMessage) doOnIncomingMessage(dataWrapped.data, clientSocket);
15630
-
15631
-
15632
- }
15633
- };
15634
-
15635
-
15636
- ///!!!
15637
- nodeClientInstance.receptionEntryPoints.push(receptionEntryPoint);
15638
-
15639
- // SPECIAL FOR THE SOCKETIO IMPLEMENTATION :
15640
- if(WebsocketImplementation.useSocketIOImplementation){
15641
- const channelName=receptionEntryPoint.channelName;
15642
- clientSocket.on(channelName, (eventOrMessage)=>{
15643
- receptionEntryPoint.execute(eventOrMessage, clientSocket);
15644
- });
15645
- }
15646
-
15647
-
15648
- return nodeClientInstance;
15649
- },
15650
-
15651
-
15652
-
15653
- // TODO : FIXME : DUPLICATED CODE !
15654
- sendChainable:(channelNameParam, data, clientsRoomsTag=null)=>{
15655
-
15656
- // DBG
15657
- lognow(">>>>>>sendChainable NODE CLIENT ("+channelNameParam+"):data:",data);
15658
-
15659
- // We add a message id :
15660
- const messageId=getUUID();
15661
- data.messageId=messageId;
15662
-
15663
- // 1) We prepare the reception :
15664
- const resultPromise={
15665
- clientsRoomsTag:clientsRoomsTag,
15666
- messageId:messageId,
15667
- thenWhenReceiveMessageType:(channelNameForResponse, listenerConfig={messageType:"",condition:()=>true}, doOnIncomingMessageForResponse)=>{
15668
-
15669
- listenerConfig=nonull(listenerConfig,{messageType:"",condition:()=>true});
15670
- const listenerId=nonull(listenerConfig.messageType,"");
15671
-
15672
- //
15673
- nodeClientInstance.receive(channelNameForResponse, (dataLocal, clientSocket)=>{
15674
-
15675
- // We check if the message matches the condition :
15676
- if(listenerConfig.condition && !listenerConfig.condition(dataLocal, clientSocket)) return ;
15677
-
15678
- // We check if we have the same message id:
15679
- if(resultPromise.messageId!==dataLocal.messageId){
15680
- // DBG
15681
- lognow("resultPromise.messageId:"+resultPromise.messageId+"|dataLocal.messageId"+dataLocal.messageId);
15682
- return;
15683
- }
15684
-
15685
- doOnIncomingMessageForResponse(dataLocal, clientSocket);
15686
- }, resultPromise.clientsRoomsTag, listenerId, {destroyListenerAfterReceiving:true});
15687
- //
15688
-
15689
- return resultPromise;
15690
- }
15691
- };
15692
-
15693
- // 2) We send the data :
15694
- nodeClientInstance.send(channelNameParam, data, clientsRoomsTag);
15695
-
15696
-
15697
- return resultPromise;
15698
- },
15699
-
15700
-
15701
- send:(channelNameParam, data, clientsRoomsTag=null)=>{
15702
-
15703
- // // DBG
15704
- // lognow("(CLIENT) (NODEJS) CLIENT TRIES TO SEND !");
15705
-
15706
-
15707
- const clientSocket=nodeClientInstance.clientSocket;
15708
-
15709
-
15710
- // // DBG
15711
- // console.log("(NODE CLIENT) TRYING TO SEND : clientSocket.readyState:",clientSocket.readyState);
15712
-
15713
- if(!isConnected(clientSocket)) return;
15714
-
15715
-
15716
- // Room information is stored in client socket object :
15717
- if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
15718
-
15719
- // Channel information is stored in exchanged data :
15720
- let dataWrapped={channelName:channelNameParam, data:data};
15721
-
15722
-
15723
- // // DBG
15724
- // console.log("(NODE CLIENT) SENDING DATA ! dataWrapped:",dataWrapped);
15725
-
15726
-
15727
- dataWrapped=stringifyObject(dataWrapped);
15728
-
15729
-
15730
- // // DBG
15731
- // console.log("(NODE CLIENT) SENDING DATA ! channelNameParam:«"+channelNameParam+"» ; clientsRoomsTag:«"+clientsRoomsTag+"»");
15732
- // console.log("(NODE CLIENT) SENDING DATA ! dataWrapped:",dataWrapped);
15733
-
15734
- // TODO : FIXME : Use one single interface !
15735
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
15736
- else clientSocket.emit(channelNameParam,dataWrapped);
15737
-
15738
- return nodeClientInstance;
15739
- },
15740
-
15741
-
15742
- join:(clientRoomTag)=>{
15743
- // Join room client part protocol :
15744
- const message={type:"joinRoom",clientRoomTag:clientRoomTag};
15745
- nodeClientInstance.send("protocol",message);
15746
- },
15747
-
15748
-
15749
- onConnectionToServer:(doOnConnection)=>{
15750
-
15751
- // DBG
15752
- lognow("DEBUG : CLIENT : setting up onConnectionToServer.");
15753
-
15754
- const doAllOnConnection=()=>{
15755
-
15756
- // To avoid triggering this event several times, depending on the implementation :
15757
- if(nodeClientInstance.hasConnectEventFired) return;
15758
- nodeClientInstance.hasConnectEventFired=true;
15759
-
15760
- // DBG
15761
- lognow("DEBUG : CLIENT (NODEJS) : doOnConnection !");
15762
-
15763
- const doOnMessage=(eventOrMessage)=>{
15764
-
15765
- // We execute the listeners entry points registration :
15766
- foreach(nodeClientInstance.receptionEntryPoints,(receptionEntryPoint)=>{
15767
- receptionEntryPoint.execute(eventOrMessage);
15768
- });
15769
-
15770
- };
15771
-
15772
- const clientSocket=nodeClientInstance.clientSocket;
15773
- if(!WebsocketImplementation.useSocketIOImplementation){ clientSocket.addEventListener("message", doOnMessage);
15774
- // NO: else clientSocket.on("message", doOnMessage);
15775
- }
15776
-
15777
- doOnConnection(nodeClientInstance, clientSocket);
15778
-
15779
- };
15780
-
15781
-
15782
- if(!WebsocketImplementation.useSocketIOImplementation) nodeClientInstance.clientSocket.addEventListener("open",doAllOnConnection);
15783
- else nodeClientInstance.clientSocket.on("connect",doAllOnConnection);
15784
-
15785
-
15786
- // DBG
15787
- lognow("DEBUG : CLIENT : nodeClientInstance.clientSocket.on(connect)");
15788
-
15789
-
15790
- // Node client ping handling : (SocketIO implementation only)
15791
- if(WebsocketImplementation.useSocketIOImplementation){
15792
- nodeClientInstance.receive("protocol",(message)=>{
15793
- if(message.type!=="ping") return;
15794
- nodeClientInstance.send("protocol",{type:"pong"});
15795
-
15796
- // DBG
15797
- lognow("DEBUG : NODE CLIENT : Pong sent.");
15798
- });
15799
- }
15800
-
15801
-
15802
- },
15803
-
15804
-
15805
- };
15806
-
15807
-
15294
+ const nodeClientInstance=new ClientInstance(clientSocket);
15808
15295
  return nodeClientInstance;
15809
15296
  },
15810
15297
 
15811
-
15812
-
15298
+ //
15813
15299
  // BROWSER CLIENT
15300
+ //
15814
15301
 
15815
15302
  /*private*/connectToServerFromBrowser:(serverURL, port, isSecure, timeout)=>{
15816
15303
 
@@ -15824,225 +15311,17 @@ WebsocketImplementation={
15824
15311
  // TODO : FIXME : Use one single interface !
15825
15312
  // BROWSER CLIENT MODE ONLY :
15826
15313
  let clientSocket;
15827
- if(!WebsocketImplementation.useSocketIOImplementation){
15828
- clientSocket=new WebSocket(serverURL+":"+port,["ws","wss"]);
15829
- }else if(typeof(io)!=="undefined"){
15830
- // OLD SYNTAX :clientSocket=io.connect(serverURL + ":" + port,{timeout: timeout, secure: isSecure});
15831
- // ALTERNATIVE :
15832
- clientSocket=io(serverURL + ":" + port,{timeout: timeout, secure: isSecure});
15833
- }
15834
-
15835
-
15836
- // BROWSER CLIENT INSTANCE :
15837
- const browserInstance={
15838
-
15839
- clientSocket:clientSocket,
15840
- receptionEntryPoints:[],
15841
-
15842
- receive:(channelNameParam, doOnIncomingMessage, clientsRoomsTag=null, receptionEntryPointId=null, listenerConfig={destroyListenerAfterReceiving:false})=>{
15843
-
15844
- // DBG
15845
- lognow("INFO : (CLIENT-BROWSER) SETTING UP RECEIVE for :",channelNameParam);
15846
-
15847
-
15848
- const receptionEntryPoint={
15849
- channelName:channelNameParam,
15850
- clientsRoomsTag:clientsRoomsTag,
15851
- // TODO : ADD TO ALL OTHER SUBSYSTEMS !
15852
- id:receptionEntryPointId,
15853
- listenerConfig:listenerConfig,
15854
- doOnIncomingMessage:doOnIncomingMessage,
15855
- execute:(eventOrMessage)=>{
15856
-
15857
- const dataWrapped=WebsocketImplementation.getMessageDataBothImplementations(eventOrMessage);
15858
-
15859
- // Channel information is stored in exchanged data :
15860
- if(dataWrapped.channelName && dataWrapped.channelName!==receptionEntryPoint.channelName) return;
15861
-
15862
- // Room information is stored in client socket object :
15863
- const clientSocket=browserInstance.clientSocket;
15864
- if(!WebsocketImplementation.isInRoom(clientSocket, receptionEntryPoint.clientsRoomsTag)) return;
15865
-
15866
- // We remove one-time usage listeners :
15867
- // We remove BEFORE executing doOnIncomingMessage(), because in receptionEntryPoint function we can have other listener registration UNDER THE SAME ID !
15868
- if(receptionEntryPoint.listenerConfig && receptionEntryPoint.listenerConfig.destroyListenerAfterReceiving)
15869
- remove(browserInstance.receptionEntryPoints, receptionEntryPoint);
15870
-
15871
- if(receptionEntryPoint.doOnIncomingMessage)
15872
- receptionEntryPoint.doOnIncomingMessage(dataWrapped.data, clientSocket);
15873
-
15874
- }
15875
- };
15876
-
15877
- ///!!!
15878
- // TODO : ADD TO ALL OTHER SUBSYSTEMS !
15879
- if(!contains.filter((l)=>(l.id && receptionEntryPoint.id && l.id===receptionEntryPoint.id))(browserInstance.receptionEntryPoints))
15880
- browserInstance.receptionEntryPoints.push(receptionEntryPoint);
15881
-
15882
- // SPECIAL FOR THE SOCKETIO IMPLEMENTATION :
15883
- if(WebsocketImplementation.useSocketIOImplementation){
15884
- const channelName=receptionEntryPoint.channelName;
15885
- clientSocket.on(channelName, (eventOrMessage)=>{
15886
- receptionEntryPoint.execute(eventOrMessage, clientSocket);
15887
- });
15888
- }
15889
-
15890
-
15891
- return browserInstance;
15892
- },
15893
-
15894
-
15895
-
15896
- // TODO : FIXME : DUPLICATED CODE !
15897
- sendChainable:(channelNameParam, data, clientsRoomsTag=null)=>{
15898
-
15899
- // DBG
15900
- lognow(">>>>>>sendChainable BROWSER CLIENT ("+channelNameParam+"):data:",data);
15901
-
15902
- // We add a message id :
15903
- const messageId=getUUID();
15904
- data.messageId=messageId;
15905
-
15906
- // 1) We prepare the reception :
15907
- const resultPromise={
15908
- clientsRoomsTag:clientsRoomsTag,
15909
- messageId:messageId,
15910
- thenWhenReceiveMessageType:(channelNameForResponse, listenerConfig={messageType:"",condition:()=>true}, doOnIncomingMessageForResponse)=>{
15911
- listenerConfig=nonull(listenerConfig,{messageType:"",condition:()=>true});
15912
- const listenerId=nonull(listenerConfig.messageType,"");
15913
-
15914
- browserInstance.receive(channelNameForResponse, (dataLocal, clientSocket)=>{
15915
-
15916
- // We check if the message matches the condition :
15917
- if(listenerConfig.condition && !listenerConfig.condition(dataLocal, clientSocket)) return ;
15918
-
15919
- // We check if we have the same message id:
15920
- if(resultPromise.messageId!==dataLocal.messageId){
15921
- // DBG
15922
- lognow("resultPromise.messageId:"+resultPromise.messageId+"|dataLocal.messageId"+dataLocal.messageId);
15923
- return;
15924
- }
15925
-
15926
- doOnIncomingMessageForResponse(dataLocal, clientSocket);
15927
- }, resultPromise.clientsRoomsTag, listenerId, {destroyListenerAfterReceiving:true});
15928
- return resultPromise;
15929
- }
15930
- };
15931
-
15932
- // 2) We send the data :
15933
- browserInstance.send(channelNameParam, data, clientsRoomsTag);
15934
-
15935
-
15936
- return resultPromise;
15937
- },
15938
-
15939
-
15940
-
15941
-
15942
-
15943
-
15944
- send:(channelNameParam, data, clientsRoomsTag=null)=>{
15945
-
15946
- // // DBG
15947
- // lognow("(CLIENT) (BROWSER) CLIENT TRIES TO SEND !");
15948
-
15949
- const clientSocket=browserInstance.clientSocket;
15950
-
15951
-
15952
- // // DBG
15953
- // console.log("(BROWSER) TRYING TO SEND : clientSocket.readyState:",clientSocket.readyState);
15954
-
15955
- if(!isConnected(clientSocket)) return;
15956
-
15957
-
15958
- // Room information is stored in client socket object :
15959
- if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
15960
-
15961
- // Channel information is stored in exchanged data :
15962
- let dataWrapped={channelName:channelNameParam, data:data};
15963
-
15964
-
15965
- // // DBG
15966
- // console.log("(BROWSER) SENDING... : dataWrapped :",dataWrapped);
15967
- // console.log("(BROWSER) SENDING... : clientSocket :",clientSocket);
15968
-
15969
-
15970
- dataWrapped=stringifyObject(dataWrapped);
15971
-
15972
-
15973
- // TODO : FIXME : Use one single interface !
15974
- if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
15975
- else clientSocket.emit(channelNameParam,dataWrapped);
15976
-
15977
-
15978
- return browserInstance;
15979
- },
15980
-
15981
-
15982
- join:(clientRoomTag)=>{
15983
- // Join room client part protocol :
15984
- const message={type:"joinRoom",clientRoomTag:clientRoomTag};
15985
- browserInstance.send("protocol",message);
15986
- },
15987
-
15988
-
15989
- onConnectionToServer:(doOnConnection)=>{
15990
- const doAllOnConnection=()=>{
15991
-
15992
- // To avoid triggering this event several times, depending on the implementation :
15993
- if(browserInstance.hasConnectEventFired) return;
15994
- browserInstance.hasConnectEventFired=true;
15995
-
15996
-
15997
-
15998
- // DBG
15999
- lognow("DEBUG : CLIENT (BROWSER) : doOnConnection !");
16000
-
16001
- const doOnMessage=(eventOrMessage)=>{
16002
-
16003
- // We execute the listeners entry points registration :
16004
- foreach(browserInstance.receptionEntryPoints,(receptionEntryPoint)=>{
16005
- receptionEntryPoint.execute(eventOrMessage);
16006
- });
16007
-
16008
- };
16009
-
16010
- const clientSocket=browserInstance.clientSocket;
16011
- if(!WebsocketImplementation.useSocketIOImplementation){ clientSocket.addEventListener("message", doOnMessage);
16012
- // NO: else clientSocket.on("message", doOnMessage);
16013
- }
16014
-
16015
-
16016
- doOnConnection(browserInstance, clientSocket);
16017
-
16018
- };
16019
-
16020
- if(!WebsocketImplementation.useSocketIOImplementation) browserInstance.clientSocket.addEventListener("open",doAllOnConnection);
16021
- else browserInstance.clientSocket.on("connect",doAllOnConnection);
16022
-
16023
-
16024
-
16025
- // Browser client ping handling : (SocketIO implementation only)
16026
- if(WebsocketImplementation.useSocketIOImplementation){
16027
- browserInstance.receive("protocol",(message)=>{
16028
- if(message.type!=="ping") return;
16029
- browserInstance.send("protocol",{type:"pong"});
16030
-
16031
- // DBG
16032
- lognow("DEBUG : BROWSER CLIENT : Pong sent.");
16033
- });
16034
- }
16035
-
16036
-
16037
- },
16038
-
16039
-
16040
- };
16041
-
16042
-
16043
-
15314
+ if(!WebsocketImplementation.useSocketIOImplementation){
15315
+ clientSocket=new WebSocket(serverURL+":"+port,["ws","wss"]);
15316
+ }else if(typeof(io)!=="undefined"){
15317
+ // OLD SYNTAX :clientSocket=io.connect(serverURL + ":" + port,{timeout: timeout, secure: isSecure});
15318
+ // ALTERNATIVE :
15319
+ clientSocket=io(serverURL + ":" + port,{timeout: timeout, secure: isSecure});
15320
+ }
16044
15321
 
16045
- return browserInstance;
15322
+ // BROWSER CLIENT INSTANCE :
15323
+ const browserClientInstance=new ClientInstance(clientSocket);
15324
+ return browserClientInstance;
16046
15325
  },
16047
15326
 
16048
15327
  };
@@ -17648,9 +16927,495 @@ getAORTACNode=function(nodeId=getUUID(), selfOrigin="ws://127.0.0.1:40000", outc
17648
16927
 
17649
16928
 
17650
16929
 
16930
+ // ==================================================================================================================
16931
+
16932
+ class NodeServerInstance{
16933
+
16934
+ constructor(serverSocket, listenableServer){
16935
+
16936
+ this.onClientLostListeners=[];
16937
+
16938
+ this.clientPingIntervalMillis=5000;
16939
+ this.serverSocket=serverSocket;
16940
+ this.listenableServer=listenableServer;
16941
+ this.receptionEntryPoints=[];
16942
+
16943
+ }
16944
+
16945
+ setPingPongTimeout(clientPingIntervalMillis){
16946
+ this.clientPingIntervalMillis=clientPingIntervalMillis;
16947
+ return this;
16948
+ }
16949
+
16950
+ close(doOnCloseServer){
16951
+ if(!this.serverSocket) return;
16952
+ this.serverSocket.close(()=>{
16953
+ if(!this.listenableServer) return;
16954
+ this.listenableServer.close(doOnCloseServer);
16955
+ });
16956
+ }
16957
+
16958
+ receive(channelNameParam, doOnIncomingMessage, clientsRoomsTag=null){
16959
+ const self=this;
16960
+
16961
+ // DBG
16962
+ lognow("(SERVER) Registering receive for «"+channelNameParam+"»...");
16963
+
16964
+
16965
+ const receptionEntryPoint={
16966
+ channelName:channelNameParam,
16967
+ clientsRoomsTag:clientsRoomsTag,
16968
+ execute:(eventOrMessage, clientSocketParam)=>{
16969
+
16970
+ // With «ws» library we have no choive than register message events inside a «connection» event !
16971
+
16972
+ const dataWrapped=WebsocketImplementation.getMessageDataBothImplementations(eventOrMessage);
16973
+
16974
+ // Channel information is stored in exchanged data :
16975
+ if(dataWrapped.channelName!==receptionEntryPoint.channelName) return;
16976
+
16977
+
16978
+ // TODO : FIXME : Use one single interface !
16979
+ // Room information is stored in client socket object :
16980
+ const isClientInRoom=WebsocketImplementation.isInRoom(clientSocketParam, receptionEntryPoint.clientsRoomsTag);
16981
+
16982
+ // DBG
16983
+ lognow("(SERVER) isClientInRoom:",isClientInRoom);
16984
+
16985
+ if(!isClientInRoom) return;
16986
+
16987
+ if(doOnIncomingMessage){
16988
+ // DBG
16989
+ lognow("(SERVER) doOnIncomingMessage:");
16990
+ doOnIncomingMessage(dataWrapped.data, clientSocketParam);
16991
+ }
16992
+
16993
+ },
16994
+ };
16995
+
16996
+
16997
+ ///!!!
16998
+ self.receptionEntryPoints.push(receptionEntryPoint);
16999
+
17000
+ // SPECIAL FOR THE SOCKETIO IMPLEMENTATION :
17001
+ if(WebsocketImplementation.useSocketIOImplementation){
17002
+ const channelName=receptionEntryPoint.channelName;
17003
+ clientSocket.on(channelName, (eventOrMessage)=>{
17004
+ receptionEntryPoint.execute(eventOrMessage, clientSocket);
17005
+ });
17006
+ }
17007
+
17008
+ return this;
17009
+ }
17010
+
17011
+
17012
+ send(channelName, data, clientsRoomsTag=null, clientSocketParam=null){
17013
+
17014
+ // DBG
17015
+ lognow("(SERVER) SERVER TRIES TO SEND !");
17016
+
17017
+
17018
+ if(!clientSocketParam){
17019
+
17020
+ // DBG
17021
+ lognow("(SERVER) (server sends to all clients)");
17022
+
17023
+ // TODO : FIXME : Use one single interface !
17024
+ let serverClients;
17025
+ if(!WebsocketImplementation.useSocketIOImplementation) serverClients=this.serverSocket.clients;
17026
+ else serverClients=this.serverSocket.sockets.sockets;
17027
+
17028
+
17029
+ serverClients.forEach((clientSocket)=>{
17030
+
17031
+
17032
+ if(!isConnected(clientSocket)) return;
17033
+
17034
+
17035
+ // Room information is stored in client socket object :
17036
+ if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
17037
+
17038
+ // Channel information is stored in exchanged data :
17039
+ let dataWrapped={channelName:channelName, data:data};
17040
+
17041
+
17042
+ dataWrapped=stringifyObject(dataWrapped);
17043
+
17044
+ // TODO : FIXME : Use one single interface !
17045
+ if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
17046
+ else clientSocket.emit(channelName,dataWrapped);
17047
+
17048
+ });
17049
+
17050
+ }else{
17051
+
17052
+ // DBG
17053
+ lognow("(SERVER) (server sends to a client)");
17054
+
17055
+
17056
+ // TODO : FIXME : Use one single interface !
17057
+ let clientSocket=clientSocketParam;
17058
+ if(!WebsocketImplementation.useSocketIOImplementation) if(clientSocket.readyState!==WebSocket.OPEN) return;
17059
+ else if(clientSocket.connected) return;
17060
+
17061
+
17062
+ // Room information is stored in client socket object :
17063
+ if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
17064
+
17065
+ // Channel information is stored in exchanged data :
17066
+ let dataWrapped={channelName:channelName, data:data};
17067
+ dataWrapped=stringifyObject(dataWrapped);
17068
+
17069
+
17070
+ // DBG
17071
+ lognow("(SERVER) WebsocketImplementation.useSocketIOImplementation:"+WebsocketImplementation.useSocketIOImplementation);
17072
+
17073
+
17074
+ // TODO : FIXME : Use one single interface !
17075
+ if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
17076
+ else clientSocket.emit(channelName,dataWrapped);
17077
+
17078
+ }
17079
+
17080
+
17081
+ return this;
17082
+ }
17083
+
17084
+
17085
+ onConnectionToClient(doOnConnection){
17086
+ const self=this;
17087
+
17088
+
17089
+ // «connection» is the only event fired by the serverSocket :
17090
+ this.serverSocket.on("connection", (clientSocket)=>{
17091
+
17092
+ // DBG
17093
+ console.log("SERVER : ON CONNECTION !");
17094
+
17095
+
17096
+ const clientId="autogeneratedid_"+getUUID();
17097
+
17098
+ clientSocket.clientId=clientId;
17099
+
17100
+
17101
+ const doOnMessage=(eventOrMessage)=>{
17102
+ // We execute the events registration listeners entry points:
17103
+ foreach(self.receptionEntryPoints,(receptionEntryPoint,i)=>{
17104
+ receptionEntryPoint.execute(eventOrMessage, clientSocket);
17105
+ });
17106
+ };
17107
+
17108
+ if(!WebsocketImplementation.useSocketIOImplementation)
17109
+ clientSocket.addEventListener("message", doOnMessage);
17110
+
17111
+ doOnConnection(this, clientSocket);
17112
+
17113
+
17114
+ // DBG
17115
+ lognow("DEBUG : Starting ping-pong with client : clientSocket.clientId:",clientSocket.clientId);
17116
+ lognow("DEBUG : WebsocketImplementation.useSocketIOImplementation:",WebsocketImplementation.useSocketIOImplementation);
17117
+ lognow("DEBUG : clientSocket.readyState:",clientSocket.readyState);
17118
+
17119
+
17120
+ // To make the server aware of the clients connections states :
17121
+ clientSocket.isConnectionAlive=true;
17122
+ clientSocket.stateCheckInterval=setInterval(()=>{
17123
+
17124
+ if (clientSocket.isConnectionAlive===false){
17125
+
17126
+ // On today, this method is named as same for the two implementations :
17127
+ // TRACE
17128
+ lognow("(SERVER) Removing all listeners for client socket «"+clientSocket.clientId+"».");
17129
+
17130
+ clientSocket.removeAllListeners();
17131
+
17132
+ // TODO : FIXME : Use one single interface !
17133
+ if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.terminate();
17134
+ else clientSocket.emit("endConnection");
17135
+
17136
+ if(!empty(self.onClientLostListeners))
17137
+ foreach(self.onClientLostListeners,l=>{l.execute(clientSocket);});
17138
+
17139
+ // DBG
17140
+ lognow("DEBUG : (SERVER) Connection closed for failed ping-pong.");
17141
+
17142
+
17143
+ clearInterval(clientSocket.stateCheckInterval);
17144
+ return;
17145
+ }
17146
+
17147
+ clientSocket.isConnectionAlive=false;
17148
+
17149
+ if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.ping();
17150
+ else self.send("protocol",{type:"ping"}, null, clientSocket);
17151
+
17152
+
17153
+ }, this.clientPingIntervalMillis);
17154
+
17155
+
17156
+ if(!WebsocketImplementation.useSocketIOImplementation){
17157
+ clientSocket.on("pong",()=>{
17158
+ clientSocket.isConnectionAlive=true;
17159
+ });
17160
+ }else{
17161
+
17162
+ this.receive("protocol",(message)=>{
17163
+ if(message.type!=="pong") return;
17164
+ clientSocket.isConnectionAlive=true;
17165
+ });
17166
+
17167
+ }
17168
+
17169
+ });
17170
+
17171
+
17172
+ return this;
17173
+ }
17174
+
17175
+ onFinalize(doOnFinalizeServer){
17176
+
17177
+ doOnFinalizeServer(this);
17178
+
17179
+ // TRACE
17180
+ console.log("INFO : SERVER : Node server setup complete.");
17181
+
17182
+ return this;
17183
+ }
17184
+
17185
+ addToRoom(clientSocket, clientRoomTag){
17186
+ clientSocket.clientRoomTag=clientRoomTag;
17187
+ }
17188
+
17189
+ }
17190
+
17191
+
17192
+
17193
+
17194
+
17195
+
17196
+
17197
+
17198
+ /* ## Utility network global methods in a javascript, console (nodejs), or vanilla javascript with no browser environment.
17199
+ *
17200
+ * This set of methods gathers utility generic-purpose methods usable in any JS project.
17201
+ * Several authors of snippets published freely on the Internet contributed to this library.
17202
+ * Feel free to use/modify-enhance/publish them under the terms of its license.
17203
+ *
17204
+ * # Library name : «aotrautils»
17205
+ * # Library license : HGPL(Help Burma) (see aotra README information for details : https://alqemia.com/aotra.js )
17206
+ * # Author name : Jérémie Ratomposon (massively helped by his native country free education system)
17207
+ * # Author email : info@alqemia.com
17208
+ * # Organization name : Alqemia
17209
+ * # Organization email : admin@alqemia.com
17210
+ * # Organization website : https://alqemia.com
17211
+ *
17212
+ *
17213
+ */
17214
+
17215
+
17216
+
17217
+ // COMPATIBILITY browser javascript / nodejs environment :
17218
+ if(typeof(window)==="undefined") window=global;
17219
+
17220
+
17221
+
17222
+ // ==================================================================================================================
17223
+
17224
+ //
17225
+ // CLIENT INSTANCE :
17226
+ //
17227
+ class ClientInstance{
17228
+
17229
+ constructor(clientSocket){
17230
+ this.clientSocket=clientSocket;
17231
+ this.receptionEntryPoints=[];
17232
+
17233
+ }
17234
+
17235
+ receive(channelNameParam, doOnIncomingMessage, clientsRoomsTag=null, receptionEntryPointId=null, listenerConfig={destroyListenerAfterReceiving:false}){
17236
+ const self=this;
17237
+
17238
+ // DBG
17239
+ lognow("INFO : (CLIENT-BROWSER) SETTING UP RECEIVE for :",channelNameParam);
17240
+
17241
+ const receptionEntryPoint={
17242
+ channelName:channelNameParam,
17243
+ clientsRoomsTag:clientsRoomsTag,
17244
+ // TODO : ADD TO ALL OTHER SUBSYSTEMS !
17245
+ id:receptionEntryPointId,
17246
+ listenerConfig:listenerConfig,
17247
+ doOnIncomingMessage:doOnIncomingMessage,
17248
+ execute:(eventOrMessage)=>{
17249
+
17250
+ const dataWrapped=WebsocketImplementation.getMessageDataBothImplementations(eventOrMessage);
17251
+
17252
+ // Channel information is stored in exchanged data :
17253
+ if(dataWrapped.channelName && dataWrapped.channelName!==receptionEntryPoint.channelName) return;
17254
+
17255
+ // Room information is stored in client socket object :
17256
+ const clientSocket=self.clientSocket;
17257
+ if(!WebsocketImplementation.isInRoom(clientSocket, receptionEntryPoint.clientsRoomsTag)) return;
17258
+
17259
+ // We remove one-time usage listeners :
17260
+ // We remove BEFORE executing doOnIncomingMessage(), because in receptionEntryPoint function we can have other listener registration UNDER THE SAME ID !
17261
+ if(receptionEntryPoint.listenerConfig && receptionEntryPoint.listenerConfig.destroyListenerAfterReceiving)
17262
+ remove(self.receptionEntryPoints, receptionEntryPoint);
17263
+
17264
+ if(receptionEntryPoint.doOnIncomingMessage)
17265
+ receptionEntryPoint.doOnIncomingMessage(dataWrapped.data, clientSocket);
17266
+
17267
+ }
17268
+ };
17269
+
17270
+ ///!!!
17271
+ // TODO : ADD TO ALL OTHER SUBSYSTEMS !
17272
+ if(!contains.filter((l)=>(l.id && receptionEntryPoint.id && l.id===receptionEntryPoint.id))(this.receptionEntryPoints))
17273
+ this.receptionEntryPoints.push(receptionEntryPoint);
17274
+
17275
+ // SPECIAL FOR THE SOCKETIO IMPLEMENTATION :
17276
+ if(WebsocketImplementation.useSocketIOImplementation){
17277
+ const channelName=receptionEntryPoint.channelName;
17278
+ clientSocket.on(channelName, (eventOrMessage)=>{
17279
+ receptionEntryPoint.execute(eventOrMessage, clientSocket);
17280
+ });
17281
+ }
17282
+
17283
+
17284
+ return this;
17285
+ }
17286
+
17287
+
17288
+ // TODO : FIXME : DUPLICATED CODE !
17289
+ sendChainable(channelNameParam, data, clientsRoomsTag=null){
17290
+ const self=this;
17291
+
17292
+ // DBG
17293
+ lognow(">>>>>>sendChainable CLIENT ("+channelNameParam+"):data:",data);
17294
+
17295
+ // We add a message id :
17296
+ const messageId=getUUID();
17297
+ data.messageId=messageId;
17298
+
17299
+ // 1) We prepare the reception :
17300
+ const resultPromise={
17301
+ clientsRoomsTag:clientsRoomsTag,
17302
+ messageId:messageId,
17303
+ thenWhenReceiveMessageType:(channelNameForResponse, listenerConfig={messageType:"",condition:()=>true}, doOnIncomingMessageForResponse)=>{
17304
+ listenerConfig=nonull(listenerConfig,{messageType:"",condition:()=>true});
17305
+ const listenerId=nonull(listenerConfig.messageType,"");
17306
+
17307
+ //
17308
+ self.receive(channelNameForResponse, (dataLocal, clientSocket)=>{
17309
+
17310
+ // We check if the message matches the condition :
17311
+ if(listenerConfig.condition && !listenerConfig.condition(dataLocal, clientSocket)) return ;
17312
+
17313
+ // We check if we have the same message id:
17314
+ if(resultPromise.messageId!==dataLocal.messageId){
17315
+ // DBG
17316
+ lognow("resultPromise.messageId:"+resultPromise.messageId+"|dataLocal.messageId"+dataLocal.messageId);
17317
+ return;
17318
+ }
17319
+
17320
+ doOnIncomingMessageForResponse(dataLocal, clientSocket);
17321
+ }, resultPromise.clientsRoomsTag, listenerId, {destroyListenerAfterReceiving:true});
17322
+ //
17323
+
17324
+ return resultPromise;
17325
+ }
17326
+ };
17327
+
17328
+ // 2) We send the data :
17329
+ this.send(channelNameParam, data, clientsRoomsTag);
17330
+
17331
+
17332
+ return resultPromise;
17333
+ }
17334
+
17335
+
17336
+ send(channelNameParam, data, clientsRoomsTag=null){
17337
+
17338
+ // // DBG
17339
+ // lognow("(CLIENT) CLIENT TRIES TO SEND !");
17340
+
17341
+ const clientSocket=this.clientSocket;
17342
+
17343
+ if(!isConnected(clientSocket)) return;
17344
+
17345
+ // Room information is stored in client socket object :
17346
+ if(!WebsocketImplementation.isInRoom(clientSocket,clientsRoomsTag)) return;
17347
+
17348
+ // Channel information is stored in exchanged data :
17349
+ let dataWrapped={channelName:channelNameParam, data:data};
17350
+
17351
+ dataWrapped=stringifyObject(dataWrapped);
17352
+
17353
+ // TODO : FIXME : Use one single interface !
17354
+ if(!WebsocketImplementation.useSocketIOImplementation) clientSocket.send(dataWrapped);
17355
+ else clientSocket.emit(channelNameParam,dataWrapped);
17356
+
17357
+ return this;
17358
+ }
17359
+
17360
+
17361
+ join(clientRoomTag){
17362
+ // Join room client part protocol :
17363
+ const message={type:"joinRoom",clientRoomTag:clientRoomTag};
17364
+ this.send("protocol",message);
17365
+ }
17366
+
17367
+
17368
+ onConnectionToServer(doOnConnection){
17369
+ const self=this;
17370
+
17371
+ // DBG
17372
+ lognow("DEBUG : CLIENT : setting up onConnectionToServer.");
17373
+
17374
+ const doAllOnConnection=()=>{
17651
17375
 
17376
+ // To avoid triggering this event several times, depending on the implementation :
17377
+ if(self.hasConnectEventFired) return;
17378
+ self.hasConnectEventFired=true;
17379
+
17380
+ // DBG
17381
+ lognow("DEBUG : CLIENT : doOnConnection !");
17382
+
17383
+ const doOnMessage=(eventOrMessage)=>{
17384
+
17385
+ // We execute the listeners entry points registration :
17386
+ foreach(self.receptionEntryPoints,(receptionEntryPoint)=>{
17387
+ receptionEntryPoint.execute(eventOrMessage);
17388
+ });
17652
17389
 
17390
+ };
17391
+
17392
+ const clientSocket=self.clientSocket;
17393
+ if(!WebsocketImplementation.useSocketIOImplementation){ clientSocket.addEventListener("message", doOnMessage);
17394
+ }
17653
17395
 
17396
+ doOnConnection(self, clientSocket);
17397
+
17398
+ };
17399
+
17400
+ if(!WebsocketImplementation.useSocketIOImplementation) this.clientSocket.addEventListener("open",doAllOnConnection);
17401
+ else this.clientSocket.on("connect",doAllOnConnection);
17402
+
17403
+
17404
+ // Client ping handling : (SocketIO implementation only)
17405
+ if(WebsocketImplementation.useSocketIOImplementation){
17406
+ this.receive("protocol",(message)=>{
17407
+ if(message.type!=="ping") return;
17408
+ self.send("protocol",{type:"pong"});
17409
+
17410
+ // DBG
17411
+ lognow("DEBUG : CLIENT : Pong sent.");
17412
+ });
17413
+ }
17414
+
17415
+
17416
+ }
17417
+
17418
+ }
17654
17419
 
17655
17420
 
17656
17421
  /* INCLUDED EXTERNAL LIBRAIRIES
aotrautils/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aotrautils",
3
- "version": "0.0.1476",
3
+ "version": "0.0.1477",
4
4
  "main": "aotrautils.build.js",
5
5
  "description": "A library for vanilla javascript utils (client-side) used in aotra javascript CMS",
6
6
  "author": "Jeremie Ratomposon <info@alqemia.com> (https://alqemia.com)",