feat: Admin shipping options routes to Typescript (#891)

This commit is contained in:
Oliver Windall Juhl
2021-12-07 17:07:23 +01:00
committed by GitHub
parent 487356a96f
commit 6579c13111
13 changed files with 393 additions and 124 deletions

View File

@@ -383,4 +383,95 @@ describe("/admin/shipping-options", () => {
}
})
})
describe("GET /admin/shipping-options", () => {
beforeEach(async () => {
try {
await adminSeeder(dbConnection)
await shippingOptionSeeder(dbConnection)
} catch (err) {
console.error(err)
throw err
}
})
afterEach(async () => {
const db = useDb()
await db.teardown()
})
it("lists shipping options", async () => {
const api = useApi()
const res = await api.get(`/admin/shipping-options`, {
headers: {
Authorization: "Bearer test_token",
},
})
expect(res.status).toEqual(200)
})
it("lists admin only shipping options", async () => {
const api = useApi()
const res = await api.get(`/admin/shipping-options?admin_only=true`, {
headers: {
Authorization: "Bearer test_token",
},
})
expect(res.status).toEqual(200)
expect(res.data.shipping_options).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "test-option-req-admin-only",
admin_only: true,
}),
])
)
})
it("lists return shipping options", async () => {
const api = useApi()
const res = await api.get(`/admin/shipping-options?is_return=true`, {
headers: {
Authorization: "Bearer test_token",
},
})
expect(res.status).toEqual(200)
expect(res.data.shipping_options).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "test-option-req-return",
is_return: true,
}),
])
)
})
it("lists shipping options without return and admin options", async () => {
const api = useApi()
const res = await api.get(
`/admin/shipping-options?is_return=false&admin_only=true`,
{
headers: {
Authorization: "Bearer test_token",
},
}
)
expect(res.status).toEqual(200)
expect(res.data.shipping_options).not.toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "test-option-req-return",
is_return: true,
}),
expect.objectContaining({
id: "test-option-req-admin-only",
admin_only: true,
}),
])
)
})
})
})

View File

@@ -43,6 +43,30 @@ module.exports = async (connection, data = {}) => {
is_return: false,
})
await manager.insert(ShippingOption, {
id: "test-option-req-admin-only",
name: "With req",
profile_id: defaultProfile.id,
region_id: "region",
admin_only: true,
provider_id: "test-ful",
data: {},
price_type: "flat_rate",
amount: 2000,
is_return: false,
})
await manager.insert(ShippingOption, {
id: "test-option-req-return",
name: "With req",
profile_id: defaultProfile.id,
region_id: "region",
is_return: true,
provider_id: "test-ful",
data: {},
price_type: "flat_rate",
amount: 2000,
})
await manager.insert(ShippingOptionRequirement, {
id: "option-req",
shipping_option_id: "test-option-req",

View File

@@ -8,15 +8,15 @@
"build": "babel src -d dist --extensions \".ts,.js\""
},
"dependencies": {
"@medusajs/medusa": "1.1.57-dev-1638295280349",
"medusa-interfaces": "1.1.31-dev-1638295280349",
"@medusajs/medusa": "1.1.57-dev-1638874121913",
"medusa-interfaces": "1.1.31-dev-1638874121913",
"typeorm": "^0.2.31"
},
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"babel-preset-medusa-package": "1.1.18-dev-1638295280349",
"babel-preset-medusa-package": "1.1.18-dev-1638874121913",
"jest": "^26.6.3"
}
}

View File

