@peable.to/sdk 0.2.3-oxy-one.0 → 0.2.4-oxy-one.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/cjs/core/config.js +2 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/resources/billing.js +54 -1
- package/dist/esm/core/config.js +2 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/resources/billing.js +54 -1
- package/dist/types/core/config.d.ts +5 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/resources/billing.d.ts +6 -2
- package/package.json +2 -2
package/dist/cjs/core/config.js
CHANGED
|
@@ -41,6 +41,8 @@ function resolveConfig(config) {
|
|
|
41
41
|
}
|
|
42
42
|
return {
|
|
43
43
|
requestTimeoutMs: resolveRequestTimeout(config.requestTimeoutMs),
|
|
44
|
+
taxQuoteAuthorityKeys: config.taxQuoteAuthorityKeys ? Object.freeze({ ...config.taxQuoteAuthorityKeys }) : undefined,
|
|
45
|
+
invoiceAuthorityKeys: config.invoiceAuthorityKeys ? Object.freeze({ ...config.invoiceAuthorityKeys }) : undefined,
|
|
44
46
|
publicKey: config.publicKey,
|
|
45
47
|
secret: config.secret,
|
|
46
48
|
baseURL: stripTrailingSlash(config.baseURL ?? exports.DEFAULT_GATEWAY_BASE_URL),
|
package/dist/cjs/index.js
CHANGED
|
@@ -41,7 +41,7 @@ class Peable {
|
|
|
41
41
|
const resolved = (0, config_1.resolveConfig)(config);
|
|
42
42
|
const tokenProvider = (0, serviceToken_1.createServiceTokenProvider)(config);
|
|
43
43
|
const client = (0, client_1.createRestClient)({ baseURL: resolved.baseURL, requestTimeoutMs: resolved.requestTimeoutMs }, tokenProvider);
|
|
44
|
-
this.billing = new billing_1.BillingResource(client);
|
|
44
|
+
this.billing = new billing_1.BillingResource(client, resolved.invoiceAuthorityKeys, resolved.taxQuoteAuthorityKeys);
|
|
45
45
|
this.paymentIntents = new paymentIntents_1.PaymentIntentsResource(client);
|
|
46
46
|
this.paymentLinks = new paymentLinks_1.PaymentLinksResource(client);
|
|
47
47
|
this.checkout = new checkoutSessions_1.CheckoutResource(client);
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BillingResource = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const shared_types_1 = require("@peable.to/shared-types");
|
|
4
6
|
/** Recurring billing is separate from one-off checkout and marketplace transfers. */
|
|
5
7
|
class BillingResource {
|
|
6
|
-
constructor(client) {
|
|
8
|
+
constructor(client, invoiceAuthorityKeys, taxQuoteAuthorityKeys) {
|
|
7
9
|
this.client = client;
|
|
10
|
+
this.invoiceAuthorityKeys = invoiceAuthorityKeys;
|
|
11
|
+
this.taxQuoteAuthorityKeys = taxQuoteAuthorityKeys;
|
|
8
12
|
}
|
|
9
13
|
ensureCustomer(params, options) {
|
|
10
14
|
return this.client.request('POST', '/v1/billing/customers', { body: params, idempotencyKey: options.idempotencyKey });
|
|
@@ -16,6 +20,55 @@ class BillingResource {
|
|
|
16
20
|
return this.client.request('POST', '/v1/billing/portal_sessions', { body: params, idempotencyKey: options.idempotencyKey });
|
|
17
21
|
}
|
|
18
22
|
retrieveCheckout(ref) { return this.client.request('GET', `/v1/billing/checkout_sessions/${encodeURIComponent(ref)}`); }
|
|
23
|
+
async createTaxQuote(params) {
|
|
24
|
+
if (!this.taxQuoteAuthorityKeys || Object.keys(this.taxQuoteAuthorityKeys).length === 0)
|
|
25
|
+
throw new Error('Peable: tax quote authority verification is unconfigured');
|
|
26
|
+
const result = await this.client.request('POST', '/v1/billing/tax_quotes', { body: params });
|
|
27
|
+
try {
|
|
28
|
+
const pinned = this.taxQuoteAuthorityKeys[result.signature.keyId];
|
|
29
|
+
if (!pinned || result.schemaVersion !== 1 || result.signature.algorithm !== 'Ed25519' || !/^[A-Za-z0-9_-]{86}$/.test(result.signature.value)
|
|
30
|
+
|| result.source.storeId !== params.storeId || result.source.planId !== params.planId || result.quote.customerLocationEvidenceId !== params.customerLocationEvidenceId
|
|
31
|
+
|| !Number.isFinite(Date.parse(result.quote.quotedAt)) || Date.parse(result.quote.quotedAt) > Date.now()
|
|
32
|
+
|| !Number.isFinite(Date.parse(result.quote.expiresAt)) || Date.parse(result.quote.expiresAt) <= Date.now())
|
|
33
|
+
throw new Error('Invalid quote');
|
|
34
|
+
const key = (0, node_crypto_1.createPublicKey)(pinned);
|
|
35
|
+
if (key.asymmetricKeyType !== 'ed25519' || !(0, node_crypto_1.verify)(null, Buffer.from((0, shared_types_1.canonicalBillingTaxQuote)(result)), key, Buffer.from(result.signature.value, 'base64url')))
|
|
36
|
+
throw new Error('Invalid signature');
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
throw new Error('Peable: tax quote authority verification failed');
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef) {
|
|
44
|
+
if (!this.invoiceAuthorityKeys || Object.keys(this.invoiceAuthorityKeys).length === 0)
|
|
45
|
+
throw new Error('Peable: invoice authority verification is unconfigured');
|
|
46
|
+
const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`);
|
|
47
|
+
try {
|
|
48
|
+
const pinnedKey = this.invoiceAuthorityKeys[authority.signature.keyId];
|
|
49
|
+
if (authority.schemaVersion !== 1 || !pinnedKey || authority.signature.algorithm !== 'Ed25519' || !/^[A-Za-z0-9_-]{86}$/.test(authority.signature.value)
|
|
50
|
+
|| authority.source.invoiceId !== invoiceRef || authority.source.subscriptionId !== subscriptionRef
|
|
51
|
+
|| authority.invoice.context.providerSubscriptionId !== subscriptionRef
|
|
52
|
+
|| !['card', 'faircoin'].includes(authority.method)
|
|
53
|
+
|| !Number.isFinite(Date.parse(authority.invoice.issuedAt)) || Date.parse(authority.invoice.issuedAt) > Date.now()
|
|
54
|
+
|| !Number.isFinite(Date.parse(authority.invoice.expiresAt)) || Date.parse(authority.invoice.expiresAt) <= Date.now())
|
|
55
|
+
throw new Error('Invalid authority');
|
|
56
|
+
if (authority.method === 'faircoin') {
|
|
57
|
+
const quote = authority.invoice.faircoinQuote;
|
|
58
|
+
if (!quote || !/^[1-9][0-9]*$/.test(quote.amountBaseUnits) || !Number.isFinite(Date.parse(quote.quotedAt))
|
|
59
|
+
|| Date.parse(quote.quotedAt) > Date.now() || !Number.isFinite(Date.parse(quote.expiresAt))
|
|
60
|
+
|| Date.parse(quote.expiresAt) <= Date.now() || Date.parse(quote.expiresAt) > Date.parse(authority.invoice.expiresAt))
|
|
61
|
+
throw new Error('Invalid quote');
|
|
62
|
+
}
|
|
63
|
+
const key = (0, node_crypto_1.createPublicKey)(pinnedKey);
|
|
64
|
+
if (key.asymmetricKeyType !== 'ed25519' || !(0, node_crypto_1.verify)(null, Buffer.from((0, shared_types_1.canonicalBillingAuthority)(authority), 'utf8'), key, Buffer.from(authority.signature.value, 'base64url')))
|
|
65
|
+
throw new Error('Invalid signature');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
throw new Error('Peable: invoice authority verification failed');
|
|
69
|
+
}
|
|
70
|
+
return authority;
|
|
71
|
+
}
|
|
19
72
|
retrievePaidInvoice(subscriptionRef, invoiceRef) { return this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/paid_invoices/${encodeURIComponent(invoiceRef)}`); }
|
|
20
73
|
retrieveInvoiceState(subscriptionRef, invoiceRef) { return this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_states/${encodeURIComponent(invoiceRef)}`); }
|
|
21
74
|
retrieveSubscription(ref) {
|
package/dist/esm/core/config.js
CHANGED
|
@@ -36,6 +36,8 @@ export function resolveConfig(config) {
|
|
|
36
36
|
}
|
|
37
37
|
return {
|
|
38
38
|
requestTimeoutMs: resolveRequestTimeout(config.requestTimeoutMs),
|
|
39
|
+
taxQuoteAuthorityKeys: config.taxQuoteAuthorityKeys ? Object.freeze({ ...config.taxQuoteAuthorityKeys }) : undefined,
|
|
40
|
+
invoiceAuthorityKeys: config.invoiceAuthorityKeys ? Object.freeze({ ...config.invoiceAuthorityKeys }) : undefined,
|
|
39
41
|
publicKey: config.publicKey,
|
|
40
42
|
secret: config.secret,
|
|
41
43
|
baseURL: stripTrailingSlash(config.baseURL ?? DEFAULT_GATEWAY_BASE_URL),
|
package/dist/esm/index.js
CHANGED
|
@@ -38,7 +38,7 @@ export class Peable {
|
|
|
38
38
|
const resolved = resolveConfig(config);
|
|
39
39
|
const tokenProvider = createServiceTokenProvider(config);
|
|
40
40
|
const client = createRestClient({ baseURL: resolved.baseURL, requestTimeoutMs: resolved.requestTimeoutMs }, tokenProvider);
|
|
41
|
-
this.billing = new BillingResource(client);
|
|
41
|
+
this.billing = new BillingResource(client, resolved.invoiceAuthorityKeys, resolved.taxQuoteAuthorityKeys);
|
|
42
42
|
this.paymentIntents = new PaymentIntentsResource(client);
|
|
43
43
|
this.paymentLinks = new PaymentLinksResource(client);
|
|
44
44
|
this.checkout = new CheckoutResource(client);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { createPublicKey, verify } from 'node:crypto';
|
|
2
|
+
import { canonicalBillingAuthority, canonicalBillingTaxQuote } from '@peable.to/shared-types';
|
|
1
3
|
/** Recurring billing is separate from one-off checkout and marketplace transfers. */
|
|
2
4
|
export class BillingResource {
|
|
3
|
-
constructor(client) {
|
|
5
|
+
constructor(client, invoiceAuthorityKeys, taxQuoteAuthorityKeys) {
|
|
4
6
|
this.client = client;
|
|
7
|
+
this.invoiceAuthorityKeys = invoiceAuthorityKeys;
|
|
8
|
+
this.taxQuoteAuthorityKeys = taxQuoteAuthorityKeys;
|
|
5
9
|
}
|
|
6
10
|
ensureCustomer(params, options) {
|
|
7
11
|
return this.client.request('POST', '/v1/billing/customers', { body: params, idempotencyKey: options.idempotencyKey });
|
|
@@ -13,6 +17,55 @@ export class BillingResource {
|
|
|
13
17
|
return this.client.request('POST', '/v1/billing/portal_sessions', { body: params, idempotencyKey: options.idempotencyKey });
|
|
14
18
|
}
|
|
15
19
|
retrieveCheckout(ref) { return this.client.request('GET', `/v1/billing/checkout_sessions/${encodeURIComponent(ref)}`); }
|
|
20
|
+
async createTaxQuote(params) {
|
|
21
|
+
if (!this.taxQuoteAuthorityKeys || Object.keys(this.taxQuoteAuthorityKeys).length === 0)
|
|
22
|
+
throw new Error('Peable: tax quote authority verification is unconfigured');
|
|
23
|
+
const result = await this.client.request('POST', '/v1/billing/tax_quotes', { body: params });
|
|
24
|
+
try {
|
|
25
|
+
const pinned = this.taxQuoteAuthorityKeys[result.signature.keyId];
|
|
26
|
+
if (!pinned || result.schemaVersion !== 1 || result.signature.algorithm !== 'Ed25519' || !/^[A-Za-z0-9_-]{86}$/.test(result.signature.value)
|
|
27
|
+
|| result.source.storeId !== params.storeId || result.source.planId !== params.planId || result.quote.customerLocationEvidenceId !== params.customerLocationEvidenceId
|
|
28
|
+
|| !Number.isFinite(Date.parse(result.quote.quotedAt)) || Date.parse(result.quote.quotedAt) > Date.now()
|
|
29
|
+
|| !Number.isFinite(Date.parse(result.quote.expiresAt)) || Date.parse(result.quote.expiresAt) <= Date.now())
|
|
30
|
+
throw new Error('Invalid quote');
|
|
31
|
+
const key = createPublicKey(pinned);
|
|
32
|
+
if (key.asymmetricKeyType !== 'ed25519' || !verify(null, Buffer.from(canonicalBillingTaxQuote(result)), key, Buffer.from(result.signature.value, 'base64url')))
|
|
33
|
+
throw new Error('Invalid signature');
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
throw new Error('Peable: tax quote authority verification failed');
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
async retrieveFinalInvoiceAuthority(subscriptionRef, invoiceRef) {
|
|
41
|
+
if (!this.invoiceAuthorityKeys || Object.keys(this.invoiceAuthorityKeys).length === 0)
|
|
42
|
+
throw new Error('Peable: invoice authority verification is unconfigured');
|
|
43
|
+
const authority = await this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_authorities/${encodeURIComponent(invoiceRef)}`);
|
|
44
|
+
try {
|
|
45
|
+
const pinnedKey = this.invoiceAuthorityKeys[authority.signature.keyId];
|
|
46
|
+
if (authority.schemaVersion !== 1 || !pinnedKey || authority.signature.algorithm !== 'Ed25519' || !/^[A-Za-z0-9_-]{86}$/.test(authority.signature.value)
|
|
47
|
+
|| authority.source.invoiceId !== invoiceRef || authority.source.subscriptionId !== subscriptionRef
|
|
48
|
+
|| authority.invoice.context.providerSubscriptionId !== subscriptionRef
|
|
49
|
+
|| !['card', 'faircoin'].includes(authority.method)
|
|
50
|
+
|| !Number.isFinite(Date.parse(authority.invoice.issuedAt)) || Date.parse(authority.invoice.issuedAt) > Date.now()
|
|
51
|
+
|| !Number.isFinite(Date.parse(authority.invoice.expiresAt)) || Date.parse(authority.invoice.expiresAt) <= Date.now())
|
|
52
|
+
throw new Error('Invalid authority');
|
|
53
|
+
if (authority.method === 'faircoin') {
|
|
54
|
+
const quote = authority.invoice.faircoinQuote;
|
|
55
|
+
if (!quote || !/^[1-9][0-9]*$/.test(quote.amountBaseUnits) || !Number.isFinite(Date.parse(quote.quotedAt))
|
|
56
|
+
|| Date.parse(quote.quotedAt) > Date.now() || !Number.isFinite(Date.parse(quote.expiresAt))
|
|
57
|
+
|| Date.parse(quote.expiresAt) <= Date.now() || Date.parse(quote.expiresAt) > Date.parse(authority.invoice.expiresAt))
|
|
58
|
+
throw new Error('Invalid quote');
|
|
59
|
+
}
|
|
60
|
+
const key = createPublicKey(pinnedKey);
|
|
61
|
+
if (key.asymmetricKeyType !== 'ed25519' || !verify(null, Buffer.from(canonicalBillingAuthority(authority), 'utf8'), key, Buffer.from(authority.signature.value, 'base64url')))
|
|
62
|
+
throw new Error('Invalid signature');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new Error('Peable: invoice authority verification failed');
|
|
66
|
+
}
|
|
67
|
+
return authority;
|
|
68
|
+
}
|
|
16
69
|
retrievePaidInvoice(subscriptionRef, invoiceRef) { return this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/paid_invoices/${encodeURIComponent(invoiceRef)}`); }
|
|
17
70
|
retrieveInvoiceState(subscriptionRef, invoiceRef) { return this.client.request('GET', `/v1/billing/subscriptions/${encodeURIComponent(subscriptionRef)}/invoice_states/${encodeURIComponent(invoiceRef)}`); }
|
|
18
71
|
retrieveSubscription(ref) {
|
|
@@ -15,6 +15,9 @@ export interface PeableConfig {
|
|
|
15
15
|
oxyApiUrl?: string;
|
|
16
16
|
/** Optional deadline per HTTP attempt, including body consumption. */
|
|
17
17
|
requestTimeoutMs?: number;
|
|
18
|
+
/** Pinned Ed25519 authority keys, obtained from trusted deployment configuration. */
|
|
19
|
+
invoiceAuthorityKeys?: Readonly<Record<string, string>>;
|
|
20
|
+
taxQuoteAuthorityKeys?: Readonly<Record<string, string>>;
|
|
18
21
|
}
|
|
19
22
|
/** `PeableConfig` with every optional field defaulted and normalized. */
|
|
20
23
|
export interface ResolvedPeableConfig {
|
|
@@ -23,6 +26,8 @@ export interface ResolvedPeableConfig {
|
|
|
23
26
|
baseURL: string;
|
|
24
27
|
oxyApiUrl: string;
|
|
25
28
|
requestTimeoutMs?: number;
|
|
29
|
+
invoiceAuthorityKeys?: Readonly<Record<string, string>>;
|
|
30
|
+
taxQuoteAuthorityKeys?: Readonly<Record<string, string>>;
|
|
26
31
|
}
|
|
27
32
|
export declare function resolveRequestTimeout(value: number | undefined): number | undefined;
|
|
28
33
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BillingResource } from './resources/billing';
|
|
2
2
|
export type { BillingRequestOptions } from './resources/billing';
|
|
3
|
-
export type { BillingObservation, BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams } from '@peable.to/shared-types';
|
|
3
|
+
export type { CreateBillingTaxQuoteParams, BillingTaxQuote, BillingInvoiceAuthoritySource, BillingFinalInvoice, BillingFinalInvoiceAuthority, BillingFaircoinRenewalChoice, BillingFaircoinRenewalConsent, BillingFaircoinRenewalRevocation, BillingObservation, BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams } from '@peable.to/shared-types';
|
|
4
4
|
import { type PeableConfig } from './core/config';
|
|
5
5
|
import { PaymentIntentsResource } from './resources/paymentIntents';
|
|
6
6
|
import { PaymentLinksResource } from './resources/paymentLinks';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams } from '@peable.to/shared-types';
|
|
1
|
+
import type { BillingTaxQuote, CreateBillingTaxQuoteParams, BillingFinalInvoiceAuthority, BillingCustomer, BillingHostedSession, BillingCheckoutSession, BillingCheckoutObservation, BillingPaidInvoice, BillingInvoiceState, BillingSubscription, CreateBillingCheckoutParams, CreateBillingPortalParams, EnsureBillingCustomerParams } from '@peable.to/shared-types';
|
|
2
2
|
import type { RestClient } from '../core/client';
|
|
3
3
|
export interface BillingRequestOptions {
|
|
4
4
|
idempotencyKey: string;
|
|
@@ -6,11 +6,15 @@ export interface BillingRequestOptions {
|
|
|
6
6
|
/** Recurring billing is separate from one-off checkout and marketplace transfers. */
|
|
7
7
|
export declare class BillingResource {
|
|
8
8
|
private readonly client;
|
|
9
|
-
|
|
9
|
+
private readonly invoiceAuthorityKeys?;
|
|
10
|
+
private readonly taxQuoteAuthorityKeys?;
|
|
11
|
+
constructor(client: RestClient, invoiceAuthorityKeys?: Readonly<Record<string, string>> | undefined, taxQuoteAuthorityKeys?: Readonly<Record<string, string>> | undefined);
|
|
10
12
|
ensureCustomer(params: EnsureBillingCustomerParams, options: BillingRequestOptions): Promise<BillingCustomer>;
|
|
11
13
|
createCheckoutSession(params: CreateBillingCheckoutParams, options: BillingRequestOptions): Promise<BillingCheckoutSession>;
|
|
12
14
|
createPortalSession(params: CreateBillingPortalParams, options: BillingRequestOptions): Promise<BillingHostedSession>;
|
|
13
15
|
retrieveCheckout(ref: string): Promise<BillingCheckoutObservation>;
|
|
16
|
+
createTaxQuote(params: CreateBillingTaxQuoteParams): Promise<BillingTaxQuote>;
|
|
17
|
+
retrieveFinalInvoiceAuthority(subscriptionRef: string, invoiceRef: string): Promise<BillingFinalInvoiceAuthority>;
|
|
14
18
|
retrievePaidInvoice(subscriptionRef: string, invoiceRef: string): Promise<BillingPaidInvoice>;
|
|
15
19
|
retrieveInvoiceState(subscriptionRef: string, invoiceRef: string): Promise<BillingInvoiceState>;
|
|
16
20
|
retrieveSubscription(ref: string): Promise<BillingSubscription>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peable.to/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4-oxy-one.0",
|
|
4
4
|
"description": "Peable SDK — a Stripe-ergonomics TypeScript client over the Peable Gateway REST + realtime contract. Server entry (`@peable.to/sdk`) mints Oxy service tokens from an ApplicationCredential and exposes paymentIntents/paymentLinks/checkout.sessions/webhooks; browser entry (`@peable.to/sdk/checkout`) is the anonymous payer-side client core.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"prepublishOnly": "bun run clean && bun run build"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@peable.to/shared-types": "0.3.
|
|
76
|
+
"@peable.to/shared-types": "0.3.2-oxy-one.0",
|
|
77
77
|
"qrcode-generator": "^2.0.4",
|
|
78
78
|
"socket.io-client": "^4.8.3"
|
|
79
79
|
},
|