@igorchugurov/public-api-sdk 1.2.0 → 1.3.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/LICENSE CHANGED
@@ -20,3 +20,4 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
22
22
 
23
+
package/README.md CHANGED
@@ -157,14 +157,25 @@ const { data, pagination } = await sdk.getInstances(entityDefinitionId, {
157
157
  ```typescript
158
158
  const instance = await sdk.getInstance(entityDefinitionId, id, {
159
159
  relationsAsIds?: boolean; // default: false
160
+ loadFiles?: boolean; // default: false
160
161
  });
161
162
  ```
162
163
 
163
164
  **Пример:**
164
165
 
165
166
  ```typescript
167
+ // Базовое использование - без файлов
168
+ const instance = await sdk.getInstance("entity-def-id", "instance-id");
169
+
170
+ // Для редактирования - нужны только ID связей
171
+ const instance = await sdk.getInstance("entity-def-id", "instance-id", {
172
+ relationsAsIds: true,
173
+ });
174
+
175
+ // Для отображения с файлами - полные объекты
166
176
  const instance = await sdk.getInstance("entity-def-id", "instance-id", {
167
- relationsAsIds: true, // для редактирования - нужны только ID
177
+ relationsAsIds: false,
178
+ loadFiles: true, // файлы и изображения будут загружены как полные объекты EntityFile
168
179
  });
169
180
  ```
170
181
 
@@ -175,24 +186,33 @@ const instance = await sdk.getInstance("entity-def-id", "instance-id", {
175
186
  ```typescript
176
187
  const instance = await sdk.getInstanceBySlug(entityDefinitionId, slug, {
177
188
  relationsAsIds?: boolean; // default: false
189
+ loadFiles?: boolean; // default: false
178
190
  });
179
191
  ```
180
192
 
181
193
  **Пример:**
182
194
 
183
195
  ```typescript
196
+ // Базовое использование - без файлов
197
+ const instance = await sdk.getInstanceBySlug("entity-def-id", "my-article-slug");
198
+
199
+ // Для отображения с файлами - полные объекты
184
200
  const instance = await sdk.getInstanceBySlug("entity-def-id", "my-article-slug", {
185
- relationsAsIds: false, // для отображения - нужны полные объекты
201
+ relationsAsIds: false,
202
+ loadFiles: true, // файлы и изображения будут загружены как полные объекты EntityFile
186
203
  });
187
204
  ```
188
205
 
189
206
  **Особенности:**
190
207
  - Валидирует формат slug перед запросом (только строчные латинские буквы, цифры и дефисы)
191
208
  - Работает аналогично `getInstance`, но ищет по slug вместо id
192
- - Поддерживает те же параметры, что и `getInstance` (relationsAsIds)
209
+ - Поддерживает те же параметры, что и `getInstance`
193
210
  - Параметр `relationsAsIds`:
194
211
  - `false` (по умолчанию) - возвращает полные объекты связанных сущностей
195
212
  - `true` - возвращает только массивы ID связанных сущностей
213
+ - Параметр `loadFiles`:
214
+ - `false` (по умолчанию) - файлы и изображения не загружаются
215
+ - `true` - файлы и изображения загружаются как полные объекты `EntityFile` (с `fileUrl`, `fileName`, `fileSize` и т.д.)
196
216
 
197
217
  #### `createInstance(entityDefinitionId, data)`
198
218
 
@@ -356,3 +376,4 @@ pnpm dev
356
376
 
357
377
  MIT
358
378
 
379
+
@@ -1108,9 +1108,11 @@ declare abstract class BasePublicAPIClient {
1108
1108
  }>;
1109
1109
  abstract getInstance(entityDefinitionId: string, id: string, params?: {
1110
1110
  relationsAsIds?: boolean;
1111
+ loadFiles?: boolean;
1111
1112
  }): Promise<EntityInstanceWithFields>;
1112
1113
  abstract getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
1113
1114
  relationsAsIds?: boolean;
1115
+ loadFiles?: boolean;
1114
1116
  }): Promise<EntityInstanceWithFields>;
1115
1117
  abstract createInstance(entityDefinitionId: string, data: CreateInstanceData): Promise<EntityInstanceWithFields>;
1116
1118
  abstract updateInstance(entityDefinitionId: string, id: string, data: UpdateInstanceData): Promise<EntityInstanceWithFields>;
@@ -1149,17 +1151,24 @@ declare class PublicAPIClient extends BasePublicAPIClient {
1149
1151
  * Получить режим работы клиента (для отладки)
1150
1152
  */
1151
1153
  getMode(): "server" | "client";
1154
+ /**
1155
+ * Загружает файлы для экземпляра и возвращает их как полные объекты EntityFile,
1156
+ * сгруппированные по именам полей
1157
+ */
1158
+ private loadFilesForInstance;
1152
1159
  /**
1153
1160
  * Получить один экземпляр
1154
1161
  */
1155
1162
  getInstance(entityDefinitionId: string, id: string, params?: {
1156
1163
  relationsAsIds?: boolean;
1164
+ loadFiles?: boolean;
1157
1165
  }): Promise<EntityInstanceWithFields>;
1158
1166
  /**
1159
1167
  * Получить один экземпляр по slug
1160
1168
  */
1161
1169
  getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
1162
1170
  relationsAsIds?: boolean;
1171
+ loadFiles?: boolean;
1163
1172
  }): Promise<EntityInstanceWithFields>;
1164
1173
  /**
1165
1174
  * Получить список экземпляров
@@ -1108,9 +1108,11 @@ declare abstract class BasePublicAPIClient {
1108
1108
  }>;
1109
1109
  abstract getInstance(entityDefinitionId: string, id: string, params?: {
1110
1110
  relationsAsIds?: boolean;
1111
+ loadFiles?: boolean;
1111
1112
  }): Promise<EntityInstanceWithFields>;
1112
1113
  abstract getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
1113
1114
  relationsAsIds?: boolean;
1115
+ loadFiles?: boolean;
1114
1116
  }): Promise<EntityInstanceWithFields>;
1115
1117
  abstract createInstance(entityDefinitionId: string, data: CreateInstanceData): Promise<EntityInstanceWithFields>;
1116
1118
  abstract updateInstance(entityDefinitionId: string, id: string, data: UpdateInstanceData): Promise<EntityInstanceWithFields>;
@@ -1149,17 +1151,24 @@ declare class PublicAPIClient extends BasePublicAPIClient {
1149
1151
  * Получить режим работы клиента (для отладки)
1150
1152
  */
1151
1153
  getMode(): "server" | "client";
1154
+ /**
1155
+ * Загружает файлы для экземпляра и возвращает их как полные объекты EntityFile,
1156
+ * сгруппированные по именам полей
1157
+ */
1158
+ private loadFilesForInstance;
1152
1159
  /**
1153
1160
  * Получить один экземпляр
1154
1161
  */
1155
1162
  getInstance(entityDefinitionId: string, id: string, params?: {
1156
1163
  relationsAsIds?: boolean;
1164
+ loadFiles?: boolean;
1157
1165
  }): Promise<EntityInstanceWithFields>;
1158
1166
  /**
1159
1167
  * Получить один экземпляр по slug
1160
1168
  */
1161
1169
  getInstanceBySlug(entityDefinitionId: string, slug: string, params?: {
1162
1170
  relationsAsIds?: boolean;
1171
+ loadFiles?: boolean;
1163
1172
  }): Promise<EntityInstanceWithFields>;
1164
1173
  /**
1165
1174
  * Получить список экземпляров
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-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';
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-D3jtlTId.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-D3jtlTId.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-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';
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-D3jtlTId.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-D3jtlTId.js';
3
3
  import '@supabase/supabase-js';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -765,6 +765,22 @@ function flattenInstance(instance, fields, relationsAsIds = false) {
765
765
  }
766
766
  return result;
767
767
  }
768
+ function transformEntityFile(row) {
769
+ return {
770
+ id: row.id,
771
+ entityInstanceId: row.entity_instance_id,
772
+ fieldId: row.field_id,
773
+ fileUrl: row.file_url,
774
+ filePath: row.file_path,
775
+ fileName: row.file_name,
776
+ fileSize: row.file_size,
777
+ fileType: row.file_type,
778
+ storageBucket: row.storage_bucket,
779
+ uploadedBy: row.uploaded_by,
780
+ createdAt: row.created_at,
781
+ updatedAt: row.updated_at
782
+ };
783
+ }
768
784
 
769
785
  // src/client.ts
770
786
  init_slug();
@@ -797,6 +813,42 @@ var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
797
813
  getMode() {
798
814
  return this.mode;
799
815
  }
816
+ /**
817
+ * Загружает файлы для экземпляра и возвращает их как полные объекты EntityFile,
818
+ * сгруппированные по именам полей
819
+ */
820
+ async loadFilesForInstance(instanceId, fileFields) {
821
+ if (fileFields.length === 0) {
822
+ return /* @__PURE__ */ new Map();
823
+ }
824
+ const { data: allFiles, error: filesError } = await this.supabase.from("entity_file").select("*").eq("entity_instance_id", instanceId);
825
+ if (filesError) {
826
+ throw new SDKError(
827
+ "FILES_LOAD_ERROR",
828
+ `Failed to load files for instance ${instanceId}: ${filesError.message}`,
829
+ 500,
830
+ filesError
831
+ );
832
+ }
833
+ if (!allFiles || allFiles.length === 0) {
834
+ return /* @__PURE__ */ new Map();
835
+ }
836
+ const filesMap = /* @__PURE__ */ new Map();
837
+ const fieldIdToName = new Map(
838
+ fileFields.map((f) => [f.id, f.name])
839
+ );
840
+ allFiles.forEach((fileRow) => {
841
+ if (!fileRow.field_id) return;
842
+ const fieldName = fieldIdToName.get(fileRow.field_id);
843
+ if (!fieldName) return;
844
+ const entityFile = transformEntityFile(fileRow);
845
+ if (!filesMap.has(fieldName)) {
846
+ filesMap.set(fieldName, []);
847
+ }
848
+ filesMap.get(fieldName).push(entityFile);
849
+ });
850
+ return filesMap;
851
+ }
800
852
  /**
801
853
  * Получить один экземпляр
802
854
  */
@@ -873,34 +925,15 @@ var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
873
925
  }
