backend-manager 3.2.85 → 3.2.86

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "3.2.85",
3
+ "version": "3.2.86",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -71,4 +71,4 @@
71
71
  "wonderful-log": "^1.0.5",
72
72
  "yargs": "^17.7.2"
73
73
  }
74
- }
74
+ }
@@ -349,7 +349,7 @@ BackendAssistant.prototype.errorify = function (e, options) {
349
349
  // Construct error
350
350
  const newError = e instanceof Error
351
351
  ? e
352
- : new Error(stringify(e));
352
+ : new Error(stringifyNonStrings(e));
353
353
 
354
354
  // Fix code
355
355
  // options.code = newError.code || options.code;
@@ -474,7 +474,7 @@ function isBetween(value, min, max) {
474
474
  return value >= min && value <= max;
475
475
  }
476
476
 
477
- function stringify(e) {
477
+ function stringifyNonStrings(e) {
478
478
  if (typeof e === 'string') {
479
479
  return e;
480
480
  } else {
@@ -942,30 +942,33 @@ BackendAssistant.prototype.parseMultipartFormData = function (options) {
942
942
  });
943
943
  }
944
944
 
945
- function stringify(obj, replacer, spaces, cycleReplacer) {
946
- return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
947
- }
948
-
949
- // https://github.com/moll/json-stringify-safe/blob/master/stringify.js
950
- function serializer(replacer, cycleReplacer) {
951
- var stack = [], keys = []
952
-
953
- if (cycleReplacer == null) cycleReplacer = function(key, value) {
954
- if (stack[0] === value) return '[Circular ~]'
955
- return `[Circular ~.${keys.slice(0, stack.indexOf(value)).join('.')}]`;
956
- }
957
-
958
- return function(key, value) {
959
- if (stack.length > 0) {
960
- var thisPos = stack.indexOf(this)
961
- ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
962
- ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
963
- if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
964
- }
965
- else stack.push(value)
966
-
967
- return replacer == null ? value : replacer.call(this, key, value)
968
- }
969
- }
945
+ // Not sure what this is for? But it has a good serializer code
946
+ // Disabled 2024-03-21 because there was another stringify() function that i was intending to use but it was actually using this
947
+ // It was adding escaped quotes to strings
948
+ // function stringify(obj, replacer, spaces, cycleReplacer) {
949
+ // return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
950
+ // }
951
+
952
+ // // https://github.com/moll/json-stringify-safe/blob/master/stringify.js
953
+ // function serializer(replacer, cycleReplacer) {
954
+ // var stack = [], keys = []
955
+
956
+ // if (cycleReplacer == null) cycleReplacer = function(key, value) {
957
+ // if (stack[0] === value) return '[Circular ~]'
958
+ // return `[Circular ~.${keys.slice(0, stack.indexOf(value)).join('.')}]`;
959
+ // }
960
+
961
+ // return function(key, value) {
962
+ // if (stack.length > 0) {
963
+ // var thisPos = stack.indexOf(this)
964
+ // ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
965
+ // ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
966
+ // if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
967
+ // }
968
+ // else stack.push(value)
969
+
970
+ // return replacer == null ? value : replacer.call(this, key, value)
971
+ // }
972
+ // }
970
973
 
971
974
  module.exports = BackendAssistant;
@@ -34,6 +34,7 @@ Middleware.prototype.run = function (libPath, options) {
34
34
  options.setupAnalytics = typeof options.setupAnalytics === 'boolean' ? options.setupAnalytics : true;
35
35
  options.setupUsage = typeof options.setupUsage === 'boolean' ? options.setupUsage : true;
36
36
  options.setupSettings = typeof options.setupSettings === 'undefined' ? true : options.setupSettings;
37
+ options.cleanSettings = typeof options.cleanSettings === 'undefined' ? true : options.cleanSettings;
37
38
  options.schema = typeof options.schema === 'undefined' ? undefined : options.schema;
38
39
 
39
40
  // Log
@@ -80,12 +81,19 @@ Middleware.prototype.run = function (libPath, options) {
80
81
  if (options.setupSettings) {
81
82
  // assistant.log(`Middleware.process(): Resolving settings with schema ${options.schema}...`);
82
83
 
84
+ // Resolve settings
83
85
  try {
84
86
  assistant.settings = Manager.Settings().resolve(assistant, options.schema, data);
85
87
  } catch (e) {
86
88
  return assistant.respond(new Error(`Unable to resolve schema ${options.schema}: ${e.message}`), {code: 500, sentry: true});
87
89
  }
88
90
 
91
+ // Clean settings by looping through and trimming all strings
92
+ if (options.cleanSettings) {
93
+ clean(assistant.settings);
94
+ }
95
+
96
+ // Log
89
97
  assistant.log(`Middleware.process(): Resolved settings with schema ${options.schema}`, JSON.stringify(assistant.settings));
90
98
  }
91
99
 
@@ -106,4 +114,15 @@ Middleware.prototype.run = function (libPath, options) {
106
114
  });
107
115
  };
108
116
 
117
+ function clean(obj) {
118
+ for (let key in obj) {
119
+ if (typeof obj[key] === 'object') {
120
+ clean(obj[key]);
121
+ } else if (typeof obj[key] === 'string') {
122
+ obj[key] = obj[key]
123
+ .trim();
124
+ }
125
+ }
126
+ }
127
+
109
128
  module.exports = Middleware;
@@ -42,22 +42,36 @@ Settings.prototype.resolve = function (assistant, schema, settings) {
42
42
  // Resolve settings
43
43
  self.settings = powertools.defaults(settings, schema);
44
44
 
45
- // Check for missing required keys
46
- powertools.getKeys(schema).forEach((key) => {
47
- const isRequired = key.endsWith('.required') ? _.get(schema, key, false) : false;
45
+ // Iterate each key and check for some things
46
+ processSchema(schema, (path, schemaNode) => {
47
+ const originalValue = _.get(settings, path);
48
+ const resolvedValue = _.get(self.settings, path);
49
+ let replaceValue = undefined;
50
+
51
+ // assistant.log('Found:', path, schemaNode);
52
+ // assistant.log('originalValue:', originalValue);
53
+ // assistant.log('resolvedValue:', resolvedValue);
54
+
55
+ // Check if this node is marked as required
56
+ if (schemaNode.required && typeof originalValue === 'undefined') {
57
+ throw assistant.errorify(`Required key {${path}} is missing in settings`, {code: 400});
58
+ }
48
59
 
49
- // Skip if not required
50
- if (!isRequired) {
51
- return;
60
+ // Clean
61
+ if (schemaNode.clean) {
62
+ if (schemaNode.clean instanceof RegExp) {
63
+ replaceValue = resolvedValue.replace(schemaNode.clean, '');
64
+ } else if (typeof schemaNode.clean === 'function') {
65
+ replaceValue = schemaNode.clean(resolvedValue);
66
+ }
52
67
  }
53
68
 
54
- // Use regex to replace '.required' only if it's at the end of the string
55
- const settingsKey = key.replace(/\.required$/, '');
69
+ // assistant.log('replaceValue:', replaceValue);
56
70
 
57
- // Check if the required key is missing
58
- if (typeof _.get(settings, settingsKey, undefined) === 'undefined') {
59
- // Handle the missing required key as needed
60
- throw assistant.errorify(`Required key '${settingsKey}' is missing in settings`, {code: 400});
71
+ // Replace
72
+ if (typeof replaceValue !== 'undefined' && replaceValue !== resolvedValue) {
73
+ assistant.warn(`Replacing ${path}: originalValue=${originalValue}, resolvedValue=${resolvedValue}, replaceValue=${replaceValue}`);
74
+ _.set(self.settings, path, replaceValue);
61
75
  }
62
76
  });
63
77
 
@@ -92,6 +106,23 @@ Settings.prototype.constant = function (name, options) {
92
106
  }
93
107
  };
94
108
 
109
+ function processSchema(schema, fn, path) {
110
+ path = path || '';
111
+
112
+ // Base case: Check if the current level has 'types' and 'default', indicating metadata
113
+ if (schema.hasOwnProperty('types') && schema.hasOwnProperty('default')) {
114
+ // Call the processing function with the current path and schema as arguments
115
+ fn(path, schema);
116
+ return;
117
+ }
118
+
119
+ // Recursive case: Iterate through nested keys if we're not at a metadata node
120
+ Object.keys(schema).forEach(key => {
121
+ const nextPath = path ? `${path}.${key}` : key;
122
+ processSchema(schema[key], fn, nextPath);
123
+ });
124
+ }
125
+
95
126
  function loadSchema(assistant, schema, settings) {
96
127
  const planId = assistant.request.user.plan.id;
97
128