Fixed issues with query builder
This commit is contained in:
parent
a1c95a019a
commit
f04aaca29e
@ -5,7 +5,7 @@ const nextConfig: NextConfig = {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: 'https',
|
||||
hostname: 'media.bambooapp.ai',
|
||||
hostname: 'media.taylordb.ai',
|
||||
pathname: '/files/**',
|
||||
},
|
||||
{
|
||||
|
||||
@ -7,7 +7,8 @@
|
||||
"dev": "next dev --turbopack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint ."
|
||||
"lint": "eslint .",
|
||||
"regenerate:types": "npx @taylordb/cli generate-schema af483cef-ec47-48fc-b186-e11022dbb0e2 src/shared/database.types.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
@ -25,7 +26,8 @@
|
||||
"@radix-ui/react-toast": "^1.2.11",
|
||||
"@radix-ui/react-tooltip": "^1.2.6",
|
||||
"@reduxjs/toolkit": "^2.7.0",
|
||||
"@taylordb/query-builder": "^0.10.1",
|
||||
"@taylordb/cli": "^0.18.2",
|
||||
"@taylordb/query-builder": "^0.18.2",
|
||||
"aos": "^2.3.4",
|
||||
"axios": "^1.9.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
@ -87,4 +89,4 @@
|
||||
"@types/react-dom": "19.2.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
639
pnpm-lock.yaml
generated
639
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,32 +1,33 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
import { TaylorDatabase } from '@/shared/types/database.types';
|
||||
|
||||
import {
|
||||
AttachmentColumnValue,
|
||||
TableRaws,
|
||||
} from '@/shared/types/database.types';
|
||||
type TaylorColumnRaw<TColumn> = TColumn extends {
|
||||
raw: infer TRaw;
|
||||
isRequired: true;
|
||||
}
|
||||
? TRaw
|
||||
: TColumn extends { raw: infer TRaw }
|
||||
? TRaw | undefined
|
||||
: never;
|
||||
|
||||
// Helper to get image URL from Attachment array
|
||||
export const getAttachmentUrl = (
|
||||
attachments: AttachmentColumnValue[] | undefined | null,
|
||||
): string | null => {
|
||||
if (isEmpty(attachments) || !attachments?.[0]) return null;
|
||||
const attachment = attachments[0];
|
||||
return `${process.env.TAYLOR_MEDIA_URL}/${attachment.url}`;
|
||||
type TableRaws<TTableName extends keyof TaylorDatabase> = {
|
||||
[K in keyof TaylorDatabase[TTableName]]: TaylorColumnRaw<
|
||||
TaylorDatabase[TTableName][K]
|
||||
>;
|
||||
};
|
||||
|
||||
// Helper to get link select name (link to selectTable returns object with name)
|
||||
export const getLinkSelectName = (
|
||||
link: { name: string } | undefined | null,
|
||||
): string | null => {
|
||||
return link?.name || null;
|
||||
};
|
||||
const getAttachmentUrl = (urls: string[] | undefined): string | null => {
|
||||
if (!urls?.length) return null;
|
||||
|
||||
// Helper to get multiple link select names (for arrays of links)
|
||||
export const getLinkSelectNames = (
|
||||
links: Array<{ name: string }> | undefined | null,
|
||||
): string[] => {
|
||||
if (!links || isEmpty(links)) return [];
|
||||
return links.map((link) => link.name);
|
||||
const [url] = urls;
|
||||
if (!url) return null;
|
||||
|
||||
if (/^https?:\/\//.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return process.env.TAYLOR_MEDIA_URL
|
||||
? `${process.env.TAYLOR_MEDIA_URL}/${url}`
|
||||
: url;
|
||||
};
|
||||
|
||||
// Presenters for TaylorDB query builder results (direct array format, no wrapper)
|
||||
@ -53,13 +54,9 @@ export const presentJobsFromTaylor = (
|
||||
return jobs.map((job, index) => ({
|
||||
id: index + 1,
|
||||
name: job.zagolovok || '',
|
||||
// tegi is a LinkColumnType, so it returns objects when loaded with .with()
|
||||
tags: Array.isArray(job.tegi)
|
||||
? (job.tegi as Array<{ name: string }>).map((tag) => tag.name)
|
||||
: [],
|
||||
// tip and lokaciya are SingleSelectColumnType, which return arrays of strings
|
||||
location: job.lokaciya?.[0] || null,
|
||||
type: job.tip?.[0] || null,
|
||||
tags: job.tegi || [],
|
||||
location: job.lokaciya || null,
|
||||
type: job.tip || null,
|
||||
}));
|
||||
};
|
||||
|
||||
@ -108,9 +105,7 @@ export const presentStationsFromTaylor = (
|
||||
name: station.imya || '',
|
||||
description: station.opisanie || '',
|
||||
address: station.adress || '',
|
||||
// chasyRaboty and region are SingleSelectColumnType, which return arrays of strings
|
||||
workingHours: station.chasyRaboty?.[0] || null,
|
||||
// Parse string coordinates to numbers
|
||||
workingHours: station.chasyRaboty || null,
|
||||
latitude: parseFloat(station.lat || '0') || 0,
|
||||
longitude: parseFloat(station.long || '0') || 0,
|
||||
carWash: station.avtomojka || false,
|
||||
@ -122,7 +117,7 @@ export const presentStationsFromTaylor = (
|
||||
electricCharge: station.zaryadnayaStanciya || false,
|
||||
miniMarket: station.miniMarket || false,
|
||||
toilet: station.tualet || false,
|
||||
region: station.region?.[0] || null,
|
||||
region: station.region || null,
|
||||
image: getAttachmentUrl(station.foto),
|
||||
}));
|
||||
};
|
||||
|
||||
@ -30,36 +30,16 @@ export async function fetchMainPageContent(): Promise<MainPageData> {
|
||||
await taylorQueryBuilder
|
||||
.batch([
|
||||
// Fetch partners
|
||||
taylorQueryBuilder
|
||||
.selectFrom('partnyory')
|
||||
.selectAll()
|
||||
.with({
|
||||
izobrozhenie: (qb) => qb.selectAll(),
|
||||
}),
|
||||
taylorQueryBuilder.selectFrom('partnyory').selectAll(),
|
||||
|
||||
// Fetch jobs
|
||||
taylorQueryBuilder
|
||||
.selectFrom('vakansii')
|
||||
.selectAll()
|
||||
.with({
|
||||
tegi: (qb) => qb.select(['name']),
|
||||
}),
|
||||
taylorQueryBuilder.selectFrom('vakansii').selectAll(),
|
||||
|
||||
// Fetch discounts
|
||||
taylorQueryBuilder
|
||||
.selectFrom('akcii')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
}),
|
||||
taylorQueryBuilder.selectFrom('akcii').selectAll(),
|
||||
|
||||
// Fetch stations
|
||||
taylorQueryBuilder
|
||||
.selectFrom('azs')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
}),
|
||||
taylorQueryBuilder.selectFrom('azs').selectAll(),
|
||||
])
|
||||
.execute();
|
||||
|
||||
@ -82,12 +62,7 @@ export async function fetchAboutUsPageContent(): Promise<AboutUsPageData> {
|
||||
await taylorQueryBuilder
|
||||
.batch([
|
||||
// Fetch team members
|
||||
taylorQueryBuilder
|
||||
.selectFrom('komanda')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
}),
|
||||
taylorQueryBuilder.selectFrom('komanda').selectAll(),
|
||||
|
||||
// Fetch history items
|
||||
taylorQueryBuilder.selectFrom('istoriyaKompanii').selectAll(),
|
||||
@ -96,10 +71,7 @@ export async function fetchAboutUsPageContent(): Promise<AboutUsPageData> {
|
||||
taylorQueryBuilder
|
||||
.selectFrom('azs')
|
||||
.selectAll()
|
||||
.where('foto', 'isNotEmpty')
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
}),
|
||||
.where('foto', 'isNotEmpty'),
|
||||
|
||||
// Fetch reviews (filtered by published status)
|
||||
taylorQueryBuilder
|
||||
@ -126,9 +98,6 @@ export async function fetchCharityPageContent(): Promise<CharityPageData> {
|
||||
const charitiesData = await taylorQueryBuilder
|
||||
.selectFrom('blagotvoritelnyjFond')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
})
|
||||
.execute();
|
||||
|
||||
console.log('Loading charity page content...');
|
||||
@ -145,9 +114,6 @@ export async function fetchCertificatesPageContent(): Promise<CertificatesPageDa
|
||||
const certificatesData = await taylorQueryBuilder
|
||||
.selectFrom('sertifikaty')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
})
|
||||
.execute();
|
||||
|
||||
console.log('Loading certificates page content...');
|
||||
@ -182,9 +148,6 @@ export async function fetchMediaContent(): Promise<
|
||||
const mediaData = await taylorQueryBuilder
|
||||
.selectFrom('mediaKontentSajta')
|
||||
.selectAll()
|
||||
.with({
|
||||
foto: (qb) => qb.selectAll(),
|
||||
})
|
||||
.execute();
|
||||
|
||||
console.log('Loading media content...');
|
||||
|
||||
@ -4,545 +4,235 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import {
|
||||
attachmentField,
|
||||
autoDateField,
|
||||
autoNumberField,
|
||||
checkboxField,
|
||||
dateField,
|
||||
defineTaylorSchema,
|
||||
linkField,
|
||||
numberField,
|
||||
searchField,
|
||||
selectField,
|
||||
textField,
|
||||
} from '@taylordb/query-builder';
|
||||
import type { InferTaylorDatabase } from '@taylordb/query-builder';
|
||||
|
||||
interface FileInformation {
|
||||
fieldname: string;
|
||||
originalname: string;
|
||||
encoding: string;
|
||||
mimetype: string;
|
||||
destination: string;
|
||||
filename: string;
|
||||
path: string;
|
||||
size: number;
|
||||
format: string;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
export const taylorSchema = defineTaylorSchema({
|
||||
attachmentTable: {
|
||||
id: autoNumberField(),
|
||||
name: textField({ required: true }),
|
||||
metadata: textField({ required: true }),
|
||||
size: numberField({ required: true }),
|
||||
fileType: textField({ required: true }),
|
||||
url: textField({ required: true }),
|
||||
searchText: searchField(),
|
||||
},
|
||||
collaborators: {
|
||||
id: autoNumberField(),
|
||||
name: textField({ required: true }),
|
||||
emailAddress: textField({ required: true }),
|
||||
avatar: textField({ required: true }),
|
||||
searchText: searchField(),
|
||||
},
|
||||
vakansii: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
zagolovok: textField({ required: false }),
|
||||
tip: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: ['Офис', 'Заправки'] as const,
|
||||
}),
|
||||
lokaciya: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: ['Душанбе'] as const,
|
||||
}),
|
||||
tegi: selectField({
|
||||
required: false,
|
||||
mode: 'multi',
|
||||
options: ['Полный день', 'Опыт от 1 года', 'Мужчины'] as const,
|
||||
}),
|
||||
},
|
||||
partnyory: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
nazvanie: textField({ required: false }),
|
||||
tt: linkField({
|
||||
linkedTo: 'ff',
|
||||
required: false
|
||||
}),
|
||||
izobrozhenie: attachmentField({ required: false }),
|
||||
},
|
||||
azs: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
imya: textField({ required: false }),
|
||||
adress: textField({ required: false }),
|
||||
opisanie: textField({ required: false }),
|
||||
chasyRaboty: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: ['Круглосуточно'] as const,
|
||||
}),
|
||||
lat: textField({ required: false }),
|
||||
long: textField({ required: false }),
|
||||
avtomojka: checkboxField({ required: false }),
|
||||
dt: checkboxField({ required: false }),
|
||||
ai92: checkboxField({ required: false }),
|
||||
ai95: checkboxField({ required: false }),
|
||||
z100: checkboxField({ required: false }),
|
||||
propan: checkboxField({ required: false }),
|
||||
zaryadnayaStanciya: checkboxField({ required: false }),
|
||||
miniMarket: checkboxField({ required: false }),
|
||||
tualet: checkboxField({ required: false }),
|
||||
region: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: [
|
||||
'Душанбе',
|
||||
'Бохтар',
|
||||
'Худжанд',
|
||||
'Регар',
|
||||
'Вахдат',
|
||||
'А.Джоми',
|
||||
'Обикиик',
|
||||
'Кулоб',
|
||||
'Дахана',
|
||||
'Ёвон',
|
||||
'Панч',
|
||||
'Исфара',
|
||||
'Мастчох',
|
||||
'Хисор',
|
||||
] as const,
|
||||
}),
|
||||
foto: attachmentField({ required: false }),
|
||||
},
|
||||
akcii: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
zagolovok: textField({ required: false }),
|
||||
opisanie: textField({ required: false }),
|
||||
do: dateField({ required: false }),
|
||||
foto: attachmentField({ required: false }),
|
||||
},
|
||||
istoriyaKompanii: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
zagolovok: textField({ required: false }),
|
||||
god: numberField({ required: false }),
|
||||
opisanie: textField({ required: false }),
|
||||
},
|
||||
komanda: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
polnoeImya: textField({ required: false }),
|
||||
foto: attachmentField({ required: false }),
|
||||
zvanie: textField({ required: false }),
|
||||
},
|
||||
otzyvy: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
polnoeImya: textField({ required: false }),
|
||||
otzyv: textField({ required: false }),
|
||||
rejting: numberField({ required: false }),
|
||||
status: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: ['Опубликовано', 'Не публиковать'] as const,
|
||||
}),
|
||||
},
|
||||
tekstovyjKontentSajta: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
klyuchNeIzmenyat: textField({ required: true }),
|
||||
znachenie: textField({ required: true }),
|
||||
opisanie: selectField({
|
||||
required: false,
|
||||
mode: 'multi',
|
||||
options: [
|
||||
'Общая',
|
||||
'Домашняя страница',
|
||||
'О нас',
|
||||
'Благотворительность',
|
||||
'Клиенты',
|
||||
'Почты',
|
||||
'Соц сети',
|
||||
'Карты',
|
||||
'Лояльность',
|
||||
'Авторизация',
|
||||
'Сертификаты',
|
||||
'Бонусный клиент',
|
||||
'Корпоративный клиент',
|
||||
'Транзакции',
|
||||
] as const,
|
||||
}),
|
||||
},
|
||||
sertifikaty: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
nazvanie: textField({ required: false }),
|
||||
opisanie: textField({ required: false }),
|
||||
dataVydachi: dateField({ required: false }),
|
||||
dejstvitelenDo: dateField({ required: false }),
|
||||
foto: attachmentField({ required: false }),
|
||||
},
|
||||
mediaKontentSajta: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
mestopolozheniya: textField({ required: false }),
|
||||
klyuchNeIzmenyat: textField({ required: true }),
|
||||
foto: attachmentField({ required: false }),
|
||||
stranica: selectField({
|
||||
required: false,
|
||||
mode: 'single',
|
||||
options: [
|
||||
'Главная',
|
||||
'О нас',
|
||||
'Благотворительность',
|
||||
'Общая',
|
||||
'Клиенты',
|
||||
'Программа лояльности',
|
||||
] as const,
|
||||
}),
|
||||
},
|
||||
blagotvoritelnyjFond: {
|
||||
id: autoNumberField(),
|
||||
createdAt: autoDateField(),
|
||||
updatedAt: autoDateField(),
|
||||
searchText: searchField(),
|
||||
zagolovok: textField({ required: false }),
|
||||
opisanie: textField({ required: false }),
|
||||
data: dateField({ required: false }),
|
||||
lokaciya: textField({ required: false }),
|
||||
foto: attachmentField({ required: false }),
|
||||
},
|
||||
});
|
||||
|
||||
interface UploadResponse {
|
||||
collectionName: string;
|
||||
fileInformation: FileInformation;
|
||||
metadata: {
|
||||
thumbnails: any[];
|
||||
clips: any[];
|
||||
};
|
||||
baseId: string;
|
||||
storageAdaptor: string;
|
||||
_id: string;
|
||||
__v: number;
|
||||
}
|
||||
|
||||
export interface AttachmentColumnValue {
|
||||
url: string;
|
||||
fileType: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export class Attachment {
|
||||
public readonly collectionName: string;
|
||||
public readonly fileInformation: FileInformation;
|
||||
public readonly metadata: { thumbnails: any[]; clips: any[] };
|
||||
public readonly baseId: string;
|
||||
public readonly storageAdaptor: string;
|
||||
public readonly _id: string;
|
||||
|
||||
constructor(data: UploadResponse) {
|
||||
this.collectionName = data.collectionName;
|
||||
this.fileInformation = data.fileInformation;
|
||||
this.metadata = data.metadata;
|
||||
this.baseId = data.baseId;
|
||||
this.storageAdaptor = data.storageAdaptor;
|
||||
this._id = data._id;
|
||||
}
|
||||
|
||||
toColumnValue(): AttachmentColumnValue {
|
||||
return {
|
||||
url: this.fileInformation.path,
|
||||
fileType: this.fileInformation.mimetype,
|
||||
size: this.fileInformation.size,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
type IsWithinOperatorValue =
|
||||
| 'pastWeek'
|
||||
| 'pastMonth'
|
||||
| 'pastYear'
|
||||
| 'nextWeek'
|
||||
| 'nextMonth'
|
||||
| 'nextYear'
|
||||
| 'daysFromNow'
|
||||
| 'daysAgo'
|
||||
| 'currentWeek'
|
||||
| 'currentMonth'
|
||||
| 'currentYear';
|
||||
|
||||
type DefaultDateFilterValue =
|
||||
| (
|
||||
| 'today'
|
||||
| 'tomorrow'
|
||||
| 'yesterday'
|
||||
| 'oneWeekAgo'
|
||||
| 'oneWeekFromNow'
|
||||
| 'oneMonthAgo'
|
||||
| 'oneMonthFromNow'
|
||||
)
|
||||
| ['exactDay' | 'exactTimestamp', string]
|
||||
| ['daysAgo' | 'daysFromNow', number];
|
||||
|
||||
type DateFilters = {
|
||||
'=': DefaultDateFilterValue;
|
||||
'!=': DefaultDateFilterValue;
|
||||
'<': DefaultDateFilterValue;
|
||||
'>': DefaultDateFilterValue;
|
||||
'<=': DefaultDateFilterValue;
|
||||
'>=': DefaultDateFilterValue;
|
||||
isWithIn:
|
||||
| IsWithinOperatorValue
|
||||
| { value: 'daysAgo' | 'daysFromNow'; date: number };
|
||||
isEmpty: boolean;
|
||||
isNotEmpty: boolean;
|
||||
};
|
||||
|
||||
type DateAggregations = {
|
||||
empty: number;
|
||||
filled: number;
|
||||
unique: number;
|
||||
percentEmpty: number;
|
||||
percentFilled: number;
|
||||
percentUnique: number;
|
||||
min: number | null;
|
||||
max: number | null;
|
||||
daysRange: number | null;
|
||||
monthRange: number | null;
|
||||
};
|
||||
|
||||
type TextFilters = {
|
||||
'=': string;
|
||||
'!=': string;
|
||||
caseEqual: string;
|
||||
hasAnyOf: string[];
|
||||
contains: string;
|
||||
startsWith: string;
|
||||
endsWith: string;
|
||||
doesNotContain: string;
|
||||
isEmpty: never;
|
||||
isNotEmpty: never;
|
||||
};
|
||||
|
||||
type LinkFilters = {
|
||||
hasAnyOf: number[];
|
||||
hasAllOf: number[];
|
||||
isExactly: number[];
|
||||
'=': number;
|
||||
hasNoneOf: number[];
|
||||
contains: string;
|
||||
doesNotContain: string;
|
||||
isEmpty: never;
|
||||
isNotEmpty: never;
|
||||
};
|
||||
|
||||
type SelectFilters<O extends readonly string[]> = {
|
||||
hasAnyOf: O[number][];
|
||||
hasAllOf: O[number][];
|
||||
isExactly: O[number][];
|
||||
'=': O[number];
|
||||
hasNoneOf: O[number][];
|
||||
contains: string;
|
||||
doesNotContain: string;
|
||||
isEmpty: never;
|
||||
isNotEmpty: never;
|
||||
};
|
||||
|
||||
type LinkAggregations = {
|
||||
empty: number;
|
||||
filled: number;
|
||||
percentEmpty: number;
|
||||
percentFilled: number;
|
||||
};
|
||||
|
||||
type NumberFilters = {
|
||||
'=': number;
|
||||
'!=': number;
|
||||
'>': number;
|
||||
'>=': number;
|
||||
'<': number;
|
||||
'<=': number;
|
||||
hasAnyOf: number[];
|
||||
hasNoneOf: number[];
|
||||
isEmpty: never;
|
||||
isNotEmpty: never;
|
||||
};
|
||||
|
||||
type NumberAggregations = {
|
||||
sum: number;
|
||||
average: number;
|
||||
median: number;
|
||||
min: number | null;
|
||||
max: number | null;
|
||||
range: number;
|
||||
standardDeviation: number;
|
||||
histogram: Record<string, number>;
|
||||
empty: number;
|
||||
filled: number;
|
||||
unique: number;
|
||||
percentEmpty: number;
|
||||
percentFilled: number;
|
||||
percentUnique: number;
|
||||
};
|
||||
|
||||
type CheckboxFilters = {
|
||||
'=': number;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Column types
|
||||
*
|
||||
*/
|
||||
export type ColumnType<
|
||||
S,
|
||||
U,
|
||||
I,
|
||||
R extends boolean,
|
||||
F extends { [key: string]: any } = object,
|
||||
A extends { [key: string]: any } = object,
|
||||
> = {
|
||||
raw: S;
|
||||
insert: I;
|
||||
update: U;
|
||||
filters: F;
|
||||
aggregations: A;
|
||||
isRequired: R;
|
||||
};
|
||||
|
||||
export type DateColumnType<R extends boolean> = ColumnType<
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
R,
|
||||
DateFilters,
|
||||
DateAggregations
|
||||
>;
|
||||
|
||||
export type TextColumnType<R extends boolean> = ColumnType<
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
R,
|
||||
TextFilters
|
||||
>;
|
||||
|
||||
export type ALinkColumnType<
|
||||
T extends string,
|
||||
S,
|
||||
U,
|
||||
I,
|
||||
R extends boolean,
|
||||
F extends { [key: string]: any } = LinkFilters,
|
||||
A extends LinkAggregations = LinkAggregations,
|
||||
> = ColumnType<S, U, I, R, F, A> & {
|
||||
linkedTo: T;
|
||||
};
|
||||
|
||||
export type LinkColumnType<
|
||||
T extends string,
|
||||
R extends boolean,
|
||||
> = ALinkColumnType<
|
||||
T,
|
||||
object,
|
||||
number | number[] | { newIds: number[]; deletedIds: number[] },
|
||||
number | number[],
|
||||
R
|
||||
>;
|
||||
|
||||
export type AttachmentColumnType<R extends boolean> = ALinkColumnType<
|
||||
'attachmentTable',
|
||||
AttachmentColumnValue[],
|
||||
Attachment[] | { newIds: number[]; deletedIds: number[] } | number[],
|
||||
Attachment[] | number[],
|
||||
R
|
||||
>;
|
||||
|
||||
export type NumberColumnType<R extends boolean> = ColumnType<
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
R,
|
||||
NumberFilters,
|
||||
NumberAggregations
|
||||
>;
|
||||
|
||||
export type CheckboxColumnType<R extends boolean> = ColumnType<
|
||||
boolean,
|
||||
boolean,
|
||||
boolean,
|
||||
R,
|
||||
CheckboxFilters
|
||||
>;
|
||||
|
||||
export type AutoGeneratedNumberColumnType = ColumnType<
|
||||
number,
|
||||
never,
|
||||
never,
|
||||
false,
|
||||
NumberFilters,
|
||||
NumberAggregations
|
||||
>;
|
||||
|
||||
export type AutoGeneratedDateColumnType = ColumnType<
|
||||
string,
|
||||
never,
|
||||
never,
|
||||
false,
|
||||
DateFilters,
|
||||
DateAggregations
|
||||
>;
|
||||
|
||||
export type SingleSelectColumnType<
|
||||
O extends readonly string[],
|
||||
R extends boolean,
|
||||
> = ALinkColumnType<
|
||||
'selectTable',
|
||||
O[number],
|
||||
O[number] | O[number][],
|
||||
O[number] | O[number][],
|
||||
R,
|
||||
SelectFilters<O>
|
||||
>;
|
||||
|
||||
export type TableRaws<T extends keyof TaylorDatabase> = {
|
||||
[K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
|
||||
infer S,
|
||||
any,
|
||||
any,
|
||||
infer R,
|
||||
any,
|
||||
any
|
||||
>
|
||||
? R extends true
|
||||
? S
|
||||
: S | undefined
|
||||
: never;
|
||||
};
|
||||
|
||||
export type TableInserts<T extends keyof TaylorDatabase> = {
|
||||
[K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
|
||||
any,
|
||||
infer I,
|
||||
any,
|
||||
infer R,
|
||||
any,
|
||||
any
|
||||
>
|
||||
? R extends true
|
||||
? I
|
||||
: I | undefined
|
||||
: never;
|
||||
};
|
||||
|
||||
export type TableUpdates<T extends keyof TaylorDatabase> = {
|
||||
[K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
|
||||
any,
|
||||
any,
|
||||
infer U,
|
||||
any,
|
||||
any,
|
||||
any
|
||||
>
|
||||
? U
|
||||
: never;
|
||||
};
|
||||
|
||||
export type SelectTable = {
|
||||
id: AutoGeneratedNumberColumnType;
|
||||
name: TextColumnType<true>;
|
||||
color: TextColumnType<true>;
|
||||
};
|
||||
|
||||
export type AttachmentTable = {
|
||||
id: AutoGeneratedNumberColumnType;
|
||||
name: TextColumnType<true>;
|
||||
metadata: TextColumnType<true>;
|
||||
size: NumberColumnType<true>;
|
||||
fileType: TextColumnType<true>;
|
||||
url: TextColumnType<true>;
|
||||
};
|
||||
|
||||
export type CollaboratorsTable = {
|
||||
id: AutoGeneratedNumberColumnType;
|
||||
name: TextColumnType<true>;
|
||||
emailAddress: TextColumnType<true>;
|
||||
avatar: TextColumnType<true>;
|
||||
};
|
||||
|
||||
export type TaylorDatabase = {
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Internal tables, these tables can not be queried directly.
|
||||
*
|
||||
*/
|
||||
selectTable: SelectTable;
|
||||
attachmentTable: AttachmentTable;
|
||||
collaboratorsTable: CollaboratorsTable;
|
||||
vakansii: VakansiiTable;
|
||||
partnyory: PartnyoryTable;
|
||||
azs: AzsTable;
|
||||
akcii: AkciiTable;
|
||||
istoriyaKompanii: IstoriyaKompaniiTable;
|
||||
komanda: KomandaTable;
|
||||
otzyvy: OtzyvyTable;
|
||||
tekstovyjKontentSajta: TekstovyjKontentSajtaTable;
|
||||
sertifikaty: SertifikatyTable;
|
||||
mediaKontentSajta: MediaKontentSajtaTable;
|
||||
blagotvoritelnyjFond: BlagotvoritelnyjFondTable;
|
||||
};
|
||||
|
||||
export const VakansiiTipOptions = ['Офис', 'Заправки'] as const;
|
||||
export const VakansiiLokaciyaOptions = ['Душанбе'] as const;
|
||||
|
||||
type VakansiiTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
zagolovok: TextColumnType<false>;
|
||||
tip: SingleSelectColumnType<typeof VakansiiTipOptions, false>;
|
||||
lokaciya: SingleSelectColumnType<typeof VakansiiLokaciyaOptions, false>;
|
||||
tegi: LinkColumnType<'selectTable', false>;
|
||||
};
|
||||
type PartnyoryTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
nazvanie: TextColumnType<false>;
|
||||
izobrozhenie: AttachmentColumnType<false>;
|
||||
};
|
||||
|
||||
export const AzsChasyRabotyOptions = ['Круглосуточно'] as const;
|
||||
export const AzsRegionOptions = [
|
||||
'Душанбе',
|
||||
'Бохтар',
|
||||
'Худжанд',
|
||||
'Регар',
|
||||
'Вахдат',
|
||||
'А.Джоми',
|
||||
'Обикиик',
|
||||
'Кулоб',
|
||||
'Дахана',
|
||||
'Ёвон',
|
||||
'Панч',
|
||||
'Исфара',
|
||||
'Мастчох',
|
||||
'Хисор',
|
||||
] as const;
|
||||
|
||||
type AzsTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
imya: TextColumnType<false>;
|
||||
adress: TextColumnType<false>;
|
||||
opisanie: TextColumnType<false>;
|
||||
chasyRaboty: SingleSelectColumnType<typeof AzsChasyRabotyOptions, false>;
|
||||
lat: TextColumnType<false>;
|
||||
long: TextColumnType<false>;
|
||||
avtomojka: CheckboxColumnType<false>;
|
||||
dt: CheckboxColumnType<false>;
|
||||
ai92: CheckboxColumnType<false>;
|
||||
ai95: CheckboxColumnType<false>;
|
||||
z100: CheckboxColumnType<false>;
|
||||
propan: CheckboxColumnType<false>;
|
||||
zaryadnayaStanciya: CheckboxColumnType<false>;
|
||||
miniMarket: CheckboxColumnType<false>;
|
||||
tualet: CheckboxColumnType<false>;
|
||||
region: SingleSelectColumnType<typeof AzsRegionOptions, false>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
};
|
||||
type AkciiTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
zagolovok: TextColumnType<false>;
|
||||
opisanie: TextColumnType<false>;
|
||||
do: DateColumnType<false>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
};
|
||||
type IstoriyaKompaniiTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
zagolovok: TextColumnType<false>;
|
||||
god: NumberColumnType<false>;
|
||||
opisanie: TextColumnType<false>;
|
||||
};
|
||||
type KomandaTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
polnoeImya: TextColumnType<false>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
zvanie: TextColumnType<false>;
|
||||
};
|
||||
|
||||
export const OtzyvyStatusOptions = ['Опубликовано', 'Не публиковать'] as const;
|
||||
|
||||
type OtzyvyTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
polnoeImya: TextColumnType<false>;
|
||||
otzyv: TextColumnType<false>;
|
||||
rejting: NumberColumnType<false>;
|
||||
status: SingleSelectColumnType<typeof OtzyvyStatusOptions, false>;
|
||||
};
|
||||
type TekstovyjKontentSajtaTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
klyuchNeIzmenyat: TextColumnType<true>;
|
||||
znachenie: TextColumnType<true>;
|
||||
opisanie: LinkColumnType<'selectTable', false>;
|
||||
};
|
||||
type SertifikatyTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
nazvanie: TextColumnType<false>;
|
||||
opisanie: TextColumnType<false>;
|
||||
dataVydachi: DateColumnType<false>;
|
||||
dejstvitelenDo: DateColumnType<false>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
};
|
||||
|
||||
export const MediaKontentSajtaStranicaOptions = [
|
||||
'Главная',
|
||||
'О нас',
|
||||
'Благотворительность',
|
||||
'Общая',
|
||||
'Клиенты',
|
||||
'Программа лояльности',
|
||||
] as const;
|
||||
|
||||
type MediaKontentSajtaTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
mestopolozheniya: TextColumnType<false>;
|
||||
klyuchNeIzmenyat: TextColumnType<true>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
stranica: SingleSelectColumnType<
|
||||
typeof MediaKontentSajtaStranicaOptions,
|
||||
false
|
||||
>;
|
||||
};
|
||||
type BlagotvoritelnyjFondTable = {
|
||||
id: NumberColumnType<false>;
|
||||
createdAt: AutoGeneratedDateColumnType;
|
||||
updatedAt: AutoGeneratedDateColumnType;
|
||||
zagolovok: TextColumnType<false>;
|
||||
opisanie: TextColumnType<false>;
|
||||
data: DateColumnType<false>;
|
||||
lokaciya: TextColumnType<false>;
|
||||
foto: AttachmentColumnType<false>;
|
||||
/** Generic type for plugin actions */
|
||||
export type PluginActionType<I, O> = { input: I; result: O };
|
||||
export type TaylorDatabase = InferTaylorDatabase<typeof taylorSchema> & {
|
||||
_plugins: {};
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user