Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 9920845af6b7dae89a68467ae252b86d1dda72f0
parent fe9a33301463c5ec9d1ff5396279b9677e07f962
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu, 24 Sep 2026 13:12:01 -0400

channels: column ids and presets move to a plain module (server-importable)

A server component that imports a VALUE from a "use client" module gets a
client reference, not the value: ChannelWorkTable's `WORK_COLUMNS.filter`
threw "filter is not a function" on every operation page (found by the e2e
run's first minute; tsc cannot see it). The ids, sort keys, PipelineColumn
and the three presets now live in `channelColumnPresets.ts` (no directive);
the client registry re-exports them for client importers, and the two server
importers (ChannelWorkTable, channels/page) take them from the plain module.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Aeditor/app/channels/components/channelColumnPresets.ts | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Meditor/app/channels/components/channelColumns.tsx | 105++++++++++++-------------------------------------------------------------------
Meditor/app/channels/page.tsx | 2+-
Meditor/app/components/channelWork/ChannelWorkTable.tsx | 8++++----
4 files changed, 116 insertions(+), 95 deletions(-)

diff --git a/editor/app/channels/components/channelColumnPresets.ts b/editor/app/channels/components/channelColumnPresets.ts @@ -0,0 +1,96 @@ +// THE CHANNEL COLUMN IDS AND PRESETS — plain data, deliberately NOT in the +// "use client" registry (./channelColumns.tsx). A server component that imports +// a value from a client module gets a client REFERENCE, not the value: the work +// tables' server shell calling `WORK_COLUMNS.filter(...)` threw "filter is not +// a function". So the ids, the sort keys, the pipeline-column shape and the +// presets live here, importable from either side; the cells stay client-only. + +export type ChannelColumnId = + | "select" + | "slug" + | "name" + | "handling" + | "build" + | "tier" + | "playlist" + | "videos" + | "digestReachable" + | "count" + | "extra" + | "lastSync" + | "lastSyncRelative" + | "report" + | "location" + | "size" + | "pipelines" + | "actions"; + +// Sorting a pipeline column sorts by `reachable` — "which channel has the most +// diarizable audio left right now". +export type ChannelSortKey = + | "slug" + | "name" + | "handling" + | "build" + | "tier" + | "playlist" + | "lastSync" + | "report" + | "location" + | "size" + | `op:${string}`; + +// A column heading for one pipeline. Comes off the operation registry on the +// server (shortLabel, costBasis) rather than being abbreviated here — see +// operations.ts. +export type PipelineColumn = { + id: string; + shortLabel: string; + label: string; + costBasis: string; + // The two externally-dispatched pipelines keep their existing count column + // semantics: the cell's text node is the bare number the suite asserts on, + // under this accessible name. The slug is appended by the cell, so this is + // the prefix — `"downloads count"` becomes `"downloads count for foo"`, which + // is the name channels-counts.spec.ts has always addressed these cells by. + // Null for the derived operations, which have never had a count column and + // get the band's sentence as their text. + countLabel: string | null; +}; + +// THE PRESETS. The rack draws everything; the dashboard and a work section +// each name the handful they have always drawn. +export const RACK_COLUMNS: readonly ChannelColumnId[] = [ + "select", + "slug", + "name", + "handling", + "build", + "tier", + "playlist", + "lastSync", + "report", + "location", + "size", + "pipelines", + "actions", +]; + +export const DASHBOARD_COLUMNS: readonly ChannelColumnId[] = [ + "slug", + "handling", + "videos", + "digestReachable", + "lastSyncRelative", + "actions", +]; + +// `extra` is dropped by the caller when the section has no extra column. +export const WORK_COLUMNS: readonly ChannelColumnId[] = [ + "slug", + "count", + "extra", + "report", + "lastSync", + "actions", +]; diff --git a/editor/app/channels/components/channelColumns.tsx b/editor/app/channels/components/channelColumns.tsx @@ -11,6 +11,21 @@ import { ChannelAvailabilityButton } from "./ChannelAvailabilityButton"; import { ChannelBuildToggle } from "./ChannelBuildToggle"; import { ChannelSyncButton } from "./ChannelSyncButton"; import ChannelTierSelect from "./ChannelTierSelect"; +import type { + ChannelColumnId, + ChannelSortKey, +} from "./channelColumnPresets"; + +// Re-exported for the client importers; a SERVER importer must take these from +// ./channelColumnPresets.ts directly (see there). +export { + DASHBOARD_COLUMNS, + RACK_COLUMNS, + WORK_COLUMNS, + type ChannelColumnId, + type ChannelSortKey, + type PipelineColumn, +} from "./channelColumnPresets"; // THE CHANNEL COLUMN REGISTRY. // @@ -27,59 +42,6 @@ import ChannelTierSelect from "./ChannelTierSelect"; // `playlist count for`, `report age for`, `media location for`, `media size // for`, and — in the table's pipeline cell — `${countLabel} for`. -export type ChannelColumnId = - | "select" - | "slug" - | "name" - | "handling" - | "build" - | "tier" - | "playlist" - | "videos" - | "digestReachable" - | "count" - | "extra" - | "lastSync" - | "lastSyncRelative" - | "report" - | "location" - | "size" - | "pipelines" - | "actions"; - -// Sorting a pipeline column sorts by `reachable` — "which channel has the most -// diarizable audio left right now". -export type ChannelSortKey = - | "slug" - | "name" - | "handling" - | "build" - | "tier" - | "playlist" - | "lastSync" - | "report" - | "location" - | "size" - | `op:${string}`; - -// A column heading for one pipeline. Comes off the operation registry on the -// server (shortLabel, costBasis) rather than being abbreviated here — see -// operations.ts. -export type PipelineColumn = { - id: string; - shortLabel: string; - label: string; - costBasis: string; - // The two externally-dispatched pipelines keep their existing count column - // semantics: the cell's text node is the bare number the suite asserts on, - // under this accessible name. The slug is appended by the cell, so this is - // the prefix — `"downloads count"` becomes `"downloads count for foo"`, which - // is the name channels-counts.spec.ts has always addressed these cells by. - // Null for the derived operations, which have never had a count column and - // get the band's sentence as their text. - countLabel: string | null; -}; - // What a server caller adds to one row: the section's count and extra figure, // and its actions cluster as an ELEMENT (elements cross the boundary; the // functions that built them stay on the server). @@ -377,40 +339,3 @@ export const CHANNEL_COLUMNS: Record< }), }, }; - -// THE PRESETS. The rack draws everything; the dashboard and a work section -// each name the handful they have always drawn. -export const RACK_COLUMNS: readonly ChannelColumnId[] = [ - "select", - "slug", - "name", - "handling", - "build", - "tier", - "playlist", - "lastSync", - "report", - "location", - "size", - "pipelines", - "actions", -]; - -export const DASHBOARD_COLUMNS: readonly ChannelColumnId[] = [ - "slug", - "handling", - "videos", - "digestReachable", - "lastSyncRelative", - "actions", -]; - -// `extra` is dropped by the caller when the section has no extra column. -export const WORK_COLUMNS: readonly ChannelColumnId[] = [ - "slug", - "count", - "extra", - "report", - "lastSync", - "actions", -]; diff --git a/editor/app/channels/page.tsx b/editor/app/channels/page.tsx @@ -39,7 +39,7 @@ import { import { buildChannelBands } from "yt-dlp-transcript-common/views/pipeline/buildBands"; import { EXTERNAL_BAND_IDS } from "yt-dlp-transcript-common/views/pipeline/buildBands"; import { ChannelsRack } from "./components/ChannelsRack"; -import type { PipelineColumn } from "./components/channelColumns"; +import type { PipelineColumn } from "./components/channelColumnPresets"; import { buildChannelRowView, channelVolumeOf, diff --git a/editor/app/components/channelWork/ChannelWorkTable.tsx b/editor/app/components/channelWork/ChannelWorkTable.tsx @@ -9,10 +9,10 @@ import { } from "yt-dlp-transcript-common/views/channelRow"; import { InlineActionButton } from "../actions/InlineActionButton"; import { ChannelsTable } from "../../channels/components/ChannelsTable"; -import { - WORK_COLUMNS, - type ChannelRowExtras, -} from "../../channels/components/channelColumns"; +import type { ChannelRowExtras } from "../../channels/components/channelColumns"; +// From the plain-data module, never the "use client" registry: a server +// component importing a client module's value gets a reference, not the array. +import { WORK_COLUMNS } from "../../channels/components/channelColumnPresets"; import type { SectionConfig } from "./sections"; // A server component on purpose: `SectionConfig.primaryAction` is a function