Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

lightship

Package Overview
Dependencies
Maintainers
1
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lightship - npm Package Compare versions

Comparing version 7.2.0 to 7.3.0

50

package.json

@@ -8,17 +8,11 @@ {

"ava": {
"extensions": [
"ts"
],
"files": [
"test/lightship/**/*"
],
"require": [
"ts-node/register/transpile-only"
]
"extensions": {
"ts": "module"
}
},
"dependencies": {
"delay": "^5.0.0",
"fastify": "^4.10.2",
"roarr": "^7.14.0",
"serialize-error": "^8.1.0"
"fastify": "^4.17.0",
"roarr": "^7.15.0",
"serialize-error": "^11.0.0"
},

@@ -35,7 +29,7 @@ "description": "Abstracts readiness, liveness and startup checks and graceful shutdown of Node.js services running in Kubernetes.",

"@types/sinon": "^10.0.13",
"ava": "^3.15.0",
"axios": "^0.24.0",
"ava": "^5.2.0",
"axios": "^1.4.0",
"coveralls": "^3.1.1",
"eslint": "^8.28.0",
"eslint-config-canonical": "^37.0.3",
"eslint": "^8.40.0",
"eslint-config-canonical": "^41.0.4",
"gitdown": "^3.1.5",

@@ -47,7 +41,18 @@ "husky": "^5.0.0",

"ts-node": "^10.9.1",
"typescript": "^4.9.3"
"tsx": "^3.12.7",
"typescript": "^5.0.4"
},
"engines": {
"node": ">=14"
"node": ">=18"
},
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": [
"src",
"dist"
],
"husky": {

@@ -62,4 +67,2 @@ "hooks": {

"license": "BSD-3-Clause",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"name": "lightship",

@@ -71,9 +74,10 @@ "repository": {

"scripts": {
"build": "rm -fr ./dist && tsc",
"build": "rm -fr ./dist && tsc --project ./tsconfig.build.json",
"generate-readme": "gitdown ./.README/README.md --output-file ./README.md",
"lint": "eslint ./src ./test",
"test": "NODE_ENV=test ava --verbose --serial",
"test": "NODE_OPTIONS='--loader=tsx --no-warnings' ava --verbose --serial",
"typecheck": "tsc --noEmit"
},
"version": "7.2.0"
"type": "module",
"version": "7.3.0"
}
/* eslint-disable promise/prefer-await-to-then */
import { Logger } from '../Logger.js';
import {
EventEmitter,
} from 'events';
import delay from 'delay';
import createFastify from 'fastify';
import {
serializeError,
} from 'serialize-error';
import Logger from '../Logger';
import {
SERVER_IS_NOT_READY,

@@ -17,15 +9,17 @@ SERVER_IS_NOT_SHUTTING_DOWN,

SERVER_IS_SHUTTING_DOWN,
} from '../states';
} from '../states.js';
import {
type BeaconContext,
type BeaconController,
type BlockingTask,
type Configuration,
type ConfigurationInput,
type Configuration,
type Lightship,
type ShutdownHandler,
type BeaconController,
} from '../types';
import {
isKubernetes,
} from '../utilities';
} from '../types.js';
import { isKubernetes } from '../utilities/isKubernetes.js';
import delay from 'delay';
import createFastify from 'fastify';
import { EventEmitter } from 'node:events';
import { serializeError } from 'serialize-error';

