mentie 0.1.15 → 0.1.18

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/modules/cache.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { log } from "./logging"
2
+
1
3
  /**
2
4
  * Cache object for storing data.
3
5
  * @type {Object}
@@ -15,6 +17,17 @@ const _cache = {}
15
17
  * @returns {*} The cached value.
16
18
  */
17
19
  export function cache( key, value ) {
20
+
21
+ // If the key is undefined, log a warning
22
+ if( key === undefined ) {
23
+ log.warn( `The cache key is undefined, this may indicate a bug in your cache logic` )
24
+ }
25
+
26
+ // Warn if the key contains 'undefined'
27
+ if( key.includes( 'undefined' ) ) {
28
+ log.warn( `The cache key ${ key } contains 'undefined', this may indicate a bug in your cache logic` )
29
+ }
30
+
18
31
  if( value ) _cache[key] = value
19
32
  return _cache[key]
20
33
  }
@@ -2,61 +2,128 @@
2
2
  // Platform and environment detection
3
3
  // ///////////////////////////////
4
4
 
5
+
6
+
7
+ /**
8
+ * Environment checks for various runtime contexts.
9
+ * Useful in compiled code where the runtime environment may not be known at compile time.
10
+ * @namespace
11
+ */
12
+ export const env = {}
13
+
14
+ /**
15
+ * Determines if the current runtime environment is a web browser.
16
+ * @returns {boolean} True if running in a web environment, otherwise false.
17
+ */
18
+ env.is_web = () => typeof window !== 'undefined'
19
+
20
+ /**
21
+ * Checks if the code is running in the Cypress testing environment within a web browser.
22
+ * @returns {boolean} True if running in Cypress, otherwise false.
23
+ */
24
+ env.is_cypress = () => env.is_web() && typeof window.Cypress !== 'undefined'
25
+
26
+ /**
27
+ * Determines if the current runtime environment is Node.js.
28
+ * @returns {boolean} True if running in Node.js, otherwise false.
29
+ */
30
+ env.is_node = () => typeof process !== 'undefined' && process.versions && process.versions?.node
31
+
32
+ /**
33
+ * Checks if the code is running in an emulator environment in Node.js.
34
+ * @returns {boolean} True if running in a Node.js emulator, otherwise false.
35
+ */
36
+ env.is_emulator = () => env.is_node() && process.env?.FUNCTIONS_EMULATOR === 'true'
37
+
38
+ /**
39
+ * Determines if the Node.js environment is in development mode.
40
+ * @returns {boolean} True if NODE_ENV is 'development', otherwise false.
41
+ */
42
+ env.node_dev = () => typeof process !== 'undefined' && process.env?.NODE_ENV === 'development'
43
+
44
+ /**
45
+ * Determines if the web environment is in development mode.
46
+ * @returns {boolean} True if the URL includes 'debug=true' or 'localhost', otherwise false.
47
+ */
48
+ env.web_dev = () => typeof location !== 'undefined' && ( `${ location.href }`.includes( 'debug=true' ) || `${ location.href }`.includes( 'localhost' ) )
49
+
50
+ /**
51
+ * Determines if the environment is in development mode (either web or Node.js).
52
+ * @returns {boolean} True if either web_dev or node_dev returns true, otherwise false.
53
+ */
54
+ env.dev = () => env.node_dev() || env.web_dev()
55
+
56
+ /**
57
+ * Retrieves the log level set via URL parameters in a web environment.
58
+ * @returns {string|null} The log level from URL parameters, or null if not set.
59
+ */
60
+ env.web_loglevel = () => env.is_web() && new URLSearchParams( location?.search ).get( 'loglevel' )
61
+
62
+ /**
63
+ * Retrieves the log level set via environment variables in a Node.js environment.
64
+ * @returns {string|undefined} The log level from environment variables, or undefined if not set.
65
+ */
66
+ env.node_loglevel = () => env.is_node() && process.env?.LOG_LEVEL
67
+
68
+ /**
69
+ * Retrieves the effective log level based on the environment. Defaults to 'info' in development environments, 'error' otherwise.
70
+ * @returns {string} The determined log level.
71
+ */
72
+ env.loglevel = () => env.web_loglevel() || env.node_loglevel() || env.dev() ? 'info' : 'error'
73
+
74
+
5
75
  /**
6
76
  * Checks if the code is running in a web environment.
7
77
  * @returns {boolean} Returns true if the code is running in a web environment, otherwise returns false.
8
78
  */
