@apito-io/js-admin-sdk 2.7.0 → 3.0.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/src/client.ts CHANGED
@@ -11,27 +11,44 @@ import {
11
11
  ApitoError,
12
12
  ValidationError,
13
13
  InjectedDBOperationInterface,
14
- TenantLoginResponse,
15
- TenantUser,
16
- TenantUsersResponse,
14
+ LoginUserResponse,
15
+ User,
16
+ UsersResponse,
17
17
  TenantByDomainResponse,
18
18
  TenantCatalogSearchRow,
19
- TenantLoginParams,
20
- CreateTenantUserParams,
21
- UpdateTenantUserParams,
19
+ LoginUserParams,
20
+ CreateUserParams,
21
+ UpdateUserParams,
22
+ GoogleOAuthStateResponse,
23
+ ProjectStorageSettings,
24
+ UpdateProjectStorageInput,
25
+ SystemFile,
26
+ SystemFilesListResponse,
27
+ SystemFileUploadParams,
28
+ DeleteSystemFilesResponse,
22
29
  } from './types';
23
30
 
31
+ function deriveRestBaseURL(graphqlURL: string): string {
32
+ const u = graphqlURL.trim().replace(/\/$/, '');
33
+ if (u.endsWith('/graphql')) {
34
+ return u.slice(0, -'/graphql'.length);
35
+ }
36
+ return u;
37
+ }
38
+
24
39
  /**
25
40
  * Apito SDK Client - JavaScript implementation matching the Go SDK
26
41
  */