@@ -38,3 +32,3 @@ const log = Logger.child({

LIGHTSHIP_PORT,
// eslint-disable-next-line node/no-process-env
// eslint-disable-next-line node/no-process-env
} = process.env;

@@ -48,7 +42,3 @@

shutdownHandlerTimeout: 5_000,
signals: [
'SIGTERM',
'SIGHUP',
'SIGINT',
],
signals: ['SIGTERM', 'SIGHUP', 'SIGINT'],
terminate: () => {

@@ -61,6 +51,8 @@ // eslint-disable-next-line node/no-process-exit

type Beacon = {
context: BeaconContext,
context: BeaconContext;
};
export default async (userConfiguration?: ConfigurationInput): Promise<Lightship> => {
export const createLightship = async (
userConfiguration?: ConfigurationInput,
): Promise<Lightship> => {
let blockingTasks: BlockingTask[] = [];

@@ -87,3 +79,4 @@

const modeIsLocal = configuration.detectKubernetes === true && isKubernetes() === false;
const modeIsLocal =
configuration.detectKubernetes === true && isKubernetes() === false;

@@ -94,3 +87,5 @@ if (modeIsLocal) {

if (userConfiguration?.shutdownDelay === undefined) {
log.info('detected local mode and shutdownDelay is not configured, defaulting shutdownDelay to 0ms');
log.info(
'detected local mode and shutdownDelay is not configured, defaulting shutdownDelay to 0ms',
);

@@ -102,4 +97,8 @@ // @ts-expect-error overriding read-only value

if (configuration.gracefulShutdownTimeout < configuration.shutdownHandlerTimeout) {
throw new Error('gracefulShutdownTimeout cannot be lesser than shutdownHandlerTimeout.');
if (
configuration.gracefulShutdownTimeout < configuration.shutdownHandlerTimeout
) {
throw new Error(
'gracefulShutdownTimeout cannot be lesser than shutdownHandlerTimeout.',
);
}

@@ -125,5 +124,8 @@

app.addHook('onError', (request, reply, error, done) => {
log.error({
error: serializeError(error),
}, 'lightship error');
log.error(
{
error: serializeError(error),
},
'lightship error',
);

@@ -135,12 +137,7 @@ done();

if (serverIsShuttingDown) {
await reply
.code(500)
.send(SERVER_IS_SHUTTING_DOWN);
await reply.code(500).send(SERVER_IS_SHUTTING_DOWN);
} else if (serverIsReady) {
await reply
.send(SERVER_IS_READY);
await reply.send(SERVER_IS_READY);
} else {
await reply
.code(500)
.send(SERVER_IS_NOT_READY);
await reply.code(500).send(SERVER_IS_NOT_READY);
}

@@ -151,8 +148,5 @@ });

if (serverIsShuttingDown) {
await reply
.code(500)
.send(SERVER_IS_SHUTTING_DOWN);
await reply.code(500).send(SERVER_IS_SHUTTING_DOWN);
} else {
await reply
.send(SERVER_IS_NOT_SHUTTING_DOWN);
await reply.send(SERVER_IS_NOT_SHUTTING_DOWN);
}

@@ -163,8 +157,5 @@ });

if (isServerReady()) {
await reply
.send(SERVER_IS_READY);
await reply.send(SERVER_IS_READY);
} else {
await reply
.code(500)
.send(SERVER_IS_NOT_READY);
await reply.code(500).send(SERVER_IS_NOT_READY);
}

@@ -198,3 +189,5 @@ });

if (blockingTasks.length > 0) {
log.debug('service will not become immediately ready because there are blocking tasks');
log.debug(
'service will not become immediately ready because there are blocking tasks',
);
}

@@ -224,3 +217,6 @@

if (configuration.shutdownDelay) {
log.debug('delaying shutdown handler by %d seconds', configuration.shutdownDelay / 1_000);
log.debug(
'delaying shutdown handler by %d seconds',
configuration.shutdownDelay / 1_000,
);

@@ -248,7 +244,12 @@ await delay(configuration.shutdownDelay);

if (beacons.length > 0) {
log.info({
beacons,
} as {}, 'program termination is on hold because there are live beacons');
log.info(
{
beacons,
} as {},
'program termination is on hold because there are live beacons',
);
} else {
log.info('there are no live beacons; proceeding to terminate the Node.js process');
log.info(
'there are no live beacons; proceeding to terminate the Node.js process',
);

@@ -289,5 +290,8 @@ eventEmitter.off('beaconStateChange', check);

} catch (error) {
log.error({
error: serializeError(error),
}, 'shutdown handler produced an error');
log.error(
{
error: serializeError(error),
},
'shutdown handler produced an error',
);
}

@@ -300,3 +304,5 @@ }

log.debug('all shutdown handlers have run to completion; proceeding to terminate the Node.js process');
log.debug(
'all shutdown handlers have run to completion; proceeding to terminate the Node.js process',
);

@@ -306,8 +312,8 @@ void app.close();

setTimeout(() => {
log.warn('process did not exit on its own; investigate what is keeping the event loop active');
log.warn(
'process did not exit on its own; investigate what is keeping the event loop active',
);
configuration.terminate();
}, 1_000)
.unref();
}, 1_000).unref();
};

@@ -320,5 +326,8 @@

