fluncle 0.136.0 → 0.137.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.
- package/bin/fluncle.mjs +81 -4
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -561,7 +561,7 @@ function parseVersion(version) {
|
|
|
561
561
|
var currentVersion;
|
|
562
562
|
var init_version = __esm(() => {
|
|
563
563
|
init_output();
|
|
564
|
-
currentVersion = "0.
|
|
564
|
+
currentVersion = "0.137.0".trim() ? "0.137.0".trim() : "0.1.0";
|
|
565
565
|
});
|
|
566
566
|
|
|
567
567
|
// src/update-notifier.ts
|
|
@@ -2189,7 +2189,7 @@ function parseVersion2(version) {
|
|
|
2189
2189
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2190
2190
|
var init_version2 = __esm(() => {
|
|
2191
2191
|
init_output();
|
|
2192
|
-
currentVersion2 = "0.
|
|
2192
|
+
currentVersion2 = "0.137.0".trim() ? "0.137.0".trim() : "0.1.0";
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
2195
|
// ../../packages/registry/src/index.ts
|
|
@@ -2247,11 +2247,11 @@ var init_src = __esm(() => {
|
|
|
2247
2247
|
},
|
|
2248
2248
|
{
|
|
2249
2249
|
exposedContent: [
|
|
2250
|
-
"the
|
|
2250
|
+
"the free mixing tool — name artists you like, and Fluncle ranks what mixes in clean next from the whole archive; chain a set and share it as a link"
|
|
2251
2251
|
],
|
|
2252
2252
|
kind: "web_route",
|
|
2253
2253
|
name: "web.mix",
|
|
2254
|
-
operatorNotes: "
|
|
2254
|
+
operatorNotes: "PUBLIC-CAPABLE, gated by a SELF-LIFTING DEPTH MEASUREMENT (not admin auth). The old ~250-finding / admin gate is gone: `/mix` now measures the live archive on every load (`getMixChainDepth` — can the median track reach a full set + rail by a named harmonic move?) and opens to the world on its own the day the catalogue lands enough keyed depth. Until then a stranger is redirected home and the operator still gets in to dogfood. This entry stays `pending` (dark to the dev-row, llms.txt, the sitemap, /status) ONLY so we do not advertise a URL that still redirects — the flip is: confirm the depth gate has opened in prod, remove `pending`, announce. The web weight is pre-set, so the flip needs no other change. No probeConfig — a closed gate 302s a bare GET, which would read as a false 'down'.",
|
|
2255
2255
|
pending: true,
|
|
2256
2256
|
route: "/mix",
|
|
2257
2257
|
url: `${SITE}/mix`,
|
|
@@ -5746,6 +5746,22 @@ var init_admin_artists = __esm(() => {
|
|
|
5746
5746
|
init_api();
|
|
5747
5747
|
});
|
|
5748
5748
|
|
|
5749
|
+
// src/commands/admin-labels.ts
|
|
5750
|
+
var exports_admin_labels = {};
|
|
5751
|
+
__export(exports_admin_labels, {
|
|
5752
|
+
backfillLabelImagesCommand: () => backfillLabelImagesCommand
|
|
5753
|
+
});
|
|
5754
|
+
async function backfillLabelImagesCommand(limit, dryRun, cursor) {
|
|
5755
|
+
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
5756
|
+
if (cursor) {
|
|
5757
|
+
params.set("cursor", cursor);
|
|
5758
|
+
}
|
|
5759
|
+
return adminApiPost(`/api/admin/backfill/label-images?${params.toString()}`);
|
|
5760
|
+
}
|
|
5761
|
+
var init_admin_labels = __esm(() => {
|
|
5762
|
+
init_api();
|
|
5763
|
+
});
|
|
5764
|
+
|
|
5749
5765
|
// src/commands/preview-migration.ts
|
|
5750
5766
|
var exports_preview_migration = {};
|
|
5751
5767
|
__export(exports_preview_migration, {
|
|
@@ -8762,6 +8778,10 @@ function addAdminCommands(program2) {
|
|
|
8762
8778
|
const { backfillArtistImagesCommand: backfillArtistImagesCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
8763
8779
|
await runBackfillArtistImages(options, backfillArtistImagesCommand2);
|
|
8764
8780
|
});
|
|
8781
|
+
backfill.command("label-images").description("Resolve label logos (Discogs \u2192 Wikidata) into R2 for existing labels").option("--dry-run", "Report the eligible worklist without any vendor call or write", false).option("--limit <limit>", "Max labels to process", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
8782
|
+
const { backfillLabelImagesCommand: backfillLabelImagesCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
8783
|
+
await runBackfillLabelImages(options, backfillLabelImagesCommand2);
|
|
8784
|
+
});
|
|
8765
8785
|
artists.command("resolve").description("Resolve an artist's social identity (MB url-rels + Firecrawl gap-fill)").argument("[artistId]").option("--queue", "Show the resolve worklist (artists awaiting resolution), oldest first", false).option("--limit <limit>", "Number of artists to show with --queue", "50").option("--json", "Print JSON", false).allowExcessArguments().action(async (artistId, options) => {
|
|
8766
8786
|
if (options.queue) {
|
|
8767
8787
|
const { listArtistsCommand: listArtistsCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
@@ -9253,6 +9273,63 @@ async function runBackfillArtistImages(options, backfillArtistImagesCommand2) {
|
|
|
9253
9273
|
process.exitCode = 1;
|
|
9254
9274
|
}
|
|
9255
9275
|
}
|
|
9276
|
+
async function runBackfillLabelImages(options, backfillLabelImagesCommand2) {
|
|
9277
|
+
const limit = parseListLimit(options.limit);
|
|
9278
|
+
const resolved = [];
|
|
9279
|
+
const none = [];
|
|
9280
|
+
const failed = [];
|
|
9281
|
+
let cursor;
|
|
9282
|
+
let dryRun = options.dryRun;
|
|
9283
|
+
let throttled = false;
|
|
9284
|
+
while (resolved.length + none.length + failed.length < limit) {
|
|
9285
|
+
const remaining = limit - (resolved.length + none.length + failed.length);
|
|
9286
|
+
const result = await backfillLabelImagesCommand2(remaining, options.dryRun, cursor);
|
|
9287
|
+
dryRun = result.dryRun;
|
|
9288
|
+
resolved.push(...result.resolved);
|
|
9289
|
+
none.push(...result.none);
|
|
9290
|
+
failed.push(...result.failed);
|
|
9291
|
+
if (!options.json) {
|
|
9292
|
+
const verb2 = result.dryRun ? "would resolve" : "resolved";
|
|
9293
|
+
console.log(` \u2026${verb2} ${result.resolvedCount}; ${result.noneCount} without an image; ${result.failedCount} failed`);
|
|
9294
|
+
}
|
|
9295
|
+
if (result.rateLimited) {
|
|
9296
|
+
throttled = true;
|
|
9297
|
+
break;
|
|
9298
|
+
}
|
|
9299
|
+
if (result.nextCursor === null) {
|
|
9300
|
+
break;
|
|
9301
|
+
}
|
|
9302
|
+
cursor = result.nextCursor;
|
|
9303
|
+
}
|
|
9304
|
+
if (options.json) {
|
|
9305
|
+
printJson({
|
|
9306
|
+
dryRun,
|
|
9307
|
+
failed,
|
|
9308
|
+
failedCount: failed.length,
|
|
9309
|
+
none,
|
|
9310
|
+
noneCount: none.length,
|
|
9311
|
+
ok: true,
|
|
9312
|
+
rateLimited: throttled,
|
|
9313
|
+
resolved,
|
|
9314
|
+
resolvedCount: resolved.length
|
|
9315
|
+
});
|
|
9316
|
+
if (failed.length > 0) {
|
|
9317
|
+
process.exitCode = 1;
|
|
9318
|
+
}
|
|
9319
|
+
return;
|
|
9320
|
+
}
|
|
9321
|
+
const verb = dryRun ? "Would resolve" : "Resolved";
|
|
9322
|
+
console.log(`${verb} ${resolved.length} label logo(s); ${none.length} without an image; ${failed.length} failed.`);
|
|
9323
|
+
for (const slug of resolved) {
|
|
9324
|
+
console.log(` ${slug}`);
|
|
9325
|
+
}
|
|
9326
|
+
for (const item of failed) {
|
|
9327
|
+
console.log(` ${item.slug}: ${item.error}`);
|
|
9328
|
+
}
|
|
9329
|
+
if (failed.length > 0) {
|
|
9330
|
+
process.exitCode = 1;
|
|
9331
|
+
}
|
|
9332
|
+
}
|
|
9256
9333
|
async function runArtistResolveQueue(options, listArtistsCommand2) {
|
|
9257
9334
|
const limit = parseListLimit(options.limit);
|
|
9258
9335
|
const result = await listArtistsCommand2(limit ?? 50);
|
package/package.json
CHANGED