- Add lib/server/utils/normalize.ts with normalizeTicker, normalizeTagsOrNull, nowIso, todayIso - Add lib/server/utils/validation.ts with asRecord, asBoolean, asStringArray, asEnum - Add lib/server/utils/index.ts re-exporting all utilities - Remove duplicate lib/server/utils.ts (old file) - Update all repos and files to use shared utilities - Remove redundant ?? '' from normalizeTicker calls - Update watchlist.ts to use normalizeTagsOrNull for null-return tags
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
export function asRecord(value: unknown): Record<string, unknown> {
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
return {};
|
|
}
|
|
return value as Record<string, unknown>;
|
|
}
|
|
|
|
export function asOptionalRecord(value: unknown): Record<string, unknown> | null {
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
return null;
|
|
}
|
|
return value as Record<string, unknown>;
|
|
}
|
|
|
|
export function asPositiveNumber(value: unknown): number | null {
|
|
const parsed = typeof value === 'number' ? value : Number(value);
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
}
|
|
|
|
export function asBoolean(value: unknown, fallback = false): boolean {
|
|
if (typeof value === 'boolean') {
|
|
return value;
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
const normalized = value.trim().toLowerCase();
|
|
if (normalized === 'true' || normalized === '1' || normalized === 'yes') {
|
|
return true;
|
|
}
|
|
if (normalized === 'false' || normalized === '0' || normalized === 'no') {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
export function asStringArray(value: unknown): string[] {
|
|
const source = Array.isArray(value)
|
|
? value
|
|
: typeof value === 'string'
|
|
? value.split(',')
|
|
: [];
|
|
|
|
const unique = new Set<string>();
|
|
for (const entry of source) {
|
|
if (typeof entry !== 'string') continue;
|
|
const tag = entry.trim();
|
|
if (tag) unique.add(tag);
|
|
}
|
|
return [...unique];
|
|
}
|
|
|
|
export function asEnum<T extends string>(value: unknown, allowed: readonly T[]): T | undefined {
|
|
return allowed.includes(value as T) ? (value as T) : undefined;
|
|
}
|