UNPKG

@snapdm/model

Version:

An opinionated snapshot oriented modeling system for Cloud Firestore

213 lines (199 loc) 7.12 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var preconditions = require('@snapdm/preconditions'); var __mergeWith = require('lodash/mergeWith'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var __mergeWith__default = /*#__PURE__*/_interopDefaultLegacy(__mergeWith); let __adapter; function adapter() { preconditions.assertIsDefined(__adapter, "Adapter not set. Call 'initialize' before creating models."); return __adapter; } function setAdapter(adapter2) { __adapter = adapter2; } function initialize(options) { setAdapter(options.adapter); } function isSnapshot(value) { const v = value; return typeof v.type === "string" && typeof v.id === "string" && typeof v.ref !== "undefined" && typeof v.createdAt !== "undefined" && typeof v.updatedAt !== "undefined"; } function delegate(target, delegateProperty) { return new Proxy(target, { get: (t, p) => { const prop = coerceToString(p); if (p in t) { return t[prop]; } return applyInScope(t[delegateProperty][prop], (thisArg) => thisArg === t ? t[delegateProperty] : thisArg); } }); } function applyInScope(value, scope) { if (typeof value === "function") { return new Proxy(value, { apply: (f, thisArg, args) => { return f.apply(scope(thisArg), args); } }); } return value; } function coerceToString(p) { return typeof p === "string" ? p : p.toString(); } function merge(...sources) { return __mergeWith__default["default"]({}, ...sources, (obj, val) => Array.isArray(obj) ? val : void 0); } var __defProp$1 = Object.defineProperty; var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols; var __hasOwnProp$1 = Object.prototype.hasOwnProperty; var __propIsEnum$1 = Object.prototype.propertyIsEnumerable; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$1 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); if (__getOwnPropSymbols$1) for (var prop of __getOwnPropSymbols$1(b)) { if (__propIsEnum$1.call(b, prop)) __defNormalProp$1(a, prop, b[prop]); } return a; }; function combine(validators) { return (value) => validators.reduce((res, next) => { const errors = next(value); if (errors) { return res ? __spreadValues$1(__spreadValues$1({}, res), errors) : errors; } return res; }, null); } var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); function isExtendModelOptions(value) { const v = value; return typeof v.extends === "function"; } class RootModel { constructor(initializer, options) { var _a; if (isSnapshot(initializer)) { this.isNew = (_a = options == null ? void 0 : options.isNew) != null ? _a : false; this.updates = options == null ? void 0 : options.updates; this.snapshot = initializer; } else { this.isNew = true; this.snapshot = newSnapshot(this.constructor, initializer); } return delegate(this, "snapshot"); } } function Model(options) { var _a; const { type, initialize, validators } = options; let baseClass; let collection; let parent; let validator; if (isExtendModelOptions(options)) { baseClass = options.extends; collection = options.extends.collection; parent = options.extends.parent; const extendValidator = options.extends.validator; validator = validators ? combine([...validators, extendValidator]) : extendValidator; } else { baseClass = RootModel; collection = options.collection; parent = options.parent; validator = validators ? combine(validators) : () => null; } return _a = class extends baseClass { constructor(init, options2) { super(init, options2); this.model = this.constructor; } toRef(...includeAttributes) { const { type: type2, id, ref } = this.snapshot; return includeAttributes.map((k) => [k, this.snapshot[k]]).reduce((o, [k, v]) => { o[k] = v; return o; }, { type: type2, id, ref }); } clone(updates) { if (updates === void 0 || Object.keys(updates).length === 0) { return new this.model(__spreadValues({}, this.snapshot)); } const computedUpdates = merge(this.updates, updates, { updatedAt: adapter().fieldValues.serverTimestamp() }); const newValue = merge(this.snapshot, computedUpdates); const newEntity = new this.model(newValue, { updates: computedUpdates, isNew: this.isNew }); return newEntity; } }, _a.type = type, _a.collection = collection, _a.parent = parent, _a.initialize = initialize != null ? initialize : identity, _a.validator = validator, _a; } function newSnapshot(type, init) { const resource = type.initialize(init); if (preconditions.isUndefined(resource.type)) { preconditions.assertIsDefined(type.type, "must have modelType defined"); resource.type = type.type; } if (preconditions.isUndefined(resource.id)) { resource.id = adapter().ids(); } const now = adapter().fieldValues.serverTimestamp(); return __spreadProps(__spreadValues({}, resource), { ref: adapter().references(type.collection, resource.id, resolveParentRef(type, resource)), createdAt: now, updatedAt: now }); } function resolveParentRef(type, init) { if (type.parent) { const parentRef = init[type.parent.attribute]; preconditions.assert(isModelRef(parentRef), `parent.attribute value '${String(type.parent.attribute)}' does not point to a ModelRef`); return parentRef.ref; } return void 0; } function isModelRef(value) { const v = value; return typeof v.type === "string" && typeof v.id === "string" && preconditions.isDefined(v.ref); } function identity(e) { return e; } function buildModel(factory, data) { return isModelClass(factory) ? new factory(data) : factory.factory(data); } function isModelClass(factory) { return typeof factory === "function"; } exports.Model = Model; exports.adapter = adapter; exports.buildModel = buildModel; exports.initialize = initialize; //# sourceMappingURL=index.cjs.map