aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--apps/cli/src/commands/dump.ts291
-rw-r--r--apps/cli/src/commands/migrate.ts281
-rw-r--r--apps/cli/src/commands/wipe.ts151
3 files changed, 419 insertions, 304 deletions
diff --git a/apps/cli/src/commands/dump.ts b/apps/cli/src/commands/dump.ts
index 2e126654..5f3f8f5e 100644
--- a/apps/cli/src/commands/dump.ts
+++ b/apps/cli/src/commands/dump.ts
@@ -103,6 +103,19 @@ export const dumpCmd = new Command()
.description("dump all account data and assets into an archive")
.option("--output <file>", "output archive path (.tar.gz)")
.option(
+ "--exclude-assets",
+ "exclude binary assets (skip assets index and files)",
+ )
+ .option("--exclude-bookmarks", "exclude bookmarks (metadata/content)")
+ .option("--exclude-lists", "exclude lists and list membership")
+ .option("--exclude-tags", "exclude tags")
+ .option("--exclude-ai-prompts", "exclude AI prompts")
+ .option("--exclude-rules", "exclude rule engine rules")
+ .option("--exclude-feeds", "exclude RSS feeds")
+ .option("--exclude-webhooks", "exclude webhooks")
+ .option("--exclude-user-settings", "exclude user settings")
+ .option("--exclude-link-content", "exclude link content")
+ .option(
"--batch-size <n>",
`number of bookmarks per page (max ${MAX_NUM_BOOKMARKS_PER_PAGE})`,
(v) => Math.min(Number(v || 50), MAX_NUM_BOOKMARKS_PER_PAGE),
@@ -154,150 +167,178 @@ export const dumpCmd = new Command()
};
// 1) User settings
- stepStart("Exporting user settings");
- const settings = await api.users.settings.query();
- await writeJson(path.join(workRoot, "users", "settings.json"), settings);
- stepEndSuccess();
+ if (!opts.excludeUserSettings) {
+ stepStart("Exporting user settings");
+ const settings = await api.users.settings.query();
+ await writeJson(
+ path.join(workRoot, "users", "settings.json"),
+ settings,
+ );
+ stepEndSuccess();
+ }
// 2) Lists
- stepStart("Exporting lists");
- const { lists } = await api.lists.list.query();
- await writeJson(path.join(workRoot, "lists", "index.json"), lists);
- manifest.counts.lists = lists.length;
- stepEndSuccess();
+ let lists: ZBookmarkList[] | undefined;
+ if (!opts.excludeLists) {
+ stepStart("Exporting lists");
+ const resp = await api.lists.list.query();
+ lists = resp.lists;
+ await writeJson(path.join(workRoot, "lists", "index.json"), lists);
+ manifest.counts.lists = lists.length;
+ stepEndSuccess();
+ }
// 3) Tags
- stepStart("Exporting tags");
- const { tags } = await api.tags.list.query();
- await writeJson(path.join(workRoot, "tags", "index.json"), tags);
- manifest.counts.tags = tags.length;
- stepEndSuccess();
+ if (!opts.excludeTags) {
+ stepStart("Exporting tags");
+ const { tags } = await api.tags.list.query();
+ await writeJson(path.join(workRoot, "tags", "index.json"), tags);
+ manifest.counts.tags = tags.length;
+ stepEndSuccess();
+ }
// 4) Rules
- stepStart("Exporting rules");
- const { rules } = await api.rules.list.query();
- await writeJson(path.join(workRoot, "rules", "index.json"), rules);
- manifest.counts.rules = rules.length;
- stepEndSuccess();
+ if (!opts.excludeRules) {
+ stepStart("Exporting rules");
+ const { rules } = await api.rules.list.query();
+ await writeJson(path.join(workRoot, "rules", "index.json"), rules);
+ manifest.counts.rules = rules.length;
+ stepEndSuccess();
+ }
// 5) Feeds
- stepStart("Exporting feeds");
- const { feeds } = await api.feeds.list.query();
- await writeJson(path.join(workRoot, "feeds", "index.json"), feeds);
- manifest.counts.feeds = feeds.length;
- stepEndSuccess();
+ if (!opts.excludeFeeds) {
+ stepStart("Exporting feeds");
+ const { feeds } = await api.feeds.list.query();
+ await writeJson(path.join(workRoot, "feeds", "index.json"), feeds);
+ manifest.counts.feeds = feeds.length;
+ stepEndSuccess();
+ }
// 6) Prompts
- stepStart("Exporting AI prompts");
- const prompts = await api.prompts.list.query();
- await writeJson(path.join(workRoot, "prompts", "index.json"), prompts);
- manifest.counts.prompts = prompts.length;
- stepEndSuccess();
+ if (!opts.excludeAiPrompts) {
+ stepStart("Exporting AI prompts");
+ const prompts = await api.prompts.list.query();
+ await writeJson(path.join(workRoot, "prompts", "index.json"), prompts);
+ manifest.counts.prompts = prompts.length;
+ stepEndSuccess();
+ }
// 7) Webhooks
- stepStart("Exporting webhooks");
- const webhooks = await api.webhooks.list.query();
- await writeJson(
- path.join(workRoot, "webhooks", "index.json"),
- webhooks.webhooks,
- );
- manifest.counts.webhooks = webhooks.webhooks.length;
- stepEndSuccess();
+ if (!opts.excludeWebhooks) {
+ stepStart("Exporting webhooks");
+ const webhooks = await api.webhooks.list.query();
+ await writeJson(
+ path.join(workRoot, "webhooks", "index.json"),
+ webhooks.webhooks,
+ );
+ manifest.counts.webhooks = webhooks.webhooks.length;
+ stepEndSuccess();
+ }
// 8) Bookmarks (JSONL + list membership)
- stepStart("Exporting bookmarks (metadata/content)");
- const bookmarkJsonl = path.join(workRoot, "bookmarks", "index.jsonl");
- let bookmarksExported = 0;
- const bookmarkIterator = async function* (): AsyncGenerator<ZBookmark> {
- let cursor: ZCursor | null = null;
- do {
- const resp = await api.bookmarks.getBookmarks.query({
- includeContent: true,
- limit: Number(opts.batchSize) || 50,
- cursor,
- useCursorV2: true,
- });
- for (const b of resp.bookmarks) {
- yield b;
- bookmarksExported++;
- progressUpdate("Bookmarks", bookmarksExported);
- }
- cursor = resp.nextCursor;
- } while (cursor);
- };
- await writeJsonl(bookmarkJsonl, bookmarkIterator());
- progressDone();
- manifest.counts.bookmarks = bookmarksExported;
- stepEndSuccess();
+ if (!opts.excludeBookmarks) {
+ stepStart("Exporting bookmarks (metadata/content)");
+ const bookmarkJsonl = path.join(workRoot, "bookmarks", "index.jsonl");
+ let bookmarksExported = 0;
+ const bookmarkIterator = async function* (): AsyncGenerator<ZBookmark> {
+ let cursor: ZCursor | null = null;
+ do {
+ const resp = await api.bookmarks.getBookmarks.query({
+ includeContent: !opts.excludeLinkContent,
+ limit: Number(opts.batchSize) || 50,
+ cursor,
+ useCursorV2: true,
+ });
+ for (const b of resp.bookmarks) {
+ yield b;
+ bookmarksExported++;
+ progressUpdate("Bookmarks", bookmarksExported);
+ }
+ cursor = resp.nextCursor;
+ } while (cursor);
+ };
+ await writeJsonl(bookmarkJsonl, bookmarkIterator());
+ progressDone();
+ manifest.counts.bookmarks = bookmarksExported;
+ stepEndSuccess();
+ }
// 9) List membership (listId -> [bookmarkId])
- stepStart("Exporting list membership");
- const membership = await buildListMembership(api, lists, (p, t) =>
- progressUpdate("Lists scanned", p, t),
- );
- progressDone();
- await writeJson(
- path.join(workRoot, "lists", "membership.json"),
- Object.fromEntries(membership.entries()),
- );
- stepEndSuccess();
+ if (!opts.excludeLists && !opts.excludeBookmarks && lists) {
+ stepStart("Exporting list membership");
+ const membership = await buildListMembership(api, lists, (p, t) =>
+ progressUpdate("Lists scanned", p, t),
+ );
+ progressDone();
+ await writeJson(
+ path.join(workRoot, "lists", "membership.json"),
+ Object.fromEntries(membership.entries()),
+ );
+ stepEndSuccess();
+ }
// 10) Assets: index + files
- stepStart("Exporting assets (binary files)");
- const assetsDir = path.join(workRoot, "assets", "files");
- await ensureDir(assetsDir);
- const assetsIndex: {
- id: string;
- assetType: string;
- size: number;
- contentType: string | null;
- fileName: string | null;
- bookmarkId: string | null;
- filePath: string; // relative inside archive
- }[] = [];
- let assetPageCursor: number | null | undefined = null;
- let downloaded = 0;
- let totalAssets: number | undefined = undefined;
- do {
- const resp = await api.assets.list.query({
- limit: 50,
- cursor: assetPageCursor ?? undefined,
- });
- if (totalAssets == null) totalAssets = resp.totalCount;
- for (const a of resp.assets) {
- const relPath = path.join("assets", "files", a.id);
- const absPath = path.join(workRoot, relPath);
- try {
- await downloadAsset(
- globals.serverAddr,
- globals.apiKey,
- a.id,
- absPath,
- );
- assetsIndex.push({
- id: a.id,
- assetType: a.assetType,
- size: a.size,
- contentType: a.contentType,
- fileName: a.fileName,
- bookmarkId: a.bookmarkId,
- filePath: relPath.replace(/\\/g, "/"),
- });
- downloaded++;
- progressUpdate("Assets", downloaded, totalAssets);
- } catch (e) {
- printErrorMessageWithReason(
- `Failed to download asset "${a.id}"`,
- e as object,
- );
+ if (!opts.excludeAssets) {
+ stepStart("Exporting assets (binary files)");
+ const assetsDir = path.join(workRoot, "assets", "files");
+ await ensureDir(assetsDir);
+ const assetsIndex: {
+ id: string;
+ assetType: string;
+ size: number;
+ contentType: string | null;
+ fileName: string | null;
+ bookmarkId: string | null;
+ filePath: string; // relative inside archive
+ }[] = [];
+ let assetPageCursor: number | null | undefined = null;
+ let downloaded = 0;
+ let totalAssets: number | undefined = undefined;
+ do {
+ const resp = await api.assets.list.query({
+ limit: 50,
+ cursor: assetPageCursor ?? undefined,
+ });
+ if (totalAssets == null) totalAssets = resp.totalCount;
+ for (const a of resp.assets) {
+ const relPath = path.join("assets", "files", a.id);
+ const absPath = path.join(workRoot, relPath);
+ try {
+ await downloadAsset(
+ globals.serverAddr,
+ globals.apiKey,
+ a.id,
+ absPath,
+ );
+ assetsIndex.push({
+ id: a.id,
+ assetType: a.assetType,
+ size: a.size,
+ contentType: a.contentType,
+ fileName: a.fileName,
+ bookmarkId: a.bookmarkId,
+ filePath: relPath.replace(/\\/g, "/"),
+ });
+ downloaded++;
+ progressUpdate("Assets", downloaded, totalAssets);
+ } catch (e) {
+ printErrorMessageWithReason(
+ `Failed to download asset "${a.id}"`,
+ e as object,
+ );
+ }
}
- }
- assetPageCursor = resp.nextCursor;
- } while (assetPageCursor);
- progressDone();
- manifest.counts.assets = downloaded;
- await writeJson(path.join(workRoot, "assets", "index.json"), assetsIndex);
- stepEndSuccess();
+ assetPageCursor = resp.nextCursor;
+ } while (assetPageCursor);
+ progressDone();
+ manifest.counts.assets = downloaded;
+ await writeJson(
+ path.join(workRoot, "assets", "index.json"),
+ assetsIndex,
+ );
+ stepEndSuccess();
+ }
// 11) Manifest
stepStart("Writing manifest");
diff --git a/apps/cli/src/commands/migrate.ts b/apps/cli/src/commands/migrate.ts
index 48343992..750daf61 100644
--- a/apps/cli/src/commands/migrate.ts
+++ b/apps/cli/src/commands/migrate.ts
@@ -71,6 +71,15 @@ export const migrateCmd = new Command()
)
.requiredOption("--dest-api-key <key>", "API key for the destination server")
.option("-y, --yes", "skip confirmation prompt")
+ .option("--exclude-assets", "exclude assets (skip asset bookmarks)")
+ .option("--exclude-lists", "exclude lists and list membership")
+ .option("--exclude-ai-prompts", "exclude AI prompts")
+ .option("--exclude-rules", "exclude rule engine rules")
+ .option("--exclude-feeds", "exclude RSS feeds")
+ .option("--exclude-webhooks", "exclude webhooks")
+ .option("--exclude-bookmarks", "exclude bookmarks migration")
+ .option("--exclude-tags", "exclude tags migration")
+ .option("--exclude-user-settings", "exclude user settings migration")
.option(
"--batch-size <n>",
`number of bookmarks per page (max ${MAX_NUM_BOOKMARKS_PER_PAGE})`,
@@ -118,130 +127,163 @@ export const migrateCmd = new Command()
}
// 1) User settings
- stepStart("Migrating user settings");
- await migrateUserSettings(src, dest);
- stepEndSuccess();
+ if (!opts.excludeUserSettings) {
+ stepStart("Migrating user settings");
+ await migrateUserSettings(src, dest);
+ stepEndSuccess();
+ }
// 2) Lists (and mapping)
- stepStart("Migrating lists");
- const listsStart = Date.now();
- const {
- lists,
- listIdMap,
- createdCount: listsCreated,
- } = await migrateLists(src, dest, (created, alreadyExists, total) => {
- progressUpdate("Lists (created)", created + alreadyExists, total);
- });
- progressDone();
- stepEndSuccess(
- `${listsCreated} created in ${Math.round((Date.now() - listsStart) / 1000)}s`,
- );
+ let lists: ZBookmarkList[] = [];
+ let listIdMap = new Map<string, string>();
+ if (!opts.excludeLists) {
+ stepStart("Migrating lists");
+ const listsStart = Date.now();
+ const listsRes = await migrateLists(
+ src,
+ dest,
+ (created, alreadyExists, total) => {
+ progressUpdate("Lists (created)", created + alreadyExists, total);
+ },
+ );
+ lists = listsRes.lists;
+ listIdMap = listsRes.listIdMap;
+ progressDone();
+ stepEndSuccess(
+ `${listsRes.createdCount} created in ${Math.round((Date.now() - listsStart) / 1000)}s`,
+ );
+ }
// 3) Feeds
- stepStart("Migrating feeds");
- const feedsStart = Date.now();
- const { idMap: feedIdMap, count: feedsCount } = await migrateFeeds(
- src,
- dest,
- (created, total) => {
+ let feedIdMap = new Map<string, string>();
+ if (!opts.excludeFeeds) {
+ stepStart("Migrating feeds");
+ const feedsStart = Date.now();
+ const res = await migrateFeeds(src, dest, (created, total) => {
progressUpdate("Feeds", created, total);
- },
- );
- progressDone();
- stepEndSuccess(
- `${feedsCount} migrated in ${Math.round((Date.now() - feedsStart) / 1000)}s`,
- );
+ });
+ feedIdMap = res.idMap;
+ progressDone();
+ stepEndSuccess(
+ `${res.count} migrated in ${Math.round((Date.now() - feedsStart) / 1000)}s`,
+ );
+ }
// 4) AI settings (custom prompts)
- stepStart("Migrating AI prompts");
- const promptsStart = Date.now();
- const promptsCount = await migratePrompts(src, dest, (created, total) => {
- progressUpdate("Prompts", created, total);
- });
- progressDone();
- stepEndSuccess(
- `${promptsCount} migrated in ${Math.round((Date.now() - promptsStart) / 1000)}s`,
- );
+ if (!opts.excludeAiPrompts) {
+ stepStart("Migrating AI prompts");
+ const promptsStart = Date.now();
+ const promptsCount = await migratePrompts(
+ src,
+ dest,
+ (created, total) => {
+ progressUpdate("Prompts", created, total);
+ },
+ );
+ progressDone();
+ stepEndSuccess(
+ `${promptsCount} migrated in ${Math.round((Date.now() - promptsStart) / 1000)}s`,
+ );
+ }
// 5) Webhooks (tokens cannot be read; created without token)
- stepStart("Migrating webhooks");
- const webhooksStart = Date.now();
- const webhooksCount = await migrateWebhooks(
- src,
- dest,
- (created, total) => {
- progressUpdate("Webhooks", created, total);
- },
- );
- progressDone();
- stepEndSuccess(
- `${webhooksCount} migrated in ${Math.round((Date.now() - webhooksStart) / 1000)}s`,
- );
+ if (!opts.excludeWebhooks) {
+ stepStart("Migrating webhooks");
+ const webhooksStart = Date.now();
+ const webhooksCount = await migrateWebhooks(
+ src,
+ dest,
+ (created, total) => {
+ progressUpdate("Webhooks", created, total);
+ },
+ );
+ progressDone();
+ stepEndSuccess(
+ `${webhooksCount} migrated in ${Math.round((Date.now() - webhooksStart) / 1000)}s`,
+ );
+ }
// 6) Tags (build id map for rules)
- stepStart("Ensuring tags on destination");
- const tagsStart = Date.now();
- const { idMap: tagIdMap, count: tagsCount } = await migrateTags(
- src,
- dest,
- (ensured, total) => {
+ let tagIdMap = new Map<string, string>();
+ if (!opts.excludeTags) {
+ stepStart("Ensuring tags on destination");
+ const tagsStart = Date.now();
+ const res = await migrateTags(src, dest, (ensured, total) => {
progressUpdate("Tags", ensured, total);
- },
- );
- progressDone();
- stepEndSuccess(
- `${tagsCount} ensured in ${Math.round((Date.now() - tagsStart) / 1000)}s`,
- );
+ });
+ tagIdMap = res.idMap;
+ progressDone();
+ stepEndSuccess(
+ `${res.count} ensured in ${Math.round((Date.now() - tagsStart) / 1000)}s`,
+ );
+ }
// 7) Rules (requires tag/list/feed id maps)
- stepStart("Migrating rule engine rules");
- const rulesStart = Date.now();
- const rulesCount = await migrateRules(
- src,
- dest,
- { tagIdMap, listIdMap, feedIdMap },
- (created, total) => {
- progressUpdate("Rules", created, total);
- },
- );
- progressDone();
- stepEndSuccess(
- `${rulesCount} migrated in ${Math.round((Date.now() - rulesStart) / 1000)}s`,
- );
+ if (
+ !opts.excludeRules &&
+ !opts.excludeLists &&
+ !opts.excludeFeeds &&
+ !opts.excludeTags
+ ) {
+ stepStart("Migrating rule engine rules");
+ const rulesStart = Date.now();
+ const rulesCount = await migrateRules(
+ src,
+ dest,
+ { tagIdMap, listIdMap, feedIdMap },
+ (created, total) => {
+ progressUpdate("Rules", created, total);
+ },
+ );
+ progressDone();
+ stepEndSuccess(
+ `${rulesCount} migrated in ${Math.round((Date.now() - rulesStart) / 1000)}s`,
+ );
+ }
// 8) Bookmarks (with list membership + tags)
- stepStart("Building list membership for bookmarks");
- const blmStart = Date.now();
- const { bookmarkListsMap, scannedLists } =
- await buildBookmarkListMembership(src, lists, (processed, total) => {
- progressUpdate("Scanning lists", processed, total);
+ let bookmarkListsMap = new Map<string, string[]>();
+ if (!opts.excludeLists && !opts.excludeBookmarks) {
+ stepStart("Building list membership for bookmarks");
+ const blmStart = Date.now();
+ const res = await buildBookmarkListMembership(
+ src,
+ lists,
+ (processed, total) => {
+ progressUpdate("Scanning lists", processed, total);
+ },
+ );
+ bookmarkListsMap = res.bookmarkListsMap;
+ progressDone();
+ stepEndSuccess(
+ `${res.scannedLists} lists scanned in ${Math.round((Date.now() - blmStart) / 1000)}s`,
+ );
+ }
+ if (!opts.excludeBookmarks) {
+ stepStart("Migrating bookmarks");
+ const bmStart = Date.now();
+ const res = await migrateBookmarks(src, dest, {
+ pageSize: Number(opts.batchSize) || 50,
+ listIdMap,
+ bookmarkListsMap,
+ total: totalBookmarks,
+ onProgress: (migrated, skipped, total) => {
+ const suffix =
+ skipped > 0 ? `(skipped ${skipped} assets)` : undefined;
+ progressUpdate("Bookmarks", migrated, total, suffix);
+ },
+ srcServer: globals.serverAddr,
+ srcApiKey: globals.apiKey,
+ destServer: opts.destServer,
+ destApiKey: opts.destApiKey,
+ excludeAssets: !!opts.excludeAssets,
+ excludeLists: !!opts.excludeLists,
});
- progressDone();
- stepEndSuccess(
- `${scannedLists} lists scanned in ${Math.round((Date.now() - blmStart) / 1000)}s`,
- );
-
- stepStart("Migrating bookmarks");
- const bmStart = Date.now();
- const res = await migrateBookmarks(src, dest, {
- pageSize: Number(opts.batchSize) || 50,
- listIdMap,
- bookmarkListsMap,
- total: totalBookmarks,
- onProgress: (migrated, skipped, total) => {
- const suffix =
- skipped > 0 ? `(skipped ${skipped} assets)` : undefined;
- progressUpdate("Bookmarks", migrated, total, suffix);
- },
- srcServer: globals.serverAddr,
- srcApiKey: globals.apiKey,
- destServer: opts.destServer,
- destApiKey: opts.destApiKey,
- });
- progressDone();
- stepEndSuccess(
- `${res.migrated} migrated${res.skippedAssets ? `, ${res.skippedAssets} skipped` : ""} in ${Math.round((Date.now() - bmStart) / 1000)}s`,
- );
+ progressDone();
+ stepEndSuccess(
+ `${res.migrated} migrated${res.skippedAssets ? `, ${res.skippedAssets} skipped` : ""} in ${Math.round((Date.now() - bmStart) / 1000)}s`,
+ );
+ }
printStatusMessage(true, "Migration completed successfully");
} catch (error) {
@@ -629,6 +671,8 @@ async function migrateBookmarks(
srcApiKey: string;
destServer: string;
destApiKey: string;
+ excludeAssets: boolean;
+ excludeLists: boolean;
},
) {
let cursor: ZCursor | null = null;
@@ -674,6 +718,11 @@ async function migrateBookmarks(
break;
}
case BookmarkTypes.ASSET: {
+ if (opts.excludeAssets) {
+ // Skip migrating asset bookmarks when excluded
+ skippedAssets++;
+ continue;
+ }
// Download from source and re-upload to destination
try {
const downloadResp = await fetch(
@@ -746,14 +795,16 @@ async function migrateBookmarks(
}
// Add to lists (map src -> dest list ids)
- const srcListIds = opts.bookmarkListsMap.get(b.id) ?? [];
- for (const srcListId of srcListIds) {
- const destListId = opts.listIdMap.get(srcListId);
- if (destListId) {
- await dest.lists.addToList.mutate({
- listId: destListId,
- bookmarkId: createdId!,
- });
+ if (!opts.excludeLists) {
+ const srcListIds = opts.bookmarkListsMap.get(b.id) ?? [];
+ for (const srcListId of srcListIds) {
+ const destListId = opts.listIdMap.get(srcListId);
+ if (destListId) {
+ await dest.lists.addToList.mutate({
+ listId: destListId,
+ bookmarkId: createdId!,
+ });
+ }
}
}
migrated++;
diff --git a/apps/cli/src/commands/wipe.ts b/apps/cli/src/commands/wipe.ts
index 34281e2b..713ac452 100644
--- a/apps/cli/src/commands/wipe.ts
+++ b/apps/cli/src/commands/wipe.ts
@@ -58,6 +58,14 @@ export const wipeCmd = new Command()
.name("wipe")
.description("wipe all data for the current user from the server")
.option("-y, --yes", "skip confirmation prompt")
+ .option("--exclude-lists", "exclude lists from deletion")
+ .option("--exclude-ai-prompts", "exclude AI prompts from deletion")
+ .option("--exclude-rules", "exclude rules from deletion")
+ .option("--exclude-feeds", "exclude RSS feeds from deletion")
+ .option("--exclude-webhooks", "exclude webhooks from deletion")
+ .option("--exclude-bookmarks", "exclude bookmarks from deletion")
+ .option("--exclude-tags", "exclude tags cleanup from deletion")
+ .option("--exclude-user-settings", "exclude user settings (no-op)")
.option(
"--batch-size <n>",
`number of bookmarks per page (max ${MAX_NUM_BOOKMARKS_PER_PAGE})`,
@@ -100,82 +108,96 @@ export const wipeCmd = new Command()
}
// 1) Rules
- stepStart("Deleting rule engine rules");
- const rulesStart = Date.now();
- const rulesDeleted = await wipeRules(api, (deleted, total) => {
- progressUpdate("Rules", deleted, total);
- });
- progressDone();
- stepEndSuccess(
- `${rulesDeleted} deleted in ${Math.round((Date.now() - rulesStart) / 1000)}s`,
- );
+ if (!opts.excludeRules) {
+ stepStart("Deleting rule engine rules");
+ const rulesStart = Date.now();
+ const rulesDeleted = await wipeRules(api, (deleted, total) => {
+ progressUpdate("Rules", deleted, total);
+ });
+ progressDone();
+ stepEndSuccess(
+ `${rulesDeleted} deleted in ${Math.round((Date.now() - rulesStart) / 1000)}s`,
+ );
+ }
// 2) Feeds
- stepStart("Deleting feeds");
- const feedsStart = Date.now();
- const feedsDeleted = await wipeFeeds(api, (deleted, total) => {
- progressUpdate("Feeds", deleted, total);
- });
- progressDone();
- stepEndSuccess(
- `${feedsDeleted} deleted in ${Math.round((Date.now() - feedsStart) / 1000)}s`,
- );
+ if (!opts.excludeFeeds) {
+ stepStart("Deleting feeds");
+ const feedsStart = Date.now();
+ const feedsDeleted = await wipeFeeds(api, (deleted, total) => {
+ progressUpdate("Feeds", deleted, total);
+ });
+ progressDone();
+ stepEndSuccess(
+ `${feedsDeleted} deleted in ${Math.round((Date.now() - feedsStart) / 1000)}s`,
+ );
+ }
// 3) Webhooks
- stepStart("Deleting webhooks");
- const webhooksStart = Date.now();
- const webhooksDeleted = await wipeWebhooks(api, (deleted, total) => {
- progressUpdate("Webhooks", deleted, total);
- });
- progressDone();
- stepEndSuccess(
- `${webhooksDeleted} deleted in ${Math.round((Date.now() - webhooksStart) / 1000)}s`,
- );
+ if (!opts.excludeWebhooks) {
+ stepStart("Deleting webhooks");
+ const webhooksStart = Date.now();
+ const webhooksDeleted = await wipeWebhooks(api, (deleted, total) => {
+ progressUpdate("Webhooks", deleted, total);
+ });
+ progressDone();
+ stepEndSuccess(
+ `${webhooksDeleted} deleted in ${Math.round((Date.now() - webhooksStart) / 1000)}s`,
+ );
+ }
// 4) Prompts
- stepStart("Deleting AI prompts");
- const promptsStart = Date.now();
- const promptsDeleted = await wipePrompts(api, (deleted, total) => {
- progressUpdate("Prompts", deleted, total);
- });
- progressDone();
- stepEndSuccess(
- `${promptsDeleted} deleted in ${Math.round((Date.now() - promptsStart) / 1000)}s`,
- );
+ if (!opts.excludeAiPrompts) {
+ stepStart("Deleting AI prompts");
+ const promptsStart = Date.now();
+ const promptsDeleted = await wipePrompts(api, (deleted, total) => {
+ progressUpdate("Prompts", deleted, total);
+ });
+ progressDone();
+ stepEndSuccess(
+ `${promptsDeleted} deleted in ${Math.round((Date.now() - promptsStart) / 1000)}s`,
+ );
+ }
// 5) Bookmarks
- stepStart("Deleting bookmarks");
- const bmStart = Date.now();
- const bookmarksDeleted = await wipeBookmarks(api, {
- pageSize: Number(opts.batchSize) || 50,
- total: totalBookmarks,
- onProgress: (deleted, total) => {
- progressUpdate("Bookmarks", deleted, total);
- },
- });
- progressDone();
- stepEndSuccess(
- `${bookmarksDeleted} deleted in ${Math.round((Date.now() - bmStart) / 1000)}s`,
- );
+ if (!opts.excludeBookmarks) {
+ stepStart("Deleting bookmarks");
+ const bmStart = Date.now();
+ const bookmarksDeleted = await wipeBookmarks(api, {
+ pageSize: Number(opts.batchSize) || 50,
+ total: totalBookmarks,
+ onProgress: (deleted, total) => {
+ progressUpdate("Bookmarks", deleted, total);
+ },
+ });
+ progressDone();
+ stepEndSuccess(
+ `${bookmarksDeleted} deleted in ${Math.round((Date.now() - bmStart) / 1000)}s`,
+ );
+ }
// 6) Lists
- stepStart("Deleting lists");
- const listsStart = Date.now();
- const listsDeleted = await wipeLists(api, (deleted, total) => {
- progressUpdate("Lists", deleted, total);
- });
- progressDone();
- stepEndSuccess(
- `${listsDeleted} deleted in ${Math.round((Date.now() - listsStart) / 1000)}s`,
- );
+ if (!opts.excludeLists) {
+ stepStart("Deleting lists");
+ const listsStart = Date.now();
+ const listsDeleted = await wipeLists(api, (deleted, total) => {
+ progressUpdate("Lists", deleted, total);
+ });
+ progressDone();
+ stepEndSuccess(
+ `${listsDeleted} deleted in ${Math.round((Date.now() - listsStart) / 1000)}s`,
+ );
+ }
// 7) Tags (unused)
- stepStart("Deleting unused tags");
- const tagsStart = Date.now();
- const deletedTags = await wipeTags(api);
- stepEndSuccess(
- `${deletedTags} deleted in ${Math.round((Date.now() - tagsStart) / 1000)}s`,
- );
+ if (!opts.excludeTags) {
+ stepStart("Deleting unused tags");
+ const tagsStart = Date.now();
+ const deletedTags = await wipeTags(api);
+ stepEndSuccess(
+ `${deletedTags} deleted in ${Math.round((Date.now() - tagsStart) / 1000)}s`,
+ );
+ }
printStatusMessage(true, "Wipe completed successfully");
} catch (error) {
@@ -304,6 +326,7 @@ async function wipeBookmarks(
limit: opts.pageSize,
cursor,
useCursorV2: true,
+ includeContent: false,
});
for (const b of resp.bookmarks) {
try {