feat: add application productivity foundations
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 11:13:03 +05:30
parent 46195462c3
commit 64ab20cc95
42 changed files with 1533 additions and 40 deletions
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.8.9",
"version": "0.8.10",
"private": true,
"type": "module",
"main": "./src/index.ts",
@@ -23,6 +23,7 @@
"typescript": "^6.0.3"
},
"dependencies": {
"@wrnexus/core": "workspace:*"
"@wrnexus/core": "workspace:*",
"@wrnexus/db": "workspace:*"
}
}
+2
View File
@@ -160,3 +160,5 @@ export type {
DecryptedHttpBody,
ReplayStore,
} from "./http.ts";
export { defineSecretResource } from "./resource.ts";
export type { SecretResourceOptions } from "./resource.ts";
+53
View File
@@ -0,0 +1,53 @@
import type { Db } from "@wrnexus/db";
import { decrypt, encrypt } from "./index.ts";
export interface SecretResourceOptions<T extends Record<string, unknown>> {
db: () => Db;
table: string;
key: string | (() => string);
encrypted: readonly (keyof T & string)[];
hidden?: readonly (keyof T & string)[];
id?: string;
}
const SAFE = /^[A-Za-z_][A-Za-z0-9_]*$/;
/** Encrypt selected database fields and guarantee hidden fields never leave `safe()`. */
export function defineSecretResource<T extends Record<string, unknown>>(
options: SecretResourceOptions<T>,
) {
const checked = (value: string) => {
if (!SAFE.test(value)) throw new TypeError(`Unsafe secret resource identifier: ${value}`);
return value;
};
const table = checked(options.table);
const id = checked(options.id ?? "id");
const encrypted = options.encrypted.map(checked);
const hidden = new Set((options.hidden ?? options.encrypted).map(checked));
const key = () => (typeof options.key === "function" ? options.key() : options.key);
return {
async seal(input: T): Promise<T> {
const output = { ...input };
const writable = output as Record<string, unknown>;
for (const field of encrypted)
if (writable[field] !== undefined)
writable[field] = await encrypt(String(writable[field]), key());
return output;
},
async open(input: T): Promise<T> {
const output = { ...input };
const writable = output as Record<string, unknown>;
for (const field of encrypted)
if (writable[field]) writable[field] = await decrypt(String(writable[field]), key());
return output;
},
safe(input: T): Partial<T> {
return Object.fromEntries(
Object.entries(input).filter(([field]) => !hidden.has(field)),
) as Partial<T>;
},
async find(value: string | number): Promise<T | null> {
return options.db().one<T>(`SELECT * FROM ${table} WHERE ${id} = ?`, [value]);
},
};
}