@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
75 lines • 10.4 kB
JavaScript
import { DBKeys } from "./../model/constants.js";
import { getAllPropertyDecoratorsRecursive } from "./../repository/utils.js";
import { ModelKeys, sf } from "@decaf-ts/decorator-validation";
import { InternalError } from "./../repository/errors.js";
/**
* @description Finds the primary key attribute for a model
* @summary Searches in all the properties in the object for an {@link id} decorated property and returns the property key and metadata
* @param {Model} model - The model object to search for primary key
* @return {Object} An object containing the id property name and its metadata
* @function findPrimaryKey
* @mermaid
* sequenceDiagram
* participant Caller
* participant findPrimaryKey
* participant getAllPropertyDecoratorsRecursive
*
* Caller->>findPrimaryKey: model
* findPrimaryKey->>getAllPropertyDecoratorsRecursive: get decorators
* getAllPropertyDecoratorsRecursive-->>findPrimaryKey: decorators
* findPrimaryKey->>findPrimaryKey: filter ID decorators
* findPrimaryKey->>findPrimaryKey: validate single ID property
* findPrimaryKey-->>Caller: {id, props}
* @memberOf module:db-decorators
*/
export function findPrimaryKey(model) {
const decorators = getAllPropertyDecoratorsRecursive(model, undefined, DBKeys.REFLECT + DBKeys.ID);
const idDecorators = Object.entries(decorators).reduce((accum, [prop, decs]) => {
const filtered = decs.filter((d) => d.key !== ModelKeys.TYPE);
if (filtered && filtered.length) {
accum[prop] = accum[prop] || [];
accum[prop].push(...filtered);
}
return accum;
}, {});
if (!idDecorators || !Object.keys(idDecorators).length)
throw new InternalError("Could not find ID decorated Property");
if (Object.keys(idDecorators).length > 1)
throw new InternalError(sf(Object.keys(idDecorators).join(", ")));
const idProp = Object.keys(idDecorators)[0];
if (!idProp)
throw new InternalError("Could not find ID decorated Property");
return {
id: idProp,
props: idDecorators[idProp][0].props,
};
}
/**
* @description Retrieves the primary key value from a model
* @summary Searches for the ID-decorated property in the model and returns its value
* @param {Model} model - The model object to extract the ID from
* @param {boolean} [returnEmpty=false] - Whether to return undefined if no ID value is found
* @return {string | number | bigint} The primary key value
* @function findModelId
* @mermaid
* sequenceDiagram
* participant Caller
* participant findModelId
* participant findPrimaryKey
*
* Caller->>findModelId: model, returnEmpty
* findModelId->>findPrimaryKey: model
* findPrimaryKey-->>findModelId: {id, props}
* findModelId->>findModelId: extract model[id]
* findModelId->>findModelId: validate ID exists if required
* findModelId-->>Caller: ID value
* @memberOf module:db-decorators
*/
export function findModelId(model, returnEmpty = false) {
const idProp = findPrimaryKey(model).id;
const modelId = model[idProp];
if (typeof modelId === "undefined" && !returnEmpty)
throw new InternalError(`No value for the Id is defined under the property ${idProp}`);
return modelId;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaWRlbnRpdHkvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxnQ0FBMkI7QUFDNUMsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLGlDQUE0QjtBQUN4RSxPQUFPLEVBQVMsU0FBUyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxhQUFhLEVBQUUsa0NBQTZCO0FBRXJEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBa0IsS0FBUTtJQUN0RCxNQUFNLFVBQVUsR0FBRyxpQ0FBaUMsQ0FDbEQsS0FBSyxFQUNMLFNBQVMsRUFDVCxNQUFNLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQzNCLENBQUM7SUFDRixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQW9CLENBQUMsQ0FBQyxNQUFNLENBQzlELENBQUMsS0FBbUMsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3BELE1BQU0sUUFBUSxHQUFJLElBQTBCLENBQUMsTUFBTSxDQUNqRCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxTQUFTLENBQUMsSUFBSSxDQUNoQyxDQUFDO1FBQ0YsSUFBSSxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2hDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDLEVBQ0QsRUFBRSxDQUNILENBQUM7SUFFRixJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNO1FBQ3BELE1BQU0sSUFBSSxhQUFhLENBQUMsc0NBQXNDLENBQUMsQ0FBQztJQUNsRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDdEMsTUFBTSxJQUFJLGFBQWEsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsSUFBSSxDQUFDLE1BQU07UUFBRSxNQUFNLElBQUksYUFBYSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFDN0UsT0FBTztRQUNMLEVBQUUsRUFBRSxNQUFpQjtRQUNyQixLQUFLLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUs7S0FDckMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUN6QixLQUFRLEVBQ1IsV0FBVyxHQUFHLEtBQUs7SUFFbkIsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUN4QyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUIsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXLElBQUksQ0FBQyxXQUFXO1FBQ2hELE1BQU0sSUFBSSxhQUFhLENBQ3JCLHFEQUFxRCxNQUFnQixFQUFFLENBQ3hFLENBQUM7SUFDSixPQUFPLE9BQW1DLENBQUM7QUFDN0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZSB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3V0aWxzXCI7XG5pbXBvcnQgeyBNb2RlbCwgTW9kZWxLZXlzLCBzZiB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRmluZHMgdGhlIHByaW1hcnkga2V5IGF0dHJpYnV0ZSBmb3IgYSBtb2RlbFxuICogQHN1bW1hcnkgU2VhcmNoZXMgaW4gYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHRoZSBvYmplY3QgZm9yIGFuIHtAbGluayBpZH0gZGVjb3JhdGVkIHByb3BlcnR5IGFuZCByZXR1cm5zIHRoZSBwcm9wZXJ0eSBrZXkgYW5kIG1ldGFkYXRhXG4gKiBAcGFyYW0ge01vZGVsfSBtb2RlbCAtIFRoZSBtb2RlbCBvYmplY3QgdG8gc2VhcmNoIGZvciBwcmltYXJ5IGtleVxuICogQHJldHVybiB7T2JqZWN0fSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgaWQgcHJvcGVydHkgbmFtZSBhbmQgaXRzIG1ldGFkYXRhXG4gKiBAZnVuY3Rpb24gZmluZFByaW1hcnlLZXlcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRQcmltYXJ5S2V5XG4gKiAgIHBhcnRpY2lwYW50IGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZVxuICpcbiAqICAgQ2FsbGVyLT4+ZmluZFByaW1hcnlLZXk6IG1vZGVsXG4gKiAgIGZpbmRQcmltYXJ5S2V5LT4+Z2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlOiBnZXQgZGVjb3JhdG9yc1xuICogICBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUtLT4+ZmluZFByaW1hcnlLZXk6IGRlY29yYXRvcnNcbiAqICAgZmluZFByaW1hcnlLZXktPj5maW5kUHJpbWFyeUtleTogZmlsdGVyIElEIGRlY29yYXRvcnNcbiAqICAgZmluZFByaW1hcnlLZXktPj5maW5kUHJpbWFyeUtleTogdmFsaWRhdGUgc2luZ2xlIElEIHByb3BlcnR5XG4gKiAgIGZpbmRQcmltYXJ5S2V5LS0+PkNhbGxlcjoge2lkLCBwcm9wc31cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFByaW1hcnlLZXk8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSkge1xuICBjb25zdCBkZWNvcmF0b3JzID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgIG1vZGVsLFxuICAgIHVuZGVmaW5lZCxcbiAgICBEQktleXMuUkVGTEVDVCArIERCS2V5cy5JRFxuICApO1xuICBjb25zdCBpZERlY29yYXRvcnMgPSBPYmplY3QuZW50cmllcyhkZWNvcmF0b3JzIGFzIG9iamVjdCkucmVkdWNlKFxuICAgIChhY2N1bTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSwgW3Byb3AsIGRlY3NdKSA9PiB7XG4gICAgICBjb25zdCBmaWx0ZXJlZCA9IChkZWNzIGFzIHsga2V5OiBzdHJpbmcgfVtdKS5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmtleSAhPT0gTW9kZWxLZXlzLlRZUEVcbiAgICAgICk7XG4gICAgICBpZiAoZmlsdGVyZWQgJiYgZmlsdGVyZWQubGVuZ3RoKSB7XG4gICAgICAgIGFjY3VtW3Byb3BdID0gYWNjdW1bcHJvcF0gfHwgW107XG4gICAgICAgIGFjY3VtW3Byb3BdLnB1c2goLi4uZmlsdGVyZWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAge31cbiAgKTtcblxuICBpZiAoIWlkRGVjb3JhdG9ycyB8fCAhT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCBJRCBkZWNvcmF0ZWQgUHJvcGVydHlcIik7XG4gIGlmIChPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmxlbmd0aCA+IDEpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3Ioc2YoT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKS5qb2luKFwiLCBcIikpKTtcbiAgY29uc3QgaWRQcm9wID0gT2JqZWN0LmtleXMoaWREZWNvcmF0b3JzKVswXTtcbiAgaWYgKCFpZFByb3ApIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiQ291bGQgbm90IGZpbmQgSUQgZGVjb3JhdGVkIFByb3BlcnR5XCIpO1xuICByZXR1cm4ge1xuICAgIGlkOiBpZFByb3AgYXMga2V5b2YgTSxcbiAgICBwcm9wczogaWREZWNvcmF0b3JzW2lkUHJvcF1bMF0ucHJvcHMsXG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyB0aGUgcHJpbWFyeSBrZXkgdmFsdWUgZnJvbSBhIG1vZGVsXG4gKiBAc3VtbWFyeSBTZWFyY2hlcyBmb3IgdGhlIElELWRlY29yYXRlZCBwcm9wZXJ0eSBpbiB0aGUgbW9kZWwgYW5kIHJldHVybnMgaXRzIHZhbHVlXG4gKiBAcGFyYW0ge01vZGVsfSBtb2RlbCAtIFRoZSBtb2RlbCBvYmplY3QgdG8gZXh0cmFjdCB0aGUgSUQgZnJvbVxuICogQHBhcmFtIHtib29sZWFufSBbcmV0dXJuRW1wdHk9ZmFsc2VdIC0gV2hldGhlciB0byByZXR1cm4gdW5kZWZpbmVkIGlmIG5vIElEIHZhbHVlIGlzIGZvdW5kXG4gKiBAcmV0dXJuIHtzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnR9IFRoZSBwcmltYXJ5IGtleSB2YWx1ZVxuICogQGZ1bmN0aW9uIGZpbmRNb2RlbElkXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBmaW5kTW9kZWxJZFxuICogICBwYXJ0aWNpcGFudCBmaW5kUHJpbWFyeUtleVxuICpcbiAqICAgQ2FsbGVyLT4+ZmluZE1vZGVsSWQ6IG1vZGVsLCByZXR1cm5FbXB0eVxuICogICBmaW5kTW9kZWxJZC0+PmZpbmRQcmltYXJ5S2V5OiBtb2RlbFxuICogICBmaW5kUHJpbWFyeUtleS0tPj5maW5kTW9kZWxJZDoge2lkLCBwcm9wc31cbiAqICAgZmluZE1vZGVsSWQtPj5maW5kTW9kZWxJZDogZXh0cmFjdCBtb2RlbFtpZF1cbiAqICAgZmluZE1vZGVsSWQtPj5maW5kTW9kZWxJZDogdmFsaWRhdGUgSUQgZXhpc3RzIGlmIHJlcXVpcmVkXG4gKiAgIGZpbmRNb2RlbElkLS0+PkNhbGxlcjogSUQgdmFsdWVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZE1vZGVsSWQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHJldHVybkVtcHR5ID0gZmFsc2Vcbik6IHN0cmluZyB8IG51bWJlciB8IGJpZ2ludCB7XG4gIGNvbnN0IGlkUHJvcCA9IGZpbmRQcmltYXJ5S2V5KG1vZGVsKS5pZDtcbiAgY29uc3QgbW9kZWxJZCA9IG1vZGVsW2lkUHJvcF07XG4gIGlmICh0eXBlb2YgbW9kZWxJZCA9PT0gXCJ1bmRlZmluZWRcIiAmJiAhcmV0dXJuRW1wdHkpXG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke2lkUHJvcCBhcyBzdHJpbmd9YFxuICAgICk7XG4gIHJldHVybiBtb2RlbElkIGFzIHN0cmluZyB8IG51bWJlciB8IGJpZ2ludDtcbn1cbiJdfQ==