A universal query and mutation library for seamless data fetching and state management, designed for use with React, Vue, Svelte, Solid, Qwik, and Astro. Built for modern JavaScript projects and Laravel/VormiaPHP backends.
Install VormiaQueryJS using your favorite package manager:
npm install vormiaqueryjs
bun add vormiaqueryjs
yarn add vormiaqueryjs
pnpm add vormiaqueryjs
import vormiaqueryjs from "npm:vormiaqueryjs";
โ ๏ธ VormiaQueryJS is not fully Deno-compatible due to Node.js built-ins. Use with caution.
After installing vormiaqueryjs
, you must also install the correct peer dependencies for your stack:
npm install @tanstack/react-query
npm install @tanstack/eslint-plugin-query
(optional)npm install @tanstack/vue-query
npm install @tanstack/eslint-plugin-query
(optional)npm install @tanstack/svelte-query
npm install @tanstack/eslint-plugin-query
(optional)npm install @tanstack/solid-query
npm install @tanstack/eslint-plugin-query
(optional)npm install @builder.io/qwik
npm install @tanstack/eslint-plugin-query
(optional)npm install @tanstack/react-query
npm install @tanstack/eslint-plugin-query
(optional)npm install react react-dom
(if not present, for React-based hooks/components)npm install axios
Note: VormiaQuery no longer prompts you to install peer dependencies after installation. Please refer to the instructions above and install the required dependencies for your framework manually. This change improves compatibility with bun, pnpm, and other package managers.
src/adapters/astro/useVormia.js
.setEncrypt
in useVormiaQuery
.useVrmAuth
โ useVormiaQueryAuth
, etc. Update your imports and usage accordingly.import React from "react";
import {
VormiaQueryProvider,
useVormiaQuery,
useVormiaQueryAuth,
useVormiaQueryAuthMutation,
} from "vormiaqueryjs";
function App() {
return (
<VormiaQueryProvider config={{ baseURL: "https://api.example.com" }}>
<CategoriesList />
</VormiaQueryProvider>
);
}
function CategoriesList() {
const { data, isLoading, error, refetch } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
setEncrypt: true, // Optional: encrypt request/response
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data?.response?.map((cat) => (
<li key={cat.id}>{cat.name}</li>
))}
</ul>
);
}
import React from "react";
import { useVormiaQuery } from "vormiaqueryjs";
function EncryptedCategoriesList() {
const { data, isLoading, error } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
setEncrypt: true,
});
if (isLoading) return <div>Loading (encrypted)...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data?.response?.map((cat) => (
<li key={cat.id}>{cat.name}</li>
))}
</ul>
);
}
Astro uses React Query under the hood for VormiaQueryJS hooks.
import { useVormiaQuery } from "vormiaqueryjs/adapters/astro";
export default function App() {
const { data, isLoading, error } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data?.response?.map((cat) => (
<li key={cat.id}>{cat.name}</li>
))}
</ul>
);
}
import { useVormiaQuery } from "vormiaqueryjs/adapters/astro";
export default function AppEncrypt() {
const { data, isLoading, error } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
setEncrypt: true,
});
if (isLoading) return <div>Loading (encrypted)...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data?.response?.map((cat) => (
<li key={cat.id}>{cat.name}</li>
))}
</ul>
);
}
<script setup>
import { useVormiaQuery } from 'vormiaqueryjs/adapters/vue';
const { data, error, isLoading, refetch } = useVormiaQuery({
endpoint: '/categories',
method: 'GET',
setEncrypt: true, // Optional: encrypt request/response
});
</script>
<template>
<div v-if="isLoading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="cat in data?.response" :key="cat.id">{{ cat.name }}</li>
</ul>
</template>
<script setup>
import { useVormiaQuery } from 'vormiaqueryjs/adapters/vue';
const { data, error, isLoading, refetch } = useVormiaQuery({
endpoint: '/categories',
method: 'GET',
setEncrypt: true,
});
</script>
<template>
<div v-if="isLoading">Loading (encrypted)...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="cat in data?.response" :key="cat.id">{{ cat.name }}</li>
</ul>
</template>
<script>
import { createVormiaStore } from 'vormiaqueryjs/adapters/svelte';
const store = createVormiaStore({ endpoint: '/categories', method: 'GET', setEncrypt: true });
</script>
{#if $store.loading}
<p>Loading...</p>
{:else if $store.error}
<p>Error: {$store.error.message}</p>
{:else}
<ul>
{#each $store.data?.response as cat}
<li>{cat.name}</li>
{/each}
</ul>
{/if}
<script>
import { createVormiaStore } from 'vormiaqueryjs/adapters/svelte';
const store = createVormiaStore({ endpoint: '/categories', method: 'GET', setEncrypt: true });
</script>
{#if $store.loading}
<p>Loading (encrypted)...</p>
{:else if $store.error}
<p>Error: {$store.error.message}</p>
{:else}
<ul>
{#each $store.data?.response as cat}
<li>{cat.name}</li>
{/each}
</ul>
{/if}
import { createVormiaResource } from "vormiaqueryjs/adapters/solid";
const [categories] = createVormiaResource({
endpoint: "/categories",
method: "GET",
setEncrypt: true, // Optional: encrypt request/response
});
function CategoriesList() {
return (
<ul>
{categories()?.response?.map((cat) => (
<li>{cat.name}</li>
))}
</ul>
);
}
import { createVormiaResource } from "vormiaqueryjs/adapters/solid";
const [categories] = createVormiaResource({
endpoint: "/categories",
method: "GET",
setEncrypt: true,
});
function EncryptedCategoriesList() {
return (
<ul>
{categories()?.response?.map((cat) => (
<li>{cat.name}</li>
))}
</ul>
);
}
import { useVormiaQuery } from "vormiaqueryjs/adapters/qwik";
export default function CategoriesList() {
const { data, isLoading, error } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
setEncrypt: true, // Optional: encrypt request/response
});
// Render logic for Qwik
}
import { useVormiaQuery } from "vormiaqueryjs/adapters/qwik";
export default function EncryptedCategoriesList() {
const { data, isLoading, error } = useVormiaQuery({
endpoint: "/categories",
method: "GET",
setEncrypt: true,
});
// Render logic for Qwik
}
VormiaQuery supports optional end-to-end encryption using RSA public/private key pairs.
โ ๏ธ Security Warning: Never expose your private key in any client-side (browser) application. Only use the public key in frontend code. The private key should only be used in secure, server-side (Node.js/SSR) environments for full encryption/decryption. Exposing your private key in the browser can compromise all encrypted data.
After installing vormiaqueryjs
, you can generate a secure RSA key pair using the built-in CLI tool:
npx vormiaquery-gen-keys
Or, if installed globally:
vormiaquery-gen-keys
Note: The CLI script is now implemented as a
.cjs
file for compatibility with Node.js projects using ES modules. You should still use the commandnpx vormiaquery-gen-keys
(orvormiaquery-gen-keys
if installed globally); the usage does not change for end users.
This will create two files in your project directory:
vormia_public.pem
(public key)vormia_private.pem
(private key).env
or config (both are needed for encryption/decryption)..env
or config.
Example .env entries:VORMIA_PRIVATE_KEY="<contents of vormia_private.pem>"
VORMIA_PUBLIC_KEY="<contents of vormia_public.pem>"
.env
, vormia_private.pem
, and vormia_public.pem
to your .gitignore
.Location | Needs Public Key | Needs Private Key | .env Recommended | .gitignore? | Delete PEM after? |
---|---|---|---|---|---|
Laravel Backend | Yes | Yes | Yes | Yes | Yes |
SSR/Node.js | Yes | Yes | Yes | Yes | Yes |
Browser Client | Yes | No | No | N/A | N/A |
Note: The
vormiaquery-gen-keys
CLI is included with thevormiaqueryjs
package and is available after installation. You can run it withnpx vormiaquery-gen-keys
(locally) orvormiaquery-gen-keys
(globally) to generate your RSA key pair for encryption support.
For Laravel backend integration with VormiaQueryJS, install the official Laravel package:
composer require vormiaphp/vormiaqueryphp
Follow the complete installation and usage instructions at:
The Laravel package provides middleware, helpers, and complete integration for encrypted API communication with VormiaQueryJS.
VormiaQuery supports configuration through environment variables. Create a .env
file in your project root:
VORMIA_API_URL=https://your-api.com/api/v1
VORMIA_AUTH_TOKEN_KEY=auth_token
VORMIA_TIMEOUT=30000
VORMIA_WITH_CREDENTIALS=false
import { useVormiaQueryAuth } from "vormiaqueryjs";
function LoginForm() {
const { login, isLoading, error, isAuthenticated } = useVormiaQueryAuth({
endpoint: "/auth/login",
encryptData: true,
storeToken: true,
onLoginSuccess: (data) => {
console.log("Login successful:", data.user);
},
});
const handleLogin = async (credentials) => {
try {
await login(credentials);
} catch (err) {
console.error("Login failed:", err);
}
};
if (isAuthenticated) return <div>Welcome back!</div>;
return (
<form
onSubmit={(e) => {
e.preventDefault();
handleLogin({ email: "[email protected]", password: "password" });
}}
>
<button type="submit" disabled={isLoading}>
{isLoading ? "Logging in..." : "Login"}
</button>
</form>
);
}
import { useVormiaQueryAuthMutation } from "vormiaqueryjs";
function AddCategory() {
const mutation = useVormiaQueryAuthMutation({
endpoint: "/categories",
method: "POST",
});
const handleAdd = async () => {
await mutation.mutate({ name: "New Category" });
};
return <button onClick={handleAdd}>Add Category</button>;
}
try {
await mutation.mutateAsync(data);
} catch (error) {
if (error.isValidationError()) {
// Handle validation errors
} else if (error.isUnauthorized()) {
// Handle auth errors
} else if (error.isServerError()) {
// Handle server errors
}
}
This project uses Vitest for all tests. Example:
npm test
MIT License. See LICENSE for details.
import { useVormiaQueryAuthMutation } from "vormiaqueryjs";
function SendSecret() {
const mutation = useVormiaQueryAuthMutation({
endpoint: "/secret",
method: "POST",
rsaEncrypt: true, // Enable RSA encryption
});
const handleSend = async () => {
await mutation.mutate({ message: "Top Secret" });
};
return <button onClick={handleSend}>Send Secret</button>;
}
import { VormiaClient } from "vormiaqueryjs";
const client = new VormiaClient({
baseURL: "https://api.example.com",
rsaEncrypt: true,
privateKey: process.env.VORMIA_PRIVATE_KEY,
publicKey: process.env.VORMIA_PUBLIC_KEY,
});
async function getEncryptedData() {
const response = await client.get("/secure-data");
// response.data is automatically decrypted
console.log(response.data);
}
import { useVormiaQuery } from "vormiaqueryjs";
const { data } = useVormiaQuery({
endpoint: "/profile",
method: "GET",
headers: {
"X-Requested-With": "VormiaQuery",
"X-Custom-Token": "abc123",
},
});
import { useVormiaQueryAuthMutation } from "vormiaqueryjs";
function RegisterForm() {
const mutation = useVormiaQueryAuthMutation({
endpoint: "/register",
method: "POST",
});
const handleRegister = async (formData) => {
try {
await mutation.mutateAsync(formData);
} catch (error) {
if (error.isValidationError()) {
// Show validation errors to the user
const errors = error.getValidationErrors();
alert(JSON.stringify(errors));
}
}
};
// ...form rendering
}
// pages/api/proxy.js
import { VormiaClient } from "vormiaqueryjs";
const client = new VormiaClient({
baseURL: "https://api.example.com",
rsaEncrypt: true,
privateKey: process.env.VORMIA_PRIVATE_KEY,
publicKey: process.env.VORMIA_PUBLIC_KEY,
});
export default async function handler(req, res) {
const apiRes = await client.get("/protected-data");
res.status(200).json(apiRes.data);
}