UNPKG

xml-class-transformer

Version:

Fluently parse XML into beautiful JS/TS classes and serialize them. GoLang's encoding/xml alternative for JS/TS world.

7 lines (6 loc) 9.78 kB
/*! * xml-class-transformer v3.0.1 * (c) Edgar Pogosyan * Released under the MIT License. */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("xml-js-v2")):"function"==typeof define&&define.amd?define(["exports","xml-js-v2"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["xml-class-transformer"]={},e.xmljs)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=n(t);const o=new class{marshal(e){if(void 0!==e)return null===e?"":`${e}`}unmarshal(e){if(void 0===e)return;const t=`${e}`;return""===t?null:t?parseFloat(t):void 0}},i=new class{marshal(e){if(void 0!==e)return null===e?"":`${e}`}unmarshal(e){if(void 0===e)return;const t=`${e}`;return""===t?null:t?BigInt(t):void 0}},s=new class{marshal(e){if(void 0!==e)return null===e?"":`${e}`}unmarshal(e){if(void 0!==e)return`${e}`}},a=new class{marshal(e){if(void 0!==e)return null===e?"":`${e}`}unmarshal(e){if(void 0===e)return;const t=`${e}`;return""===t?null:t?"true"===t:void 0}},l=new class{marshal(e){if(void 0!==e)return null===e?"":e.toISOString()}unmarshal(e){if(void 0!==e)return""===e?null:new Date(e)}};function m(e){return new Error(`xml-class-transformer: class "${e}" not found. Make sure there is a @XmlElem({...}) decorator on it, or XmlChildElem, XmlAttribute, XmlChardata or XmlComments decorator on its properties.`)}function c(e){return new Error(`xml-class-transformer: no XML name is specified for ${null==e?void 0:e.name}. Specify it with the @XmlElem({ name: '...' }) decorator.`)}function u(e){return e===String||e===Number||e===BigInt||e===Boolean||e===Date}function f(e){switch(e){case String:return s;case Number:return o;case BigInt:return i;case Boolean:return a;case Date:return l}throw new Error("unknown primitive type "+e)}const p=new class{constructor(){this.registry=new Map}setEntityOptions(e,t){const n=this.registry.get(e);n?n.entity=t:this.registry.set(e,{entity:t,properties:new Map})}setPropertyOptions(e,t,n){const r=this.getOrCreate(e);if(n.comments)for(const[n,o]of r.properties)if(o.comments)throw new Error(`xml-class-transformer: only one @XmlComment() decorator is allowed per class. Can not define @XmlComment() decorator for ${e.name}#${t} since it's already used for ${e.name}#${n}.`);if(n.name)for(const[o,i]of r.properties){if(i.name===n.name)throw new Error(`xml-class-transformer: can't use XML element name defined in { name: ${JSON.stringify(n.name)} } for ${e.name}#${t} since it's already used for ${e.name}#${o}. Change it to something else.`);if(n.chardata&&i.chardata)throw new Error(`xml-class-transformer: an XML element can have only one chardata property. Both ${e.name}#${t} and ${e.name}#${i.name} are defined as chardata, which is not valid.`)}r.properties.set(t,n)}getOrCreate(e){const t=this.registry.get(e);if(t)return t;{const t={entity:{name:null==e?void 0:e.name},properties:new Map};return this.registry.set(e,t),t}}get(e){return this.registry.get(e)}resolveUnionComponents(e){const t=new Map;for(const n of e){const e=p.get(n);if(!e)throw m(n);const r=e.entity.name;if(!r)throw c(n);t.set(r,n)}return t}};function h(e,t,n){if(u(n))return d(e,t,n);const r=p.get(n);if(!r)throw m(n);const o=t||r.entity.name;if(!o)throw c(n);const i=[],s={};for(const[t,o]of r.properties)y(n,e,o,t,i,s);return r.entity.xmlns&&(s.xmlns=r.entity.xmlns),{type:"element",name:o,attributes:s,elements:i}}function d(e,t,n){const r=f(n).marshal(e);return void 0===r?{}:{type:"element",name:t,elements:[{type:"text",text:r}]}}function y(e,t,n,r,o,i){n.comments?function(e,t,n){if(Array.isArray(e[t]))for(const r of e[t])n.push({type:"comment",comment:null==r?"":`${r}`})}(t,r,o):n.attr?function(e,t,n,r,o){if(!n.name)throw new Error(`xml-class-transformer: no name is specified for the property ${null==e?void 0:e.name}#${r}. Specify it with the @XmlAttribute({ name: '...' }) decorator.`);const i=v(t[r],n);if(void 0===i)return;o[n.name]=`${i}`}(e,t,n,r,i):n.chardata?function(e,t,n,r){const o=v(e[n],t);if(void 0===o)return;r.push({type:"text",text:o})}(t,n,r,o):n.array?function(e,t,n,r){if(null===e[n]||void 0===e[n])return;for(const o of e[n])if(t.marshaller||t.isPrimitiveType()){if(void 0===v(o,t))continue;r.push(d(o,t.name,String))}else{if(null==o)continue;const e=t.union?o.constructor:t.type();r.push(h(o,t.name,e))}}(t,n,r,o):n.marshaller||n.isPrimitiveType()?function(e,t,n,r,o){if(!n.name)throw new Error(`xml-class-transformer: no name is specified for property ${null==e?void 0:e.name}#${r}. Specify it with @XmlChildElem({ name: '...' }) decorator.`);const i=v(t[r],n);if(void 0===i)return;o.push(d(i,n.name,String))}(e,t,n,r,o):n.union?function(e,t,n){const r=e[t].constructor;n.push(h(e[t],void 0,r))}(t,r,o):function(e,t,n,r){void 0!==e[n]&&null!==e[n]&&r.push(h(e[n],t.name,t.type()))}(t,n,r,o)}function v(e,t){let n=e;if(t.marshaller)n=t.marshaller.marshal(e);else if(t.type){const r=t.type();u(r)&&(n=f(r).marshal(e))}return n}function w(e,t){if(u(t)){return function(e,t){const n=t?f(t):s,r="number"==typeof e?`${e}`:e;return n.unmarshal(r)}(g(e),t)}const n=p.get(t);if(!n)throw m(t);const r=new t;for(const[t,o]of n.properties)$(e,o,t,r);return r}function $(e,t,n,r){t.comments?function(e,t,n){const r=[];for(const t of e.elements||[])"comment"===t.type&&r.push(t.comment||"");n[t]=r}(e,n,r):t.attr?function(e,t,n,r){var o;if(!n.name)throw new Error(`xml-class-transformer: no name is specified for attribute ${t}. Specify it with @XmlAttribute({ name: '...' }) decorator.`);let i=null===(o=e.attributes)||void 0===o?void 0:o[n.name];"number"==typeof i&&(i=`${i}`);const s=x(i,n);r[t]=s}(e,n,t,r):t.chardata?function(e,t,n,r){const o=g(e),i=x(o,n);r[t]=i}(e,n,t,r):t.array?function(e,t,n,r){var o;if(n.union){const o=p.resolveUnionComponents(n.union()),i=[];for(const t of e.elements||[])if(t.name&&o.has(t.name)){const e=w(t,o.get(t.name));i.push(e)}r[t]=i}else{const i=(null===(o=e.elements)||void 0===o?void 0:o.filter((e=>e.name===n.name)))||[],s=[];for(const e of i){const t=w(e,n.type());s.push(t)}r[t]=s}}(e,n,t,r):t.union?function(e,t,n,r){var o;const i=p.resolveUnionComponents(n.union()),s=null===(o=e.elements)||void 0===o?void 0:o.find((e=>!!e.name&&i.has(e.name)));r[t]=s?w(s,i.get(s.name)):void 0}(e,n,t,r):function(e,t,n,r){var o;const i=null===(o=e.elements)||void 0===o?void 0:o.find((e=>e.name===n.name));if(n.marshaller||n.isPrimitiveType()){const e=x(i?g(i):void 0,n);r[t]=e}else r[t]=i?w(i,n.type()):void 0}(e,n,t,r)}function g(e){let t="";for(const n of e.elements||[])"text"===n.type&&n.text&&(t+=n.text||"");return t}function x(e,t){let n=e;if(t.marshaller)n=t.marshaller.unmarshal(e);else if(t.type){const r=t.type();u(r)&&(n=f(r).unmarshal(e))}return n}class b{}class E extends b{constructor(e){super(),Object.assign(this,e)}isPrimitiveType(){return!!this.type&&u(this.type())}}function X(e,t){return(n,r)=>{if("string"!=typeof r)throw new TypeError(`xml-class-transformer: Can't use @${e}({...}) decorator on a symbol property at ${n.constructor.name}#${r.toString()}`);if(!t.union&&!t.type&&!t.marshaller)throw new TypeError(`xml-class-transformer: No "type", "union" or "marshaller" was specified for the ${n.constructor.name}#${r.toString()}. Add it to the @${e}({...}) decorator.`);if(t.union&&t.type||t.union&&t.marshaller||t.type&&t.marshaller)throw new TypeError(`xml-class-transformer: The "union", "type" or "marshaller" options are not compatible with each other at ${n.constructor.name}#${r.toString()}. You can specify only one of them.`);if(t.union&&!t.union().length)throw new TypeError(`xml-class-transformer: The "union" option in @${e}({ ... }) can't be empty at ${n.constructor.name}#${r.toString()}. Either remove the "union" option or provide it with at least one type.`);if(t.union){if(t.name)throw new TypeError(`xml-class-transformer: The "union" option is not compatible with the "name" option at ${n.constructor.name}#${r.toString()}. XML element names for the union members should be specified at the union member classes.`)}else t.name=t.name||r;if(t.union){const i=t.union();if(i.find((e=>u(e))))throw new TypeError(`xml-class-transformer: unions of primitive types (String, Number, Boolean, BigInt or Date) are not supported. Fix it in the decorator @${e}({ union: ${o=i,"["+o.map((e=>{var t;return null!==(t=null==e?void 0:e.name)&&void 0!==t?t:`${o}`})).join(", ")+"]"}, ... }) at "${n.constructor.name}#${r.toString()}".`)}var o;p.setPropertyOptions(n.constructor,r,t)}}e.XmlAttribute=function(e){return X("XmlAttribute",new E(Object.assign(Object.assign({},e),{attr:!0})))},e.XmlChardata=function(e){return X("XmlChardata",new E(Object.assign(Object.assign({},e),{chardata:!0})))},e.XmlChildElem=function(e){return X("XmlChildElem",new E(e))},e.XmlComments=function(){return(e,t)=>{if("string"!=typeof t)throw new TypeError(`xml-class-transformer: Can't use @XmlComments({...}) decorator on a symbol property at ${e.constructor.name}#${t.toString()}`);p.setPropertyOptions(e.constructor,t,new E({comments:!0}))}},e.XmlElem=function(e){return t=>{if((e=e||{}).name=e.name||t.name,!e.name)throw c(t);return p.setEntityOptions(t,e),t}},e.classToXml=function(e,t){const n={elements:[h(e,"",e.constructor)]};return!1!==(null==t?void 0:t.declaration)&&("object"==typeof(null==t?void 0:t.declaration)&&null!==(null==t?void 0:t.declaration)?n.declaration=t.declaration:n.declaration={attributes:{version:"1.0",encoding:"UTF-8"}}),r.default.js2xml(n,t)},e.xmlToClass=function(e,t,n){var o;const i=null===(o=r.default.xml2js(e,Object.assign(Object.assign({},n),{compact:!1,alwaysArray:!0})).elements)||void 0===o?void 0:o[0];if(!i)throw new Error("xml-class-transformer: No elements found in the xml, make sure its valid.");return w(i,t)},Object.defineProperty(e,"__esModule",{value:!0})}));