@genvoris/node 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Genvoris
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Genvoris
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,132 +1,132 @@
1
- # @genvoris/node
2
-
3
- Official Node.js SDK for the [Genvoris Virtual Try-On API](https://docs.genvoris.org).
4
-
5
- ## Requirements
6
-
7
- Node.js **18** or higher (uses native `fetch`).
8
-
9
- ## Installation
10
-
11
- ```bash
12
- npm install @genvoris/node
13
- ```
14
-
15
- ## Quick start
16
-
17
- ```ts
18
- import Genvoris from '@genvoris/node';
19
-
20
- const gv = new Genvoris({ apiKey: process.env.GENVORIS_API_KEY! });
21
-
22
- // Create a customer
23
- const customer = await gv.customers.create({
24
- externalId: 'user_42',
25
- email: 'shopper@example.com',
26
- planId: 'pln_xxxxxxxx',
27
- });
28
-
29
- // Mint a session token for the widget
30
- const session = await gv.sessions.mint({ customerId: customer.id });
31
- // → pass session.token to your frontend
32
- ```
33
-
34
- ## Resources
35
-
36
- ### Customers
37
-
38
- ```ts
39
- await gv.customers.create({ externalId, email?, planId?, metadata? })
40
- await gv.customers.retrieve(id)
41
- await gv.customers.update(id, { email?, planId?, status?, resetPeriod? })
42
- await gv.customers.list({ status?, limit?, cursor? })
43
- await gv.customers.cancel(id)
44
- await gv.customers.usage(id)
45
- await gv.customers.sessions(id)
46
- ```
47
-
48
- ### Plans
49
-
50
- ```ts
51
- await gv.plans.list({ include_inactive? })
52
- await gv.plans.create({ name, monthlyTryOns, externalPriceId?, active? })
53
- await gv.plans.retrieve(id)
54
- await gv.plans.update(id, { name?, monthlyTryOns?, active? })
55
- await gv.plans.archive(id)
56
- ```
57
-
58
- ### Sessions
59
-
60
- ```ts
61
- await gv.sessions.mint({ customerId, ttlSeconds? })
62
- ```
63
-
64
- ### Webhooks
65
-
66
- ```ts
67
- await gv.webhooks.list()
68
- await gv.webhooks.create({ url, secret, events })
69
- await gv.webhooks.test(id)
70
- await gv.webhooks.delete(id)
71
- ```
72
-
73
- ## Webhook verification
74
-
75
- ```ts
76
- import { WebhooksResource } from '@genvoris/node';
77
-
78
- // In your Express / Next.js handler — pass the raw body, not parsed JSON
79
- const event = WebhooksResource.verify({
80
- payload: req.body,
81
- header: req.header('x-genvoris-signature') ?? '',
82
- secret: process.env.GENVORIS_WEBHOOK_SECRET!,
83
- });
84
-
85
- console.log(event.type, event.data);
86
- ```
87
-
88
- The signature format is `t=<unix>,v1=<hex>`. The signed string is `${timestamp}.${rawBody}` using HMAC-SHA256. Verification uses `crypto.timingSafeEqual`.
89
-
90
- ## Error handling
91
-
92
- ```ts
93
- import {
94
- GenvorisAPIError,
95
- GenvorisAuthError,
96
- GenvorisRateLimitError,
97
- GenvorisValidationError,
98
- } from '@genvoris/node';
99
-
100
- try {
101
- await gv.customers.retrieve('cus_missing');
102
- } catch (err) {
103
- if (err instanceof GenvorisAuthError) {
104
- // 401 / 403 — bad or revoked key
105
- } else if (err instanceof GenvorisRateLimitError) {
106
- console.log(`retry after ${err.retryAfterSeconds}s`);
107
- } else if (err instanceof GenvorisValidationError) {
108
- console.error(err.fieldErrors);
109
- } else if (err instanceof GenvorisAPIError) {
110
- console.error(err.status, err.code, err.requestId);
111
- }
112
- }
113
- ```
114
-
115
- The client automatically retries `429`, `502`, `503`, and `504` responses using exponential backoff with jitter (`min(2^n × 250 ms, 8 000 ms)`), up to `maxRetries` (default: 3).
116
-
117
- ## Configuration
118
-
119
- ```ts
120
- const gv = new Genvoris({
121
- apiKey: 'gvk_live_...',
122
- baseUrl: 'https://genvoris.org/api/v1', // default
123
- timeoutMs: 30_000, // default 30 s
124
- maxRetries: 3, // default 3
125
- defaultHeaders: { 'X-My-Header': 'val' },
126
- fetch: customFetch, // bring-your-own fetch
127
- });
128
- ```
129
-
130
- ## License
131
-
132
- MIT — see [LICENSE](./LICENSE).
1
+ # @genvoris/node
2
+
3
+ Official Node.js SDK for the [Genvoris Virtual Try-On API](https://docs.genvoris.org).
4
+
5
+ ## Requirements
6
+
7
+ Node.js **18** or higher (uses native `fetch`).
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @genvoris/node
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import Genvoris from '@genvoris/node';
19
+
20
+ const gv = new Genvoris({ apiKey: process.env.GENVORIS_API_KEY! });
21
+
22
+ // Create a customer
23
+ const customer = await gv.customers.create({
24
+ externalId: 'user_42',
25
+ email: 'shopper@example.com',
26
+ planId: 'pln_xxxxxxxx',
27
+ });
28
+
29
+ // Mint a session token for the widget
30
+ const session = await gv.sessions.mint({ customerId: customer.id });
31
+ // → pass session.token to your frontend
32
+ ```
33
+
34
+ ## Resources
35
+
36
+ ### Customers
37
+
38
+ ```ts
39
+ await gv.customers.create({ externalId, email?, planId?, metadata? })
40
+ await gv.customers.retrieve(id)
41
+ await gv.customers.update(id, { email?, planId?, status?, resetPeriod? })
42
+ await gv.customers.list({ status?, limit?, cursor? })
43
+ await gv.customers.cancel(id)
44
+ await gv.customers.usage(id)
45
+ await gv.customers.sessions(id)
46
+ ```
47
+
48
+ ### Plans
49
+
50
+ ```ts
51
+ await gv.plans.list({ include_inactive? })
52
+ await gv.plans.create({ name, monthlyTryOns, externalPriceId?, active? })
53
+ await gv.plans.retrieve(id)
54
+ await gv.plans.update(id, { name?, monthlyTryOns?, active? })
55
+ await gv.plans.archive(id)
56
+ ```
57
+
58
+ ### Sessions
59
+
60
+ ```ts
61
+ await gv.sessions.mint({ customerId, ttlSeconds? })
62
+ ```
63
+
64
+ ### Webhooks
65
+
66
+ ```ts
67
+ await gv.webhooks.list()
68
+ await gv.webhooks.create({ url, secret, events })
69
+ await gv.webhooks.test(id)
70
+ await gv.webhooks.delete(id)
71
+ ```
72
+
73
+ ## Webhook verification
74
+
75
+ ```ts
76
+ import { WebhooksResource } from '@genvoris/node';
77
+
78
+ // In your Express / Next.js handler — pass the raw body, not parsed JSON
79
+ const event = WebhooksResource.verify({
80
+ payload: req.body,
81
+ header: req.header('x-genvoris-signature') ?? '',
82
+ secret: process.env.GENVORIS_WEBHOOK_SECRET!,
83
+ });
84
+
85
+ console.log(event.type, event.data);
86
+ ```
87
+
88
+ The signature format is `t=<unix>,v1=<hex>`. The signed string is `${timestamp}.${rawBody}` using HMAC-SHA256. Verification uses `crypto.timingSafeEqual`.
89
+
90
+ ## Error handling
91
+
92
+ ```ts
93
+ import {
94
+ GenvorisAPIError,
95
+ GenvorisAuthError,
96
+ GenvorisRateLimitError,
97
+ GenvorisValidationError,
98
+ } from '@genvoris/node';
99
+
100
+ try {
101
+ await gv.customers.retrieve('cus_missing');
102
+ } catch (err) {
103
+ if (err instanceof GenvorisAuthError) {
104
+ // 401 / 403 — bad or revoked key
105
+ } else if (err instanceof GenvorisRateLimitError) {
106
+ console.log(`retry after ${err.retryAfterSeconds}s`);
107
+ } else if (err instanceof GenvorisValidationError) {
108
+ console.error(err.fieldErrors);
109
+ } else if (err instanceof GenvorisAPIError) {
110
+ console.error(err.status, err.code, err.requestId);
111
+ }
112
+ }
113
+ ```
114
+
115
+ The client automatically retries `429`, `502`, `503`, and `504` responses using exponential backoff with jitter (`min(2^n × 250 ms, 8 000 ms)`), up to `maxRetries` (default: 3).
116
+
117
+ ## Configuration
118
+
119
+ ```ts
120
+ const gv = new Genvoris({
121
+ apiKey: 'gvk_live_...',
122
+ baseUrl: 'https://genvoris.org/api/v1', // default
123
+ timeoutMs: 30_000, // default 30 s
124
+ maxRetries: 3, // default 3
125
+ defaultHeaders: { 'X-My-Header': 'val' },
126
+ fetch: customFetch, // bring-your-own fetch
127
+ });
128
+ ```
129
+
130
+ ## License
131
+
132
+ MIT — see [LICENSE](./LICENSE).
package/dist/index.d.mts CHANGED
@@ -161,6 +161,12 @@ interface SessionMintParams {
161
161
  /** JWT lifetime in seconds. Default: 900 (15 min). */
162
162
  ttlSeconds?: number;
163
163
  }
164
+ interface SessionRevokeParams {
165
+ /** Genvoris customer ID or your `externalId`. */
166
+ customerId: string;
167
+ /** The `jti` claim of the session token to revoke. */
168
+ jti: string;
169
+ }
164
170
  interface MintedSession {
165
171
  token: string;
166
172
  token_type: 'Bearer';
@@ -176,6 +182,10 @@ interface MintedSession {
176
182
  period_end: string | null;
177
183
  };
178
184
  }
185
+ interface RevokedSession {
186
+ jti: string;
187
+ revoked: true;
188
+ }
179
189
  declare class SessionsResource {
180
190
  private readonly config;
181
191
  constructor(config: GenvorisConfig);
@@ -186,6 +196,14 @@ declare class SessionsResource {
186
196
  * Genvoris widget — never exposed in client-side code directly.
187
197
  */
188
198
  mint({ customerId, ttlSeconds }: SessionMintParams): Promise<MintedSession>;
199
+ /**
200
+ * Revoke a previously minted session token by its `jti` claim.
201
+ *
202
+ * Use this on end-customer logout or when a token is suspected
203
+ * compromised. The token is rejected immediately even though its
204
+ * signature and expiry are otherwise still valid. Idempotent.
205
+ */
206
+ revoke({ customerId, jti }: SessionRevokeParams): Promise<RevokedSession>;
189
207
  }
190
208
 
191
209
  interface WebhookCreateParams {
package/dist/index.d.ts CHANGED
@@ -161,6 +161,12 @@ interface SessionMintParams {
161
161
  /** JWT lifetime in seconds. Default: 900 (15 min). */
162
162
  ttlSeconds?: number;
163
163
  }
164
+ interface SessionRevokeParams {
165
+ /** Genvoris customer ID or your `externalId`. */
166
+ customerId: string;
167
+ /** The `jti` claim of the session token to revoke. */
168
+ jti: string;
169
+ }
164
170
  interface MintedSession {
165
171
  token: string;
166
172
  token_type: 'Bearer';
@@ -176,6 +182,10 @@ interface MintedSession {
176
182
  period_end: string | null;
177
183
  };
178
184
  }
185
+ interface RevokedSession {
186
+ jti: string;
187
+ revoked: true;
188
+ }
179
189
  declare class SessionsResource {
180
190
  private readonly config;
181
191
  constructor(config: GenvorisConfig);
@@ -186,6 +196,14 @@ declare class SessionsResource {
186
196
  * Genvoris widget — never exposed in client-side code directly.
187
197
  */
188
198
  mint({ customerId, ttlSeconds }: SessionMintParams): Promise<MintedSession>;
199
+ /**
200
+ * Revoke a previously minted session token by its `jti` claim.
201
+ *
202
+ * Use this on end-customer logout or when a token is suspected
203
+ * compromised. The token is rejected immediately even though its
204
+ * signature and expiry are otherwise still valid. Idempotent.
205
+ */
206
+ revoke({ customerId, jti }: SessionRevokeParams): Promise<RevokedSession>;
189
207
  }
190
208
 
191
209
  interface WebhookCreateParams {
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ function sleep(ms) {
69
69
  return new Promise((resolve) => setTimeout(resolve, ms));
70
70
  }
71
71
  async function request(config, path, opts = {}, attempt = 0) {
72
- const { method = "GET", body, query } = opts;
72
+ const { method = "GET", body, query, contentType } = opts;
73
73
  const fetchFn = config.fetch ?? globalThis.fetch;
74
74
  const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
75
75
  let url = `${baseUrl}${path}`;
@@ -88,20 +88,33 @@ async function request(config, path, opts = {}, attempt = 0) {
88
88
  );
89
89
  let res;
90
90
  try {
91
+ const headers = {
92
+ Authorization: `Bearer ${config.apiKey}`,
93
+ "User-Agent": `genvoris-node/${SDK_VERSION}`,
94
+ Accept: "application/json",
95
+ ...config.defaultHeaders
96
+ };
97
+ if (body !== void 0 || contentType) {
98
+ headers["Content-Type"] = contentType ?? "application/json";
99
+ }
91
100
  res = await fetchFn(url, {
92
101
  method,
93
- headers: {
94
- Authorization: `Bearer ${config.apiKey}`,
95
- "Content-Type": "application/json",
96
- "User-Agent": `genvoris-node/${SDK_VERSION}`,
97
- ...config.defaultHeaders
98
- },
102
+ headers,
99
103
  body: body !== void 0 ? JSON.stringify(body) : void 0,
100
104
  signal: controller.signal
101
105
  });
102
- } finally {
106
+ } catch (err) {
103
107
  clearTimeout(timerId);
108
+ if (attempt < (config.maxRetries ?? 3)) {
109
+ const target = Math.pow(2, attempt) * 250;
110
+ const jittered = target * (0.7 + Math.random() * 0.6);
111
+ const delay = Math.min(jittered, MAX_DELAY_MS);
112
+ await sleep(delay);
113
+ return request(config, path, opts, attempt + 1);
114
+ }
115
+ throw err;
104
116
  }
117
+ clearTimeout(timerId);
105
118
  if (res.ok) {
106
119
  if (res.status === 204) return void 0;
107
120
  return res.json();
@@ -112,13 +125,14 @@ async function request(config, path, opts = {}, attempt = 0) {
112
125
  errBody = await res.json();
113
126
  } catch {
114
127
  }
115
- const code = errBody.error ?? "unknown_error";
116
- const message = errBody.message ?? code;
128
+ const code = errBody.error || "unknown_error";
129
+ const message = errBody.message || code;
117
130
  if (RETRY_STATUSES.has(res.status)) {
118
131
  const maxRetries = config.maxRetries ?? 3;
119
132
  if (attempt < maxRetries) {
120
- const base = Math.min(Math.pow(2, attempt) * 250, MAX_DELAY_MS);
121
- const delay = Math.random() * base;
133
+ const target = Math.pow(2, attempt) * 250;
134
+ const jittered = target * (0.7 + Math.random() * 0.6);
135
+ const delay = Math.min(jittered, MAX_DELAY_MS);
122
136
  await sleep(delay);
123
137
  return request(config, path, opts, attempt + 1);
124
138
  }
@@ -262,12 +276,29 @@ var SessionsResource = class {
262
276
  }
263
277
  );
264
278
  }
279
+ /**
280
+ * Revoke a previously minted session token by its `jti` claim.
281
+ *
282
+ * Use this on end-customer logout or when a token is suspected
283
+ * compromised. The token is rejected immediately even though its
284
+ * signature and expiry are otherwise still valid. Idempotent.
285
+ */
286
+ revoke({ customerId, jti }) {
287
+ return request(
288
+ this.config,
289
+ `/customers/${encodeURIComponent(customerId)}/sessions/${encodeURIComponent(jti)}`,
290
+ { method: "DELETE" }
291
+ );
292
+ }
265
293
  };
266
294
 
267
295
  // src/resources/webhooks.ts
268
296
  var import_node_crypto = require("crypto");
269
297
  function hexToBytes(hex) {
270
298
  if (hex.length % 2 !== 0) throw new Error("genvoris: invalid hex string");
299
+ if (!/^[a-f0-9]+$/i.test(hex)) {
300
+ throw new Error("genvoris: invalid hex string \u2014 non-hex characters");
301
+ }
271
302
  const bytes = new Uint8Array(hex.length / 2);
272
303
  for (let i = 0; i < bytes.length; i++) {
273
304
  bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
package/dist/index.mjs CHANGED
@@ -38,7 +38,7 @@ function sleep(ms) {
38
38
  return new Promise((resolve) => setTimeout(resolve, ms));
39
39
  }
40
40
  async function request(config, path, opts = {}, attempt = 0) {
41
- const { method = "GET", body, query } = opts;
41
+ const { method = "GET", body, query, contentType } = opts;
42
42
  const fetchFn = config.fetch ?? globalThis.fetch;
43
43
  const baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
44
44
  let url = `${baseUrl}${path}`;
@@ -57,20 +57,33 @@ async function request(config, path, opts = {}, attempt = 0) {
57
57
  );
58
58
  let res;
59
59
  try {
60
+ const headers = {
61
+ Authorization: `Bearer ${config.apiKey}`,
62
+ "User-Agent": `genvoris-node/${SDK_VERSION}`,
63
+ Accept: "application/json",
64
+ ...config.defaultHeaders
65
+ };
66
+ if (body !== void 0 || contentType) {
67
+ headers["Content-Type"] = contentType ?? "application/json";
68
+ }
60
69
  res = await fetchFn(url, {
61
70
  method,
62
- headers: {
63
- Authorization: `Bearer ${config.apiKey}`,
64
- "Content-Type": "application/json",
65
- "User-Agent": `genvoris-node/${SDK_VERSION}`,
66
- ...config.defaultHeaders
67
- },
71
+ headers,
68
72
  body: body !== void 0 ? JSON.stringify(body) : void 0,
69
73
  signal: controller.signal
70
74
  });
71
- } finally {
75
+ } catch (err) {
72
76
  clearTimeout(timerId);
77
+ if (attempt < (config.maxRetries ?? 3)) {
78
+ const target = Math.pow(2, attempt) * 250;
79
+ const jittered = target * (0.7 + Math.random() * 0.6);
80
+ const delay = Math.min(jittered, MAX_DELAY_MS);
81
+ await sleep(delay);
82
+ return request(config, path, opts, attempt + 1);
83
+ }
84
+ throw err;
73
85
  }
86
+ clearTimeout(timerId);
74
87
  if (res.ok) {
75
88
  if (res.status === 204) return void 0;
76
89
  return res.json();
@@ -81,13 +94,14 @@ async function request(config, path, opts = {}, attempt = 0) {
81
94
  errBody = await res.json();
82
95
  } catch {
83
96
  }
84
- const code = errBody.error ?? "unknown_error";
85
- const message = errBody.message ?? code;
97
+ const code = errBody.error || "unknown_error";
98
+ const message = errBody.message || code;
86
99
  if (RETRY_STATUSES.has(res.status)) {
87
100
  const maxRetries = config.maxRetries ?? 3;
88
101
  if (attempt < maxRetries) {
89
- const base = Math.min(Math.pow(2, attempt) * 250, MAX_DELAY_MS);
90
- const delay = Math.random() * base;
102
+ const target = Math.pow(2, attempt) * 250;
103
+ const jittered = target * (0.7 + Math.random() * 0.6);
104
+ const delay = Math.min(jittered, MAX_DELAY_MS);
91
105
  await sleep(delay);
92
106
  return request(config, path, opts, attempt + 1);
93
107
  }
@@ -231,12 +245,29 @@ var SessionsResource = class {
231
245
  }
232
246
  );
233
247
  }
248
+ /**
249
+ * Revoke a previously minted session token by its `jti` claim.
250
+ *
251
+ * Use this on end-customer logout or when a token is suspected
252
+ * compromised. The token is rejected immediately even though its
253
+ * signature and expiry are otherwise still valid. Idempotent.
254
+ */
255
+ revoke({ customerId, jti }) {
256
+ return request(
257
+ this.config,
258
+ `/customers/${encodeURIComponent(customerId)}/sessions/${encodeURIComponent(jti)}`,
259
+ { method: "DELETE" }
260
+ );
261
+ }
234
262
  };
235
263
 
236
264
  // src/resources/webhooks.ts
237
265
  import { createHmac, timingSafeEqual } from "crypto";
238
266
  function hexToBytes(hex) {
239
267
  if (hex.length % 2 !== 0) throw new Error("genvoris: invalid hex string");
268
+ if (!/^[a-f0-9]+$/i.test(hex)) {
269
+ throw new Error("genvoris: invalid hex string \u2014 non-hex characters");
270
+ }
240
271
  const bytes = new Uint8Array(hex.length / 2);
241
272
  for (let i = 0; i < bytes.length; i++) {
242
273
  bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
package/package.json CHANGED
@@ -1,52 +1,55 @@
1
- {
2
- "name": "@genvoris/node",
3
- "version": "1.0.0",
4
- "description": "Official Node.js SDK for the Genvoris Virtual Try-On API",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.mjs",
12
- "require": "./dist/index.js"
13
- }
14
- },
15
- "scripts": {
16
- "build": "tsup src/index.ts --format cjs,esm --dts --clean",
17
- "prepublishOnly": "npm run build"
18
- },
19
- "files": [
20
- "dist",
21
- "README.md",
22
- "LICENSE"
23
- ],
24
- "engines": {
25
- "node": ">=18"
26
- },
27
- "license": "MIT",
28
- "publishConfig": {
29
- "access": "public"
30
- },
31
- "keywords": [
32
- "genvoris",
33
- "virtual-try-on",
34
- "vton",
35
- "ecommerce",
36
- "fashion",
37
- "ai"
38
- ],
39
- "repository": {
40
- "type": "git",
41
- "url": "https://github.com/DevSajjadAli/genvoris-node"
42
- },
43
- "homepage": "https://docs.genvoris.org",
44
- "bugs": {
45
- "url": "https://github.com/DevSajjadAli/genvoris-node/issues",
46
- "email": "support@genvoris.org"
47
- },
48
- "devDependencies": {
49
- "typescript": "^5.4.5",
50
- "tsup": "^8.0.2"
51
- }
52
- }
1
+ {
2
+ "name": "@genvoris/node",
3
+ "version": "1.0.1",
4
+ "description": "Official Node.js SDK for the Genvoris Virtual Try-On API",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
17
+ "pretest": "npm run build",
18
+ "test": "node --test",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "license": "MIT",
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "keywords": [
34
+ "genvoris",
35
+ "virtual-try-on",
36
+ "vton",
37
+ "ecommerce",
38
+ "fashion",
39
+ "ai"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/DevSajjadAli/genvoris-node"
44
+ },
45
+ "homepage": "https://docs.genvoris.org",
46
+ "bugs": {
47
+ "url": "https://github.com/DevSajjadAli/genvoris-node/issues",
48
+ "email": "support@genvoris.org"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": ">=18",
52
+ "typescript": "^5.4.5",
53
+ "tsup": "^8.0.2"
54
+ }
55
+ }