9
- export const is_web = typeof window !== 'undefined'
79
+ export const is_web = env.is_web()
10
80
 
11
81
  /**
12
82
  * Checks if the code is running within a Cypress environment.
13
83
  * @returns {boolean} Returns true if the code is running in a Cypress environment, otherwise returns false.
14
84
  */
15
- export const is_cypress = is_web && typeof window.Cypress !== 'undefined'
85
+ export const is_cypress = env.is_cypress()
16
86
 
17
87
  /**
18
88
  * Checks if the code is running in a Node environment.
19
89
  * @returns {boolean} Returns true if the code is running in a Node environment, otherwise returns false.
20
90
  */
21
- export const is_node = typeof process !== 'undefined' && process.versions && process.versions?.node
91
+ export const is_node = env.is_node()
22
92
 
23
93
  /**
24
94
  * Checks if the code is running in a Firebase functions emulator environment.
25
95
  * @returns {boolean} Returns true if the code is running in a Firebase environment, otherwise returns false.
26
96
  */
27
- export const is_emulator = typeof process !== 'undefined' && process.env?.FUNCTIONS_EMULATOR === 'true'
97
+ export const is_emulator = env.is_emulator()
28
98
 
29
99
  // ///////////////////////////////
30
100
  // Mode and loglevel detection
31
101
  // ///////////////////////////////
32
102
 
33
- const node_dev = typeof process !== 'undefined' && process.env?.NODE_ENV === 'development'
34
- const web_dev = typeof location !== 'undefined' && ( `${ location.href }`.includes( 'debug=true' ) || `${ location.href }`.includes( 'localhost' ) )
35
-
36
103
  /**
37
104
  * Represents the development environment.
38
105
  * @type {boolean}
39
106
  */
40
- export const dev = node_dev || web_dev
107
+ export const dev = env.dev()
41
108
 
42
109
  /**
43
110
  * The log level for web applications.
44
111
  * @type {string} - Log level. Valid values are: 'info', 'warn', 'error'
45
112
  */
46
- export const web_loglevel = is_web && new URLSearchParams( location?.search ).get( 'loglevel' )
113
+ export const web_loglevel = env.web_loglevel()
47
114
 
48
115
  /**
49
116
  * The log level for the Node environment.
50
117
  * @type {string} - Log level. Valid values are: 'info', 'warn', 'error'
51
118
  */
52
- export const node_loglevel = typeof process !== 'undefined' && process.env?.LOG_LEVEL
119
+ export const node_loglevel = env.node_loglevel()
53
120
 
54
121
 
55
122
  /**
56
123
  * The log level used in the environment.
57
124
  * @type {string}
58
125
  */
59
- export const loglevel = web_loglevel || node_loglevel || dev ? 'info' : 'error'
126
+ export const loglevel = env.loglevel()
60
127
 
61
128
 