@@ -1256,10 +1256,10 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
"@medusajs/medusa-cli@1.1.23-dev-1638295280349":
version "1.1.23-dev-1638295280349"
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.1.23-dev-1638295280349.tgz#65fb12a6d63a0132f93547373344f2352d184a13"
integrity sha512-EcnaL44hGs7vlC7vujPeebzx0HK3nj4ADikoAsrXeaulzGOcAaqrHSgMC8g/pz3f8vDFdimm1tqemWL+Zr1ijQ==
"@medusajs/medusa-cli@1.1.23-dev-1638874121913":
version "1.1.23-dev-1638874121913"
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.1.23-dev-1638874121913.tgz#6f12e4f54c08f4846ce3c213fb3407833b1febec"
integrity sha512-ZhO3UhIdyjKOoqjfWn09wmV7Vk2A52qOE3JwLvJkyiPVt3tO23/2H7DHF93faYtrKjBCo32xSLBuZYqsRm6p+w==
dependencies:
"@babel/polyfill" "^7.8.7"
"@babel/runtime" "^7.9.6"
@@ -1277,8 +1277,8 @@
is-valid-path "^0.1.1"
joi-objectid "^3.0.1"
meant "^1.0.1"
medusa-core-utils "1.1.30-dev-1638295280349"
medusa-telemetry "0.0.10-dev-1638295280349"
medusa-core-utils "1.1.30-dev-1638874121913"
medusa-telemetry "0.0.10-dev-1638874121913"
netrc-parser "^3.1.6"
open "^8.0.6"
ora "^5.4.1"
@@ -1292,13 +1292,13 @@
winston "^3.3.3"
yargs "^15.3.1"
"@medusajs/medusa@1.1.57-dev-1638295280349":
version "1.1.57-dev-1638295280349"
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.57-dev-1638295280349.tgz#ea276c471ca79db87ab44e761c22f6c68068e39a"
integrity sha512-xAY1NO/7i6hinYkUWXtyH7ievW6oY0WJ3ZPN6q3vQBs8wsaysmsev1CHpjq7pZZJ6JUNGL39m4wTwUnCMQ+stw==
"@medusajs/medusa@1.1.57-dev-1638874121913":
version "1.1.57-dev-1638874121913"
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.57-dev-1638874121913.tgz#c4a40d588a2567a6f80a84b8017dd64382e224bc"
integrity sha512-WSTL4U3TnB7u8YjaqaEnfjQQCmQMpZIqAwRA2+1SuaRrW3A3SYbxoRkL/3bgH13KGv/PCBAvkV1e7l9xcziAnQ==
dependencies:
"@hapi/joi" "^16.1.8"
"@medusajs/medusa-cli" "1.1.23-dev-1638295280349"
"@medusajs/medusa-cli" "1.1.23-dev-1638874121913"
"@types/lodash" "^4.14.168"
awilix "^4.2.3"
body-parser "^1.19.0"
@@ -1322,8 +1322,8 @@
joi "^17.3.0"
joi-objectid "^3.0.1"
jsonwebtoken "^8.5.1"
medusa-core-utils "1.1.30-dev-1638295280349"
medusa-test-utils "1.1.33-dev-1638295280349"
medusa-core-utils "1.1.30-dev-1638874121913"
medusa-test-utils "1.1.33-dev-1638874121913"
morgan "^1.9.1"
multer "^1.4.2"
passport "^0.4.0"
@@ -1947,10 +1947,10 @@ babel-preset-jest@^26.6.2:
babel-plugin-jest-hoist "^26.6.2"
babel-preset-current-node-syntax "^1.0.0"
babel-preset-medusa-package@1.1.18-dev-1638295280349:
version "1.1.18-dev-1638295280349"
resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.18-dev-1638295280349.tgz#fa9b9b75642d40b0235f1fbc06f8bea1a166c600"
integrity sha512-hfj+GRAzaG8GY3tBbq7y+Hpcf4CkCp3/GsdbxWjJYdWirBOLgRKxaOip8A9mEtxPk8DEFQfsgMyyJnraRpVSZw==
babel-preset-medusa-package@1.1.18-dev-1638874121913:
version "1.1.18-dev-1638874121913"
resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.18-dev-1638874121913.tgz#d50b513bbbfe691318c9b9463c7ec0c0c1ca8711"
integrity sha512-FDJyHCp+FyncJDlapHIwxHRUkM/RCxKy7+XIMmlJRGsiF6a7KGjPwQF6KUhVN3vkCl7LMBrO4qPa40uE9N5zVQ==
dependencies:
"@babel/plugin-proposal-class-properties" "^7.12.1"
"@babel/plugin-proposal-decorators" "^7.12.1"
@@ -5135,25 +5135,25 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
medusa-core-utils@1.1.30-dev-1638295280349:
version "1.1.30-dev-1638295280349"
resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.30-dev-1638295280349.tgz#bead12ee83fa00a03dd208329260b73eaea2a019"
integrity sha512-i4SXOB5VARyYgDMAydfZXK8DHrHZUjad0ABsxOD4m1XYBGMLJfcBQFfOzAiipQDuX38cVAQUoVnPbM3fm1WLKQ==
medusa-core-utils@1.1.30-dev-1638874121913:
version "1.1.30-dev-1638874121913"
resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.30-dev-1638874121913.tgz#72e5b0694fecbc83a61c58af212d993bb7b2104a"
integrity sha512-ldQ7WXJTdaGzUMVsF8LJqr5uLCJT0ZYUUTYUGazCgj30kULSUV3/VZm4+B7a5D7UoqJMexBqG+qmRDzCZ74Drg==
dependencies:
joi "^17.3.0"
joi-objectid "^3.0.1"
medusa-interfaces@1.1.31-dev-1638295280349:
version "1.1.31-dev-1638295280349"
resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.1.31-dev-1638295280349.tgz#978e0215a8b232e375a6ec512dc1e3e65a1d6de7"
integrity sha512-Qs9qYTtYfGTJfDrjRFvQiSTNsQNjpAfdMlNXxeH/HAXZxk3/bYHdf51c8FNhpoMX/zHA150B4yPDksHf0B1Eeg==
medusa-interfaces@1.1.31-dev-1638874121913:
version "1.1.31-dev-1638874121913"
resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.1.31-dev-1638874121913.tgz#0ee6c3efe637eff3364b1bd69419001a8db14422"
integrity sha512-NUzBuml4/mxSpx5BBgkQVDNqItdrYlXqqNjwhq5GjHgqkCDVrQRJA5GGcQJ/17NbRSr6KKVEJuKkWlFhOgadkQ==
dependencies:
medusa-core-utils "1.1.30-dev-1638295280349"
medusa-core-utils "1.1.30-dev-1638874121913"
medusa-telemetry@0.0.10-dev-1638295280349:
version "0.0.10-dev-1638295280349"
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.10-dev-1638295280349.tgz#00c397861ec79453733865a20ca4fc5e37b4152f"
integrity sha512-qRdXd5DcGv0eFZJ70Ns79sJL13xKOXd8trVQEkUjPAWTcaxtmb1tCw8vXQAoWXycq+9kb7KS3zcTdBnI+ML2Bw==
medusa-telemetry@0.0.10-dev-1638874121913:
version "0.0.10-dev-1638874121913"
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.10-dev-1638874121913.tgz#b8e58daa306dfeffbf28bdadca12ac852beb7912"
integrity sha512-3V/Um1B2NzmztGttGFNSFzT0ZPyGg6vsxZc1M4XTDQfB1YeioQYImQiGw62mIpnKxTyRLWpQfkaiRIK9ILNL+Q==
dependencies:
axios "^0.21.1"
axios-retry "^3.1.9"
@@ -5165,13 +5165,13 @@ medusa-telemetry@0.0.10-dev-1638295280349:
remove-trailing-slash "^0.1.1"
uuid "^8.3.2"
medusa-test-utils@1.1.33-dev-1638295280349:
version "1.1.33-dev-1638295280349"
resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.33-dev-1638295280349.tgz#61dc97815f02a3a0756ce5ac4f8cdaace7cd8a92"
integrity sha512-CqKubpbybtCt/SVjdbwM44KA2b9jFH8NMfmjTy/FJnuWqus5GWi6nBYhBMJM609uuSbGXCv8HmhI4B5fg4Cy8A==
medusa-test-utils@1.1.33-dev-1638874121913:
version "1.1.33-dev-1638874121913"
resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.33-dev-1638874121913.tgz#422aa74ceff6e09abf28c070ea941982544afbad"
integrity sha512-I7Z0GCdPQWMwygffjKw9CnGkFeudA/TCmxNTkWna+4WOlK3FFoilAi/T6Ps3q4ZDXkJ1O+vNG9yBG9zAldGPmw==
dependencies:
"@babel/plugin-transform-classes" "^7.9.5"
medusa-core-utils "1.1.30-dev-1638295280349"
medusa-core-utils "1.1.30-dev-1638874121913"
randomatic "^3.1.1"
merge-descriptors@1.0.1:

