@igorchugurov/public-api-sdk 1.1.0 → 1.2.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 +35 -1
- package/dist/{client-BV5AAKYo.d.mts → client-DS5xnLAo.d.mts} +9 -0
- package/dist/{client-BV5AAKYo.d.ts → client-DS5xnLAo.d.ts} +9 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +141 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -1
- 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 +156 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +156 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,7 +152,7 @@ const { data, pagination } = await sdk.getInstances(entityDefinitionId, {
|
|
|
152
152
|
|
|
153
153
|
#### `getInstance(entityDefinitionId, id, params?)`
|
|
154
154
|
|
|
155
|
-
Получить один
|
|
155
|
+
Получить один экземпляр по ID.
|
|
156
156
|
|
|
157
157
|
```typescript
|
|
158
158
|
const instance = await sdk.getInstance(entityDefinitionId, id, {
|
|
@@ -160,6 +160,40 @@ const instance = await sdk.getInstance(entityDefinitionId, id, {
|
|
|
160
160
|
});
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
**Пример:**
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const instance = await sdk.getInstance("entity-def-id", "instance-id", {
|
|
167
|
+
relationsAsIds: true, // для редактирования - нужны только ID
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### `getInstanceBySlug(entityDefinitionId, slug, params?)`
|
|
172
|
+
|
|
173
|
+
Получить один экземпляр по slug.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const instance = await sdk.getInstanceBySlug(entityDefinitionId, slug, {
|
|
177
|
+
relationsAsIds?: boolean; // default: false
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Пример:**
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const instance = await sdk.getInstanceBySlug("entity-def-id", "my-article-slug", {
|
|
185
|
+
relationsAsIds: false, // для отображения - нужны полные объекты
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Особенности:**
|
|
190
|
+
- Валидирует формат slug перед запросом (только строчные латинские буквы, цифры и дефисы)
|
|
191
|
+
- Работает аналогично `getInstance`, но ищет по slug вместо id
|
|
192
|
+
- Поддерживает те же параметры, что и `getInstance` (relationsAsIds)
|
|
193
|
+
- Параметр `relationsAsIds`:
|
|
194
|
+
- `false` (по умолчанию) - возвращает полные объекты связанных сущностей
|
|
195
|
+
- `true` - возвращает только массивы ID связанных сущностей
|
|
196
|
+
|
|
163
197
|
#### `createInstance(entityDefinitionId, data)`
|
|
164
198
|
|
|
165
199
|
Создать новый экземпляр. Автоматически генерирует уникальный `slug` из поля `name`.
|
|
@@ -1109,6 +1109,9 @@ declare abstract class BasePublicAPIClient {
|
|
|
1109
1109
|
abstract getInstance(entityDefinitionId: string, id: string, params?: {
|
|
1110
1110
|
relationsAsIds?: boolean;
|
|
1111
1111
|
}): Promise<EntityInstanceWithFields>;
|
|
1112
|
+
abstract getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
|
|
1113
|
+
relationsAsIds?: boolean;
|
|
1114
|
+
}): Promise<EntityInstanceWithFields>;
|
|
1112
1115
|
abstract createInstance(entityDefinitionId: string, data: CreateInstanceData): Promise<EntityInstanceWithFields>;
|
|
1113
1116
|
abstract updateInstance(entityDefinitionId: string, id: string, data: UpdateInstanceData): Promise<EntityInstanceWithFields>;
|
|
1114
1117
|
abstract deleteInstance(entityDefinitionId: string, id: string): Promise<void>;
|
|
@@ -1152,6 +1155,12 @@ declare class PublicAPIClient extends BasePublicAPIClient {
|
|
|
1152
1155
|
getInstance(entityDefinitionId: string, id: string, params?: {
|
|
1153
1156
|
relationsAsIds?: boolean;
|
|
1154
1157
|
}): Promise<EntityInstanceWithFields>;
|
|
1158
|
+
/**
|
|
1159
|
+
* Получить один экземпляр по slug
|
|
1160
|
+
*/
|
|
1161
|
+
getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
|
|
1162
|
+
relationsAsIds?: boolean;
|
|
1163
|
+
}): Promise<EntityInstanceWithFields>;
|
|
1155
1164
|
/**
|
|
1156
1165
|
* Получить список экземпляров
|
|
1157
1166
|
* Поддерживает поиск, фильтры (JSONB и relation), пагинацию
|
|
@@ -1109,6 +1109,9 @@ declare abstract class BasePublicAPIClient {
|
|
|
1109
1109
|
abstract getInstance(entityDefinitionId: string, id: string, params?: {
|
|
1110
1110
|
relationsAsIds?: boolean;
|
|
1111
1111
|
}): Promise<EntityInstanceWithFields>;
|
|
1112
|
+
abstract getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
|
|
1113
|
+
relationsAsIds?: boolean;
|
|
1114
|
+
}): Promise<EntityInstanceWithFields>;
|
|
1112
1115
|
abstract createInstance(entityDefinitionId: string, data: CreateInstanceData): Promise<EntityInstanceWithFields>;
|
|
1113
1116
|
abstract updateInstance(entityDefinitionId: string, id: string, data: UpdateInstanceData): Promise<EntityInstanceWithFields>;
|
|
1114
1117
|
abstract deleteInstance(entityDefinitionId: string, id: string): Promise<void>;
|
|
@@ -1152,6 +1155,12 @@ declare class PublicAPIClient extends BasePublicAPIClient {
|
|
|
1152
1155
|
getInstance(entityDefinitionId: string, id: string, params?: {
|
|
1153
1156
|
relationsAsIds?: boolean;
|
|
1154
1157
|
}): Promise<EntityInstanceWithFields>;
|
|
1158
|
+
/**
|
|
1159
|
+
* Получить один экземпляр по slug
|
|
1160
|
+
*/
|
|
1161
|
+
getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
|
|
1162
|
+
relationsAsIds?: boolean;
|
|
1163
|
+
}): Promise<EntityInstanceWithFields>;
|
|
1155
1164
|
/**
|
|
1156
1165
|
* Получить список экземпляров
|
|
1157
1166
|
* Поддерживает поиск, фильтры (JSONB и relation), пагинацию
|
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-DS5xnLAo.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-DS5xnLAo.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-DS5xnLAo.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-DS5xnLAo.js';
|
|
3
3
|
import '@supabase/supabase-js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,8 @@ var __export = (target, all) => {
|
|
|
34
34
|
var slug_exports = {};
|
|
35
35
|
__export(slug_exports, {
|
|
36
36
|
generateSlug: () => generateSlug,
|
|
37
|
-
generateUniqueSlugForInstance: () => generateUniqueSlugForInstance
|
|
37
|
+
generateUniqueSlugForInstance: () => generateUniqueSlugForInstance,
|
|
38
|
+
validateSlug: () => validateSlug
|
|
38
39
|
});
|
|
39
40
|
function generateSlug(name) {
|
|
40
41
|
if (!name || typeof name !== "string") {
|
|
@@ -42,6 +43,16 @@ function generateSlug(name) {
|
|
|
42
43
|
}
|
|
43
44
|
return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").substring(0, 100);
|
|
44
45
|
}
|
|
46
|
+
function validateSlug(slug) {
|
|
47
|
+
if (!slug || typeof slug !== "string") {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (slug.length === 0 || slug.length > 100) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
54
|
+
return slugRegex.test(slug);
|
|
55
|
+
}
|
|
45
56
|
function generateRandomSuffix() {
|
|
46
57
|
return Math.random().toString(36).substring(2, 6);
|
|
47
58
|
}
|
|
@@ -756,6 +767,7 @@ function flattenInstance(instance, fields, relationsAsIds = false) {
|
|
|
756
767
|
}
|
|
757
768
|
|
|
758
769
|
// src/client.ts
|
|
770
|
+
init_slug();
|
|
759
771
|
var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
|
|
760
772
|
constructor(supabase, projectId, mode, options = {}) {
|
|
761
773
|
super(supabase, projectId, options);
|
|
@@ -907,6 +919,134 @@ var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
|
|
|
907
919
|
handleSupabaseError(error);
|
|
908
920
|
}
|
|
909
921
|
}
|
|
922
|
+
/**
|
|
923
|
+
* Получить один экземпляр по slug
|
|
924
|
+
*/
|
|
925
|
+
async getInstanceBySlug(entityDefinitionId, slug, params) {
|
|
926
|
+
var _a;
|
|
927
|
+
try {
|
|
928
|
+
if (!validateSlug(slug)) {
|
|
929
|
+
throw new ValidationError(
|
|
930
|
+
"slug",
|
|
931
|
+
"Slug must contain only lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen"
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
const fields = await this.getFields(entityDefinitionId);
|
|
935
|
+
const { data: instance, error: instanceError } = await this.supabase.from("entity_instance").select("*").eq("slug", slug).eq("entity_definition_id", entityDefinitionId).eq("project_id", this.projectId).single();
|
|
936
|
+
if (instanceError || !instance) {
|
|
937
|
+
handleInstanceError(
|
|
938
|
+
instanceError || new Error("Instance not found"),
|
|
939
|
+
slug
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
const transformedInstance = transformEntityInstance(instance);
|
|
943
|
+
if (transformedInstance.entityDefinitionId !== entityDefinitionId) {
|
|
944
|
+
throw new NotFoundError("Entity instance", slug);
|
|
945
|
+
}
|
|
946
|
+
const relationFields = fields.filter(
|
|
947
|
+
(f) => f.dbType === "manyToMany" || f.dbType === "manyToOne" || f.dbType === "oneToMany" || f.dbType === "oneToOne"
|
|
948
|
+
);
|
|
949
|
+
const relations = {};
|
|
950
|
+
if (relationFields.length > 0) {
|
|
951
|
+
const relationFieldIds = relationFields.map((f) => f.id).filter((id) => Boolean(id));
|
|
952
|
+
if (relationFieldIds.length > 0) {
|
|
953
|
+
const { data: allRelations, error: relationsError } = await this.supabase.from("entity_relation").select("target_instance_id, relation_field_id").eq("source_instance_id", transformedInstance.id).in("relation_field_id", relationFieldIds);
|
|
954
|
+
if (relationsError) {
|
|
955
|
+
throw new SDKError(
|
|
956
|
+
"RELATIONS_LOAD_ERROR",
|
|
957
|
+
`Failed to load relations for instance with slug ${slug}: ${relationsError.message}`,
|
|
958
|
+
500,
|
|
959
|
+
relationsError
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
if (allRelations && allRelations.length > 0) {
|
|
963
|
+
const targetInstanceIds = [
|
|
964
|
+
...new Set(allRelations.map((r) => r.target_instance_id))
|
|
965
|
+
];
|
|
966
|
+
const { data: relatedInstances, error: instancesError } = await this.supabase.from("entity_instance").select("*").in("id", targetInstanceIds);
|
|
967
|
+
if (instancesError) {
|
|
968
|
+
throw new SDKError(
|
|
969
|
+
"RELATED_INSTANCES_LOAD_ERROR",
|
|
970
|
+
`Failed to load related instances for instance with slug ${slug}: ${instancesError.message}`,
|
|
971
|
+
500,
|
|
972
|
+
instancesError
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
if (relatedInstances) {
|
|
976
|
+
const relatedInstancesMap = new Map(
|
|
977
|
+
relatedInstances.map((inst) => [
|
|
978
|
+
inst.id,
|
|
979
|
+
transformEntityInstance(inst)
|
|
980
|
+
])
|
|
981
|
+
);
|
|
982
|
+
for (const relation of allRelations) {
|
|
983
|
+
const relationField = relationFields.find(
|
|
984
|
+
(f) => f.id === relation.relation_field_id
|
|
985
|
+
);
|
|
986
|
+
if (relationField) {
|
|
987
|
+
const relatedInstance = relatedInstancesMap.get(
|
|
988
|
+
relation.target_instance_id
|
|
989
|
+
);
|
|
990
|
+
if (relatedInstance) {
|
|
991
|
+
if (!relations[relationField.name]) {
|
|
992
|
+
relations[relationField.name] = [];
|
|
993
|
+
}
|
|
994
|
+
relations[relationField.name].push(
|
|
995
|
+
relatedInstance
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
const fileFields = fields.filter(
|
|
1005
|
+
(f) => f.type === "files" || f.type === "images"
|
|
1006
|
+
);
|
|
1007
|
+
if (fileFields.length > 0) {
|
|
1008
|
+
const { data: allFiles, error: filesError } = await this.supabase.from("entity_file").select("id, field_id").eq("entity_instance_id", transformedInstance.id);
|
|
1009
|
+
if (filesError) {
|
|
1010
|
+
throw new SDKError(
|
|
1011
|
+
"FILES_LOAD_ERROR",
|
|
1012
|
+
`Failed to load files for instance with slug ${slug}: ${filesError.message}`,
|
|
1013
|
+
500,
|
|
1014
|
+
filesError
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
if (allFiles) {
|
|
1018
|
+
const filesByFieldId = /* @__PURE__ */ new Map();
|
|
1019
|
+
allFiles.forEach((file) => {
|
|
1020
|
+
if (file.field_id) {
|
|
1021
|
+
if (!filesByFieldId.has(file.field_id)) {
|
|
1022
|
+
filesByFieldId.set(file.field_id, []);
|
|
1023
|
+
}
|
|
1024
|
+
filesByFieldId.get(file.field_id).push(file.id);
|
|
1025
|
+
}
|
|
1026
|
+
});
|
|
1027
|
+
fileFields.forEach((field) => {
|
|
1028
|
+
const fileIds = filesByFieldId.get(field.id) || [];
|
|
1029
|
+
if (fileIds.length > 0 || !transformedInstance.data[field.name]) {
|
|
1030
|
+
transformedInstance.data[field.name] = fileIds;
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
const instanceWithRelations = __spreadProps(__spreadValues({}, transformedInstance), {
|
|
1036
|
+
relations: Object.keys(relations).length > 0 ? relations : void 0
|
|
1037
|
+
});
|
|
1038
|
+
return flattenInstance(
|
|
1039
|
+
instanceWithRelations,
|
|
1040
|
+
fields.map((f) => ({ name: f.name, dbType: f.dbType })),
|
|
1041
|
+
(_a = params == null ? void 0 : params.relationsAsIds) != null ? _a : false
|
|
1042
|
+
);
|
|
1043
|
+
} catch (error) {
|
|
1044
|
+
if (error instanceof NotFoundError || error instanceof PermissionDeniedError || error instanceof ValidationError || error instanceof SDKError) {
|
|
1045
|
+
throw error;
|
|
1046
|
+
}
|
|
1047
|
+
handleSupabaseError(error);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
910
1050
|
/**
|
|
911
1051
|
* Получить список экземпляров
|
|
912
1052
|
* Поддерживает поиск, фильтры (JSONB и relation), пагинацию
|