@creamapi/cream
Version:
Concise REST API Maker - An extension library for express to create REST APIs faster
251 lines (250 loc) • 10.6 kB
JavaScript
;
/*
* Copyright 2024 Raul Radu
*
* 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.CreamSerializers = void 0;
const Serializer_1 = require("./Serializer");
/**
* In this namespace you can find common serializers defined by
* Cream
*/
var CreamSerializers;
(function (CreamSerializers) {
/**
* This serializer serialize objects to JSON notation
* It does not serialize methods, only attributes
* @remarks circular dependencies are not checked yet and this can
* cause a serious issue with your code.
*/
class JSON extends Serializer_1.Serializer {
/**
* This method takes a number as input and returns a string corresponding to that number
* it just uses {@link Number.toString} under the hood
* @param _dataLabel **ignored**
* @param num The number to be serialized
* @returns a string representing the number num in json format
*/
async serializeNumber(_dataLabel, num) {
return Number(num).toString();
}
/**
* This method just adds one quota at the beginning and one at the end of the string
* @param _dataLabel **ignored**
* @param data The string to be serialized
* @returns a string representing the string data in json format
*/
async serializeString(_dataLabel, data) {
return '"' + data + '"';
}
/**
* This method returns the string equivalent of the boolean values true/false in the JSON format
* @param _dataLabel **ignored**
* @param data the boolean data to be serialized
* @returns the string equivalent in JSON format of data
*/
async serializeBoolean(_dataLabel, data) {
return data ? 'true' : 'false';
}
/**
* This method is called when a null valued attribute is found.
* @remarks Beware that this doesn't mean that the value was undefined, but rather that
* the attribute exists but it is null, with not a value.\
* For further information about the difference between undefined and null
* you should look in the JavaScript documentation.
* @param _dataLabel **ignored**
* @returns 'null'
*/
async serializeNull(_dataLabel) {
return 'null';
}
/**
* This method is used to serialize a Date into a string
* it works like Date.toJSON except it is calling directly
* Date.toISOString
* @param dataLabel unused. The label of the field containing the date
* @param data the actual date to be serialized
* @returns the serialized date as string, encapsulated by colons ("\<date\>").
*/
async serializeDate(dataLabel, data) {
return '"' + (await super.serializeDate(dataLabel, data)) + '"';
}
/**
* This method will do the job of serializing the input
* object that is automatically converted to a stream.\
* @remarks The stream order is top-down from class notation,
* so the first attribute found in the class will be the first
* to be inserted in the serialStream
* @param _serializedObjectName - **ignored**
* @param serialStream - the input stream the object to be serialized was sliced to by the {@link Serializer.serialize} method
* @param metaInfo - additional meta information about how to handle the object. These attributes were defined
* by {@link Meta} or by the {@link Serializer.serialize} method
* @returns a string representing the serialized version of the stream in JSON format
*/
async handleSerializationStream(_serializedObjectName, serialStream, metaInfo) {
if (metaInfo.hasAttribute(Serializer_1.SerializerCommon.Attributes.Array)) {
return this.serializeArray(serialStream);
}
return this.serializeObject(serialStream);
}
/**
* This method serializes array-like objects previously identified by
* the {@link Serializer.serialize} method.
* @param serialStream - the serial stream of the array. each object is one object of the array
* SerialBite.dataLabel will be the index of the object
* @returns the string corresponding to the array. If the array is empty it will return a '[]'
* representing the empty array in JSON
*/
async serializeArray(serialStream) {
if (serialStream.length == 0)
return '[]';
let outStream = '[';
for (let elem of serialStream) {
outStream +=
(await this.serialize(elem.dataLabel, elem.data)) + ',';
}
return outStream.slice(0, outStream.length - 1) + ']';
}
/**
* This method is used to serialize a stream that contains object-like data
* {@link SerialBite.dataLabel} will contain either the attribute name or the alternative
* given by the {@link MapTo} decorator. This is not an issue because a reference to
* the actual field is held in {@link SerialBite.data}
* @param serialStream - the array of SerialBites representing the object
* @returns the string representing the serialStream in JSON format
*/
async serializeObject(serialStream) {
if (serialStream.length == 0)
return '{}';
let outStream = '{';
for (let elem of serialStream) {
if (elem.data !== undefined) {
outStream +=
'"' +
elem.dataLabel +
'":' +
(await this.serialize(elem.dataLabel, elem.data)) +
',';
}
}
return outStream.slice(0, outStream.length - 1) + '}';
}
}
CreamSerializers.JSON = JSON;
/**
* @experimental
* This class will act as a serializer to XML format.
* This is still experimental and it is not yet suggested for
* extensive use. Any help on its enhancement is welcome!
*/
class XML extends Serializer_1.Serializer {
static Attribute = 'xml:attribute';
static Text = 'xml:text';
static AddIndex = 'xml:addIndex';
async serializeNumber(dataLabel, num) {
if (dataLabel == '')
return Number(num).toString();
return ('<' +
dataLabel +
'>' +
Number(num).toString() +
'</' +
dataLabel +
'>');
}
async serializeString(dataLabel, data) {
if (dataLabel == '')
return data;
return '<' + dataLabel + '>' + data + '</' + dataLabel + '>';
}
async serializeBoolean(dataLabel, data) {
if (dataLabel == '')
return data ? 'true' : 'false';
return ('<' +
dataLabel +
'>' +
(data ? 'true' : 'false') +
'</' +
dataLabel +
'>');
}
async serializeNull(dataLabel) {
if (dataLabel == '')
return 'null';
return '<' + dataLabel + '/>';
}
async serializeDate(dataLabel, data) {
if (dataLabel == '')
return super.serializeDate(dataLabel, data);
else
return ('<' +
dataLabel +
'>' +
(await super.serializeDate(dataLabel, data)) +
'</' +
dataLabel +
'>');
}
async handleSerializationStream(serializedObjectName, serialStream, objectMetaInfo) {
if (objectMetaInfo.hasAttribute(Serializer_1.SerializerCommon.Attributes.Array)) {
return this.serializeArray(serializedObjectName, serialStream, objectMetaInfo);
}
let objectLabel = '<' + serializedObjectName;
let objectChildren = '';
for (let elem of serialStream) {
if (elem.metaInfo != undefined &&
elem.metaInfo.hasAttribute(XML.Attribute)) {
objectLabel +=
' ' +
elem.dataLabel +
'="' +
(await this.serialize('', elem.data)) +
'"';
}
else if (elem.metaInfo != undefined &&
elem.metaInfo.hasAttribute(XML.Text)) {
objectChildren += await this.serialize('', elem.data);
}
else {
objectChildren += await this.serialize(elem.dataLabel, elem.data);
}
}
if (objectChildren == '') {
return objectLabel + '/>';
}
return (objectLabel +
'>' +
objectChildren +
'</' +
serializedObjectName +
'>');
}
async serializeArray(arrayName, serialStream, metaInfo) {
let outStream = '';
let shouldAddIndex = metaInfo.hasAttribute(XML.AddIndex);
for (let elem of serialStream) {
outStream += '<' + arrayName;
if (shouldAddIndex) {
outStream += ' index="' + elem.dataLabel + '"';
}
outStream += '>';
outStream += await this.serialize('', elem.data);
outStream += '</' + arrayName + '>';
}
return outStream;
}
}
CreamSerializers.XML = XML;
})(CreamSerializers || (exports.CreamSerializers = CreamSerializers = {}));