Tasks: import TickTick backup CSV (csv: keys, matched against API rows, rekeyed when the API returns them)
All checks were successful
Deploy production / deploy (push) Successful in 2m29s
All checks were successful
Deploy production / deploy (push) Successful in 2m29s
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
/**
|
||||
* Sync a TickTick export (scripts/ticktick-export.ts) into the private `tasks`
|
||||
* schema. Idempotent; rerun after a new export to pull in changes.
|
||||
* Sync TickTick into the private `tasks` schema. Idempotent; rerun after a new export.
|
||||
*
|
||||
* bun scripts/ticktick-import.ts [--dry-run] ~/.cache/ticktick-export/all.json
|
||||
* bun scripts/ticktick-import.ts [--dry-run] [--csv backup.csv] ~/.cache/ticktick-export/all.json
|
||||
*
|
||||
* all.json comes from scripts/ticktick-export.ts (Open API). --csv adds the tasks from a
|
||||
* TickTick backup (Settings → Backup & Import) that the API no longer returns (closed lists,
|
||||
* old won't-do tasks); rows the API also has are matched and skipped (see mergeCsv).
|
||||
* Links listed in data/tasks/ticktick-merges.json (plus exact title matches, see
|
||||
* syncTickTick) attach a TickTick task to an existing task instead of duplicating it.
|
||||
* Uses DB_URL (the app role on prod, personal_dev on dev).
|
||||
@@ -11,16 +13,31 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { drizzle } from 'drizzle-orm/postgres-js';
|
||||
import postgres from 'postgres';
|
||||
import { syncTickTick, type TtExport, type TtMerge } from '../src/lib/server/ticktick';
|
||||
import {
|
||||
mergeCsv,
|
||||
parseTickTickCsv,
|
||||
syncTickTick,
|
||||
type TtExport,
|
||||
type TtMerge
|
||||
} from '../src/lib/server/ticktick';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const dryRun = args.includes('--dry-run');
|
||||
const files = args.filter((a) => !a.startsWith('--'));
|
||||
if (files.length !== 1) {
|
||||
console.error('usage: bun scripts/ticktick-import.ts [--dry-run] <export.json>');
|
||||
const csvAt = args.indexOf('--csv');
|
||||
const csvPath = csvAt >= 0 ? args[csvAt + 1] : undefined;
|
||||
const files = args.filter((a, i) => !a.startsWith('--') && (csvAt < 0 || i !== csvAt + 1));
|
||||
if (files.length !== 1 || (csvAt >= 0 && !csvPath)) {
|
||||
console.error(
|
||||
'usage: bun scripts/ticktick-import.ts [--dry-run] [--csv backup.csv] <export.json>'
|
||||
);
|
||||
process.exit(2);
|
||||
}
|
||||
const data = JSON.parse(await readFile(files[0], 'utf8')) as TtExport;
|
||||
let data = JSON.parse(await readFile(files[0], 'utf8')) as TtExport;
|
||||
if (csvPath) {
|
||||
const merged = mergeCsv(data, parseTickTickCsv(await readFile(csvPath, 'utf8')));
|
||||
data = merged.data;
|
||||
console.log(JSON.stringify({ csv: merged.report }));
|
||||
}
|
||||
const merges = JSON.parse(
|
||||
await readFile(new URL('../data/tasks/ticktick-merges.json', import.meta.url), 'utf8')
|
||||
) as TtMerge[];
|
||||
@@ -29,9 +46,8 @@ const client = postgres(process.env.DB_URL, { max: 1, onnotice: () => {} });
|
||||
class DryRun extends Error {}
|
||||
try {
|
||||
const db = drizzle({ client });
|
||||
let report;
|
||||
try {
|
||||
report = await db.transaction(async (tx) => {
|
||||
const report = await db.transaction(async (tx) => {
|
||||
const r = await syncTickTick(tx, data, { merges });
|
||||
if (dryRun) {
|
||||
console.log(JSON.stringify(r, null, 2));
|
||||
|
||||
Reference in New Issue
Block a user