fluncle 0.216.0 → 0.218.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +93 -7
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -610,7 +610,7 @@ function parseVersion(version) {
610
610
  var currentVersion;
611
611
  var init_version = __esm(() => {
612
612
  init_output();
613
- currentVersion = "0.216.0".trim() ? "0.216.0".trim() : "0.1.0";
613
+ currentVersion = "0.218.0".trim() ? "0.218.0".trim() : "0.1.0";
614
614
  });
615
615
 
616
616
  // src/update-notifier.ts
@@ -2452,7 +2452,7 @@ function parseVersion2(version) {
2452
2452
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2453
2453
  var init_version2 = __esm(() => {
2454
2454
  init_output();
2455
- currentVersion2 = "0.216.0".trim() ? "0.216.0".trim() : "0.1.0";
2455
+ currentVersion2 = "0.218.0".trim() ? "0.218.0".trim() : "0.1.0";
2456
2456
  });
2457
2457
 
2458
2458
  // ../../packages/registry/src/index.ts
@@ -4730,6 +4730,7 @@ __export(exports_admin_tracks, {
4730
4730
  backfillLastfmCommand: () => backfillLastfmCommand,
4731
4731
  backfillDiscogsFactsCommand: () => backfillDiscogsFactsCommand,
4732
4732
  backfillDiscogsCommand: () => backfillDiscogsCommand,
4733
+ backfillDeezerCommand: () => backfillDeezerCommand,
4733
4734
  backfillBeatportCommand: () => backfillBeatportCommand,
4734
4735
  backfillArtistEdgesCommand: () => backfillArtistEdgesCommand,
4735
4736
  backfillArtistCreditsCommand: () => backfillArtistCreditsCommand,
@@ -4918,6 +4919,10 @@ async function backfillDiscogsFactsCommand(limit, dryRun) {
4918
4919
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4919
4920
  return adminApiPost(`/api/v1/admin/backfill/discogs-facts?${params.toString()}`);
4920
4921
  }
4922
+ async function backfillDeezerCommand(limit, dryRun) {
4923
+ const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4924
+ return adminApiPost(`/api/v1/admin/backfill/deezer?${params.toString()}`);
4925
+ }
4921
4926
  async function backfillBeatportCommand(limit, dryRun, cursor) {
4922
4927
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4923
4928
  if (cursor) {
@@ -10466,14 +10471,15 @@ JSON field reference:
10466
10471
  });
10467
10472
  reach.command("collect").description("Collect + record one daily reach snapshot across every platform").option("--json", "Print JSON", false).action(async (options) => {
10468
10473
  const { reachCollectCommand: reachCollectCommand2 } = await Promise.resolve().then(() => (init_admin_reach(), exports_admin_reach));
10469
- const { collected, inserted, skipped } = await reachCollectCommand2();
10474
+ const { collected, failed, inserted, skipped } = await reachCollectCommand2();
10470
10475
  if (options.json) {
10471
- printJson({ collected, inserted, ok: true, skipped });
10476
+ printJson({ collected, failed, inserted, ok: true, skipped });
10472
10477
  return;
10473
10478
  }
10474
10479
  const landed = collected.map((entry) => `${entry.platform} (${entry.metrics.join(", ")})`).join("; ");
10475
- const missed = skipped.map((entry) => `${entry.platform}: ${entry.reason}`).join("; ");
10476
- console.log(`Collected ${collected.length} platform(s), wrote ${inserted} new row(s).${landed ? ` Landed: ${landed}.` : ""}${missed ? ` Skipped: ${missed}.` : ""}`);
10480
+ const missed = skipped.map((entry) => `${entry.platform} (${entry.kind}): ${entry.reason}`).join("; ");
10481
+ const faults = failed.map((entry) => `${entry.platform}: ${entry.reason}`).join("; ");
10482
+ console.log(`Collected ${collected.length} platform(s), wrote ${inserted} new row(s).${landed ? ` Landed: ${landed}.` : ""}${missed ? ` Skipped: ${missed}.` : ""}${faults ? ` Failed: ${faults}.` : ""}`);
10477
10483
  });
10478
10484
  const backfill = configureCommand(admin.command("backfills").description("Backfill operator-only archives"));
10479
10485
  backfill.action(() => {
@@ -10507,6 +10513,10 @@ JSON field reference:
10507
10513
  const { backfillBeatportCommand: backfillBeatportCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
10508
10514
  await runBackfillBeatport(options, backfillBeatportCommand2);
10509
10515
  });
10516
+ backfill.command("deezer").description("Resolve missing Deezer track ids for certified + catalogue rows (exact ISRC)").option("--dry-run", "Report the eligible set without resolving or writing", false).option("--limit <limit>", "Max rows to resolve", "50").option("--json", "Print JSON", false).action(async (options) => {
10517
+ const { backfillDeezerCommand: backfillDeezerCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
10518
+ await runBackfillDeezer(options, backfillDeezerCommand2);
10519
+ });
10510
10520
  backfill.command("artists").description("Back-fill the artist entity (artists + track_artists) for existing findings").option("--dry-run", "Report which findings would be upserted without touching the DB", false).option("--limit <limit>", "Max findings to process", "50").option("--json", "Print JSON", false).action(async (options) => {
10511
10521
  const { backfillArtistsCommand: backfillArtistsCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
10512
10522
  await runBackfillArtists(options, backfillArtistsCommand2);
@@ -11172,6 +11182,9 @@ async function runBackfillBeatport(options, backfillBeatportCommand2) {
11172
11182
  const unresolved = [];
11173
11183
  const failed = [];
11174
11184
  const skipped = [];
11185
+ const catalogueResolved = [];
11186
+ const catalogueUnresolved = [];
11187
+ const catalogueFailed = [];
11175
11188
  let cursor;
11176
11189
  let dryRun = options.dryRun;
11177
11190
  let configured = true;
@@ -11184,6 +11197,9 @@ async function runBackfillBeatport(options, backfillBeatportCommand2) {
11184
11197
  unresolved.push(...result.unresolved);
11185
11198
  failed.push(...result.failed);
11186
11199
  skipped.push(...result.skipped);
11200
+ catalogueResolved.push(...result.catalogueResolved);
11201
+ catalogueUnresolved.push(...result.catalogueUnresolved);
11202
+ catalogueFailed.push(...result.catalogueFailed);
11187
11203
  if (!options.json) {
11188
11204
  const verb2 = result.dryRun ? "would resolve" : "resolved";
11189
11205
  console.log(` \u2026${verb2} ${result.resolvedCount}; ${result.unresolvedCount} unresolved; ${result.failedCount} failed; ${result.skippedCount} skipped`);
@@ -11198,6 +11214,12 @@ async function runBackfillBeatport(options, backfillBeatportCommand2) {
11198
11214
  }
11199
11215
  if (options.json) {
11200
11216
  printSweepJson({
11217
+ catalogueFailed,
11218
+ catalogueFailedCount: catalogueFailed.length,
11219
+ catalogueResolved,
11220
+ catalogueResolvedCount: catalogueResolved.length,
11221
+ catalogueUnresolved,
11222
+ catalogueUnresolvedCount: catalogueUnresolved.length,
11201
11223
  configured,
11202
11224
  dryRun,
11203
11225
  failed,
@@ -11207,7 +11229,7 @@ async function runBackfillBeatport(options, backfillBeatportCommand2) {
11207
11229
  skippedCount: skipped.length,
11208
11230
  unresolved,
11209
11231
  unresolvedCount: unresolved.length
11210
- }, failed.length);
11232
+ }, failed.length + catalogueFailed.length);
11211
11233
  return;
11212
11234
  }
11213
11235
  if (!configured) {
@@ -11216,12 +11238,76 @@ async function runBackfillBeatport(options, backfillBeatportCommand2) {
11216
11238
  }
11217
11239
  const verb = dryRun ? "Would resolve" : "Resolved";
11218
11240
  console.log(`${verb} ${resolved.length} Beatport URL(s); ${unresolved.length} unresolved; ${failed.length} failed; ${skipped.length} skipped.`);
11241
+ console.log(` Catalogue tier \u2014 ${catalogueResolved.length} resolved; ${catalogueUnresolved.length} unresolved; ${catalogueFailed.length} failed.`);
11219
11242
  for (const item of resolved) {
11220
11243
  console.log(` ${item.logId}: ${item.url}`);
11221
11244
  }
11245
+ for (const item of catalogueResolved) {
11246
+ console.log(` ${item.trackId}: ${item.url}`);
11247
+ }
11222
11248
  for (const item of failed) {
11223
11249
  console.log(` ${item.logId}: ${item.error}`);
11224
11250
  }
11251
+ for (const item of catalogueFailed) {
11252
+ console.log(` ${item.trackId}: ${item.error}`);
11253
+ }
11254
+ if (failed.length + catalogueFailed.length > 0) {
11255
+ process.exitCode = 1;
11256
+ }
11257
+ }
11258
+ async function runBackfillDeezer(options, backfillDeezerCommand2) {
11259
+ const limit = parseListLimit(options.limit);
11260
+ const resolved = [];
11261
+ const unresolved = [];
11262
+ const unvouchable = [];
11263
+ const failed = [];
11264
+ let dryRun = options.dryRun;
11265
+ let throttled = false;
11266
+ while (resolved.length + unresolved.length + unvouchable.length + failed.length < limit) {
11267
+ const handled = resolved.length + unresolved.length + unvouchable.length + failed.length;
11268
+ const result = await backfillDeezerCommand2(limit - handled, options.dryRun);
11269
+ dryRun = result.dryRun;
11270
+ resolved.push(...result.resolved);
11271
+ unresolved.push(...result.unresolved);
11272
+ unvouchable.push(...result.unvouchable);
11273
+ failed.push(...result.failed);
11274
+ if (!options.json) {
11275
+ const verb2 = result.dryRun ? "would resolve" : "resolved";
11276
+ console.log(` \u2026${verb2} ${result.resolvedCount}; ${result.unresolvedCount} not on Deezer; ${result.unvouchableCount} unvouchable; ${result.failedCount} failed`);
11277
+ }
11278
+ if (result.rateLimited) {
11279
+ throttled = true;
11280
+ break;
11281
+ }
11282
+ if (result.resolvedCount === 0 && result.unresolvedCount === 0 && result.unvouchableCount === 0 && result.failedCount === 0) {
11283
+ break;
11284
+ }
11285
+ }
11286
+ if (options.json) {
11287
+ printSweepJson({
11288
+ dryRun,
11289
+ failed,
11290
+ rateLimited: throttled,
11291
+ resolved,
11292
+ resolvedCount: resolved.length,
11293
+ unresolved,
11294
+ unresolvedCount: unresolved.length,
11295
+ unvouchable,
11296
+ unvouchableCount: unvouchable.length
11297
+ }, failed.length);
11298
+ return;
11299
+ }
11300
+ const verb = dryRun ? "Would resolve" : "Resolved";
11301
+ console.log(`${verb} ${resolved.length} Deezer id(s); ${unresolved.length} not on Deezer; ${unvouchable.length} unvouchable; ${failed.length} failed.`);
11302
+ if (throttled) {
11303
+ console.log("Deezer answered its quota limit \u2014 the pass stopped and recorded nothing.");
11304
+ }
11305
+ for (const item of resolved) {
11306
+ console.log(` ${item.trackId}: ${item.url}`);
11307
+ }
11308
+ for (const item of failed) {
11309
+ console.log(` ${item.trackId}: ${item.error}`);
11310
+ }
11225
11311
  if (failed.length > 0) {
11226
11312
  process.exitCode = 1;
11227
11313
  }
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.216.0"
34
+ "version": "0.218.0"
35
35
  }