UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

151 lines 6.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pkOnCreate = pkOnCreate; exports.pkDec = pkDec; exports.pk = pk; const decorator_validation_1 = require("@decaf-ts/decorator-validation"); const SequenceOptions_1 = require("./../interfaces/SequenceOptions.cjs"); const db_decorators_1 = require("@decaf-ts/db-decorators"); const decorators_1 = require("./../model/decorators.cjs"); const constants_1 = require("./../repository/constants.cjs"); const decoration_1 = require("@decaf-ts/decoration"); const defaultPkPriority = 60; // Default priority for primary key to run latter than other properties /** * @description Callback function for primary key creation * @summary Handles the creation of primary key values for models using sequences * @template M - Type that extends Model * @template R - Type that extends Repo<M, F, C> * @template V - Type that extends SequenceOptions * @template F - Type that extends RepositoryFlags * @template C - Type that extends Context<F> * @param {Context<F>} context - The execution context * @param {V} data - The sequence options * @param key - The property key to set as primary key * @param {M} model - The model instance * @return {Promise<void>} A promise that resolves when the primary key is set * @function pkOnCreate * @category Property Decorators * @mermaid * sequenceDiagram * participant Model * participant pkOnCreate * participant Adapter * participant Sequence * * Model->>pkOnCreate: Call with model instance * Note over pkOnCreate: Check if key already exists * alt Key exists or no type specified * pkOnCreate-->>Model: Return early * else Key needs to be created * pkOnCreate->>pkOnCreate: Generate sequence name if not provided * pkOnCreate->>Adapter: Request Sequence(data) * Adapter->>Sequence: Create sequence * Sequence-->>pkOnCreate: Return sequence * pkOnCreate->>Sequence: Call next() * Sequence-->>pkOnCreate: Return next value * pkOnCreate->>Model: Set primary key value * end */ async function pkOnCreate(context, data, key, model) { if (!data.type || !data.generated || model[key]) { return; } const setPrimaryKeyValue = function (target, propertyKey, value) { Reflect.set(target, propertyKey, value); }; if (!data.name) data.name = decorator_validation_1.Model.sequenceName(model, "pk"); let sequence; try { sequence = await this.adapter.Sequence(data); } catch (e) { throw new db_decorators_1.InternalError(`Failed to instantiate Sequence ${data.name}: ${e}`); } const next = await sequence.next(context); setPrimaryKeyValue(model, key, next); } function pkDec(options, groupsort) { return function pkDec(obj, attr) { (0, decoration_1.prop)()(obj, attr); switch (options.type) { case undefined: { const metaType = decoration_1.Metadata.type(obj.constructor, attr); if (![Number.name, String.name, BigInt.name].includes(metaType?.name || metaType)) throw new Error("Incorrrect option type"); options.type = metaType; break; } case String.name || String.name.toLowerCase(): console.warn(`Deprecated "${options.type}" type in options`); // eslint-disable-next-line no-fallthrough case String: options.generated = false; options.type = String; break; case Number.name || String.name.toLowerCase(): console.warn(`Deprecated "${options.type}" type in options`); // eslint-disable-next-line no-fallthrough case Number: options.generated = true; options.type = Number; break; case BigInt.name || BigInt.name.toLowerCase(): console.warn(`Deprecated "${options.type}" type in options`); // eslint-disable-next-line no-fallthrough case BigInt: options.type = BigInt; options.generated = true; break; case "uuid": case "serial": options.generated = true; break; default: throw new Error("Unsupported type"); } if (typeof options.generated === "undefined") { options.generated = true; } const decs = [ (0, decorators_1.index)([constants_1.OrderDirection.ASC, constants_1.OrderDirection.DSC]), (0, decorator_validation_1.required)(), (0, db_decorators_1.readonly)(), (0, decoration_1.propMetadata)(decoration_1.Metadata.key(db_decorators_1.DBKeys.ID, attr), options), (0, db_decorators_1.onCreate)(pkOnCreate, options, groupsort), ]; if (options.generated) decs.push((0, decorators_1.generated)()); return (0, decoration_1.apply)(...decs)(obj, attr); }; } /** * @description Primary Key Decorator * @summary Marks a property as the model's primary key with automatic sequence generation * This decorator combines multiple behaviors: it marks the property as unique, required, * and ensures the index is created properly according to the provided sequence options. * @param {Omit<SequenceOptions, "cycle" | "startWith" | "incrementBy">} opts - Options for the sequence generation * @return {PropertyDecorator} A property decorator that can be applied to model properties * @function pk * @category Property Decorators * @example * ```typescript * class User extends BaseModel { * @pk() * id!: string; * * @required() * username!: string; * } * ``` */ function pk(opts = SequenceOptions_1.DefaultSequenceOptions) { opts = Object.assign({}, SequenceOptions_1.DefaultSequenceOptions, opts); return decoration_1.Decoration.for(db_decorators_1.DBKeys.ID) .define({ decorator: pkDec, args: [opts, { priority: defaultPkPriority }], }) .apply(); } //# sourceMappingURL=decorators.js.map