@powerhousedao/contributor-billing 0.0.89 → 0.0.91
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/editors/contributor-billing/components/InvoiceTable/HeaderStats.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderStats.js +8 -4
- package/dist/editors/contributor-billing/util.d.ts +2 -1
- package/dist/editors/contributor-billing/util.d.ts.map +1 -1
- package/dist/editors/contributor-billing/util.js +45 -16
- package/dist/editors/invoice/ingestPDF.js +1 -1
- package/dist/editors/invoice/invoiceToGnosis.js +1 -1
- package/dist/editors/invoice/requestFinance.js +1 -1
- package/dist/editors/invoice/uploadPdfChunked.js +1 -1
- package/dist/migrate-zip.d.ts +2 -0
- package/dist/migrate-zip.d.ts.map +1 -0
- package/dist/migrate-zip.js +56 -0
- package/dist/style.css +19 -0
- package/package.json +13 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderStats.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderStats.tsx"],"names":[],"mappings":"AAkBA,eAAO,MAAM,WAAW,+
|
|
1
|
+
{"version":3,"file":"HeaderStats.d.ts","sourceRoot":"","sources":["../../../../../editors/contributor-billing/components/InvoiceTable/HeaderStats.tsx"],"names":[],"mappings":"AAkBA,eAAO,MAAM,WAAW,+CAoHvB,CAAC"}
|
|
@@ -30,20 +30,24 @@ export const HeaderStats = () => {
|
|
|
30
30
|
for (const doc of invoices) {
|
|
31
31
|
const invoice = doc;
|
|
32
32
|
const invoiceAmount = invoice.state.global.totalPriceTaxIncl;
|
|
33
|
-
let invoiceCurrency = invoice.state.global.currency;
|
|
33
|
+
let invoiceCurrency = invoice.state.global.currency || 'USD'; // Fallback to USD if currency is empty
|
|
34
34
|
let selectCurrency = selectedCurrency;
|
|
35
35
|
if (invoiceCurrency === selectedCurrency) {
|
|
36
36
|
total += invoiceAmount;
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
try {
|
|
40
|
+
// Only convert crypto currencies to USD for the API call
|
|
41
|
+
let fromCurrency = invoiceCurrency;
|
|
42
|
+
let toCurrency = selectedCurrency;
|
|
43
|
+
// Convert crypto to USD for API compatibility
|
|
40
44
|
if (invoiceCurrency === "DAI" || invoiceCurrency === "USDS") {
|
|
41
|
-
|
|
45
|
+
fromCurrency = "USD";
|
|
42
46
|
}
|
|
43
47
|
if (selectedCurrency === "DAI" || selectedCurrency === "USDS") {
|
|
44
|
-
|
|
48
|
+
toCurrency = "USD";
|
|
45
49
|
}
|
|
46
|
-
const exchangeRate = await getExchangeRate(
|
|
50
|
+
const exchangeRate = await getExchangeRate(fromCurrency, toCurrency, invoiceAmount);
|
|
47
51
|
total += invoiceAmount * exchangeRate;
|
|
48
52
|
}
|
|
49
53
|
catch (error) {
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Supports both fiat and crypto currencies.
|
|
4
4
|
* @param fromCurrency - The currency code to convert from (e.g., 'USD', 'DAI').
|
|
5
5
|
* @param toCurrency - The currency code to convert to (e.g., 'EUR', 'USDS').
|
|
6
|
+
* @param amount - The amount to convert (optional, used for validation).
|
|
6
7
|
* @returns The exchange rate from fromCurrency to toCurrency.
|
|
7
8
|
*/
|
|
8
|
-
export declare const getExchangeRate: (fromCurrency: string, toCurrency: string) => Promise<number>;
|
|
9
|
+
export declare const getExchangeRate: (fromCurrency: string, toCurrency: string, amount?: number) => Promise<number>;
|
|
9
10
|
//# sourceMappingURL=util.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../editors/contributor-billing/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../editors/contributor-billing/util.ts"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAU,cAAc,MAAM,EAAE,YAAY,MAAM,EAAE,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAoH/G,CAAC"}
|
|
@@ -1,35 +1,58 @@
|
|
|
1
1
|
// Cache for exchange rates to avoid repeated API calls
|
|
2
2
|
const exchangeRateCache = {};
|
|
3
|
+
/**
|
|
4
|
+
* Validates if an amount should trigger an exchange rate fetch
|
|
5
|
+
* @param amount - The amount to validate
|
|
6
|
+
* @returns true if the amount is valid and should trigger API calls
|
|
7
|
+
*/
|
|
8
|
+
const isValidAmount = (amount) => {
|
|
9
|
+
return amount !== undefined && amount !== null && !isNaN(amount) && amount > 0;
|
|
10
|
+
};
|
|
3
11
|
/**
|
|
4
12
|
* Fetches the exchange rate between two currencies using ExchangeRate-API.
|
|
5
13
|
* Supports both fiat and crypto currencies.
|
|
6
14
|
* @param fromCurrency - The currency code to convert from (e.g., 'USD', 'DAI').
|
|
7
15
|
* @param toCurrency - The currency code to convert to (e.g., 'EUR', 'USDS').
|
|
16
|
+
* @param amount - The amount to convert (optional, used for validation).
|
|
8
17
|
* @returns The exchange rate from fromCurrency to toCurrency.
|
|
9
18
|
*/
|
|
10
|
-
export const getExchangeRate = async (fromCurrency, toCurrency) => {
|
|
19
|
+
export const getExchangeRate = async (fromCurrency, toCurrency, amount) => {
|
|
20
|
+
// Normalize inputs
|
|
21
|
+
const base = (fromCurrency || '').trim().toUpperCase();
|
|
22
|
+
const quote = (toCurrency || '').trim().toUpperCase();
|
|
23
|
+
// Guard empty currencies
|
|
24
|
+
if (!base || !quote) {
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
11
27
|
// Return 1 if currencies are the same
|
|
12
|
-
if (
|
|
28
|
+
if (base === quote) {
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
// Skip API call if amount is explicitly provided and invalid
|
|
32
|
+
if (amount !== undefined && !isValidAmount(amount)) {
|
|
13
33
|
return 1;
|
|
14
34
|
}
|
|
15
35
|
// Create cache key
|
|
16
|
-
const cacheKey = `${
|
|
36
|
+
const cacheKey = `${base}_${quote}`;
|
|
17
37
|
// Return cached rate if available
|
|
18
38
|
if (exchangeRateCache[cacheKey] !== undefined) {
|
|
19
39
|
return exchangeRateCache[cacheKey];
|
|
20
40
|
}
|
|
21
41
|
try {
|
|
22
|
-
// Use
|
|
23
|
-
//
|
|
24
|
-
const
|
|
42
|
+
// Use a CORS-friendly endpoint that does not redirect
|
|
43
|
+
// API: https://open.er-api.com/v6/latest/{BASE}
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
|
46
|
+
const response = await fetch(`https://open.er-api.com/v6/latest/${base}`, { signal: controller.signal });
|
|
47
|
+
clearTimeout(timeoutId);
|
|
25
48
|
if (!response.ok) {
|
|
26
49
|
throw new Error(`Failed to fetch exchange rates: ${response.status}`);
|
|
27
50
|
}
|
|
28
51
|
const data = await response.json();
|
|
29
|
-
if (!data.rates || !data.rates[
|
|
30
|
-
throw new Error(`Exchange rate not found for ${
|
|
52
|
+
if (!data.rates || !data.rates[quote]) {
|
|
53
|
+
throw new Error(`Exchange rate not found for ${base} to ${quote}`);
|
|
31
54
|
}
|
|
32
|
-
const exchangeRate = data.rates[
|
|
55
|
+
const exchangeRate = data.rates[quote];
|
|
33
56
|
// Cache the result
|
|
34
57
|
exchangeRateCache[cacheKey] = exchangeRate;
|
|
35
58
|
return exchangeRate;
|
|
@@ -37,18 +60,21 @@ export const getExchangeRate = async (fromCurrency, toCurrency) => {
|
|
|
37
60
|
catch (error) {
|
|
38
61
|
console.error('ExchangeRate-API error:', error);
|
|
39
62
|
// Fallback: try a different approach for crypto currencies
|
|
40
|
-
if (['USDS', 'DAI'].includes(
|
|
63
|
+
if (['USDS', 'DAI'].includes(base) || ['USDS', 'DAI'].includes(quote)) {
|
|
41
64
|
try {
|
|
42
65
|
// For crypto currencies, use CoinGecko as fallback
|
|
43
66
|
const cryptoMapping = {
|
|
44
67
|
'USDS': 'usd-coin',
|
|
45
68
|
'DAI': 'dai',
|
|
46
69
|
};
|
|
47
|
-
const fromMapped = cryptoMapping[
|
|
48
|
-
const toMapped = cryptoMapping[
|
|
49
|
-
if (cryptoMapping[
|
|
70
|
+
const fromMapped = cryptoMapping[base] || base.toLowerCase();
|
|
71
|
+
const toMapped = cryptoMapping[quote] || quote.toLowerCase();
|
|
72
|
+
if (cryptoMapping[base]) {
|
|
50
73
|
// From crypto to fiat/crypto
|
|
51
|
-
const
|
|
74
|
+
const cryptoController = new AbortController();
|
|
75
|
+
const cryptoTimeoutId = setTimeout(() => cryptoController.abort(), 8000); // 8 second timeout
|
|
76
|
+
const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${fromMapped}&vs_currencies=${toMapped}`, { signal: cryptoController.signal });
|
|
77
|
+
clearTimeout(cryptoTimeoutId);
|
|
52
78
|
if (response.ok) {
|
|
53
79
|
const data = await response.json();
|
|
54
80
|
const rate = data[fromMapped]?.[toMapped];
|
|
@@ -58,9 +84,12 @@ export const getExchangeRate = async (fromCurrency, toCurrency) => {
|
|
|
58
84
|
}
|
|
59
85
|
}
|
|
60
86
|
}
|
|
61
|
-
else if (cryptoMapping[
|
|
87
|
+
else if (cryptoMapping[quote]) {
|
|
62
88
|
// From fiat to crypto
|
|
63
|
-
const
|
|
89
|
+
const cryptoController2 = new AbortController();
|
|
90
|
+
const cryptoTimeoutId2 = setTimeout(() => cryptoController2.abort(), 8000); // 8 second timeout
|
|
91
|
+
const response = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${toMapped}&vs_currencies=${fromMapped}`, { signal: cryptoController2.signal });
|
|
92
|
+
clearTimeout(cryptoTimeoutId2);
|
|
64
93
|
if (response.ok) {
|
|
65
94
|
const data = await response.json();
|
|
66
95
|
const rate = data[toMapped]?.[fromMapped];
|
|
@@ -6,7 +6,7 @@ import { uploadPdfChunked } from "./uploadPdfChunked.js";
|
|
|
6
6
|
import { getCountryCodeFromName } from "./utils/utils.js";
|
|
7
7
|
let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
|
|
8
8
|
if (!window.document.baseURI.includes('localhost')) {
|
|
9
|
-
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
9
|
+
GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
|
|
10
10
|
}
|
|
11
11
|
export async function loadPDFFile({ file, dispatch, }) {
|
|
12
12
|
if (!file)
|
|
@@ -4,7 +4,7 @@ import { actions } from "../../document-models/invoice/index.js";
|
|
|
4
4
|
import { generateId } from "document-model";
|
|
5
5
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
6
6
|
if (!window.document.baseURI.includes('localhost')) {
|
|
7
|
-
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
7
|
+
GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
|
|
8
8
|
}
|
|
9
9
|
const InvoiceToGnosis = ({ docState, dispatch, }) => {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -4,7 +4,7 @@ import { actions } from "../../document-models/invoice/index.js";
|
|
|
4
4
|
import { generateId } from "document-model";
|
|
5
5
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
6
6
|
if (!window.document.baseURI.includes('localhost')) {
|
|
7
|
-
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
7
|
+
GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
|
|
8
8
|
}
|
|
9
9
|
const RequestFinance = ({ docState, dispatch, }) => {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
|
|
9
9
|
if (!window.document.baseURI.includes('localhost')) {
|
|
10
|
-
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
10
|
+
GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
|
|
11
11
|
}
|
|
12
12
|
export async function uploadPdfChunked(pdfData, endpoint = GRAPHQL_URL, chunkSize = 500 * 1024, // 500KB chunks
|
|
13
13
|
onProgress) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-zip.d.ts","sourceRoot":"","sources":["../migrate-zip.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import JSZip from "jszip";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { documentModelDocumentModelModule } from "document-model";
|
|
5
|
+
import { argv } from "node:process";
|
|
6
|
+
const docModelMap = {
|
|
7
|
+
"powerhouse/document-model": documentModelDocumentModelModule,
|
|
8
|
+
// add other document models here
|
|
9
|
+
};
|
|
10
|
+
async function loadFromZip(zip, entryName) {
|
|
11
|
+
const entry = await zip.file(entryName).async("string");
|
|
12
|
+
return JSON.parse(entry);
|
|
13
|
+
}
|
|
14
|
+
async function resolvePath(argPath) {
|
|
15
|
+
if (fs.lstatSync(argPath).isDirectory()) {
|
|
16
|
+
const children = fs.readdirSync(argPath);
|
|
17
|
+
return children
|
|
18
|
+
.filter((child) => child.endsWith(".zip") &&
|
|
19
|
+
fs.lstatSync(path.join(argPath, child)).isFile())
|
|
20
|
+
.map((child) => path.join(argPath, child));
|
|
21
|
+
}
|
|
22
|
+
return [path.resolve(argPath)];
|
|
23
|
+
}
|
|
24
|
+
async function migrateZip(zipPath) {
|
|
25
|
+
const file = fs.readFileSync(zipPath);
|
|
26
|
+
const docZip = new JSZip();
|
|
27
|
+
await docZip.loadAsync(file);
|
|
28
|
+
const header = await loadFromZip(docZip, "header.json");
|
|
29
|
+
const operations = await loadFromZip(docZip, "operations.json");
|
|
30
|
+
const documentModel = docModelMap[header.documentType];
|
|
31
|
+
if (!documentModel) {
|
|
32
|
+
throw new Error(`Unknown document type: ${header.documentType}. Add it to docModelMap.`);
|
|
33
|
+
}
|
|
34
|
+
const result = Object.values(operations)
|
|
35
|
+
.flat()
|
|
36
|
+
.reduce((doc, operation) => {
|
|
37
|
+
const action = "action" in operation ? operation.action : operation;
|
|
38
|
+
return documentModel.reducer(doc, action);
|
|
39
|
+
}, documentModel.utils.createDocument());
|
|
40
|
+
const targetName = path.basename(zipPath, path.extname(zipPath));
|
|
41
|
+
const targetPath = path.resolve(zipPath, "../");
|
|
42
|
+
await documentModel.utils.saveToFile(result, targetPath, `${targetName}-migrated`);
|
|
43
|
+
console.info(`Migrated ${path.relative(process.cwd(), zipPath)} to ${path.relative(process.cwd(), path.join(targetPath, `${targetName}-migrated.${documentModel.documentModel.extension}.zip`))}`);
|
|
44
|
+
}
|
|
45
|
+
const paths = argv.length > 2 ? argv.slice(2) : [process.cwd()];
|
|
46
|
+
paths.forEach(async (val) => {
|
|
47
|
+
const resolvedPaths = await resolvePath(val);
|
|
48
|
+
for (const zipPath of resolvedPaths) {
|
|
49
|
+
try {
|
|
50
|
+
await migrateZip(zipPath);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.error(`Error migrating ${zipPath}`, e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
package/dist/style.css
CHANGED
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
--color-zinc-200: oklch(92% 0.004 286.32);
|
|
91
91
|
--color-zinc-500: oklch(55.2% 0.016 285.938);
|
|
92
92
|
--color-zinc-600: oklch(44.2% 0.017 285.786);
|
|
93
|
+
--color-stone-300: oklch(86.9% 0.005 56.366);
|
|
93
94
|
--color-black: #000;
|
|
94
95
|
--color-white: #fff;
|
|
95
96
|
--spacing: 0.25rem;
|
|
@@ -1999,6 +2000,7 @@
|
|
|
1999
2000
|
--color-zinc-200: oklch(92% 0.004 286.32);
|
|
2000
2001
|
--color-zinc-500: oklch(55.2% 0.016 285.938);
|
|
2001
2002
|
--color-zinc-600: oklch(44.2% 0.017 285.786);
|
|
2003
|
+
--color-stone-300: oklch(86.9% 0.005 56.366);
|
|
2002
2004
|
--color-black: hsl(0 0% 0%);
|
|
2003
2005
|
--color-white: hsl(0 0% 100%);
|
|
2004
2006
|
--spacing: 0.25rem;
|
|
@@ -3753,6 +3755,9 @@
|
|
|
3753
3755
|
.text-slate-800 {
|
|
3754
3756
|
color: var(--color-slate-800);
|
|
3755
3757
|
}
|
|
3758
|
+
.text-stone-300 {
|
|
3759
|
+
color: var(--color-stone-300);
|
|
3760
|
+
}
|
|
3756
3761
|
.text-white {
|
|
3757
3762
|
color: var(--color-white);
|
|
3758
3763
|
}
|
|
@@ -4387,6 +4392,13 @@
|
|
|
4387
4392
|
}
|
|
4388
4393
|
}
|
|
4389
4394
|
}
|
|
4395
|
+
.hover\:bg-blue-600 {
|
|
4396
|
+
&:hover {
|
|
4397
|
+
@media (hover: hover) {
|
|
4398
|
+
background-color: var(--color-blue-600);
|
|
4399
|
+
}
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4390
4402
|
.hover\:bg-gray-50 {
|
|
4391
4403
|
&:hover {
|
|
4392
4404
|
@media (hover: hover) {
|
|
@@ -4422,6 +4434,13 @@
|
|
|
4422
4434
|
}
|
|
4423
4435
|
}
|
|
4424
4436
|
}
|
|
4437
|
+
.hover\:bg-slate-100 {
|
|
4438
|
+
&:hover {
|
|
4439
|
+
@media (hover: hover) {
|
|
4440
|
+
background-color: var(--color-slate-100);
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4425
4444
|
.hover\:bg-slate-800 {
|
|
4426
4445
|
&:hover {
|
|
4427
4446
|
@media (hover: hover) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/contributor-billing",
|
|
3
3
|
"description": "Document models that help contributors of open organisations get paid anonymously for their work on a monthly basis.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.91",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@google-cloud/documentai": "^8.12.0",
|
|
60
|
-
"@powerhousedao/builder-tools": "^5.0.0-staging.
|
|
61
|
-
"@powerhousedao/common": "^5.0.0-staging.
|
|
62
|
-
"@powerhousedao/design-system": "^5.0.0-staging.
|
|
60
|
+
"@powerhousedao/builder-tools": "^5.0.0-staging.18",
|
|
61
|
+
"@powerhousedao/common": "^5.0.0-staging.18",
|
|
62
|
+
"@powerhousedao/design-system": "^5.0.0-staging.18",
|
|
63
63
|
"@powerhousedao/document-engineering": "^1.37.0",
|
|
64
64
|
"@react-pdf/renderer": "^4.3.0",
|
|
65
65
|
"@safe-global/api-kit": "^3.0.1",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@types/cors": "^2.8.17",
|
|
70
70
|
"axios": "^1.9.0",
|
|
71
71
|
"cors": "^2.8.5",
|
|
72
|
-
"document-model": "^5.0.0-staging.
|
|
72
|
+
"document-model": "^5.0.0-staging.18",
|
|
73
73
|
"dotenv": "^16.5.0",
|
|
74
74
|
"error": "^10.4.0",
|
|
75
75
|
"ethers": "^6.14.0",
|
|
@@ -85,23 +85,24 @@
|
|
|
85
85
|
"@electric-sql/pglite": "^0.2.12",
|
|
86
86
|
"@eslint/js": "^9.25.0",
|
|
87
87
|
"@powerhousedao/analytics-engine-core": "^0.5.0",
|
|
88
|
-
"@powerhousedao/codegen": "^5.0.0-staging.
|
|
89
|
-
"@powerhousedao/ph-cli": "^5.0.0-staging.
|
|
90
|
-
"@powerhousedao/reactor-api": "^5.0.0-staging.
|
|
91
|
-
"@powerhousedao/reactor-browser": "^5.0.0-staging.
|
|
92
|
-
"@powerhousedao/reactor-local": "^5.0.0-staging.
|
|
88
|
+
"@powerhousedao/codegen": "^5.0.0-staging.18",
|
|
89
|
+
"@powerhousedao/ph-cli": "^5.0.0-staging.18",
|
|
90
|
+
"@powerhousedao/reactor-api": "^5.0.0-staging.18",
|
|
91
|
+
"@powerhousedao/reactor-browser": "^5.0.0-staging.18",
|
|
92
|
+
"@powerhousedao/reactor-local": "^5.0.0-staging.18",
|
|
93
93
|
"@powerhousedao/scalars": "^1.33.1-staging.5",
|
|
94
|
-
"@powerhousedao/switchboard": "^5.0.0-staging.
|
|
94
|
+
"@powerhousedao/switchboard": "^5.0.0-staging.18",
|
|
95
95
|
"@tailwindcss/cli": "^4.1.4",
|
|
96
96
|
"@testing-library/react": "^16.3.0",
|
|
97
97
|
"@types/node": "^22.14.1",
|
|
98
98
|
"@types/react": "^18.3.20",
|
|
99
99
|
"@vitejs/plugin-react": "^4.4.1",
|
|
100
|
-
"document-drive": "^5.0.0-staging.
|
|
100
|
+
"document-drive": "^5.0.0-staging.18",
|
|
101
101
|
"eslint": "^9.25.0",
|
|
102
102
|
"eslint-plugin-react": "^7.37.5",
|
|
103
103
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
104
104
|
"globals": "^16.0.0",
|
|
105
|
+
"jszip": "^3.10.1",
|
|
105
106
|
"package-manager-detector": "^0.2.8",
|
|
106
107
|
"pm2": "^5.4.3",
|
|
107
108
|
"react": "^18.3.1",
|