@igorchugurov/public-api-sdk 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -2
- package/dist/{client-DqqjGYgA.d.mts → client-BV5AAKYo.d.mts} +11 -0
- package/dist/{client-DqqjGYgA.d.ts → client-BV5AAKYo.d.ts} +11 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -0
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +99 -0
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +99 -0
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,6 +12,56 @@ pnpm add @igorchugurov/public-api-sdk@workspace:*
|
|
|
12
12
|
pnpm add @igorchugurov/public-api-sdk
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
## ✨ Возможности
|
|
16
|
+
|
|
17
|
+
SDK предоставляет полный набор инструментов для работы с универсальными сущностями:
|
|
18
|
+
|
|
19
|
+
### 🔄 CRUD операции
|
|
20
|
+
- **Получение списка** с расширенной фильтрацией, поиском и пагинацией
|
|
21
|
+
- **Получение одного экземпляра** с автоматической загрузкой связей и файлов
|
|
22
|
+
- **Создание** экземпляров с поддержкой relations и автоматической установкой `created_by`
|
|
23
|
+
- **Обновление** экземпляров с поддержкой частичных обновлений и relations
|
|
24
|
+
- **Удаление** экземпляров с автоматической очисткой связей
|
|
25
|
+
|
|
26
|
+
### 🔗 Работа со связями (Relations)
|
|
27
|
+
- Автоматическое определение relation-полей из конфигурации
|
|
28
|
+
- Поддержка всех типов связей: `manyToMany`, `manyToOne`, `oneToMany`, `oneToOne`
|
|
29
|
+
- Batch-загрузка связанных объектов для оптимизации производительности
|
|
30
|
+
- Фильтрация по relations с режимами `any` (OR) и `all` (AND)
|
|
31
|
+
- Опция получения relations как ID или полных объектов
|
|
32
|
+
|
|
33
|
+
### 🔍 Поиск и фильтрация
|
|
34
|
+
- **Умный поиск** по полям с флагом `searchable: true`
|
|
35
|
+
- **JSONB фильтрация** для обычных полей
|
|
36
|
+
- **Relation фильтрация** с автоматическим определением relation-полей
|
|
37
|
+
- **Гибкая сортировка** по любому полю с поддержкой `asc`/`desc`
|
|
38
|
+
|
|
39
|
+
### 📁 Работа с файлами
|
|
40
|
+
- Автоматическая загрузка файлов и изображений для полей типа `files` и `images`
|
|
41
|
+
- Batch-загрузка файлов для оптимизации запросов
|
|
42
|
+
- Поддержка множественных файлов на поле
|
|
43
|
+
|
|
44
|
+
### ⚡ Производительность
|
|
45
|
+
- **Кэширование конфигурации** EntityDefinition и Fields (TTL: 5 минут по умолчанию)
|
|
46
|
+
- **Batch-запросы** для relations и файлов
|
|
47
|
+
- **Оптимизированные RPC функции** для поиска и загрузки связей
|
|
48
|
+
- Поддержка ESM и CJS форматов
|
|
49
|
+
|
|
50
|
+
### 🎯 Типобезопасность
|
|
51
|
+
- Полная типизация всех методов и параметров
|
|
52
|
+
- Экспорт всех типов для использования в вашем коде
|
|
53
|
+
- Типизированные ошибки для удобной обработки
|
|
54
|
+
|
|
55
|
+
### 🔐 Безопасность
|
|
56
|
+
- Интеграция с Supabase RLS (Row Level Security)
|
|
57
|
+
- Автоматическая проверка прав доступа
|
|
58
|
+
- Типизированные ошибки для различных сценариев доступа
|
|
59
|
+
|
|
60
|
+
### 🎨 UI конфигурация
|
|
61
|
+
- Автоматическая генерация UI конфигурации из EntityDefinition и Fields
|
|
62
|
+
- Поддержка кастомных UI настроек
|
|
63
|
+
- Генерация конфигурации колонок таблицы из полей
|
|
64
|
+
|
|
15
65
|
## 🚀 Быстрый старт
|
|
16
66
|
|
|
17
67
|
### 1. Server Component (SSR)
|
|
@@ -112,15 +162,21 @@ const instance = await sdk.getInstance(entityDefinitionId, id, {
|
|
|
112
162
|
|
|
113
163
|
#### `createInstance(entityDefinitionId, data)`
|
|
114
164
|
|
|
115
|
-
Создать новый экземпляр.
|
|
165
|
+
Создать новый экземпляр. Автоматически генерирует уникальный `slug` из поля `name`.
|
|
116
166
|
|
|
117
167
|
```typescript
|
|
118
168
|
const instance = await sdk.createInstance(entityDefinitionId, {
|
|
119
|
-
data: Record<string, unknown>;
|
|
169
|
+
data: Record<string, unknown>; // Обязательно должно содержать поле 'name' (string)
|
|
120
170
|
relations?: Record<string, string[]>;
|
|
121
171
|
});
|
|
122
172
|
```
|
|
123
173
|
|
|
174
|
+
**Особенности:**
|
|
175
|
+
- Автоматически генерирует уникальный `slug` из поля `name`
|
|
176
|
+
- Если slug уже существует, добавляет случайный суффикс
|
|
177
|
+
- Автоматически устанавливает `created_by` из текущего пользователя
|
|
178
|
+
- Поддерживает создание relations в одном запросе
|
|
179
|
+
|
|
124
180
|
#### `updateInstance(entityDefinitionId, id, data)`
|
|
125
181
|
|
|
126
182
|
Обновить экземпляр.
|
|
@@ -159,6 +215,16 @@ const config = await sdk.getEntityDefinitionWithUIConfig(entityDefinitionId);
|
|
|
159
215
|
// config: { entityDefinition, fields, uiConfig }
|
|
160
216
|
```
|
|
161
217
|
|
|
218
|
+
#### `getAllEntityDefinitions()`
|
|
219
|
+
|
|
220
|
+
Получить все EntityDefinitions проекта с полями одним запросом (JOIN). Используется для загрузки всех сущностей в layout.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
const entityDefinitions = await sdk.getAllEntityDefinitions();
|
|
224
|
+
// Возвращает массив EntityDefinitionConfig с полями
|
|
225
|
+
// Каждый элемент содержит: { id, name, slug, fields, ... }
|
|
226
|
+
```
|
|
227
|
+
|
|
162
228
|
## 🔧 Типы
|
|
163
229
|
|
|
164
230
|
```typescript
|
|
@@ -173,6 +239,30 @@ import type {
|
|
|
173
239
|
} from '@igorchugurov/public-api-sdk';
|
|
174
240
|
```
|
|
175
241
|
|
|
242
|
+
### Slug поддержка
|
|
243
|
+
|
|
244
|
+
Все экземпляры и определения сущностей теперь содержат поле `slug`:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
// EntityInstance содержит slug
|
|
248
|
+
const instance: EntityInstanceWithFields = {
|
|
249
|
+
id: string;
|
|
250
|
+
slug: string; // URL-friendly идентификатор
|
|
251
|
+
entityDefinitionId: string;
|
|
252
|
+
// ...
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// EntityDefinition также содержит slug
|
|
256
|
+
const entityDef: EntityDefinition = {
|
|
257
|
+
id: string;
|
|
258
|
+
name: string;
|
|
259
|
+
slug: string; // URL-friendly идентификатор
|
|
260
|
+
// ...
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Slug автоматически генерируется при создании экземпляра из поля `name` и гарантирует уникальность в рамках одной EntityDefinition.
|
|
265
|
+
|
|
176
266
|
## 🛠️ Обработка ошибок
|
|
177
267
|
|
|
178
268
|
SDK использует типизированные ошибки:
|
|
@@ -109,6 +109,7 @@ type PartialUIConfig = {
|
|
|
109
109
|
interface EntityDefinition {
|
|
110
110
|
id: string;
|
|
111
111
|
name: string;
|
|
112
|
+
slug: string;
|
|
112
113
|
description?: string | null;
|
|
113
114
|
tableName: string;
|
|
114
115
|
type: "primary" | "secondary" | "tertiary";
|
|
@@ -207,6 +208,7 @@ type DbTypeToTSType = {
|
|
|
207
208
|
type EntityData<T extends Record<string, FieldValue> = Record<string, FieldValue>> = T;
|
|
208
209
|
interface EntityInstance<TData extends Record<string, FieldValue> = Record<string, FieldValue>> {
|
|
209
210
|
id: string;
|
|
211
|
+
slug: string;
|
|
210
212
|
entityDefinitionId: string;
|
|
211
213
|
projectId: string;
|
|
212
214
|
data: EntityData<TData>;
|
|
@@ -230,6 +232,7 @@ interface EntityRelation {
|
|
|
230
232
|
*/
|
|
231
233
|
type EntityInstanceWithFields<TFields extends Record<string, FieldValue> = Record<string, FieldValue>> = {
|
|
232
234
|
id: string;
|
|
235
|
+
slug: string;
|
|
233
236
|
entityDefinitionId: string;
|
|
234
237
|
projectId: string;
|
|
235
238
|
createdAt: string;
|
|
@@ -318,6 +321,7 @@ interface ProjectConfig {
|
|
|
318
321
|
interface EntityDefinitionConfig {
|
|
319
322
|
id: string;
|
|
320
323
|
name: string;
|
|
324
|
+
slug: string;
|
|
321
325
|
description?: string | null;
|
|
322
326
|
tableName: string;
|
|
323
327
|
type: "primary" | "secondary" | "tertiary";
|
|
@@ -1067,6 +1071,13 @@ declare abstract class BasePublicAPIClient {
|
|
|
1067
1071
|
* @returns EntityDefinitionConfig с полями, отсортированными по display_index
|
|
1068
1072
|
*/
|
|
1069
1073
|
getEntityDefinitionConfig(entityDefinitionId: string): Promise<EntityDefinitionConfig>;
|
|
1074
|
+
/**
|
|
1075
|
+
* Получить все EntityDefinitions проекта с полями одним запросом (JOIN)
|
|
1076
|
+
* Используется для загрузки всех сущностей в layout
|
|
1077
|
+
*
|
|
1078
|
+
* @returns Массив EntityDefinitionConfig с полями
|
|
1079
|
+
*/
|
|
1080
|
+
getAllEntityDefinitions(): Promise<EntityDefinitionConfig[]>;
|
|
1070
1081
|
/**
|
|
1071
1082
|
* Преобразование EntityDefinitionConfig в EntityDefinition
|
|
1072
1083
|
*/
|
|
@@ -109,6 +109,7 @@ type PartialUIConfig = {
|
|
|
109
109
|
interface EntityDefinition {
|
|
110
110
|
id: string;
|
|
111
111
|
name: string;
|
|
112
|
+
slug: string;
|
|
112
113
|
description?: string | null;
|
|
113
114
|
tableName: string;
|
|
114
115
|
type: "primary" | "secondary" | "tertiary";
|
|
@@ -207,6 +208,7 @@ type DbTypeToTSType = {
|
|
|
207
208
|
type EntityData<T extends Record<string, FieldValue> = Record<string, FieldValue>> = T;
|
|
208
209
|
interface EntityInstance<TData extends Record<string, FieldValue> = Record<string, FieldValue>> {
|
|
209
210
|
id: string;
|
|
211
|
+
slug: string;
|
|
210
212
|
entityDefinitionId: string;
|
|
211
213
|
projectId: string;
|
|
212
214
|
data: EntityData<TData>;
|
|
@@ -230,6 +232,7 @@ interface EntityRelation {
|
|
|
230
232
|
*/
|
|
231
233
|
type EntityInstanceWithFields<TFields extends Record<string, FieldValue> = Record<string, FieldValue>> = {
|
|
232
234
|
id: string;
|
|
235
|
+
slug: string;
|
|
233
236
|
entityDefinitionId: string;
|
|
234
237
|
projectId: string;
|
|
235
238
|
createdAt: string;
|
|
@@ -318,6 +321,7 @@ interface ProjectConfig {
|
|
|
318
321
|
interface EntityDefinitionConfig {
|
|
319
322
|
id: string;
|
|
320
323
|
name: string;
|
|
324
|
+
slug: string;
|
|
321
325
|
description?: string | null;
|
|
322
326
|
tableName: string;
|
|
323
327
|
type: "primary" | "secondary" | "tertiary";
|
|
@@ -1067,6 +1071,13 @@ declare abstract class BasePublicAPIClient {
|
|
|
1067
1071
|
* @returns EntityDefinitionConfig с полями, отсортированными по display_index
|
|
1068
1072
|
*/
|
|
1069
1073
|
getEntityDefinitionConfig(entityDefinitionId: string): Promise<EntityDefinitionConfig>;
|
|
1074
|
+
/**
|
|
1075
|
+
* Получить все EntityDefinitions проекта с полями одним запросом (JOIN)
|
|
1076
|
+
* Используется для загрузки всех сущностей в layout
|
|
1077
|
+
*
|
|
1078
|
+
* @returns Массив EntityDefinitionConfig с полями
|
|
1079
|
+
*/
|
|
1080
|
+
getAllEntityDefinitions(): Promise<EntityDefinitionConfig[]>;
|
|
1070
1081
|
/**
|
|
1071
1082
|
* Преобразование EntityDefinitionConfig в EntityDefinition
|
|
1072
1083
|
*/
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FieldConfig, a as FieldValue, E as EntityDefinition, b as Field, c as EntityUIConfig, C as ColumnConfig, S as SDKOptions, P as PublicAPIClient } from './client-
|
|
2
|
-
export { y as ActionConfig, A as AuthResult, g as CreateInstanceData, D as DbType, l as DbTypeToTSType, m as EntityData, e as EntityDefinitionConfig, x as EntityFile, n as EntityInstance, q as EntityInstanceWithFields, p as EntityRelation, k as FieldOption, j as FieldType, r as FilterValue, z as FormPageConfig, G as GetInstancesOptions, I as InstanceData, L as ListPageConfig, M as MessagesConfig, h as PaginationResult, w as PartialInstanceData, B as PartialUIConfig, d as ProjectConfig, Q as QueryParams, R as RelationFilterInfo, f as RelationFilterMode, o as RelationType, s as RelationsData, i as SignUpData, U as UpdateInstanceData, v as getFieldValue, u as isEntityData, t as isFieldValue } from './client-
|
|
1
|
+
import { F as FieldConfig, a as FieldValue, E as EntityDefinition, b as Field, c as EntityUIConfig, C as ColumnConfig, S as SDKOptions, P as PublicAPIClient } from './client-BV5AAKYo.mjs';
|
|
2
|
+
export { y as ActionConfig, A as AuthResult, g as CreateInstanceData, D as DbType, l as DbTypeToTSType, m as EntityData, e as EntityDefinitionConfig, x as EntityFile, n as EntityInstance, q as EntityInstanceWithFields, p as EntityRelation, k as FieldOption, j as FieldType, r as FilterValue, z as FormPageConfig, G as GetInstancesOptions, I as InstanceData, L as ListPageConfig, M as MessagesConfig, h as PaginationResult, w as PartialInstanceData, B as PartialUIConfig, d as ProjectConfig, Q as QueryParams, R as RelationFilterInfo, f as RelationFilterMode, o as RelationType, s as RelationsData, i as SignUpData, U as UpdateInstanceData, v as getFieldValue, u as isEntityData, t as isFieldValue } from './client-BV5AAKYo.mjs';
|
|
3
3
|
import '@supabase/supabase-js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FieldConfig, a as FieldValue, E as EntityDefinition, b as Field, c as EntityUIConfig, C as ColumnConfig, S as SDKOptions, P as PublicAPIClient } from './client-
|
|
2
|
-
export { y as ActionConfig, A as AuthResult, g as CreateInstanceData, D as DbType, l as DbTypeToTSType, m as EntityData, e as EntityDefinitionConfig, x as EntityFile, n as EntityInstance, q as EntityInstanceWithFields, p as EntityRelation, k as FieldOption, j as FieldType, r as FilterValue, z as FormPageConfig, G as GetInstancesOptions, I as InstanceData, L as ListPageConfig, M as MessagesConfig, h as PaginationResult, w as PartialInstanceData, B as PartialUIConfig, d as ProjectConfig, Q as QueryParams, R as RelationFilterInfo, f as RelationFilterMode, o as RelationType, s as RelationsData, i as SignUpData, U as UpdateInstanceData, v as getFieldValue, u as isEntityData, t as isFieldValue } from './client-
|
|
1
|
+
import { F as FieldConfig, a as FieldValue, E as EntityDefinition, b as Field, c as EntityUIConfig, C as ColumnConfig, S as SDKOptions, P as PublicAPIClient } from './client-BV5AAKYo.js';
|
|
2
|
+
export { y as ActionConfig, A as AuthResult, g as CreateInstanceData, D as DbType, l as DbTypeToTSType, m as EntityData, e as EntityDefinitionConfig, x as EntityFile, n as EntityInstance, q as EntityInstanceWithFields, p as EntityRelation, k as FieldOption, j as FieldType, r as FilterValue, z as FormPageConfig, G as GetInstancesOptions, I as InstanceData, L as ListPageConfig, M as MessagesConfig, h as PaginationResult, w as PartialInstanceData, B as PartialUIConfig, d as ProjectConfig, Q as QueryParams, R as RelationFilterInfo, f as RelationFilterMode, o as RelationType, s as RelationsData, i as SignUpData, U as UpdateInstanceData, v as getFieldValue, u as isEntityData, t as isFieldValue } from './client-BV5AAKYo.js';
|
|
3
3
|
import '@supabase/supabase-js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ var ssr = require('@supabase/ssr');
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
6
|
var __defProps = Object.defineProperties;
|
|
7
7
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
9
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
11
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -21,6 +22,50 @@ var __spreadValues = (a, b) => {
|
|
|
21
22
|
return a;
|
|
22
23
|
};
|
|
23
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __esm = (fn, res) => function __init() {
|
|
26
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
27
|
+
};
|
|
28
|
+
var __export = (target, all) => {
|
|
29
|
+
for (var name in all)
|
|
30
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/utils/slug.ts
|
|
34
|
+
var slug_exports = {};
|
|
35
|
+
__export(slug_exports, {
|
|
36
|
+
generateSlug: () => generateSlug,
|
|
37
|
+
generateUniqueSlugForInstance: () => generateUniqueSlugForInstance
|
|
38
|
+
});
|
|
39
|
+
function generateSlug(name) {
|
|
40
|
+
if (!name || typeof name !== "string") {
|
|
41
|
+
throw new Error("Name must be a non-empty string");
|
|
42
|
+
}
|
|
43
|
+
return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").substring(0, 100);
|
|
44
|
+
}
|
|
45
|
+
function generateRandomSuffix() {
|
|
46
|
+
return Math.random().toString(36).substring(2, 6);
|
|
47
|
+
}
|
|
48
|
+
async function generateUniqueSlugForInstance(name, entityDefinitionId, checkExists, excludeId) {
|
|
49
|
+
const baseSlug = generateSlug(name);
|
|
50
|
+
let slug = baseSlug;
|
|
51
|
+
let attempts = 0;
|
|
52
|
+
const maxAttempts = 100;
|
|
53
|
+
while (attempts < maxAttempts) {
|
|
54
|
+
const exists = await checkExists(slug, entityDefinitionId, excludeId);
|
|
55
|
+
if (!exists) {
|
|
56
|
+
return slug;
|
|
57
|
+
}
|
|
58
|
+
const randomSuffix = generateRandomSuffix();
|
|
59
|
+
slug = `${baseSlug}-${randomSuffix}`;
|
|
60
|
+
attempts++;
|
|
61
|
+
}
|
|
62
|
+
const timestamp = Date.now().toString(36);
|
|
63
|
+
return `${baseSlug}-${timestamp}`;
|
|
64
|
+
}
|
|
65
|
+
var init_slug = __esm({
|
|
66
|
+
"src/utils/slug.ts"() {
|
|
67
|
+
}
|
|
68
|
+
});
|
|
24
69
|
|
|
25
70
|
// src/types/entity-types.ts
|
|
26
71
|
function isFieldValue(value) {
|
|
@@ -397,6 +442,7 @@ var BasePublicAPIClient = class {
|
|
|
397
442
|
return {
|
|
398
443
|
id: row.id,
|
|
399
444
|
name: row.name,
|
|
445
|
+
slug: row.slug,
|
|
400
446
|
description: row.description,
|
|
401
447
|
tableName: row.table_name,
|
|
402
448
|
type: row.type,
|
|
@@ -519,6 +565,38 @@ var BasePublicAPIClient = class {
|
|
|
519
565
|
}
|
|
520
566
|
return config;
|
|
521
567
|
}
|
|
568
|
+
/**
|
|
569
|
+
* Получить все EntityDefinitions проекта с полями одним запросом (JOIN)
|
|
570
|
+
* Используется для загрузки всех сущностей в layout
|
|
571
|
+
*
|
|
572
|
+
* @returns Массив EntityDefinitionConfig с полями
|
|
573
|
+
*/
|
|
574
|
+
async getAllEntityDefinitions() {
|
|
575
|
+
const { data, error } = await this.supabase.from("entity_definition").select(
|
|
576
|
+
`
|
|
577
|
+
*,
|
|
578
|
+
field!field_entity_definition_id_fkey (*)
|
|
579
|
+
`
|
|
580
|
+
).eq("project_id", this.projectId).order("name");
|
|
581
|
+
if (error) {
|
|
582
|
+
throw new Error(`Failed to load entity definitions: ${error.message}`);
|
|
583
|
+
}
|
|
584
|
+
if (!data || data.length === 0) {
|
|
585
|
+
return [];
|
|
586
|
+
}
|
|
587
|
+
return data.map((row) => {
|
|
588
|
+
const entityDefinition = this.transformEntityDefinitionFromDB(row);
|
|
589
|
+
const fields = (row.field || []).map(
|
|
590
|
+
(fieldRow) => this.transformFieldFromDB(fieldRow)
|
|
591
|
+
);
|
|
592
|
+
fields.sort(
|
|
593
|
+
(a, b) => a.displayIndex - b.displayIndex
|
|
594
|
+
);
|
|
595
|
+
return __spreadProps(__spreadValues({}, entityDefinition), {
|
|
596
|
+
fields
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
}
|
|
522
600
|
/**
|
|
523
601
|
* Преобразование EntityDefinitionConfig в EntityDefinition
|
|
524
602
|
*/
|
|
@@ -526,6 +604,7 @@ var BasePublicAPIClient = class {
|
|
|
526
604
|
return {
|
|
527
605
|
id: config.id,
|
|
528
606
|
name: config.name,
|
|
607
|
+
slug: config.slug,
|
|
529
608
|
description: config.description,
|
|
530
609
|
tableName: config.tableName,
|
|
531
610
|
type: config.type,
|
|
@@ -637,6 +716,7 @@ var BasePublicAPIClient = class {
|
|
|
637
716
|
function transformEntityInstance(row) {
|
|
638
717
|
return {
|
|
639
718
|
id: row.id,
|
|
719
|
+
slug: row.slug,
|
|
640
720
|
entityDefinitionId: row.entity_definition_id,
|
|
641
721
|
projectId: row.project_id,
|
|
642
722
|
data: row.data || {},
|
|
@@ -647,6 +727,7 @@ function transformEntityInstance(row) {
|
|
|
647
727
|
function flattenInstance(instance, fields, relationsAsIds = false) {
|
|
648
728
|
const result = {
|
|
649
729
|
id: instance.id,
|
|
730
|
+
slug: instance.slug,
|
|
650
731
|
entityDefinitionId: instance.entityDefinitionId,
|
|
651
732
|
projectId: instance.projectId,
|
|
652
733
|
createdAt: instance.createdAt,
|
|
@@ -1214,9 +1295,27 @@ var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
|
|
|
1214
1295
|
);
|
|
1215
1296
|
}
|
|
1216
1297
|
const { data: instanceData, relations } = data;
|
|
1298
|
+
const name = instanceData.name;
|
|
1299
|
+
if (!name || typeof name !== "string") {
|
|
1300
|
+
throw new Error(
|
|
1301
|
+
"Field 'name' is required and must be a string for slug generation"
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
const {
|
|
1305
|
+
generateUniqueSlugForInstance: generateUniqueSlugForInstance2
|
|
1306
|
+
} = await Promise.resolve().then(() => (init_slug(), slug_exports));
|
|
1307
|
+
const slug = await generateUniqueSlugForInstance2(
|
|
1308
|
+
name,
|
|
1309
|
+
entityDefinitionId,
|
|
1310
|
+
async (slugToCheck, entityDefIdToCheck) => {
|
|
1311
|
+
const { data: existing } = await this.supabase.from("entity_instance").select("id").eq("entity_definition_id", entityDefIdToCheck).eq("slug", slugToCheck).single();
|
|
1312
|
+
return !!existing;
|
|
1313
|
+
}
|
|
1314
|
+
);
|
|
1217
1315
|
const { data: instance, error: instanceError } = await this.supabase.from("entity_instance").insert({
|
|
1218
1316
|
entity_definition_id: entityDefinitionId,
|
|
1219
1317
|
project_id: this.projectId,
|
|
1318
|
+
slug,
|
|
1220
1319
|
data: instanceData,
|
|
1221
1320
|
created_by: (user == null ? void 0 : user.id) || null
|
|
1222
1321
|
}).select().single();
|