@artu-ai/compliance-sdk 0.2.0 → 0.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.
Files changed (155) hide show
  1. package/dist/models/Client.d.ts.map +1 -1
  2. package/dist/models/Client.js +21 -3
  3. package/dist/models/ReportItem.d.ts +2 -2
  4. package/dist/models/ReportItem.d.ts.map +1 -1
  5. package/dist/models/ReportItem.js +4 -4
  6. package/dist/models/mex/MexReportItem.js +1 -1
  7. package/dist/models/mex/actividad-vulnerable/MexActividadVulnerableReportItem.js +1 -1
  8. package/dist/models/mex/actividad-vulnerable/avi/MexAVIReportItem.js +1 -1
  9. package/dist/models/mex/actividad-vulnerable/jys/MexJYSReportItem.js +1 -1
  10. package/dist/models/mex/actividad-vulnerable/tsc/MexTSCReportItem.js +1 -1
  11. package/dist/resources/addresses.d.ts +3 -3
  12. package/dist/resources/addresses.d.ts.map +1 -1
  13. package/dist/resources/bank-accounts.d.ts +3 -3
  14. package/dist/resources/bank-accounts.d.ts.map +1 -1
  15. package/dist/resources/base.d.ts +7 -6
  16. package/dist/resources/base.d.ts.map +1 -1
  17. package/dist/resources/base.js +3 -0
  18. package/dist/resources/clients.d.ts +3 -3
  19. package/dist/resources/clients.d.ts.map +1 -1
  20. package/dist/resources/contact-methods.d.ts +3 -3
  21. package/dist/resources/contact-methods.d.ts.map +1 -1
  22. package/dist/resources/documents.d.ts +94 -7
  23. package/dist/resources/documents.d.ts.map +1 -1
  24. package/dist/resources/documents.js +107 -0
  25. package/dist/resources/index.d.ts +1 -1
  26. package/dist/resources/index.d.ts.map +1 -1
  27. package/dist/resources/index.js +1 -1
  28. package/dist/resources/mex/actividad-vulnerable/avi/clients.d.ts +9 -3
  29. package/dist/resources/mex/actividad-vulnerable/avi/clients.d.ts.map +1 -1
  30. package/dist/resources/mex/actividad-vulnerable/avi/clients.js +14 -1
  31. package/dist/resources/mex/actividad-vulnerable/avi/reports.d.ts +39 -21
  32. package/dist/resources/mex/actividad-vulnerable/avi/reports.d.ts.map +1 -1
  33. package/dist/resources/mex/actividad-vulnerable/avi/reports.js +88 -20
  34. package/dist/resources/mex/actividad-vulnerable/avi/transactions.d.ts +9 -3
  35. package/dist/resources/mex/actividad-vulnerable/avi/transactions.d.ts.map +1 -1
  36. package/dist/resources/mex/actividad-vulnerable/avi/transactions.js +14 -1
  37. package/dist/resources/mex/actividad-vulnerable/jys/clients.d.ts +10 -3
  38. package/dist/resources/mex/actividad-vulnerable/jys/clients.d.ts.map +1 -1
  39. package/dist/resources/mex/actividad-vulnerable/jys/clients.js +14 -1
  40. package/dist/resources/mex/actividad-vulnerable/jys/reports.d.ts +33 -11
  41. package/dist/resources/mex/actividad-vulnerable/jys/reports.d.ts.map +1 -1
  42. package/dist/resources/mex/actividad-vulnerable/jys/reports.js +82 -10
  43. package/dist/resources/mex/actividad-vulnerable/jys/transactions.d.ts +10 -3
  44. package/dist/resources/mex/actividad-vulnerable/jys/transactions.d.ts.map +1 -1
  45. package/dist/resources/mex/actividad-vulnerable/jys/transactions.js +14 -1
  46. package/dist/resources/mex/actividad-vulnerable/tsc/clients.d.ts +10 -3
  47. package/dist/resources/mex/actividad-vulnerable/tsc/clients.d.ts.map +1 -1
  48. package/dist/resources/mex/actividad-vulnerable/tsc/clients.js +14 -1
  49. package/dist/resources/mex/actividad-vulnerable/tsc/reports.d.ts +33 -11
  50. package/dist/resources/mex/actividad-vulnerable/tsc/reports.d.ts.map +1 -1
  51. package/dist/resources/mex/actividad-vulnerable/tsc/reports.js +82 -10
  52. package/dist/resources/mex/actividad-vulnerable/tsc/transactions.d.ts +10 -3
  53. package/dist/resources/mex/actividad-vulnerable/tsc/transactions.d.ts.map +1 -1
  54. package/dist/resources/mex/actividad-vulnerable/tsc/transactions.js +14 -1
  55. package/dist/resources/mex/addresses.d.ts +11 -3
  56. package/dist/resources/mex/addresses.d.ts.map +1 -1
  57. package/dist/resources/mex/addresses.js +16 -1
  58. package/dist/resources/mex/bank-accounts.d.ts +11 -3
  59. package/dist/resources/mex/bank-accounts.d.ts.map +1 -1
  60. package/dist/resources/mex/bank-accounts.js +16 -0
  61. package/dist/resources/mex/clients.d.ts +12 -3
  62. package/dist/resources/mex/clients.d.ts.map +1 -1
  63. package/dist/resources/mex/clients.js +17 -1
  64. package/dist/resources/mex/reports.d.ts +41 -19
  65. package/dist/resources/mex/reports.d.ts.map +1 -1
  66. package/dist/resources/mex/reports.js +55 -19
  67. package/dist/resources/mex/transactions.d.ts +11 -3
  68. package/dist/resources/mex/transactions.d.ts.map +1 -1
  69. package/dist/resources/mex/transactions.js +16 -1
  70. package/dist/resources/reports.d.ts +33 -39
  71. package/dist/resources/reports.d.ts.map +1 -1
  72. package/dist/resources/reports.js +34 -36
  73. package/dist/resources/transactions.d.ts +3 -3
  74. package/dist/resources/transactions.d.ts.map +1 -1
  75. package/dist/sdk/ComplianceSDK.d.ts +2 -0
  76. package/dist/sdk/ComplianceSDK.d.ts.map +1 -1
  77. package/dist/sdk/ComplianceSDK.js +17 -9
  78. package/dist/sdk/mex/ComplianceSDK.d.ts.map +1 -1
  79. package/dist/sdk/mex/actividad-vulnerable/avi/ComplianceSDK.d.ts.map +1 -1
  80. package/dist/sdk/mex/actividad-vulnerable/avi/types.d.ts +2 -2
  81. package/dist/sdk/mex/actividad-vulnerable/avi/types.d.ts.map +1 -1
  82. package/dist/sdk/mex/actividad-vulnerable/avi/types.js +1 -0
  83. package/dist/sdk/mex/actividad-vulnerable/jys/ComplianceSDK.d.ts.map +1 -1
  84. package/dist/sdk/mex/actividad-vulnerable/jys/types.d.ts +2 -2
  85. package/dist/sdk/mex/actividad-vulnerable/jys/types.d.ts.map +1 -1
  86. package/dist/sdk/mex/actividad-vulnerable/jys/types.js +1 -0
  87. package/dist/sdk/mex/actividad-vulnerable/tsc/ComplianceSDK.d.ts.map +1 -1
  88. package/dist/sdk/mex/actividad-vulnerable/tsc/types.d.ts +2 -2
  89. package/dist/sdk/mex/actividad-vulnerable/tsc/types.d.ts.map +1 -1
  90. package/dist/sdk/mex/actividad-vulnerable/tsc/types.js +1 -0
  91. package/dist/sdk/mex/types.d.ts +2 -2
  92. package/dist/sdk/mex/types.d.ts.map +1 -1
  93. package/dist/sdk/types.d.ts +24 -1
  94. package/dist/sdk/types.d.ts.map +1 -1
  95. package/dist/utils/environment.d.ts +24 -0
  96. package/dist/utils/environment.d.ts.map +1 -1
  97. package/dist/utils/environment.js +38 -0
  98. package/dist/utils/index.d.ts +2 -0
  99. package/dist/utils/index.d.ts.map +1 -1
  100. package/dist/utils/index.js +4 -0
  101. package/dist/utils/session.d.ts +20 -2
  102. package/dist/utils/session.d.ts.map +1 -1
  103. package/dist/utils/session.js +9 -1
  104. package/dist/utils/trpc-client.d.ts +370 -200
  105. package/dist/utils/trpc-client.d.ts.map +1 -1
  106. package/dist/utils/trpc-client.js +2 -1
  107. package/dist/utils/upload.d.ts +81 -0
  108. package/dist/utils/upload.d.ts.map +1 -0
  109. package/dist/utils/upload.js +261 -0
  110. package/package.json +9 -8
  111. package/src/models/Client.ts +23 -3
  112. package/src/models/ReportItem.ts +4 -4
  113. package/src/models/mex/MexReportItem.ts +1 -1
  114. package/src/models/mex/actividad-vulnerable/MexActividadVulnerableReportItem.ts +1 -1
  115. package/src/models/mex/actividad-vulnerable/avi/MexAVIReportItem.ts +1 -1
  116. package/src/models/mex/actividad-vulnerable/jys/MexJYSReportItem.ts +1 -1
  117. package/src/models/mex/actividad-vulnerable/tsc/MexTSCReportItem.ts +1 -1
  118. package/src/resources/addresses.ts +8 -4
  119. package/src/resources/bank-accounts.ts +8 -4
  120. package/src/resources/base.ts +9 -4
  121. package/src/resources/clients.ts +10 -4
  122. package/src/resources/contact-methods.ts +4 -2
  123. package/src/resources/documents.ts +185 -5
  124. package/src/resources/index.ts +6 -1
  125. package/src/resources/mex/actividad-vulnerable/avi/clients.ts +30 -8
  126. package/src/resources/mex/actividad-vulnerable/avi/reports.ts +122 -26
  127. package/src/resources/mex/actividad-vulnerable/avi/transactions.ts +20 -2
  128. package/src/resources/mex/actividad-vulnerable/jys/clients.ts +20 -2
  129. package/src/resources/mex/actividad-vulnerable/jys/reports.ts +118 -16
  130. package/src/resources/mex/actividad-vulnerable/jys/transactions.ts +20 -2
  131. package/src/resources/mex/actividad-vulnerable/tsc/clients.ts +20 -2
  132. package/src/resources/mex/actividad-vulnerable/tsc/reports.ts +118 -16
  133. package/src/resources/mex/actividad-vulnerable/tsc/transactions.ts +20 -2
  134. package/src/resources/mex/addresses.ts +24 -2
  135. package/src/resources/mex/bank-accounts.ts +26 -2
  136. package/src/resources/mex/clients.ts +25 -2
  137. package/src/resources/mex/reports.ts +94 -26
  138. package/src/resources/mex/transactions.ts +24 -2
  139. package/src/resources/reports.ts +65 -43
  140. package/src/resources/transactions.ts +8 -4
  141. package/src/sdk/ComplianceSDK.ts +23 -8
  142. package/src/sdk/mex/ComplianceSDK.ts +7 -0
  143. package/src/sdk/mex/actividad-vulnerable/avi/ComplianceSDK.ts +4 -0
  144. package/src/sdk/mex/actividad-vulnerable/avi/types.ts +22 -8
  145. package/src/sdk/mex/actividad-vulnerable/jys/ComplianceSDK.ts +3 -0
  146. package/src/sdk/mex/actividad-vulnerable/jys/types.ts +22 -8
  147. package/src/sdk/mex/actividad-vulnerable/tsc/ComplianceSDK.ts +3 -0
  148. package/src/sdk/mex/actividad-vulnerable/tsc/types.ts +22 -8
  149. package/src/sdk/mex/types.ts +6 -2
  150. package/src/sdk/types.ts +31 -2
  151. package/src/utils/environment.ts +42 -0
  152. package/src/utils/index.ts +19 -0
  153. package/src/utils/session.ts +33 -3
  154. package/src/utils/trpc-client.ts +10 -1
  155. package/src/utils/upload.ts +388 -0