874
926
  }
875
927
  }
876
- const fileFields = fields.filter(
877
- (f) => f.type === "files" || f.type === "images"
878
- );
879
- if (fileFields.length > 0) {
880
- const { data: allFiles, error: filesError } = await this.supabase.from("entity_file").select("id, field_id").eq("entity_instance_id", id);
881
- if (filesError) {
882
- throw new SDKError(
883
- "FILES_LOAD_ERROR",
884
- `Failed to load files for instance ${id}: ${filesError.message}`,
885
- 500,
886
- filesError
887
- );
888
- }
889
- if (allFiles) {
890
- const filesByFieldId = /* @__PURE__ */ new Map();
891
- allFiles.forEach((file) => {
892
- if (file.field_id) {
893
- if (!filesByFieldId.has(file.field_id)) {
894
- filesByFieldId.set(file.field_id, []);
895
- }
896
- filesByFieldId.get(file.field_id).push(file.id);
897
- }
898
- });
928
+ if ((params == null ? void 0 : params.loadFiles) === true) {
929
+ const fileFields = fields.filter(
930
+ (f) => f.type === "files" || f.type === "images"
931
+ );
932
+ if (fileFields.length > 0) {
933
+ const filesMap = await this.loadFilesForInstance(id, fileFields);
899
934
  fileFields.forEach((field) => {
900
- const fileIds = filesByFieldId.get(field.id) || [];
901
- if (fileIds.length > 0 || !transformedInstance.data[field.name]) {
902
- transformedInstance.data[field.name] = fileIds;
903
- }
935
+ const files = filesMap.get(field.name) || [];
936
+ transformedInstance.data[field.name] = files;
904
937
  });
905
938
  }
906
939
  }
@@ -1001,34 +1034,18 @@ var _PublicAPIClient = class _PublicAPIClient extends BasePublicAPIClient {
1001
1034
  }
1002
1035
  }
1003
1036
  }
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
1037
+ if ((params == null ? void 0 : params.loadFiles) === true) {
1038
+ const fileFields = fields.filter(
1039
+ (f) => f.type === "files" || f.type === "images"
1040
+ );
1041
+ if (fileFields.length > 0) {
1042
+ const filesMap = await this.loadFilesForInstance(
1043
+ transformedInstance.id,
1044
+ fileFields
1015
1045
  );
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
1046
  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
- }
1047
+ const files = filesMap.get(field.name) || [];
1048
+ transformedInstance.data[field.name] = files;
1032
1049
  });
1033
1050
  }
1034
1051
  }