factuplan 0.2.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,6 +129,27 @@ const { url } = await factuplan.invoices.downloadXml('invoice-id');
129
129
  const { url } = await factuplan.invoices.downloadPdf('invoice-id');
130
130
  ```
131
131
 
132
+ ### Importar factura ya autorizada por el SRI
133
+
134
+ Si tienes una factura que ya fue autorizada directamente por el SRI (no a través de Factuplan), puedes importarla para almacenarla en tu cuenta y generar el PDF (RIDE):
135
+
136
+ ```typescript
137
+ const result = await factuplan.invoices.importByAccessKey({
138
+ accessKey: '1512202501095019440700120010020000000116488711218',
139
+ });
140
+
141
+ console.log(result.id); // ID interno del comprobante
142
+ console.log(result.accessKey); // Clave de acceso SRI
143
+ console.log(result.sequential); // Número secuencial
144
+ console.log(result.status); // 'AUTHORIZED'
145
+ console.log(result.total); // Total del comprobante
146
+
147
+ // El PDF se genera automáticamente. Descárgalo una vez listo:
148
+ const { url } = await factuplan.invoices.downloadPdf(result.id);
149
+ ```
150
+
151
+ > **Nota:** Este método no envía el comprobante al SRI ni envía correo al cliente. Solo importa y genera el PDF.
152
+
132
153
  ### Firmar y autorizar XML (Modo B)
133
154
 
134
155
  Si ya tienes tu XML generado (sin firmar), puedes enviarlo para que Factuplan lo firme con tu certificado y lo autorice ante el SRI:
@@ -152,6 +173,35 @@ const status = await factuplan.invoices.getStatus(result.id);
152
173
  const { url } = await factuplan.invoices.downloadXml(result.id);
153
174
  ```
154
175
 
176
+ ### Solo firmar XML (Modo C)
177
+
178
+ Firma el XML con tu certificado sin enviarlo al SRI:
179
+
180
+ ```typescript
181
+ const { signedXml } = await factuplan.invoices.signOnly({ xml });
182
+ ```
183
+
184
+ ### Validar XML
185
+
186
+ Valida la estructura de un XML sin procesarlo:
187
+
188
+ ```typescript
189
+ const { valid, errors } = await factuplan.invoices.validateXml({ xml });
190
+ if (!valid) {
191
+ console.log('Errores:', errors);
192
+ }
193
+ ```
194
+
195
+ ### Verificar autorizacion
196
+
197
+ Consulta el estado de autorizacion de un comprobante por su clave de acceso:
198
+
199
+ ```typescript
200
+ const result = await factuplan.invoices.verify('0104202601099337815000110010010000000011234567890');
201
+ console.log(result.authorized); // true/false
202
+ console.log(result.authorizationNumber); // Numero de autorizacion
203
+ ```
204
+
155
205
  ### Uso y certificado
156
206
 
