tethys.backend/start/rules/unique.ts

60 lines
1.7 KiB
TypeScript

/*
|--------------------------------------------------------------------------
| Preloaded File - node ace make:preload rules/unique
|--------------------------------------------------------------------------
|*/
import { FieldContext } from '@vinejs/vine/types';
import db from '@adonisjs/lucid/services/db';
import vine from '@vinejs/vine';
import { VineString, VineNumber } from '@vinejs/vine';
/**
* Options accepted by the unique rule
*/
type Options = {
table: string;
column: string;
whereNot?: ((field: FieldContext) => string);
};
async function isUnique(value: unknown, options: Options, field: FieldContext) {
if (typeof value !== 'string' && typeof value != 'number') {
return;
}
let ignoreId: string | undefined;
if (options.whereNot) {
ignoreId = options.whereNot(field);
}
const builder = db.from(options.table).select(options.column).where(options.column, value);
if (ignoreId) {
builder.whereNot('id', '=', ignoreId);
}
const result = await builder.first();
if (result) {
// report that value is NOT unique
field.report('The {{ field }} field is not unique', 'isUnique', field);
}
}
export const isUniqueRule = vine.createRule(isUnique);
declare module '@vinejs/vine' {
interface VineString {
isUnique(options: Options): this;
}
interface VineNumber {
isUnique(options: Options): this;
}
}
VineString.macro('isUnique', function (this: VineString, options: Options) {
return this.use(isUniqueRule(options));
});
VineNumber.macro('isUnique', function (this: VineNumber, options: Options) {
return this.use(isUniqueRule(options));
});