From 4e61705bbd00c3c87e757f73bf97c73c5a0b8685 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 3 May 2021 23:09:14 +0800 Subject: [PATCH 1/7] virtual children --- .gitignore | 2 +- lib/annotations/XMLAttribute.ts | 11 +- lib/annotations/XMLChild.ts | 9 +- lib/annotations/XMLElement.ts | 6 +- lib/interfaces/ICustomXMLAttributeOptions.ts | 3 +- lib/interfaces/ICustomXMLChildOptions.ts | 3 +- lib/interfaces/IFullXMLAttributeOptions.ts | 3 +- lib/interfaces/IFullXMLChildOptions.ts | 3 +- lib/interfaces/ISchemaOptions.ts | 2 - lib/interfaces/IXMLAttributeOptions.ts | 2 - lib/interfaces/IXMLChildOptions.ts | 3 +- lib/interfaces/IXMLElementOptions.ts | 2 - lib/models/XMLAttribute.ts | 68 +++++----- lib/models/XMLChild.ts | 130 ++++++++++-------- lib/models/XMLElement.ts | 131 +++++++++++-------- lib/utils.ts | 14 +- package.json | 6 +- test/models/Child.ts | 6 + test/models/ChildA.ts | 6 + test/models/ChildB.ts | 6 + test/specs/virtual.spec.ts | 27 ++++ tsconfig.json | 15 +-- 22 files changed, 267 insertions(+), 191 deletions(-) create mode 100644 test/models/Child.ts create mode 100644 test/models/ChildA.ts create mode 100644 test/models/ChildB.ts create mode 100644 test/specs/virtual.spec.ts diff --git a/.gitignore b/.gitignore index 56987e8..03255c9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ # ide .idea - +yarn.lock # libraries node_modules diff --git a/lib/annotations/XMLAttribute.ts b/lib/annotations/XMLAttribute.ts index f0267aa..5a5c296 100644 --- a/lib/annotations/XMLAttribute.ts +++ b/lib/annotations/XMLAttribute.ts @@ -1,17 +1,16 @@ import 'reflect-metadata'; -import {XMLAttribute as XMLAttributeModel} from "../models/XMLAttribute"; -import {IXMLAttributeOptions} from "../interfaces/IXMLAttributeOptions"; +import { XMLAttribute as XMLAttributeModel } from '../models/XMLAttribute'; +import { IXMLAttributeOptions } from '../interfaces/IXMLAttributeOptions'; export function XMLAttribute(target: any, key: string, descriptor?: TypedPropertyDescriptor): void; export function XMLAttribute(options: IXMLAttributeOptions): Function; -export function XMLAttribute(...args: any[]): void|Function { - +export function XMLAttribute(...args: any[]): void | Function { if (args.length === 1) { - return (target: any, key: string, descriptor?: TypedPropertyDescriptor) => { - return XMLAttributeModel.annotate(target, key, args[0], descriptor); }; + } else if (args.length === 4) { + return XMLAttributeModel.annotate(args[0], args[1], args[2], args[3]); } return XMLAttributeModel.annotate(args[0], args[1], void 0, args[2]); } diff --git a/lib/annotations/XMLChild.ts b/lib/annotations/XMLChild.ts index b42f411..ef0ddfa 100644 --- a/lib/annotations/XMLChild.ts +++ b/lib/annotations/XMLChild.ts @@ -1,15 +1,12 @@ import 'reflect-metadata'; -import {XMLChild as XMLChildModel} from "../models/XMLChild"; -import {IXMLChildOptions} from "../interfaces/IXMLChildOptions"; +import { XMLChild as XMLChildModel } from '../models/XMLChild'; +import { IXMLChildOptions } from '../interfaces/IXMLChildOptions'; export function XMLChild(target: any, key: string, descriptor?: TypedPropertyDescriptor): void; export function XMLChild(options: IXMLChildOptions): Function; -export function XMLChild(...args: any[]): void|Function { - +export function XMLChild(...args: any[]): void | Function { if (args.length === 1) { - return (target: any, key: string, descriptor?: TypedPropertyDescriptor) => { - return XMLChildModel.annotate(target, key, args[0], descriptor); }; } diff --git a/lib/annotations/XMLElement.ts b/lib/annotations/XMLElement.ts index adfc853..4588025 100644 --- a/lib/annotations/XMLElement.ts +++ b/lib/annotations/XMLElement.ts @@ -1,11 +1,9 @@ import 'reflect-metadata'; -import {XMLElement as XMLElementModel} from "../models/XMLElement"; -import {IXMLElementOptions} from "../interfaces/IXMLElementOptions"; +import { XMLElement as XMLElementModel } from '../models/XMLElement'; +import { IXMLElementOptions } from '../interfaces/IXMLElementOptions'; export function XMLElement(options: IXMLElementOptions): Function { - return (target: any) => { - return XMLElementModel.annotate(target.prototype, options); }; } diff --git a/lib/interfaces/ICustomXMLAttributeOptions.ts b/lib/interfaces/ICustomXMLAttributeOptions.ts index 3c0f75a..89794bf 100644 --- a/lib/interfaces/ICustomXMLAttributeOptions.ts +++ b/lib/interfaces/ICustomXMLAttributeOptions.ts @@ -1,7 +1,6 @@ -import {IXMLAttributeOptions} from "./IXMLAttributeOptions"; +import { IXMLAttributeOptions } from './IXMLAttributeOptions'; export interface ICustomXMLAttributeOptions extends IXMLAttributeOptions { - name: string; getter?: (entity?: any) => any; value?: any; diff --git a/lib/interfaces/ICustomXMLChildOptions.ts b/lib/interfaces/ICustomXMLChildOptions.ts index e4a47b2..c7c07d4 100644 --- a/lib/interfaces/ICustomXMLChildOptions.ts +++ b/lib/interfaces/ICustomXMLChildOptions.ts @@ -1,7 +1,6 @@ -import {IXMLChildOptions} from "./IXMLChildOptions"; +import { IXMLChildOptions } from './IXMLChildOptions'; export interface ICustomXMLChildOptions extends IXMLChildOptions { - name: string; getter?: (entity?: any) => any; value?: any; diff --git a/lib/interfaces/IFullXMLAttributeOptions.ts b/lib/interfaces/IFullXMLAttributeOptions.ts index cb1ee5e..1e777cc 100644 --- a/lib/interfaces/IFullXMLAttributeOptions.ts +++ b/lib/interfaces/IFullXMLAttributeOptions.ts @@ -1,7 +1,6 @@ -import {IXMLAttributeOptions} from "./IXMLAttributeOptions"; +import { IXMLAttributeOptions } from './IXMLAttributeOptions'; export interface IFullXMLAttributeOptions extends IXMLAttributeOptions { - name: string; getter: (entity: any) => any; } diff --git a/lib/interfaces/IFullXMLChildOptions.ts b/lib/interfaces/IFullXMLChildOptions.ts index 67778ca..409d305 100644 --- a/lib/interfaces/IFullXMLChildOptions.ts +++ b/lib/interfaces/IFullXMLChildOptions.ts @@ -1,7 +1,6 @@ -import {IXMLChildOptions} from "./IXMLChildOptions"; +import { IXMLChildOptions } from './IXMLChildOptions'; export interface IFullXMLChildOptions extends IXMLChildOptions { - name: string; getter: (entity: any) => any; } diff --git a/lib/interfaces/ISchemaOptions.ts b/lib/interfaces/ISchemaOptions.ts index d6fbb4f..c20c7c0 100644 --- a/lib/interfaces/ISchemaOptions.ts +++ b/lib/interfaces/ISchemaOptions.ts @@ -1,5 +1,3 @@ - export interface ISchemaOptions { - attrContainerName?: string; } diff --git a/lib/interfaces/IXMLAttributeOptions.ts b/lib/interfaces/IXMLAttributeOptions.ts index 2fa8a85..f90d628 100644 --- a/lib/interfaces/IXMLAttributeOptions.ts +++ b/lib/interfaces/IXMLAttributeOptions.ts @@ -1,6 +1,4 @@ - export interface IXMLAttributeOptions { - name?: string; required?: boolean; namespace?: string; diff --git a/lib/interfaces/IXMLChildOptions.ts b/lib/interfaces/IXMLChildOptions.ts index 1652ad7..6da90c9 100644 --- a/lib/interfaces/IXMLChildOptions.ts +++ b/lib/interfaces/IXMLChildOptions.ts @@ -1,9 +1,8 @@ - export interface IXMLChildOptions { - name?: string; stripPluralS?: boolean; namespace?: string; nestedNamespace?: string; implicitStructure?: string; + virtual?: boolean; } diff --git a/lib/interfaces/IXMLElementOptions.ts b/lib/interfaces/IXMLElementOptions.ts index f0057f0..121dd62 100644 --- a/lib/interfaces/IXMLElementOptions.ts +++ b/lib/interfaces/IXMLElementOptions.ts @@ -1,5 +1,3 @@ - export interface IXMLElementOptions { - root?: string; } diff --git a/lib/models/XMLAttribute.ts b/lib/models/XMLAttribute.ts index bdc8fbd..757f308 100644 --- a/lib/models/XMLAttribute.ts +++ b/lib/models/XMLAttribute.ts @@ -1,31 +1,40 @@ -import {XMLElement} from "./XMLElement"; -import {IXMLAttributeOptions} from "../interfaces/IXMLAttributeOptions"; -import {IFullXMLAttributeOptions} from "../interfaces/IFullXMLAttributeOptions"; -import {ICustomXMLAttributeOptions} from "../interfaces/ICustomXMLAttributeOptions"; -import {createCustomGetter} from "../utils"; +import { XMLElement } from './XMLElement'; +import { IXMLAttributeOptions } from '../interfaces/IXMLAttributeOptions'; +import { IFullXMLAttributeOptions } from '../interfaces/IFullXMLAttributeOptions'; +import { ICustomXMLAttributeOptions } from '../interfaces/ICustomXMLAttributeOptions'; +import { createCustomGetter } from '../utils'; export class XMLAttribute { - private name: string; + getName() { + return this.name; + } - static annotate(target: any, - key: string, - options: IXMLAttributeOptions = {}, - descriptor?: TypedPropertyDescriptor): void { - + getOptions(){ + return this.options + } + static annotate( + target: any, + key: string, + options: IXMLAttributeOptions = {}, + descriptor?: TypedPropertyDescriptor, + ): void { const element = XMLElement.getOrCreateIfNotExists(target); - const fullOptions = Object.assign({ - getter(entity: any): any { - if (descriptor && descriptor.get) { - return descriptor.get.call(entity); - } - return entity[key]; - } - }, options); + const fullOptions = Object.assign( + { + getter(entity: any): any { + if (descriptor && descriptor.get) { + return descriptor.get.call(entity); + } + return entity[key]; + }, + }, + options, + ); fullOptions.name = options.name || key; - - element.addAttribute(new XMLAttribute(fullOptions as IFullXMLAttributeOptions)); + if (!element.hasAttribute(fullOptions.name)) + element.addAttribute(new XMLAttribute(fullOptions as IFullXMLAttributeOptions)); } static createAttribute(options: ICustomXMLAttributeOptions): XMLAttribute { @@ -33,35 +42,32 @@ export class XMLAttribute { const hasValue = options.value !== void 0; if ((hasGetter && hasValue) || (!hasGetter && !hasValue)) { - throw new Error(`Either a getter or a value has to be defined for attribute "${options.name}".`); } - const fullOptions = Object.assign({ - getter: createCustomGetter(options), - }, options); - + const fullOptions = Object.assign( + { + getter: createCustomGetter(options), + }, + options, + ); + return new XMLAttribute(fullOptions); } setSchema(target: any, entity: any): void { - const value = this.options.getter.call(null, entity); - if (value !== void 0) { target[this.name] = value; } else if (this.options.required) { - throw new Error(`Attribute ${this.name} is required, but empty.`); } } private constructor(private options: IFullXMLAttributeOptions) { - this.name = options.name; if (options.namespace) { - this.name = options.namespace + ':' + this.name; } } diff --git a/lib/models/XMLChild.ts b/lib/models/XMLChild.ts index 6e069cb..863823d 100644 --- a/lib/models/XMLChild.ts +++ b/lib/models/XMLChild.ts @@ -1,37 +1,41 @@ -import 'es6-shim'; -import {XMLElement} from "./XMLElement"; -import * as _ from "lodash"; -import {ns} from "../utils"; -import {IXMLChildOptions} from "../interfaces/IXMLChildOptions"; -import {IFullXMLChildOptions} from "../interfaces/IFullXMLChildOptions"; -import {ICustomXMLChildOptions} from "../interfaces/ICustomXMLChildOptions"; -import {createCustomGetter} from "../utils"; -import {ISchemaOptions} from "../interfaces/ISchemaOptions"; - -type Tree = {name: string; attributes: {[name: string]: string}}; +import { META_KEY, XMLElement } from './XMLElement'; +import merge from 'lodash.merge'; +import { ns } from '../utils'; +import { IXMLChildOptions } from '../interfaces/IXMLChildOptions'; +import { IFullXMLChildOptions } from '../interfaces/IFullXMLChildOptions'; +import { ICustomXMLChildOptions } from '../interfaces/ICustomXMLChildOptions'; +import { createCustomGetter } from '../utils'; +import { ISchemaOptions } from '../interfaces/ISchemaOptions'; +import groupBy from 'lodash.groupby'; + +type Tree = { name: string; attributes: { [name: string]: string } }; export class XMLChild { - private name: string; - - static annotate(target: any, - key: string, - options: IXMLChildOptions = {}, - descriptor?: TypedPropertyDescriptor): void { - + getName() { + return this.name; + } + static annotate( + target: any, + key: string, + options: IXMLChildOptions = {}, + descriptor?: TypedPropertyDescriptor, + ): void { const element = XMLElement.getOrCreateIfNotExists(target); - const fullOptions = Object.assign({ - getter(entity: any): any { - if (descriptor && descriptor.get) { - return descriptor.get.call(entity); - } + const fullOptions = Object.assign( + { + getter(entity: any): any { + if (descriptor && descriptor.get) { + return descriptor.get.call(entity); + } - return entity[key]; - } - }, options); + return entity[key]; + }, + }, + options, + ); fullOptions.name = options.name || key; - element.addChild(new XMLChild(fullOptions as IFullXMLChildOptions)); } @@ -40,33 +44,54 @@ export class XMLChild { const hasValue = options.value !== void 0; if ((hasGetter && hasValue) || (!hasGetter && !hasValue)) { - throw new Error(`Either a getter or a value has to be defined for attribute "${options.name}".`); } - const fullOptions = Object.assign({ - getter: createCustomGetter(options), - }, options); + const fullOptions = Object.assign( + { + getter: createCustomGetter(options), + }, + options, + ); return new XMLChild(fullOptions); } setSchema(target: any, parentEntity: any, isAsync: boolean = false, schemaOptions: ISchemaOptions): any { - const entity = this.options.getter.call(null, parentEntity); - const process = (schema: any) => { + if (this.options.virtual === true) { + Object.entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY, e))).forEach(([key, val]) => { + const properties = (val as any[]).map((item) => { + let next = Object.getPrototypeOf(item); + let temp = null; + let ele = null; + const result = {}; + while (true) { + temp = new next.constructor(); + if (typeof XMLElement.getXMLElement(temp, key) === 'undefined') { + break; + } + Object.assign(temp, item); + ele = XMLElement.getSchema(temp); + merge(result, ele); + next = Object.getPrototypeOf(next); + } + return result; + }); + target[key] = properties; + }); + return; + } + const process = (schema: any) => { if (schema !== void 0 && schema !== null) { - - const structure: string|undefined = this.options.implicitStructure; + const structure: string | undefined = this.options.implicitStructure; if (structure) { - // a schema can be an array or an object, // so we ensure that this is always an // array and don't have to distinguish - [].concat(schema).forEach(_schema => this.resolveImplicitStructure(structure, target, _schema)); + [].concat(schema).forEach((_schema) => this.resolveImplicitStructure(structure, target, _schema)); } else { - if (entity === schema && this.options.nestedNamespace) { let nsSchema = {}; @@ -85,17 +110,13 @@ export class XMLChild { }; if (isAsync) { - - XMLElement.getSchemaAsync(entity, schemaOptions) - .then(schema => process(schema)); + XMLElement.getSchemaAsync(entity, schemaOptions).then((schema) => process(schema)); } else { - process(XMLElement.getSchema(entity, schemaOptions)); } } private constructor(private options: IFullXMLChildOptions) { - this.name = options.name; if (options.stripPluralS) { @@ -110,22 +131,23 @@ export class XMLChild { private resolveImplicitStructure(structure: string, target: any, schema: any): void { const PLACEHOLDER = '$'; - if (!new RegExp(`.\\.\\${PLACEHOLDER}`).test(structure) && + if ( + !new RegExp(`.\\.\\${PLACEHOLDER}`).test(structure) && !new RegExp(`.\\.\\${PLACEHOLDER}\\..`).test(structure) && - !new RegExp(`\\${PLACEHOLDER}\\..`).test(structure)) { + !new RegExp(`\\${PLACEHOLDER}\\..`).test(structure) + ) { throw new Error(`Structure '${structure}' is invalid`); } let tree = this.getImplicitNodeTree(structure); - const indexOfPlaceholder = tree.findIndex(node => node.name === PLACEHOLDER); + const indexOfPlaceholder = tree.findIndex((node) => node.name === PLACEHOLDER); tree[indexOfPlaceholder].name = this.name; - for (let i = 0; i < tree.length; i++) { let node = tree[i]; if (!Array.isArray(target)) { if (!target[node.name]) { if (i !== indexOfPlaceholder) { - target[node.name] = {'@': node.attributes}; + target[node.name] = { '@': node.attributes }; } else { target[node.name] = []; } @@ -140,7 +162,7 @@ export class XMLChild { if (Array.isArray(target)) { target.push(schema); } else { - target[node.name] = _.merge(schema, {'@': node.attributes}); + target[node.name] = merge(schema, { '@': node.attributes }); } } } @@ -152,26 +174,22 @@ export class XMLChild { const tree: Tree[] = []; while (match !== null) { - const tagName = match[1] || match[3]; const attributeString = match[2]; tree.push({ name: tagName, - attributes: this.getAttributes(attributeString) + attributes: this.getAttributes(attributeString), }); match = REGEX.exec(treeString); } return tree; } - private getAttributes(attributeString: string): {[attrName: string]: string} { - + private getAttributes(attributeString: string): { [attrName: string]: string } { let attributes = {}; if (attributeString) { - - attributeString.split(',').forEach(val => { - + attributeString.split(',').forEach((val) => { const attributesArr = val.split('='); attributes[attributesArr[0]] = attributesArr[1]; }); diff --git a/lib/models/XMLElement.ts b/lib/models/XMLElement.ts index 438af7a..f8937e7 100644 --- a/lib/models/XMLElement.ts +++ b/lib/models/XMLElement.ts @@ -1,21 +1,26 @@ import 'reflect-metadata'; -import * as Promise from "bluebird"; -import {XMLChild} from "./XMLChild"; -import {XMLAttribute} from "./XMLAttribute"; +// import * as Promise from "bluebird"; +import { XMLChild } from './XMLChild'; +import { XMLAttribute } from './XMLAttribute'; import * as js2xmlparser from 'js2xmlparser'; -import {DEFAULT_ATTRIBUTE_PROPERTY} from "../utils"; -import {IXMLElementOptions} from "../interfaces/IXMLElementOptions"; -import {ISchemaOptions} from "../interfaces/ISchemaOptions"; +import { DEFAULT_ATTRIBUTE_PROPERTY } from '../utils'; +import { IXMLElementOptions } from '../interfaces/IXMLElementOptions'; +import { ISchemaOptions } from '../interfaces/ISchemaOptions'; +import merge from 'lodash.merge'; const PARSER_OPTIONS = { declaration: { - encoding: 'UTF-8' - } + encoding: 'UTF-8', + }, + useCDATA: true, + cdataKeys: ['*'], + format: { + doubleQuotes: true, + }, }; -const META_KEY = 'xml:element'; +export const META_KEY = 'xml:element'; export class XMLElement { - private attributes: XMLAttribute[]; private children: XMLChild[]; private root?: string; @@ -23,33 +28,27 @@ export class XMLElement { static serialize(entity: any): string; static serialize(root: string, entity: any): string; static serialize(...args: any[]): string { - - const {root, entity} = this.getRootAndEntity(args); + const { root, entity } = this.getRootAndEntity(args); const schema = this.getSchema(entity); - - return js2xmlparser.parse(root, schema, PARSER_OPTIONS); + const parseOptions = Object.assign({}, PARSER_OPTIONS); + return js2xmlparser.parse(root, schema, parseOptions); } static serializeAsync(entity: any): Promise; static serializeAsync(root: string, entity: any): Promise; static serializeAsync(...args: any[]): Promise { + const { root, entity } = this.getRootAndEntity(args); - const {root, entity} = this.getRootAndEntity(args); - - return this.getSchemaAsync(entity) - .then(schema => js2xmlparser.parse(root, schema, PARSER_OPTIONS)) - ; + return this.getSchemaAsync(entity).then((schema) => js2xmlparser.parse(root, schema, PARSER_OPTIONS)); } static getSchema(entities: any[], schemaOptions?: ISchemaOptions): any; static getSchema(entity: any, schemaOptions?: ISchemaOptions): any; static getSchema(arg: any, schemaOptions: ISchemaOptions = {}): any { - if (arg === void 0) return; if (Array.isArray(arg)) { - - return arg.map(entity => this.processSchema(entity, false, schemaOptions)); + return arg.map((entity) => this.processSchema(entity, false, schemaOptions)); } return this.processSchema(arg, false, schemaOptions); } @@ -57,66 +56,88 @@ export class XMLElement { static getSchemaAsync(entities: any[], schemaOptions?: ISchemaOptions): Promise; static getSchemaAsync(entity: any, schemaOptions?: ISchemaOptions): Promise; static getSchemaAsync(arg: any, schemaOptions: ISchemaOptions = {}): Promise { - const processAsync = (entity: any) => { - return Promise.resolve(this.processSchema(entity, true, schemaOptions)); }; if (arg === void 0) Promise.resolve(); if (Array.isArray(arg)) { - - return Promise.all(arg.map(entity => processAsync(entity))); + return Promise.all(arg.map((entity) => processAsync(entity))); } return processAsync(arg); } - static getXMLElement(target: any): XMLElement|undefined { - - return Reflect.getMetadata(META_KEY, target); + static getXMLElement(target: any, root?: string): XMLElement | undefined { + const rootName = root ? root : Reflect.getMetadata(META_KEY, target); + return Reflect.getMetadata(rootName, target); } - static setXMLElement(target: any, element: XMLElement): void { + static setXMLElement(target: any, ele: XMLElement, root: string): void { + Reflect.defineMetadata(META_KEY, root, target); + let next = Object.getPrototypeOf(target); + let tempEle = null; + while (true) { + tempEle = XMLElement.getXMLElement(next); + if (typeof tempEle === 'undefined') { + break; + } + const oldAttrs = ele.attributes?.map((e) => e.getName()) || []; + const oldChilds = ele.children?.map((e) => e.getName()) || []; + + if (oldAttrs.length) { + merge(ele, { + attributes: tempEle.attributes?.filter((e) => oldAttrs.indexOf(e.name) === -1) || tempEle.attributes, + }); + } else { + Object.assign(ele, { + attributes: tempEle.attributes && tempEle.attributes.length ? tempEle.attributes : [], + }); + } - return Reflect.defineMetadata(META_KEY, element, target); + if (oldChilds.length) { + merge(ele, { + children: tempEle.children?.filter((e) => oldChilds.indexOf(e.name) === -1) || tempEle.children, + }); + } else { + Object.assign(ele, { + children: tempEle.children && tempEle.children.length ? tempEle.children : [], + }); + } + next = Object.getPrototypeOf(next); + } + return Reflect.defineMetadata(root, ele, target); } - static getOrCreateIfNotExists(target: any): XMLElement { - let element = this.getXMLElement(target); + static getOrCreateIfNotExists(target: any, root?: string): XMLElement { + const rootName = root ? root : Reflect.getMetadata(META_KEY, target); + let element = this.getXMLElement(target, rootName); if (!element) { - element = new XMLElement(); - this.setXMLElement(target, element); + element.root = rootName; + this.setXMLElement(target, element, rootName); } return element; } static annotate(target: any, options: IXMLElementOptions): void { - - let element = this.getOrCreateIfNotExists(target); - - element.root = options.root; + this.getOrCreateIfNotExists(target, options.root); } - private static processSchema(entity: any, - isAsync: boolean, - schemaOptions: ISchemaOptions): any { + private static processSchema(entity: any, isAsync: boolean, schemaOptions: ISchemaOptions): any { if (entity && typeof entity === 'object') { - const element = XMLElement.getXMLElement(entity); if (element) { - return element.getSchema(entity, isAsync, schemaOptions); } + } return entity; } - private static getRootAndEntity(args: any[]): {root: string, entity: any} { - + private static getRootAndEntity(args: any[]): { root: string; entity: any } { let entity; let root; @@ -136,35 +157,35 @@ export class XMLElement { throw new Error('No root defined for entity: ' + JSON.stringify(entity)); } - return {root, entity}; + return { root, entity }; + } + hasAttribute(name: string): boolean { + if (!this.attributes) { + return false; + } + return this.attributes.filter((e) => e.getName() === name).length >= 1; } - addAttribute(attribute: XMLAttribute): void { - if (!this.attributes) this.attributes = []; - this.attributes.push(attribute); } addChild(child: XMLChild): void { - if (!this.children) this.children = []; this.children.push(child); } private getSchema(entity: any, isAsync: boolean, schemaOptions: ISchemaOptions): void { - const object: any = {}; const attrProperty = schemaOptions.attrContainerName || DEFAULT_ATTRIBUTE_PROPERTY; if (this.attributes) { object[attrProperty] = {}; - this.attributes.forEach(attr => attr.setSchema(object[attrProperty], entity)); + this.attributes.forEach((attr) => attr.setSchema(object[attrProperty], entity)); } - if (this.children) { - this.children.forEach(child => child.setSchema(object, entity, isAsync, schemaOptions)); + this.children.forEach((child) => child.setSchema(object, entity, isAsync, schemaOptions)); } return object; diff --git a/lib/utils.ts b/lib/utils.ts index b05b1f4..b852739 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,19 +1,21 @@ - export const DEFAULT_ATTRIBUTE_PROPERTY = '@'; export function ns(namepsace: string, value: string): string { - return namepsace + ':' + value; } -export function createCustomGetter(_options: {restrictTo?: any[], getter?: (entity: any) => any, value?: any}): (entity: any) => any { +export function createCustomGetter(_options: { + restrictTo?: any[]; + getter?: (entity: any) => any; + value?: any; +}): (entity: any) => any { if (_options.restrictTo) { const restrictTo = _options.restrictTo as any[]; - return entity => { + return (entity) => { if (restrictTo.indexOf(entity) !== -1) { - return (_options.getter ? _options.getter(entity) : _options.value); + return _options.getter ? _options.getter(entity) : _options.value; } }; } - return (_options.getter || (() => _options.value)); + return _options.getter || (() => _options.value); } diff --git a/package.json b/package.json index 34167ec..a815b8c 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ "bluebird": "3.5.1", "es6-shim": "0.35.3", "js2xmlparser": "3.0.0", - "lodash": "4.17.10" + "lodash": "4.17.10", + "lodash.groupby": "4.6.0", + "lodash.merge": "4.6.2" }, "devDependencies": { "@types/chai": "4.1.4", @@ -36,6 +38,6 @@ "mocha": "5.2.0", "reflect-metadata": "^0.1.8", "tslint": "5.11.0", - "typescript": "2.9.2" + "typescript": "^3.9.3" } } diff --git a/test/models/Child.ts b/test/models/Child.ts new file mode 100644 index 0000000..c89f0e0 --- /dev/null +++ b/test/models/Child.ts @@ -0,0 +1,6 @@ +import {XMLElement} from "../../lib/annotations/XMLElement"; + +@XMLElement({root: "child"}) +export class Child { + +} \ No newline at end of file diff --git a/test/models/ChildA.ts b/test/models/ChildA.ts new file mode 100644 index 0000000..36ffa40 --- /dev/null +++ b/test/models/ChildA.ts @@ -0,0 +1,6 @@ + +import {XMLElement} from "../../lib/annotations/XMLElement"; +// import { Child } from "./Child"; +@XMLElement({root: "child_b"}) +export class ChildA { +} diff --git a/test/models/ChildB.ts b/test/models/ChildB.ts new file mode 100644 index 0000000..38b98f0 --- /dev/null +++ b/test/models/ChildB.ts @@ -0,0 +1,6 @@ +import {XMLElement} from "../../lib/annotations/XMLElement"; + +@XMLElement({root: "child_a"}) +export class ChildB { + +} \ No newline at end of file diff --git a/test/specs/virtual.spec.ts b/test/specs/virtual.spec.ts new file mode 100644 index 0000000..1c43943 --- /dev/null +++ b/test/specs/virtual.spec.ts @@ -0,0 +1,27 @@ + +import {expect} from 'chai'; +import {XMLChild} from "../../lib/annotations/XMLChild"; +import { xml } from '../../'; +import {XMLElement} from "../../lib/annotations/XMLElement"; +import { Child } from "../models/Child"; +import { ChildA } from "../models/ChildA"; +import { ChildB } from "../models/ChildB"; + +@XMLElement({root: "parent"}) +class Parent extends Child{ + @XMLChild({virtual: true}) + childs: Child[] = []; +} + + +describe("virtual children", () => { + + it(`should have attributes "firstname" and "age" with specified values`, () => { + const a = new Parent(); + a.childs.push(new ChildA()); + a.childs.push(new ChildB()); + const s = xml.serialize(a); + expect(s).contains(" Date: Tue, 4 May 2021 02:41:53 +0800 Subject: [PATCH 2/7] add virtual children elements, xml model inheritance --- lib/models/XMLAttribute.ts | 3 +-- lib/models/XMLChild.ts | 10 ++++---- lib/models/XMLElement.ts | 50 +++++++++++++++----------------------- package.json | 4 +-- test/models/Child.ts | 4 ++- test/models/ChildA.ts | 8 ++++-- test/models/ChildB.ts | 9 ++++--- test/specs/Person.spec.ts | 5 ++-- test/specs/virtual.spec.ts | 8 +++--- tsconfig.json | 15 ++++++------ 10 files changed, 56 insertions(+), 60 deletions(-) diff --git a/lib/models/XMLAttribute.ts b/lib/models/XMLAttribute.ts index 757f308..e8d739f 100644 --- a/lib/models/XMLAttribute.ts +++ b/lib/models/XMLAttribute.ts @@ -33,8 +33,7 @@ export class XMLAttribute { ); fullOptions.name = options.name || key; - if (!element.hasAttribute(fullOptions.name)) - element.addAttribute(new XMLAttribute(fullOptions as IFullXMLAttributeOptions)); + element.addAttribute(new XMLAttribute(fullOptions as IFullXMLAttributeOptions)); } static createAttribute(options: ICustomXMLAttributeOptions): XMLAttribute { diff --git a/lib/models/XMLChild.ts b/lib/models/XMLChild.ts index 863823d..bb19769 100644 --- a/lib/models/XMLChild.ts +++ b/lib/models/XMLChild.ts @@ -1,12 +1,13 @@ +import 'es6-shim'; import { META_KEY, XMLElement } from './XMLElement'; -import merge from 'lodash.merge'; +import * as merge from 'lodash.merge'; import { ns } from '../utils'; import { IXMLChildOptions } from '../interfaces/IXMLChildOptions'; import { IFullXMLChildOptions } from '../interfaces/IFullXMLChildOptions'; import { ICustomXMLChildOptions } from '../interfaces/ICustomXMLChildOptions'; import { createCustomGetter } from '../utils'; import { ISchemaOptions } from '../interfaces/ISchemaOptions'; -import groupBy from 'lodash.groupby'; +import * as groupBy from 'lodash.groupby'; type Tree = { name: string; attributes: { [name: string]: string } }; @@ -60,7 +61,7 @@ export class XMLChild { setSchema(target: any, parentEntity: any, isAsync: boolean = false, schemaOptions: ISchemaOptions): any { const entity = this.options.getter.call(null, parentEntity); if (this.options.virtual === true) { - Object.entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY, e))).forEach(([key, val]) => { + Object.entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY + ":name", e))).forEach(([key, val]) => { const properties = (val as any[]).map((item) => { let next = Object.getPrototypeOf(item); let temp = null; @@ -68,7 +69,7 @@ export class XMLChild { const result = {}; while (true) { temp = new next.constructor(); - if (typeof XMLElement.getXMLElement(temp, key) === 'undefined') { + if (typeof XMLElement.getXMLElement(temp) === 'undefined') { break; } Object.assign(temp, item); @@ -78,7 +79,6 @@ export class XMLChild { } return result; }); - target[key] = properties; }); return; diff --git a/lib/models/XMLElement.ts b/lib/models/XMLElement.ts index f8937e7..b620e9a 100644 --- a/lib/models/XMLElement.ts +++ b/lib/models/XMLElement.ts @@ -1,5 +1,5 @@ import 'reflect-metadata'; -// import * as Promise from "bluebird"; +import { Promise } from "bluebird"; import { XMLChild } from './XMLChild'; import { XMLAttribute } from './XMLAttribute'; import * as js2xmlparser from 'js2xmlparser'; @@ -11,12 +11,7 @@ import merge from 'lodash.merge'; const PARSER_OPTIONS = { declaration: { encoding: 'UTF-8', - }, - useCDATA: true, - cdataKeys: ['*'], - format: { - doubleQuotes: true, - }, + } }; export const META_KEY = 'xml:element'; @@ -68,15 +63,13 @@ export class XMLElement { return processAsync(arg); } - static getXMLElement(target: any, root?: string): XMLElement | undefined { - const rootName = root ? root : Reflect.getMetadata(META_KEY, target); - return Reflect.getMetadata(rootName, target); + static getXMLElement(target: any): XMLElement | undefined { + return Reflect.getMetadata(META_KEY, target); } - static setXMLElement(target: any, ele: XMLElement, root: string): void { - Reflect.defineMetadata(META_KEY, root, target); + static setXMLElement(target: any, ele: XMLElement): void { let next = Object.getPrototypeOf(target); - let tempEle = null; + let tempEle: XMLElement | undefined; while (true) { tempEle = XMLElement.getXMLElement(next); if (typeof tempEle === 'undefined') { @@ -87,7 +80,7 @@ export class XMLElement { if (oldAttrs.length) { merge(ele, { - attributes: tempEle.attributes?.filter((e) => oldAttrs.indexOf(e.name) === -1) || tempEle.attributes, + attributes: tempEle.attributes?.filter((e) => oldAttrs.indexOf(e.getName()) === -1) || tempEle.attributes, }); } else { Object.assign(ele, { @@ -97,7 +90,7 @@ export class XMLElement { if (oldChilds.length) { merge(ele, { - children: tempEle.children?.filter((e) => oldChilds.indexOf(e.name) === -1) || tempEle.children, + children: tempEle.children?.filter((e) => oldChilds.indexOf(e.getName()) === -1) || tempEle.children, }); } else { Object.assign(ele, { @@ -106,24 +99,25 @@ export class XMLElement { } next = Object.getPrototypeOf(next); } - return Reflect.defineMetadata(root, ele, target); + return Reflect.defineMetadata(META_KEY, ele, target); } - static getOrCreateIfNotExists(target: any, root?: string): XMLElement { - const rootName = root ? root : Reflect.getMetadata(META_KEY, target); - let element = this.getXMLElement(target, rootName); - + static getOrCreateIfNotExists(target: any): XMLElement { + let element = this.getXMLElement(target); if (!element) { element = new XMLElement(); - element.root = rootName; - this.setXMLElement(target, element, rootName); + this.setXMLElement(target, element); } return element; } - + public getName(){ + return this.root + } static annotate(target: any, options: IXMLElementOptions): void { - this.getOrCreateIfNotExists(target, options.root); + let element = this.getOrCreateIfNotExists(target); + element.root = options.root + Reflect.defineMetadata(META_KEY + ":name", options.root, target); } private static processSchema(entity: any, isAsync: boolean, schemaOptions: ISchemaOptions): any { @@ -149,7 +143,6 @@ export class XMLElement { } const element = this.getXMLElement(entity); - if (!root && element && element.root) { root = element.root; } @@ -159,12 +152,7 @@ export class XMLElement { return { root, entity }; } - hasAttribute(name: string): boolean { - if (!this.attributes) { - return false; - } - return this.attributes.filter((e) => e.getName() === name).length >= 1; - } + addAttribute(attribute: XMLAttribute): void { if (!this.attributes) this.attributes = []; this.attributes.push(attribute); diff --git a/package.json b/package.json index a815b8c..7307d18 100644 --- a/package.json +++ b/package.json @@ -22,16 +22,14 @@ "reflect-metadata": "^0.1.8" }, "dependencies": { - "@types/bluebird": "3.5.22", - "@types/lodash": "~4.14.42", "bluebird": "3.5.1", "es6-shim": "0.35.3", "js2xmlparser": "3.0.0", - "lodash": "4.17.10", "lodash.groupby": "4.6.0", "lodash.merge": "4.6.2" }, "devDependencies": { + "@types/bluebird": "3.5.33", "@types/chai": "4.1.4", "@types/mocha": "5.2.5", "chai": "4.1.2", diff --git a/test/models/Child.ts b/test/models/Child.ts index c89f0e0..5ae4571 100644 --- a/test/models/Child.ts +++ b/test/models/Child.ts @@ -1,6 +1,8 @@ import {XMLElement} from "../../lib/annotations/XMLElement"; +import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; @XMLElement({root: "child"}) export class Child { - + @XMLAttribute + Child_props = 1 } \ No newline at end of file diff --git a/test/models/ChildA.ts b/test/models/ChildA.ts index 36ffa40..a4ce4e2 100644 --- a/test/models/ChildA.ts +++ b/test/models/ChildA.ts @@ -1,6 +1,10 @@ import {XMLElement} from "../../lib/annotations/XMLElement"; -// import { Child } from "./Child"; +import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import { Child } from "./Child"; +class ChildABridge extends Child{} @XMLElement({root: "child_b"}) -export class ChildA { +export class ChildA extends ChildABridge { + @XMLAttribute + ChildA_props = 2 } diff --git a/test/models/ChildB.ts b/test/models/ChildB.ts index 38b98f0..874bbc3 100644 --- a/test/models/ChildB.ts +++ b/test/models/ChildB.ts @@ -1,6 +1,9 @@ import {XMLElement} from "../../lib/annotations/XMLElement"; - +import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import { Child } from "./Child"; +class ChildBBridge extends Child{} @XMLElement({root: "child_a"}) -export class ChildB { - +export class ChildB extends ChildBBridge{ + @XMLAttribute + ChildB_props = 3 } \ No newline at end of file diff --git a/test/specs/Person.spec.ts b/test/specs/Person.spec.ts index 9441221..8197fda 100644 --- a/test/specs/Person.spec.ts +++ b/test/specs/Person.spec.ts @@ -64,7 +64,6 @@ describe("Person", () => { }); it(`should have child hobbies named as "hobby"`, () => { - expect(schema[ns(PERSON_NS, 'hobby')]).not.to.be.undefined; expect(schema[ns(PERSON_NS, 'hobby')].length).to.equal(hobbies.length); }); @@ -118,7 +117,9 @@ describe("Person", () => { it(`should result in the same schema value as schema from sync process`, () => xml .getSchemaAsync(elisa) - .then(asyncSchema => expect(asyncSchema).to.deep.equal(schema)) + .then(asyncSchema => { + expect(asyncSchema).to.deep.equal(schema) + }) ); }); diff --git a/test/specs/virtual.spec.ts b/test/specs/virtual.spec.ts index 1c43943..2454811 100644 --- a/test/specs/virtual.spec.ts +++ b/test/specs/virtual.spec.ts @@ -8,7 +8,7 @@ import { ChildA } from "../models/ChildA"; import { ChildB } from "../models/ChildB"; @XMLElement({root: "parent"}) -class Parent extends Child{ +class Parent { @XMLChild({virtual: true}) childs: Child[] = []; } @@ -16,12 +16,12 @@ class Parent extends Child{ describe("virtual children", () => { - it(`should have attributes "firstname" and "age" with specified values`, () => { + it(`should have "child_a" and "child_b" elements`, () => { const a = new Parent(); a.childs.push(new ChildA()); a.childs.push(new ChildB()); const s = xml.serialize(a); - expect(s).contains(" Date: Tue, 4 May 2021 02:51:22 +0800 Subject: [PATCH 3/7] add object.entries shim --- lib/models/XMLChild.ts | 1 + package.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/models/XMLChild.ts b/lib/models/XMLChild.ts index bb19769..e3afdec 100644 --- a/lib/models/XMLChild.ts +++ b/lib/models/XMLChild.ts @@ -1,4 +1,5 @@ import 'es6-shim'; +import 'object.entries' import { META_KEY, XMLElement } from './XMLElement'; import * as merge from 'lodash.merge'; import { ns } from '../utils'; diff --git a/package.json b/package.json index 7307d18..f659dcf 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "es6-shim": "0.35.3", "js2xmlparser": "3.0.0", "lodash.groupby": "4.6.0", - "lodash.merge": "4.6.2" + "lodash.merge": "4.6.2", + "object.entries": "1.1.3" }, "devDependencies": { "@types/bluebird": "3.5.33", From f8e30de15041ec315d20840fbc89d7fcf0edbf9c Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 4 May 2021 02:57:05 +0800 Subject: [PATCH 4/7] o --- lib/models/XMLChild.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/models/XMLChild.ts b/lib/models/XMLChild.ts index e3afdec..3765fba 100644 --- a/lib/models/XMLChild.ts +++ b/lib/models/XMLChild.ts @@ -1,5 +1,5 @@ import 'es6-shim'; -import 'object.entries' +import * as entries from 'object.entries' import { META_KEY, XMLElement } from './XMLElement'; import * as merge from 'lodash.merge'; import { ns } from '../utils'; @@ -62,7 +62,7 @@ export class XMLChild { setSchema(target: any, parentEntity: any, isAsync: boolean = false, schemaOptions: ISchemaOptions): any { const entity = this.options.getter.call(null, parentEntity); if (this.options.virtual === true) { - Object.entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY + ":name", e))).forEach(([key, val]) => { + entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY + ":name", e))).forEach(([key, val]) => { const properties = (val as any[]).map((item) => { let next = Object.getPrototypeOf(item); let temp = null; From f383c2d4681c1c7a0464da933f916ca33876a8f9 Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 4 May 2021 04:14:22 +0800 Subject: [PATCH 5/7] remove unnecessary prototype chain manipulate --- lib/models/XMLChild.ts | 16 +--------------- lib/models/XMLElement.ts | 32 -------------------------------- package.json | 2 +- test/specs/virtual.spec.ts | 8 ++++++++ 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/lib/models/XMLChild.ts b/lib/models/XMLChild.ts index 3765fba..98a5de0 100644 --- a/lib/models/XMLChild.ts +++ b/lib/models/XMLChild.ts @@ -64,21 +64,7 @@ export class XMLChild { if (this.options.virtual === true) { entries(groupBy(entity, (e) => Reflect.getMetadata(META_KEY + ":name", e))).forEach(([key, val]) => { const properties = (val as any[]).map((item) => { - let next = Object.getPrototypeOf(item); - let temp = null; - let ele = null; - const result = {}; - while (true) { - temp = new next.constructor(); - if (typeof XMLElement.getXMLElement(temp) === 'undefined') { - break; - } - Object.assign(temp, item); - ele = XMLElement.getSchema(temp); - merge(result, ele); - next = Object.getPrototypeOf(next); - } - return result; + return XMLElement.getSchema(item); }); target[key] = properties; }); diff --git a/lib/models/XMLElement.ts b/lib/models/XMLElement.ts index b620e9a..e02f80a 100644 --- a/lib/models/XMLElement.ts +++ b/lib/models/XMLElement.ts @@ -6,7 +6,6 @@ import * as js2xmlparser from 'js2xmlparser'; import { DEFAULT_ATTRIBUTE_PROPERTY } from '../utils'; import { IXMLElementOptions } from '../interfaces/IXMLElementOptions'; import { ISchemaOptions } from '../interfaces/ISchemaOptions'; -import merge from 'lodash.merge'; const PARSER_OPTIONS = { declaration: { @@ -68,37 +67,6 @@ export class XMLElement { } static setXMLElement(target: any, ele: XMLElement): void { - let next = Object.getPrototypeOf(target); - let tempEle: XMLElement | undefined; - while (true) { - tempEle = XMLElement.getXMLElement(next); - if (typeof tempEle === 'undefined') { - break; - } - const oldAttrs = ele.attributes?.map((e) => e.getName()) || []; - const oldChilds = ele.children?.map((e) => e.getName()) || []; - - if (oldAttrs.length) { - merge(ele, { - attributes: tempEle.attributes?.filter((e) => oldAttrs.indexOf(e.getName()) === -1) || tempEle.attributes, - }); - } else { - Object.assign(ele, { - attributes: tempEle.attributes && tempEle.attributes.length ? tempEle.attributes : [], - }); - } - - if (oldChilds.length) { - merge(ele, { - children: tempEle.children?.filter((e) => oldChilds.indexOf(e.getName()) === -1) || tempEle.children, - }); - } else { - Object.assign(ele, { - children: tempEle.children && tempEle.children.length ? tempEle.children : [], - }); - } - next = Object.getPrototypeOf(next); - } return Reflect.defineMetadata(META_KEY, ele, target); } diff --git a/package.json b/package.json index f659dcf..137a3be 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Decorators for xml serialization", "main": "index.js", "scripts": { - "build": "tsc", + "build": "tsc --build tsconfig.json", "pretest": "npm run build", "test": "mocha 'test/specs/**/*.js'" }, diff --git a/test/specs/virtual.spec.ts b/test/specs/virtual.spec.ts index 2454811..ca8992f 100644 --- a/test/specs/virtual.spec.ts +++ b/test/specs/virtual.spec.ts @@ -24,4 +24,12 @@ describe("virtual children", () => { expect(s).contains(" { + const a = new Parent(); + a.childs.push(new ChildA()); + const s = xml.serialize(a); + expect(s).contains("Child_props='1'"); + expect(s).contains("ChildA_props='2'"); + }) }) From 2175dc21df68c4e7c972fffa9526d4cea40b166a Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 4 May 2021 04:42:29 +0800 Subject: [PATCH 6/7] restruct dirs --- index.ts | 15 --------------- package.json | 6 +++--- {lib => src}/annotations/XMLAttribute.ts | 0 {lib => src}/annotations/XMLChild.ts | 0 {lib => src}/annotations/XMLElement.ts | 0 src/index.ts | 15 +++++++++++++++ .../interfaces/ICustomXMLAttributeOptions.ts | 0 {lib => src}/interfaces/ICustomXMLChildOptions.ts | 0 .../interfaces/IFullXMLAttributeOptions.ts | 0 {lib => src}/interfaces/IFullXMLChildOptions.ts | 0 {lib => src}/interfaces/ISchemaOptions.ts | 0 {lib => src}/interfaces/IXMLAttributeOptions.ts | 0 {lib => src}/interfaces/IXMLChildOptions.ts | 0 {lib => src}/interfaces/IXMLElementOptions.ts | 0 {lib => src}/models/XMLAttribute.ts | 0 {lib => src}/models/XMLChild.ts | 0 {lib => src}/models/XMLElement.ts | 0 {lib => src}/utils.ts | 0 test/models/Child.ts | 4 ++-- test/models/ChildA.ts | 4 ++-- test/models/ChildB.ts | 4 ++-- test/models/Hobby.ts | 2 +- test/models/Person.ts | 6 +++--- test/specs/Person.spec.ts | 4 ++-- test/specs/virtual.spec.ts | 6 +++--- tsconfig.json | 15 +++++++-------- 26 files changed, 40 insertions(+), 41 deletions(-) delete mode 100644 index.ts rename {lib => src}/annotations/XMLAttribute.ts (100%) rename {lib => src}/annotations/XMLChild.ts (100%) rename {lib => src}/annotations/XMLElement.ts (100%) create mode 100644 src/index.ts rename {lib => src}/interfaces/ICustomXMLAttributeOptions.ts (100%) rename {lib => src}/interfaces/ICustomXMLChildOptions.ts (100%) rename {lib => src}/interfaces/IFullXMLAttributeOptions.ts (100%) rename {lib => src}/interfaces/IFullXMLChildOptions.ts (100%) rename {lib => src}/interfaces/ISchemaOptions.ts (100%) rename {lib => src}/interfaces/IXMLAttributeOptions.ts (100%) rename {lib => src}/interfaces/IXMLChildOptions.ts (100%) rename {lib => src}/interfaces/IXMLElementOptions.ts (100%) rename {lib => src}/models/XMLAttribute.ts (100%) rename {lib => src}/models/XMLChild.ts (100%) rename {lib => src}/models/XMLElement.ts (100%) rename {lib => src}/utils.ts (100%) diff --git a/index.ts b/index.ts deleted file mode 100644 index fa71e59..0000000 --- a/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export {DEFAULT_ATTRIBUTE_PROPERTY, ns} from './lib/utils'; - -export {XMLAttribute} from './lib/annotations/XMLAttribute'; -export {XMLChild} from './lib/annotations/XMLChild'; -export {XMLElement} from './lib/annotations/XMLElement'; - -export {XMLElement as xml} from './lib/models/XMLElement'; -export {XMLAttribute as xmlAttribute} from './lib/models/XMLAttribute'; -export {XMLChild as xmlChild} from './lib/models/XMLChild'; - -export {ISchemaOptions} from './lib/interfaces/ISchemaOptions'; -export {IXMLAttributeOptions} from './lib/interfaces/IXMLAttributeOptions'; -export {IXMLChildOptions} from './lib/interfaces/IXMLChildOptions'; -export {IXMLElementOptions} from './lib/interfaces/IXMLElementOptions'; - diff --git a/package.json b/package.json index 137a3be..47b1303 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,10 @@ "name": "xml-decorators", "version": "1.0.6", "description": "Decorators for xml serialization", - "main": "index.js", + "main": "lib/index.js", "scripts": { "build": "tsc --build tsconfig.json", - "pretest": "npm run build", - "test": "mocha 'test/specs/**/*.js'" + "test": "ts-mocha -p tsconfig.json 'test/specs/**/*.js'" }, "repository": { "type": "git", @@ -36,6 +35,7 @@ "chai": "4.1.2", "mocha": "5.2.0", "reflect-metadata": "^0.1.8", + "ts-mocha": "8.0.0", "tslint": "5.11.0", "typescript": "^3.9.3" } diff --git a/lib/annotations/XMLAttribute.ts b/src/annotations/XMLAttribute.ts similarity index 100% rename from lib/annotations/XMLAttribute.ts rename to src/annotations/XMLAttribute.ts diff --git a/lib/annotations/XMLChild.ts b/src/annotations/XMLChild.ts similarity index 100% rename from lib/annotations/XMLChild.ts rename to src/annotations/XMLChild.ts diff --git a/lib/annotations/XMLElement.ts b/src/annotations/XMLElement.ts similarity index 100% rename from lib/annotations/XMLElement.ts rename to src/annotations/XMLElement.ts diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..80c2689 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,15 @@ +export {DEFAULT_ATTRIBUTE_PROPERTY, ns} from './utils'; + +export {XMLAttribute} from './annotations/XMLAttribute'; +export {XMLChild} from './annotations/XMLChild'; +export {XMLElement} from './annotations/XMLElement'; + +export {XMLElement as xml} from './models/XMLElement'; +export {XMLAttribute as xmlAttribute} from './models/XMLAttribute'; +export {XMLChild as xmlChild} from './models/XMLChild'; + +export {ISchemaOptions} from './interfaces/ISchemaOptions'; +export {IXMLAttributeOptions} from './interfaces/IXMLAttributeOptions'; +export {IXMLChildOptions} from './interfaces/IXMLChildOptions'; +export {IXMLElementOptions} from './interfaces/IXMLElementOptions'; + diff --git a/lib/interfaces/ICustomXMLAttributeOptions.ts b/src/interfaces/ICustomXMLAttributeOptions.ts similarity index 100% rename from lib/interfaces/ICustomXMLAttributeOptions.ts rename to src/interfaces/ICustomXMLAttributeOptions.ts diff --git a/lib/interfaces/ICustomXMLChildOptions.ts b/src/interfaces/ICustomXMLChildOptions.ts similarity index 100% rename from lib/interfaces/ICustomXMLChildOptions.ts rename to src/interfaces/ICustomXMLChildOptions.ts diff --git a/lib/interfaces/IFullXMLAttributeOptions.ts b/src/interfaces/IFullXMLAttributeOptions.ts similarity index 100% rename from lib/interfaces/IFullXMLAttributeOptions.ts rename to src/interfaces/IFullXMLAttributeOptions.ts diff --git a/lib/interfaces/IFullXMLChildOptions.ts b/src/interfaces/IFullXMLChildOptions.ts similarity index 100% rename from lib/interfaces/IFullXMLChildOptions.ts rename to src/interfaces/IFullXMLChildOptions.ts diff --git a/lib/interfaces/ISchemaOptions.ts b/src/interfaces/ISchemaOptions.ts similarity index 100% rename from lib/interfaces/ISchemaOptions.ts rename to src/interfaces/ISchemaOptions.ts diff --git a/lib/interfaces/IXMLAttributeOptions.ts b/src/interfaces/IXMLAttributeOptions.ts similarity index 100% rename from lib/interfaces/IXMLAttributeOptions.ts rename to src/interfaces/IXMLAttributeOptions.ts diff --git a/lib/interfaces/IXMLChildOptions.ts b/src/interfaces/IXMLChildOptions.ts similarity index 100% rename from lib/interfaces/IXMLChildOptions.ts rename to src/interfaces/IXMLChildOptions.ts diff --git a/lib/interfaces/IXMLElementOptions.ts b/src/interfaces/IXMLElementOptions.ts similarity index 100% rename from lib/interfaces/IXMLElementOptions.ts rename to src/interfaces/IXMLElementOptions.ts diff --git a/lib/models/XMLAttribute.ts b/src/models/XMLAttribute.ts similarity index 100% rename from lib/models/XMLAttribute.ts rename to src/models/XMLAttribute.ts diff --git a/lib/models/XMLChild.ts b/src/models/XMLChild.ts similarity index 100% rename from lib/models/XMLChild.ts rename to src/models/XMLChild.ts diff --git a/lib/models/XMLElement.ts b/src/models/XMLElement.ts similarity index 100% rename from lib/models/XMLElement.ts rename to src/models/XMLElement.ts diff --git a/lib/utils.ts b/src/utils.ts similarity index 100% rename from lib/utils.ts rename to src/utils.ts diff --git a/test/models/Child.ts b/test/models/Child.ts index 5ae4571..d3767e7 100644 --- a/test/models/Child.ts +++ b/test/models/Child.ts @@ -1,5 +1,5 @@ -import {XMLElement} from "../../lib/annotations/XMLElement"; -import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import {XMLElement} from "../../src/annotations/XMLElement"; +import {XMLAttribute} from "../../src/annotations/XMLAttribute"; @XMLElement({root: "child"}) export class Child { diff --git a/test/models/ChildA.ts b/test/models/ChildA.ts index a4ce4e2..512f53d 100644 --- a/test/models/ChildA.ts +++ b/test/models/ChildA.ts @@ -1,6 +1,6 @@ -import {XMLElement} from "../../lib/annotations/XMLElement"; -import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import {XMLElement} from "../../src/annotations/XMLElement"; +import {XMLAttribute} from "../../src/annotations/XMLAttribute"; import { Child } from "./Child"; class ChildABridge extends Child{} @XMLElement({root: "child_b"}) diff --git a/test/models/ChildB.ts b/test/models/ChildB.ts index 874bbc3..a319e5f 100644 --- a/test/models/ChildB.ts +++ b/test/models/ChildB.ts @@ -1,5 +1,5 @@ -import {XMLElement} from "../../lib/annotations/XMLElement"; -import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import {XMLElement} from "../../src/annotations/XMLElement"; +import {XMLAttribute} from "../../src/annotations/XMLAttribute"; import { Child } from "./Child"; class ChildBBridge extends Child{} @XMLElement({root: "child_a"}) diff --git a/test/models/Hobby.ts b/test/models/Hobby.ts index f4ff95d..6ded502 100644 --- a/test/models/Hobby.ts +++ b/test/models/Hobby.ts @@ -1,4 +1,4 @@ -import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import {XMLAttribute} from "../../src/annotations/XMLAttribute"; export const HOBBY_NS = 'h'; diff --git a/test/models/Person.ts b/test/models/Person.ts index a68842e..de9d1d6 100644 --- a/test/models/Person.ts +++ b/test/models/Person.ts @@ -1,7 +1,7 @@ -import {XMLChild} from "../../lib/annotations/XMLChild"; -import {XMLElement} from "../../lib/annotations/XMLElement"; +import {XMLChild} from "../../src/annotations/XMLChild"; +import {XMLElement} from "../../src/annotations/XMLElement"; import {Hobby} from "./Hobby"; -import {XMLAttribute} from "../../lib/annotations/XMLAttribute"; +import {XMLAttribute} from "../../src/annotations/XMLAttribute"; export const PERSON_ROOT = 'person'; export const PERSON_NS = 'ps'; diff --git a/test/specs/Person.spec.ts b/test/specs/Person.spec.ts index 8197fda..25d0eac 100644 --- a/test/specs/Person.spec.ts +++ b/test/specs/Person.spec.ts @@ -2,8 +2,8 @@ import 'es6-shim'; import {expect} from 'chai'; import {Person, PERSON_NS} from "../models/Person"; import {Hobby, HOBBY_NS} from "../models/Hobby"; -import {xml, xmlAttribute, xmlChild} from "../../index"; -import {ns, DEFAULT_ATTRIBUTE_PROPERTY} from "../../lib/utils"; +import {xml, xmlAttribute, xmlChild} from "../../src/index"; +import {ns, DEFAULT_ATTRIBUTE_PROPERTY} from "../../src/utils"; const elisa = new Person('Elisa', '_', 25); const robin = new Person('Robin', 'Buschmann', 29); diff --git a/test/specs/virtual.spec.ts b/test/specs/virtual.spec.ts index ca8992f..949a6de 100644 --- a/test/specs/virtual.spec.ts +++ b/test/specs/virtual.spec.ts @@ -1,8 +1,8 @@ import {expect} from 'chai'; -import {XMLChild} from "../../lib/annotations/XMLChild"; -import { xml } from '../../'; -import {XMLElement} from "../../lib/annotations/XMLElement"; +import {XMLChild} from "../../src/annotations/XMLChild"; +import { xml } from '../../src'; +import {XMLElement} from "../../src/annotations/XMLElement"; import { Child } from "../models/Child"; import { ChildA } from "../models/ChildA"; import { ChildB } from "../models/ChildB"; diff --git a/tsconfig.json b/tsconfig.json index 4fae115..89fa4e2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,16 +10,15 @@ "strictNullChecks": true, "skipLibCheck": true, "pretty": true, + "rootDir": "./src", + "sourceRoot": "src", + "outDir": "lib", "lib": ["es2019"] }, - "include": [ - "lib/**/*", - "test/**/*" - ], - "files": [ - "index.ts" - ], + + "exclude": [ - "node_modules" + "test", + "lib" ] } From 864f099fc72ad00fa44c7345baec3807aaec2d52 Mon Sep 17 00:00:00 2001 From: bung87 Date: Tue, 4 May 2021 04:43:19 +0800 Subject: [PATCH 7/7] ts-mocha path --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47b1303..4484649 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "scripts": { "build": "tsc --build tsconfig.json", - "test": "ts-mocha -p tsconfig.json 'test/specs/**/*.js'" + "test": "ts-mocha -p tsconfig.json 'test/specs/**/*.ts'" }, "repository": { "type": "git",