From 996205bc9ab508380cb639c6ac3b5108c1399478 Mon Sep 17 00:00:00 2001 From: Giacomo117 Date: Fri, 7 Nov 2025 19:51:22 +0000 Subject: [PATCH 1/3] fix: Add objectParser action for ParseServerOptions in Definitions.js --- resources/buildConfigDefinitions.js | 2 ++ src/Options/Definitions.js | 1 + 2 files changed, 3 insertions(+) diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js index 5b9084f863..da9db8d480 100644 --- a/resources/buildConfigDefinitions.js +++ b/resources/buildConfigDefinitions.js @@ -153,6 +153,8 @@ function mapperFor(elt, t) { return wrap(t.identifier('objectParser')); } else if (t.isBooleanTypeAnnotation(elt)) { return wrap(t.identifier('booleanParser')); + } else if (t.isObjectTypeAnnotation(elt)) { + return wrap(t.identifier('objectParser')); } else if (t.isGenericTypeAnnotation(elt)) { const type = elt.typeAnnotation.id.name; if (type == 'Adapter') { diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index d5674eaf29..61f7391ecd 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -111,6 +111,7 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_AUTH_PROVIDERS', help: 'Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication', + action: parsers.objectParser, }, cacheAdapter: { env: 'PARSE_SERVER_CACHE_ADAPTER', From 69875a25699315fc05bb5d4aff918e87a18eba47 Mon Sep 17 00:00:00 2001 From: Giacomo117 Date: Wed, 12 Nov 2025 13:32:47 +0000 Subject: [PATCH 2/3] test: Add unit tests for mapperFor function in buildConfigDefinitions --- spec/buildConfigDefinitions.spec.js | 187 ++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 spec/buildConfigDefinitions.spec.js diff --git a/spec/buildConfigDefinitions.spec.js b/spec/buildConfigDefinitions.spec.js new file mode 100644 index 0000000000..6165c7136f --- /dev/null +++ b/spec/buildConfigDefinitions.spec.js @@ -0,0 +1,187 @@ +const t = require('@babel/types'); + +describe('buildConfigDefinitions', () => { + describe('mapperFor', () => { + // Recreate the mapperFor function for testing + function mapperFor(elt, t) { + const p = t.identifier('parsers'); + const wrap = identifier => t.memberExpression(p, identifier); + + if (t.isNumberTypeAnnotation(elt)) { + return t.callExpression(wrap(t.identifier('numberParser')), [t.stringLiteral(elt.name)]); + } else if (t.isArrayTypeAnnotation(elt)) { + return wrap(t.identifier('arrayParser')); + } else if (t.isAnyTypeAnnotation(elt)) { + return wrap(t.identifier('objectParser')); + } else if (t.isBooleanTypeAnnotation(elt)) { + return wrap(t.identifier('booleanParser')); + } else if (t.isObjectTypeAnnotation(elt)) { + return wrap(t.identifier('objectParser')); + } else if (t.isGenericTypeAnnotation(elt)) { + const type = elt.typeAnnotation.id.name; + if (type == 'Adapter') { + return wrap(t.identifier('moduleOrObjectParser')); + } + if (type == 'NumberOrBoolean') { + return wrap(t.identifier('numberOrBooleanParser')); + } + if (type == 'NumberOrString') { + return t.callExpression(wrap(t.identifier('numberOrStringParser')), [ + t.stringLiteral(elt.name), + ]); + } + if (type === 'StringOrStringArray') { + return wrap(t.identifier('arrayParser')); + } + return wrap(t.identifier('objectParser')); + } + } + + it('should return objectParser for ObjectTypeAnnotation', () => { + const mockElement = { + type: 'ObjectTypeAnnotation', + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('objectParser'); + }); + + it('should return objectParser for AnyTypeAnnotation', () => { + const mockElement = { + type: 'AnyTypeAnnotation', + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('objectParser'); + }); + + it('should return arrayParser for ArrayTypeAnnotation', () => { + const mockElement = { + type: 'ArrayTypeAnnotation', + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('arrayParser'); + }); + + it('should return booleanParser for BooleanTypeAnnotation', () => { + const mockElement = { + type: 'BooleanTypeAnnotation', + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('booleanParser'); + }); + + it('should return numberParser call expression for NumberTypeAnnotation', () => { + const mockElement = { + type: 'NumberTypeAnnotation', + name: 'testNumber', + }; + + const result = mapperFor(mockElement, t); + + expect(t.isCallExpression(result)).toBe(true); + expect(result.callee.property.name).toBe('numberParser'); + expect(result.arguments[0].value).toBe('testNumber'); + }); + + it('should return moduleOrObjectParser for Adapter GenericTypeAnnotation', () => { + const mockElement = { + type: 'GenericTypeAnnotation', + typeAnnotation: { + id: { + name: 'Adapter', + }, + }, + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('moduleOrObjectParser'); + }); + + it('should return numberOrBooleanParser for NumberOrBoolean GenericTypeAnnotation', () => { + const mockElement = { + type: 'GenericTypeAnnotation', + typeAnnotation: { + id: { + name: 'NumberOrBoolean', + }, + }, + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('numberOrBooleanParser'); + }); + + it('should return numberOrStringParser call expression for NumberOrString GenericTypeAnnotation', () => { + const mockElement = { + type: 'GenericTypeAnnotation', + name: 'testString', + typeAnnotation: { + id: { + name: 'NumberOrString', + }, + }, + }; + + const result = mapperFor(mockElement, t); + + expect(t.isCallExpression(result)).toBe(true); + expect(result.callee.property.name).toBe('numberOrStringParser'); + expect(result.arguments[0].value).toBe('testString'); + }); + + it('should return arrayParser for StringOrStringArray GenericTypeAnnotation', () => { + const mockElement = { + type: 'GenericTypeAnnotation', + typeAnnotation: { + id: { + name: 'StringOrStringArray', + }, + }, + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('arrayParser'); + }); + + it('should return objectParser for unknown GenericTypeAnnotation', () => { + const mockElement = { + type: 'GenericTypeAnnotation', + typeAnnotation: { + id: { + name: 'UnknownType', + }, + }, + }; + + const result = mapperFor(mockElement, t); + + expect(t.isMemberExpression(result)).toBe(true); + expect(result.object.name).toBe('parsers'); + expect(result.property.name).toBe('objectParser'); + }); + }); +}); From 8224a93f96dc963d0df5c7c6cf3bcf2c8a107de3 Mon Sep 17 00:00:00 2001 From: Giacomo117 Date: Wed, 12 Nov 2025 13:45:13 +0000 Subject: [PATCH 3/3] feat: Export mapperFor function for testing purposes --- resources/buildConfigDefinitions.js | 3 +++ spec/buildConfigDefinitions.spec.js | 36 +---------------------------- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js index 1f11b1639c..a10b0b8696 100644 --- a/resources/buildConfigDefinitions.js +++ b/resources/buildConfigDefinitions.js @@ -383,3 +383,6 @@ const res = babel.transformFileSync('./src/Options/index.js', { }); require('fs').writeFileSync('./src/Options/Definitions.js', res.code + '\n'); require('fs').writeFileSync('./src/Options/docs.js', docs); + +// Export mapperFor for testing +module.exports = { mapperFor }; diff --git a/spec/buildConfigDefinitions.spec.js b/spec/buildConfigDefinitions.spec.js index 6165c7136f..f0a8055860 100644 --- a/spec/buildConfigDefinitions.spec.js +++ b/spec/buildConfigDefinitions.spec.js @@ -1,42 +1,8 @@ const t = require('@babel/types'); +const { mapperFor } = require('../resources/buildConfigDefinitions'); describe('buildConfigDefinitions', () => { describe('mapperFor', () => { - // Recreate the mapperFor function for testing - function mapperFor(elt, t) { - const p = t.identifier('parsers'); - const wrap = identifier => t.memberExpression(p, identifier); - - if (t.isNumberTypeAnnotation(elt)) { - return t.callExpression(wrap(t.identifier('numberParser')), [t.stringLiteral(elt.name)]); - } else if (t.isArrayTypeAnnotation(elt)) { - return wrap(t.identifier('arrayParser')); - } else if (t.isAnyTypeAnnotation(elt)) { - return wrap(t.identifier('objectParser')); - } else if (t.isBooleanTypeAnnotation(elt)) { - return wrap(t.identifier('booleanParser')); - } else if (t.isObjectTypeAnnotation(elt)) { - return wrap(t.identifier('objectParser')); - } else if (t.isGenericTypeAnnotation(elt)) { - const type = elt.typeAnnotation.id.name; - if (type == 'Adapter') { - return wrap(t.identifier('moduleOrObjectParser')); - } - if (type == 'NumberOrBoolean') { - return wrap(t.identifier('numberOrBooleanParser')); - } - if (type == 'NumberOrString') { - return t.callExpression(wrap(t.identifier('numberOrStringParser')), [ - t.stringLiteral(elt.name), - ]); - } - if (type === 'StringOrStringArray') { - return wrap(t.identifier('arrayParser')); - } - return wrap(t.identifier('objectParser')); - } - } - it('should return objectParser for ObjectTypeAnnotation', () => { const mockElement = { type: 'ObjectTypeAnnotation',