UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

1,191 lines (1,134 loc) 1.14 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("OpenHPS", [], factory); else if(typeof exports === 'object') exports["OpenHPS"] = factory(); else root["OpenHPS"] = root["OpenHPS"] || {}, root["OpenHPS"]["core"] = factory(); })((typeof self !== 'undefined' ? self : this), () => { return /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./dist/esm5/ModelBuilder.js": /*!***********************************!*\ !*** ./dist/esm5/ModelBuilder.js ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ModelBuilder: () => (/* binding */ ModelBuilder) /* harmony export */ }); /* harmony import */ var reflect_metadata__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! reflect-metadata */ "./node_modules/reflect-metadata/Reflect.js"); /* harmony import */ var reflect_metadata__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(reflect_metadata__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./data */ "./dist/esm5/data/object/DataObject.js"); /* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./data */ "./dist/esm5/data/object/space/ReferenceSpace.js"); /* harmony import */ var _graph_internal_implementations__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./graph/_internal/implementations */ "./dist/esm5/graph/_internal/implementations/ModelGraph.js"); /* harmony import */ var _graph_internal_implementations__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./graph/_internal/implementations */ "./dist/esm5/graph/_internal/implementations/GraphValidator.js"); /* harmony import */ var _graph_builders_GraphBuilder__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./graph/builders/GraphBuilder */ "./dist/esm5/graph/builders/GraphBuilder.js"); /* harmony import */ var _service__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./service */ "./dist/esm5/service/DataObjectService.js"); /* harmony import */ var _service__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./service */ "./dist/esm5/service/MemoryDataService.js"); /* harmony import */ var _service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./service */ "./dist/esm5/service/NodeDataService.js"); /* harmony import */ var _service__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./service */ "./dist/esm5/service/TimeService.js"); /** * Model builder to construct and build a {@link Model} consisting of graph shapes and services. * * ## Usage * Models can be created using the {@link ModelBuilder}. Once you have added all services and constructed the graph, you can build the model using the ```build()``` function. A promise will be returned with the created model. * * ```typescript * import { ModelBuilder } from '@openhps/core'; * * ModelBuilder.create() * .build().then(model => { * // ... * }); * ``` * The graph shape of a model is immutable and can not be altered after building. * * ### Shape Builder * Shapes can be created by starting with the ```from()``` function. This function takes an optional * parameter of one or multiple [source nodes](#sourcenode). * * In order to end a shape, the ```to()``` function needs to be called with one or more optional [sink nodes](#sinknode). * ```typescript * import { ModelBuilder } from '@openhps/core'; * * ModelBuilder.create() * .from() * .to() * .build().then(model => { * // ... * }); * ``` * * Alternatively for readability with multiple shapes, the shapes can individually be created using the ```addShape()``` function as shown below. * ```typescript * import { ModelBuilder, GraphBuilder } from '@openhps/core'; * * ModelBuilder.create() * .addShape( * GraphBuilder.create() * .from() * .to()) * .build().then(model => { * // ... * }); * ``` * * #### Building Source Processors * It is possible to have multiple processing nodes between the source and sink. These processing nodes can manipulate the data frame * when it traverses from node to node. * ```typescript * import { ModelBuilder } from '@openhps/core'; * * ModelBuilder.create() * .from(...) * .via(new ComputingNode()) * .via(new AnotherComputingNode()) * .to(...) * .build().then(model => { * // ... * }); * ``` * * #### Helper Functions * Helper functions can replace the ```via()``` function. Commonly used nodes such as frame filters, merging of data frames from * multiple sources, ... can be replaced with simple functions as ```filter()``` or ```merge()``` respectively. * ```typescript * import { ModelBuilder } from '@openhps/core'; * import { CSVSourceNode, CSVSinkNode } from '@openhps/csv'; * * ModelBuilder.create() * .from( * new CSVSourceNode('scanner1.csv', ...), * new CSVSourceNode('scanner2.csv', ...), * new CSVSourceNode('scanner3.csv', ...) * ) * .filter((frame: DataFrame) => true) * .merge((frame: DataFrame) => frame.source.uid) * .via(new ComputingNode()) * .via(new AnotherComputingNode()) * .to(new CSVSinkNode('output.csv', ...)) * .build().then(model => { * // ... * }); * ``` * * ### Debug Logging * When building the model, you can provide a logger callback that has two arguments. An error level complying * with normal log levels and a log object that represents an object. * ```typescript * import { ModelBuilder } from '@openhps/core'; * * ModelBuilder.create() * // Set the logger that will be used by all nodes and services * .withLogger((level: string, log: any) => { * console.log(log); * }) * // ... * .build().then(model => { * // ... * }); * ``` * * ### Adding Services * Adding services can be done using the ```addService()``` function in the model builder. * ```typescript * import { ModelBuilder } from '@openhps/core'; * * ModelBuilder.create() * .addService(...) * // ... * .build().then(model => { * * }); * ``` */ class ModelBuilder extends _graph_builders_GraphBuilder__WEBPACK_IMPORTED_MODULE_1__.GraphBuilder { constructor() { super(new _graph_internal_implementations__WEBPACK_IMPORTED_MODULE_2__.ModelGraph()); this.graph.name = 'model'; // Store data objects this.graph.addService(new _service__WEBPACK_IMPORTED_MODULE_3__.DataObjectService(new _service__WEBPACK_IMPORTED_MODULE_4__.MemoryDataService(_data__WEBPACK_IMPORTED_MODULE_5__.DataObject, { keepChangelog: false }))); // Store spaces in their own memory data object service this.graph.addService(new _service__WEBPACK_IMPORTED_MODULE_3__.DataObjectService(new _service__WEBPACK_IMPORTED_MODULE_4__.MemoryDataService(_data__WEBPACK_IMPORTED_MODULE_6__.ReferenceSpace, { keepChangelog: false }))); // Store node data this.graph.addService(new _service__WEBPACK_IMPORTED_MODULE_7__.NodeDataService(new _service__WEBPACK_IMPORTED_MODULE_4__.MemoryDataService(_service__WEBPACK_IMPORTED_MODULE_7__.NodeData, { keepChangelog: false }))); // Default time service using system time this.graph.addService(new _service__WEBPACK_IMPORTED_MODULE_8__.TimeService()); } static create() { return new ModelBuilder(); } /** * Model logger * @param {Function} logger Logging function * @returns {ModelBuilder} Model builder instance */ withLogger(logger) { this.graph.logger = logger; return this; } withReferenceSpace(space) { this.graph.referenceSpace = space; return this; } /** * Add a service to the model * @param {Service} service Service to add * @param {ProxyHandler} [proxy] Proxy handler * @returns {ModelBuilder} Model builder instance */ addService(service, proxy) { this.graph.addService(service, proxy); return this; } /** * Add multiple services to the model * @param {Service[]} services Services to add * @returns {ModelBuilder} Model builder instance */ addServices(...services) { services.forEach(service => this.addService(service)); return this; } /** * Add graph shape to graph * @param {GraphBuilder | GraphShape | Model} shape Graph builder or abstract graph * @returns {GraphBuilder} Current graph builder instance */ addShape(shape) { if (shape instanceof _graph_internal_implementations__WEBPACK_IMPORTED_MODULE_2__.ModelGraph) { // Add services shape.findAllServices().forEach(service => { this.addService(service); }); } else if (shape instanceof ModelBuilder) { shape.graph.findAllServices().forEach(service => { this.addService(service); }); } return super.addShape(shape); } build() { return new Promise((resolve, reject) => { _graph_internal_implementations__WEBPACK_IMPORTED_MODULE_9__.GraphValidator.validate(this.graph); this.graph.once('ready', () => { resolve(this.graph); }); this.graph.emitAsync('build', this).catch(ex => { // Destroy model this.graph.emit('destroy'); reject(ex); }); }); } } /***/ }), /***/ "./dist/esm5/ModelSerializer.js": /*!**************************************!*\ !*** ./dist/esm5/ModelSerializer.js ***! \**************************************/ /***/ ((module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ModelSerializer: () => (/* binding */ ModelSerializer) /* harmony export */ }); /* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./data */ "./dist/esm5/data/DataSerializer.js"); /* harmony import */ var _Node__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Node */ "./dist/esm5/Node.js"); /* harmony import */ var _service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./service */ "./dist/esm5/service/Service.js"); /** * Model serializer allows you to serialize a positioning model to JSON. */ class ModelSerializer { static get options() { return { serialize: _data__WEBPACK_IMPORTED_MODULE_0__.DataSerializer.serialize, deserialize: _data__WEBPACK_IMPORTED_MODULE_0__.DataSerializer.deserialize }; } static serialize(model) { return this.serializeNode(model); } static serializeNode(node) { this.initialize(); return this.options.serialize(node); } /** * Deserialize a model * @param model * @returns */ static deserialize(model) { const deserializedModel = this.deserializeNode(model); deserializedModel.nodes.forEach(node => { node.graph = deserializedModel; }); return deserializedModel; } /** * Deserialize a node * @param node * @returns */ static deserializeNode(node) { this.initialize(); return this.options.deserialize(node); } /** * Load all classes from the module * @param module * @returns */ static loadClasses(module = __webpack_require__.c[__webpack_require__.s]) { if (module === undefined) { // Use cache instead Object.values(__webpack_require__.c).map(m => this.loadClasses(m)); return; } this._modules.add(module.id); if (module.exports) { Object.keys(module.exports).forEach(key => { const childModule = module.exports[key]; if (childModule && childModule.prototype instanceof _Node__WEBPACK_IMPORTED_MODULE_1__.Node) { this.NODES.set(key, { constructor: childModule }); } else if (childModule && childModule.prototype instanceof _service__WEBPACK_IMPORTED_MODULE_2__.Service) { this.SERVICES.set(key, { constructor: childModule }); } }); } if (module.children) { module.children.forEach(module => { if (!this._modules.has(module.id)) { this.loadClasses(module); } }); } } /** * Initialize the serializer */ static initialize() { if (this.SERVICES.size === 0 || this.NODES.size === 0) { this.loadClasses(); this._modules.clear(); this.SERVICES.forEach(service => _data__WEBPACK_IMPORTED_MODULE_0__.DataSerializer.registerType(service.constructor)); this.NODES.forEach(node => _data__WEBPACK_IMPORTED_MODULE_0__.DataSerializer.registerType(node.constructor)); } } } ModelSerializer.NODES = new Map(); ModelSerializer.SERVICES = new Map(); ModelSerializer._modules = new Set(); /***/ }), /***/ "./dist/esm5/Node.js": /*!***************************!*\ !*** ./dist/esm5/Node.js ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Node: () => (/* binding */ Node) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var _graph_internal_GraphNode__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./graph/_internal/GraphNode */ "./dist/esm5/graph/_internal/GraphNode.js"); /* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./data */ "./dist/esm5/data/decorators/SerializableMember.js"); /* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./data */ "./dist/esm5/data/decorators/SerializableObject.js"); /** * The graph node has an input and output {@link DataFrame} * * ## Usage * * ### Creating a Node * Default nodes require you to specify the input and output data frame type. In general, nodes have the ability * to process an input data frame and output a different (processed) data frame. * ```typescript * import { DataFrame, Node } from '@openhps/core'; * * export class CustomNode<In extends DataFrame, Out extends DataFrame> extends Node<In, Out> { * // ... * } * ``` * Abstract implementations such as a {@link SourceNode} and {@link SinkNode} only take one input or output * data frame type as they do not process or change the frame. * @category Node */ let Node = class Node extends _graph_internal_GraphNode__WEBPACK_IMPORTED_MODULE_0__.GraphNode { constructor(options) { super(); this.setOptions(options || {}); // Set the uid of the node if manually set this.uid = this.options.uid || this.uid; } /** * Set the node options * @param {NodeOptions} options Node options to set * @returns {Node} Node instance */ setOptions(options) { this.options = Object.assign(Object.assign({}, options), this.options || []); // Set the display name of the node to the type name this.name = this.options.name || this.constructor.name; return this; } /** * Get the node options * @returns {NodeOptions} Node options */ getOptions() { return this.options; } /** * Graph this model is part of * @returns {Model} Positioning model */ get model() { return this.graph; } }; (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([(0,_data__WEBPACK_IMPORTED_MODULE_2__.SerializableMember)(), (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__metadata)("design:type", Object)], Node.prototype, "options", void 0); Node = (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([(0,_data__WEBPACK_IMPORTED_MODULE_3__.SerializableObject)(), (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__metadata)("design:paramtypes", [Object])], Node); /***/ }), /***/ "./dist/esm5/_internal/AsyncEventEmitter.js": /*!**************************************************!*\ !*** ./dist/esm5/_internal/AsyncEventEmitter.js ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AsyncEventEmitter: () => (/* binding */ AsyncEventEmitter) /* harmony export */ }); /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! events */ "./node_modules/events/events.js"); /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(events__WEBPACK_IMPORTED_MODULE_0__); /** * Asynchronous event emitter that adds * the function ```emitAsync()```. */ class AsyncEventEmitter extends events__WEBPACK_IMPORTED_MODULE_0__.EventEmitter { emitAsync(type, ...args) { return new Promise((resolve, reject) => { const handlers = this.listeners(type); // eslint-disable-line if (handlers.length === 0) { return resolve(false); } const promises = []; handlers.forEach(handler => { promises.push(handler(...args)); }); Promise.all(promises).then(() => { resolve(true); }).catch(reject); }); } } /***/ }), /***/ "./dist/esm5/data/DataFrame.js": /*!*************************************!*\ !*** ./dist/esm5/data/DataFrame.js ***! \*************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DataFrame: () => (/* binding */ DataFrame) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-browser/v4.js"); /* harmony import */ var _object_DataObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./object/DataObject */ "./dist/esm5/data/object/DataObject.js"); /* harmony import */ var _decorators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./decorators */ "./dist/esm5/data/decorators/SerializableMember.js"); /* harmony import */ var _decorators__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./decorators */ "./dist/esm5/data/decorators/options.js"); /* harmony import */ var _decorators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./decorators */ "./dist/esm5/data/decorators/SerializableMapMember.js"); /* harmony import */ var _decorators__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./decorators */ "./dist/esm5/data/decorators/SerializableObject.js"); /* harmony import */ var _service_TimeService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../service/TimeService */ "./dist/esm5/service/TimeService.js"); /* harmony import */ var _DataSerializer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./DataSerializer */ "./dist/esm5/data/DataSerializer.js"); var DataFrame_1; /** * A data frame is information that is passed through each node in a positioning model. * * ![DataFrame content](media://images/dataframe.svg) * * ## Usage * * ### Creation * A data frame can be created with an optional source {@link DataObject} that represents * the object responsible for generating the frame. * ```typescript * const dataFrame = new DataFrame(new DataObject("phone")); * ``` * * ### Creating a custom DataFrame * Custom data frames can be created by extending the default {@link DataFrame} class. Important when handling * data frames (and objects) is to add serializable decorators. * ```typescript * import { DataFrame, SerializableObject, SerializableArrayMember } from '@openhps/core'; * * @SerializableObject() * export class CustomDataFrame extends DataFrame { * @SerialisableArrayMember(Number) * public customFrameAttribute: number[]; * } * ``` * * ### Adding {@link DataObject}s * Adding data object will clone the data objects to the data frame. Any changes made to the object after cloning will not * be applied to the data frame. */ let DataFrame = DataFrame_1 = class DataFrame { constructor(data) { var _a; /** * Data frame unique identifier */ this.uid = (0,uuid__WEBPACK_IMPORTED_MODULE_0__["default"])(); this._objects = new Map(); this.createdTimestamp = _service_TimeService__WEBPACK_IMPORTED_MODULE_1__.TimeService.now(); if (data instanceof DataFrame_1) { // Copy data frame this.createdTimestamp = data.createdTimestamp; this.phenomenonTimestamp = data.phenomenonTimestamp; this.uid = data.uid; this._objects = data._objects; this.source = data.source; } else if (data instanceof _object_DataObject__WEBPACK_IMPORTED_MODULE_2__.DataObject) { this.source = data; } this.phenomenonTimestamp = (_a = this.phenomenonTimestamp) !== null && _a !== void 0 ? _a : this.createdTimestamp; } /** * Source object clone that captured the data frame * @returns {DataObject} Source data object */ get source() { return this.getObjectByUID(this._source); } /** * Set the source object clone that captured the data frame * @param {DataObject} object Source data object */ set source(object) { if (object === undefined) return; this.addObject(object.clone()); this._source = object.uid; } /** * Get known sensor objects used in this data frame * @param {typeof SensorObject} type Sensor type * @param {string} [defaultUID] Default UID. When sensor is not added, it will be created * @returns {SensorObject} Found data objects */ getSensor(type, defaultUID) { let sensor = this.getObjects(type)[0]; if (!sensor && defaultUID !== undefined) { sensor = new type(defaultUID); this.addObject(sensor); } return sensor; } /** * Get known objects used in this data frame * @param {typeof DataObject} dataType Data object type * @returns {DataObject[]} Array of found data objects */ getObjects(dataType) { if (dataType === undefined) { const filteredObjects = []; this._objects.forEach(object => { filteredObjects.push(object); }); return filteredObjects; } else { const filteredObjects = []; this._objects.forEach(object => { if (object.constructor.name === dataType.name) filteredObjects.push(object); }); return filteredObjects; } } /** * Get a specific object by its identifier * @param {string} uid Object UID * @returns {DataObject} Data object if found */ getObjectByUID(uid) { return this._objects.get(uid); } /** * Check if the data frame has an object * @param {DataObject} object Data object to find * @returns {boolean} Object exist */ hasObject(object) { return this._objects.has(object.uid); } /** * Add a new object relevant to this data frame * @param {DataObject} object Relevant object * @returns {DataFrame} instance */ addObject(object) { if (object === undefined) return this; this._objects.set(object.uid, object); return this; } /** * Add a new sensor relevant to this data frame * @param {SensorObject} object Relevant sensor * @returns {DataFrame} instance */ addSensor(object) { return this.addObject(object); } /** * Add a new reference space relevant to this data frame. * @alias addObject Alias for addObject * @param {ReferenceSpace} referenceSpace Relevant reference space */ addReferenceSpace(referenceSpace) { this.addObject(referenceSpace); } /** * Remove an object from the data frame * @param {DataObject | string} object Object to remove */ removeObject(object) { this._objects.delete(typeof object === 'string' ? object : object.uid); } /** * Clear all objects * @param {Function} objectFilter object filter */ clearObjects(objectFilter) { const filter = objectFilter !== null && objectFilter !== void 0 ? objectFilter : object => true; this._objects.forEach((obj, key) => { if (filter(obj)) { this._objects.delete(key); } }); } /** * Clone the data frame * @returns {DataFrame} Cloned data frame */ clone() { return _DataSerializer__WEBPACK_IMPORTED_MODULE_3__.DataSerializer.clone(this); } }; (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_5__.SerializableMember)({ primaryKey: true }), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:type", String)], DataFrame.prototype, "uid", void 0); (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_5__.SerializableMember)({ index: true, numberType: _decorators__WEBPACK_IMPORTED_MODULE_6__.NumberType.LONG }), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:type", Number)], DataFrame.prototype, "createdTimestamp", void 0); (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_5__.SerializableMember)({ index: true, numberType: _decorators__WEBPACK_IMPORTED_MODULE_6__.NumberType.LONG }), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:type", Number)], DataFrame.prototype, "phenomenonTimestamp", void 0); (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_5__.SerializableMember)({ name: 'source' }), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:type", String)], DataFrame.prototype, "_source", void 0); (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_7__.SerializableMapMember)(String, _object_DataObject__WEBPACK_IMPORTED_MODULE_2__.DataObject, { name: 'objects' }), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:type", Map)], DataFrame.prototype, "_objects", void 0); DataFrame = DataFrame_1 = (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([(0,_decorators__WEBPACK_IMPORTED_MODULE_8__.SerializableObject)(), (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__metadata)("design:paramtypes", [Object])], DataFrame); /***/ }), /***/ "./dist/esm5/data/DataSerializer.js": /*!******************************************!*\ !*** ./dist/esm5/data/DataSerializer.js ***! \******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ DataSerializer: () => (/* binding */ DataSerializer) /* harmony export */ }); /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! events */ "./node_modules/events/events.js"); /* harmony import */ var events__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(events__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/metadata.js"); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/json-object.js"); /* harmony import */ var _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./DataSerializerUtils */ "./dist/esm5/data/DataSerializerUtils.js"); /* harmony import */ var _Deserializer__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Deserializer */ "./dist/esm5/data/Deserializer.js"); /* harmony import */ var _Serializer__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Serializer */ "./dist/esm5/data/Serializer.js"); /* harmony import */ var _decorators_SerializableMember__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./decorators/SerializableMember */ "./dist/esm5/data/decorators/SerializableMember.js"); typedjson__WEBPACK_IMPORTED_MODULE_1__.JsonObjectMetadata.getFromConstructor = function (ctor) { if (!ctor) { return; } const prototype = ctor.prototype; if (prototype == null) { return; } let metadata; if (Object.prototype.hasOwnProperty.call(prototype, _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.META_FIELD)) { // The class prototype contains own jsonObject metadata metadata = prototype[_DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.META_FIELD]; } else { const parent = Object.getPrototypeOf(ctor.prototype); if (!parent) { return; } metadata = typedjson__WEBPACK_IMPORTED_MODULE_1__.JsonObjectMetadata.getFromConstructor(parent.constructor); } // Ignore implicitly added jsonObject (through jsonMember) if ((metadata === null || metadata === void 0 ? void 0 : metadata.isExplicitlyMarked) === true) { return metadata; } // In the end maybe it is something which we can handle directly if (typedjson__WEBPACK_IMPORTED_MODULE_1__.JsonObjectMetadata['doesHandleWithoutAnnotation'](ctor)) { const primitiveMeta = new typedjson__WEBPACK_IMPORTED_MODULE_1__.JsonObjectMetadata(ctor); primitiveMeta.isExplicitlyMarked = true; // we do not store the metadata here to not modify builtin prototype return primitiveMeta; } }; /** * Allows the serialization and deserialization of objects using the {@link SerializableObject} decorator. * * ## Usage * * ### Registration * Objects are registered upon loading with the {@link SerializableObject} decorator. * Manual registration is possible using: * ```typescript * DataSerializer.registerType(MyObjectClass); * ``` */ class DataSerializer { /** * Manually register a new type * @param {typeof any} type Type to register * @param {MappedTypeConverters} [converters] Optional converters */ static registerType(type, converters) { DataSerializer.knownTypes.set(type.name, type); if (converters) { // Set custom serialization strategies if (converters.serializer) { DataSerializer.serializer.setSerializationStrategy(type, value => { return converters.serializer(value, { fallback: (so, td) => DataSerializer.serializer.convertSingleValue(so, td) }); }); } if (converters.deserializer) { DataSerializer.deserializer.setDeserializationStrategy(type, value => { return converters.deserializer(value, { fallback: (so, td) => DataSerializer.deserializer.convertSingleValue(so, td, DataSerializer.knownTypes) }); }); } if (type.name !== 'Object') { // Ensure that the type has a serializable metadata _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.createMetadata(type.prototype); const options = {}; (0,typedjson__WEBPACK_IMPORTED_MODULE_3__.jsonObject)(options)(type); DataSerializer['eventEmitter'].emit('updateSerializableObject', type, options); // Merge const ownMeta = _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.getMetadata(type); const rootMeta = _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.getRootMetadata(type.prototype); _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.updateObjectMetadata(type, options, ownMeta, rootMeta); } // Register members if (converters.members) { Object.keys(converters.members).forEach(key => { const memberOptions = converters.members[key]; (0,_decorators_SerializableMember__WEBPACK_IMPORTED_MODULE_4__.SerializableMember)(memberOptions)(type.prototype, key); }); } } DataSerializer.eventEmitter.emit('registerType', type, converters); } /** * Get the TypedJSON metadata * @deprecated use {@link DataSerializerUtils.getMetadata} * @see {@link https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static getMetadata(proto) { return _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.getMetadata(proto); } /** * Get the root TypedJSON metadata * @deprecated use {@link DataSerializerUtils.getRootMetadata} * @see {@link https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static getRootMetadata(proto) { return _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.getRootMetadata(proto); } /** * Find the root TypedJSON metadata * @deprecated use {@link DataSerializerUtils.getRootMetadata} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static findRootMetaInfo(proto) { return _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.getRootMetadata(proto); } /** * Unregister a type * @param {typeof any} type Type to unregister */ static unregisterType(type) { DataSerializer.knownTypes.delete(type.name); DataSerializer.eventEmitter.emit('unregisterType', type); } static findTypeByName(name) { return DataSerializer.knownTypes.get(name); } /** * Clone a serializable object * @param {any} object Serializable object * @param {Constructor<any>} [dataType] Data type to clone to * @returns {any} Cloned object */ static clone(object, dataType) { return DataSerializer.deserialize(DataSerializer.serialize(object), dataType); } /** * Serialize data * @param {any} data Data to serialize * @param {DataSerializerConfig} [config] Data serializer configuration * @returns {any} Serialized data */ static serialize(data, config = {}) { var _a; if (data === null || data === undefined) { return undefined; } const globalDataType = Object.getPrototypeOf(data).constructor; // First check if it is a registered type // this is important as some serializable classes // may extend an array if (!DataSerializer.findTypeByName(globalDataType.name) && Array.isArray(data)) { return data.map(DataSerializer.serialize.bind(DataSerializer)); } const serializer = (_a = config.serializer) !== null && _a !== void 0 ? _a : DataSerializer.serializer; return serializer.convertSingleValue(data, _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.ensureTypeDescriptor(globalDataType), undefined, undefined, config); } static deserialize(serializedData, dataType, config = {}) { var _a; if (typeof serializedData !== 'object' && typeof serializedData !== 'function' || !serializedData) { return serializedData; } if (Array.isArray(serializedData)) { return serializedData.map(serializedObject => DataSerializer.deserialize(serializedObject)); } const deserializer = (_a = config.deserializer) !== null && _a !== void 0 ? _a : DataSerializer.deserializer; const finalType = dataType !== null && dataType !== void 0 ? dataType : deserializer.getTypeResolver()(serializedData, DataSerializer.knownTypes); return deserializer.convertSingleValue(serializedData, _DataSerializerUtils__WEBPACK_IMPORTED_MODULE_2__.DataSerializerUtils.ensureTypeDescriptor(finalType), DataSerializer.knownTypes, undefined, undefined, config); } } DataSerializer.knownTypes = new Map(); DataSerializer.serializer = new _Serializer__WEBPACK_IMPORTED_MODULE_5__.Serializer(); DataSerializer.deserializer = new _Deserializer__WEBPACK_IMPORTED_MODULE_6__.Deserializer(); /* Event emitter used to listen for registrations and unregister of data types */ DataSerializer.eventEmitter = new events__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); (() => { DataSerializer.registerType(Object, { serializer: object => Object.assign(Object.assign({}, Object.keys(object).map(key => { return { [key]: typeof object[key] === 'function' ? { function: object[key].toString(), __type: 'Function' } : DataSerializer.serialize(object[key]) }; }).reduce((a, b) => Object.assign(Object.assign({}, a), b), {})), { __type: 'Object' }), deserializer: objectJson => Object.keys(objectJson).map(key => { if (key === '__type') { return {}; } return { [key]: typeof objectJson[key] === 'object' && objectJson[key].__type === 'Function' ? eval(objectJson[key].function) : DataSerializer.deserialize(objectJson[key]) }; }).reduce((a, b) => Object.assign(Object.assign({}, a), b), {}) }); })(); /***/ }), /***/ "./dist/esm5/data/DataSerializerUtils.js": /*!***********************************************!*\ !*** ./dist/esm5/data/DataSerializerUtils.js ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ConcreteTypeDescriptor: () => (/* binding */ ConcreteTypeDescriptor), /* harmony export */ DataSerializerUtils: () => (/* binding */ DataSerializerUtils), /* harmony export */ TypeDescriptor: () => (/* binding */ TypeDescriptor) /* harmony export */ }); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/metadata.js"); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/type-descriptor.js"); /* harmony import */ var _decorators_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./decorators/utils */ "./dist/esm5/data/decorators/utils.js"); /** * Data serializer utilities for managing the ORM mapping */ class DataSerializerUtils { static get META_FIELD() { return '__typedJsonJsonObjectMetadataInformation__'; } /** * Get the own TypedJSON metadata of the prototype * @see {@link https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static getOwnMetadata(proto) { return typedjson__WEBPACK_IMPORTED_MODULE_0__.JsonObjectMetadata.getFromConstructor(proto instanceof Function ? proto : proto.constructor); } /** * Get the TypedJSON metadata * @see {@link https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static getMetadata(proto) { var _a; return (_a = DataSerializerUtils.getOwnMetadata(proto)) !== null && _a !== void 0 ? _a : DataSerializerUtils.getRootMetadata(proto); } static createMetadata(proto) { if (Object.prototype.hasOwnProperty.call(proto, this.META_FIELD)) { return proto[this.META_FIELD]; } // Target has no JsonObjectMetadata associated with it yet, create it now. const objectMetadata = new typedjson__WEBPACK_IMPORTED_MODULE_0__.JsonObjectMetadata(proto.constructor); // Inherit json members and known types from parent @jsonObject (if any). const parentMetadata = proto[this.META_FIELD]; if (parentMetadata !== undefined) { parentMetadata.dataMembers.forEach((memberMetadata, propKey) => { objectMetadata.dataMembers.set(propKey, memberMetadata); }); parentMetadata.knownTypes.forEach(knownType => { // Only add if sub type if (knownType === proto.constructor || !(knownType.prototype instanceof proto.constructor)) { return; } objectMetadata.knownTypes.add(knownType); }); // Add sub class to parent parentMetadata.knownTypes.add(objectMetadata.classType); objectMetadata.typeResolver = parentMetadata.typeResolver; objectMetadata.typeHintEmitter = parentMetadata.typeHintEmitter; } Object.defineProperty(proto, this.META_FIELD, { enumerable: false, configurable: false, writable: false, value: objectMetadata }); return objectMetadata; } /** * Get the root TypedJSON metadata * @see {@link https://gist.github.com/krizka/c83fb1966dd57997a1fc02625719387d} * @param {any} proto Prototype of target * @returns {ObjectMetadata} Root object metadata */ static getRootMetadata(proto) { const protoProto = proto instanceof Function ? proto.prototype : Object.getPrototypeOf(proto); if (!protoProto || !protoProto[DataSerializerUtils.META_FIELD]) { return proto[DataSerializerUtils.META_FIELD]; } return DataSerializerUtils.getRootMetadata(protoProto); } static ensureTypeDescriptor(type) { return type instanceof TypeDescriptor ? type : new ConcreteTypeDescriptor(type); } /** * Get member options of a property in a data type * @param {Constructor} dataType Data type * @param {string} propertyKey Property key * @returns {SerializableMemberOptions} member options */ static getMemberOptions(dataType, propertyKey) { const metadata = DataSerializerUtils.getMetadata(dataType); if (!metadata) { return undefined; } const dataMember = metadata.dataMembers.get(propertyKey); if (!dataMember) { return undefined; } return dataMember.options; } /** * Get member options of an identifier property in a data type * @param {Constructor} dataType Data type * @returns {SerializableMemberOptions} identifier member options */ static getIdentifierMemberOptions(dataType) { const metadata = DataSerializerUtils.getMetadata(dataType); if (!metadata) { return undefined; } return Array.from(metadata.dataMembers.values()).filter(member => { return member && member.primaryKey; })[0]; } /** * Deep merge member options * @param {unknown} target Target object * @param {string} propertyKey Property key in target * @param {any} options Member options * @returns {any} Merged objects */ static mergeMemberOptions(target, propertyKey, options) { if (typeof options === 'function') { return options; } const memberOptions = DataSerializerUtils.getMemberOptions(target.constructor, propertyKey); if (!memberOptions) { return options; } return mergeDeep(memberOptions, options); } static updateMemberOptions(target, propertyKey, options) { var _a, _b; const reflectPropCtor = Reflect.getMetadata('design:type', target, propertyKey); // Inject additional options if available if (options) { const ownMeta = typedjson__WEBPACK_IMPORTED_MODULE_0__.JsonObjectMetadata.ensurePresentInPrototype(target); const rootMeta = DataSerializerUtils.getRootMetadata(target.constructor); const ownMemberMetadata = ownMeta.dataMembers.get(propertyKey) || ownMeta.dataMembers.get(options.name); const rootMemberMetadata = rootMeta ? rootMeta.dataMembers.get(propertyKey) || rootMeta.dataMembers.get(options.name) : undefined; if (!ownMemberMetadata) { throw new Error(`Unable to get member metadata for ${target} on property ${propertyKey}!`); } ownMemberMetadata.options = mergeDeep((_a = ownMemberMetadata.options) !== null && _a !== void 0 ? _a : {}, options); if (rootMemberMetadata) { ownMemberMetadata.options = mergeDeep((_b = rootMemberMetadata.options) !== null && _b !== void 0 ? _b : {}, ownMemberMetadata.options); } // Merge known sub types as well rootMeta.knownTypes.forEach(otherType => { var _a, _b, _c; if (otherType === target.constructor || !(otherType.prototype instanceof target.constructor)) { return; } const otherMeta = (_a = DataSerializerUtils.getMetadata(otherType)) !== null && _a !== void 0 ? _a : typedjson__WEBPACK_IMPORTED_MODULE_0__.JsonObjectMetadata.ensurePresentInPrototype(otherType); const otherMemberMetadata = otherMeta.dataMembers.get(propertyKey) || otherMeta.dataMembers.get(options.name); if (otherMemberMetadata) { otherMemberMetadata.options = mergeDeep((_b = ownMemberMetadata.options) !== null && _b !== void 0 ? _b : {}, otherMemberMetadata.options); } else { otherMeta.dataMembers.set((_c = options.name) !== null && _c !== void 0 ? _c : propertyKey, (0,_decorators_utils__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(ownMemberMetadata)); } }); // TODO: Possibly need to sync super types as well } // Detect generic types that have no deserialization or constructor specified const meta = typedjson__WEBPACK_IMPORTED_MODULE_0__.JsonObjectMetadata.ensurePresentInPrototype(target); const existingOptions = meta.dataMembers.get(options ? options.name || propertyKey : propertyKey); if (reflectPropCtor === Object && (!options || !options.deserializer && !Object.keys(options).includes('constructor'))) { // If the type is Object and no deserializer is specified, it can be any // type of object, including serializable objects. existingOptions.type = () => typedjson__WEBPACK_IMPORTED_MODULE_2__.AnyT; } else if (existingOptions && typeof options !== 'object' && existingOptions.type() instanceof ConcreteTypeDescriptor) { existingOptions.type = () => new ConcreteTypeDescriptor(reflectPropCtor); } } static updateObjectMetadata(target, options, ownMeta, rootMeta) { var _a, _b, _c; rootMeta.knownTypes.add(target); if (rootMeta.initializerCallback && !ownMeta.initializerCallback) { ownMeta.initializerCallback = rootMeta.initializerCallback; } // Merge options if (options) { ownMeta.options = mergeDeep(ownMeta === rootMeta ? (_a = ownMeta.options) !== null && _a !== void 0 ? _a : {} : (_c = (_b = ownMeta.options) !== null && _b !== void 0 ? _b : rootMeta.options) !== null && _c !== void 0 ? _c : {}, options); // Merge known sub types as well rootMeta.knownTypes.forEach(otherType => { var _a; if (otherType === target || !(otherType.prototype instanceof target)) { return; } const otherMeta = DataSerializerUtils.getMetadata(otherType); otherMeta.options = mergeDeep((_a = ownMeta.options) !== null && _a !== void 0 ? _a : {}, otherMeta.options); if (!otherMeta.initializerCallback && ownMeta.initializerCallback) { otherMeta.initializerCallback = ownMeta.initializerCallback; } }); } // Sync settings from super types rootMeta.knownTypes.forEach(otherType => { if (otherType === target || !(target.prototype instanceof otherType)) { return; } const otherMeta = DataSerializerUtils.getMetadata(otherType); if (otherMeta && otherMeta.initializerCallback && !ownMeta.initializerCallback) { ownMeta.initializerCallback = otherMeta.initializerCallback; } }); return ownMeta; } } class TypeDescriptor { constructor(ctor) { this.ctor = ctor; } getTypes() { return [this.ctor]; } hasFriendlyName() { return this.ctor.name !== 'Object'; } } class ConcreteTypeDescriptor extends TypeDescriptor { constructor(ctor) { super(ctor); } } /** * Deep merge objects * @param {any} target Target object * @param {any} source Source object * @returns {any} Merged object */ function mergeDeep(target, source) { const output = (0,_decorators_utils__WEBPACK_IMPORTED_MODULE_1__.cloneDeep)(target); if ((0,_decorators_utils__WEBPACK_IMPORTED_MODULE_1__.isObject)(target) && (0,_decorators_utils__WEBPACK_IMPORTED_MODULE_1__.isObject)(source)) { Object.keys(source).forEach(key => { if (Array.isArray(source[key])) { output[key] = source[key]; const targetProperty = target[key] !== undefined ? Array.isArray(target[key]) ? target[key] : [target[key]] : []; output[key].push(...targetProperty.filter(val => !source[key].includes(val))); } else if ((0,_decorators_utils__WEBPACK_IMPORTED_MODULE_1__.isObject)(source[key])) { if (!(key in target)) Object.assign(output, { [key]: source[key] });else output[key] = mergeDeep(target[key], source[key]); } else { Object.assign(output, { [key]: source[key] }); } }); } return output; } /***/ }), /***/ "./dist/esm5/data/Deserializer.js": /*!****************************************!*\ !*** ./dist/esm5/data/Deserializer.js ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ Deserializer: () => (/* binding */ Deserializer) /* harmony export */ }); /* harmony import */ var typedjson_lib_esm5_deserializer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! typedjson/lib/esm5/deserializer */ "./node_modules/typedjson/lib/esm5/deserializer.js"); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/type-descriptor.js"); /* harmony import */ var typedjson__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! typedjson */ "./node_modules/typedjson/lib/esm5/metadata.js"); /* harmony import */ var typedjson_lib_esm5_options_base__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! typedjson/lib/esm5/options-base */ "./node_modules/typedjson/lib/esm5/options-base.js"); /* harmony import */ var typedjson_lib_esm5_helpers__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! typedjson/lib/esm5/helpers */ "./node_modules/typedjson/lib/esm5/helpers.js"); /* harmony import */ var _utils_BufferUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/BufferUtils */ "./dist/esm5/utils/BufferUtils.js"); class Deser