62
129
  /**
@@ -1,8 +1,10 @@
1
1
  // Import environment data
2
- import { dev, is_cypress, is_emulator, loglevel } from "./environment.js"
2
+ import { dev, env } from "./environment.js"
3
3
 
4
4
  const should_log = levels => {
5
5
 
6
+ const loglevel = env.loglevel()
7
+
6
8
  // Check if the loglevel matches this call
7
9
  const valid_levels = [ 'info', 'warn', 'error' ]
8
10
 
@@ -63,7 +65,7 @@ const annotate_messages = messages => {
63
65
 
64
66
 
65
67
  // If we are running in cypress, stringify the messages because they become unavailable in the console
66
- if( is_cypress ) {
68
+ if( env.is_cypress() ) {
67
69
 
68
70
  try {
69
71
  messages = messages.map( message => JSON.stringify( message, null, 2 ) )
@@ -122,7 +124,7 @@ log.info = function( ...messages ) {
122
124
  const levels = [ 'info' ]
123
125
 
124
126
  // Log the messages if the loglevel matches
125
- if( is_emulator || should_log( levels ) ) {
127
+ if( env.is_emulator() || should_log( levels ) ) {
126
128
 
127
129
  // Annotate the provided messages
128
130
  annotate_messages( messages )
@@ -170,7 +172,7 @@ log.error = function( ...messages ) {
170
172
 
171
173
  // Check if the loglevel matches this call
172
174
  const levels = [ 'error', 'warn', 'info' ]
173
- const should_log = dev || levels.includes( loglevel )
175
+ const should_log = dev || levels.includes( env.loglevel() )
174
176
  if( !dev || !should_log ) return
175
177
 
176
178
  // Log the messages if the loglevel matches
@@ -180,4 +182,4 @@ log.error = function( ...messages ) {
180
182
  }
181
183
 
182
184
  // Set the loglevel on the log function
183
- log.loglevel = loglevel
185
+ log.loglevel = env.loglevel()
@@ -11,4 +11,56 @@ export const email_regex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/
11
11
  * @param {string} string - The string to be sanitized.
12
12
  * @returns {string} - The sanitized string.
13
13
  */
14
- export const sanetise_string = string => `${ string }`.trim().toLowerCase()
14
+ export const sanetise_string = string => `${ string }`.trim().toLowerCase()
15
+
16
+
17
+ /**
18
+ * Checks if an object contains all the required properties.
19
+ * @param {Object} obj - The object to check.
20
+ * @param {Array} required_properties - The array of required properties.
21
+ * @param {boolean} [error_on_fail=true] - Determines whether to throw an error if properties are missing.
22
+ * @returns {boolean} - Returns true if all required properties are present, otherwise returns false.
23
+ * @throws {Error} - Throws an error if properties are missing and `error_on_fail` is true.
24
+ */
25
+ export const require_props = ( obj={}, required_properties=[], error_on_fail=true ) => {
26
+
27
+ // Get the keys on the object
28
+ const keys = Object.keys( obj )
29
+
30
+ // Check that required props are present
31
+ const contains_all_required = required_properties.every( key => keys.includes( key ) )
32
+
33
+ // If properties are missing, throw errors or return false
34
+ if( error_on_fail && !contains_all_required ) throw new Error( `Missing required properties on object` )
35
+ if( !contains_all_required ) return false
36
+
37
+ // If all good, return true
38
+ return true
39
+
40
+ }
41
+
42
+ /**
43
+ * Validates the properties of an object against a list of allowed properties.
44
+ *
45
+ * @param {Object} obj - The object to validate.
46
+ * @param {Array} allowed_properties - The list of allowed properties.
47
+ * @param {boolean} [error_on_fail=true] - Determines whether to throw an error if unknown properties are found.
48
+ * @returns {boolean} - Returns true if all properties are allowed, false otherwise.
49
+ * @throws {Error} - Throws an error if unknown properties are found and `error_on_fail` is true.
50
+ */
51
+ export const allow_props = ( obj={}, allowed_properties=[], error_on_fail=true ) => {
52
+
53
+ // Get the keys on the object
54
+ const keys = Object.keys( obj )
55
+
56
+ // Check that required props are present
57
+ const unknownProperties = keys.filter( key => !allowed_properties.includes( key ) )
58
+
59
+ // If properties are missing, throw errors or return false
60
+ if( error_on_fail && unknownProperties.length ) throw new Error( `Unknown properties on object: ${ unknownProperties.join( ', ' ) }` )
61
+ if( unknownProperties.length ) return false
62
+
63
+ // If all good, return true
64
+ return true
65
+
66
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mentie",
3
- "version": "0.1.15",
3
+ "version": "0.1.18",
4
4
  "description": "Mentor's toolbelt",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -30,5 +30,8 @@
30
30
  "peerDependencies": {
31
31
  "promise-parallel-throttle": "^3.5.0",
32
32
  "promise-retry": "^2.0.1"
33
+ },
34
+ "dependencies": {
35
+ "safe-stable-stringify": "^2.4.3"
33
36
  }
34
37
  }