@proteinjs/server 3.2.1 → 3.3.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
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.3.1](https://github.com/proteinjs/server/compare/@proteinjs/server@3.3.0...@proteinjs/server@3.3.1) (2026-08-13)
7
+
8
+ **Note:** Version bump only for package @proteinjs/server
9
+
10
+
11
+
12
+
13
+
14
+ # [3.3.0](https://github.com/proteinjs/server/compare/@proteinjs/server@3.2.1...@proteinjs/server@3.3.0) (2026-08-12)
15
+
16
+
17
+ ### Features
18
+
19
+ * graceful shutdown — SIGTERM drains (readiness 503, bounded, exit 0) ([e98b8bc](https://github.com/proteinjs/server/commit/e98b8bc563d41f6b2cec9d1064c41d27859e98dd))
20
+
21
+
22
+
23
+
24
+
6
25
  # [3.2.0](https://github.com/proteinjs/server/compare/@proteinjs/server@3.1.14...@proteinjs/server@3.2.0) (2026-08-11)
7
26
 
8
27
 
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Brent Bahry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -33,7 +33,7 @@ require("react-helmet");
33
33
  require("socket.io");
34
34
  require("typescript");
35
35
  /** Generate Source Graph */
36
- var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
36
+ var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
37
37
  /** Generate Source Links */
38
38
  var NodeGlobalDataStorage_1 = require("../src/NodeGlobalDataStorage");
39
39
  var NodeSessionDataStorage_1 = require("../src/NodeSessionDataStorage");
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,o4RAAo4R,CAAC;AAGz5R,4BAA4B;AAE5B,sEAAqE;AACrE,wEAAuE;AACvE,4CAAmD;AACnD,yDAAwD;AAExD,IAAM,WAAW,GAAG;IACnB,yCAAyC,EAAE,6CAAqB;IAChE,0CAA0C,EAAE,+CAAsB;IAClE,oCAAoC,EAAE,2BAAgB;IACtD,+BAA+B,EAAE,yBAAW;CAC5C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,gqRAAgqR,CAAC;AAGrrR,4BAA4B;AAE5B,sEAAqE;AACrE,wEAAuE;AACvE,4CAAmD;AACnD,yDAAwD;AAExD,IAAM,WAAW,GAAG;IACnB,yCAAyC,EAAE,6CAAqB;IAChE,0CAA0C,EAAE,+CAAsB;IAClE,oCAAoC,EAAE,2BAAgB;IACtD,+BAA+B,EAAE,yBAAW;CAC5C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './src/startServer';
2
+ export * from './src/GracefulShutdown';
2
3
  export * from './src/envCache';
3
4
  export * from './src/Request';
4
5
  export * from './src/SocketIOServerRepo';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./src/startServer"), exports);
18
+ __exportStar(require("./src/GracefulShutdown"), exports);
18
19
  __exportStar(require("./src/envCache"), exports);
19
20
  __exportStar(require("./src/Request"), exports);
20
21
  __exportStar(require("./src/SocketIOServerRepo"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,iDAA+B;AAC/B,gDAA8B;AAC9B,2DAAyC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC;AACvC,iDAA+B;AAC/B,gDAA8B;AAC9B,2DAAyC"}
@@ -0,0 +1,52 @@
1
+ /// <reference types="node" />
2
+ import { Server as HttpServer } from 'http';
3
+ import { ServerConfig } from '@proteinjs/server-api';
4
+ /**
5
+ * The one owner of the server's shutdown state. Installed by `startServer` before the listener
6
+ * opens; the `/health-check` route reads `isShuttingDown()` — no other flag system exists.
7
+ *
8
+ * Signal / exit-code contract:
9
+ * SIGTERM → drain, then exit 0:
10
+ * 1. `/health-check` flips to 503 immediately while the listener KEEPS accepting for
11
+ * `shutdown.drainDelayMs` — load balancers must OBSERVE the failing readiness and
12
+ * de-register before connections start being refused, or draining becomes user-facing
13
+ * errors. (In Kubernetes, a preStop sleep buys de-registration time BEFORE the SIGTERM
14
+ * even arrives; this window makes the server correct regardless of that wiring.)
15
+ * 2. The listener closes (socket.io clients are disconnected, and `io.close()` closes the
16
+ * http server it is attached to), idle keep-alive connections are closed, and in-flight
17
+ * requests run to completion.
18
+ * 3. The drain is BOUNDED by `shutdown.drainTimeoutMs`: past it, remaining connections are
19
+ * force-closed. Either way the exit code is 0 — a drained shutdown is not a crash.
20
+ * SIGINT → exit 0 immediately (dev ctrl-C: fast and quiet; nothing needs flushing).
21
+ * exit 86 → NOT this class's concern: `process.exit(86)` is the ServePackageSupervisor
22
+ * restart-request contract (a liveness monitor giving up on a dependency); it is not
23
+ * signal-driven and is untouched by these handlers.
24
+ *
25
+ * A SIGTERM before the listener is open (mid-boot kill) exits 0 immediately — nothing is
26
+ * registered anywhere and nothing is in flight.
27
+ *
28
+ * Supervisor compatibility (dev): ServePackageSupervisor SIGTERMs the child's process group and
29
+ * escalates to SIGKILL after its grace period (default 10s); its exit handler ignores exit codes
30
+ * for kills it initiated, so the drain-then-exit-0 shape cannot be misread. DEVELOPMENT defaults
31
+ * `drainDelayMs` to 0 so supervised restarts stay fast.
32
+ */
33
+ export declare class GracefulShutdown {
34
+ private server;
35
+ private config;
36
+ private static instance?;
37
+ private shuttingDown;
38
+ private logger;
39
+ private constructor();
40
+ /** Install the SIGTERM/SIGINT handlers for this process's server. Idempotent. */
41
+ static install(server: HttpServer, config: ServerConfig): void;
42
+ /** The readiness seam: `/health-check` reports 503 whenever this is true. */
43
+ static isShuttingDown(): boolean;
44
+ private drainAndExit;
45
+ private exitNow;
46
+ private drainDelayMs;
47
+ private drainTimeoutMs;
48
+ /** Await a promise with a deadline; true if it settled in time. */
49
+ private settled;
50
+ private sleep;
51
+ }
52
+ //# sourceMappingURL=GracefulShutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GracefulShutdown.d.ts","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,gBAAgB;IAMzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAE1D,OAAO;IAKP,iFAAiF;IACjF,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IAU9D,6EAA6E;IAC7E,MAAM,CAAC,cAAc,IAAI,OAAO;YAIlB,YAAY;IAwC1B,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,cAAc;IAItB,mEAAmE;YACrD,OAAO;IAUrB,OAAO,CAAC,KAAK;CAGd"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.GracefulShutdown = void 0;
40
+ var logger_1 = require("@proteinjs/logger");
41
+ var SocketIOServerRepo_1 = require("./SocketIOServerRepo");
42
+ /**
43
+ * The one owner of the server's shutdown state. Installed by `startServer` before the listener
44
+ * opens; the `/health-check` route reads `isShuttingDown()` — no other flag system exists.
45
+ *
46
+ * Signal / exit-code contract:
47
+ * SIGTERM → drain, then exit 0:
48
+ * 1. `/health-check` flips to 503 immediately while the listener KEEPS accepting for
49
+ * `shutdown.drainDelayMs` — load balancers must OBSERVE the failing readiness and
50
+ * de-register before connections start being refused, or draining becomes user-facing
51
+ * errors. (In Kubernetes, a preStop sleep buys de-registration time BEFORE the SIGTERM
52
+ * even arrives; this window makes the server correct regardless of that wiring.)
53
+ * 2. The listener closes (socket.io clients are disconnected, and `io.close()` closes the
54
+ * http server it is attached to), idle keep-alive connections are closed, and in-flight
55
+ * requests run to completion.
56
+ * 3. The drain is BOUNDED by `shutdown.drainTimeoutMs`: past it, remaining connections are
57
+ * force-closed. Either way the exit code is 0 — a drained shutdown is not a crash.
58
+ * SIGINT → exit 0 immediately (dev ctrl-C: fast and quiet; nothing needs flushing).
59
+ * exit 86 → NOT this class's concern: `process.exit(86)` is the ServePackageSupervisor
60
+ * restart-request contract (a liveness monitor giving up on a dependency); it is not
61
+ * signal-driven and is untouched by these handlers.
62
+ *
63
+ * A SIGTERM before the listener is open (mid-boot kill) exits 0 immediately — nothing is
64
+ * registered anywhere and nothing is in flight.
65
+ *
66
+ * Supervisor compatibility (dev): ServePackageSupervisor SIGTERMs the child's process group and
67
+ * escalates to SIGKILL after its grace period (default 10s); its exit handler ignores exit codes
68
+ * for kills it initiated, so the drain-then-exit-0 shape cannot be misread. DEVELOPMENT defaults
69
+ * `drainDelayMs` to 0 so supervised restarts stay fast.
70
+ */
71
+ var GracefulShutdown = /** @class */ (function () {
72
+ function GracefulShutdown(server, config) {
73
+ this.server = server;
74
+ this.config = config;
75
+ this.shuttingDown = false;
76
+ this.logger = new logger_1.Logger({ name: 'GracefulShutdown' });
77
+ }
78
+ /** Install the SIGTERM/SIGINT handlers for this process's server. Idempotent. */
79
+ GracefulShutdown.install = function (server, config) {
80
+ if (GracefulShutdown.instance) {
81
+ return;
82
+ }
83
+ var instance = new GracefulShutdown(server, config);
84
+ GracefulShutdown.instance = instance;
85
+ process.on('SIGTERM', function () { return void instance.drainAndExit(); });
86
+ process.on('SIGINT', function () { return instance.exitNow(); });
87
+ };
88
+ /** The readiness seam: `/health-check` reports 503 whenever this is true. */
89
+ GracefulShutdown.isShuttingDown = function () {
90
+ var _a, _b;
91
+ return (_b = (_a = GracefulShutdown.instance) === null || _a === void 0 ? void 0 : _a.shuttingDown) !== null && _b !== void 0 ? _b : false;
92
+ };
93
+ GracefulShutdown.prototype.drainAndExit = function () {
94
+ return __awaiter(this, void 0, void 0, function () {
95
+ var drainDelayMs, drainTimeoutMs, drained, io;
96
+ var _this = this;
97
+ return __generator(this, function (_a) {
98
+ switch (_a.label) {
99
+ case 0:
100
+ if (this.shuttingDown) {
101
+ return [2 /*return*/]; // already draining; the sender's escalation is SIGKILL, not a second drain
102
+ }
103
+ this.shuttingDown = true;
104
+ if (!this.server.listening) {
105
+ this.logger.info({ message: "Received SIGTERM before the listener opened \u2014 exiting immediately" });
106
+ process.exit(0);
107
+ }
108
+ drainDelayMs = this.drainDelayMs();
109
+ drainTimeoutMs = this.drainTimeoutMs();
110
+ this.logger.info({
111
+ message: "Received SIGTERM \u2014 /health-check now reports 503; accepting connections for another ".concat(drainDelayMs, "ms, then draining in-flight requests (bound: ").concat(drainTimeoutMs, "ms)"),
112
+ });
113
+ // 1. Readiness-propagation window: the LB observes the 503 while we still serve normally.
114
+ return [4 /*yield*/, this.sleep(drainDelayMs)];
115
+ case 1:
116
+ // 1. Readiness-propagation window: the LB observes the 503 while we still serve normally.
117
+ _a.sent();
118
+ drained = new Promise(function (resolve) { return _this.server.once('close', function () { return resolve(); }); });
119
+ io = SocketIOServerRepo_1.SocketIOServerRepo.getSocketIOServerIfExists();
120
+ if (io) {
121
+ io.close();
122
+ }
123
+ else {
124
+ this.server.close();
125
+ }
126
+ this.server.closeIdleConnections();
127
+ return [4 /*yield*/, this.settled(drained, drainTimeoutMs)];
128
+ case 2:
129
+ // 3. Bounded: past the drain timeout, force-close what remains. Exit 0 either way.
130
+ if (!(_a.sent())) {
131
+ this.logger.warn({
132
+ message: "Drain exceeded its ".concat(drainTimeoutMs, "ms bound \u2014 force-closing the remaining connections"),
133
+ });
134
+ this.server.closeAllConnections();
135
+ }
136
+ this.logger.info({ message: "Drained \u2014 exiting 0" });
137
+ process.exit(0);
138
+ return [2 /*return*/];
139
+ }
140
+ });
141
+ });
142
+ };
143
+ GracefulShutdown.prototype.exitNow = function () {
144
+ this.shuttingDown = true;
145
+ this.logger.info({ message: "Received SIGINT \u2014 exiting immediately" });
146
+ process.exit(0);
147
+ };
148
+ GracefulShutdown.prototype.drainDelayMs = function () {
149
+ var _a;
150
+ if (typeof ((_a = this.config.shutdown) === null || _a === void 0 ? void 0 : _a.drainDelayMs) === 'number') {
151
+ return this.config.shutdown.drainDelayMs;
152
+ }
153
+ return process.env.DEVELOPMENT ? 0 : 5000;
154
+ };
155
+ GracefulShutdown.prototype.drainTimeoutMs = function () {
156
+ var _a, _b;
157
+ return (_b = (_a = this.config.shutdown) === null || _a === void 0 ? void 0 : _a.drainTimeoutMs) !== null && _b !== void 0 ? _b : 30000;
158
+ };
159
+ /** Await a promise with a deadline; true if it settled in time. */
160
+ GracefulShutdown.prototype.settled = function (promise, ms) {
161
+ return __awaiter(this, void 0, void 0, function () {
162
+ var timer, timedOut, result;
163
+ return __generator(this, function (_a) {
164
+ switch (_a.label) {
165
+ case 0:
166
+ timedOut = new Promise(function (resolve) {
167
+ timer = setTimeout(function () { return resolve(false); }, ms);
168
+ });
169
+ return [4 /*yield*/, Promise.race([promise.then(function () { return true; }), timedOut])];
170
+ case 1:
171
+ result = _a.sent();
172
+ clearTimeout(timer);
173
+ return [2 /*return*/, result];
174
+ }
175
+ });
176
+ });
177
+ };
178
+ GracefulShutdown.prototype.sleep = function (ms) {
179
+ return new Promise(function (resolve) { return setTimeout(resolve, ms); });
180
+ };
181
+ return GracefulShutdown;
182
+ }());
183
+ exports.GracefulShutdown = GracefulShutdown;
184
+ //# sourceMappingURL=GracefulShutdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GracefulShutdown.js","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
1
  import { Route } from '@proteinjs/server-api';
2
+ /**
3
+ * Readiness: 200 while serving, 503 once GracefulShutdown has begun draining (SIGTERM
4
+ * received) — load balancers and kubelet readiness probes read this route, and the 503 is
5
+ * what makes them stop routing new traffic while in-flight requests finish.
6
+ */
2
7
  export declare const healthCheck: Route;
3
8
  //# sourceMappingURL=healthCheck.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"healthCheck.d.ts","sourceRoot":"","sources":["../../../src/routes/healthCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAE9C,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC"}
1
+ {"version":3,"file":"healthCheck.d.ts","sourceRoot":"","sources":["../../../src/routes/healthCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAG9C;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAYzB,CAAC"}
@@ -37,12 +37,22 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.healthCheck = void 0;
40
+ var GracefulShutdown_1 = require("../GracefulShutdown");
41
+ /**
42
+ * Readiness: 200 while serving, 503 once GracefulShutdown has begun draining (SIGTERM
43
+ * received) — load balancers and kubelet readiness probes read this route, and the 503 is
44
+ * what makes them stop routing new traffic while in-flight requests finish.
45
+ */
40
46
  exports.healthCheck = {
41
47
  path: 'health-check',
42
48
  method: 'get',
43
49
  useHttp: true,
44
50
  onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
45
51
  return __generator(this, function (_a) {
52
+ if (GracefulShutdown_1.GracefulShutdown.isShuttingDown()) {
53
+ response.status(503).send('draining');
54
+ return [2 /*return*/];
55
+ }
46
56
  response.send();
47
57
  return [2 /*return*/];
48
58
  });
@@ -1 +1 @@
1
- {"version":3,"file":"healthCheck.js","sourceRoot":"","sources":["../../../src/routes/healthCheck.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEa,QAAA,WAAW,GAAU;IAChC,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;YACjC,QAAQ,CAAC,IAAI,EAAE,CAAC;;;SACjB;CACF,CAAC"}
1
+ {"version":3,"file":"healthCheck.js","sourceRoot":"","sources":["../../../src/routes/healthCheck.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wDAAuD;AAEvD;;;;GAIG;AACU,QAAA,WAAW,GAAU;IAChC,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;YACjC,IAAI,mCAAgB,CAAC,cAAc,EAAE,EAAE;gBACrC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACtC,sBAAO;aACR;YAED,QAAQ,CAAC,IAAI,EAAE,CAAC;;;SACjB;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"startServer.d.ts","sourceRoot":"","sources":["../../src/startServer.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,YAAY,EAKb,MAAM,uBAAuB,CAAC;AAW/B,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,iBAwCrD"}
1
+ {"version":3,"file":"startServer.d.ts","sourceRoot":"","sources":["../../src/startServer.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,YAAY,EAKb,MAAM,uBAAuB,CAAC;AAY/B,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,iBA2CrD"}
@@ -65,6 +65,7 @@ var loadRoutes_1 = require("./loadRoutes");
65
65
  var logger_1 = require("@proteinjs/logger");
66
66
  var SocketIOServerRepo_1 = require("./SocketIOServerRepo");
67
67
  var DevClientBuild_1 = require("./DevClientBuild");
68
+ var GracefulShutdown_1 = require("./GracefulShutdown");
68
69
  var staticContentPath = '/static/';
69
70
  var logger = new logger_1.Logger({ name: 'Server' });
70
71
  var app = (0, express_1.default)();
@@ -74,7 +75,11 @@ function startServer(config) {
74
75
  var routes, clientBuildReady, globalData, _i, _a, globalDataCache, _b, _c;
75
76
  return __generator(this, function (_d) {
76
77
  switch (_d.label) {
77
- case 0: return [4 /*yield*/, runStartupTasks('before server config')];
78
+ case 0:
79
+ // First, before any (possibly long) startup work: a SIGTERM must drain gracefully from the
80
+ // moment this process can be part of a rollout, including mid-boot.
81
+ GracefulShutdown_1.GracefulShutdown.install(server, config);
82
+ return [4 /*yield*/, runStartupTasks('before server config')];
78
83
  case 1:
79
84
  _d.sent();
80
85
  routes = (0, server_api_1.getRoutes)();
@@ -1 +1 @@
1
- {"version":3,"file":"startServer.js","sourceRoot":"","sources":["../../src/startServer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"startServer.js","sourceRoot":"","sources":["../../src/startServer.ts"],"names":[],"mappings":"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"}
@@ -18,11 +18,10 @@ import 'react-helmet';
18
18
  import 'socket.io';
19
19
  import 'typescript';
20
20
 
21
-
22
21
  /** Generate Source Graph */
23
22
 
24
- const sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/Users/brentbahry/repos/farm/n3xa2/packages/proteinjs/packages/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
25
-
23
+ const sourceGraph =
24
+ '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"@proteinjs/server/NodeGlobalDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeGlobalDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts","qualifiedName":"@proteinjs/server/NodeGlobalDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"GLOBAL_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: GlobalData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: GlobalData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"GlobalData","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"GlobalDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/GlobalDataStorage"},{"v":"@proteinjs/server/NodeSessionDataStorage","value":{"packageName":"@proteinjs/server","name":"NodeSessionDataStorage","filePath":"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts","qualifiedName":"@proteinjs/server/NodeSessionDataStorage","isAbstract":false,"isStatic":false,"visibility":"public","properties":[{"name":"HOOK_INITIALIZED","type":null,"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"SESSION_DATA","type":{"packageName":"@proteinjs/server","name":"{ [id: string]: SessionData }","filePath":null,"qualifiedName":"@proteinjs/server/{ [id: string]: SessionData }","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":true,"visibility":"private"},{"name":"environment","type":null,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[{"name":"setData","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[{"name":"data","type":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null}}]},{"name":"getData","returnType":{"packageName":"@proteinjs/server-api","name":"SessionData","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionData","typeParameters":null,"directParents":null},"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public","parameters":[]},{"name":"initHook","returnType":null,"isAsync":false,"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"private","parameters":[]}],"typeParameters":[],"directParentInterfaces":[{"packageName":"@proteinjs/server-api","name":"SessionDataStorage","filePath":null,"qualifiedName":"@proteinjs/server-api/SessionDataStorage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"directParentClasses":[],"sourceType":2}},{"v":"@proteinjs/server-api/SessionDataStorage"},{"v":"@proteinjs/server/ExtendedIncomingMessage","value":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","properties":[{"name":"sessionID","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"},{"name":"user","type":{"packageName":"","name":"string","filePath":null,"qualifiedName":"/string","typeParameters":null,"directParents":null},"isOptional":true,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"http","name":"IncomingMessage","filePath":null,"qualifiedName":"http/IncomingMessage","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"http/IncomingMessage"},{"v":"@proteinjs/server/ExtendedSocket","value":{"packageName":"@proteinjs/server","name":"ExtendedSocket","filePath":"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts","qualifiedName":"@proteinjs/server/ExtendedSocket","properties":[{"name":"request","type":{"packageName":"@proteinjs/server","name":"ExtendedIncomingMessage","filePath":null,"qualifiedName":"@proteinjs/server/ExtendedIncomingMessage","typeParameters":null,"directParents":null},"isOptional":false,"isAbstract":false,"isStatic":false,"visibility":"public"}],"methods":[],"typeParameters":[],"directParents":[{"packageName":"socket.io","name":"Socket","filePath":null,"qualifiedName":"socket.io/Socket","properties":[],"methods":[],"typeParameters":[],"directParents":[]}],"sourceType":3}},{"v":"socket.io/Socket"},{"v":"@proteinjs/server/environmentCache","value":{"packageName":"@proteinjs/server","name":"environmentCache","filePath":"/home/runner/work/server/server/packages/server/src/envCache.ts","qualifiedName":"@proteinjs/server/environmentCache","type":{"packageName":"","name":"GlobalDataCache<Env>","filePath":null,"qualifiedName":"/GlobalDataCache<Env>","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"GlobalDataCache","filePath":null,"qualifiedName":"@proteinjs/server-api/GlobalDataCache","typeParameters":["@proteinjs/server-api/Env"],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/GlobalDataCache"},{"v":"@proteinjs/server/healthCheck","value":{"packageName":"@proteinjs/server","name":"healthCheck","filePath":"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts","qualifiedName":"@proteinjs/server/healthCheck","type":{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":[{"packageName":"@proteinjs/server-api","name":"Route","filePath":null,"qualifiedName":"@proteinjs/server-api/Route","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/server-api/Route"}],"edges":[{"v":"@proteinjs/server/NodeGlobalDataStorage","w":"@proteinjs/server-api/GlobalDataStorage","value":"implements interface"},{"v":"@proteinjs/server/NodeSessionDataStorage","w":"@proteinjs/server-api/SessionDataStorage","value":"implements interface"},{"v":"@proteinjs/server/ExtendedIncomingMessage","w":"http/IncomingMessage","value":"extends interface"},{"v":"@proteinjs/server/ExtendedSocket","w":"socket.io/Socket","value":"extends interface"},{"v":"@proteinjs/server/environmentCache","w":"@proteinjs/server-api/GlobalDataCache","value":"has type"},{"v":"@proteinjs/server/healthCheck","w":"@proteinjs/server-api/Route","value":"has type"}]}';
26
25
 
27
26
  /** Generate Source Links */
28
27
 
@@ -32,17 +31,15 @@ import { environmentCache } from '../src/envCache';
32
31
  import { healthCheck } from '../src/routes/healthCheck';
33
32
 
34
33
  const sourceLinks = {
35
- '@proteinjs/server/NodeGlobalDataStorage': NodeGlobalDataStorage,
36
- '@proteinjs/server/NodeSessionDataStorage': NodeSessionDataStorage,
37
- '@proteinjs/server/environmentCache': environmentCache,
38
- '@proteinjs/server/healthCheck': healthCheck,
34
+ '@proteinjs/server/NodeGlobalDataStorage': NodeGlobalDataStorage,
35
+ '@proteinjs/server/NodeSessionDataStorage': NodeSessionDataStorage,
36
+ '@proteinjs/server/environmentCache': environmentCache,
37
+ '@proteinjs/server/healthCheck': healthCheck,
39
38
  };
40
39
 
41
-
42
40
  /** Load Source Graph and Links */
43
41
 
44
42
  import { SourceRepository } from '@proteinjs/reflection';
45
43
  SourceRepository.merge(sourceGraph, sourceLinks);
46
44
 
47
-
48
- export * from '../index';
45
+ export * from '../index';
package/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './src/startServer';
2
+ export * from './src/GracefulShutdown';
2
3
  export * from './src/envCache';
3
4
  export * from './src/Request';
4
5
  export * from './src/SocketIOServerRepo';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/server",
3
- "version": "3.2.1",
3
+ "version": "3.3.1",
4
4
  "description": "A server impl",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,13 +18,14 @@
18
18
  "scripts": {
19
19
  "clean": "rm -rf dist/ generated/ node_modules/",
20
20
  "build": "reflection-build && tsc",
21
- "watch": "reflection-watch"
21
+ "watch": "reflection-watch",
22
+ "test": "jest --runInBand"
22
23
  },
23
24
  "dependencies": {
24
- "@proteinjs/event": "^1.0.17",
25
+ "@proteinjs/event": "^1.0.18",
25
26
  "@proteinjs/logger": "^1.0.21",
26
27
  "@proteinjs/reflection": "^1.1.12",
27
- "@proteinjs/server-api": "^3.0.11",
28
+ "@proteinjs/server-api": "^3.1.1",
28
29
  "@proteinjs/util-node": "^1.10.1",
29
30
  "body-parser": "1.19.0",
30
31
  "cookie-parser": "1.4.5",
@@ -45,7 +46,8 @@
45
46
  "@types/cookie-parser": "1.4.2",
46
47
  "@types/express": "4.17.7",
47
48
  "@types/express-session": "1.17.0",
48
- "@types/node": "14.0.13",
49
+ "@types/jest": "29.5.5",
50
+ "@types/node": "^20.11.0",
49
51
  "@types/passport": "1.0.4",
50
52
  "@types/passport-local": "1.0.33",
51
53
  "@types/react": "18.2.23",
@@ -56,8 +58,11 @@
56
58
  "@typescript-eslint/parser": "7.8.0",
57
59
  "eslint": "8.57.0",
58
60
  "eslint-config-prettier": "9.1.0",
59
- "eslint-plugin-prettier": "5.1.3"
61
+ "eslint-plugin-prettier": "5.1.3",
62
+ "jest": "29.7.0",
63
+ "ts-jest": "29.1.1"
60
64
  },
61
65
  "main": "./dist/generated/index.js",
62
- "types": "./dist/generated/index.d.ts"
66
+ "types": "./dist/generated/index.d.ts",
67
+ "gitHead": "3182b24b4fc245548a39cf3eb689c5cd64f318f1"
63
68
  }
@@ -0,0 +1,132 @@
1
+ import { Server as HttpServer } from 'http';
2
+ import { ServerConfig } from '@proteinjs/server-api';
3
+ import { Logger } from '@proteinjs/logger';
4
+ import { SocketIOServerRepo } from './SocketIOServerRepo';
5
+
6
+ /**
7
+ * The one owner of the server's shutdown state. Installed by `startServer` before the listener
8
+ * opens; the `/health-check` route reads `isShuttingDown()` — no other flag system exists.
9
+ *
10
+ * Signal / exit-code contract:
11
+ * SIGTERM → drain, then exit 0:
12
+ * 1. `/health-check` flips to 503 immediately while the listener KEEPS accepting for
13
+ * `shutdown.drainDelayMs` — load balancers must OBSERVE the failing readiness and
14
+ * de-register before connections start being refused, or draining becomes user-facing
15
+ * errors. (In Kubernetes, a preStop sleep buys de-registration time BEFORE the SIGTERM
16
+ * even arrives; this window makes the server correct regardless of that wiring.)
17
+ * 2. The listener closes (socket.io clients are disconnected, and `io.close()` closes the
18
+ * http server it is attached to), idle keep-alive connections are closed, and in-flight
19
+ * requests run to completion.
20
+ * 3. The drain is BOUNDED by `shutdown.drainTimeoutMs`: past it, remaining connections are
21
+ * force-closed. Either way the exit code is 0 — a drained shutdown is not a crash.
22
+ * SIGINT → exit 0 immediately (dev ctrl-C: fast and quiet; nothing needs flushing).
23
+ * exit 86 → NOT this class's concern: `process.exit(86)` is the ServePackageSupervisor
24
+ * restart-request contract (a liveness monitor giving up on a dependency); it is not
25
+ * signal-driven and is untouched by these handlers.
26
+ *
27
+ * A SIGTERM before the listener is open (mid-boot kill) exits 0 immediately — nothing is
28
+ * registered anywhere and nothing is in flight.
29
+ *
30
+ * Supervisor compatibility (dev): ServePackageSupervisor SIGTERMs the child's process group and
31
+ * escalates to SIGKILL after its grace period (default 10s); its exit handler ignores exit codes
32
+ * for kills it initiated, so the drain-then-exit-0 shape cannot be misread. DEVELOPMENT defaults
33
+ * `drainDelayMs` to 0 so supervised restarts stay fast.
34
+ */
35
+ export class GracefulShutdown {
36
+ private static instance?: GracefulShutdown;
37
+ private shuttingDown = false;
38
+ private logger = new Logger({ name: 'GracefulShutdown' });
39
+
40
+ private constructor(
41
+ private server: HttpServer,
42
+ private config: ServerConfig
43
+ ) {}
44
+
45
+ /** Install the SIGTERM/SIGINT handlers for this process's server. Idempotent. */
46
+ static install(server: HttpServer, config: ServerConfig): void {
47
+ if (GracefulShutdown.instance) {
48
+ return;
49
+ }
50
+ const instance = new GracefulShutdown(server, config);
51
+ GracefulShutdown.instance = instance;
52
+ process.on('SIGTERM', () => void instance.drainAndExit());
53
+ process.on('SIGINT', () => instance.exitNow());
54
+ }
55
+
56
+ /** The readiness seam: `/health-check` reports 503 whenever this is true. */
57
+ static isShuttingDown(): boolean {
58
+ return GracefulShutdown.instance?.shuttingDown ?? false;
59
+ }
60
+
61
+ private async drainAndExit(): Promise<void> {
62
+ if (this.shuttingDown) {
63
+ return; // already draining; the sender's escalation is SIGKILL, not a second drain
64
+ }
65
+ this.shuttingDown = true;
66
+ if (!this.server.listening) {
67
+ this.logger.info({ message: `Received SIGTERM before the listener opened — exiting immediately` });
68
+ process.exit(0);
69
+ }
70
+ const drainDelayMs = this.drainDelayMs();
71
+ const drainTimeoutMs = this.drainTimeoutMs();
72
+ this.logger.info({
73
+ message: `Received SIGTERM — /health-check now reports 503; accepting connections for another ${drainDelayMs}ms, then draining in-flight requests (bound: ${drainTimeoutMs}ms)`,
74
+ });
75
+ // 1. Readiness-propagation window: the LB observes the 503 while we still serve normally.
76
+ await this.sleep(drainDelayMs);
77
+ // 2. Stop accepting and drain. The http 'close' event is the drain-complete signal (it
78
+ // fires once the listener is closed AND every connection has ended). socket.io's close()
79
+ // disconnects its clients (websockets would otherwise hold the drain open forever) and
80
+ // closes the http server it is attached to; closeIdleConnections reaps keep-alive
81
+ // connections that are between requests. In-flight requests run to completion.
82
+ const drained = new Promise<void>((resolve) => this.server.once('close', () => resolve()));
83
+ const io = SocketIOServerRepo.getSocketIOServerIfExists();
84
+ if (io) {
85
+ io.close();
86
+ } else {
87
+ this.server.close();
88
+ }
89
+ this.server.closeIdleConnections();
90
+ // 3. Bounded: past the drain timeout, force-close what remains. Exit 0 either way.
91
+ if (!(await this.settled(drained, drainTimeoutMs))) {
92
+ this.logger.warn({
93
+ message: `Drain exceeded its ${drainTimeoutMs}ms bound — force-closing the remaining connections`,
94
+ });
95
+ this.server.closeAllConnections();
96
+ }
97
+ this.logger.info({ message: `Drained — exiting 0` });
98
+ process.exit(0);
99
+ }
100
+
101
+ private exitNow(): void {
102
+ this.shuttingDown = true;
103
+ this.logger.info({ message: `Received SIGINT — exiting immediately` });
104
+ process.exit(0);
105
+ }
106
+
107
+ private drainDelayMs(): number {
108
+ if (typeof this.config.shutdown?.drainDelayMs === 'number') {
109
+ return this.config.shutdown.drainDelayMs;
110
+ }
111
+ return process.env.DEVELOPMENT ? 0 : 5000;
112
+ }
113
+
114
+ private drainTimeoutMs(): number {
115
+ return this.config.shutdown?.drainTimeoutMs ?? 30_000;
116
+ }
117
+
118
+ /** Await a promise with a deadline; true if it settled in time. */
119
+ private async settled(promise: Promise<void>, ms: number): Promise<boolean> {
120
+ let timer: NodeJS.Timeout | undefined;
121
+ const timedOut = new Promise<boolean>((resolve) => {
122
+ timer = setTimeout(() => resolve(false), ms);
123
+ });
124
+ const result = await Promise.race([promise.then(() => true), timedOut]);
125
+ clearTimeout(timer);
126
+ return result;
127
+ }
128
+
129
+ private sleep(ms: number): Promise<void> {
130
+ return new Promise((resolve) => setTimeout(resolve, ms));
131
+ }
132
+ }
@@ -1,10 +1,21 @@
1
1
  import { Route } from '@proteinjs/server-api';
2
+ import { GracefulShutdown } from '../GracefulShutdown';
2
3
 
4
+ /**
5
+ * Readiness: 200 while serving, 503 once GracefulShutdown has begun draining (SIGTERM
6
+ * received) — load balancers and kubelet readiness probes read this route, and the 503 is
7
+ * what makes them stop routing new traffic while in-flight requests finish.
8
+ */
3
9
  export const healthCheck: Route = {
4
10
  path: 'health-check',
5
11
  method: 'get',
6
12
  useHttp: true,
7
13
  onRequest: async (request, response): Promise<void> => {
14
+ if (GracefulShutdown.isShuttingDown()) {
15
+ response.status(503).send('draining');
16
+ return;
17
+ }
18
+
8
19
  response.send();
9
20
  },
10
21
  };
@@ -20,6 +20,7 @@ import { loadRoutes, loadDefaultStarRoute } from './loadRoutes';
20
20
  import { Logger } from '@proteinjs/logger';
21
21
  import { SocketIOServerRepo, ExtendedSocket } from './SocketIOServerRepo';
22
22
  import { DevClientBuild } from './DevClientBuild';
23
+ import { GracefulShutdown } from './GracefulShutdown';
23
24
 
24
25
  const staticContentPath = '/static/';
25
26
  const logger = new Logger({ name: 'Server' });
@@ -27,6 +28,9 @@ const app = express();
27
28
  const server = new HttpServer(app);
28
29
 
29
30
  export async function startServer(config: ServerConfig) {
31
+ // First, before any (possibly long) startup work: a SIGTERM must drain gracefully from the
32
+ // moment this process can be part of a rollout, including mid-boot.
33
+ GracefulShutdown.install(server, config);
30
34
  await runStartupTasks('before server config');
31
35
  const routes = getRoutes();
32
36
  configureRequests(app);
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Test fixture: a REAL @proteinjs/server (the built dist — the same code prod runs) with a
3
+ * deliberately slow endpoint, so the graceful-shutdown suite can hold a request in flight
4
+ * while it signals the process. Run with:
5
+ * FIXTURE_PORT=<port> [FIXTURE_DRAIN_DELAY_MS=..] [FIXTURE_DRAIN_TIMEOUT_MS=..] node gracefulShutdownServer.js
6
+ *
7
+ * Markers on stdout (the suite's synchronization points):
8
+ * FIXTURE_READY — startServer resolved (the listener is up)
9
+ * SLOW_REQUEST_STARTED — the /slow handler is executing (a request is now in flight)
10
+ */
11
+ const expressSession = require('express-session');
12
+ const { startServer } = require('../../dist/generated/index.js');
13
+
14
+ const port = Number(process.env.FIXTURE_PORT);
15
+ if (!port) {
16
+ throw new Error('FIXTURE_PORT is required');
17
+ }
18
+
19
+ startServer({
20
+ port,
21
+ session: { secret: 'graceful-shutdown-test', store: new expressSession.MemoryStore() },
22
+ request: {
23
+ disableRequestLogging: true,
24
+ // The slow endpoint rides the beforeRequest middleware seam so the fixture needs no
25
+ // reflection-registered Route of its own: it answers /slow itself (never calls next)
26
+ // after ?ms= of held work, standing in for any long in-flight request.
27
+ beforeRequest: async (request, response, next) => {
28
+ if (request.path !== '/slow') {
29
+ next();
30
+ return;
31
+ }
32
+ console.log('SLOW_REQUEST_STARTED');
33
+ const ms = Number(request.query.ms ?? 3000);
34
+ await new Promise((resolve) => setTimeout(resolve, ms));
35
+ response.status(200).send('slow-done');
36
+ },
37
+ },
38
+ shutdown: {
39
+ drainDelayMs: process.env.FIXTURE_DRAIN_DELAY_MS ? Number(process.env.FIXTURE_DRAIN_DELAY_MS) : undefined,
40
+ drainTimeoutMs: process.env.FIXTURE_DRAIN_TIMEOUT_MS ? Number(process.env.FIXTURE_DRAIN_TIMEOUT_MS) : undefined,
41
+ },
42
+ }).then(() => console.log('FIXTURE_READY'));
@@ -0,0 +1,190 @@
1
+ import * as http from 'http';
2
+ import * as net from 'net';
3
+ import * as path from 'path';
4
+ import { ChildProcess, spawn } from 'child_process';
5
+
6
+ /**
7
+ * Graceful-shutdown contract of a real server process (spawns the built dist — run
8
+ * `npm run build` first). The exit-code/signal contract these tests pin down:
9
+ *
10
+ * SIGTERM → readiness (/health-check) flips to 503 immediately while the listener stays
11
+ * open for shutdown.drainDelayMs (LBs observe the failing readiness and drain),
12
+ * then the listener closes (new connections refused), in-flight requests COMPLETE,
13
+ * idle keep-alives are closed, and the process exits 0 — bounded by
14
+ * shutdown.drainTimeoutMs (past it, remaining connections are force-closed and
15
+ * the exit is still 0).
16
+ * SIGINT → immediate exit 0 (dev ctrl-C: fast, quiet).
17
+ * exit 86 → RESTART_REQUEST_EXIT_CODE, untouched by this feature: process.exit(86) is not
18
+ * signal-driven (ServePackageSupervisor's respawn contract rides it).
19
+ */
20
+ const packageRoot = path.join(__dirname, '..');
21
+ const fixturePath = path.join(__dirname, 'fixture', 'gracefulShutdownServer.js');
22
+
23
+ type Fixture = {
24
+ child: ChildProcess;
25
+ port: number;
26
+ stdout: () => string;
27
+ waitForMarker: (marker: string, timeoutMs?: number) => Promise<void>;
28
+ exited: Promise<{ code: number | null; signal: NodeJS.Signals | null }>;
29
+ };
30
+
31
+ describe('graceful shutdown', () => {
32
+ let fixture: Fixture | undefined;
33
+
34
+ afterEach(async () => {
35
+ if (fixture && fixture.child.exitCode === null && fixture.child.signalCode === null) {
36
+ fixture.child.kill('SIGKILL');
37
+ await fixture.exited.catch(() => undefined);
38
+ }
39
+ fixture = undefined;
40
+ });
41
+
42
+ it('SIGTERM: health flips to 503, in-flight request completes, new connections refused after the delay, exit 0 within the bound', async () => {
43
+ // Generous drain delay so the 503 window is deterministic on slow CI runners.
44
+ fixture = await startFixture({ drainDelayMs: 3000, drainTimeoutMs: 10000 });
45
+
46
+ // Hold a request in flight (6s — longer than the 3s drain delay, well under the bound).
47
+ const slow = request(fixture.port, '/slow?ms=6000');
48
+ slow.catch(() => undefined); // an assertion failing earlier SIGKILLs the fixture — keep that teardown from surfacing as an unhandled rejection
49
+ await fixture.waitForMarker('SLOW_REQUEST_STARTED');
50
+
51
+ const sigtermAt = Date.now();
52
+ fixture.child.kill('SIGTERM');
53
+
54
+ // 1. Readiness fails IMMEDIATELY: a fresh connection inside the drain-delay window gets 503.
55
+ const during = await request(fixture.port, '/health-check');
56
+ expect(during.status).toBe(503);
57
+ expect(Date.now() - sigtermAt).toBeLessThan(3000); // still inside the delay window
58
+
59
+ // 2. After the delay the listener is closed: new connections are refused while the
60
+ // in-flight request is still draining.
61
+ await sleep(sigtermAt + 4000 - Date.now());
62
+ await expect(request(fixture.port, '/health-check')).rejects.toMatchObject({
63
+ code: expect.stringMatching(/ECONNREFUSED|ECONNRESET/),
64
+ });
65
+
66
+ // 3. The in-flight request COMPLETES with its full response.
67
+ const slowResult = await slow;
68
+ expect(slowResult.status).toBe(200);
69
+ expect(slowResult.body).toBe('slow-done');
70
+
71
+ // 4. The process exits 0 shortly after the drain completes — the drain ended it, not the
72
+ // timeout (slow done at ~6s; bound would land at ~13s).
73
+ const exit = await fixture.exited;
74
+ expect(exit).toEqual({ code: 0, signal: null });
75
+ expect(Date.now() - sigtermAt).toBeLessThan(10000);
76
+ }, 30000);
77
+
78
+ it('SIGTERM: the drain is BOUNDED — a request longer than drainTimeoutMs is force-closed and the exit is still 0', async () => {
79
+ fixture = await startFixture({ drainDelayMs: 0, drainTimeoutMs: 3000 });
80
+
81
+ // In-flight request that would outlive the bound by far.
82
+ const slow = request(fixture.port, '/slow?ms=60000').catch((e) => e);
83
+ await fixture.waitForMarker('SLOW_REQUEST_STARTED');
84
+
85
+ const sigtermAt = Date.now();
86
+ fixture.child.kill('SIGTERM');
87
+
88
+ const exit = await fixture.exited;
89
+ expect(exit).toEqual({ code: 0, signal: null });
90
+ const elapsed = Date.now() - sigtermAt;
91
+ expect(elapsed).toBeGreaterThanOrEqual(3000); // the bound was actually served
92
+ expect(elapsed).toBeLessThan(9000); // ...and it ended the drain, not the 60s request
93
+ await slow; // the held request errored (socket destroyed) — surfaced, not leaked
94
+ }, 30000);
95
+
96
+ it('SIGINT: fast exit 0 (dev ctrl-C)', async () => {
97
+ fixture = await startFixture({ drainDelayMs: 3000, drainTimeoutMs: 10000 });
98
+ const sigintAt = Date.now();
99
+ fixture.child.kill('SIGINT');
100
+ const exit = await fixture.exited;
101
+ expect(exit).toEqual({ code: 0, signal: null });
102
+ expect(Date.now() - sigintAt).toBeLessThan(2000); // no drain delay on the fast path
103
+ }, 30000);
104
+ });
105
+
106
+ async function startFixture(shutdown: { drainDelayMs: number; drainTimeoutMs: number }): Promise<Fixture> {
107
+ const port = await ephemeralPort();
108
+ // Scrub the env vars startServer reads (dev machines export some of these): the fixture's
109
+ // behavior must come from its own config only.
110
+ const env = { ...process.env };
111
+ delete env.SERVER_PORT;
112
+ delete env.DEVELOPMENT;
113
+ delete env.DISABLE_HOT_CLIENT_BUILDS;
114
+ delete env.HMR_PORT;
115
+ const child = spawn(process.execPath, [fixturePath], {
116
+ cwd: packageRoot,
117
+ env: {
118
+ ...env,
119
+ FIXTURE_PORT: String(port),
120
+ FIXTURE_DRAIN_DELAY_MS: String(shutdown.drainDelayMs),
121
+ FIXTURE_DRAIN_TIMEOUT_MS: String(shutdown.drainTimeoutMs),
122
+ },
123
+ stdio: ['ignore', 'pipe', 'pipe'],
124
+ });
125
+ let output = '';
126
+ child.stdout!.on('data', (chunk) => (output += String(chunk)));
127
+ child.stderr!.on('data', (chunk) => (output += String(chunk)));
128
+ const exited = new Promise<{ code: number | null; signal: NodeJS.Signals | null }>((resolve) =>
129
+ child.once('exit', (code, signal) => resolve({ code, signal }))
130
+ );
131
+ const fixture: Fixture = {
132
+ child,
133
+ port,
134
+ stdout: () => output,
135
+ waitForMarker: async (marker: string, timeoutMs = 15000) => {
136
+ const deadline = Date.now() + timeoutMs;
137
+ while (!output.includes(marker)) {
138
+ if (Date.now() > deadline) {
139
+ throw new Error(`Timed out waiting for marker ${marker}; output so far:\n${output}`);
140
+ }
141
+ await sleep(50);
142
+ }
143
+ },
144
+ exited,
145
+ };
146
+ // Ready = the health check answers 200 (readiness through the front door, not log lines).
147
+ const deadline = Date.now() + 20000;
148
+ for (;;) {
149
+ if (child.exitCode !== null || child.signalCode !== null) {
150
+ throw new Error(`Fixture exited during boot; output:\n${output}`);
151
+ }
152
+ const result = await request(port, '/health-check').catch(() => undefined);
153
+ if (result?.status === 200) {
154
+ return fixture;
155
+ }
156
+ if (Date.now() > deadline) {
157
+ throw new Error(`Fixture never became ready; output:\n${output}`);
158
+ }
159
+ await sleep(100);
160
+ }
161
+ }
162
+
163
+ /** One request on its OWN connection (agent: false — no keep-alive pooling), so listener
164
+ * refusal after close is observable instead of masked by a pooled connection. */
165
+ function request(port: number, requestPath: string): Promise<{ status: number; body: string }> {
166
+ return new Promise((resolve, reject) => {
167
+ const req = http.get({ host: '127.0.0.1', port, path: requestPath, agent: false }, (res) => {
168
+ let body = '';
169
+ res.on('data', (chunk) => (body += String(chunk)));
170
+ res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
171
+ res.on('error', reject);
172
+ });
173
+ req.on('error', reject);
174
+ });
175
+ }
176
+
177
+ async function ephemeralPort(): Promise<number> {
178
+ return new Promise((resolve, reject) => {
179
+ const probe = net.createServer();
180
+ probe.once('error', reject);
181
+ probe.listen(0, '127.0.0.1', () => {
182
+ const address = probe.address() as net.AddressInfo;
183
+ probe.close(() => resolve(address.port));
184
+ });
185
+ });
186
+ }
187
+
188
+ function sleep(ms: number): Promise<void> {
189
+ return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
190
+ }
package/tsconfig.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "noEmitOnError": true,
3
4
  "rootDir": "./",
4
5
  "target": "es5",
5
6
  "module": "commonjs",
@@ -14,5 +15,6 @@
14
15
  "forceConsistentCasingInFileNames": true,
15
16
  "resolveJsonModule": true,
16
17
  "allowJs": true
17
- }
18
+ },
19
+ "exclude": ["node_modules", "dist", "test", "jest.config.js"]
18
20
  }
@@ -1,8 +0,0 @@
1
- export let roots: string[];
2
- export let transform: {
3
- '^.+\\.tsx?$': string;
4
- };
5
- export let testRegex: string;
6
- export let moduleFileExtensions: string[];
7
- export let testEnvironment: string;
8
- //# sourceMappingURL=jest.config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jest.config.d.ts","sourceRoot":"","sources":["../jest.config.js"],"names":[],"mappings":""}
@@ -1,11 +0,0 @@
1
- "use strict";
2
- module.exports = {
3
- roots: ['<rootDir>/test'],
4
- transform: {
5
- '^.+\\.tsx?$': 'ts-jest',
6
- },
7
- testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
8
- moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
9
- testEnvironment: 'node',
10
- };
11
- //# sourceMappingURL=jest.config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jest.config.js","sourceRoot":"","sources":["../jest.config.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACf,KAAK,EAAE,CAAC,gBAAgB,CAAC;IACzB,SAAS,EAAE;QACT,aAAa,EAAE,SAAS;KACzB;IACD,SAAS,EAAE,4CAA4C;IACvD,oBAAoB,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;IAChE,eAAe,EAAE,MAAM;CACxB,CAAC"}