mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
Spellings the new majors removed, each fatal at import rather than at a call site, so the modules that held them could not load: - `Schema.Enum` — zod 4 dropped the capitalised alias. `.enum` is the property in both majors. - `z.string().ip()` — the address formats left `z.string()`; an IP is the union of `z.ipv4()` and `z.ipv6()`, which is what it always meant. - `invalid_type_error` — the per-cause message params folded into `error`. - `@noble/ciphers/chacha` — noble 2 exports a subpath only with its extension. `@noble/hashes/sha256` is `sha2.js` now. The `.js` form resolves under the old major too, so every noble import takes it. Two test files in packages/prisma could not load because of these; they run. Also drops an assignment nothing reads, in the job runner's failure branch: ESLint 10 moved no-useless-assignment into its recommended set. Co-authored-by: Hanzo Dev <[email protected]>
65 lines
1.5 KiB
TypeScript
65 lines
1.5 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
import { getIpAddress } from './get-ip-address';
|
|
|
|
// Either family. Zod 4 moved the address formats off `z.string()` and gave each
|
|
// its own schema, so "an IP" is said as the union it always was.
|
|
const ZIpSchema = z.union([z.ipv4(), z.ipv6()]);
|
|
|
|
export const ZRequestMetadataSchema = z.object({
|
|
ipAddress: ZIpSchema.optional(),
|
|
userAgent: z.string().optional(),
|
|
});
|
|
|
|
export type RequestMetadata = z.infer<typeof ZRequestMetadataSchema>;
|
|
|
|
export type ApiRequestMetadata = {
|
|
/**
|
|
* The general metadata of the request.
|
|
*/
|
|
requestMetadata: RequestMetadata;
|
|
|
|
/**
|
|
* The source of the request.
|
|
*/
|
|
source: 'apiV1' | 'apiV2' | 'app';
|
|
|
|
/**
|
|
* The method of authentication used to access the API.
|
|
*
|
|
* If the request is not authenticated, the value will be `null`.
|
|
*/
|
|
auth: 'api' | 'session' | null;
|
|
|
|
/**
|
|
* The user that is performing the action.
|
|
*
|
|
* If a team API key is used, the user will classified as the team.
|
|
*/
|
|
auditUser?: {
|
|
id: number | null;
|
|
email: string | null;
|
|
name: string | null;
|
|
};
|
|
};
|
|
|
|
export const extractRequestMetadata = (req: Request): RequestMetadata => {
|
|
let ip: string | undefined = undefined;
|
|
|
|
try {
|
|
ip = getIpAddress(req);
|
|
} catch {
|
|
// Do nothing.
|
|
}
|
|
|
|
const parsedIp = ZIpSchema.safeParse(ip);
|
|
|
|
const ipAddress = parsedIp.success ? parsedIp.data : undefined;
|
|
const userAgent = req.headers.get('user-agent');
|
|
|
|
return {
|
|
ipAddress,
|
|
userAgent: userAgent ?? undefined,
|
|
};
|
|
};
|