@saber-usa/node-common 1.7.5 → 1.7.6

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/README.md CHANGED
@@ -1,42 +1,42 @@
1
- # Saber Common node functions
2
-
3
- The contains common node functions used across saber applications
4
-
5
- ## Logger
6
-
7
- The logger component is a standard logger based on [winston](https://github.com/winstonjs/winston). The logger factory
8
- creates a default console logger for errors along with exception/rejection catching. By setting the `CONSOLE_LOG`
9
- variable to `true` will turn on the console logger for local development. The log level is configured by the `LOG_LEVEL`
10
- environment variable to one of the following levels: `emerg`, `alert`, `crit`, `error`, `warning`, `warn`, `notice`,
11
- `info`, `debug` (default level is `error`). The reason using an environment variable for the level is useful when
12
- deployed to the server. Changing the environment variable is easier than setting a new flag in the script execution.
13
-
14
- ### Usage
15
-
16
- To create a new logger, just pass in options to the factory:
17
-
18
- ```javascript
19
- const logger = loggerFactory(opts);
20
-
21
- logger.debug("This is a debug message");
22
- ```
23
-
24
- For further usage, consult [winston](https://github.com/winstonjs/winston)
25
-
26
- ### Options
27
-
28
- - `nameSpace` help distinguish where the logger message comes from.
29
- - `additionalData` Data to include with each message
30
- - `level` overwrite the `LOG_LEVEL` environment level
31
-
32
- ## Transformer
33
-
34
- A transformer for object keys is provided. This will take an object and transform the keys using a function.
35
-
36
- ## Publishing changes
37
-
38
- 1. Change the version in package.json
39
- 2. Run `npm publish && npm install`
40
- 3. Enable GPG in GIT: `git config --global commit.gpgsign true`
41
- 4. Run `gpg --list-keys` to get your <id>
1
+ # Saber Common node functions
2
+
3
+ The contains common node functions used across saber applications
4
+
5
+ ## Logger
6
+
7
+ The logger component is a standard logger based on [winston](https://github.com/winstonjs/winston). The logger factory
8
+ creates a default console logger for errors along with exception/rejection catching. By setting the `CONSOLE_LOG`
9
+ variable to `true` will turn on the console logger for local development. The log level is configured by the `LOG_LEVEL`
10
+ environment variable to one of the following levels: `emerg`, `alert`, `crit`, `error`, `warning`, `warn`, `notice`,
11
+ `info`, `debug` (default level is `error`). The reason using an environment variable for the level is useful when
12
+ deployed to the server. Changing the environment variable is easier than setting a new flag in the script execution.
13
+
14
+ ### Usage
15
+
16
+ To create a new logger, just pass in options to the factory:
17
+
18
+ ```javascript
19
+ const logger = loggerFactory(opts);
20
+
21
+ logger.debug("This is a debug message");
22
+ ```
23
+
24
+ For further usage, consult [winston](https://github.com/winstonjs/winston)
25
+
26
+ ### Options
27
+
28
+ - `nameSpace` help distinguish where the logger message comes from.
29
+ - `additionalData` Data to include with each message
30
+ - `level` overwrite the `LOG_LEVEL` environment level
31
+
32
+ ## Transformer
33
+
34
+ A transformer for object keys is provided. This will take an object and transform the keys using a function.
35
+
36
+ ## Publishing changes
37
+
38
+ 1. Change the version in package.json
39
+ 2. Run `npm publish && npm install`
40
+ 3. Enable GPG in GIT: `git config --global commit.gpgsign true`
41
+ 4. Run `gpg --list-keys` to get your <id>
42
42
  5. Tell the GIT to use your key `git config user.signingkey <id>`
package/package.json CHANGED
@@ -1,51 +1,51 @@
1
- {
2
- "name": "@saber-usa/node-common",
3
- "version": "1.7.5",
4
- "description": "Common node functions for Saber",
5
- "main": "src/index.js",
6
- "type": "module",
7
- "scripts": {
8
- "lint": "eslint . --ext js",
9
- "lint:fix": "eslint . --ext js --fix",
10
- "test": "jest --no-coverage --silent",
11
- "test:unit": "jest --coverage --runInBand --no-watch",
12
- "sonar": "node --experimental-vm-modules sonar-project.js"
13
- },
14
- "files": [
15
- "src/**/*"
16
- ],
17
- "author": "Saber USA",
18
- "license": "ISC",
19
- "dependencies": {
20
- "@aws-sdk/client-s3": "^3.666.0",
21
- "date-fns": "^4.1.0",
22
- "lodash": "4.17.21",
23
- "mathjs": "^14.7.0",
24
- "pious-squid": "^2.3.0",
25
- "plotly": "^1.0.6",
26
- "satellite.js": "^6.0.1",
27
- "solar-calculator": "^0.3.0",
28
- "three": "^0.178.0",
29
- "winston": "3.3.3"
30
- },
31
- "devDependencies": {
32
- "@babel/core": "7.16.0",
33
- "@babel/eslint-parser": "7.16.3",
34
- "@babel/plugin-transform-modules-commonjs": "7.16.0",
35
- "@jest/globals": "27.4.4",
36
- "eslint-config-google": "0.14.0",
37
- "eslint-plugin-jest": "25.3.0",
38
- "jest": "29.7.0",
39
- "jest-diff": "29.7.0",
40
- "nodemon": "3.1.4",
41
- "sonarqube-scanner": "3.0.1"
42
- },
43
- "overrides": {
44
- "braces": "3.0.3"
45
- },
46
- "babel": {
47
- "plugins": [
48
- "@babel/plugin-transform-modules-commonjs"
49
- ]
50
- }
51
- }
1
+ {
2
+ "name": "@saber-usa/node-common",
3
+ "version": "1.7.6",
4
+ "description": "Common node functions for Saber",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "lint": "eslint . --ext js",
9
+ "lint:fix": "eslint . --ext js --fix",
10
+ "test": "jest --no-coverage --silent",
11
+ "test:unit": "jest --coverage --runInBand --no-watch",
12
+ "sonar": "node --experimental-vm-modules sonar-project.js"
13
+ },
14
+ "files": [
15
+ "src/**/*"
16
+ ],
17
+ "author": "Saber USA",
18
+ "license": "ISC",
19
+ "dependencies": {
20
+ "@aws-sdk/client-s3": "^3.666.0",
21
+ "date-fns": "^4.1.0",
22
+ "lodash": "4.17.21",
23
+ "mathjs": "^14.7.0",
24
+ "pious-squid": "^2.3.0",
25
+ "plotly": "^1.0.6",
26
+ "satellite.js": "^6.0.1",
27
+ "solar-calculator": "^0.3.0",
28
+ "three": "^0.178.0",
29
+ "winston": "3.3.3"
30
+ },
31
+ "devDependencies": {
32
+ "@babel/core": "7.16.0",
33
+ "@babel/eslint-parser": "7.16.3",
34
+ "@babel/plugin-transform-modules-commonjs": "7.16.0",
35
+ "@jest/globals": "27.4.4",
36
+ "eslint-config-google": "0.14.0",
37
+ "eslint-plugin-jest": "25.3.0",
38
+ "jest": "29.7.0",
39
+ "jest-diff": "29.7.0",
40
+ "nodemon": "3.1.4",
41
+ "sonarqube-scanner": "3.0.1"
42
+ },
43
+ "overrides": {
44
+ "braces": "3.0.3"
45
+ },
46
+ "babel": {
47
+ "plugins": [
48
+ "@babel/plugin-transform-modules-commonjs"
49
+ ]
50
+ }
51
+ }
@@ -21,8 +21,6 @@ const ReferenceFrame = {
21
21
  };
22
22
 
23
23
  class LaunchNominalClass {
24
-
25
-
26
24
  /** Get position at a given time in specified reference frame
27
25
  *
28
26
  * @param {Date} utc - UTC time
package/src/astro.js CHANGED
@@ -42,7 +42,8 @@ import {DEG2RAD,
42
42
  WGS72_EARTH_EQUATORIAL_RADIUS_KM,
43
43
  WGS84_EARTH_EQUATORIAL_RADIUS_KM,
44
44
  MILLIS_PER_DAY,
45
- GEO_ALTITUDE_KM} from "./constants.js";
45
+ GEO_ALTITUDE_KM,
46
+ ERROR_CODES} from "./constants.js";
46
47
 
47
48
  // Solar Terminator
48
49
  // Returns sun latitude and longitude as -180/180
@@ -74,6 +75,98 @@ const checkTle = (line1, line2) => {
74
75
  }
75
76
  };
76
77
 
78
+ /**
79
+ * Validates the output of the satellite.js propagate function.
80
+ * The satellite.js propagate function returns a object with the following properties:
81
+ * - position: {x: number, y: number, z: number}
82
+ * - velocity: {x: number, y: number, z: number}
83
+ * - meanElements: {am: number, em: number, im: number, Om: number, om: number, nm: number, mm: number}
84
+ *
85
+ * When propgation fails, the output is null. However, there are cases where the output is not null, but the position and velocity are NaN.
86
+ * This happens when the input satrec is invalid or malformed due to a bad TLE, in some way. This is rare, and hard to reproduce.
87
+ *
88
+ * This function takes into account those rare cases as part of the validation.
89
+ *
90
+ * @param {Object} out The output of the satellite.js propagate function.
91
+ * @return {boolean} true if the propagation output is valid, false otherwise
92
+ */
93
+ const isPropagateValid = (out) => {
94
+ if (out === null || out === undefined) {
95
+ return false;
96
+ }
97
+
98
+ if (out.position) {
99
+ const pos = out.position;
100
+ if (pos.x === null || pos.x === undefined || Number.isNaN(pos.x)
101
+ || pos.y === null || pos.y === undefined || Number.isNaN(pos.y)
102
+ || pos.z === null || pos.z === undefined || Number.isNaN(pos.z)) {
103
+ return false;
104
+ }
105
+ }
106
+
107
+ if (out.velocity) {
108
+ const vel = out.velocity;
109
+ if (vel.x === null || vel.x === undefined || Number.isNaN(vel.x)
110
+ || vel.y === null || vel.y === undefined || Number.isNaN(vel.y)
111
+ || vel.z === null || vel.z === undefined || Number.isNaN(vel.z)) {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ return true;
117
+ };
118
+
119
+ /** A function that attempts to propagate a satellite record to a given time, and returns a standardized output object.
120
+ *
121
+ * @param {Object} satrec The satellite record from satellite.js
122
+ * @param {Date} time The time to propagate the satellite to
123
+ * @return {Object} An object with the following properties:
124
+ * - ok: 0 or 1
125
+ * - err: null or an error message
126
+ * - out: null or the output of the satellite.js propagate function
127
+ */
128
+ const tryPropagateSatrec = (satrec, time) => {
129
+ // Validate time
130
+ if (!time || !(time instanceof Date)) {
131
+ return {
132
+ ok: 0,
133
+ err: ERROR_CODES.INVALID_TIME_INPUT,
134
+ out: null,
135
+ };
136
+ }
137
+ // Validate satrec
138
+ if (!satrec) {
139
+ return {
140
+ ok: 0,
141
+ err: ERROR_CODES.INVALID_SATELLITE_RECORD,
142
+ out: null,
143
+ };
144
+ }
145
+ // Propagate
146
+ try {
147
+ const out = propagate(satrec, time);
148
+ // Validate propagate output
149
+ if (!isPropagateValid(out)) {
150
+ return {
151
+ ok: 0,
152
+ err: ERROR_CODES.INVALID_PROPAGATE_OUTPUT + `: ${satrec.error}`,
153
+ out: null,
154
+ };
155
+ }
156
+ return {
157
+ ok: 1,
158
+ err: null,
159
+ out: out,
160
+ };
161
+ } catch (e) {
162
+ return {
163
+ ok: 0,
164
+ err: ERROR_CODES.INVALID_PROPAGATE_OUTPUT + `: ${e.message}`,
165
+ out: null,
166
+ };
167
+ }
168
+ };
169
+
77
170
  /**
78
171
  * Calculates the semi-major axis in kilometers from a satellite record.
79
172
  * @param {Object} satrec The satellite record from satellite.js
@@ -3209,6 +3302,7 @@ export {REGIMES,
3209
3302
  getRaanDetails,
3210
3303
  isSatInShadow,
3211
3304
  calculateGeoCrossingTimes,
3305
+ tryPropagateSatrec,
3212
3306
  };
3213
3307
  export const raDecToGeodetic = RaDecToGeodetic;
3214
3308
  export const getResiduals = GetResiduals;
@@ -1,20 +1,20 @@
1
- const _ = require("lodash");
2
- const {resolve4} = require("dns").promises;
3
-
4
-
5
- const checkRecord = (hostName) => resolve4(hostName).
6
- then((addresss) => !_.isEmpty(addresss)).
7
- catch(_.stubFalse);
8
-
9
-
10
- module.exports.checkRecord = checkRecord;
11
- module.exports.checkNetwork = (domains) => Promise.all(
12
- _.map(
13
- domains,
14
- (hostName) => checkRecord(hostName).
15
- then((found) => found
16
- ? hostName
17
- : null,
18
- ),
19
- ),
20
- ).then((resolved) => _.flow(_.compact, _.first)(resolved) || null);
1
+ const _ = require("lodash");
2
+ const {resolve4} = require("dns").promises;
3
+
4
+
5
+ const checkRecord = (hostName) => resolve4(hostName).
6
+ then((addresss) => !_.isEmpty(addresss)).
7
+ catch(_.stubFalse);
8
+
9
+
10
+ module.exports.checkRecord = checkRecord;
11
+ module.exports.checkNetwork = (domains) => Promise.all(
12
+ _.map(
13
+ domains,
14
+ (hostName) => checkRecord(hostName).
15
+ then((found) => found
16
+ ? hostName
17
+ : null,
18
+ ),
19
+ ),
20
+ ).then((resolved) => _.flow(_.compact, _.first)(resolved) || null);
package/src/constants.js CHANGED
@@ -28,3 +28,8 @@ export const REGIMES = {
28
28
  GeoDrifter: 512,
29
29
  };
30
30
 
31
+ export const ERROR_CODES = {
32
+ INVALID_TIME_INPUT: "Invalid time input",
33
+ INVALID_SATELLITE_RECORD: "Invalid satellite record",
34
+ INVALID_PROPAGATE_OUTPUT: "Invalid propagate output",
35
+ };
@@ -1,98 +1,98 @@
1
- const winston = require("winston");
2
- const {
3
- createLogger,
4
- format,
5
- transports,
6
- } = winston;
7
- const cj = (data) => Object.keys(data).length > 0
8
- ? JSON.stringify(data, null, 2)
9
- : null;
10
-
11
- const isTest = process.env.NODE_ENV === "test";
12
-
13
- const defaultLogger = new transports.Console({
14
- silent: isTest,
15
- level: "warn",
16
- format: format.errors({stack: true}),
17
- timestamp: true,
18
- });
19
-
20
- const errorLogger = new transports.Console({
21
- silent: isTest,
22
- format: format.errors({stack: true}),
23
- });
24
-
25
- /**
26
- * Creates a logger
27
- *
28
- * @param {String} nameSpace Namespace for the logger
29
- * @param {Object} additionalData additional data to include with logging
30
- * @param {string} level Default logging level to set (overwrites environment setting)
31
- * @return {winston.Logger}
32
- */
33
- module.exports.loggerFactory = ({
34
- nameSpace = "saber",
35
- additionalData = {},
36
- level,
37
- } = {}) => {
38
- const logLevel = process.env.LOG_LEVEL || "warn";
39
- const isConsole = !!(process.env.CONSOLE_LOG);
40
-
41
- const loggerTransport = isConsole
42
- ? new transports.Console({
43
- defaultMeta: additionalData,
44
- level: level || logLevel,
45
- format: format.combine(
46
- format.errors({stack: true}),
47
- format.cli(),
48
- // eslint-disable-next-line max-len
49
- format.printf(({
50
- level,
51
- message,
52
- nameSpace,
53
- stack,
54
- ...rest
55
- }) =>
56
- [
57
- level,
58
- `[${nameSpace}]`,
59
- ":",
60
- message,
61
- stack,
62
- cj(rest),
63
- ].filter((value) => !!value)
64
- .join(" "),
65
- ),
66
- ),
67
- })
68
- : defaultLogger;
69
-
70
- const config = {
71
- levels: {
72
- // RFC5424
73
- emerg: 0,
74
- alert: 1,
75
- crit: 2,
76
- error: 3,
77
- warning: 4,
78
- notice: 5,
79
- info: 6,
80
- debug: 7,
81
- // npm levels
82
- warn: 4,
83
- verbose: 6,
84
- silly: 8,
85
- },
86
- exitOnError: false,
87
- transports: [loggerTransport],
88
- // Console logger from above will log errors
89
- exceptionHandlers: !isConsole ? [errorLogger] : [],
90
- rejectionHandlers: !isConsole ? [errorLogger] : [],
91
- };
92
-
93
- return createLogger(config)
94
- .child({
95
- ...additionalData,
96
- nameSpace: nameSpace,
97
- });
98
- }
1
+ const winston = require("winston");
2
+ const {
3
+ createLogger,
4
+ format,
5
+ transports,
6
+ } = winston;
7
+ const cj = (data) => Object.keys(data).length > 0
8
+ ? JSON.stringify(data, null, 2)
9
+ : null;
10
+
11
+ const isTest = process.env.NODE_ENV === "test";
12
+
13
+ const defaultLogger = new transports.Console({
14
+ silent: isTest,
15
+ level: "warn",
16
+ format: format.errors({stack: true}),
17
+ timestamp: true,
18
+ });
19
+
20
+ const errorLogger = new transports.Console({
21
+ silent: isTest,
22
+ format: format.errors({stack: true}),
23
+ });
24
+
25
+ /**
26
+ * Creates a logger
27
+ *
28
+ * @param {String} nameSpace Namespace for the logger
29
+ * @param {Object} additionalData additional data to include with logging
30
+ * @param {string} level Default logging level to set (overwrites environment setting)
31
+ * @return {winston.Logger}
32
+ */
33
+ module.exports.loggerFactory = ({
34
+ nameSpace = "saber",
35
+ additionalData = {},
36
+ level,
37
+ } = {}) => {
38
+ const logLevel = process.env.LOG_LEVEL || "warn";
39
+ const isConsole = !!(process.env.CONSOLE_LOG);
40
+
41
+ const loggerTransport = isConsole
42
+ ? new transports.Console({
43
+ defaultMeta: additionalData,
44
+ level: level || logLevel,
45
+ format: format.combine(
46
+ format.errors({stack: true}),
47
+ format.cli(),
48
+ // eslint-disable-next-line max-len
49
+ format.printf(({
50
+ level,
51
+ message,
52
+ nameSpace,
53
+ stack,
54
+ ...rest
55
+ }) =>
56
+ [
57
+ level,
58
+ `[${nameSpace}]`,
59
+ ":",
60
+ message,
61
+ stack,
62
+ cj(rest),
63
+ ].filter((value) => !!value)
64
+ .join(" "),
65
+ ),
66
+ ),
67
+ })
68
+ : defaultLogger;
69
+
70
+ const config = {
71
+ levels: {
72
+ // RFC5424
73
+ emerg: 0,
74
+ alert: 1,
75
+ crit: 2,
76
+ error: 3,
77
+ warning: 4,
78
+ notice: 5,
79
+ info: 6,
80
+ debug: 7,
81
+ // npm levels
82
+ warn: 4,
83
+ verbose: 6,
84
+ silly: 8,
85
+ },
86
+ exitOnError: false,
87
+ transports: [loggerTransport],
88
+ // Console logger from above will log errors
89
+ exceptionHandlers: !isConsole ? [errorLogger] : [],
90
+ rejectionHandlers: !isConsole ? [errorLogger] : [],
91
+ };
92
+
93
+ return createLogger(config)
94
+ .child({
95
+ ...additionalData,
96
+ nameSpace: nameSpace,
97
+ });
98
+ }