157
207
  ```typescript
package/dist/index.d.mts CHANGED
@@ -115,6 +115,10 @@ interface CreateInvoiceInput {
115
115
  paymentMethod?: string;
116
116
  additionalInfo?: Record<string, string>;
117
117
  }
118
+ interface ImportByAccessKeyInput {
119
+ /** 49-digit SRI access key (claveAcceso) of an already-authorized invoice */
120
+ accessKey: string;
121
+ }
118
122
  interface Invoice {
119
123
  id: string;
120
124
  accessKey: string;
@@ -142,6 +146,30 @@ interface SignAndAuthorizeResponse {
142
146
  accessKey: string;
143
147
  status: string;
144
148
  }
149
+ interface SignOnlyInput {
150
+ /** Unsigned XML string */
151
+ xml: string;
152
+ }
153
+ interface SignOnlyResponse {
154
+ signedXml: string;
155
+ }
156
+ interface ValidateXmlInput {
157
+ /** XML string to validate */
158
+ xml: string;
159
+ }
160
+ interface ValidateXmlResponse {
161
+ valid: boolean;
162
+ errors: string[];
163
+ }
164
+ interface VerifyResponse {
165
+ authorized: boolean;
166
+ authorizationNumber?: string;
167
+ authorizationDate?: string;
168
+ messages?: Array<{
169
+ code?: string;
170
+ message?: string;
171
+ }>;
172
+ }
145
173
  interface UsageResponse {
146
174
  apiKeyId: string;
147
175
  month: string;
@@ -158,6 +186,24 @@ interface CertificateStatus {
158
186
  legalName?: string;
159
187
  expiresAt?: string;
160
188
  }
189
+ interface WebhookEvent {
190
+ id: string;
191
+ event: string;
192
+ timestamp: string;
193
+ data: WebhookReceiptData;
194
+ webhookId: string;
195
+ attempt: number;
196
+ }
197
+ interface WebhookReceiptData {
198
+ receiptId: string;
199
+ type: string;
200
+ accessKey: string;
201
+ authorizationNumber: string;
202
+ documentNumber: string;
203
+ total: string;
204
+ customerName: string;
205
+ customerIdentification: string;
206
+ }
161
207
  interface FactuplanOptions {
162
208
  /** Base URL of the API (default: https://api.factuplan.com/api/v1) */
163
209
  baseUrl?: string;
@@ -165,10 +211,10 @@ interface FactuplanOptions {
165
211
  timeout?: number;
166
212
  }
167
213
 
168
- type Requester$2 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
214
+ type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
169
215
  declare class CustomersResource {
170
216
  private request;
171
- constructor(request: Requester$2);
217
+ constructor(request: Requester$3);
172
218
  create(input: CreateCustomerInput): Promise<Customer>;
173
219
  list(params?: CustomerListParams): Promise<PaginatedResponse<Customer>>;
174
220
  get(id: string): Promise<Customer>;
@@ -176,22 +222,26 @@ declare class CustomersResource {
176
222
  delete(id: string): Promise<void>;
177
223
  }
178
224
 
179
- type Requester$1 = (method: string, path: string, body?: unknown) => Promise<unknown>;
225
+ type Requester$2 = (method: string, path: string, body?: unknown) => Promise<unknown>;
180
226
  declare class InvoicesResource {
181
227
  private request;
182
- constructor(request: Requester$1);
228
+ constructor(request: Requester$2);
183
229
  create(input: CreateInvoiceInput): Promise<Invoice>;
184
230
  signAndAuthorize(input: SignAndAuthorizeInput): Promise<SignAndAuthorizeResponse>;
231
+ signOnly(input: SignOnlyInput): Promise<SignOnlyResponse>;
232
+ validateXml(input: ValidateXmlInput): Promise<ValidateXmlResponse>;
233
+ verify(accessKey: string): Promise<VerifyResponse>;
185
234
  get(id: string): Promise<Record<string, unknown>>;
186
235
  getStatus(id: string): Promise<InvoiceStatus>;
187
236
  downloadXml(id: string): Promise<DownloadUrlResponse>;
188
237
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
238
+ importByAccessKey(input: ImportByAccessKeyInput): Promise<Invoice>;
189
239
  }
190
240
 
191
- type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
241
+ type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
192
242
  declare class ProductsResource {
193
243
  private request;
194
- constructor(request: Requester);
244
+ constructor(request: Requester$1);
195
245
  create(input: CreateProductInput): Promise<Product>;
196
246
  list(params?: ProductListParams): Promise<PaginatedResponse<Product>>;
197
247
  get(id: string): Promise<Product>;
@@ -199,6 +249,20 @@ declare class ProductsResource {
199
249
  delete(id: string): Promise<void>;
200
250
  }
201
251
 
252
+ type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
253
+ declare class WebhooksResource {
254
+ private readonly request;
255
+ constructor(requester: Requester);
256
+ /**
257
+ * Verify that a receipt (document) exists in the API.
258
+ * This is a second layer of verification beyond signature checking.
259
+ *
260
+ * @param receiptId - The receipt ID from the webhook payload
261
+ * @returns The receipt object if it exists, or `null` if not found
262
+ */
263
+ verifyReceipt(receiptId: string): Promise<Record<string, unknown> | null>;
264
+ }
265
+
202
266
  declare class Factuplan {
203
267
  private readonly apiKey;
204
268
  private readonly baseUrl;
@@ -206,6 +270,8 @@ declare class Factuplan {
206
270
  readonly customers: CustomersResource;
207
271
  readonly products: ProductsResource;
208
272
  readonly invoices: InvoicesResource;
273
+ readonly webhooks: WebhooksResource;
274
+ static readonly webhooks: typeof WebhooksResource;
209
275
  constructor(apiKey: string, options?: FactuplanOptions);
210
276
  usage(): Promise<UsageResponse>;
211
277
  certificateStatus(): Promise<CertificateStatus>;
@@ -225,4 +291,4 @@ declare class RateLimitError extends FactuplanError {
225
291
  constructor(message?: string);
226
292
  }
227
293
 
228
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse };
294
+ 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 };
package/dist/index.d.ts CHANGED
@@ -115,6 +115,10 @@ interface CreateInvoiceInput {
115
115
  paymentMethod?: string;
116
116
  additionalInfo?: Record<string, string>;
117
117
  }
118
+ interface ImportByAccessKeyInput {
119
+ /** 49-digit SRI access key (claveAcceso) of an already-authorized invoice */
120
+ accessKey: string;
121
+ }
118
122
  interface Invoice {
119
123
  id: string;
120
124
  accessKey: string;
@@ -142,6 +146,30 @@ interface SignAndAuthorizeResponse {
142
146
  accessKey: string;
143
147
  status: string;
144
148
  }
149
+ interface SignOnlyInput {
150
+ /** Unsigned XML string */
151
+ xml: string;
152
+ }
153
+ interface SignOnlyResponse {
154
+ signedXml: string;
155
+ }
156
+ interface ValidateXmlInput {
157
+ /** XML string to validate */
158
+ xml: string;
159
+ }
160
+ interface ValidateXmlResponse {
161
+ valid: boolean;
162
+ errors: string[];
163
+ }
164
+ interface VerifyResponse {
165
+ authorized: boolean;
166
+ authorizationNumber?: string;
167
+ authorizationDate?: string;
168
+ messages?: Array<{
169
+ code?: string;
170
+ message?: string;
171
+ }>;
172
+ }
145
173
  interface UsageResponse {
146
174
  apiKeyId: string;
147
175
  month: string;
@@ -158,6 +186,24 @@ interface CertificateStatus {
158
186
  legalName?: string;
159
187
  expiresAt?: string;
160
188
  }
189
+ interface WebhookEvent {
190
+ id: string;
191
+ event: string;
192
+ timestamp: string;
193
+ data: WebhookReceiptData;
194
+ webhookId: string;
195
+ attempt: number;
196
+ }
197
+ interface WebhookReceiptData {
198
+ receiptId: string;
199
+ type: string;
200
+ accessKey: string;
201
+ authorizationNumber: string;
202
+ documentNumber: string;
203
+ total: string;
204
+ customerName: string;
205
+ customerIdentification: string;
206
+ }
161
207
  interface FactuplanOptions {
162
208
  /** Base URL of the API (default: https://api.factuplan.com/api/v1) */
163
209
  baseUrl?: string;
@@ -165,10 +211,10 @@ interface FactuplanOptions {
165
211
  timeout?: number;
166
212
  }
167
213
 
168
- type Requester$2 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
214
+ type Requester$3 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
169
215
  declare class CustomersResource {
170
216
  private request;
171
- constructor(request: Requester$2);
217
+ constructor(request: Requester$3);
172
218
  create(input: CreateCustomerInput): Promise<Customer>;
173
219
  list(params?: CustomerListParams): Promise<PaginatedResponse<Customer>>;
174
220
  get(id: string): Promise<Customer>;
@@ -176,22 +222,26 @@ declare class CustomersResource {
176
222
  delete(id: string): Promise<void>;
177
223
  }
178
224
 
179
- type Requester$1 = (method: string, path: string, body?: unknown) => Promise<unknown>;
225
+ type Requester$2 = (method: string, path: string, body?: unknown) => Promise<unknown>;
180
226
  declare class InvoicesResource {
181
227
  private request;
182
- constructor(request: Requester$1);
228
+ constructor(request: Requester$2);
183
229
  create(input: CreateInvoiceInput): Promise<Invoice>;
184
230
  signAndAuthorize(input: SignAndAuthorizeInput): Promise<SignAndAuthorizeResponse>;
231
+ signOnly(input: SignOnlyInput): Promise<SignOnlyResponse>;
232
+ validateXml(input: ValidateXmlInput): Promise<ValidateXmlResponse>;
233
+ verify(accessKey: string): Promise<VerifyResponse>;
185
234
  get(id: string): Promise<Record<string, unknown>>;
186
235
  getStatus(id: string): Promise<InvoiceStatus>;
187
236
  downloadXml(id: string): Promise<DownloadUrlResponse>;
188
237
  downloadPdf(id: string): Promise<DownloadUrlResponse>;
238
+ importByAccessKey(input: ImportByAccessKeyInput): Promise<Invoice>;
189
239
  }
190
240
 
191
- type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
241
+ type Requester$1 = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
192
242
  declare class ProductsResource {
193
243
  private request;
194
- constructor(request: Requester);
244
+ constructor(request: Requester$1);
195
245
  create(input: CreateProductInput): Promise<Product>;
196
246
  list(params?: ProductListParams): Promise<PaginatedResponse<Product>>;
197
247
  get(id: string): Promise<Product>;
@@ -199,6 +249,20 @@ declare class ProductsResource {
199
249
  delete(id: string): Promise<void>;
200
250
  }
201
251
 
252
+ type Requester = (method: string, path: string, body?: unknown, params?: Record<string, string | number | undefined>) => Promise<unknown>;
253
+ declare class WebhooksResource {
254
+ private readonly request;
255
+ constructor(requester: Requester);
256
+ /**
257
+ * Verify that a receipt (document) exists in the API.
258
+ * This is a second layer of verification beyond signature checking.
259
+ *
260
+ * @param receiptId - The receipt ID from the webhook payload
261
+ * @returns The receipt object if it exists, or `null` if not found
262
+ */
263
+ verifyReceipt(receiptId: string): Promise<Record<string, unknown> | null>;
264
+ }
265
+
202
266
  declare class Factuplan {
203
267
  private readonly apiKey;
204
268
  private readonly baseUrl;
@@ -206,6 +270,8 @@ declare class Factuplan {
206
270
  readonly customers: CustomersResource;
207
271
  readonly products: ProductsResource;
208
272
  readonly invoices: InvoicesResource;
273
+ readonly webhooks: WebhooksResource;
274
+ static readonly webhooks: typeof WebhooksResource;
209
275
  constructor(apiKey: string, options?: FactuplanOptions);
210
276
  usage(): Promise<UsageResponse>;
211
277
  certificateStatus(): Promise<CertificateStatus>;
@@ -225,4 +291,4 @@ declare class RateLimitError extends FactuplanError {
225
291
  constructor(message?: string);
226
292
  }
227
293
 
228
- export { AuthenticationError, type CertificateStatus, type CreateCustomerInput, type CreateInvoiceInput, type CreateProductInput, type Customer, type CustomerListParams, type DownloadUrlResponse, Factuplan, FactuplanError, type FactuplanOptions, type Invoice, type InvoiceCustomer, type InvoiceItem, type InvoiceStatus, type PaginatedResponse, type Product, type ProductListParams, RateLimitError, type SignAndAuthorizeInput, type SignAndAuthorizeResponse, type UpdateCustomerInput, type UpdateProductInput, type UsageResponse };
294
+ 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 };
package/dist/index.js CHANGED
@@ -83,6 +83,15 @@ var InvoicesResource = class {
83
83
  async signAndAuthorize(input) {
84
84
  return this.request("POST", "/developer/sign-and-authorize", input);
85
85
  }
86
+ async signOnly(input) {
87
+ return this.request("POST", "/developer/sign", input);
88
+ }
89
+ async validateXml(input) {
90
+ return this.request("POST", "/developer/validate-xml", input);
91
+ }
92
+ async verify(accessKey) {
93
+ return this.request("GET", `/developer/verify/${accessKey}`);
94
+ }
86
95
  async get(id) {
87
96
  return this.request("GET", `/developer/receipts/${id}`);
88
97
  }
@@ -95,6 +104,9 @@ var InvoicesResource = class {
95
104
  async downloadPdf(id) {
96
105
  return this.request("GET", `/developer/receipts/${id}/pdf`);
97
106
  }
107
+ async importByAccessKey(input) {
108
+ return this.request("POST", "/developer/invoices/import", input);
109
+ }
98
110
  };
99
111
 
100
112
  // src/resources/products.ts
@@ -119,6 +131,28 @@ var ProductsResource = class {
119
131
  }
120
132
  };
121
133
 
134
+ // src/resources/webhooks.ts
135
+ var WebhooksResource = class {
136
+ constructor(requester) {
137
+ this.request = requester;
138
+ }
139
+ /**
140
+ * Verify that a receipt (document) exists in the API.
141
+ * This is a second layer of verification beyond signature checking.
142
+ *
143
+ * @param receiptId - The receipt ID from the webhook payload
144
+ * @returns The receipt object if it exists, or `null` if not found
145
+ */
146
+ async verifyReceipt(receiptId) {
147
+ try {
148
+ const result = await this.request("GET", `/developer/receipts/${receiptId}`);
149
+ return result ?? null;
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+ };
155
+
122
156
  // src/client.ts
123
157
  var DEFAULT_BASE_URL = "https://api-rest.factuplan.com.ec/api/v1";
124
158
  var DEFAULT_TIMEOUT = 3e4;
@@ -132,6 +166,7 @@ var Factuplan = class {
132
166
  this.customers = new CustomersResource(requester);
133
167
  this.products = new ProductsResource(requester);
134
168
  this.invoices = new InvoicesResource(requester);
169
+ this.webhooks = new WebhooksResource(requester);
135
170
  }
136
171
  async usage() {
137
172
  return this.request("GET", "/developer/usage");
@@ -185,6 +220,7 @@ var Factuplan = class {
185
220
  return json;
186
221
  }
187
222
  };
223
+ Factuplan.webhooks = WebhooksResource;
188
224
  // Annotate the CommonJS export names for ESM import in node:
189
225
  0 && (module.exports = {
190
226
  AuthenticationError,
package/dist/index.mjs CHANGED
@@ -54,6 +54,15 @@ var InvoicesResource = class {
54
54
  async signAndAuthorize(input) {
55
55
  return this.request("POST", "/developer/sign-and-authorize", input);
56
56
  }
57
+ async signOnly(input) {
58
+ return this.request("POST", "/developer/sign", input);
59
+ }
60
+ async validateXml(input) {
61
+ return this.request("POST", "/developer/validate-xml", input);
62
+ }
63
+ async verify(accessKey) {
64
+ return this.request("GET", `/developer/verify/${accessKey}`);
65
+ }
57
66
  async get(id) {
58
67
  return this.request("GET", `/developer/receipts/${id}`);
59
68
  }
@@ -66,6 +75,9 @@ var InvoicesResource = class {
66
75
  async downloadPdf(id) {
67
76
  return this.request("GET", `/developer/receipts/${id}/pdf`);
68
77
  }
78
+ async importByAccessKey(input) {
79
+ return this.request("POST", "/developer/invoices/import", input);
80
+ }
69
81
  };
70
82
 
71
83
  // src/resources/products.ts
@@ -90,6 +102,28 @@ var ProductsResource = class {
90
102
  }
91
103
  };
92
104
 
105
+ // src/resources/webhooks.ts
106
+ var WebhooksResource = class {
107
+ constructor(requester) {
108
+ this.request = requester;
109
+ }
110
+ /**
111
+ * Verify that a receipt (document) exists in the API.
112
+ * This is a second layer of verification beyond signature checking.
113
+ *
114
+ * @param receiptId - The receipt ID from the webhook payload
115
+ * @returns The receipt object if it exists, or `null` if not found
116
+ */
117
+ async verifyReceipt(receiptId) {
118
+ try {
119
+ const result = await this.request("GET", `/developer/receipts/${receiptId}`);
120
+ return result ?? null;
121
+ } catch {
122
+ return null;
123
+ }
124
+ }
125
+ };
126
+
93
127
  // src/client.ts
94
128
  var DEFAULT_BASE_URL = "https://api-rest.factuplan.com.ec/api/v1";
95
129
  var DEFAULT_TIMEOUT = 3e4;
@@ -103,6 +137,7 @@ var Factuplan = class {
103
137
  this.customers = new CustomersResource(requester);
104
138
  this.products = new ProductsResource(requester);
105
139
  this.invoices = new InvoicesResource(requester);
140
+ this.webhooks = new WebhooksResource(requester);
106
141
  }
107
142
  async usage() {
108
143
  return this.request("GET", "/developer/usage");
@@ -156,6 +191,7 @@ var Factuplan = class {
156
191
  return json;
157
192
  }
158
193
  };
194
+ Factuplan.webhooks = WebhooksResource;
159
195
  export {
160
196
  AuthenticationError,
161
197
  Factuplan,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "factuplan",
3
- "version": "0.2.2",
3
+ "version": "0.5.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",
@@ -16,6 +16,7 @@
16
16
  "dist"
17
17
  ],
18
18
  "devDependencies": {
19
+ "@types/node": "^25.6.0",
19
20
  "tsup": "^8.0.0",
20
21
  "typescript": "^5.5.0"
21
22
  },