From 6b261f4e3f37b5eee48f030746c7e79e7fb7c1e1 Mon Sep 17 00:00:00 2001 From: Rob Knight Date: Fri, 13 Sep 2024 19:23:02 +0200 Subject: [PATCH] GPC proofs in test client --- apps/client-web/.gitignore | 1 + apps/client-web/index.html | 2 +- apps/client-web/package.json | 5 +- apps/client-web/src/App.tsx | 278 ++++++++++++++++-- apps/client-web/src/client/gpc.ts | 9 +- apps/client-web/src/client/pod.ts | 21 +- apps/client-web/src/client/pod_collection.ts | 6 +- .../src/client/query_subscriptions.ts | 12 +- apps/client-web/src/client/utils.ts | 20 -- apps/client-web/src/state.ts | 8 + apps/client-web/vite.config.ts | 5 +- examples/test-app/src/apis/GPC.tsx | 26 +- .../client-helpers/src/connection/iframe.ts | 37 ++- packages/podspec/src/gpc/proof_request.ts | 4 +- packages/podspec/src/parse/pod.ts | 14 +- pnpm-lock.yaml | 29 +- 16 files changed, 372 insertions(+), 105 deletions(-) diff --git a/apps/client-web/.gitignore b/apps/client-web/.gitignore index a547bf3..c6d388a 100644 --- a/apps/client-web/.gitignore +++ b/apps/client-web/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +public/artifacts/* diff --git a/apps/client-web/index.html b/apps/client-web/index.html index 1975e38..1f85e1a 100644 --- a/apps/client-web/index.html +++ b/apps/client-web/index.html @@ -5,7 +5,7 @@ PARCNET Client - +
diff --git a/apps/client-web/package.json b/apps/client-web/package.json index 72fc2c0..57c8ec4 100644 --- a/apps/client-web/package.json +++ b/apps/client-web/package.json @@ -19,8 +19,7 @@ "eventemitter3": "^5.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "vite-plugin-node-polyfills": "^0.22.0", - "zod": "^3.23.8" + "vite-plugin-node-polyfills": "^0.22.0" }, "devDependencies": { "@parcnet/eslint-config": "workspace:*", @@ -33,6 +32,6 @@ "postcss": "^8.4.41", "tailwindcss": "^3.4.10", "typescript": "^5.5", - "vite": "^5.4.1" + "vite": "^5.4.4" } } diff --git a/apps/client-web/src/App.tsx b/apps/client-web/src/App.tsx index c428e2a..b92d619 100644 --- a/apps/client-web/src/App.tsx +++ b/apps/client-web/src/App.tsx @@ -1,6 +1,16 @@ import { listen } from "@parcnet/client-helpers/connection/iframe"; import { Zapp } from "@parcnet/client-rpc"; -import { Dispatch, ReactNode, useEffect, useReducer } from "react"; +import { EntriesSchema, PODSchema, proofRequest } from "@parcnet/podspec"; +import { gpcProve } from "@pcd/gpc"; +import { POD, POD_INT_MAX, POD_INT_MIN } from "@pcd/pod"; +import { + Dispatch, + Fragment, + ReactNode, + useEffect, + useReducer, + useState +} from "react"; import { ParcnetClientProcessor } from "./client/client"; import { PODCollection } from "./client/pod_collection"; import { loadPODsFromStorage, savePODsToStorage } from "./client/utils"; @@ -67,18 +77,173 @@ function App() { state.authorized && state.zapp && state.proofInProgress && ( - + )} ); } +function Reveal({ children }: { children: ReactNode }) { + const [isRevealed, setIsRevealed] = useState(false); + return ( + <> + + {isRevealed &&
{children}
} + + ); +} + +function ProvePODInfo({ + name, + schema, + pods, + selectedPOD, + onChange +}: { + name: string; + schema: PODSchema; + pods: POD[]; + selectedPOD: POD | undefined; + onChange: (pod: POD | undefined) => void; +}): ReactNode { + const revealedEntries = Object.entries(schema.entries) + .map(([name, entry]) => { + if (entry.type === "optional") { + entry = entry.innerType; + } + return [name, entry] as const; + }) + .filter(([_, entry]) => entry.isRevealed); + + const selectedPODEntries = selectedPOD?.content.asEntries(); + + const entriesWithConstraints = Object.entries(schema.entries) + .map(([name, entry]) => { + if (entry.type === "optional") { + entry = entry.innerType; + } + return [name, entry] as const; + }) + .filter( + ([_, entry]) => + !!entry.isMemberOf || + !!entry.isNotMemberOf || + !!(entry.type === "int" && entry.inRange) + ); + + return ( +
+
+
{name}
+ +
+
+ {revealedEntries.length > 0 && "Revealed entries:"} +
+
+ {revealedEntries.map(([entryName, _]) => { + return ( + +
{entryName}
+
+ {selectedPODEntries?.[entryName].value.toString() ?? "-"} +
+
+ ); + })} +
+ {entriesWithConstraints.length > 0 && ( +
+
Proven constraints:
+ {entriesWithConstraints.map(([entryName, entry]) => { + return ( +
+ {entry.isMemberOf && ( +
+ {entryName} is member + of list:{" "} + +
+ {entry.isMemberOf + .map((v) => v.value.toString()) + .join(", ")} +
+
+
+ )} + {entry.isNotMemberOf && ( +
+ {entryName} is not + member of list:{" "} + +
+ {entry.isNotMemberOf + .map((v) => v.value.toString()) + .join(", ")} +
+
+
+ )} + {entry.type === "int" && entry.inRange && ( +
+ {entryName} is +
+ {entry.inRange.min === POD_INT_MIN && + entry.inRange.max === POD_INT_MAX && + "any number"} + {entry.inRange.min !== POD_INT_MIN && + entry.inRange.max === POD_INT_MAX && + `greater than ${entry.inRange.min}`} + {entry.inRange.min === POD_INT_MIN && + entry.inRange.max !== POD_INT_MAX && + `less than ${entry.inRange.max}`} + {entry.inRange.min !== POD_INT_MIN && + entry.inRange.max !== POD_INT_MAX && + `between ${entry.inRange.min} and ${entry.inRange.max}`} +
+
+ )} +
+ ); + })} +
+ )} +
+ ); +} + function Prove({ - proveOperation + proveOperation, + dispatch }: { proveOperation: NonNullable; + dispatch: Dispatch; }): ReactNode { + const canProve = + Object.keys(proveOperation.selectedPods).length === + Object.keys(proveOperation.proofRequest.pods).length && + Object.values(proveOperation.selectedPods).every((maybePod) => !!maybePod); + /** * show exactly which fields are revealed and which are not, literally show * the whole POD and which entries are revealed @@ -86,25 +251,94 @@ function Prove({ */ return (
-
    - {Object.entries(proveOperation.pods).map(([key, pods]) => { - return ( -
    -

    {key}

    -
    - {pods.map((pod) => { - return ( -
    - {pod.contentID.toString()} - {pod.serialize()} -
    - ); - })} -
    -
    - ); - })} -
+
+

This proof will reveal the following data from your PODs:

+ {Object.entries(proveOperation.proofRequest.pods).map( + ([name, schema]) => { + return ( + { + dispatch({ + type: "set-proof-in-progress", + ...proveOperation, + selectedPods: { + ...proveOperation.selectedPods, + ...{ [name]: pod } + } + }); + }} + /> + ); + } + )} +
+ +
+
); } diff --git a/apps/client-web/src/client/gpc.ts b/apps/client-web/src/client/gpc.ts index 2c940e8..50344dc 100644 --- a/apps/client-web/src/client/gpc.ts +++ b/apps/client-web/src/client/gpc.ts @@ -1,14 +1,9 @@ import { ConnectorAdvice } from "@parcnet/client-helpers"; -import { - ParcnetGPCRPC, - ParcnetRPCSchema, - ProveResult -} from "@parcnet/client-rpc"; +import { ParcnetGPCRPC, ProveResult } from "@parcnet/client-rpc"; import { PodspecProofRequest, proofRequest } from "@parcnet/podspec"; import { Dispatch } from "react"; import { ClientAction } from "../state"; import { PODCollection } from "./pod_collection"; -import { validateInput } from "./utils"; export class ParcnetGPCProcessor implements ParcnetGPCRPC { public constructor( @@ -17,7 +12,6 @@ export class ParcnetGPCProcessor implements ParcnetGPCRPC { private readonly advice: ConnectorAdvice ) {} - @validateInput(ParcnetRPCSchema.shape.gpc.shape.canProve) public async canProve(request: PodspecProofRequest): Promise { const prs = proofRequest(request); @@ -31,7 +25,6 @@ export class ParcnetGPCProcessor implements ParcnetGPCRPC { return true; } - @validateInput(ParcnetRPCSchema.shape.gpc.shape.prove) public async prove(request: PodspecProofRequest): Promise { const prs = proofRequest(request); diff --git a/apps/client-web/src/client/pod.ts b/apps/client-web/src/client/pod.ts index f8b25d1..5d4e338 100644 --- a/apps/client-web/src/client/pod.ts +++ b/apps/client-web/src/client/pod.ts @@ -1,10 +1,8 @@ -import { ParcnetPODRPC, ParcnetRPCSchema } from "@parcnet/client-rpc"; -import * as p from "@parcnet/podspec"; +import { ParcnetPODRPC } from "@parcnet/client-rpc"; import { EntriesSchema, PODSchema } from "@parcnet/podspec"; import { POD } from "@pcd/pod"; import { PODCollection } from "./pod_collection.js"; import { QuerySubscriptions } from "./query_subscriptions.js"; -import { validateInput } from "./utils.js"; export class ParcnetPODProcessor implements ParcnetPODRPC { public constructor( @@ -12,28 +10,27 @@ export class ParcnetPODProcessor implements ParcnetPODRPC { private readonly subscriptions: QuerySubscriptions ) {} - @validateInput(ParcnetRPCSchema.shape.pod.shape.query) - public async query(query: PODSchema): Promise { - return this.pods.query(p.pod(query)).map((pod) => pod.serialize()); + public async query( + query: PODSchema + ): Promise { + return this.pods.query(query).map((pod) => pod.serialize()); } - @validateInput(ParcnetRPCSchema.shape.pod.shape.insert) public async insert(serializedPod: string): Promise { const pod = POD.deserialize(serializedPod); this.pods.insert(pod); } - @validateInput(ParcnetRPCSchema.shape.pod.shape.delete) public async delete(signature: string): Promise { this.pods.delete(signature); } - @validateInput(ParcnetRPCSchema.shape.pod.shape.subscribe) - public async subscribe(query: PODSchema): Promise { - return this.subscriptions.subscribe(p.pod(query)); + public async subscribe( + query: PODSchema + ): Promise { + return this.subscriptions.subscribe(query); } - @validateInput(ParcnetRPCSchema.shape.pod.shape.unsubscribe) public async unsubscribe(subscriptionId: string): Promise { this.subscriptions.unsubscribe(subscriptionId); } diff --git a/apps/client-web/src/client/pod_collection.ts b/apps/client-web/src/client/pod_collection.ts index 37c112d..3fa4adf 100644 --- a/apps/client-web/src/client/pod_collection.ts +++ b/apps/client-web/src/client/pod_collection.ts @@ -2,8 +2,6 @@ import * as p from "@parcnet/podspec"; import { POD } from "@pcd/pod"; import { EventEmitter } from "eventemitter3"; -type PODQuery = ReturnType; - export interface PODCollectionUpdate { type: "insert" | "delete"; affectedPOD: POD; @@ -38,9 +36,9 @@ export class PODCollection { } } - public query(query: PODQuery): POD[] { + public query(query: p.PODSchema): POD[] { console.log(query); - return query.query(this.pods).matches; + return p.pod(query).query(this.pods).matches; } public onUpdate(listener: (update: PODCollectionUpdate) => void): void { diff --git a/apps/client-web/src/client/query_subscriptions.ts b/apps/client-web/src/client/query_subscriptions.ts index a8d1728..88690e3 100644 --- a/apps/client-web/src/client/query_subscriptions.ts +++ b/apps/client-web/src/client/query_subscriptions.ts @@ -1,5 +1,6 @@ import { SubscriptionUpdateResult } from "@parcnet/client-rpc"; -import { EntriesSchema, PodSpec } from "@parcnet/podspec"; +import * as p from "@parcnet/podspec"; +import { EntriesSchema, PODSchema, PodSpec } from "@parcnet/podspec"; import { EventEmitter } from "eventemitter3"; import { PODCollection } from "./pod_collection.js"; @@ -57,9 +58,14 @@ export class QuerySubscriptions { }); } - public async subscribe(query: PodSpec): Promise { + public async subscribe( + query: PODSchema + ): Promise { const subscriptionId = (this.nextSubscriptionId++).toString(); - this.subscriptions.set(subscriptionId, { query, serial: 0 }); + this.subscriptions.set(subscriptionId, { + query: p.pod(query) as PodSpec, + serial: 0 + }); return subscriptionId; } diff --git a/apps/client-web/src/client/utils.ts b/apps/client-web/src/client/utils.ts index abaacc4..00e5729 100644 --- a/apps/client-web/src/client/utils.ts +++ b/apps/client-web/src/client/utils.ts @@ -1,24 +1,4 @@ import { POD } from "@pcd/pod"; -import { z } from "zod"; - -export function validateInput( - parser: z.ZodSchema -) { - return function actualDecorator( - originalMethod: (this: This, ...args: Args) => Return, - context: ClassMethodDecoratorContext - ): (this: This, ...args: Args) => Return { - function replacementMethod(this: This, ...args: Args): Return { - const input = parser.safeParse(args); - if (!input.success) { - throw new Error(`Invalid arguments for ${context.name.toString()}`); - } - return originalMethod.call(this, ...input.data); - } - - return replacementMethod; - }; -} export function loadPODsFromStorage(): POD[] { let pods: POD[] = []; diff --git a/apps/client-web/src/state.ts b/apps/client-web/src/state.ts index 9e7169c..0e2daaa 100644 --- a/apps/client-web/src/state.ts +++ b/apps/client-web/src/state.ts @@ -43,6 +43,9 @@ export type ClientAction = proofRequest: PodspecProofRequest; proving: boolean; resolve?: (result: ProveResult) => void; + } + | { + type: "clear-proof-in-progress"; }; export function clientReducer(state: ClientState, action: ClientAction) { @@ -66,5 +69,10 @@ export function clientReducer(state: ClientState, action: ClientAction) { resolve: action.resolve } }; + case "clear-proof-in-progress": + return { + ...state, + proofInProgress: undefined + }; } } diff --git a/apps/client-web/vite.config.ts b/apps/client-web/vite.config.ts index 87c0b82..88235f0 100644 --- a/apps/client-web/vite.config.ts +++ b/apps/client-web/vite.config.ts @@ -9,5 +9,8 @@ export default defineConfig({ nodePolyfills({ include: ["assert", "buffer"] }) - ] + ], + esbuild: { + target: "es2020" + } }); diff --git a/examples/test-app/src/apis/GPC.tsx b/examples/test-app/src/apis/GPC.tsx index 8db1d95..4dc655e 100644 --- a/examples/test-app/src/apis/GPC.tsx +++ b/examples/test-app/src/apis/GPC.tsx @@ -1,4 +1,5 @@ import { PodspecProofRequest } from "@parcnet/podspec"; +import JSONBig from "json-bigint"; import { ReactNode, useState } from "react"; import { ProveResult } from "../../../../packages/client-rpc/src"; import { TryIt } from "../components/TryIt"; @@ -8,7 +9,11 @@ const request: PodspecProofRequest = { pods: { pod1: { entries: { - wis: { type: "int", inRange: { min: BigInt(5), max: BigInt(1000) } }, + wis: { + type: "int", + inRange: { min: BigInt(5), max: BigInt(1000) }, + isRevealed: true + }, str: { type: "int", inRange: { min: BigInt(5), max: BigInt(1000) } } } }, @@ -16,7 +21,8 @@ const request: PodspecProofRequest = { entries: { test: { type: "string", - isMemberOf: [{ type: "string", value: "secret" }] + isMemberOf: [{ type: "string", value: "secret" }], + isRevealed: true } } } @@ -41,7 +47,11 @@ const request: PodspecProofRequest = { pods: { pod1: { entries: { - wis: { type: "int", inRange: { min: BigInt(5), max: BigInt(1000) } }, + wis: { + type: "int", + inRange: { min: BigInt(5), max: BigInt(1000) }, + isRevealed: true + }, str: { type: "int", inRange: { min: BigInt(5), max: BigInt(1000) } } } }, @@ -49,15 +59,17 @@ const request: PodspecProofRequest = { entries: { test: { type: "string", - isMemberOf: [{ type: "string", value: "secret" }] + isMemberOf: [{ type: "string", value: "secret" }], + isRevealed: true } } } } }; - + +const gpcProof = await z.gpc.prove(request); + `} - const gpcProof = await z.gpc.prove(request);

{proof && (
-              {JSON.stringify(proof, null, 2)}
+              {JSONBig.stringify(proof, null, 2)}
             
)} diff --git a/packages/client-helpers/src/connection/iframe.ts b/packages/client-helpers/src/connection/iframe.ts index f55b07c..f711f7f 100644 --- a/packages/client-helpers/src/connection/iframe.ts +++ b/packages/client-helpers/src/connection/iframe.ts @@ -3,6 +3,8 @@ import { InitializationMessageSchema, InitializationMessageType, ParcnetRPC, + ParcnetRPCMethodName, + ParcnetRPCSchema, RPCMessage, RPCMessageSchema, RPCMessageType, @@ -58,6 +60,32 @@ export class AdviceChannel implements ConnectorAdvice { } } +function getSchema(method: ParcnetRPCMethodName) { + switch (method) { + case "gpc.canProve": + return ParcnetRPCSchema.shape.gpc.shape.canProve; + case "gpc.prove": + return ParcnetRPCSchema.shape.gpc.shape.prove; + case "gpc.verify": + return ParcnetRPCSchema.shape.gpc.shape.verify; + case "identity.getSemaphoreV3Commitment": + return ParcnetRPCSchema.shape.identity.shape.getSemaphoreV3Commitment; + case "pod.query": + return ParcnetRPCSchema.shape.pod.shape.query; + case "pod.insert": + return ParcnetRPCSchema.shape.pod.shape.insert; + case "pod.delete": + return ParcnetRPCSchema.shape.pod.shape.delete; + case "pod.subscribe": + return ParcnetRPCSchema.shape.pod.shape.subscribe; + case "pod.unsubscribe": + return ParcnetRPCSchema.shape.pod.shape.unsubscribe; + default: + const unknownMethod: never = method; + throw new Error(`Unknown method: ${unknownMethod as string}`); + } +} + async function handleMessage( rpc: ParcnetRPC, port: MessagePort, @@ -71,11 +99,16 @@ async function handleMessage( } const object = deepGet(rpc, path); const functionToInvoke = (object as Record)[functionName]; + try { if (functionToInvoke && typeof functionToInvoke === "function") { + const schema = getSchema(message.fn); + const parsedArgs = schema.parameters().parse(message.args); try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const result = await functionToInvoke.apply(object, message.args); + const result = await schema + .returnType() + .parse(functionToInvoke.apply(object, parsedArgs)); + port.postMessage({ type: RPCMessageType.PARCNET_CLIENT_INVOKE_RESULT, result, diff --git a/packages/podspec/src/gpc/proof_request.ts b/packages/podspec/src/gpc/proof_request.ts index b85008c..2975e21 100644 --- a/packages/podspec/src/gpc/proof_request.ts +++ b/packages/podspec/src/gpc/proof_request.ts @@ -28,7 +28,9 @@ export type ProofRequest = { * A PodspecProofRequest allows us to generate a {@link ProofRequest} from a * set of Podspecs defining the allowable PODs. */ -export interface PodspecProofRequest

> { +export interface PodspecProofRequest< + P extends Record = Record> +> { pods: Readonly<{ [K in keyof P]: P[K] extends PODSchema ? P[K] & PODSchema diff --git a/packages/podspec/src/parse/pod.ts b/packages/podspec/src/parse/pod.ts index e906d1d..04dd958 100644 --- a/packages/podspec/src/parse/pod.ts +++ b/packages/podspec/src/parse/pod.ts @@ -54,7 +54,7 @@ export class PodSpec { * * @param schema The schema for the POD. */ - private constructor(schema: PODSchema>) { + private constructor(schema: PODSchema) { this.schema = Object.freeze(schema); } @@ -108,9 +108,14 @@ export class PodSpec { public query(input: POD[]): { matches: POD[]; matchingIndexes: number[] } { const matchingIndexes: number[] = []; const matches: POD[] = []; + const signatures = new Set(); for (const [index, pod] of input.entries()) { const result = this.safeParse(pod, { exitEarly: true }); if (result.isValid) { + if (signatures.has(pod.signature)) { + continue; + } + signatures.add(pod.signature); matchingIndexes.push(index); matches.push(pod); } @@ -142,7 +147,7 @@ export class PodSpec { * @returns A new PodSpec instance. */ public static create( - schema: PODSchema> + schema: PODSchema ): PodSpec { return new PodSpec(schema); } @@ -151,9 +156,8 @@ export class PodSpec { /** * Exported version of static create method, for convenience. */ -export const pod = ( - schema: PODSchema> -) => PodSpec.create(schema); +export const pod = (schema: PODSchema) => + PodSpec.create(schema); /** * Parses the POD and its entries, returning a {@link ParseResult}. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f9fdaec..3404ec0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -131,10 +131,7 @@ importers: version: 18.3.1(react@18.3.1) vite-plugin-node-polyfills: specifier: ^0.22.0 - version: 0.22.0(rollup@4.21.2)(vite@5.4.2(@types/node@22.5.4)) - zod: - specifier: ^3.23.8 - version: 3.23.8 + version: 0.22.0(rollup@4.21.2)(vite@5.4.4(@types/node@22.5.4)) devDependencies: '@parcnet/eslint-config': specifier: workspace:* @@ -147,7 +144,7 @@ importers: version: 18.3.0 '@vitejs/plugin-react': specifier: ^4.3.1 - version: 4.3.1(vite@5.4.2(@types/node@22.5.4)) + version: 4.3.1(vite@5.4.4(@types/node@22.5.4)) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.44) @@ -167,8 +164,8 @@ importers: specifier: ^5.5 version: 5.5.4 vite: - specifier: ^5.4.1 - version: 5.4.2(@types/node@22.5.4) + specifier: ^5.4.4 + version: 5.4.4(@types/node@22.5.4) examples/test-app: dependencies: @@ -3639,8 +3636,8 @@ packages: peerDependencies: vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 - vite@5.4.2: - resolution: {integrity: sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==} + vite@5.4.4: + resolution: {integrity: sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4653,14 +4650,14 @@ snapshots: '@typescript-eslint/types': 8.4.0 eslint-visitor-keys: 3.4.3 - '@vitejs/plugin-react@4.3.1(vite@5.4.2(@types/node@22.5.4))': + '@vitejs/plugin-react@4.3.1(vite@5.4.4(@types/node@22.5.4))': dependencies: '@babel/core': 7.25.2 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.2(@types/node@22.5.4) + vite: 5.4.4(@types/node@22.5.4) transitivePeerDependencies: - supports-color @@ -7324,7 +7321,7 @@ snapshots: debug: 4.3.6 pathe: 1.1.2 tinyrainbow: 1.2.0 - vite: 5.4.2(@types/node@22.5.4) + vite: 5.4.4(@types/node@22.5.4) transitivePeerDependencies: - '@types/node' - less @@ -7336,15 +7333,15 @@ snapshots: - supports-color - terser - vite-plugin-node-polyfills@0.22.0(rollup@4.21.2)(vite@5.4.2(@types/node@22.5.4)): + vite-plugin-node-polyfills@0.22.0(rollup@4.21.2)(vite@5.4.4(@types/node@22.5.4)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.21.2) node-stdlib-browser: 1.2.0 - vite: 5.4.2(@types/node@22.5.4) + vite: 5.4.4(@types/node@22.5.4) transitivePeerDependencies: - rollup - vite@5.4.2(@types/node@22.5.4): + vite@5.4.4(@types/node@22.5.4): dependencies: esbuild: 0.21.5 postcss: 8.4.44 @@ -7371,7 +7368,7 @@ snapshots: tinybench: 2.9.0 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 5.4.2(@types/node@22.5.4) + vite: 5.4.4(@types/node@22.5.4) vite-node: 2.0.5(@types/node@22.5.4) why-is-node-running: 2.3.0 optionalDependencies: