factuplan 0.8.0 → 0.11.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/dist/index.d.mts CHANGED
@@ -222,6 +222,29 @@ interface WebhookReceiptData {
222
222
  customerName: string;
223
223
  customerIdentification: string;
224
224
  }
225
+ interface VoidInvoiceResponse {
226
+ id: string;
227
+ status: string;
228
+ accessKey: string | null;
229
+ voidReason: string;
230
+ message: string;
231
+ }
232
+ interface UpdateSequentialResponse {
233
+ branchCode: string;
234
+ emissionCode: string;
235
+ invoiceSequential: number;
236
+ updatedAt: string;
237
+ }
238
+ interface CertificateUploadResponse {
239
+ hasCertificate: boolean;
240
+ isExpired?: boolean;
241
+ daysUntilExpiry?: number | null;
242
+ ruc?: string;
243
+ legalName?: string;
244
+ expiresAt?: string;
245
+ /** True if a new contribuyente was automatically created from the certificate data */
246
+ created?: boolean;
247
+ }
225
248
  interface FactuplanOptions {
226
249
  /** Base URL of the API (default: https://api-rest.factuplan.com.ec/v1) */
227
250
  baseUrl?: string;
@@ -259,6 +282,26 @@ interface QueryExternalByAccessKeyResponse {
259
282
  xmlBase64: string;
260
283
  }
261
284
 
285
+ type Requester$4 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
286
+ declare class CertificatesResource {
287
+ private request;
288
+ constructor(request: Requester$4);
289
+ /**
290
+ * Get the certificate status for the current taxpayer (requires x-taxpayer-ruc header).
291
+ */
292
+ status(): Promise<CertificateStatus>;
293
+ /**
294
+ * Upload a P12 certificate.
295
+ * If the RUC in the certificate does not yet exist as a contribuyente in your
296
+ * workspace and your plan allows it, the contribuyente is created automatically
297
+ * and linked to your API key.
298
+ *
299
+ * @param file - P12 file as a Uint8Array/Buffer (Node.js) or Blob (browser)
300
+ * @param password - Password for the P12 file
301
+ */
302
+ upload(file: Uint8Array | Blob, password: string): Promise<CertificateUploadResponse>;
303
+ }
304
+
262
305
  type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
263
306
  declare class CustomersResource {
264
307
  private request;
@@ -285,6 +328,8 @@ declare class InvoicesResource {
285
328
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
286
329
  importByAccessKey(input: ImportByAccessKeyInput): Promise<Invoice>;
287
330
  queryExternalByAccessKey(input: QueryExternalByAccessKeyInput): Promise<QueryExternalByAccessKeyResponse>;
331
+ void(id: string, reason: string): Promise<VoidInvoiceResponse>;
332
+ updateSequential(branchCode: string, emissionCode: string, invoiceSequential: number): Promise<UpdateSequentialResponse>;
288
333
  }
289
334
 
290
335
  type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
@@ -317,6 +362,7 @@ declare class Factuplan {
317
362
  private readonly baseUrl;
318
363
  private readonly timeout;
319
364
  private readonly options;
365
+ readonly certificates: CertificatesResource;
320
366
  readonly customers: CustomersResource;
321
367
  readonly products: ProductsResource;
322
368
  readonly invoices: InvoicesResource;
@@ -324,7 +370,6 @@ declare class Factuplan {
324
370
  static readonly webhooks: typeof WebhooksResource;
325
371
  constructor(apiKey: string, options?: FactuplanOptions);
326
372
  usage(): Promise<UsageResponse>;
327
- certificateStatus(): Promise<CertificateStatus>;
328
373
  private request;
329
374
  }
330
375
 
@@ -341,4 +386,4 @@ declare class RateLimitError extends FactuplanError {
341
386
  constructor(message?: string);
342
387
  }
343
388
 
344
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type ImportByAccessKeyInput, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type WebhookEvent, type WebhookReceiptData };
389
+ export { AuthenticationError, type CertificateStatus, type CertificateUploadResponse, CertificatesResource, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type ImportByAccessKeyInput, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, type QueryExternalByAccessKeyInput, type QueryExternalByAccessKeyResponse, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UpdateSequentialResponse, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type VoidInvoiceResponse, type WebhookEvent, type WebhookReceiptData };
package/dist/index.d.ts CHANGED
@@ -222,6 +222,29 @@ interface WebhookReceiptData {
222
222
  customerName: string;
223
223
  customerIdentification: string;
224
224
  }
225
+ interface VoidInvoiceResponse {
226
+ id: string;
227
+ status: string;
228
+ accessKey: string | null;
229
+ voidReason: string;
230
+ message: string;
231
+ }
232
+ interface UpdateSequentialResponse {
233
+ branchCode: string;
234
+ emissionCode: string;
235
+ invoiceSequential: number;
236
+ updatedAt: string;
237
+ }
238
+ interface CertificateUploadResponse {
239
+ hasCertificate: boolean;
240
+ isExpired?: boolean;
241
+ daysUntilExpiry?: number | null;
242
+ ruc?: string;
243
+ legalName?: string;
244
+ expiresAt?: string;
245
+ /** True if a new contribuyente was automatically created from the certificate data */
246
+ created?: boolean;
247
+ }
225
248
  interface FactuplanOptions {
226
249
  /** Base URL of the API (default: https://api-rest.factuplan.com.ec/v1) */
227
250
  baseUrl?: string;
@@ -259,6 +282,26 @@ interface QueryExternalByAccessKeyResponse {
259
282
  xmlBase64: string;
260
283
  }
261
284
 
285
+ type Requester$4 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
286
+ declare class CertificatesResource {
287
+ private request;
288
+ constructor(request: Requester$4);
289
+ /**
290
+ * Get the certificate status for the current taxpayer (requires x-taxpayer-ruc header).
291
+ */
292
+ status(): Promise<CertificateStatus>;
293
+ /**
294
+ * Upload a P12 certificate.
295
+ * If the RUC in the certificate does not yet exist as a contribuyente in your
296
+ * workspace and your plan allows it, the contribuyente is created automatically
297
+ * and linked to your API key.
298
+ *
299
+ * @param file - P12 file as a Uint8Array/Buffer (Node.js) or Blob (browser)
300
+ * @param password - Password for the P12 file
301
+ */
302
+ upload(file: Uint8Array | Blob, password: string): Promise<CertificateUploadResponse>;
303
+ }
304
+
262
305
  type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
263
306
  declare class CustomersResource {
264
307
  private request;
@@ -285,6 +328,8 @@ declare class InvoicesResource {
285
328
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
286
329
  importByAccessKey(input: ImportByAccessKeyInput): Promise<Invoice>;
287
330
  queryExternalByAccessKey(input: QueryExternalByAccessKeyInput): Promise<QueryExternalByAccessKeyResponse>;
331
+ void(id: string, reason: string): Promise<VoidInvoiceResponse>;
332
+ updateSequential(branchCode: string, emissionCode: string, invoiceSequential: number): Promise<UpdateSequentialResponse>;
288
333
  }
289
334
 
290
335
  type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
@@ -317,6 +362,7 @@ declare class Factuplan {
317
362
  private readonly baseUrl;
318
363
  private readonly timeout;
319
364
  private readonly options;
365
+ readonly certificates: CertificatesResource;
320
366
  readonly customers: CustomersResource;
321
367
  readonly products: ProductsResource;
322
368
  readonly invoices: InvoicesResource;
@@ -324,7 +370,6 @@ declare class Factuplan {
324
370
  static readonly webhooks: typeof WebhooksResource;
325
371
  constructor(apiKey: string, options?: FactuplanOptions);
326
372
  usage(): Promise<UsageResponse>;
327
- certificateStatus(): Promise<CertificateStatus>;
328
373
  private request;
329
374
  }
330
375
 
@@ -341,4 +386,4 @@ declare class RateLimitError extends FactuplanError {
341
386
  constructor(message?: string);
342
387
  }
343
388
 
344
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type ImportByAccessKeyInput, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type WebhookEvent, type WebhookReceiptData };
389
+ export { AuthenticationError, type CertificateStatus, type CertificateUploadResponse, CertificatesResource, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type ImportByAccessKeyInput, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, type QueryExternalByAccessKeyInput, type QueryExternalByAccessKeyResponse, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type SignOnlyInput, type SignOnlyResponse, type UpdateCustomerInput, type UpdateProductInput, type UpdateSequentialResponse, type UsageResponse, type ValidateXmlInput, type ValidateXmlResponse, type VerifyResponse, type VoidInvoiceResponse, type WebhookEvent, type WebhookReceiptData };
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AuthenticationError: () => AuthenticationError,
24
+ CertificatesResource: () => CertificatesResource,
24
25
  Factuplan: () => Factuplan,
25
26
  FactuplanError: () => FactuplanError,
26
27
  RateLimitError: () => RateLimitError
@@ -50,6 +51,35 @@ var RateLimitError = class extends FactuplanError {
50
51
  }
51
52
  };
52
53
 
54
+ // src/resources/certificates.ts
55
+ var CertificatesResource = class {
56
+ constructor(request) {
57
+ this.request = request;
58
+ }
59
+ /**
60
+ * Get the certificate status for the current taxpayer (requires x-taxpayer-ruc header).
61
+ */
62
+ async status() {
63
+ return this.request("GET", "/developer/certificate/status");
64
+ }
65
+ /**
66
+ * Upload a P12 certificate.
67
+ * If the RUC in the certificate does not yet exist as a contribuyente in your
68
+ * workspace and your plan allows it, the contribuyente is created automatically
69
+ * and linked to your API key.
70
+ *
71
+ * @param file - P12 file as a Uint8Array/Buffer (Node.js) or Blob (browser)
72
+ * @param password - Password for the P12 file
73
+ */
74
+ async upload(file, password) {
75
+ return this.request(
76
+ "POST",
77
+ "/developer/certificate",
78
+ { __formData: true, file, password }
79
+ );
80
+ }
81
+ };
82
+
53
83
  // src/resources/customers.ts
54
84
  var CustomersResource = class {
55
85
  constructor(request) {
@@ -114,6 +144,20 @@ var InvoicesResource = class {
114
144
  input
115
145
  );
116
146
  }
147
+ async void(id, reason) {
148
+ return this.request(
149
+ "POST",
150
+ `/developer/receipts/${id}/void`,
151
+ { reason }
152
+ );
153
+ }
154
+ async updateSequential(branchCode, emissionCode, invoiceSequential) {
155
+ return this.request(
156
+ "PATCH",
157
+ "/developer/invoices/sequential",
158
+ { branchCode, emissionCode, invoiceSequential }
159
+ );
160
+ }
117
161
  };
118
162
 
119
163
  // src/resources/products.ts
@@ -171,6 +215,7 @@ var Factuplan = class {
171
215
  this.baseUrl = (options?.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
172
216
  this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
173
217
  const requester = this.request.bind(this);
218
+ this.certificates = new CertificatesResource(requester);
174
219
  this.customers = new CustomersResource(requester);
175
220
  this.products = new ProductsResource(requester);
176
221
  this.invoices = new InvoicesResource(requester);
@@ -179,9 +224,6 @@ var Factuplan = class {
179
224
  async usage() {
180
225
  return this.request("GET", "/developer/usage");
181
226
  }
182
- async certificateStatus() {
183
- return this.request("GET", "/developer/certificate/status");
184
- }
185
227
  async request(method, path, body, params) {
186
228
  let url = `${this.baseUrl}${path}`;
187
229
  if (params) {
@@ -201,13 +243,24 @@ var Factuplan = class {
201
243
  if (this.options?.ruc) {
202
244
  headers["x-taxpayer-ruc"] = this.options.ruc;
203
245
  }
246
+ let fetchBody;
204
247
  if (body !== void 0) {
205
- headers["Content-Type"] = "application/json";
248
+ if (body !== null && typeof body === "object" && body.__formData === true) {
249
+ const { file, password } = body;
250
+ const fd = new FormData();
251
+ const blob = file instanceof Blob ? file : new Blob([file]);
252
+ fd.append("file", blob, "certificate.p12");
253
+ fd.append("password", password);
254
+ fetchBody = fd;
255
+ } else {
256
+ headers["Content-Type"] = "application/json";
257
+ fetchBody = JSON.stringify(body);
258
+ }
206
259
  }
207
260
  const response = await fetch(url, {
208
261
  method,
209
262
  headers,
210
- body: body !== void 0 ? JSON.stringify(body) : void 0,
263
+ body: fetchBody,
211
264
  signal: AbortSignal.timeout(this.timeout)
212
265
  });
213
266
  if (response.status === 204) return void 0;
@@ -235,6 +288,7 @@ Factuplan.webhooks = WebhooksResource;
235
288
  // Annotate the CommonJS export names for ESM import in node:
236
289
  0 && (module.exports = {
237
290
  AuthenticationError,
291
+ CertificatesResource,
238
292
  Factuplan,
239
293
  FactuplanError,
240
294
  RateLimitError
package/dist/index.mjs CHANGED
@@ -21,6 +21,35 @@ var RateLimitError = class extends FactuplanError {
21
21
  }
22
22
  };
23
23
 
24
+ // src/resources/certificates.ts
25
+ var CertificatesResource = class {
26
+ constructor(request) {
27
+ this.request = request;
28
+ }
29
+ /**
30
+ * Get the certificate status for the current taxpayer (requires x-taxpayer-ruc header).
31
+ */
32
+ async status() {
33
+ return this.request("GET", "/developer/certificate/status");
34
+ }
35
+ /**
36
+ * Upload a P12 certificate.
37
+ * If the RUC in the certificate does not yet exist as a contribuyente in your
38
+ * workspace and your plan allows it, the contribuyente is created automatically
39
+ * and linked to your API key.
40
+ *
41
+ * @param file - P12 file as a Uint8Array/Buffer (Node.js) or Blob (browser)
42
+ * @param password - Password for the P12 file
43
+ */
44
+ async upload(file, password) {
45
+ return this.request(
46
+ "POST",
47
+ "/developer/certificate",
48
+ { __formData: true, file, password }
49
+ );
50
+ }
51
+ };
52
+
24
53
  // src/resources/customers.ts
25
54
  var CustomersResource = class {
26
55
  constructor(request) {
@@ -85,6 +114,20 @@ var InvoicesResource = class {
85
114
  input
86
115
  );
87
116
  }
117
+ async void(id, reason) {
118
+ return this.request(
119
+ "POST",
120
+ `/developer/receipts/${id}/void`,
121
+ { reason }
122
+ );
123
+ }
124
+ async updateSequential(branchCode, emissionCode, invoiceSequential) {
125
+ return this.request(
126
+ "PATCH",
127
+ "/developer/invoices/sequential",
128
+ { branchCode, emissionCode, invoiceSequential }
129
+ );
130
+ }
88
131
  };
89
132
 
90
133
  // src/resources/products.ts
@@ -142,6 +185,7 @@ var Factuplan = class {
142
185
  this.baseUrl = (options?.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
143
186
  this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;
144
187
  const requester = this.request.bind(this);
188
+ this.certificates = new CertificatesResource(requester);
145
189
  this.customers = new CustomersResource(requester);
146
190
  this.products = new ProductsResource(requester);
147
191
  this.invoices = new InvoicesResource(requester);
@@ -150,9 +194,6 @@ var Factuplan = class {
150
194
  async usage() {
151
195
  return this.request("GET", "/developer/usage");
152
196
  }
153
- async certificateStatus() {
154
- return this.request("GET", "/developer/certificate/status");
155
- }
156
197
  async request(method, path, body, params) {
157
198
  let url = `${this.baseUrl}${path}`;
158
199
  if (params) {
@@ -172,13 +213,24 @@ var Factuplan = class {
172
213
  if (this.options?.ruc) {
173
214
  headers["x-taxpayer-ruc"] = this.options.ruc;
174
215
  }
216
+ let fetchBody;
175
217
  if (body !== void 0) {
176
- headers["Content-Type"] = "application/json";
218
+ if (body !== null && typeof body === "object" && body.__formData === true) {
219
+ const { file, password } = body;
220
+ const fd = new FormData();
221
+ const blob = file instanceof Blob ? file : new Blob([file]);
222
+ fd.append("file", blob, "certificate.p12");
223
+ fd.append("password", password);
224
+ fetchBody = fd;
225
+ } else {
226
+ headers["Content-Type"] = "application/json";
227
+ fetchBody = JSON.stringify(body);
228
+ }
177
229
  }
178
230
  const response = await fetch(url, {
179
231
  method,
180
232
  headers,
181
- body: body !== void 0 ? JSON.stringify(body) : void 0,
233
+ body: fetchBody,
182
234
  signal: AbortSignal.timeout(this.timeout)
183
235
  });
184
236
  if (response.status === 204) return void 0;
@@ -205,6 +257,7 @@ var Factuplan = class {
205
257
  Factuplan.webhooks = WebhooksResource;
206
258
  export {
207
259
  AuthenticationError,
260
+ CertificatesResource,
208
261
  Factuplan,
209
262
  FactuplanError,
210
263
  RateLimitError
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "factuplan",
3
- "version": "0.8.0",
3
+ "version": "0.11.0",
4
4
  "description": "Official Factuplan SDK for JavaScript & TypeScript — Create electronic invoices for Ecuador (SRI)",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",