View File

@@ -43,8 +43,9 @@ describe("POST /admin/shipping-options", () => {
name: "Test option",
region_id: "testregion",
provider_id: "test_provider",
metadata: undefined,
data: { id: "test" },
profile_id: expect.stringMatching(/.*/),
profile_id: expect.any(String),
price_type: "flat_rate",
amount: 100,
requirements: [
@@ -86,7 +87,9 @@ describe("POST /admin/shipping-options", () => {
})
it("returns error", () => {
expect(subject.body.message[0].message).toEqual(`"name" is required`)
expect(subject.body.message).toEqual(
expect.stringContaining(`name must be a string`)
)
})
})
})

View File

@@ -1,11 +1,21 @@
import { MedusaError, Validator } from "medusa-core-utils"
import { defaultFields, defaultRelations } from "./"
import { Type } from "class-transformer"
import {
IsArray,
IsNumber,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { defaultFields, defaultRelations } from "."
import { validator } from "../../../../utils/validator"
/**
* @oas [post] /shipping-options
* operationId: "PostShippingOptions"
* summary: "Create Shipping Option"
* description: "Creates a Shipping Option"
* x-authenticated: true
* requestBody:
* content:
* application/json:
@@ -52,6 +62,12 @@ import { defaultFields, defaultRelations } from "./"
* is_return:
* description: Whether the Shipping Option defines a return shipment.
* type: boolean
* admin_only:
* description: If true, the option can be used for draft orders
* type: boolean
* metadata:
* description: An optional set of key-value pairs with additional information.
* type: object
* tags:
* - Shipping Option
* responses:
@@ -65,41 +81,18 @@ import { defaultFields, defaultRelations } from "./"
* $ref: "#/components/schemas/shipping_option"
*/
export default async (req, res) => {
const schema = Validator.object().keys({
name: Validator.string().required(),
region_id: Validator.string().required(),
provider_id: Validator.string().required(),
profile_id: Validator.string(),
data: Validator.object().required(),
price_type: Validator.string().required(),
amount: Validator.number().integer().optional(),
requirements: Validator.array()
.items(
Validator.object({
type: Validator.string().required(),
amount: Validator.number().integer().required(),
})
)
.optional(),
is_return: Validator.boolean().default(false),
admin_only: Validator.boolean().default(false),
})
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
const validated = await validator(AdminPostShippingOptionsReq, req.body)
const optionService = req.scope.resolve("shippingOptionService")
const shippingProfileService = req.scope.resolve("shippingProfileService")
// Add to default shipping profile
if (!value.profile_id) {
if (!validated.profile_id) {
const { id } = await shippingProfileService.retrieveDefault()
value.profile_id = id
validated.profile_id = id
}
const result = await optionService.create(value)
const result = await optionService.create(validated)
const data = await optionService.retrieve(result.id, {
select: defaultFields,
relations: defaultRelations,
@@ -107,3 +100,53 @@ export default async (req, res) => {
res.status(200).json({ shipping_option: data })
}
class OptionRequirement {
@IsString()
type: string
@IsNumber()
amount: number
}
export class AdminPostShippingOptionsReq {
@IsString()
name: string
@IsString()
region_id: string
@IsString()
provider_id: string
@IsOptional()
@IsString()
profile_id?: string
@IsObject()
data: object
@IsString()
price_type: string
@IsOptional()
@IsNumber()
amount?: number
@IsArray()
@IsOptional()
@ValidateNested({ each: true })
@Type(() => OptionRequirement)
requirements?: OptionRequirement[]
@IsOptional()
@Type(() => Boolean)
admin_only?: boolean = false
@IsOptional()
@Type(() => Boolean)
is_return?: boolean = false
@IsObject()
@IsOptional()
metadata?: object
}

View File

@@ -3,6 +3,7 @@
* operationId: "DeleteShippingOptionsOption"
* summary: "Delete a Shipping Option"
* description: "Deletes a Shipping Option."
* x-authenticated: true
* parameters:
* - (path) id=* {string} The id of the Shipping Option.
* tags:

View File

@@ -3,6 +3,7 @@
* operationId: "GetShippingOptionsOption"
* summary: "Retrieve a Shipping Option"
* description: "Retrieves a Shipping Option."
* x-authenticated: true
* parameters:
* - (path) id=* {string} The id of the Shipping Option.
* tags:

View File

@@ -1,4 +1,6 @@
import { Router } from "express"
import { ShippingOption } from "../../../.."
import { DeleteResponse } from "../../../../types/common"
import middlewares from "../../../middlewares"
const route = Router()
@@ -43,3 +45,19 @@ export const defaultFields = [
]
export const defaultRelations = ["region", "profile", "requirements"]
export type AdminShippingOptionsListRes = {
shipping_options: ShippingOption[]
}
export type AdminShippingOptionsRes = {
shipping_option: ShippingOption
}
export type AdminShippingOptionsDeleteRes = DeleteResponse
export * from "./create-shipping-option"
export * from "./delete-shipping-option"
export * from "./get-shipping-option"
export * from "./list-shipping-options"
export * from "./update-shipping-option"

View File

@@ -1,33 +0,0 @@
import _ from "lodash"
import { defaultFields, defaultRelations } from "./"
/**
* @oas [get] /shipping-options
* operationId: "GetShippingOptions"
* summary: "List Shipping Options"
* description: "Retrieves a list of Shipping Options."
* tags:
* - Shipping Option
* responses:
* 200:
* description: OK
* content:
* application/json:
* schema:
* properties:
* shipping_options:
* type: array
* items:
* $ref: "#/components/schemas/shipping_option"
*/
export default async (req, res) => {
const query = _.pick(req.query, ["region_id", "is_return", "admin_only"])
const optionService = req.scope.resolve("shippingOptionService")
const data = await optionService.list(query, {
select: defaultFields,
relations: defaultRelations,
})
res.status(200).json({ shipping_options: data })
}

View File

@@ -0,0 +1,75 @@
import { Transform } from "class-transformer"
import { IsBoolean, IsOptional, IsString } from "class-validator"
import { defaultFields, defaultRelations } from "."
import { validator } from "../../../../utils/validator"
import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
/**
* @oas [get] /shipping-options
* operationId: "GetShippingOptions"
* summary: "List Shipping Options"
* description: "Retrieves a list of Shipping Options."
* x-authenticated: true
* parameters:
* - in: path
* name: region_id
* schema:
* type: string
* required: false
* description: Region to fetch options from
* - in: path
* name: is_return
* schema:
* type: boolean
* required: false
* description: Flag for fetching return options
* - in: path
* name: admin_only
* schema:
* type: boolean
* required: false
* description: Flag for fetching admin specific options
* tags:
* - Shipping Option
* responses:
* 200:
* description: OK
* content:
* application/json:
* schema:
* properties:
* shipping_options:
* type: array
* items:
* $ref: "#/components/schemas/shipping_option"
*/
export default async (req, res) => {
const validatedParams = await validator(
AdminGetShippingOptionsParams,
req.query
)
const optionService = req.scope.resolve("shippingOptionService")
const data = await optionService.list(validatedParams, {
select: defaultFields,
relations: defaultRelations,
})
res.status(200).json({ shipping_options: data })
}
export class AdminGetShippingOptionsParams {
@IsOptional()
@IsString()
region_id?: string
@IsOptional()
@IsBoolean()
@Transform(({ value }) => optionalBooleanMapper.get(value))
is_return?: string
@IsOptional()
@IsBoolean()
@Transform(({ value }) => optionalBooleanMapper.get(value))
admin_only?: string
}

View File

@@ -1,11 +1,22 @@
import { MedusaError, Validator } from "medusa-core-utils"
import { defaultFields, defaultRelations } from "./"
import { Type } from "class-transformer"
import {
IsArray,
IsBoolean,
IsNumber,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { defaultFields, defaultRelations } from "."
import { validator } from "../../../../utils/validator"
/**
* @oas [post] /shipping-options/{id}
* operationId: "PostShippingOptionsOption"
* summary: "Update Shipping Option"
* description: "Updates a Shipping Option"
* x-authenticated: true
* parameters:
* - (path) id=* {string} The id of the Shipping Option.
* requestBody:
@@ -19,6 +30,12 @@ import { defaultFields, defaultRelations } from "./"
* amount:
* description: "The amount to charge for the Shipping Option."
* type: integer
* admin_only:
* description: "If true, the option can be used for draft orders"
* type: boolean
* metadata:
* description: "An optional set of key-value pairs with additional information."
* type: object
* requirements:
* description: "The requirements that must be satisfied for the Shipping Option to be available."
* type: array
@@ -47,30 +64,12 @@ import { defaultFields, defaultRelations } from "./"
*/
export default async (req, res) => {
const { option_id } = req.params
const schema = Validator.object().keys({
name: Validator.string().optional(),
amount: Validator.number().integer().optional(),
requirements: Validator.array()
.items(
Validator.object({
id: Validator.string().optional(),
type: Validator.string().required(),
amount: Validator.number().integer().required(),
})
)
.optional(),
admin_only: Validator.boolean().optional(),
metadata: Validator.object().optional(),
})
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
const validated = await validator(AdminPostShippingOptionsOptionReq, req.body)
const optionService = req.scope.resolve("shippingOptionService")
await optionService.update(option_id, value)
await optionService.update(option_id, validated)
const data = await optionService.retrieve(option_id, {
select: defaultFields,
@@ -79,3 +78,36 @@ export default async (req, res) => {
res.status(200).json({ shipping_option: data })
}
class OptionRequirement {
@IsString()
@IsOptional()
id: string
@IsString()
type: string
@IsNumber()
amount: number
}
export class AdminPostShippingOptionsOptionReq {
@IsString()
@IsOptional()
name: string
@IsNumber()
@IsOptional()
amount?: number
@IsArray()
@ValidateNested({ each: true })
@Type(() => OptionRequirement)
requirements: OptionRequirement[]
@IsBoolean()
@IsOptional()
admin_only?: boolean
@IsObject()
@IsOptional()
metadata?: object
}

View File

@@ -0,0 +1,14 @@
// Util function defining the transformation of booleans when part of req.query
// e.g. /admin/shipping-options?is_return=false -> false
//
// We've previously been using @Type(() => Boolean), but this will always return true for strings.
// See https://github.com/typestack/class-transformer/issues/676
// and https://github.com/typestack/class-transformer/issues/306
//
// The solution here is stolen from: https://github.com/typestack/class-transformer/issues/676#issuecomment-822699830
export const optionalBooleanMapper = new Map([
["undefined", undefined],
["null", null],
["true", true],
["false", false],
])