mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
39bb8f9619
ESLint keeps raw SQL out of the repositories, but nothing looked at the rest of src/: the entities, the domain services, the src/db lifecycle files or a migration added from now on. scripts/dialect-lint.mjs (npm run lint:dialect) reads every string and template literal under src/, skipping comments, and counts INSERT OR IGNORE/REPLACE, datetime(), strftime, json_extract, GLOB, last_insert_rowid, AUTOINCREMENT, PRAGMA outside the lifecycle files, || concatenation in SQL and .insertId reads. scripts/dialect-baseline.json holds today's thirteen hits; the counts may only go down, like lint:size. The dialect layer is not scanned, and neither are the migrations that have shipped. The four seeders that still spelled INSERT OR IGNORE (addons, photo and document providers, the schema_version marker) are Kysely inserts that do nothing on conflict now, so a re-run still leaves an operator's rows alone. They leave the SQL-string exemption list in eslint.config.mjs and their pins in the selector test.
177 lines
4.1 KiB
TypeScript
177 lines
4.1 KiB
TypeScript
import type { EntityManager } from '@mikro-orm/core';
|
|
import type { SqlEntityManager } from '@mikro-orm/sql';
|
|
import { Seeder } from '@mikro-orm/seeder';
|
|
import type { DB } from '../kysely/db';
|
|
|
|
interface AddonRow {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
type: string;
|
|
icon: string;
|
|
enabled: 0 | 1;
|
|
sort_order: number;
|
|
}
|
|
|
|
const DEFAULT_ADDONS: AddonRow[] = [
|
|
{
|
|
id: 'packing',
|
|
name: 'Lists',
|
|
description: 'Packing lists and to-do tasks for your trips',
|
|
type: 'trip',
|
|
icon: 'ListChecks',
|
|
enabled: 1,
|
|
sort_order: 0,
|
|
},
|
|
{
|
|
id: 'budget',
|
|
name: 'Costs',
|
|
description: 'Track and split trip expenses',
|
|
type: 'trip',
|
|
icon: 'Wallet',
|
|
enabled: 1,
|
|
sort_order: 1,
|
|
},
|
|
{
|
|
id: 'documents',
|
|
name: 'Documents',
|
|
description: 'Store and manage travel documents',
|
|
type: 'trip',
|
|
icon: 'FileText',
|
|
enabled: 1,
|
|
sort_order: 2,
|
|
},
|
|
{
|
|
id: 'vacay',
|
|
name: 'Vacay',
|
|
description: 'Personal vacation day planner with calendar view',
|
|
type: 'global',
|
|
icon: 'CalendarDays',
|
|
enabled: 1,
|
|
sort_order: 10,
|
|
},
|
|
{
|
|
id: 'atlas',
|
|
name: 'Atlas',
|
|
description: 'World map of your visited countries with travel stats',
|
|
type: 'global',
|
|
icon: 'Globe',
|
|
enabled: 1,
|
|
sort_order: 11,
|
|
},
|
|
{
|
|
id: 'mcp',
|
|
name: 'MCP',
|
|
description: 'Model Context Protocol for AI assistant integration',
|
|
type: 'integration',
|
|
icon: 'Terminal',
|
|
enabled: 0,
|
|
sort_order: 12,
|
|
},
|
|
{
|
|
id: 'naver_list_import',
|
|
name: 'Naver List Import',
|
|
description: 'Import places from a shared Naver Maps list',
|
|
type: 'integration',
|
|
icon: 'Link2',
|
|
enabled: 1,
|
|
sort_order: 13,
|
|
},
|
|
{
|
|
id: 'collab',
|
|
name: 'Collab',
|
|
description: 'Notes, polls, and live chat for trip collaboration',
|
|
type: 'trip',
|
|
icon: 'Users',
|
|
enabled: 1,
|
|
sort_order: 6,
|
|
},
|
|
{
|
|
id: 'roadtrip',
|
|
name: 'Road trip',
|
|
description: 'Drives with stops along the route, driving times, and arrival times that update themselves',
|
|
type: 'trip',
|
|
icon: 'Route',
|
|
enabled: 0,
|
|
sort_order: 7,
|
|
},
|
|
{
|
|
id: 'tours',
|
|
name: 'Tours',
|
|
description: 'Hikes and other single-day tours that follow a route',
|
|
type: 'trip',
|
|
icon: 'Mountain',
|
|
enabled: 0,
|
|
sort_order: 8,
|
|
},
|
|
{
|
|
id: 'journey',
|
|
name: 'Journey',
|
|
description: 'Trip tracking & travel journal — check-ins, photos, daily stories',
|
|
type: 'global',
|
|
icon: 'Compass',
|
|
enabled: 0,
|
|
sort_order: 35,
|
|
},
|
|
{
|
|
id: 'airtrail',
|
|
name: 'AirTrail',
|
|
description: 'Sync flights from your AirTrail instance',
|
|
type: 'integration',
|
|
icon: 'Plane',
|
|
enabled: 0,
|
|
sort_order: 14,
|
|
},
|
|
{
|
|
id: 'dawarich',
|
|
name: 'Dawarich',
|
|
description:
|
|
'Read visits and recorded routes from your Dawarich instance — suggested journal entries, places and countries you confirm yourself',
|
|
type: 'integration',
|
|
icon: 'Dawarich',
|
|
enabled: 0,
|
|
sort_order: 17,
|
|
},
|
|
{
|
|
id: 'llm_parsing',
|
|
name: 'AI Parsing',
|
|
description: 'LLM fallback for booking imports kitinerary cannot read',
|
|
type: 'integration',
|
|
icon: 'Sparkles',
|
|
enabled: 0,
|
|
sort_order: 15,
|
|
},
|
|
{
|
|
id: 'collections',
|
|
name: 'Collections',
|
|
description:
|
|
'Personal place library — save places across trips into named lists, copy into any trip, share with others',
|
|
type: 'global',
|
|
icon: 'Bookmark',
|
|
enabled: 0,
|
|
sort_order: 16,
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Seeds the addon shelf.
|
|
*
|
|
* One insert per row that does nothing when the id is already there, not a
|
|
* table-level emptiness check: an operator who has toggled an addon keeps their
|
|
* choice, and a release that adds a new addon still gets its tile on an
|
|
* existing install.
|
|
*/
|
|
export class AddonSeeder extends Seeder {
|
|
async run(em: EntityManager): Promise<void> {
|
|
const db = (em as SqlEntityManager).getKysely<Pick<DB, 'addons'>>();
|
|
for (const addon of DEFAULT_ADDONS) {
|
|
await db
|
|
.insertInto('addons')
|
|
.values({ ...addon })
|
|
.onConflict((oc) => oc.doNothing())
|
|
.execute();
|
|
}
|
|
console.log('Default addons seeded');
|
|
}
|
|
}
|