UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

100 lines 11.7 kB
import { sequenceNameForModel } from "./../identity/utils.js"; import { InternalError } from "@decaf-ts/db-decorators"; import { Logging } from "@decaf-ts/logging"; /** * @description Abstract base class for sequence generation * @summary Provides a framework for generating sequential values (like primary keys) in the persistence layer. * Implementations of this class handle the specifics of how sequences are stored and incremented in different * database systems. * @param {SequenceOptions} options - Configuration options for the sequence generator * @class Sequence * @example * ```typescript * // Example implementation for a specific database * class PostgresSequence extends Sequence { * constructor(options: SequenceOptions) { * super(options); * } * * async next(): Promise<number> { * // Implementation to get next value from PostgreSQL sequence * const result = await this.options.executor.raw(`SELECT nextval('${this.options.name}')`); * return parseInt(result.rows[0].nextval); * } * * async current(): Promise<number> { * // Implementation to get current value from PostgreSQL sequence * const result = await this.options.executor.raw(`SELECT currval('${this.options.name}')`); * return parseInt(result.rows[0].currval); * } * * async range(count: number): Promise<number[]> { * // Implementation to get a range of values * const values: number[] = []; * for (let i = 0; i < count; i++) { * values.push(await this.next()); * } * return values; * } * } * * // Usage * const sequence = new PostgresSequence({ * name: 'user_id_seq', * executor: dbExecutor * }); * * const nextId = await sequence.next(); * ``` */ export class Sequence { /** * @description Accessor for the logger instance * @summary Gets or initializes the logger for this sequence * @return {Logger} The logger instance */ get log() { if (!this.logger) this.logger = Logging.for(this); return this.logger; } /** * @description Creates a new sequence instance * @summary Protected constructor that initializes the sequence with the provided options */ constructor(options) { this.options = options; } /** * @description Gets the primary key sequence name for a model * @summary Utility method that returns the standardized sequence name for a model's primary key * @template M - The model type * @param {M|Constructor<M>} model - The model instance or constructor * @return {string} The sequence name for the model's primary key */ static pk(model) { return sequenceNameForModel(model, "pk"); } /** * @description Parses a sequence value to the appropriate type * @summary Converts a sequence value to the specified type (Number or BigInt) * @param {"Number"|"BigInt"|undefined} type - The target type to convert to * @param {string|number|bigint} value - The value to convert * @return {string|number|bigint} The converted value */ static parseValue(type, value) { switch (type) { case "Number": return typeof value === "string" ? parseInt(value) : typeof value === "number" ? value : BigInt(value); case "BigInt": return BigInt(value); default: throw new InternalError("Should never happen"); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VxdWVuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGVyc2lzdGVuY2UvU2VxdWVuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLG9CQUFvQixFQUFFLCtCQUEwQjtBQUV6RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDeEQsT0FBTyxFQUFVLE9BQU8sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Q0c7QUFDSCxNQUFNLE9BQWdCLFFBQVE7SUFPNUI7Ozs7T0FJRztJQUNILElBQWMsR0FBRztRQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTTtZQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFXLENBQUMsQ0FBQztRQUN6RCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQXlDLE9BQXdCO1FBQXhCLFlBQU8sR0FBUCxPQUFPLENBQWlCO0lBQUcsQ0FBQztJQXdCckU7Ozs7OztPQU1HO0lBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBa0IsS0FBeUI7UUFDbEQsT0FBTyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQ2YsSUFBcUMsRUFDckMsS0FBK0I7UUFFL0IsUUFBUSxJQUFJLEVBQUUsQ0FBQztZQUNiLEtBQUssUUFBUTtnQkFDWCxPQUFPLE9BQU8sS0FBSyxLQUFLLFFBQVE7b0JBQzlCLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO29CQUNqQixDQUFDLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUTt3QkFDekIsQ0FBQyxDQUFDLEtBQUs7d0JBQ1AsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN0QixLQUFLLFFBQVE7Z0JBQ1gsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkI7Z0JBQ0UsTUFBTSxJQUFJLGFBQWEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ25ELENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBzZXF1ZW5jZU5hbWVGb3JNb2RlbCB9IGZyb20gXCIuLi9pZGVudGl0eS91dGlsc1wiO1xuaW1wb3J0IHsgU2VxdWVuY2VPcHRpb25zIH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvU2VxdWVuY2VPcHRpb25zXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBMb2dnZXIsIExvZ2dpbmcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3Igc2VxdWVuY2UgZ2VuZXJhdGlvblxuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBmcmFtZXdvcmsgZm9yIGdlbmVyYXRpbmcgc2VxdWVudGlhbCB2YWx1ZXMgKGxpa2UgcHJpbWFyeSBrZXlzKSBpbiB0aGUgcGVyc2lzdGVuY2UgbGF5ZXIuXG4gKiBJbXBsZW1lbnRhdGlvbnMgb2YgdGhpcyBjbGFzcyBoYW5kbGUgdGhlIHNwZWNpZmljcyBvZiBob3cgc2VxdWVuY2VzIGFyZSBzdG9yZWQgYW5kIGluY3JlbWVudGVkIGluIGRpZmZlcmVudFxuICogZGF0YWJhc2Ugc3lzdGVtcy5cbiAqIEBwYXJhbSB7U2VxdWVuY2VPcHRpb25zfSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgc2VxdWVuY2UgZ2VuZXJhdG9yXG4gKiBAY2xhc3MgU2VxdWVuY2VcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBFeGFtcGxlIGltcGxlbWVudGF0aW9uIGZvciBhIHNwZWNpZmljIGRhdGFiYXNlXG4gKiBjbGFzcyBQb3N0Z3Jlc1NlcXVlbmNlIGV4dGVuZHMgU2VxdWVuY2Uge1xuICogICBjb25zdHJ1Y3RvcihvcHRpb25zOiBTZXF1ZW5jZU9wdGlvbnMpIHtcbiAqICAgICBzdXBlcihvcHRpb25zKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgbmV4dCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uIHRvIGdldCBuZXh0IHZhbHVlIGZyb20gUG9zdGdyZVNRTCBzZXF1ZW5jZVxuICogICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMub3B0aW9ucy5leGVjdXRvci5yYXcoYFNFTEVDVCBuZXh0dmFsKCcke3RoaXMub3B0aW9ucy5uYW1lfScpYCk7XG4gKiAgICAgcmV0dXJuIHBhcnNlSW50KHJlc3VsdC5yb3dzWzBdLm5leHR2YWwpO1xuICogICB9XG4gKlxuICogICBhc3luYyBjdXJyZW50KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb24gdG8gZ2V0IGN1cnJlbnQgdmFsdWUgZnJvbSBQb3N0Z3JlU1FMIHNlcXVlbmNlXG4gKiAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5vcHRpb25zLmV4ZWN1dG9yLnJhdyhgU0VMRUNUIGN1cnJ2YWwoJyR7dGhpcy5vcHRpb25zLm5hbWV9JylgKTtcbiAqICAgICByZXR1cm4gcGFyc2VJbnQocmVzdWx0LnJvd3NbMF0uY3VycnZhbCk7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIHJhbmdlKGNvdW50OiBudW1iZXIpOiBQcm9taXNlPG51bWJlcltdPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb24gdG8gZ2V0IGEgcmFuZ2Ugb2YgdmFsdWVzXG4gKiAgICAgY29uc3QgdmFsdWVzOiBudW1iZXJbXSA9IFtdO1xuICogICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICogICAgICAgdmFsdWVzLnB1c2goYXdhaXQgdGhpcy5uZXh0KCkpO1xuICogICAgIH1cbiAqICAgICByZXR1cm4gdmFsdWVzO1xuICogICB9XG4gKiB9XG4gKlxuICogLy8gVXNhZ2VcbiAqIGNvbnN0IHNlcXVlbmNlID0gbmV3IFBvc3RncmVzU2VxdWVuY2Uoe1xuICogICBuYW1lOiAndXNlcl9pZF9zZXEnLFxuICogICBleGVjdXRvcjogZGJFeGVjdXRvclxuICogfSk7XG4gKlxuICogY29uc3QgbmV4dElkID0gYXdhaXQgc2VxdWVuY2UubmV4dCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBTZXF1ZW5jZSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9nZ2VyIGluc3RhbmNlIGZvciB0aGlzIHNlcXVlbmNlXG4gICAqIEBzdW1tYXJ5IExhemlseSBpbml0aWFsaXplZCBsb2dnZXIgZm9yIHRoZSBzZXF1ZW5jZSBpbnN0YW5jZVxuICAgKi9cbiAgcHJpdmF0ZSBsb2dnZXIhOiBMb2dnZXI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBY2Nlc3NvciBmb3IgdGhlIGxvZ2dlciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBHZXRzIG9yIGluaXRpYWxpemVzIHRoZSBsb2dnZXIgZm9yIHRoaXMgc2VxdWVuY2VcbiAgICogQHJldHVybiB7TG9nZ2VyfSBUaGUgbG9nZ2VyIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IGxvZygpIHtcbiAgICBpZiAoIXRoaXMubG9nZ2VyKSB0aGlzLmxvZ2dlciA9IExvZ2dpbmcuZm9yKHRoaXMgYXMgYW55KTtcbiAgICByZXR1cm4gdGhpcy5sb2dnZXI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgc2VxdWVuY2UgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgUHJvdGVjdGVkIGNvbnN0cnVjdG9yIHRoYXQgaW5pdGlhbGl6ZXMgdGhlIHNlcXVlbmNlIHdpdGggdGhlIHByb3ZpZGVkIG9wdGlvbnNcbiAgICovXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgb3B0aW9uczogU2VxdWVuY2VPcHRpb25zKSB7fVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgbmV4dCB2YWx1ZSBpbiB0aGUgc2VxdWVuY2VcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBuZXh0IHZhbHVlIGZyb20gdGhlIHNlcXVlbmNlLCBpbmNyZW1lbnRpbmcgaXQgaW4gdGhlIHByb2Nlc3NcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbmV4dCB2YWx1ZSBpbiB0aGUgc2VxdWVuY2VcbiAgICovXG4gIGFic3RyYWN0IG5leHQoKTogUHJvbWlzZTxzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQ+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgc2VxdWVuY2VcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBzZXF1ZW5jZSB3aXRob3V0IGluY3JlbWVudGluZyBpdFxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBjdXJyZW50IHZhbHVlIGluIHRoZSBzZXF1ZW5jZVxuICAgKi9cbiAgYWJzdHJhY3QgY3VycmVudCgpOiBQcm9taXNlPHN0cmluZyB8IG51bWJlciB8IGJpZ2ludD47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIGEgcmFuZ2Ugb2Ygc2VxdWVudGlhbCB2YWx1ZXNcbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIG11bHRpcGxlIHNlcXVlbnRpYWwgdmFsdWVzIGF0IG9uY2UsIHdoaWNoIGNhbiBiZSBtb3JlIGVmZmljaWVudCB0aGFuIGNhbGxpbmcgbmV4dCgpIG11bHRpcGxlIHRpbWVzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb3VudCAtIFRoZSBudW1iZXIgb2Ygc2VxdWVudGlhbCB2YWx1ZXMgdG8gcmV0cmlldmVcbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBzZXF1ZW50aWFsIHZhbHVlc1xuICAgKi9cbiAgYWJzdHJhY3QgcmFuZ2UoY291bnQ6IG51bWJlcik6IFByb21pc2U8KG51bWJlciB8IHN0cmluZyB8IGJpZ2ludClbXT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBwcmltYXJ5IGtleSBzZXF1ZW5jZSBuYW1lIGZvciBhIG1vZGVsXG4gICAqIEBzdW1tYXJ5IFV0aWxpdHkgbWV0aG9kIHRoYXQgcmV0dXJucyB0aGUgc3RhbmRhcmRpemVkIHNlcXVlbmNlIG5hbWUgZm9yIGEgbW9kZWwncyBwcmltYXJ5IGtleVxuICAgKiBAdGVtcGxhdGUgTSAtIFRoZSBtb2RlbCB0eXBlXG4gICAqIEBwYXJhbSB7TXxDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2Ugb3IgY29uc3RydWN0b3JcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgc2VxdWVuY2UgbmFtZSBmb3IgdGhlIG1vZGVsJ3MgcHJpbWFyeSBrZXlcbiAgICovXG4gIHN0YXRpYyBwazxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNIHwgQ29uc3RydWN0b3I8TT4pIHtcbiAgICByZXR1cm4gc2VxdWVuY2VOYW1lRm9yTW9kZWwobW9kZWwsIFwicGtcIik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhcnNlcyBhIHNlcXVlbmNlIHZhbHVlIHRvIHRoZSBhcHByb3ByaWF0ZSB0eXBlXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgc2VxdWVuY2UgdmFsdWUgdG8gdGhlIHNwZWNpZmllZCB0eXBlIChOdW1iZXIgb3IgQmlnSW50KVxuICAgKiBAcGFyYW0ge1wiTnVtYmVyXCJ8XCJCaWdJbnRcInx1bmRlZmluZWR9IHR5cGUgLSBUaGUgdGFyZ2V0IHR5cGUgdG8gY29udmVydCB0b1xuICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge3N0cmluZ3xudW1iZXJ8YmlnaW50fSBUaGUgY29udmVydGVkIHZhbHVlXG4gICAqL1xuICBzdGF0aWMgcGFyc2VWYWx1ZShcbiAgICB0eXBlOiBcIk51bWJlclwiIHwgXCJCaWdJbnRcIiB8IHVuZGVmaW5lZCxcbiAgICB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50XG4gICk6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIFwiTnVtYmVyXCI6XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICA/IHBhcnNlSW50KHZhbHVlKVxuICAgICAgICAgIDogdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiXG4gICAgICAgICAgICA/IHZhbHVlXG4gICAgICAgICAgICA6IEJpZ0ludCh2YWx1ZSk7XG4gICAgICBjYXNlIFwiQmlnSW50XCI6XG4gICAgICAgIHJldHVybiBCaWdJbnQodmFsdWUpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJTaG91bGQgbmV2ZXIgaGFwcGVuXCIpO1xuICAgIH1cbiAgfVxufVxuIl19