27
42
  export class ApitoClient implements InjectedDBOperationInterface {
28
43
  private httpClient: AxiosInstance;
29
44
  private baseURL: string;
45
+ private restBaseURL: string;
30
46
  private apiKey: string;
31
47
  private tenantId?: string;
32
48
 
33
49
  constructor(config: ClientConfig) {
34
50
  this.baseURL = config.baseURL;
51
+ this.restBaseURL = (config.restBaseURL ?? '').trim() || deriveRestBaseURL(config.baseURL);
35
52
  this.apiKey = config.apiKey;
36
53
  this.tenantId = config.tenantId;
37
54
 
@@ -147,10 +164,73 @@ export class ApitoClient implements InjectedDBOperationInterface {
147
164
  return data.token;
148
165
  }
149
166
 
167
+ private authHeaders(tenantId?: string): Record<string, string> {
168
+ const headers: Record<string, string> = {
169
+ ...(this.apiKey.startsWith('cli-') || this.apiKey.startsWith('sdk-')
170
+ ? { 'X-Apito-Sync-Key': this.apiKey }
171
+ : { 'X-Apito-Key': this.apiKey }),
172
+ };
173
+ const tid = tenantId ?? this.tenantId;
174
+ if (tid) {
175
+ headers['X-Apito-Tenant-ID'] = tid;
176
+ }
177
+ return headers;
178
+ }
179
+
180
+ private async executeREST<T>(
181
+ method: 'GET' | 'POST',
182
+ path: string,
183
+ options?: {
184
+ query?: Record<string, string | number | undefined>;
185
+ jsonBody?: Record<string, unknown>;
186
+ formData?: FormData;
187
+ allowFailure?: boolean;
188
+ }
189
+ ): Promise<T> {
190
+ const url = new URL(`${this.restBaseURL.replace(/\/$/, '')}${path}`);
191
+ if (options?.query) {
192
+ for (const [k, v] of Object.entries(options.query)) {
193
+ if (v !== undefined && v !== '') {
194
+ url.searchParams.set(k, String(v));
195
+ }
196
+ }
197
+ }
198
+ const headers = this.authHeaders();
199
+ let data: FormData | Record<string, unknown> | undefined;
200
+ if (options?.formData) {
201
+ data = options.formData;
202
+ } else if (options?.jsonBody) {
203
+ headers['Content-Type'] = 'application/json';
204
+ data = options.jsonBody;
205
+ }
206
+ try {
207
+ const response = await this.httpClient.request({
208
+ method,
209
+ url: url.toString(),
210
+ headers,
211
+ data,
212
+ maxBodyLength: Infinity,
213
+ maxContentLength: Infinity,
214
+ });
215
+ const body = response.data as Record<string, unknown>;
216
+ if (body.success === false && !options?.allowFailure) {
217
+ throw new ValidationError(String(body.message ?? 'request failed'));
218
+ }
219
+ return body as T;
220
+ } catch (error) {
221
+ if (axios.isAxiosError(error)) {
222
+ const msg =
223
+ (error.response?.data as { message?: string })?.message ?? error.message;
224
+ throw new ApitoError(msg, 'HTTP_ERROR', error.response?.status, error.response?.data);
225
+ }
226
+ throw error;
227
+ }
228
+ }
229
+
150
230
  /**
151
- * Tenant catalog login (system GraphQL `loginTenantUser`). Password path: pass `password` and `email` or `phone` per project Authentication settings. Google OAuth path: `authMethod: 'google'` with `code` and `state` from the redirect; call `tenantGoogleOAuthState(projectId)` before opening Google to obtain `state`.
231
+ * Project user login (system GraphQL `loginUser`). Password path: pass `password` and `email` or `phone` per project Authentication settings. Google OAuth path: `authMethod: 'google'` with `code` and `state` from the redirect; call `googleOAuthState(projectId)` before opening Google to obtain `state`.
152
232
  */
153
- async loginTenantUser(params: TenantLoginParams): Promise<TenantLoginResponse> {
233
+ async loginUser(params: LoginUserParams): Promise<LoginUserResponse> {
154
234
  const authMethod = (params.authMethod ?? 'general').trim().toLowerCase() || 'general';
155
235
  const variables: Record<string, any> = {
156
236
  project_id: params.projectId,
@@ -181,8 +261,8 @@ export class ApitoClient implements InjectedDBOperationInterface {
181
261
  }
182
262
 
183
263
  const query = `
184
- query LoginTenantUser($project_id: String!, $password: String, $auth_method: String, $email: String, $phone: String, $code: String, $state: String) {
185
- loginTenantUser(project_id: $project_id, password: $password, auth_method: $auth_method, email: $email, phone: $phone, code: $code, state: $state) {
264
+ query LoginUser($project_id: String!, $password: String, $auth_method: String, $email: String, $phone: String, $code: String, $state: String) {
265
+ loginUser(project_id: $project_id, password: $password, auth_method: $auth_method, email: $email, phone: $phone, code: $code, state: $state) {
186
266
  token
187
267
  user {
188
268
  id
@@ -199,48 +279,48 @@ export class ApitoClient implements InjectedDBOperationInterface {
199
279
  }
200
280
  `;
201
281
  const response = await this.executeGraphQL(query, variables);
202
- const raw = response.data?.loginTenantUser;
282
+ const raw = response.data?.loginUser;
203
283
  if (!raw?.token) {
204
- throw new ValidationError('Invalid response format for loginTenantUser');
284
+ throw new ValidationError('Invalid response format for loginUser');
205
285
  }
206
286
  return {
207
287
  token: raw.token as string,
208
- user: raw.user as TenantUser | undefined,
288
+ user: raw.user as User | undefined,
209
289
  };
210
290
  }
211
291
 
212
292
  /**
213
- * Signed OAuth state for tenant Google login (system query `tenantGoogleOAuthState`). Use in the authorize URL together with project `google_client_id` and the configured redirect URI.
293
+ * Signed OAuth state for Google login (system query `googleOAuthState`). Use in the authorize URL together with project `google_client_id` and the configured redirect URI.
214
294
  */
215
- async tenantGoogleOAuthState(projectId: string): Promise<{ state: string }> {
295
+ async googleOAuthState(projectId: string): Promise<GoogleOAuthStateResponse> {
216
296
  const query = `
217
- query TenantGoogleOAuthState($project_id: String!) {
218
- tenantGoogleOAuthState(project_id: $project_id) {
297
+ query GoogleOAuthState($project_id: String!) {
298
+ googleOAuthState(project_id: $project_id) {
219
299
  state
220
300
  }
221
301
  }
222
302
  `;
223
303
  const variables = { project_id: projectId };
224
304
  const response = await this.executeGraphQL(query, variables);
225
- const raw = response.data?.tenantGoogleOAuthState;
305
+ const raw = response.data?.googleOAuthState;
226
306
  const state = typeof raw?.state === 'string' ? raw.state.trim() : '';
227
307
  if (!state) {
228
- throw new ValidationError('Invalid response format for tenantGoogleOAuthState');
308
+ throw new ValidationError('Invalid response format for googleOAuthState');
229
309
  }
230
310
  return { state };
231
311
  }
232
312
 
233
313
  /**
234
- * Search tenant users for a project.
314
+ * Search project end-users.
235
315
  */
236
- async searchTenantUsers(
316
+ async searchUsers(
237
317
  projectId: string,
238
318
  limit?: number,
239
319
  offset?: number
240
- ): Promise<TenantUsersResponse> {
320
+ ): Promise<UsersResponse> {
241
321
  const query = `
242
- query SearchTenantUsers($project_id: String!, $limit: Int, $offset: Int) {
243
- searchTenantUsers(project_id: $project_id, limit: $limit, offset: $offset) {
322
+ query SearchUsers($project_id: String!, $limit: Int, $offset: Int) {
323
+ searchUsers(project_id: $project_id, limit: $limit, offset: $offset) {
244
324
  count
245
325
  users {
246
326
  id
@@ -260,15 +340,15 @@ export class ApitoClient implements InjectedDBOperationInterface {
260
340
  if (limit !== undefined) variables.limit = limit;
261
341
  if (offset !== undefined) variables.offset = offset;
262
342
  const response = await this.executeGraphQL(query, variables);
263
- const raw = response.data?.searchTenantUsers;
343
+ const raw = response.data?.searchUsers;
264
344
  if (!raw) {
265
- throw new ValidationError('Invalid response format for searchTenantUsers');
345
+ throw new ValidationError('Invalid response format for searchUsers');
266
346
  }
267
347
  let count = 0;
268
348
  if (typeof raw.count === 'number') {
269
349
  count = raw.count;
270
350
  }
271
- const users = (raw.users ?? []) as TenantUser[];
351
+ const users = (raw.users ?? []) as User[];
272
352
  return { users, count };
273
353
  }
274
354
 
@@ -303,19 +383,16 @@ export class ApitoClient implements InjectedDBOperationInterface {
303
383
  }
304
384
 
305
385
  /**
306
- * Create a tenant catalog user (local password). Use `email` and/or `phone` per engine validation for the project identifier mode.
386
+ * Create a project user (local password). Use `email` and/or `phone` per engine validation for the project identifier mode.
307
387
  */
308
- async createTenantUser(
309
- projectId: string,
310
- params: CreateTenantUserParams
311
- ): Promise<TenantUser> {
388
+ async createUser(projectId: string, params: CreateUserParams): Promise<User> {
312
389
  const password = (params.password ?? '').trim();
313
390
  if (!password) {
314
391
  throw new ValidationError('password is required');
315
392
  }
316
393
  const query = `
317
- mutation CreateTenantUser($project_id: String!, $password: String!, $role: String, $email: String, $phone: String) {
318
- createTenantUser(project_id: $project_id, password: $password, role: $role, email: $email, phone: $phone) {
394
+ mutation CreateUser($project_id: String!, $password: String!, $role: String, $email: String, $phone: String) {
395
+ createUser(project_id: $project_id, password: $password, role: $role, email: $email, phone: $phone) {
319
396
  id
320
397
  email
321
398
  phone
@@ -339,32 +416,27 @@ export class ApitoClient implements InjectedDBOperationInterface {
339
416
  const phone = (params.phone ?? '').trim();
340
417
  if (phone) variables.phone = phone;
341
418
  const response = await this.executeGraphQL(query, variables);
342
- const u = response.data?.createTenantUser;
419
+ const u = response.data?.createUser;
343
420
  if (!u?.id) {
344
- throw new ValidationError('Invalid response format for createTenantUser');
421
+ throw new ValidationError('Invalid response format for createUser');
345
422
  }
346
- return u as TenantUser;
423
+ return u as User;
347
424
  }
348
425
 
349
426
  /**
350
- * Update a tenant catalog user. Project scope is implied by the API key. Only include fields to change.
427
+ * Update a project user. Project scope is implied by the API key. Only include fields to change.
351
428
  */
352
- async updateTenantUser(userId: string, params: UpdateTenantUserParams): Promise<TenantUser> {
429
+ async updateUser(userId: string, params: UpdateUserParams): Promise<User> {
353
430
  const uid = (userId ?? '').trim();
354
431
  if (!uid) {
355
432
  throw new ValidationError('userId is required');
356
433
  }
357
- if (
358
- params.email === undefined &&
359
- params.phone === undefined &&
360
- params.password === undefined &&
361
- params.role === undefined
362
- ) {
434
+ if (params.email === undefined && params.phone === undefined && params.role === undefined) {
363
435
  throw new ValidationError('at least one field must be provided');
364
436
  }
365
437
  const query = `
366
- mutation UpdateTenantUser($user_id: String!, $email: String, $phone: String, $password: String, $role: String) {
367
- updateTenantUser(user_id: $user_id, email: $email, phone: $phone, password: $password, role: $role) {
438
+ mutation UpdateUser($user_id: String!, $email: String, $phone: String, $role: String) {
439
+ updateUser(user_id: $user_id, email: $email, phone: $phone, role: $role) {
368
440
  id
369
441
  email
370
442
  phone
@@ -380,37 +452,182 @@ export class ApitoClient implements InjectedDBOperationInterface {
380
452
  const variables: Record<string, any> = { user_id: uid };
381
453
  if (params.email !== undefined) variables.email = params.email;
382
454
  if (params.phone !== undefined) variables.phone = params.phone;
383
- if (params.password !== undefined) variables.password = params.password;
384
455
  if (params.role !== undefined) variables.role = params.role;
385
456
  const response = await this.executeGraphQL(query, variables);
386
- const u = response.data?.updateTenantUser;
457
+ const u = response.data?.updateUser;
387
458
  if (!u?.id) {
388
- throw new ValidationError('Invalid response format for updateTenantUser');
459
+ throw new ValidationError('Invalid response format for updateUser');
460
+ }
461
+ return u as User;
462
+ }
463
+
464
+ /** Set a new password for a project user (admin mutation resetUserPassword). */
465
+ async resetUserPassword(userId: string, password: string): Promise<boolean> {
466
+ const uid = (userId ?? '').trim();
467
+ if (!uid) {
468
+ throw new ValidationError('userId is required');
389
469
  }
390
- return u as TenantUser;
470
+ if (!(password ?? '').trim()) {
471
+ throw new ValidationError('password is required');
472
+ }
473
+ const query = `
474
+ mutation ResetUserPassword($user_id: String!, $password: String!) {
475
+ resetUserPassword(user_id: $user_id, password: $password)
476
+ }
477
+ `;
478
+ const response = await this.executeGraphQL(query, { user_id: uid, password });
479
+ const ok = response.data?.resetUserPassword;
480
+ if (typeof ok !== 'boolean') {
481
+ throw new ValidationError('Invalid response format for resetUserPassword');
482
+ }
483
+ return ok;
391
484
  }
392
485
 
393
486
  /**
394
- * Delete a tenant catalog user by id. Project scope is implied by the API key.
487
+ * Delete a project user by id. Project scope is implied by the API key.
395
488
  */
396
- async deleteTenantUser(userId: string): Promise<boolean> {
489
+ async deleteUser(userId: string): Promise<boolean> {
397
490
  const uid = (userId ?? '').trim();
398
491
  if (!uid) {
399
492
  throw new ValidationError('userId is required');
400
493
  }
401
494
  const query = `
402
- mutation DeleteTenantUser($user_id: String!) {
403
- deleteTenantUser(user_id: $user_id)
495
+ mutation DeleteUser($user_id: String!) {
496
+ deleteUser(user_id: $user_id)
404
497
  }
405
498
  `;
406
499
  const response = await this.executeGraphQL(query, { user_id: uid });
407
- const ok = response.data?.deleteTenantUser;
500
+ const ok = response.data?.deleteUser;
408
501
  if (typeof ok !== 'boolean') {
409
- throw new ValidationError('Invalid response format for deleteTenantUser');
502
+ throw new ValidationError('Invalid response format for deleteUser');
410
503
  }
411
504
  return ok;
412
505
  }
413
506
 
507
+ /** Read project storage settings via getProject. */
508
+ async getProjectStorageSettings(projectId: string): Promise<ProjectStorageSettings> {
509
+ const query = `
510
+ query GetProjectStorageSettings($_id: String!) {
511
+ getProject(_id: $_id) {
512
+ storage_settings {
513
+ use_free_cloud_storage
514
+ endpoint
515
+ region
516
+ bucket
517
+ access_key_id
518
+ has_secret_access_key
519
+ public_base_url
520
+ force_path_style
521
+ }
522
+ }
523
+ }
524
+ `;
525
+ const response = await this.executeGraphQL(query, { _id: projectId });
526
+ const settings = response.data?.getProject?.storage_settings;
527
+ if (!settings) {
528
+ throw new ValidationError('Invalid response format for getProjectStorageSettings');
529
+ }
530
+ return settings as ProjectStorageSettings;
531
+ }
532
+
533
+ /** Persist project storage settings. */
534
+ async updateProjectStorageSettings(
535
+ input: UpdateProjectStorageInput
536
+ ): Promise<ProjectStorageSettings> {
537
+ const query = `
538
+ mutation UpdateProjectStorageSettings($input: UpdateProjectStorageInput!) {
539
+ updateProjectStorageSettings(input: $input) {
540
+ storage_settings {
541
+ use_free_cloud_storage
542
+ endpoint
543
+ region
544
+ bucket
545
+ access_key_id
546
+ has_secret_access_key
547
+ public_base_url
548
+ force_path_style
549
+ }
550
+ }
551
+ }
552
+ `;
553
+ const response = await this.executeGraphQL(query, { input });
554
+ const settings = response.data?.updateProjectStorageSettings?.storage_settings;
555
+ if (!settings) {
556
+ throw new ValidationError('Invalid response format for updateProjectStorageSettings');
557
+ }
558
+ return settings as ProjectStorageSettings;
559
+ }
560
+
561
+ /** Upload a file via POST /system/files/upload. */
562
+ async uploadSystemFile(params: SystemFileUploadParams): Promise<SystemFile> {
563
+ const size =
564
+ params.content instanceof ArrayBuffer
565
+ ? params.content.byteLength
566
+ : params.content.byteLength;
567
+ if (!params.content || size === 0) {
568
+ throw new ValidationError('file content is required');
569
+ }
570
+ const fileName = (params.fileName ?? '').trim() || 'upload';
571
+ const form = new FormData();
572
+ const bytes =
573
+ params.content instanceof ArrayBuffer ? new Uint8Array(params.content) : params.content;
574
+ const blob = new Blob([bytes as BlobPart]);
575
+ form.append('file', blob, fileName);
576
+ if (params.fileType?.trim()) {
577
+ form.append('file_type', params.fileType.trim());
578
+ }
579
+ const body = await this.executeREST<{ file: SystemFile }>('POST', '/files/upload', {
580
+ formData: form,
581
+ });
582
+ if (!body.file?.id) {
583
+ throw new ValidationError('Invalid response format for uploadSystemFile');
584
+ }
585
+ return body.file;
586
+ }
587
+
588
+ /** List files via GET /system/files/list. */
589
+ async listSystemFiles(
590
+ fileType?: string,
591
+ limit?: number,
592
+ offset?: number
593
+ ): Promise<SystemFilesListResponse> {
594
+ const body = await this.executeREST<{
595
+ files: SystemFile[];
596
+ total: number;
597
+ }>('GET', '/files/list', {
598
+ query: {
599
+ file_type: fileType,
600
+ limit,
601
+ offset,
602
+ },
603
+ });
604
+ return {
605
+ files: body.files ?? [],
606
+ total: body.total ?? 0,
607
+ };
608
+ }
609
+
610
+ /** Delete files via POST /system/files/delete. */
611
+ async deleteSystemFiles(ids: string[]): Promise<DeleteSystemFilesResponse> {
612
+ if (!ids?.length) {
613
+ throw new ValidationError('ids are required');
614
+ }
615
+ const body = await this.executeREST<DeleteSystemFilesResponse>('POST', '/files/delete', {
616
+ jsonBody: { ids },
617
+ allowFailure: true,
618
+ });
619
+ const result: DeleteSystemFilesResponse = {
620
+ success: !!body.success,
621
+ deleted_ids: body.deleted_ids ?? [],
622
+ storage_failed: body.storage_failed,
623
+ message: body.message,
624
+ };
625
+ if (!result.success && result.message) {
626
+ throw new ValidationError(result.message);
627
+ }
628
+ return result;
629
+ }
630
+
414
631
  /**
415
632
  * Get a single resource by model and ID
416
633
  */
package/src/index.ts CHANGED
@@ -24,9 +24,14 @@ export type {
24
24
  ApitoError,
25
25
  ValidationError,
26
26
  InjectedDBOperationInterface,
27
- TenantLoginParams,
28
- CreateTenantUserParams,
29
- UpdateTenantUserParams,
27
+ LoginUserParams,
28
+ CreateUserParams,
29
+ UpdateUserParams,
30
+ User,
31
+ ProjectStorageSettings,
32
+ UpdateProjectStorageInput,
33
+ SystemFile,
34
+ SystemFileUploadParams,
30
35
  } from './types';
31
36
 
32
37
  // Default export for convenience
package/src/types.ts CHANGED
@@ -86,63 +86,110 @@ export interface CreateAndUpdateRequest {
86
86
  forceUpdate?: boolean;
87
87
  }
88
88
 
89
- /** Tenant catalog user from engine system DB (pro_tenant_users). */
90
- export interface TenantUser {
89
+ /** Project end-user from engine system DB (table project_users). */
90
+ export interface User {
91
91
  id: string;
92
92
  email?: string;
93
93
  phone?: string;
94
94
  role: string;
95
- tenant_id: string;
95
+ tenant_id?: string;
96
96
  provider?: string;
97
97
  status?: string;
98
98
  created_at?: string;
99
99
  updated_at?: string;
100
100
  }
101
101
 
102
- /** Login via system GraphQL `loginTenantUser`. Password path: use `email` or `phone` per project settings. Google OAuth code path: `authMethod: 'google'`, `code`, `state` from redirect (get `state` first via `tenantGoogleOAuthState`). */
103
- export interface TenantLoginParams {
102
+ /** Login via system GraphQL `loginUser`. Password path: use `email` or `phone` per project settings. Google OAuth code path: `authMethod: 'google'`, `code`, `state` from redirect (get `state` first via `googleOAuthState`). */
103
+ export interface LoginUserParams {
104
104
  projectId: string;
105
- /** Required for general (password) login. */
106
105
  password?: string;
107
106
  email?: string;
108
107
  phone?: string;
109
- /** `general` (default) or `google`. */
110
108
  authMethod?: string;
111
- /** Google authorization code (with `authMethod: 'google'`). */
112
109
  code?: string;
113
- /** OAuth state from `tenantGoogleOAuthState` or callback (with `authMethod: 'google'`). */
114
110
  state?: string;
115
111
  }
116
112
 
117
- export interface TenantGoogleOAuthStateResponse {
113
+ export interface GoogleOAuthStateResponse {
118
114
  state: string;
119
115
  }
120
116
 
121
- export interface CreateTenantUserParams {
117
+ export interface CreateUserParams {
122
118
  password: string;
123
119
  role?: string;
124
120
  email?: string;
125
121
  phone?: string;
126
122
  }
127
123
 
128
- /** Optional fields for `updateTenantUser`; omitted keys are not sent. */
129
- export interface UpdateTenantUserParams {
124
+ /** Optional fields for `updateUser`; omitted keys are not sent. */
125
+ export interface UpdateUserParams {
130
126
  email?: string;
131
127
  phone?: string;
132
- password?: string;
133
128
  role?: string;
134
129
  }
135
130
 
136
- export interface TenantLoginResponse {
131
+ export interface LoginUserResponse {
137
132
  token: string;
138
- user?: TenantUser;
133
+ user?: User;
139
134
  }
140
135
 
141
- export interface TenantUsersResponse {
142
- users: TenantUser[];
136
+ export interface UsersResponse {
137
+ users: User[];
143
138
  count: number;
144
139
  }
145
140
 
141
+ export interface ProjectStorageSettings {
142
+ use_free_cloud_storage: boolean;
143
+ endpoint?: string | null;
144
+ region?: string | null;
145
+ bucket?: string | null;
146
+ access_key_id?: string | null;
147
+ has_secret_access_key: boolean;
148
+ public_base_url?: string | null;
149
+ force_path_style?: boolean | null;
150
+ }
151
+
152
+ export interface UpdateProjectStorageInput {
153
+ use_free_cloud_storage?: boolean;
154
+ endpoint?: string;
155
+ region?: string;
156
+ bucket?: string;
157
+ access_key_id?: string;
158
+ secret_access_key?: string;
159
+ public_base_url?: string;
160
+ force_path_style?: boolean;
161
+ }
162
+
163
+ export interface SystemFile {
164
+ id: string;
165
+ file_type: string;
166
+ file_name: string;
167
+ file_extension?: string;
168
+ content_type?: string;
169
+ size: number;
170
+ url: string;
171
+ created_by?: string;
172
+ created_at?: string;
173
+ }
174
+
175
+ export interface SystemFilesListResponse {
176
+ files: SystemFile[];
177
+ total: number;
178
+ }
179
+
180
+ export interface SystemFileUploadParams {
181
+ fileName: string;
182
+ content: Uint8Array | ArrayBuffer;
183
+ fileType?: string;
184
+ }
185
+
186
+ export interface DeleteSystemFilesResponse {
187
+ success: boolean;
188
+ deleted_ids: string[];
189
+ storage_failed?: string[];
190
+ message?: string;
191
+ }
192
+
146
193
  /** One SaaS catalog tenant row from searchTenantsByDomain. */
147
194
  export interface TenantCatalogSearchRow {
148
195
  id: string;
@@ -158,6 +205,8 @@ export interface TenantByDomainResponse {
158
205
 
159
206
  export interface ClientConfig {
160
207
  baseURL: string;
208
+ /** REST base (e.g. http://host:5050/system); derived from baseURL when omitted */
209
+ restBaseURL?: string;
161
210
  apiKey: string;
162
211
  timeout?: number;
163
212
  httpClient?: any;
@@ -192,13 +241,19 @@ export interface InjectedDBOperationInterface {
192
241
  ): Promise<GraphQLResponse>;
193
242
  /** @param token Legacy; ignored. Auth uses client API key. */
194
243
  generateTenantToken(tenantId: string, duration?: string, role?: string): Promise<string>;
195
- loginTenantUser(params: TenantLoginParams): Promise<TenantLoginResponse>;
196
- tenantGoogleOAuthState(projectId: string): Promise<TenantGoogleOAuthStateResponse>;
197
- searchTenantUsers(projectId: string, limit?: number, offset?: number): Promise<TenantUsersResponse>;
244
+ loginUser(params: LoginUserParams): Promise<LoginUserResponse>;
245
+ googleOAuthState(projectId: string): Promise<GoogleOAuthStateResponse>;
246
+ searchUsers(projectId: string, limit?: number, offset?: number): Promise<UsersResponse>;
198
247
  searchTenantsByDomain(projectId: string, domain: string): Promise<TenantByDomainResponse>;
199
- createTenantUser(projectId: string, params: CreateTenantUserParams): Promise<TenantUser>;
200
- updateTenantUser(userId: string, params: UpdateTenantUserParams): Promise<TenantUser>;
201
- deleteTenantUser(userId: string): Promise<boolean>;
248
+ createUser(projectId: string, params: CreateUserParams): Promise<User>;
249
+ updateUser(userId: string, params: UpdateUserParams): Promise<User>;
250
+ resetUserPassword(userId: string, password: string): Promise<boolean>;
251
+ deleteUser(userId: string): Promise<boolean>;
252
+ getProjectStorageSettings(projectId: string): Promise<ProjectStorageSettings>;
253
+ updateProjectStorageSettings(input: UpdateProjectStorageInput): Promise<ProjectStorageSettings>;
254
+ uploadSystemFile(params: SystemFileUploadParams): Promise<SystemFile>;
255
+ listSystemFiles(fileType?: string, limit?: number, offset?: number): Promise<SystemFilesListResponse>;
256
+ deleteSystemFiles(ids: string[]): Promise<DeleteSystemFilesResponse>;
202
257
  getSingleResource(model: string, id: string, singlePageData?: boolean): Promise<DefaultDocumentStructure>;
203
258
  searchResources(model: string, filter?: Record<string, any>, aggregate?: boolean): Promise<SearchResult>;
204
259
  getRelationDocuments(id: string, connection: Record<string, any>): Promise<SearchResult>;
package/src/version.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Apito JavaScript internal SDK version (kept in sync with package.json for releases)
3
3
  */
4
- export const Version = '2.7.0';
4
+ export const Version = '3.0.0';
5
5
 
6
6
  /**
7
7
  * GetVersion returns the current version of the SDK