release: WRNexusJS 0.8.0
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
/* global FormData, Headers, console */
|
||||
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import {
|
||||
createKeyring,
|
||||
createMemoryReplayStore,
|
||||
encryptHttpBody,
|
||||
decryptHttpBody,
|
||||
createEncryptedRequest,
|
||||
encryptResponse,
|
||||
decryptEncryptedResponse,
|
||||
} from "../packages/encryption/src/index.ts";
|
||||
import {
|
||||
createAccessToken,
|
||||
createRefreshToken,
|
||||
verifyAccessToken,
|
||||
verifyRefreshToken,
|
||||
hasScopes,
|
||||
jwtCookie,
|
||||
createTokenPair,
|
||||
readJwtCookie,
|
||||
} from "../packages/jwt/src/index.ts";
|
||||
import { createDb, createRepository, batch, databaseHealth } from "../packages/db/src/index.ts";
|
||||
import {
|
||||
loadLocales,
|
||||
resolveI18n,
|
||||
makeT,
|
||||
resolveLang,
|
||||
renderI18nData,
|
||||
} from "../packages/i18n/src/index.ts";
|
||||
import {
|
||||
createPicture,
|
||||
createBlurPlaceholder,
|
||||
imageCacheKey,
|
||||
} from "../packages/image/src/index.ts";
|
||||
import {
|
||||
createRealtimeMessage,
|
||||
parseRealtimeMessage,
|
||||
roomMemberSummary,
|
||||
} from "../packages/realtime/src/index.ts";
|
||||
import { captchaFields, captchaHeaders, captchaTokenFrom } from "../packages/captcha/src/index.ts";
|
||||
import { uploaderAttributes, formatFileSize } from "../packages/uploader/src/index.ts";
|
||||
import { v, parseOrThrow, validationSummary } from "../packages/validation/src/index.ts";
|
||||
import { authRoute, authFailure } from "../packages/auth/src/index.ts";
|
||||
|
||||
const keyring = createKeyring([
|
||||
{ id: "active", secret: "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA=", active: true },
|
||||
]);
|
||||
const replayStore = createMemoryReplayStore(() => 1_000);
|
||||
const envelope = await encryptHttpBody(
|
||||
{ value: 42 },
|
||||
{
|
||||
keyring,
|
||||
method: "POST",
|
||||
url: "https://example.test/api/items",
|
||||
requestId: "request-1",
|
||||
timestamp: 1_000,
|
||||
},
|
||||
);
|
||||
const decrypted = await decryptHttpBody(envelope, {
|
||||
keyring,
|
||||
method: "POST",
|
||||
url: "https://example.test/api/items",
|
||||
replayStore,
|
||||
now: () => 1_000,
|
||||
});
|
||||
assert.deepEqual(decrypted.body, { value: 42 });
|
||||
await assert.rejects(
|
||||
() =>
|
||||
decryptHttpBody(envelope, {
|
||||
keyring,
|
||||
method: "POST",
|
||||
url: "https://example.test/api/items",
|
||||
replayStore,
|
||||
now: () => 1_000,
|
||||
}),
|
||||
/REPLAY/,
|
||||
);
|
||||
await assert.rejects(
|
||||
() =>
|
||||
decryptHttpBody(envelope, {
|
||||
keyring,
|
||||
method: "GET",
|
||||
url: "https://example.test/api/items",
|
||||
now: () => 1_000,
|
||||
}),
|
||||
/CONTEXT/,
|
||||
);
|
||||
const encryptedRequest = await createEncryptedRequest(
|
||||
"https://example.test/api/items",
|
||||
{ value: 42 },
|
||||
{ keyring, method: "POST", requestId: "request-2" },
|
||||
);
|
||||
const encryptedResponse = await encryptResponse({ ok: true }, encryptedRequest, { keyring });
|
||||
assert.equal(
|
||||
(await decryptEncryptedResponse(encryptedResponse, encryptedRequest, { keyring })).body.ok,
|
||||
true,
|
||||
);
|
||||
|
||||
const secret = "a-secure-jwt-secret-for-package-kit-tests";
|
||||
const access = await createAccessToken("user-1", secret, {
|
||||
scopes: ["read", "write"],
|
||||
now: 100,
|
||||
expiresIn: 60,
|
||||
});
|
||||
const refresh = await createRefreshToken("user-1", secret, {
|
||||
family: "family-1",
|
||||
now: 100,
|
||||
expiresIn: 600,
|
||||
});
|
||||
const accessClaims = await verifyAccessToken(access, secret, { now: 120 });
|
||||
const refreshClaims = await verifyRefreshToken(refresh, secret, { now: 120 });
|
||||
assert.equal(accessClaims.sub, "user-1");
|
||||
assert.equal(refreshClaims.type, "refresh");
|
||||
assert.equal(hasScopes(accessClaims, ["read", "write"]), true);
|
||||
assert.match(jwtCookie(access), /^__Host-wrn_token=/);
|
||||
assert.equal(readJwtCookie(`__Host-wrn_token=${access}`), access);
|
||||
const tokenPair = await createTokenPair("user-1", {
|
||||
accessSecret: secret,
|
||||
accessOptions: { now: 100 },
|
||||
refreshOptions: { now: 100 },
|
||||
});
|
||||
assert.equal((await verifyAccessToken(tokenPair.accessToken, secret, { now: 120 })).sub, "user-1");
|
||||
|
||||
const queries = [];
|
||||
const driver = {
|
||||
dialect: "sqlite",
|
||||
async query(sql, params = []) {
|
||||
queries.push({ sql, params });
|
||||
if (/COUNT/.test(sql)) return [{ count: 2 }];
|
||||
if (/SELECT 1 AS healthy/.test(sql)) return [{ healthy: 1 }];
|
||||
return [{ id: 1, name: "One" }];
|
||||
},
|
||||
async exec(sql, params = []) {
|
||||
queries.push({ sql, params });
|
||||
return { changes: 1, lastInsertId: 1 };
|
||||
},
|
||||
async transaction(fn) {
|
||||
return fn(this);
|
||||
},
|
||||
close() {},
|
||||
};
|
||||
const db = createDb(driver);
|
||||
const repository = createRepository(db, { table: "items", allowedColumns: ["name"] });
|
||||
assert.equal((await repository.find(1)).name, "One");
|
||||
await repository.create({ name: "Two" });
|
||||
await repository.update(1, { name: "Changed" });
|
||||
assert.equal(await repository.count(), 2);
|
||||
assert.deepEqual(batch([1, 2, 3, 4, 5], 2), [[1, 2], [3, 4], [5]]);
|
||||
assert.equal((await databaseHealth(db)).ok, true);
|
||||
assert.ok(queries.some((entry) => /INSERT INTO items/.test(entry.sql)));
|
||||
assert.throws(() => batch([1, 2], Number.NaN), /finite/);
|
||||
|
||||
const localeDir = mkdtempSync(join(tmpdir(), "wrn-i18n-"));
|
||||
try {
|
||||
writeFileSync(join(localeDir, "en.json"), JSON.stringify({ common: { hello: "Hello {name}" } }));
|
||||
mkdirSync(join(localeDir, "fr"));
|
||||
writeFileSync(join(localeDir, "fr", "common.json"), JSON.stringify({ hello: "Bonjour {name}" }));
|
||||
const i18n = resolveI18n(loadLocales(localeDir, { strict: true }), {
|
||||
default: "en",
|
||||
locales: ["en", "fr"],
|
||||
});
|
||||
assert.equal(makeT(i18n, "fr")("common.hello", { name: "Ajay" }), "Bonjour Ajay");
|
||||
assert.equal(resolveLang(i18n, undefined, "fr;q=0.9,en;q=0.8"), "fr");
|
||||
assert.equal(resolveLang(i18n, undefined, "*"), "en");
|
||||
assert.match(renderI18nData(i18n, "fr"), /Bonjour/);
|
||||
} finally {
|
||||
rmSync(localeDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
const picture = createPicture({
|
||||
src: "/hero.jpg",
|
||||
alt: "Hero",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
widths: [480, 768, 1200],
|
||||
formats: ["avif", "webp"],
|
||||
});
|
||||
assert.equal(picture.sources.length, 2);
|
||||
assert.match(createBlurPlaceholder(), /^data:image\/svg\+xml/);
|
||||
assert.equal(
|
||||
imageCacheKey({ src: "/hero.jpg", width: 480 }),
|
||||
imageCacheKey({ src: "/hero.jpg", width: 480 }),
|
||||
);
|
||||
|
||||
const message = createRealtimeMessage({
|
||||
type: "message",
|
||||
room: "support",
|
||||
data: { text: "Hello" },
|
||||
});
|
||||
assert.equal(
|
||||
parseRealtimeMessage(JSON.stringify(message), { room: "support", allowedTypes: ["message"] })
|
||||
.room,
|
||||
"support",
|
||||
);
|
||||
assert.throws(
|
||||
() => parseRealtimeMessage(JSON.stringify(message), { room: "other" }),
|
||||
/does not match/,
|
||||
);
|
||||
assert.deepEqual(
|
||||
roomMemberSummary([
|
||||
{ userId: "1", status: "online" },
|
||||
{ userId: "2", status: "away" },
|
||||
]),
|
||||
{ total: 2, online: 1, away: 1, busy: 0 },
|
||||
);
|
||||
|
||||
const form = new FormData();
|
||||
form.set("wrn-captcha-response", "token");
|
||||
assert.equal(captchaTokenFrom(form), "token");
|
||||
assert.deepEqual(captchaFields("token"), { "wrn-captcha-response": "token" });
|
||||
assert.equal(new Headers(captchaHeaders("token")).get("x-wrn-captcha-token"), "token");
|
||||
|
||||
assert.equal(uploaderAttributes({ store: "public", multiple: true })["data-uploader"], "public");
|
||||
assert.match(formatFileSize(1024), /KB/);
|
||||
|
||||
const schema = v.object({ email: v.string().email() });
|
||||
assert.deepEqual(parseOrThrow(schema, { email: "user@example.com" }), {
|
||||
email: "user@example.com",
|
||||
});
|
||||
assert.deepEqual(validationSummary({ email: "Invalid" }), [{ field: "email", message: "Invalid" }]);
|
||||
assert.equal(authRoute("signIn", { basePath: "/auth" }), "/auth/sign-in");
|
||||
assert.equal((await authFailure("invalid", "Invalid").json()).ok, false);
|
||||
|
||||
console.log("Package kit runtime probes passed.");
|
||||
Reference in New Issue
Block a user