fluncle 0.278.0 → 0.280.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 +127 -86
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -95,9 +95,11 @@ var EAGAIN_WAIT, stopWaitingForReader = () => false, CliError;
95
95
  var init_output = __esm(() => {
96
96
  EAGAIN_WAIT = new Int32Array(new SharedArrayBuffer(4));
97
97
  CliError = class CliError extends Error {
98
+ dueWork;
98
99
  code;
99
- constructor(code, message) {
100
+ constructor(code, message, dueWork) {
100
101
  super(message);
102
+ this.dueWork = dueWork;
101
103
  this.name = "CliError";
102
104
  this.code = code;
103
105
  }
@@ -702,7 +704,7 @@ function parseVersion(version) {
702
704
  var currentVersion;
703
705
  var init_version = __esm(() => {
704
706
  init_output();
705
- currentVersion = "0.278.0".trim() ? "0.278.0".trim() : "0.1.0";
707
+ currentVersion = "0.280.0".trim() ? "0.280.0".trim() : "0.1.0";
706
708
  });
707
709
 
708
710
  // src/update-notifier.ts
@@ -9740,11 +9742,12 @@ async function apiRequest(path, init = {}) {
9740
9742
  const failure = isJsonFailure(data) ? data : undefined;
9741
9743
  return yield* new ApiResponseError({
9742
9744
  code: failure?.code ?? `http_${response.status}`,
9745
+ dueWork: failure?.dueWork,
9743
9746
  message: failure?.message ?? `${response.status} ${response.statusText}`
9744
9747
  });
9745
9748
  }
9746
9749
  return data;
9747
- }).pipe(mapError2((error) => error._tag === "ApiTransportError" ? error.cause : new CliError(error.code, error.message))));
9750
+ }).pipe(mapError2((error) => error._tag === "ApiTransportError" ? error.cause : new CliError(error.code, error.message, error.dueWork))));
9748
9751
  }
