UNPKG

@citrineos/data

Version:

The OCPP data module which includes all persistence layer implementation.

135 lines 5.48 kB
// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project // // SPDX-License-Identifier: Apache-2.0 import { CrudRepository } from '@citrineos/base'; import { QueryTypes } from 'sequelize'; import {} from 'sequelize-typescript'; import { Logger } from 'tslog'; import { DefaultSequelizeInstance } from '../util.js'; export class SequelizeRepository extends CrudRepository { s; namespace; logger; constructor(config, namespace, logger, sequelizeInstance) { super(); this.s = sequelizeInstance ?? DefaultSequelizeInstance.getInstance(config, logger); this.namespace = namespace; this.logger = logger ? logger.getSubLogger({ name: this.constructor.name }) : new Logger({ name: this.constructor.name }); } async readByKey(tenantId, key, namespace = this.namespace) { return await this.s.models[namespace].findByPk(key).then((row) => row); } async readAllByQuery(tenantId, query, namespace = this.namespace) { return await this.s.models[namespace] .findAll(query) .then((row) => row); } async readAllBySqlString(tenantId, sqlString, _namespace = this.namespace) { return await this.s.query(`${sqlString}`, { type: QueryTypes.SELECT }); } async readNextValue(tenantId, columnName, query, startValue, namespace = this.namespace) { const options = query ? query : undefined; const maxValue = await this.s.models[namespace].max(columnName, options); if (maxValue === null || maxValue === undefined) { // maxValue can be 0, so we need to specifically check for null or undefined return startValue ?? 1; } if (typeof maxValue !== 'number' || isNaN(maxValue)) { throw new Error(`Max value ${maxValue} on ${columnName} is invalid.`); } return maxValue + 1; } async existsByKey(tenantId, key, namespace = this.namespace) { return await this.s.models[namespace].findByPk(key).then((row) => row !== null); } async existByQuery(tenantId, query, namespace = this.namespace) { return await this.s.models[namespace].findAll(query).then((row) => row.length); } async findAndCount(tenantId, options, namespace = this.namespace) { return this.s.models[namespace].findAndCountAll(options); } async _create(tenantId, value, _namespace = this.namespace) { return await value.save(); } async _bulkCreate(tenantId, values, namespace = this.namespace) { return await this.s.models[namespace].bulkCreate(values); } async _createByKey(tenantId, value, key, namespace = this.namespace) { const primaryKey = this.s.models[namespace].primaryKeyAttribute; value.setDataValue(primaryKey, key); return (await this.s.models[namespace].create(value.toJSON())); } async _readOrCreateByQuery(tenantId, query, namespace = this.namespace) { return await this.s.models[namespace] .findOrCreate(query) .then((result) => [result[0], result[1]]); } async _updateByKey(tenantId, value, key, namespace = this.namespace) { const model = this.s.models[namespace]; const pk = model.primaryKeyAttribute; const { tenantId: _ignored, ...safeValue } = value; const where = { [pk]: key, tenantId, }; const row = await model.findOne({ where }); if (!row) return undefined; await row.update(safeValue); return row.reload(); } async _updateAllByQuery(tenantId, value, query, namespace = this.namespace) { const model = this.s.models[namespace]; const where = { ...query.where, tenantId, }; const rows = await model.findAll({ ...query, where, }); if (rows.length === 0) return []; for (const row of rows) { await row.update(value); } return Promise.all(rows.map((r) => r.reload())); } async _deleteByKey(tenantId, key, namespace = this.namespace) { return this.s.transaction(async (transaction) => { const entryToDelete = await this.s.models[namespace] .findByPk(key, { transaction }) .then((row) => row); if (entryToDelete) { await this.s.models[namespace].destroy({ where: { [this.s.models[namespace].primaryKeyAttribute]: key }, transaction, }); return entryToDelete; } else { return undefined; } }); } async _deleteAllByQuery(tenantId, query, namespace = this.namespace) { return this.s.transaction(async (transaction) => { const entriesToDelete = await this.s.models[namespace] .findAll({ ...query, transaction, }) .then((rows) => rows); const deletedCount = await this.s.models[namespace].destroy({ ...query, transaction }); if (entriesToDelete.length === deletedCount) { return entriesToDelete; } else { throw new Error(`Deleted ${deletedCount} entries, expected ${entriesToDelete.length}`); } }); } } //# sourceMappingURL=Base.js.map