UNPKG

domain-objects

Version:

A simple, convenient way to represent domain objects, leverage domain knowledge, and add runtime validation in your code base.

88 lines 4.29 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.DomainObject = exports.MARK_AS_DOMAIN_OBJECT = void 0; const getContract_1 = require("../manipulation/getContract"); const withImmute_1 = require("../manipulation/immute/withImmute"); const hydrateNestedDomainObjects_1 = require("./hydrate/hydrateNestedDomainObjects"); const markers_1 = require("./markers"); const validate_1 = require("./validate/validate"); const version_1 = require("./version"); var markers_2 = require("./markers"); Object.defineProperty(exports, "MARK_AS_DOMAIN_OBJECT", { enumerable: true, get: function () { return markers_2.MARK_AS_DOMAIN_OBJECT; } }); /** * Domain Object * * Responsibilities: * - optionally validate the properties that are passed into the constructor against the schema at runtime, if schema is supplied * - assign all properties that are passed into constructor to self, after optional runtime validation */ class DomainObject { constructor(props, options) { // 1. validate with the schema if provided const { schema } = this.constructor; // `this.constructor` does not get typed to DomainObject automatically by ts; https://stackoverflow.com/questions/33387318/access-to-static-properties-via-this-constructor-in-typescript if (schema && !(options?.skip?.schema === true)) (0, validate_1.validate)({ props, schema, domainObjectName: this.constructor.name }); // 2. hydrate any nested props present; just overwrite the orig props for each "nested" key const nested = (this.constructor.nested ?? {}); const hydratedProps = (0, hydrateNestedDomainObjects_1.hydrateNestedDomainObjects)({ domainObjectName: this.constructor.name, props, nested, }); // 3. assign all properties to self if passed validation Object.assign(this, hydratedProps); } /** * DomainObject.contract * * returns the domain object's `schema` stamped with its identity + key metadata, as an `x-domain-object` pragma. * * whereas `schema` *validates* the data, `contract` *identifies* it: the contract is the schema that knows its * own name, primary/unique keys, alias, and nested dobj names. the stamp rides through `z.toJSONSchema()` so a * cross-service consumer can name, de-dupe, and reconstruct the dobj from the wire (no re-validation needed). * * requires a `static schema` that is a `Zod` schema; throws a `ConstraintError` otherwise. * * the returned contract also carries a `.ref(by)` method: `Seaturtle.contract.ref('primary')` * returns the schema-level *reference* to this dobj by key (an `x-domain-object-ref` pragma) — * a key-only slice for a field that references another dobj rather than composes it. * * @example * z.object({ surfboard: SeaturtleSurfboard.contract }); // composes the whole dobj * z.object({ rider: Seaturtle.contract.ref('primary') }); // references it by primary key */ static get contract() { return (0, getContract_1.getContract)(this); } /** * .what = an interface via which to construct instances w/ immute operations * * .why = * - immute operations such as .clone produce more maintainable code by preventing unexpected mutations * - these immute operations provide a safe pit of success for common operations * * .note = * - you can add withImmute to any dobj yourself, even if it wasn't built via this .build procedure * - you can override the .build to add your own domain's getters, too */ static build(props, options) { const instance = new this(props, options); return (0, withImmute_1.withImmute)(instance); } } exports.DomainObject = DomainObject; _a = DomainObject, _b = markers_1.MARK_AS_DOMAIN_OBJECT; /** * DomainObject marker symbol for cross-version compatibility. * * Uses Symbol.for() to create a global symbol that works across different versions * of the domain-objects library. The value is the version string. */ DomainObject[_b] = version_1.VERSION; /** * .as = alias for .build */ DomainObject.as = _a.build; //# sourceMappingURL=DomainObject.js.map