process.on(signal, () => {
log.debug({
signal,
}, 'received a shutdown signal');
log.debug(
{
signal,
},
'received a shutdown signal',
);

@@ -339,5 +348,8 @@ void shutdown(false);

die: async () => {
log.trace({
beacon,
} as {}, 'beacon has been killed');
log.trace(
{
beacon,
} as {},
'beacon has been killed',
);

@@ -353,11 +365,16 @@ beacons.splice(beacons.indexOf(beacon), 1);

void deferredFirstReady.then(() => {
log.info('service became available for the first time');
}).catch(async (error) => {
log.error({
error: serializeError(error),
}, 'service failed to become available for the first time');
void deferredFirstReady
.then(() => {
log.info('service became available for the first time');
})
.catch(async (error) => {
log.error(
{
error: serializeError(error),
},
'service failed to become available for the first time',
);
await shutdown(false);
});
await shutdown(false);
});

@@ -373,11 +390,13 @@ return {

void blockingTask.then(() => {
blockingTasks = blockingTasks.filter((maybeTargetBlockingTask) => {
return maybeTargetBlockingTask !== blockingTask;
});
void blockingTask
.then(() => {
blockingTasks = blockingTasks.filter((maybeTargetBlockingTask) => {
return maybeTargetBlockingTask !== blockingTask;
});
if (blockingTasks.length === 0 && serverIsReady === true) {
resolveFirstReady();
}
}).catch(rejectFirstReady);
if (blockingTasks.length === 0 && serverIsReady === true) {
resolveFirstReady();
}
})
.catch(rejectFirstReady);
},

@@ -384,0 +403,0 @@ registerShutdownHandler: (shutdownHandler) => {

@@ -1,8 +0,6 @@

export {
default as createLightship,
} from './factories/createLightship';
export { createLightship } from './factories/createLightship.js';
export type {
BeaconController,
ConfigurationInput,
Lightship,
ConfigurationInput,
BeaconController,
} from './types';
} from './types.js';

@@ -1,7 +0,5 @@

import {
Roarr,
} from 'roarr';
import { Roarr } from 'roarr';
export default Roarr.child({
export const Logger = Roarr.child({
package: 'lightship',
});

@@ -1,4 +0,2 @@

import {
type State,
} from './types';
import { type State } from './types.js';

@@ -10,4 +8,6 @@ const createState = <TState extends State>(subject: TState): TState => {

export const SERVER_IS_NOT_READY = createState('SERVER_IS_NOT_READY');
export const SERVER_IS_NOT_SHUTTING_DOWN = createState('SERVER_IS_NOT_SHUTTING_DOWN');
export const SERVER_IS_NOT_SHUTTING_DOWN = createState(
'SERVER_IS_NOT_SHUTTING_DOWN',
);
export const SERVER_IS_READY = createState('SERVER_IS_READY');
export const SERVER_IS_SHUTTING_DOWN = createState('SERVER_IS_SHUTTING_DOWN');

@@ -1,4 +0,2 @@

import {
type Server,
} from 'http';
import { type Server } from 'node:http';

@@ -20,27 +18,27 @@ /**

export type ConfigurationInput = {
readonly detectKubernetes?: boolean,
readonly gracefulShutdownTimeout?: number,
readonly port?: number,
readonly shutdownDelay?: number,
readonly shutdownHandlerTimeout?: number,
readonly signals?: readonly string[],
readonly terminate?: () => void,
readonly detectKubernetes?: boolean;
readonly gracefulShutdownTimeout?: number;
readonly port?: number;
readonly shutdownDelay?: number;
readonly shutdownHandlerTimeout?: number;
readonly signals?: readonly string[];
readonly terminate?: () => void;
};
export type Configuration = {
readonly detectKubernetes: boolean,
readonly gracefulShutdownTimeout: number,
readonly port: number,
readonly shutdownDelay: number,
readonly shutdownHandlerTimeout: number,
readonly signals: readonly string[],
readonly terminate: () => void,
readonly detectKubernetes: boolean;
readonly gracefulShutdownTimeout: number;
readonly port: number;
readonly shutdownDelay: number;
readonly shutdownHandlerTimeout: number;
readonly signals: readonly string[];
readonly terminate: () => void;
};
export type BeaconContext = {
[key: string]: unknown,
[key: string]: unknown;
};
export type BeaconController = {
readonly die: () => Promise<void>,
readonly die: () => Promise<void>;
};

@@ -50,3 +48,7 @@

export type State = 'SERVER_IS_NOT_READY' | 'SERVER_IS_NOT_SHUTTING_DOWN' | 'SERVER_IS_READY' | 'SERVER_IS_SHUTTING_DOWN';
export type State =
| 'SERVER_IS_NOT_READY'
| 'SERVER_IS_NOT_SHUTTING_DOWN'
| 'SERVER_IS_READY'
| 'SERVER_IS_SHUTTING_DOWN';

@@ -61,12 +63,12 @@ /**

export type Lightship = {
readonly createBeacon: (context?: BeaconContext) => BeaconController,
readonly isServerReady: () => boolean,
readonly isServerShuttingDown: () => boolean,
readonly queueBlockingTask: (blockingTask: BlockingTask) => void,
readonly registerShutdownHandler: (shutdownHandler: ShutdownHandler) => void,
readonly server: Server,
readonly shutdown: () => Promise<void>,
readonly signalNotReady: () => void,
readonly signalReady: () => void,
readonly whenFirstReady: () => Promise<void>,
readonly createBeacon: (context?: BeaconContext) => BeaconController;
readonly isServerReady: () => boolean;
readonly isServerShuttingDown: () => boolean;
readonly queueBlockingTask: (blockingTask: BlockingTask) => void;
readonly registerShutdownHandler: (shutdownHandler: ShutdownHandler) => void;
readonly server: Server;
readonly shutdown: () => Promise<void>;
readonly signalNotReady: () => void;
readonly signalReady: () => void;
readonly whenFirstReady: () => Promise<void>;
};

@@ -1,4 +0,4 @@

export default (): boolean => {
export const isKubernetes = (): boolean => {
// eslint-disable-next-line node/no-process-env
return Boolean(process.env.KUBERNETES_SERVICE_HOST);
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc