d58dc2a251
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts so reminders and automations get explicit user confirmation before persisting. Co-authored-by: Cursor <cursoragent@cursor.com>
59 lines
1.8 KiB
JavaScript
59 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Phase C:将 legacy 提醒/待办/自动化任务回填到 h5_tasks
|
|
*
|
|
* 用法:
|
|
* node scripts/migrate-legacy-tasks-to-h5-tasks.mjs --dry-run
|
|
* node scripts/migrate-legacy-tasks-to-h5-tasks.mjs --user-id=<uuid> --dry-run
|
|
* node scripts/migrate-legacy-tasks-to-h5-tasks.mjs --apply
|
|
*/
|
|
import fs from 'node:fs';
|
|
import mysql from 'mysql2/promise';
|
|
import { initSchema } from '../db.mjs';
|
|
import { createTaskUnifiedService } from '../task-unified-service.mjs';
|
|
|
|
function parseArgs(argv = process.argv.slice(2)) {
|
|
return {
|
|
dryRun: !argv.includes('--apply'),
|
|
userId: argv.find((arg) => arg.startsWith('--user-id='))?.split('=')[1] ?? null,
|
|
};
|
|
}
|
|
|
|
function loadDatabaseUrl() {
|
|
if (process.env.DATABASE_URL) return process.env.DATABASE_URL;
|
|
const envPath = new URL('../.env', import.meta.url);
|
|
if (!fs.existsSync(envPath)) return null;
|
|
const envText = fs.readFileSync(envPath, 'utf8');
|
|
return envText.match(/^DATABASE_URL=(.+)$/m)?.[1]?.trim().replace(/^["']|["']$/g, '') ?? null;
|
|
}
|
|
|
|
async function main() {
|
|
const options = parseArgs();
|
|
const databaseUrl = loadDatabaseUrl();
|
|
if (!databaseUrl) {
|
|
console.error('缺少 DATABASE_URL');
|
|
process.exit(1);
|
|
}
|
|
|
|
const pool = mysql.createPool(databaseUrl);
|
|
await initSchema(pool);
|
|
const service = createTaskUnifiedService(pool);
|
|
|
|
console.log(`=== migrate legacy tasks → h5_tasks (${options.dryRun ? 'dry-run' : 'apply'}) ===`);
|
|
if (options.userId) console.log(`user-id: ${options.userId}`);
|
|
|
|
const result = await service.migrateLegacyTasks({
|
|
userId: options.userId,
|
|
dryRun: options.dryRun,
|
|
});
|
|
|
|
console.log(JSON.stringify(result, null, 2));
|
|
await pool.end();
|
|
process.exit(result.errors > 0 ? 1 : 0);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err instanceof Error ? err.stack ?? err.message : err);
|
|
process.exit(1);
|
|
});
|