fix: expose client fetch and signed adjustments
Quality / quality (ubuntu-latest) (push) Failing after 9m49s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 18:56:05 +05:30
parent 6258495b67
commit 4be4b2c346
8 changed files with 64 additions and 8 deletions
+3 -3
View File
@@ -235,7 +235,7 @@
},
"packages/auth": {
"name": "@wrnexus/auth",
"version": "0.8.17",
"version": "0.8.18",
"dependencies": {
"@wrnexus/authz": "workspace:*",
"@wrnexus/captcha": "workspace:*",
@@ -342,7 +342,7 @@
},
"packages/csr": {
"name": "@wrnexus/csr",
"version": "0.8.31",
"version": "0.8.32",
"dependencies": {
"@wrnexus/core": "workspace:*",
},
@@ -501,7 +501,7 @@
},
"packages/metering": {
"name": "@wrnexus/metering",
"version": "0.8.2",
"version": "0.8.3",
},
"packages/mobile": {
"name": "@wrnexus/mobile",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/auth",
"version": "0.8.17",
"version": "0.8.18",
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
"type": "module",
"sideEffects": false,
+5
View File
@@ -1672,6 +1672,11 @@ export function createAuthEngine(options: AuthEngineOptions): AuthEngine {
(typeof metadata.deviceId === "string" ? metadata.deviceId : undefined),
trusted: Boolean(rememberedDevice) || input.session?.trusted === true,
fingerprint: typeof metadata.fingerprint === "string" ? metadata.fingerprint : undefined,
metadata: {
...(input.session?.metadata ?? {}),
mfaVerifiedAt: now(),
mfaMethod: input.method,
},
});
user.lastLoginAt = now();
user.updatedAt = now();
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.8.31",
"version": "0.8.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+15
View File
@@ -19,6 +19,21 @@ export { ACTION_RUNTIME } from "./action-runtime.ts";
export { createApiClient } from "./api-client.ts";
export type { ApiClientOptions, ApiRequest } from "./api-client.ts";
/** Public client transport used by `.wrn` client functions for dynamic URLs. */
export function useFetch<T = unknown>(
path: string,
methodOrOptions?:
string | { method?: string; query?: unknown; params?: unknown; body?: unknown; data?: unknown },
input?: unknown,
): Promise<T> {
const client = (
globalThis as typeof globalThis & { useFetch?: (...args: unknown[]) => Promise<T> }
).useFetch;
if (!client)
return Promise.reject(new Error("WRN-CSR: useFetch is only available in the browser runtime"));
return client(path, methodOrOptions, input);
}
const CONTROLLER_SECTIONS = ["PRIMARY", "UI", "PIN"] as const;
function runtimeForMode(development: boolean): string {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/metering",
"version": "0.8.2",
"version": "0.8.3",
"private": true,
"type": "module",
"main": "src/index.ts",
+14 -2
View File
@@ -90,6 +90,10 @@ export function defineMeter(options: MeterOptions) {
Number.isSafeInteger(units) && units > 0
? null
: { ok: false, reason: `${label} must be a positive whole number` };
const validSigned = (units: number): MeterResult | null =>
Number.isSafeInteger(units) && units !== 0
? null
: { ok: false, reason: `${label} adjustment must be a non-zero whole number` };
const fault = (error: unknown, operation: string): MeterResult => {
options.onFault?.(error, operation);
return {
@@ -138,7 +142,15 @@ export function defineMeter(options: MeterOptions) {
add("purchase", subjectId, units, reason, reference),
refund: (subjectId: string, units: number, reason: string, reference = "") =>
add("refund", subjectId, units, reason, reference),
adjust: (subjectId: string, units: number, reason: string, reference = "") =>
add("adjust", subjectId, units, reason, reference),
async adjust(subjectId: string, units: number, reason: string, reference = "") {
const invalid = validSigned(units);
if (invalid) return invalid;
try {
await options.store.write(subjectId, units, "adjust", reason, reference);
return { ok: true } as const;
} catch (error) {
return fault(error, "adjust");
}
},
};
}
+24
View File
@@ -40,3 +40,27 @@ test("meter distinguishes refusals from storage faults", async () => {
fault: true,
});
});
test("adjust accepts signed non-zero amounts while other additions stay positive", async () => {
const writes: number[] = [];
const meter = defineMeter({
store: {
balance: async () => 0,
reserve: async () => true,
write: async (_subject, units) => {
writes.push(units);
},
},
});
expect(await meter.adjust("u1", -25, "correction")).toEqual({ ok: true });
expect(await meter.adjust("u1", 10, "correction")).toEqual({ ok: true });
expect(await meter.adjust("u1", 0, "correction")).toEqual({
ok: false,
reason: "units adjustment must be a non-zero whole number",
});
expect(await meter.grant("u1", -1, "invalid")).toEqual({
ok: false,
reason: "units must be a positive whole number",
});
expect(writes).toEqual([-25, 10]);
});