9749
9752
  function parseJson2(text) {
9750
9753
  if (!text) {
@@ -10105,7 +10108,7 @@ async function mixtapeGetCommand(idOrLogId) {
10105
10108
  const mixtapes = await mixtapeListCommand();
10106
10109
  const match = mixtapes.find((mixtape) => mixtape.id === idOrLogId || mixtape.logId === idOrLogId);
10107
10110
  if (!match) {
10108
- throw new CliError("mixtape_not_found", `No mixtape with id or log id ${idOrLogId}`);
10111
+ throw new CliError("mixtape_not_found", `No mixtape with id or Log ID ${idOrLogId}`);
10109
10112
  }
10110
10113
  return match;
10111
10114
  }
@@ -10389,7 +10392,7 @@ async function mixtapeUpdateCommand(id, options) {
10389
10392
  async function mixtapeDistributeCommand(idOrLogId, options, onProgress = () => {}) {
10390
10393
  const mixtape = await mixtapeGetCommand(idOrLogId);
10391
10394
  if (!mixtape.id) {
10392
- throw new CliError("mixtape_not_found", `No mixtape with id or log id ${idOrLogId}`);
10395
+ throw new CliError("mixtape_not_found", `No mixtape with id or Log ID ${idOrLogId}`);
10393
10396
  }
10394
10397
  const both = !options.youtube && !options.mixcloud;
10395
10398
  const doYoutube = both || Boolean(options.youtube);
@@ -10445,7 +10448,7 @@ async function mixtapeDistributeCommand(idOrLogId, options, onProgress = () => {
10445
10448
  async function mixtapeResyncCommand(idOrLogId, options, onProgress = () => {}) {
10446
10449
  const mixtape = await mixtapeGetCommand(idOrLogId);
10447
10450
  if (!mixtape.id) {
10448
- throw new CliError("mixtape_not_found", `No mixtape with id or log id ${idOrLogId}`);
10451
+ throw new CliError("mixtape_not_found", `No mixtape with id or Log ID ${idOrLogId}`);
10449
10452
  }
10450
10453
  if (!mixtape.logId) {
10451
10454
  throw new CliError("mixtape_no_log_id", "The mixtape isn't published yet. Distribute it before re-syncing.");
@@ -11142,7 +11145,7 @@ function parseVersion2(version) {
11142
11145
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
11143
11146
  var init_version2 = __esm(() => {
11144
11147
  init_output();
11145
- currentVersion2 = "0.278.0".trim() ? "0.278.0".trim() : "0.1.0";
11148
+ currentVersion2 = "0.280.0".trim() ? "0.280.0".trim() : "0.1.0";
11146
11149
  });
11147
11150
 
11148
11151
  // ../../packages/registry/src/index.ts
@@ -11838,7 +11841,7 @@ var init_src = __esm(() => {
11838
11841
  exposedContent: ["the XML sitemap index of every public page"],
11839
11842
  kind: "discovery",
11840
11843
  name: "discovery.sitemap",
11841
- operatorNotes: "A sitemap INDEX, not a flat urlset: the URLs live in children at /sitemap/<kind>-<n>.xml, ONE CHILD PER ENTITY TYPE (pages/findings/artists/labels/albums/galaxies/logbook/docs), each auto-paged under Google's 50,000-URL ceiling so a breach cannot happen rather than merely not having happened yet. robots.txt still names this one URL — a crawler discovers the children from here. Splitting per entity type is also the diagnostic: Search Console reports coverage PER sitemap, so each entity type gets its own submitted/indexed count.",
11844
+ operatorNotes: "A sitemap INDEX, not a flat urlset: the URLs live in children at /sitemap/<kind>-<n>.xml, ONE CHILD PER ENTITY TYPE (pages/findings/tracks/artists/labels/albums/galaxies/logbook/docs), each auto-paged under Google's 50,000-URL ceiling so a breach cannot happen rather than merely not having happened yet. robots.txt still names this one URL — a crawler discovers the children from here. Splitting per entity type is also the diagnostic: Search Console reports coverage PER sitemap, so each entity type gets its own submitted/indexed count.",
11842
11845
  probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
11843
11846
  route: "/sitemap.xml",
11844
11847
  url: `${SITE}/sitemap.xml`,
@@ -11847,7 +11850,7 @@ var init_src = __esm(() => {
11847
11850
  {
11848
11851
  apiFormat: "application/xml",
11849
11852
  exposedContent: [
11850
- "one child sitemap, per entity type: the pages / findings / artists / labels / albums / galaxies / logbook / docs URLs, auto-paged"
11853
+ "one child sitemap, per entity type: the pages / findings / tracks / artists / labels / albums / galaxies / logbook / docs URLs, auto-paged"
11851
11854
  ],
11852
11855
  kind: "discovery",
11853
11856
  name: "discovery.sitemap-shard",
@@ -12785,7 +12788,7 @@ var init_src = __esm(() => {
12785
12788
  ],
12786
12789
  kind: "cron",
12787
12790
  name: "cron.projection-maintenance",
12788
- operatorNotes: "every 5m with per-firing jitter, run by a rave-02 host systemd timer (docs/agents/hermes/projection-maintenance-timer/). Reads bounded projection status exactly once; the track, crawl, and public cutovers gate their own families independently. Open indebted families run strictly serially: track and crawl get at most twenty pages of 500, then public aggregates and artist qualification get at most four pages of 500. Repair responses omit terminal status so those four commands cannot repeat the global status suite. Public aggregate repair also advances the bounded anchor cursor after marker debt drains. The agent may repair only these four fixed targets; rebuild, audit, and every cutover mutation remain operator-only. Zero LLM tokens; no new secret.",
12791
+ operatorNotes: "every 5m with per-firing jitter, run by a rave-02 host systemd timer (docs/agents/hermes/projection-maintenance-timer/). Reads bounded projection status exactly once; the track, crawl, and public cutovers gate their own families independently. Open indebted families run strictly serially, oldest debt first, each repairing in pages of 500 under a 30-second wall budget inside a 120-second tick budget; each family's step count is sized from its measured debt, capped at 100, with a floor of four for public aggregates and artist qualification. Repair responses omit terminal status so those four commands cannot repeat the global status suite. Public aggregate repair also advances the bounded anchor cursor after marker debt drains. The agent may repair only these four fixed targets; rebuild, audit, and every cutover mutation remain operator-only. Zero LLM tokens; no new secret.",
12789
12792
  probeConfig: {
12790
12793
  cadenceMs: 5 * MINUTE_MS,
12791
12794
  cronName: "fluncle-projection-maintenance",
@@ -23117,6 +23120,13 @@ var init_admin_projections = __esm(() => {
23117
23120
  scheduled: CountSchema,
23118
23121
  status: ProjectionStatusSchema.optional(),
23119
23122
  target: ProjectionTargetSchema,
23123
+ trackRepair: object({
23124
+ catalogueRankRowsScanned: CountSchema,
23125
+ physicalRowsScanned: record2(string4(), CountSchema),
23126
+ sourceMarkersCleared: CountSchema,
23127
+ sourceMarkersDeferred: CountSchema,
23128
+ sourceMarkersScanned: CountSchema
23129
+ }).optional(),
23120
23130
  trackSourceMarkersPending: boolean3().optional()
23121
23131
  }));
23122
23132
  setProjectionCutover = oc.route({
@@ -25677,7 +25687,13 @@ var init_admin_tracks = __esm(() => {
25677
25687
  sourceAudioKey: unknown2().optional(),
25678
25688
  sourceAudioRejected: unknown2().optional(),
25679
25689
  sourceVerification: unknown2().optional(),
25690
+ videoGrain: unknown2().optional(),
25691
+ videoPalette: unknown2().optional(),
25692
+ videoPlateSubject: unknown2().optional(),
25693
+ videoRegister: unknown2().optional(),
25694
+ videoStructure: unknown2().optional(),
25680
25695
  videoUrl: unknown2().optional(),
25696
+ videoVehicle: unknown2().optional(),
25681
25697
  youtubeReverdict: unknown2().optional(),
25682
25698
  youtubeVerification: unknown2().optional(),
25683
25699
  youtubeVideoId: unknown2().optional()
@@ -26223,6 +26239,7 @@ var init_admin_tracks = __esm(() => {
26223
26239
  open: literal(false)
26224
26240
  }).optional(),
26225
26241
  debtPending: boolean3().optional(),
26242
+ dueWork: object({ branch: string4(), workKind: string4() }).optional(),
26226
26243
  ok: literal(true),
26227
26244
  oldestQueuedCaptureOver24h: boolean3().optional(),
26228
26245
  queued: number4().optional(),
@@ -26571,7 +26588,7 @@ var init_admin_turso_usage = __esm(() => {
26571
26588
  });
26572
26589
 
26573
26590
  // ../../packages/contracts/src/orpc/admin-twitch.ts
26574
- var recordLiveState, adminTwitchContract;
26591
+ var LIVE_STATE_TIMESTAMP_MAX = 64, recordLiveState, adminTwitchContract;
26575
26592
  var init_admin_twitch = __esm(() => {
26576
26593
  init_dist4();
26577
26594
  init_zod();
@@ -26582,9 +26599,9 @@ var init_admin_twitch = __esm(() => {
26582
26599
  summary: "Record the current Twitch live state for the cross-surface live callout",
26583
26600
  tags: ["Admin"]
26584
26601
  }).input(object({
26585
- at: string4().min(1),
26602
+ at: string4().max(LIVE_STATE_TIMESTAMP_MAX).datetime({ offset: true }),
26586
26603
  live: boolean3(),
26587
- startedAt: string4().nullable(),
26604
+ startedAt: string4().max(LIVE_STATE_TIMESTAMP_MAX).nullable(),
26588
26605
  title: string4().nullable()
26589
26606
  })).output(object({ ok: literal(true) }));
26590
26607
  adminTwitchContract = {
@@ -26704,11 +26721,72 @@ var init_editions = __esm(() => {
26704
26721
  };
26705
26722
  });
26706
26723
 
26724
+ // ../../packages/contracts/src/orpc/me-follows.ts
26725
+ var FollowKindSchema, FollowSchema, SaveFollowBodySchema, listPrivateFollows, savePrivateFollow, deletePrivateFollow, revokePrivateFollowLinkAccess, meFollowsContract;
26726
+ var init_me_follows = __esm(() => {
26727
+ init_dist4();
26728
+ init_zod();
26729
+ FollowKindSchema = _enum(["artist", "label"]).meta({ id: "FollowKind" });
26730
+ FollowSchema = object({
26731
+ createdAt: string4(),
26732
+ entityId: string4(),
26733
+ id: string4(),
26734
+ includeSimilar: boolean3(),
26735
+ kind: FollowKindSchema,
26736
+ name: string4(),
26737
+ slug: string4()
26738
+ }).meta({ id: "Follow" });
26739
+ SaveFollowBodySchema = looseObject({
26740
+ entityId: unknown2().optional(),
26741
+ intent: unknown2().optional(),
26742
+ kind: unknown2().optional()
26743
+ });
26744
+ listPrivateFollows = oc.route({
26745
+ method: "GET",
26746
+ operationId: "listPrivateFollows",
26747
+ path: "/me/follows",
26748
+ summary: "List the artists and labels the signed-in user follows",
26749
+ tags: ["Me"]
26750
+ }).output(object({ follows: array2(FollowSchema), ok: literal(true) }));
26751
+ savePrivateFollow = oc.route({
26752
+ method: "POST",
26753
+ operationId: "savePrivateFollow",
26754
+ path: "/me/follows",
26755
+ summary: "Follow an artist or label for the signed-in user",
26756
+ tags: ["Me"]
26757
+ }).input(SaveFollowBodySchema).output(object({
26758
+ follow: FollowSchema,
26759
+ followsEmail: boolean3(),
26760
+ ok: literal(true)
26761
+ }));
26762
+ deletePrivateFollow = oc.route({
26763
+ method: "DELETE",
26764
+ operationId: "deletePrivateFollow",
26765
+ path: "/me/follows/{id}",
26766
+ summary: "Unfollow an artist or label for the signed-in user",
26767
+ tags: ["Me"]
26768
+ }).input(object({ id: string4() })).output(object({ ok: literal(true) }));
26769
+ revokePrivateFollowLinkAccess = oc.route({
26770
+ method: "POST",
26771
+ operationId: "revokePrivateFollowLinkAccess",
26772
+ path: "/me/follow-link-access/revoke",
26773
+ summary: "Revoke emailed follows management links for the signed-in user",
26774
+ tags: ["Me"]
26775
+ }).output(object({ ok: literal(true), token: string4() }));
26776
+ meFollowsContract = {
26777
+ delete_private_follow: deletePrivateFollow,
26778
+ list_private_follows: listPrivateFollows,
26779
+ revoke_private_follow_link_access: revokePrivateFollowLinkAccess,
26780
+ save_private_follow: savePrivateFollow
26781
+ };
26782
+ });
26783
+
26707
26784
  // ../../packages/contracts/src/orpc/follow-digest.ts
26708
26785
  var TokenSchema, sendFollowDigests, getFollowDigestState, setFollowDigestState, unsubscribeFollowDigest, subscribeFollowDigest, listDigestFollows, deleteDigestFollow, followDigestContract;
26709
26786
  var init_follow_digest = __esm(() => {
26710
26787
  init_dist4();
26711
26788
  init_zod();
26789
+ init_me_follows();
26712
26790
  TokenSchema = string4().min(10).max(1024);
26713
26791
  sendFollowDigests = oc.route({
26714
26792
  method: "POST",
@@ -26783,7 +26861,7 @@ var init_follow_digest = __esm(() => {
26783
26861
  }).input(object({ token: TokenSchema })).output(object({
26784
26862
  follows: array2(object({
26785
26863
  id: string4(),
26786
- kind: _enum(["artist", "label"]),
26864
+ kind: FollowKindSchema,
26787
26865
  name: string4(),
26788
26866
  slug: string4()
26789
26867
  })),
@@ -26812,74 +26890,6 @@ var init_follow_digest = __esm(() => {
26812
26890
  };
26813
26891
  });
26814
26892
 
26815
- // ../../packages/contracts/src/orpc/me-follows.ts
26816
- var FollowKindSchema, FollowSchema, SaveFollowBodySchema, listPrivateFollows, savePrivateFollow, deletePrivateFollow, revokePrivateFollowLinkAccess, meFollowsContract;
26817
- var init_me_follows = __esm(() => {
26818
- init_dist4();
26819
- init_zod();
26820
- FollowKindSchema = _enum(["artist", "label"]).meta({ id: "FollowKind" });
26821
- FollowSchema = object({
26822
- createdAt: string4(),
26823
- entityId: string4(),
26824
- id: string4(),
26825
- includeSimilar: boolean3(),
26826
- kind: FollowKindSchema,
26827
- name: string4(),
26828
- slug: string4()
26829
- }).meta({ id: "Follow" });
26830
- SaveFollowBodySchema = looseObject({
26831
- entityId: unknown2().optional(),
26832
- intent: unknown2().optional(),
26833
- kind: unknown2().optional()
26834
- });
26835
- listPrivateFollows = oc.route({
26836
- method: "GET",
26837
- operationId: "listPrivateFollows",
26838
- path: "/me/follows",
26839
- summary: "List the artists and labels the signed-in user follows",
26840
- tags: ["Me"]
26841
- }).output(object({ follows: array2(FollowSchema), ok: literal(true) }));
26842
- savePrivateFollow = oc.route({
26843
- method: "POST",
26844
- operationId: "savePrivateFollow",
26845
- path: "/me/follows",
26846
- summary: "Follow an artist or label for the signed-in user",
26847
- tags: ["Me"]
26848
- }).input(SaveFollowBodySchema).output(object({
26849
- follow: object({
26850
- createdAt: string4(),
26851
- entityId: string4(),
26852
- id: string4(),
26853
- includeSimilar: boolean3(),
26854
- kind: FollowKindSchema,
26855
- name: string4(),
26856
- slug: string4()
26857
- }),
26858
- followsEmail: boolean3(),
26859
- ok: literal(true)
26860
- }));
26861
- deletePrivateFollow = oc.route({
26862
- method: "DELETE",
26863
- operationId: "deletePrivateFollow",
26864
- path: "/me/follows/{id}",
26865
- summary: "Unfollow an artist or label for the signed-in user",
26866
- tags: ["Me"]
26867
- }).input(object({ id: string4() })).output(object({ ok: literal(true) }));
26868
- revokePrivateFollowLinkAccess = oc.route({
26869
- method: "POST",
26870
- operationId: "revokePrivateFollowLinkAccess",
26871
- path: "/me/follow-link-access/revoke",
26872
- summary: "Revoke emailed follows management links for the signed-in user",
26873
- tags: ["Me"]
26874
- }).output(object({ ok: literal(true), token: string4() }));
26875
- meFollowsContract = {
26876
- delete_private_follow: deletePrivateFollow,
26877
- list_private_follows: listPrivateFollows,
26878
- revoke_private_follow_link_access: revokePrivateFollowLinkAccess,
26879
- save_private_follow: savePrivateFollow
26880
- };
26881
- });
26882
-
26883
26893
  // ../../packages/contracts/src/orpc/me-galaxy.ts
26884
26894
  var GalaxyProgressSchema, GalaxyMergeBodySchema, GalaxyLogBodySchema, getPrivateGalaxyProgress, mergePrivateGalaxyProgress, collectPrivateGalaxyLog, GalaxyCollectionItemSchema, GalaxyCompletionSchema, listPrivateGalaxyCollection, meGalaxyContract;
26885
26895
  var init_me_galaxy = __esm(() => {
@@ -28235,19 +28245,46 @@ async function advanceProjectionCommand(input) {
28235
28245
  let wallStopped = false;
28236
28246
  let rebuildRowsWalked = response.rebuildRowsWalked ?? 0;
28237
28247
  let rebuildReported = response.rebuildStaleFamilies !== undefined;
28248
+ const trackRepair = {
28249
+ catalogueRankRowsScanned: 0,
28250
+ physicalRowsScanned: {},
28251
+ sourceMarkersCleared: 0,
28252
+ sourceMarkersDeferred: 0,
28253
+ sourceMarkersScanned: 0
28254
+ };
28255
+ let trackRepairReported = false;
28256
+ const addTrackRepair = () => {
28257
+ const metrics = response.trackRepair;
28258
+ if (metrics === undefined) {
28259
+ return;
28260
+ }
28261
+ trackRepairReported = true;
28262
+ trackRepair.catalogueRankRowsScanned += metrics.catalogueRankRowsScanned;
28263
+ trackRepair.sourceMarkersCleared += metrics.sourceMarkersCleared;
28264
+ trackRepair.sourceMarkersDeferred += metrics.sourceMarkersDeferred;
28265
+ trackRepair.sourceMarkersScanned += metrics.sourceMarkersScanned;
28266
+ for (const [kind, scanned] of Object.entries(metrics.physicalRowsScanned)) {
28267
+ trackRepair.physicalRowsScanned[kind] = (trackRepair.physicalRowsScanned[kind] ?? 0) + scanned;
28268
+ }
28269
+ };
28270
+ addTrackRepair();
28238
28271
  while (!response.complete && steps < maxSteps) {
28239
28272
  if (wallMs !== undefined && now() - startedAt >= wallMs) {
28240
28273
  wallStopped = true;
28241
28274
  break;
28242
28275
  }
28243
28276
  response = await adminApiPost(`/api/v1/admin/projections/${target}/advance`, stepBody);
28277
+ addTrackRepair();
28244
28278
  steps += 1;
28245
28279
  processed += response.processed;
28246
28280
  scheduled += response.scheduled;
28247
28281
  rebuildRowsWalked += response.rebuildRowsWalked ?? 0;
28248
28282
  rebuildReported ||= response.rebuildStaleFamilies !== undefined;
28249
28283
  }
28250
- const rebuild = rebuildReported ? { rebuildRowsWalked, rebuildStaleFamilies: response.rebuildStaleFamilies ?? 0 } : {};
28284
+ const rebuild = {
28285
+ ...rebuildReported ? { rebuildRowsWalked, rebuildStaleFamilies: response.rebuildStaleFamilies ?? 0 } : {},
28286
+ ...trackRepairReported ? { trackRepair } : {}
28287
+ };
28251
28288
  if (!includeTerminalStatus) {
28252
28289
  const { status: _status, ...withoutStatus } = response;
28253
28290
  return { ...withoutStatus, ...rebuild, processed, scheduled, steps, wallStopped };
@@ -28651,6 +28688,7 @@ async function trackWorkCommand(options) {
28651
28688
  const response = await adminApiGet(`/api/v1/admin/tracks/work?${params.toString()}`);
28652
28689
  return {
28653
28690
  debtPending: response.debtPending,
28691
+ dueWork: response.dueWork,
28654
28692
  queued: response.queued,
28655
28693
  tracks: response.tracks ?? []
28656
28694
  };
@@ -34028,9 +34066,11 @@ function routeConsoleThroughBlockingWrites(pastDeadline) {
34028
34066
  console.warn = toStderr;
34029
34067
  }
34030
34068
  class CliError2 extends Error {
34069
+ dueWork;
34031
34070
  code;
34032
- constructor(code, message) {
34071
+ constructor(code, message, dueWork) {
34033
34072
  super(message);
34073
+ this.dueWork = dueWork;
34034
34074
  this.name = "CliError";
34035
34075
  this.code = code;
34036
34076
  }
@@ -34043,6 +34083,7 @@ function toJsonFailure(error) {
34043
34083
  if (error instanceof CliError2) {
34044
34084
  return {
34045
34085
  code: error.code,
34086
+ ...error.dueWork === undefined ? {} : { dueWork: error.dueWork },
34046
34087
  message: error.message,
34047
34088
  ok: false
34048
34089
  };
@@ -34738,7 +34779,7 @@ JSON field reference:
34738
34779
  await Promise.resolve().then(() => init_mixtapes());
34739
34780
  await runMixtapeList(options, mixtapeListCommand);
34740
34781
  });
34741
- adminMixtapes.command("get").description("Show one mixtape by id or log id").argument("[idOrLogId]").option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
34782
+ adminMixtapes.command("get").description("Show one mixtape by id or Log ID").argument("[idOrLogId]").option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
34742
34783
  await Promise.resolve().then(() => init_mixtapes());
34743
34784
  await runMixtapeGet(idOrLogId, options, mixtapeGetCommand);
34744
34785
  });
@@ -37431,7 +37472,7 @@ async function runPublishAdvancePause(paused, options, publishAdvancePauseComman
37431
37472
  }
37432
37473
  async function runMixtapeGet(idOrLogId, options, mixtapeGetCommand) {
37433
37474
  if (!idOrLogId) {
37434
- throw new Error("Missing mixtape id or log id. Usage: fluncle admin mixtapes get <id|logId>");
37475
+ throw new Error("Missing mixtape id or Log ID. Usage: fluncle admin mixtapes get <id|logId>");
37435
37476
  }
37436
37477
  const mixtape = await mixtapeGetCommand(idOrLogId);
37437
37478
  if (options.json) {
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.278.0"
34
+ "version": "0.280.0"
35
35
  }