arcane-os 0.15.0 → 0.15.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.1
4
+
5
+ - Use the published `node-http-server` public lifecycle for the mail gateway.
6
+ Pass original requests and responses through its raw-request hook to the
7
+ existing mail handler, preserving complete content, provider results,
8
+ cancellation, and the returned native listener. Retain the disabled socket
9
+ inactivity timeout and use the module's listener shutdown and malformed-client
10
+ response handling.
11
+
3
12
  ## 0.15.0
4
13
 
5
14
  - Add explicit `arcane dev --http` and source API `http:true` for HTTP
package/README.md CHANGED
@@ -19,7 +19,7 @@ version-locked SDK runtime, while an integrated Arcane checkout uses its live
19
19
  `arcane/` runtime. Both profiles preserve the same app URLs, theme, packaging,
20
20
  event, cancellation, and browser run contracts.
21
21
 
22
- This checkout defines the `0.13.0` SDK contract. Applications pin one exact npm
22
+ This checkout defines the `0.15.1` SDK contract. Applications pin one exact npm
23
23
  version and lockfile; registry state is deliberately not baked into application
24
24
  artifacts.
25
25
 
@@ -283,6 +283,12 @@ Non-interactive structured output requires `--app-key-stdin` and redirected
283
283
  stdin. The server binds numeric loopback only; the default is
284
284
  `127.0.0.1:8025/v1/mail`.
285
285
 
286
+ The gateway uses the published `node-http-server` instance lifecycle. Its raw
287
+ request hook hands the original request and response directly to the mail
288
+ handler before body parsing or static routing. Socket inactivity timeout remains
289
+ disabled; caller-selected mail deadlines, cancellation, and complete responses
290
+ remain owned by the mail handler.
291
+
286
292
  The gateway protects the provider credential by requiring:
287
293
 
288
294
  - its exact numeric-loopback `Host` authority and `/v1/mail` route;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
4
4
  "description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -1,6 +1,6 @@
1
1
  import Is from 'strong-type';
2
2
  import {createHash,randomUUID,timingSafeEqual} from 'node:crypto';
3
- import http from 'node:http';
3
+ import {Server} from 'node-http-server';
4
4
 
5
5
  const is = new Is(false);
6
6
 
@@ -1283,40 +1283,16 @@ export function createResendMailRequestHandler(options={}){
1283
1283
  };
1284
1284
  }
1285
1285
 
1286
- function listen(server,{host,port}){
1286
+ function deployMailServer(mailServer){
1287
1287
  return new Promise(function waitForMailListener(resolve,reject){
1288
- function cleanup(){
1289
- server.removeListener('error',onError);
1290
- server.removeListener('listening',onListening);
1291
- }
1292
1288
  function onError(error){
1293
- cleanup();
1294
1289
  reject(error);
1295
1290
  }
1296
- function onListening(){
1297
- cleanup();
1298
- resolve();
1299
- }
1300
- server.once('error',onError);
1301
- server.once('listening',onListening);
1302
- server.listen({exclusive:true,host,port});
1303
- });
1304
- }
1305
-
1306
- function closeHttpServer(server){
1307
- return new Promise(function waitForHttpServerClose(resolve,reject){
1308
- if(!server.listening){
1309
- resolve();
1310
- return;
1311
- }
1312
- server.close(function finishHttpServerClose(error){
1313
- if(error){
1314
- reject(error);
1315
- }else{
1316
- resolve();
1317
- }
1291
+ mailServer.deploy(function onListening(instance,server){
1292
+ server.removeListener('error',onError);
1293
+ resolve(server);
1318
1294
  });
1319
- server.closeIdleConnections?.();
1295
+ mailServer.server.once('error',onError);
1320
1296
  });
1321
1297
  }
1322
1298
 
@@ -1325,29 +1301,27 @@ export async function startResendMailServer(options={}){
1325
1301
  if(configuration.signal?.aborted){
1326
1302
  throw configuration.signal.reason??new Error('Mail server start was cancelled.');
1327
1303
  }
1328
- const requestHandler=createResendMailRequestHandler(options);
1329
- const server=http.createServer(requestHandler.handle);
1330
- server.on('clientError',function rejectMalformedClient(error,socket){
1331
- if(!socket.writable){
1332
- return;
1333
- }
1334
- socket.end(
1335
- 'HTTP/1.1 400 Bad Request\r\n'
1336
- +'Connection: close\r\n'
1337
- +'Content-Length: 0\r\n'
1338
- +'\r\n'
1339
- );
1304
+ const mailServer=new Server({
1305
+ host:configuration.host,
1306
+ port:configuration.port,
1307
+ server:{timeout:0}
1340
1308
  });
1309
+ const requestHandler=createResendMailRequestHandler(options);
1310
+ mailServer.onRawRequest=function handleMailRequest(request,response){
1311
+ requestHandler.handle(request,response);
1312
+ return true;
1313
+ };
1341
1314
 
1315
+ let server;
1342
1316
  try{
1343
- await listen(server,{host:configuration.host,port:configuration.port});
1317
+ server=await deployMailServer(mailServer);
1344
1318
  }catch(error){
1345
- await requestHandler.close();
1319
+ await Promise.allSettled([mailServer.close(),requestHandler.close()]);
1346
1320
  throw error;
1347
1321
  }
1348
1322
  const address=server.address();
1349
1323
  if(!address||is.string(address)||!isNumericLoopback(address.address)){
1350
- await Promise.allSettled([closeHttpServer(server),requestHandler.close()]);
1324
+ await Promise.allSettled([mailServer.close(),requestHandler.close()]);
1351
1325
  throw configurationError('Mail server did not bind to a numeric loopback address.');
1352
1326
  }
1353
1327
  const displayHost=address.address.includes(':')?`[${address.address}]`:address.address;
@@ -1365,7 +1339,7 @@ export async function startResendMailServer(options={}){
1365
1339
  configuration.signal?.removeEventListener('abort',closeFromSignal);
1366
1340
  const handlerClosing=requestHandler.close();
1367
1341
  try{
1368
- await Promise.all([closeHttpServer(server),handlerClosing]);
1342
+ await Promise.all([mailServer.close(),handlerClosing]);
1369
1343
  resolveLifecycle();
1370
1344
  }catch(error){
1371
1345
  rejectLifecycle(error);