@@ -9,6 +9,7 @@ import type {
9
9
  CreateAddressInput,
10
10
  UpdateAddressInput,
11
11
  AddressFilter,
12
+ AddressSort,
12
13
  AddressType,
13
14
  ListOptions,
14
15
  PaginatedResponse,
@@ -51,11 +52,14 @@ import type { BatchOptions } from "./clients";
51
52
  * const addresses = await sdk.addresses.listByClient("client_123");
52
53
  * ```
53
54
  */
54
- export class AddressesResource extends BaseResource<
55
+ export class AddressesResource<
56
+ TSort = AddressSort,
57
+ > extends BaseResource<
55
58
  Address,
56
59
  CreateAddressInput,
57
60
  UpdateAddressInput,
58
- AddressFilter
61
+ AddressFilter,
62
+ TSort
59
63
  > {
60
64
  // ─────────────────────────────────────────────────────────────────
61
65
  // CRUD Operations
@@ -145,10 +149,10 @@ export class AddressesResource extends BaseResource<
145
149
  * @returns Paginated list of Addresses
146
150
  */
147
151
  async list(
148
- options?: ListOptions<AddressFilter>
152
+ options?: ListOptions<AddressFilter, TSort>
149
153
  ): Promise<PaginatedResponse<Address>> {
150
154
  const response = await this.execute(() =>
151
- this.trpc.addresses.list.query(options)
155
+ this.trpc.addresses.list.query(options as ListOptions<AddressFilter, AddressSort>)
152
156
  );
153
157
  return {
154
158
  data: response.data.map((a) => this.instantiate(a)),
@@ -12,6 +12,7 @@ import type {
12
12
  CreateBankAccountInput,
13
13
  UpdateBankAccountInput,
14
14
  BankAccountFilter,
15
+ BankAccountSort,
15
16
  PaginatedResponse,
16
17
  ListOptions,
17
18
  AtomicBatchResult,
@@ -54,11 +55,14 @@ import { BankAccount, type BankAccountData } from "../models/BankAccount";
54
55
  * const accounts = await sdk.bankAccounts.list("client_123");
55
56
  * ```
56
57
  */
57
- export class BankAccountsResource extends BaseResource<
58
+ export class BankAccountsResource<
59
+ TSort = BankAccountSort,
60
+ > extends BaseResource<
58
61
  BankAccount,
59
62
  CreateBankAccountInput,
60
63
  UpdateBankAccountInput,
61
- BankAccountFilter
64
+ BankAccountFilter,
65
+ TSort
62
66
  > {
63
67
  // ─────────────────────────────────────────────────────────────────
64
68
  // CRUD Operations
@@ -137,10 +141,10 @@ export class BankAccountsResource extends BaseResource<
137
141
  * Lists bank accounts with optional filtering.
138
142
  */
139
143
  async list(
140
- options?: ListOptions<BankAccountFilter>
144
+ options?: ListOptions<BankAccountFilter, TSort>
141
145
  ): Promise<PaginatedResponse<BankAccount>> {
142
146
  const response = await this.execute(() =>
143
- this.trpc.bankAccounts.list.query(options)
147
+ this.trpc.bankAccounts.list.query(options as ListOptions<BankAccountFilter, BankAccountSort>)
144
148
  );
145
149
 
146
150
  return {
@@ -85,6 +85,7 @@ export abstract class BaseResource<
85
85
  TCreateInput,
86
86
  TUpdateInput,
87
87
  TFilter = Record<string, unknown>,
88
+ TSort = unknown,
88
89
  TCreateResult = TModel,
89
90
  > {
90
91
  /**
@@ -172,7 +173,7 @@ export abstract class BaseResource<
172
173
  * @returns Paginated response
173
174
  */
174
175
  abstract list(
175
- options?: ListOptions<TFilter>
176
+ options?: ListOptions<TFilter, TSort>
176
177
  ): Promise<PaginatedResponse<TModel>>;
177
178
 
178
179
  // ===========================
@@ -244,12 +245,13 @@ export abstract class BaseResource<
244
245
  * ```
245
246
  */
246
247
  protected createIterator<T = TModel>(
247
- options?: IterateOptions<TFilter>
248
+ options?: IterateOptions<TFilter, TSort>
248
249
  ): AsyncGenerator<T, void, undefined> {
249
250
  return createPaginatedIterator<T>(
250
251
  (pagination) =>
251
252
  this.list({
252
253
  filter: options?.filter,
254
+ sort: options?.sort,
253
255
  ...pagination,
254
256
  }) as unknown as Promise<PaginatedResponse<T>>,
255
257
  { limit: options?.pageSize }
@@ -267,10 +269,12 @@ export abstract class BaseResource<
267
269
  *
268
270
  * @typeParam TModel - The model type returned by this resource
269
271
  * @typeParam TFilter - Filter type for list operations
272
+ * @typeParam TSort - Sort type for list operations
270
273
  */
271
274
  export abstract class ReadOnlyResource<
272
275
  TModel,
273
276
  TFilter = Record<string, unknown>,
277
+ TSort = unknown,
274
278
  > {
275
279
  protected readonly trpc: TRPCClient;
276
280
 
@@ -287,7 +291,7 @@ export abstract class ReadOnlyResource<
287
291
  * Lists resources with optional filtering and pagination
288
292
  */
289
293
  abstract list(
290
- options?: ListOptions<TFilter>
294
+ options?: ListOptions<TFilter, TSort>
291
295
  ): Promise<PaginatedResponse<TModel>>;
292
296
 
293
297
  /**
@@ -308,12 +312,13 @@ export abstract class ReadOnlyResource<
308
312
  * Creates an async iterator for paginated results
309
313
  */
310
314
  protected createIterator<T = TModel>(
311
- options?: IterateOptions<TFilter>
315
+ options?: IterateOptions<TFilter, TSort>
312
316
  ): AsyncGenerator<T, void, undefined> {
313
317
  return createPaginatedIterator<T>(
314
318
  (pagination) =>
315
319
  this.list({
316
320
  filter: options?.filter,
321
+ sort: options?.sort,
317
322
  ...pagination,
318
323
  }) as unknown as Promise<PaginatedResponse<T>>,
319
324
  { limit: options?.pageSize }
@@ -21,6 +21,7 @@ import type {
21
21
  CreateBankAccountInput,
22
22
  UpdateBankAccountInput,
23
23
  ClientFilter,
24
+ ClientSort,
24
25
  ListOptions,
25
26
  PaginatedResponse,
26
27
  AtomicBatchResult,
@@ -112,11 +113,14 @@ export interface ClientIncludeMap {
112
113
  * }
113
114
  * ```
114
115
  */
115
- export class ClientsResource extends BaseResource<
116
+ export class ClientsResource<
117
+ TSort = ClientSort,
118
+ > extends BaseResource<
116
119
  Client,
117
120
  CreateClientInput,
118
121
  UpdateClientInput,
119
- ClientFilter
122
+ ClientFilter,
123
+ TSort
120
124
  > {
121
125
  // ─────────────────────────────────────────────────────────────────
122
126
  // CRUD Operations
@@ -256,10 +260,12 @@ export class ClientsResource extends BaseResource<
256
260
  * ```
257
261
  */
258
262
  async list(
259
- options?: ListOptions<ClientFilter> & { includePrimaryContacts?: boolean }
263
+ options?: ListOptions<ClientFilter, TSort> & { includePrimaryContacts?: boolean }
260
264
  ): Promise<PaginatedResponse<Client>> {
261
265
  const response = await this.execute(() =>
262
- this.trpc.clients.list.query(options)
266
+ this.trpc.clients.list.query(
267
+ options as ListOptions<ClientFilter, ClientSort> & { includePrimaryContacts?: boolean }
268
+ )
263
269
  );
264
270
 
265
271
  return {
@@ -10,6 +10,7 @@ import type {
10
10
  UpdateContactMethodInput,
11
11
  ContactMethodType,
12
12
  ContactMethodFilter,
13
+ ContactMethodSort,
13
14
  ListOptions,
14
15
  PaginatedResponse,
15
16
  AtomicBatchResult,
@@ -52,7 +53,8 @@ export class ContactMethodsResource extends BaseResource<
52
53
  ContactMethod,
53
54
  CreateContactMethodInput,
54
55
  UpdateContactMethodInput,
55
- ContactMethodFilter
56
+ ContactMethodFilter,
57
+ ContactMethodSort
56
58
  > {
57
59
  // ─────────────────────────────────────────────────────────────────
58
60
  // CRUD Operations
@@ -145,7 +147,7 @@ export class ContactMethodsResource extends BaseResource<
145
147
  * @returns Paginated list of ContactMethods
146
148
  */
147
149
  async list(
148
- options?: ListOptions<ContactMethodFilter>
150
+ options?: ListOptions<ContactMethodFilter, ContactMethodSort>
149
151
  ): Promise<PaginatedResponse<ContactMethod>> {
150
152
  const response = await this.execute(() =>
151
153
  this.trpc.contactMethods.list.query(options)
@@ -8,6 +8,7 @@
8
8
  import type {
9
9
  PaginatedResponse,
10
10
  DocumentFilter,
11
+ DocumentSort,
11
12
  CreateDocumentInput,
12
13
  UpdateDocumentInput,
13
14
  ListOptions,
@@ -23,6 +24,14 @@ import {
23
24
  import { z } from "zod";
24
25
  import { Document, type DocumentData } from "../models/Document";
25
26
  import { BaseResource } from "./base";
27
+ import {
28
+ uploadToS3,
29
+ normalizeFile,
30
+ validateFileSize,
31
+ type UploadableFile,
32
+ type ProgressCallback,
33
+ } from "../utils/upload";
34
+ import { UploadError } from "../errors/upload";
26
35
 
27
36
  // ─────────────────────────────────────────────────────────────────
28
37
  // Types
@@ -44,13 +53,51 @@ export interface PartialBatchResult<T> {
44
53
  }
45
54
 
46
55
  /**
47
- * Result of creating a document, including presigned upload URL.
56
+ * Result of creating a document.
57
+ *
58
+ * - With contentType: Returns document + presigned upload URL
59
+ * - Without contentType: Returns document only (no-file document)
48
60
  */
49
61
  export interface CreateDocumentResult {
50
62
  /** The created document */
51
63
  document: Document;
52
- /** Presigned URL for uploading the file */
53
- upload: PresignedUploadUrl;
64
+ /** Presigned URL for uploading the file (only for file uploads) */
65
+ upload?: PresignedUploadUrl;
66
+ }
67
+
68
+ /**
69
+ * Input for uploading a document file.
70
+ * Combines document metadata with upload options.
71
+ */
72
+ export type UploadDocumentInput = Omit<CreateDocumentInput, "contentType"> & {
73
+ /** Optional content type override. If not provided, will be inferred from file. */
74
+ contentType?: string;
75
+ };
76
+
77
+ /**
78
+ * Options for the upload operation.
79
+ */
80
+ export interface UploadOptions {
81
+ /**
82
+ * Progress callback, called with a value from 0 to 1.
83
+ * Only works in browser environments.
84
+ */
85
+ onProgress?: ProgressCallback;
86
+
87
+ /**
88
+ * AbortSignal for cancelling the upload.
89
+ * @example
90
+ * const controller = new AbortController();
91
+ * sdk.documents.upload(file, data, { signal: controller.signal });
92
+ * // Later: controller.abort();
93
+ */
94
+ signal?: AbortSignal;
95
+
96
+ /**
97
+ * Upload timeout in milliseconds.
98
+ * @default 300000 (5 minutes)
99
+ */
100
+ timeout?: number;
54
101
  }
55
102
 
56
103
  // ─────────────────────────────────────────────────────────────────
@@ -82,6 +129,7 @@ export class DocumentsResource extends BaseResource<
82
129
  CreateDocumentInput,
83
130
  UpdateDocumentInput,
84
131
  DocumentFilter,
132
+ DocumentSort,
85
133
  CreateDocumentResult
86
134
  > {
87
135
  // ─────────────────────────────────────────────────────────────────
@@ -169,6 +217,138 @@ export class DocumentsResource extends BaseResource<
169
217
  return this.instantiate(response as DocumentData);
170
218
  }
171
219
 
220
+ // ─────────────────────────────────────────────────────────────────
221
+ // Upload (High-Level Helper)
222
+ // ─────────────────────────────────────────────────────────────────
223
+
224
+ /**
225
+ * Uploads a file and creates a document in one operation.
226
+ *
227
+ * This is a convenience method that combines:
228
+ * 1. Creating a document record with presigned URL
229
+ * 2. Uploading the file directly to storage
230
+ * 3. Confirming the upload
231
+ *
232
+ * For more control over the upload process, use `create()`, manual upload,
233
+ * and `confirmUpload()` separately.
234
+ *
235
+ * @param file - The file to upload (File, Blob, or UploadableFile)
236
+ * @param data - Document metadata (clientId, jurisdiction, type, etc.)
237
+ * @param options - Upload options (progress callback, abort signal, timeout)
238
+ * @returns The created and uploaded document
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Simple upload
243
+ * const document = await sdk.documents.upload(file, {
244
+ * clientId: "client-123",
245
+ * jurisdiction: "MX",
246
+ * type: "ine_front",
247
+ * });
248
+ *
249
+ * // With progress tracking
250
+ * const document = await sdk.documents.upload(file, {
251
+ * clientId: "client-123",
252
+ * jurisdiction: "MX",
253
+ * type: "ine_front",
254
+ * }, {
255
+ * onProgress: (progress) => {
256
+ * console.log(`Upload: ${Math.round(progress * 100)}%`);
257
+ * },
258
+ * });
259
+ *
260
+ * // With abort support
261
+ * const controller = new AbortController();
262
+ * const uploadPromise = sdk.documents.upload(file, data, {
263
+ * signal: controller.signal,
264
+ * });
265
+ *
266
+ * // Cancel the upload
267
+ * controller.abort();
268
+ * ```
269
+ *
270
+ * @throws {FileTooLargeError} If file exceeds 25 MB limit
271
+ * @throws {UploadError} If upload fails at any stage
272
+ * @throws {UploadAbortedError} If upload is cancelled via AbortSignal
273
+ * @throws {UploadTimeoutError} If upload times out
274
+ */
275
+ async upload(
276
+ file: File | Blob | UploadableFile,
277
+ data: UploadDocumentInput,
278
+ options: UploadOptions = {}
279
+ ): Promise<Document> {
280
+ const { onProgress, signal, timeout } = options;
281
+
282
+ // Normalize file input
283
+ const normalizedFile = normalizeFile(file);
284
+
285
+ // Validate file size before starting
286
+ validateFileSize(normalizedFile.size);
287
+
288
+ // Check if already aborted
289
+ if (signal?.aborted) {
290
+ throw new UploadError("Upload was aborted before starting", "request");
291
+ }
292
+
293
+ // Determine content type (use provided or infer from file)
294
+ const contentType = data.contentType || normalizedFile.type;
295
+ if (!contentType || contentType === "application/octet-stream") {
296
+ throw new UploadError(
297
+ "Could not determine file content type. Please provide contentType explicitly.",
298
+ "request"
299
+ );
300
+ }
301
+
302
+ // Validate content type is allowed
303
+ const allowedTypes = [
304
+ "image/jpeg",
305
+ "image/png",
306
+ "image/webp",
307
+ "application/pdf",
308
+ ] as const;
309
+ type AllowedContentType = (typeof allowedTypes)[number];
310
+
311
+ if (!allowedTypes.includes(contentType as AllowedContentType)) {
312
+ throw new UploadError(
313
+ `Invalid file type: ${contentType}. Allowed types: ${allowedTypes.join(", ")}`,
314
+ "request"
315
+ );
316
+ }
317
+
318
+ // Step 1: Create document and get presigned URL
319
+ const createInput: CreateDocumentInput = {
320
+ ...data,
321
+ contentType: contentType as AllowedContentType,
322
+ };
323
+
324
+ const { document, upload } = await this.create(createInput);
325
+
326
+ // upload should always be present when contentType is provided
327
+ if (!upload) {
328
+ throw new UploadError(
329
+ "Server did not return upload URL. This should not happen.",
330
+ "request"
331
+ );
332
+ }
333
+
334
+ // Step 2: Upload file to S3
335
+ // Note: If upload fails, the document remains in pending_upload status
336
+ // and will be cleaned up by the orphan document cleanup job
337
+ await uploadToS3(normalizedFile, upload, {
338
+ onProgress,
339
+ signal,
340
+ timeout,
341
+ });
342
+
343
+ // Step 3: Confirm upload
344
+ return this.confirmUpload({
345
+ id: document.id,
346
+ filename: normalizedFile.name,
347
+ contentType,
348
+ size: normalizedFile.size,
349
+ });
350
+ }
351
+
172
352
  /**
173
353
  * Gets a presigned URL for downloading/viewing a document.
174
354
  *
@@ -285,7 +465,7 @@ export class DocumentsResource extends BaseResource<
285
465
  * @returns Paginated list of documents
286
466
  */
287
467
  async list(
288
- options?: ListOptions<DocumentFilter>
468
+ options?: ListOptions<DocumentFilter, DocumentSort>
289
469
  ): Promise<PaginatedResponse<Document>> {
290
470
  const response = await this.execute(() =>
291
471
  this.trpc.documents.list.query(options)
@@ -335,7 +515,7 @@ export class DocumentsResource extends BaseResource<
335
515
  * @yields Documents one at a time
336
516
  */
337
517
  async *iterate(
338
- options?: ListOptions<DocumentFilter>
518
+ options?: ListOptions<DocumentFilter, DocumentSort>
339
519
  ): AsyncGenerator<Document, void, unknown> {
340
520
  let cursor: string | undefined;
341
521
  let hasMore = true;
@@ -29,7 +29,12 @@ export {
29
29
  export { AddressesResource } from "./addresses";
30
30
  export { ContactMethodsResource } from "./contact-methods";
31
31
  export { BankAccountsResource } from "./bank-accounts";
32
- export { DocumentsResource, type CreateDocumentResult } from "./documents";
32
+ export {
33
+ DocumentsResource,
34
+ type CreateDocumentResult,
35
+ type UploadDocumentInput,
36
+ type UploadOptions,
37
+ } from "./documents";
33
38
 
34
39
  // Mexico-scoped resources
35
40
  export * from "./mex";
@@ -11,6 +11,7 @@ import type {
11
11
  CreateClientInput,
12
12
  UpdateClientInput,
13
13
  ClientFilter,
14
+ ClientSort,
14
15
  ListOptions,
15
16
  PaginatedResponse,
16
17
  CreateAVIClientInput,
@@ -31,12 +32,15 @@ import type {
31
32
  SyncResult,
32
33
  MexClientFilter,
33
34
  AVIClientFilter,
35
+ AVIClientSort,
34
36
  } from "@artu-ai/shared";
35
37
  import {
36
38
  CodigoActividad,
37
39
  createAVIClientInputSchema,
38
40
  updateAVIClientInputSchema,
39
41
  linkedClientSchema,
42
+ transformSort,
43
+ aviClientFieldMapping,
40
44
  } from "@artu-ai/shared";
41
45
  import { MexClientsResource } from "../../clients";
42
46
  import { type BatchOptions, type ClientIncludeMap } from "../../../clients";
@@ -81,7 +85,7 @@ import {
81
85
  * console.log(client.username);
82
86
  * ```
83
87
  */
84
- export class AVIClientsResource extends MexClientsResource {
88
+ export class AVIClientsResource extends MexClientsResource<AVIClientSort> {
85
89
  // ─────────────────────────────────────────────────────────────────
86
90
  // CRUD Operations
87
91
  // ─────────────────────────────────────────────────────────────────
@@ -158,14 +162,16 @@ export class AVIClientsResource extends MexClientsResource {
158
162
  * ```
159
163
  */
160
164
  async list(
161
- options?: ListOptions<AVIClientFilter>
165
+ options?: ListOptions<AVIClientFilter, AVIClientSort>
162
166
  ): Promise<PaginatedResponse<MexAVIClient>> {
163
167
  const scopedFilter = this.applyScopeToFilter(options?.filter);
168
+ const scopedSort = this.applyScopeToSort(options?.sort);
164
169
 
165
170
  const response = await this.execute(() =>
166
171
  this.trpc.clients.list.query({
167
172
  ...options,
168
173
  filter: scopedFilter,
174
+ sort: scopedSort,
169
175
  })
170
176
  );
171
177
 
@@ -386,8 +392,12 @@ export class AVIClientsResource extends MexClientsResource {
386
392
  data: {
387
393
  client?: UpdateAVIClientInput;
388
394
  addresses?: SyncItem<UpdateMexAddressInput | CreateMexAddressInput>[];
389
- contactMethods?: SyncItem<UpdateContactMethodInput | CreateContactMethodInput>[];
390
- bankAccounts?: SyncItem<UpdateBankAccountInput | CreateBankAccountInput>[];
395
+ contactMethods?: SyncItem<
396
+ UpdateContactMethodInput | CreateContactMethodInput
397
+ >[];
398
+ bankAccounts?: SyncItem<
399
+ UpdateBankAccountInput | CreateBankAccountInput
400
+ >[];
391
401
  linkedClients?: LinkedClientInput[];
392
402
  },
393
403
  options?: { replaceMode?: boolean }
@@ -430,7 +440,9 @@ export class AVIClientsResource extends MexClientsResource {
430
440
  * Extracts AVI-specific fields (username) from root level and nests them
431
441
  * under jurisdictions.MX.actividadVulnerable.AVI.
432
442
  */
433
- protected override applyScopeToFilter(filter?: AVIClientFilter): ClientFilter {
443
+ protected override applyScopeToFilter(
444
+ filter?: AVIClientFilter
445
+ ): ClientFilter {
434
446
  if (!filter) {
435
447
  return super.applyScopeToFilter(undefined);
436
448
  }
@@ -439,9 +451,7 @@ export class AVIClientsResource extends MexClientsResource {
439
451
  const { username, ...mexFilter } = filter;
440
452
 
441
453
  // Let parent handle MX fields
442
- const nestedFilter = super.applyScopeToFilter(
443
- mexFilter as MexClientFilter
444
- );
454
+ const nestedFilter = super.applyScopeToFilter(mexFilter as MexClientFilter);
445
455
 
446
456
  // Only add AVI activity filter if username is provided
447
457
  if (username !== undefined) {
@@ -467,6 +477,18 @@ export class AVIClientsResource extends MexClientsResource {
467
477
  return nestedFilter;
468
478
  }
469
479
 
480
+ /**
481
+ * Transforms a flattened AVIClientSort to nested ClientSort format.
482
+ *
483
+ * Maps flattened field names (username, rfc, curp) to their full API paths.
484
+ */
485
+ protected override applyScopeToSort(sort?: AVIClientSort): ClientSort | undefined {
486
+ if (!sort || sort.length === 0) {
487
+ return undefined;
488
+ }
489
+ return transformSort(sort, aviClientFieldMapping);
490
+ }
491
+
470
492
  /**
471
493
  * Transforms flattened AVI input to nested API format.
472
494
  */