UNPKG

morphir-elm

Version:
273 lines (269 loc) 10.5 kB
"use strict"; /* Copyright 2021 Morgan Stanley Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.raiseDecodeErrorFromCustomType = exports.parseKindFromCustomTypeInput = exports.preprocessCustomTypeVariant = exports.encodeTuple = exports.encodeRecord = exports.encodeList = exports.encodeDict = exports.encodeMaybe = exports.encodeFloat = exports.encodeInt = exports.encodeString = exports.encodeDecimal = exports.encodeChar = exports.encodeBoolean = exports.encodeUnit = exports.decodeTuple = exports.decodeRecord = exports.decodeList = exports.decodeDict = exports.decodeMaybe = exports.decodeFloat = exports.decodeInt = exports.decodeString = exports.decodeDecimal = exports.decodeChar = exports.decodeBoolean = exports.decodeUnit = exports.buildCodecMap = void 0; class DecodeError extends Error { } Object.defineProperty(DecodeError.prototype, "name", { value: "DecodeError", }); // Construct a codec map, avoiding spurious type errors. // // Calling `new Map([["field", codec]])` is problematic as the Map constructor // expects an array of tuples, but the TypeScript compiler cannot differentiate // between array and tuple literals and will default to array. // // For more info, see: // * https://github.com/Microsoft/TypeScript/issues/3369 // * https://stackoverflow.com/a/53136686 // function buildCodecMap(entries) { return new Map(entries); } exports.buildCodecMap = buildCodecMap; function decodeUnit(input) { return []; } exports.decodeUnit = decodeUnit; function decodeBoolean(input) { if (typeof input != "boolean") { throw new DecodeError(`Expected bool, got ${typeof input}`); } return input; } exports.decodeBoolean = decodeBoolean; function decodeChar(input) { if (typeof input != "string") { throw new DecodeError(`Expected char, got ${typeof input}`); } if (input.length != 1) { throw new DecodeError(`Expected char, got string`); } return input; } exports.decodeChar = decodeChar; function decodeDecimal(input) { if (typeof input != "number") { throw new DecodeError(`Expected Decimal, got ${typeof input}`); } return input; } exports.decodeDecimal = decodeDecimal; function decodeString(input) { if (typeof input != "string") { throw new DecodeError(`Expected string, got ${typeof input}`); } return input; } exports.decodeString = decodeString; function decodeInt(input) { if (typeof input != "number") { throw new DecodeError(`Expected int, got ${typeof input}`); } return input; } exports.decodeInt = decodeInt; function decodeFloat(input) { if (typeof input != "number") { throw new DecodeError(`Expected float, got ${typeof input}`); } return input; } exports.decodeFloat = decodeFloat; function decodeMaybe(decodeElement, input) { if (input == null) { return null; } else { return decodeElement(input); } } exports.decodeMaybe = decodeMaybe; function decodeDict(decodeKey, decodeValue, input) { if (!(input instanceof Array)) { throw new DecodeError(`Expected array, got ${typeof input}`); } const inputArray = input; return new Map(inputArray.map((item) => { if (!(item instanceof Array)) { throw new DecodeError(`Expected array, got ${typeof item}`); } const itemArray = item; return [decodeKey(itemArray[0]), decodeValue(itemArray[1])]; })); } exports.decodeDict = decodeDict; function decodeList(decodeElement, input) { if (!(input instanceof Array)) { throw new DecodeError(`Expected Array, got ${typeof input}`); } const inputArray = input; return inputArray.map(decodeElement); } exports.decodeList = decodeList; function decodeRecord(fieldDecoders, input) { if (!(input instanceof Object)) { throw new DecodeError(`Expected Object, got ${typeof input}`); } const inputObject = input; const fieldNames = Array.from(fieldDecoders.keys()); for (var field of fieldNames) { if (!Object.keys(input).includes(field)) { throw new DecodeError(`Expected field ${field} was not found`); } } if (Object.keys(inputObject).length > fieldNames.length) { throw new DecodeError(`Input object has extra fields, expected ${fieldNames.length}, got ${input.keys().length}`); } var result = new Object(); fieldDecoders.forEach((decoder, name) => { if (!(name in inputObject)) { throw new DecodeError(`Input record object missing field: ${name}`); } result[name] = decoder(inputObject[name]); }); // @ts-ignore return result; // This function should only be called by the morphir-generated 'decoder' functions. // When called by one of those functions, those functions are responsible for // constructing the `fieldDecoders` Map correctly. If the `fieldDecoders` map is // constructed properly, then the function output will be of the correct type, and // results should be type-safe. // However, if this function were called with the wrong inputs, then it may not return // the expected type. For this reason, the compiler rightly raises an error here. // Hopefully in future this approach to decoders can be changed to remove the error. // For now, it is necesary to override the error with @ts-ignore, and trust that the // function will only be called as intended. } exports.decodeRecord = decodeRecord; function decodeTuple(elementDecoders, input) { if (!(input instanceof Array)) { throw new DecodeError(`Expected Array, got ${typeof input}`); } const inputArray = input; let result = []; for (var i = 0; i < inputArray.length; i++) { result.push(elementDecoders[i](inputArray[i])); } // @ts-ignore return result; // This function should only be called by the morphir-generated 'decoder' functions. // When called by one of those functions, those functions are responsible for // constructing the `elementDecoders` list correctly. If the `elementDecoders` list is // constructed properly, then the function output will be of the correct type, and // results should be type-safe. // However, if this function were called with the wrong inputs, then it may not return // the expected type. For this reason, the compiler rightly raises an error here. // Hopefully in future this approach to decoders can be changed to remove the error. // For now, it is necesary to override the error with @ts-ignore, and trust that the // function will only be called as intended. } exports.decodeTuple = decodeTuple; function encodeUnit(value) { return {}; } exports.encodeUnit = encodeUnit; function encodeBoolean(value) { return value; } exports.encodeBoolean = encodeBoolean; function encodeChar(value) { return value; } exports.encodeChar = encodeChar; function encodeDecimal(value) { return value; } exports.encodeDecimal = encodeDecimal; function encodeString(value) { return value; } exports.encodeString = encodeString; function encodeInt(value) { return value; } exports.encodeInt = encodeInt; function encodeFloat(value) { return value; } exports.encodeFloat = encodeFloat; function encodeMaybe(encodeElement, value) { if (value == null) { return null; } else { return encodeElement(value); } } exports.encodeMaybe = encodeMaybe; function encodeDict(encodeKey, encodeValue, value) { return Array.from(value.entries()).map((pair) => { return [encodeKey(pair[0]), encodeValue(pair[1])]; }); } exports.encodeDict = encodeDict; function encodeList(encodeElement, value) { return value.map(encodeElement); } exports.encodeList = encodeList; function encodeRecord(fieldEncoders, value) { let result = new Object(); fieldEncoders.forEach((encoder, name) => { result[name] = encoder(value[name]); }); return result; } exports.encodeRecord = encodeRecord; function encodeTuple(elementEncoders, value) { let result = new Array(); for (var i = 0; i < value.length; i++) { result.push(elementEncoders[i](value[i])); } return result; } exports.encodeTuple = encodeTuple; function preprocessCustomTypeVariant(kindString, numArgs, input) { if (typeof input == "string") input = [input]; if (!(input instanceof Array)) { throw new DecodeError(`Expected Array, got ${typeof input}`); } if (!(input.length == numArgs + 1)) { throw new DecodeError(`Expected Array of length ${numArgs + 1}, got ${input.length}`); } if (typeof input[0] != "string") { throw new DecodeError(`Expected first argument to be ${kindString}, got ${input[0]}`); } if (input[0] != kindString) { throw new DecodeError(`Expected kind ${kindString}, got ${input[0]}`); } } exports.preprocessCustomTypeVariant = preprocessCustomTypeVariant; function parseKindFromCustomTypeInput(input) { if (typeof input == "string") input = [input]; if (!(input instanceof Array)) { throw new DecodeError(`Expected Array, got ${typeof input}`); } if (!(typeof input[0] == "string")) { throw new DecodeError(`Expected String, got ${typeof input}`); } return input[0]; } exports.parseKindFromCustomTypeInput = parseKindFromCustomTypeInput; function raiseDecodeErrorFromCustomType(customTypeName, kind) { throw new DecodeError(`Error while attempting to decode an instance of ${customTypeName}.` + ` "${kind}" is not a valid 'kind' field for ${customTypeName}.`); } exports.raiseDecodeErrorFromCustomType = raiseDecodeErrorFromCustomType;