fluncle 0.38.0 → 0.40.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 +309 -49
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -2497,9 +2497,234 @@ var require_main = __commonJS((exports, module) => {
|
|
|
2497
2497
|
module.exports = DotenvModule;
|
|
2498
2498
|
});
|
|
2499
2499
|
|
|
2500
|
+
// src/output.ts
|
|
2501
|
+
function printJson2(value) {
|
|
2502
|
+
console.log(JSON.stringify(value, null, 2));
|
|
2503
|
+
}
|
|
2504
|
+
var CliError2;
|
|
2505
|
+
var init_output = __esm(() => {
|
|
2506
|
+
CliError2 = class CliError2 extends Error {
|
|
2507
|
+
code;
|
|
2508
|
+
constructor(code, message) {
|
|
2509
|
+
super(message);
|
|
2510
|
+
this.name = "CliError";
|
|
2511
|
+
this.code = code;
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
});
|
|
2515
|
+
|
|
2516
|
+
// src/version.ts
|
|
2517
|
+
function normalizeVersion(version) {
|
|
2518
|
+
return version?.trim().replace(/^v/i, "");
|
|
2519
|
+
}
|
|
2520
|
+
function compareVersions(left, right) {
|
|
2521
|
+
const leftParts = parseVersion(left);
|
|
2522
|
+
const rightParts = parseVersion(right);
|
|
2523
|
+
for (let index = 0;index < 3; index += 1) {
|
|
2524
|
+
const difference = leftParts[index] - rightParts[index];
|
|
2525
|
+
if (difference !== 0) {
|
|
2526
|
+
return difference;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
return 0;
|
|
2530
|
+
}
|
|
2531
|
+
function parseVersion(version) {
|
|
2532
|
+
const parts = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
2533
|
+
return [
|
|
2534
|
+
Number.isInteger(parts[0]) ? parts[0] : 0,
|
|
2535
|
+
Number.isInteger(parts[1]) ? parts[1] : 0,
|
|
2536
|
+
Number.isInteger(parts[2]) ? parts[2] : 0
|
|
2537
|
+
];
|
|
2538
|
+
}
|
|
2539
|
+
var currentVersion;
|
|
2540
|
+
var init_version = __esm(() => {
|
|
2541
|
+
init_output();
|
|
2542
|
+
currentVersion = "0.40.0".trim() ? "0.40.0".trim() : "0.1.0";
|
|
2543
|
+
});
|
|
2544
|
+
|
|
2545
|
+
// src/update-notifier.ts
|
|
2546
|
+
var exports_update_notifier = {};
|
|
2547
|
+
__export(exports_update_notifier, {
|
|
2548
|
+
updateCommand: () => updateCommand,
|
|
2549
|
+
shouldNotify: () => shouldNotify,
|
|
2550
|
+
notifyIfUpdateAvailable: () => notifyIfUpdateAvailable,
|
|
2551
|
+
detectInstallMethod: () => detectInstallMethod
|
|
2552
|
+
});
|
|
2553
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2554
|
+
import { homedir, platform } from "node:os";
|
|
2555
|
+
import { dirname, join, sep } from "node:path";
|
|
2556
|
+
import { fileURLToPath } from "node:url";
|
|
2557
|
+
async function notifyIfUpdateAvailable(args) {
|
|
2558
|
+
try {
|
|
2559
|
+
if (!shouldNotify(args)) {
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
const latestVersion = await resolveLatestVersion();
|
|
2563
|
+
if (!latestVersion) {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
if (compareVersions(latestVersion, currentVersion) <= 0) {
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
process.stderr.write(`
|
|
2570
|
+
${buildNotice(currentVersion, latestVersion)}
|
|
2571
|
+
`);
|
|
2572
|
+
} catch {}
|
|
2573
|
+
}
|
|
2574
|
+
function shouldNotify(args) {
|
|
2575
|
+
if (process.env.FLUNCLE_NO_UPDATE_NOTIFIER === "1") {
|
|
2576
|
+
return false;
|
|
2577
|
+
}
|
|
2578
|
+
if (process.env.CI) {
|
|
2579
|
+
return false;
|
|
2580
|
+
}
|
|
2581
|
+
if (process.stderr.isTTY !== true) {
|
|
2582
|
+
return false;
|
|
2583
|
+
}
|
|
2584
|
+
if (args.includes("--json")) {
|
|
2585
|
+
return false;
|
|
2586
|
+
}
|
|
2587
|
+
const command = firstPositional(args);
|
|
2588
|
+
if (command === "version" || command === "about" || command === "help") {
|
|
2589
|
+
return false;
|
|
2590
|
+
}
|
|
2591
|
+
if (args.includes("--help") || args.includes("-h") || args.includes("--version")) {
|
|
2592
|
+
return false;
|
|
2593
|
+
}
|
|
2594
|
+
return true;
|
|
2595
|
+
}
|
|
2596
|
+
function firstPositional(args) {
|
|
2597
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
2598
|
+
const arg = args[index];
|
|
2599
|
+
if (arg === "--env") {
|
|
2600
|
+
index += 1;
|
|
2601
|
+
continue;
|
|
2602
|
+
}
|
|
2603
|
+
if (arg.startsWith("-")) {
|
|
2604
|
+
continue;
|
|
2605
|
+
}
|
|
2606
|
+
return arg;
|
|
2607
|
+
}
|
|
2608
|
+
return;
|
|
2609
|
+
}
|
|
2610
|
+
async function resolveLatestVersion() {
|
|
2611
|
+
const cached = await readCache();
|
|
2612
|
+
if (cached && Date.now() - cached.checkedAt < cacheTtlMs) {
|
|
2613
|
+
return cached.latestVersion;
|
|
2614
|
+
}
|
|
2615
|
+
const fetched = await fetchLatestVersion();
|
|
2616
|
+
if (!fetched) {
|
|
2617
|
+
return cached?.latestVersion;
|
|
2618
|
+
}
|
|
2619
|
+
await writeCache({ checkedAt: Date.now(), latestVersion: fetched });
|
|
2620
|
+
return fetched;
|
|
2621
|
+
}
|
|
2622
|
+
async function fetchLatestVersion() {
|
|
2623
|
+
const controller = new AbortController;
|
|
2624
|
+
const timeout = setTimeout(() => controller.abort(), fetchTimeoutMs);
|
|
2625
|
+
try {
|
|
2626
|
+
const response = await fetch(registryUrl, {
|
|
2627
|
+
headers: {
|
|
2628
|
+
Accept: "application/vnd.npm.install-v1+json",
|
|
2629
|
+
"User-Agent": `fluncle/${currentVersion}`
|
|
2630
|
+
},
|
|
2631
|
+
signal: controller.signal
|
|
2632
|
+
});
|
|
2633
|
+
if (!response.ok) {
|
|
2634
|
+
return;
|
|
2635
|
+
}
|
|
2636
|
+
const body = await response.json();
|
|
2637
|
+
return normalizeVersion(body["dist-tags"]?.latest);
|
|
2638
|
+
} catch {
|
|
2639
|
+
return;
|
|
2640
|
+
} finally {
|
|
2641
|
+
clearTimeout(timeout);
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
async function readCache() {
|
|
2645
|
+
try {
|
|
2646
|
+
const raw = await readFile(cacheFilePath(), "utf8");
|
|
2647
|
+
const parsed = JSON.parse(raw);
|
|
2648
|
+
if (typeof parsed.checkedAt !== "number" || typeof parsed.latestVersion !== "string") {
|
|
2649
|
+
return;
|
|
2650
|
+
}
|
|
2651
|
+
return { checkedAt: parsed.checkedAt, latestVersion: parsed.latestVersion };
|
|
2652
|
+
} catch {
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
async function writeCache(state) {
|
|
2657
|
+
try {
|
|
2658
|
+
const file = cacheFilePath();
|
|
2659
|
+
await mkdir(dirname(file), { recursive: true });
|
|
2660
|
+
await writeFile(file, JSON.stringify(state), "utf8");
|
|
2661
|
+
} catch {}
|
|
2662
|
+
}
|
|
2663
|
+
function cacheFilePath() {
|
|
2664
|
+
const base = process.env.XDG_CACHE_HOME?.trim() || platform() === "win32" && process.env.LOCALAPPDATA?.trim() || join(homedir(), ".config");
|
|
2665
|
+
return join(base, "fluncle", "update-check.json");
|
|
2666
|
+
}
|
|
2667
|
+
function buildNotice(current, latest) {
|
|
2668
|
+
const method = detectInstallMethod({ entry: entryPath(), execPath: process.execPath || "" });
|
|
2669
|
+
const command = updateCommand(method);
|
|
2670
|
+
return [`Update available: fluncle ${current} → ${latest}`, `Run: ${command}`].join(`
|
|
2671
|
+
`);
|
|
2672
|
+
}
|
|
2673
|
+
function updateCommand(method) {
|
|
2674
|
+
if (method === "homebrew") {
|
|
2675
|
+
return "brew upgrade fluncle";
|
|
2676
|
+
}
|
|
2677
|
+
if (method === "binary") {
|
|
2678
|
+
return `curl -fsSL https://www.fluncle.com/cli/latest.sh | sh (or ${releasesUrl})`;
|
|
2679
|
+
}
|
|
2680
|
+
return "npm i -g fluncle@latest";
|
|
2681
|
+
}
|
|
2682
|
+
function detectInstallMethod(launch) {
|
|
2683
|
+
const { entry, execPath } = launch;
|
|
2684
|
+
const haystack = `${execPath}
|
|
2685
|
+
${entry}`.toLowerCase();
|
|
2686
|
+
if (isHomebrewPath(haystack)) {
|
|
2687
|
+
return "homebrew";
|
|
2688
|
+
}
|
|
2689
|
+
if (isCompiledBinary(execPath, entry)) {
|
|
2690
|
+
return "binary";
|
|
2691
|
+
}
|
|
2692
|
+
if (entry.endsWith(".mjs") || entry.endsWith(".js") || entry.endsWith(".cjs") || haystack.includes(`${sep}node_modules${sep}`) || haystack.includes("/node_modules/")) {
|
|
2693
|
+
return "npm";
|
|
2694
|
+
}
|
|
2695
|
+
return "npm";
|
|
2696
|
+
}
|
|
2697
|
+
function isHomebrewPath(haystack) {
|
|
2698
|
+
return haystack.includes("/cellar/") || haystack.includes("/homebrew/") || haystack.includes("/.linuxbrew/") || haystack.includes("/usr/local/cellar/") || haystack.includes("homebrew");
|
|
2699
|
+
}
|
|
2700
|
+
function isCompiledBinary(execPath, entry) {
|
|
2701
|
+
const exec = execPath.toLowerCase();
|
|
2702
|
+
const base = exec.split(/[\\/]/).pop() ?? "";
|
|
2703
|
+
if (!base.startsWith("fluncle")) {
|
|
2704
|
+
return false;
|
|
2705
|
+
}
|
|
2706
|
+
return entry === "" || entry === execPath;
|
|
2707
|
+
}
|
|
2708
|
+
function entryPath() {
|
|
2709
|
+
const fromArgv = process.argv[1] ?? "";
|
|
2710
|
+
if (fromArgv) {
|
|
2711
|
+
return fromArgv;
|
|
2712
|
+
}
|
|
2713
|
+
try {
|
|
2714
|
+
return fileURLToPath(import.meta.url);
|
|
2715
|
+
} catch {
|
|
2716
|
+
return "";
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
var registryUrl = "https://registry.npmjs.org/fluncle", releasesUrl = "https://github.com/mauricekleine/fluncle/releases/latest", cacheTtlMs, fetchTimeoutMs = 1500;
|
|
2720
|
+
var init_update_notifier = __esm(() => {
|
|
2721
|
+
init_version();
|
|
2722
|
+
cacheTtlMs = 24 * 60 * 60 * 1000;
|
|
2723
|
+
});
|
|
2724
|
+
|
|
2500
2725
|
// src/env.ts
|
|
2501
|
-
import { homedir } from "node:os";
|
|
2502
|
-
import { join } from "node:path";
|
|
2726
|
+
import { homedir as homedir2 } from "node:os";
|
|
2727
|
+
import { join as join2 } from "node:path";
|
|
2503
2728
|
function loadEnv(keys) {
|
|
2504
2729
|
loadConfig();
|
|
2505
2730
|
const missing = keys.filter((key) => !process.env[key]);
|
|
@@ -2517,7 +2742,7 @@ function loadConfig() {
|
|
|
2517
2742
|
if (loadedProfile === profile) {
|
|
2518
2743
|
return;
|
|
2519
2744
|
}
|
|
2520
|
-
import_dotenv2.config({ path:
|
|
2745
|
+
import_dotenv2.config({ path: join2(homedir2(), `.config/fluncle/.env.${profile}`) });
|
|
2521
2746
|
loadedProfile = profile;
|
|
2522
2747
|
}
|
|
2523
2748
|
function getEnvProfile() {
|
|
@@ -2536,22 +2761,6 @@ var init_env = __esm(() => {
|
|
|
2536
2761
|
envProfiles2 = ["local", "production"];
|
|
2537
2762
|
});
|
|
2538
2763
|
|
|
2539
|
-
// src/output.ts
|
|
2540
|
-
function printJson2(value) {
|
|
2541
|
-
console.log(JSON.stringify(value, null, 2));
|
|
2542
|
-
}
|
|
2543
|
-
var CliError2;
|
|
2544
|
-
var init_output = __esm(() => {
|
|
2545
|
-
CliError2 = class CliError2 extends Error {
|
|
2546
|
-
code;
|
|
2547
|
-
constructor(code, message) {
|
|
2548
|
-
super(message);
|
|
2549
|
-
this.name = "CliError";
|
|
2550
|
-
this.code = code;
|
|
2551
|
-
}
|
|
2552
|
-
};
|
|
2553
|
-
});
|
|
2554
|
-
|
|
2555
2764
|
// src/api.ts
|
|
2556
2765
|
async function publicApiGet(path) {
|
|
2557
2766
|
return apiRequest(path);
|
|
@@ -3715,7 +3924,10 @@ var init_about = __esm(() => {
|
|
|
3715
3924
|
// src/version.ts
|
|
3716
3925
|
var exports_version = {};
|
|
3717
3926
|
__export(exports_version, {
|
|
3718
|
-
versionCommand: () => versionCommand
|
|
3927
|
+
versionCommand: () => versionCommand,
|
|
3928
|
+
normalizeVersion: () => normalizeVersion2,
|
|
3929
|
+
currentVersion: () => currentVersion2,
|
|
3930
|
+
compareVersions: () => compareVersions2
|
|
3719
3931
|
});
|
|
3720
3932
|
async function versionCommand(options) {
|
|
3721
3933
|
const result = options.check ? await buildVersionCheck() : buildCurrentVersion();
|
|
@@ -3730,46 +3942,46 @@ async function versionCommand(options) {
|
|
|
3730
3942
|
}
|
|
3731
3943
|
function buildCurrentVersion() {
|
|
3732
3944
|
return {
|
|
3733
|
-
currentVersion,
|
|
3734
|
-
message: `fluncle ${
|
|
3945
|
+
currentVersion: currentVersion2,
|
|
3946
|
+
message: `fluncle ${currentVersion2}`
|
|
3735
3947
|
};
|
|
3736
3948
|
}
|
|
3737
3949
|
async function buildVersionCheck() {
|
|
3738
3950
|
const response = await fetch(latestReleaseUrl, {
|
|
3739
3951
|
headers: {
|
|
3740
|
-
"User-Agent": `fluncle/${
|
|
3952
|
+
"User-Agent": `fluncle/${currentVersion2}`
|
|
3741
3953
|
}
|
|
3742
3954
|
});
|
|
3743
3955
|
if (response.status === 404) {
|
|
3744
3956
|
return {
|
|
3745
|
-
currentVersion,
|
|
3746
|
-
message: `fluncle ${
|
|
3957
|
+
currentVersion: currentVersion2,
|
|
3958
|
+
message: `fluncle ${currentVersion2}. No GitHub release found yet.`
|
|
3747
3959
|
};
|
|
3748
3960
|
}
|
|
3749
3961
|
if (!response.ok) {
|
|
3750
3962
|
throw new Error(`Update check failed: ${response.status} ${response.statusText}`);
|
|
3751
3963
|
}
|
|
3752
3964
|
const release = await response.json();
|
|
3753
|
-
const latestVersion =
|
|
3965
|
+
const latestVersion = normalizeVersion2(release.tag_name);
|
|
3754
3966
|
if (!latestVersion) {
|
|
3755
3967
|
throw new Error("Update check failed: latest release did not include a tag");
|
|
3756
3968
|
}
|
|
3757
|
-
const updateAvailable =
|
|
3969
|
+
const updateAvailable = compareVersions2(latestVersion, currentVersion2) > 0;
|
|
3758
3970
|
const releaseUrl = `https://github.com/mauricekleine/fluncle/releases/latest`;
|
|
3759
3971
|
return {
|
|
3760
|
-
currentVersion,
|
|
3972
|
+
currentVersion: currentVersion2,
|
|
3761
3973
|
latestVersion,
|
|
3762
|
-
message: updateAvailable ? `fluncle ${
|
|
3974
|
+
message: updateAvailable ? `fluncle ${currentVersion2}. Update available: ${latestVersion}. Run: curl -fsSL https://www.fluncle.com/cli/latest.sh | sh` : `fluncle ${currentVersion2}. You are up to date.`,
|
|
3763
3975
|
releaseUrl,
|
|
3764
3976
|
updateAvailable
|
|
3765
3977
|
};
|
|
3766
3978
|
}
|
|
3767
|
-
function
|
|
3979
|
+
function normalizeVersion2(version) {
|
|
3768
3980
|
return version?.trim().replace(/^v/i, "");
|
|
3769
3981
|
}
|
|
3770
|
-
function
|
|
3771
|
-
const leftParts =
|
|
3772
|
-
const rightParts =
|
|
3982
|
+
function compareVersions2(left, right) {
|
|
3983
|
+
const leftParts = parseVersion2(left);
|
|
3984
|
+
const rightParts = parseVersion2(right);
|
|
3773
3985
|
for (let index = 0;index < 3; index += 1) {
|
|
3774
3986
|
const difference = leftParts[index] - rightParts[index];
|
|
3775
3987
|
if (difference !== 0) {
|
|
@@ -3778,7 +3990,7 @@ function compareVersions(left, right) {
|
|
|
3778
3990
|
}
|
|
3779
3991
|
return 0;
|
|
3780
3992
|
}
|
|
3781
|
-
function
|
|
3993
|
+
function parseVersion2(version) {
|
|
3782
3994
|
const parts = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
3783
3995
|
return [
|
|
3784
3996
|
Number.isInteger(parts[0]) ? parts[0] : 0,
|
|
@@ -3786,10 +3998,10 @@ function parseVersion(version) {
|
|
|
3786
3998
|
Number.isInteger(parts[2]) ? parts[2] : 0
|
|
3787
3999
|
];
|
|
3788
4000
|
}
|
|
3789
|
-
var
|
|
3790
|
-
var
|
|
4001
|
+
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
4002
|
+
var init_version2 = __esm(() => {
|
|
3791
4003
|
init_output();
|
|
3792
|
-
|
|
4004
|
+
currentVersion2 = "0.40.0".trim() ? "0.40.0".trim() : "0.1.0";
|
|
3793
4005
|
});
|
|
3794
4006
|
|
|
3795
4007
|
// src/commands/track.ts
|
|
@@ -3855,10 +4067,10 @@ async function readManifestFields(renderPath) {
|
|
|
3855
4067
|
} catch {}
|
|
3856
4068
|
return {};
|
|
3857
4069
|
}
|
|
3858
|
-
async function trackDraftCommand(idOrLogId,
|
|
3859
|
-
return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${
|
|
4070
|
+
async function trackDraftCommand(idOrLogId, platform2) {
|
|
4071
|
+
return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}/draft`);
|
|
3860
4072
|
}
|
|
3861
|
-
async function trackSocialUpdateCommand(idOrLogId,
|
|
4073
|
+
async function trackSocialUpdateCommand(idOrLogId, platform2, options) {
|
|
3862
4074
|
const body = { status: options.status };
|
|
3863
4075
|
if (options.url !== undefined) {
|
|
3864
4076
|
body.url = options.url;
|
|
@@ -3866,7 +4078,7 @@ async function trackSocialUpdateCommand(idOrLogId, platform, options) {
|
|
|
3866
4078
|
if (options.scheduledFor !== undefined) {
|
|
3867
4079
|
body.scheduledFor = options.scheduledFor;
|
|
3868
4080
|
}
|
|
3869
|
-
return adminApiPatch(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${
|
|
4081
|
+
return adminApiPatch(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}`, body);
|
|
3870
4082
|
}
|
|
3871
4083
|
async function trackSocialShowCommand(idOrLogId) {
|
|
3872
4084
|
return adminApiGet(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social`);
|
|
@@ -3960,7 +4172,9 @@ __export(exports_admin_tracks, {
|
|
|
3960
4172
|
vehiclesCommand: () => vehiclesCommand,
|
|
3961
4173
|
queueCommand: () => queueCommand,
|
|
3962
4174
|
enrichSweepCommand: () => enrichSweepCommand,
|
|
3963
|
-
enrichQueueCommand: () => enrichQueueCommand
|
|
4175
|
+
enrichQueueCommand: () => enrichQueueCommand,
|
|
4176
|
+
backfillLastfmCommand: () => backfillLastfmCommand,
|
|
4177
|
+
backfillDiscogsCommand: () => backfillDiscogsCommand
|
|
3964
4178
|
});
|
|
3965
4179
|
async function fetchAdminTracks(options) {
|
|
3966
4180
|
const { hasVideo, max, order, status } = options;
|
|
@@ -4001,6 +4215,12 @@ async function enrichQueueCommand(limit) {
|
|
|
4001
4215
|
async function enrichSweepCommand(limit) {
|
|
4002
4216
|
return adminApiPost(`/api/admin/enrich-sweep?limit=${limit}`);
|
|
4003
4217
|
}
|
|
4218
|
+
async function backfillLastfmCommand(limit, dryRun) {
|
|
4219
|
+
return adminApiPost(`/api/admin/backfill/lastfm?limit=${limit}&dryRun=${dryRun}`);
|
|
4220
|
+
}
|
|
4221
|
+
async function backfillDiscogsCommand(limit, dryRun) {
|
|
4222
|
+
return adminApiPost(`/api/admin/backfill/discogs?limit=${limit}&dryRun=${dryRun}`);
|
|
4223
|
+
}
|
|
4004
4224
|
async function vehiclesCommand(limit) {
|
|
4005
4225
|
const tracks = await fetchAdminTracks({ hasVideo: true, max: limit, order: "desc" });
|
|
4006
4226
|
return tracks.map((track) => ({
|
|
@@ -5088,6 +5308,8 @@ async function main(args = process.argv.slice(2)) {
|
|
|
5088
5308
|
}
|
|
5089
5309
|
process.exit(1);
|
|
5090
5310
|
}
|
|
5311
|
+
const { notifyIfUpdateAvailable: notifyIfUpdateAvailable2 } = await Promise.resolve().then(() => (init_update_notifier(), exports_update_notifier));
|
|
5312
|
+
await notifyIfUpdateAvailable2(args);
|
|
5091
5313
|
}
|
|
5092
5314
|
function configureCommand(command) {
|
|
5093
5315
|
return command.exitOverride().addHelpCommand(false).configureOutput({
|
|
@@ -5128,7 +5350,7 @@ function addMetaCommands(program2) {
|
|
|
5128
5350
|
aboutCommand2();
|
|
5129
5351
|
});
|
|
5130
5352
|
program2.command("version").description("Print or check the version").option("--check", "Check the latest GitHub release", false).option("--json", "Print JSON", false).action(async (options) => {
|
|
5131
|
-
const { versionCommand: versionCommand2 } = await Promise.resolve().then(() => (
|
|
5353
|
+
const { versionCommand: versionCommand2 } = await Promise.resolve().then(() => (init_version2(), exports_version));
|
|
5132
5354
|
await versionCommand2({
|
|
5133
5355
|
check: options.check,
|
|
5134
5356
|
json: options.json
|
|
@@ -5289,6 +5511,14 @@ function addAdminCommands(program2) {
|
|
|
5289
5511
|
const { previewArchiveBackfillCommand: previewArchiveBackfillCommand2 } = await Promise.resolve().then(() => (init_preview_archive(), exports_preview_archive));
|
|
5290
5512
|
await runPreviewArchiveBackfill(options, previewArchiveBackfillCommand2);
|
|
5291
5513
|
});
|
|
5514
|
+
backfill.command("lastfm").description("Love already-published findings on Last.fm (idempotent; a no-op until configured)").option("--dry-run", "Resolve the set but fire no loves; just report what would be loved", false).option("--limit <limit>", "Max findings to love", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
5515
|
+
const { backfillLastfmCommand: backfillLastfmCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
5516
|
+
await runBackfillLastfm(options, backfillLastfmCommand2);
|
|
5517
|
+
});
|
|
5518
|
+
backfill.command("discogs").description("Resolve missing Discogs release ids for published findings (high-confidence only)").option("--dry-run", "Resolve but write nothing; just report what would be resolved", false).option("--limit <limit>", "Max findings to resolve", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
5519
|
+
const { backfillDiscogsCommand: backfillDiscogsCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
5520
|
+
await runBackfillDiscogs(options, backfillDiscogsCommand2);
|
|
5521
|
+
});
|
|
5292
5522
|
}
|
|
5293
5523
|
async function runTrackPreviewArchive(idOrLogId, options, previewArchiveUploadCommand2) {
|
|
5294
5524
|
if (!idOrLogId || !options.file || !options.source || !options.mime) {
|
|
@@ -5358,6 +5588,36 @@ async function runPreviewArchiveBackfill(options, previewArchiveBackfillCommand2
|
|
|
5358
5588
|
console.log(` ${item.logId}: ${item.source}`);
|
|
5359
5589
|
}
|
|
5360
5590
|
}
|
|
5591
|
+
async function runBackfillLastfm(options, backfillLastfmCommand2) {
|
|
5592
|
+
const limit = parseListLimit(options.limit);
|
|
5593
|
+
const result = await backfillLastfmCommand2(limit, options.dryRun);
|
|
5594
|
+
if (options.json) {
|
|
5595
|
+
printJson(result);
|
|
5596
|
+
return;
|
|
5597
|
+
}
|
|
5598
|
+
const verb = result.dryRun ? "Would love" : "Loved";
|
|
5599
|
+
console.log(`${verb} ${result.lovedCount} finding(s) on Last.fm; ${result.failedCount} failed.`);
|
|
5600
|
+
for (const logId of result.loved) {
|
|
5601
|
+
console.log(` ${logId}`);
|
|
5602
|
+
}
|
|
5603
|
+
for (const item of result.failed) {
|
|
5604
|
+
console.log(` ${item.logId}: ${item.error}`);
|
|
5605
|
+
}
|
|
5606
|
+
}
|
|
5607
|
+
async function runBackfillDiscogs(options, backfillDiscogsCommand2) {
|
|
5608
|
+
const limit = parseListLimit(options.limit);
|
|
5609
|
+
const result = await backfillDiscogsCommand2(limit, options.dryRun);
|
|
5610
|
+
if (options.json) {
|
|
5611
|
+
printJson(result);
|
|
5612
|
+
return;
|
|
5613
|
+
}
|
|
5614
|
+
const verb = result.dryRun ? "Would resolve" : "Resolved";
|
|
5615
|
+
console.log(`${verb} ${result.resolvedCount} Discogs release id(s); ${result.unresolvedCount} unresolved.`);
|
|
5616
|
+
for (const item of result.resolved) {
|
|
5617
|
+
const master = item.masterId ? ` (master ${item.masterId})` : "";
|
|
5618
|
+
console.log(` ${item.logId}: release ${item.releaseId}${master}`);
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5361
5621
|
async function runTrackVideo(idOrLogId, options, trackVideoCommand2) {
|
|
5362
5622
|
if (!idOrLogId) {
|
|
5363
5623
|
throw new Error("Missing id. Usage: fluncle admin track video <track_id|log_id> (--dir <dir> | --footage <file> [--footage-silent <file>] [--poster <file>] [--cover <file>] [--note <file>] [--composition <file>] [--props <file>] [--render <file>])");
|
|
@@ -5406,13 +5666,13 @@ async function runTrackDraft(idOrLogId, options, trackDraftCommand2) {
|
|
|
5406
5666
|
if (!idOrLogId) {
|
|
5407
5667
|
throw new Error("Missing id. Usage: fluncle admin track draft <track_id|log_id> [--platform tiktok]");
|
|
5408
5668
|
}
|
|
5409
|
-
const
|
|
5410
|
-
const result = await trackDraftCommand2(idOrLogId,
|
|
5669
|
+
const platform2 = options.platform ?? "tiktok";
|
|
5670
|
+
const result = await trackDraftCommand2(idOrLogId, platform2);
|
|
5411
5671
|
if (options.json) {
|
|
5412
5672
|
printJson(result);
|
|
5413
5673
|
return;
|
|
5414
5674
|
}
|
|
5415
|
-
console.log(`Pushed ${
|
|
5675
|
+
console.log(`Pushed ${platform2} draft for ${result.trackId} (post ${result.externalId})`);
|
|
5416
5676
|
}
|
|
5417
5677
|
async function runTrackSocial(idOrLogId, options, trackSocialShowCommand2, trackSocialUpdateCommand2) {
|
|
5418
5678
|
if (!idOrLogId) {
|
|
@@ -5439,8 +5699,8 @@ async function runTrackSocial(idOrLogId, options, trackSocialShowCommand2, track
|
|
|
5439
5699
|
if (options.status === "published" && !options.url) {
|
|
5440
5700
|
throw new Error("Publishing requires --url <post-url>");
|
|
5441
5701
|
}
|
|
5442
|
-
const
|
|
5443
|
-
const result = await trackSocialUpdateCommand2(idOrLogId,
|
|
5702
|
+
const platform2 = options.platform ?? "tiktok";
|
|
5703
|
+
const result = await trackSocialUpdateCommand2(idOrLogId, platform2, {
|
|
5444
5704
|
scheduledFor: options.scheduledFor,
|
|
5445
5705
|
status: options.status,
|
|
5446
5706
|
url: options.url
|
|
@@ -5449,7 +5709,7 @@ async function runTrackSocial(idOrLogId, options, trackSocialShowCommand2, track
|
|
|
5449
5709
|
printJson(result);
|
|
5450
5710
|
return;
|
|
5451
5711
|
}
|
|
5452
|
-
console.log(`${
|
|
5712
|
+
console.log(`${platform2} \u2192 ${options.status} for ${result.trackId}`);
|
|
5453
5713
|
}
|
|
5454
5714
|
async function runTrackGet(idOrLogId, options, trackGetCommand2) {
|
|
5455
5715
|
if (!idOrLogId) {
|
package/package.json
CHANGED