refactor(collections): parsing and writing a list's links moves into collections helpers

This commit is contained in:
Maurice
2026-10-12 21:13:57 +00:00
parent 5b6f76c98a
commit 4984e8f5eb
3 changed files with 54 additions and 17 deletions
@@ -0,0 +1,22 @@
import type { CollectionLink } from '@trek/shared';
/**
* Pure helpers of the collections domain, moved verbatim out of
* collections.service.ts. Nothing here touches the DB, so they stay plain
* exports rather than methods on CollectionsService.
*/
/** Links are stored as a JSON TEXT column; parse on read, stringify on write. */
export function parseLinks(raw: unknown): CollectionLink[] | undefined {
if (typeof raw !== 'string' || !raw) return undefined;
try {
const v = JSON.parse(raw);
return Array.isArray(v) ? (v as CollectionLink[]) : undefined;
} catch {
return undefined;
}
}
export function serializeLinks(links: CollectionLink[] | undefined): string | null {
return links && links.length ? JSON.stringify(links) : null;
}
@@ -62,7 +62,6 @@ import type {
CollectionMember,
CollectionMembership,
CollectionPlace,
CollectionLink,
CollectionCreateRequest,
CollectionUpdateRequest,
CollectionSavePlaceRequest,
@@ -76,22 +75,7 @@ import type {
import { NotificationsService } from '../notifications/notifications.service';
import { PlaceImportService, type ExportedCollectionFile } from '../place-import/place-import.service';
import { UnitOfWork } from '../database/unit-of-work';
/** Links are stored as a JSON TEXT column; parse on read, stringify on write. */
function parseLinks(raw: unknown): CollectionLink[] | undefined {
if (typeof raw !== 'string' || !raw) return undefined;
try {
const v = JSON.parse(raw);
return Array.isArray(v) ? (v as CollectionLink[]) : undefined;
} catch {
return undefined;
}
}
function serializeLinks(links: CollectionLink[] | undefined): string | null {
return links && links.length ? JSON.stringify(links) : null;
}
import { parseLinks, serializeLinks } from './collections.helpers';
// ---------------------------------------------------------------------------
// Errors — thrown as plain Errors carrying a status; TrekExceptionFilter maps
@@ -0,0 +1,31 @@
/**
* The link helpers of the collections domain, which read and write the JSON
* TEXT column a list or a saved place keeps its links in.
* COLLECTIONS-HELPERS-001 to 003.
*/
import { parseLinks, serializeLinks } from '../../../src/nest/collections/collections.helpers';
import { describe, expect, it } from 'vitest';
const links = [{ url: 'https://menu.example/', label: 'Menu' }];
describe('parseLinks', () => {
it('COLLECTIONS-HELPERS-001: reads a stored array of links back', () => {
expect(parseLinks(JSON.stringify(links))).toEqual(links);
});
it('COLLECTIONS-HELPERS-002: answers undefined for a missing, empty, unreadable or non-array value', () => {
expect(parseLinks(null)).toBeUndefined();
expect(parseLinks('')).toBeUndefined();
expect(parseLinks('{not json')).toBeUndefined();
expect(parseLinks(JSON.stringify(links[0]))).toBeUndefined();
});
});
describe('serializeLinks', () => {
it('COLLECTIONS-HELPERS-003: writes links as JSON and no links as null', () => {
expect(serializeLinks(links)).toBe(JSON.stringify(links));
expect(serializeLinks([])).toBeNull();
expect(serializeLinks(undefined)).toBeNull();
});
});