@openrails/contentkit-ui 0.96.0 → 0.97.1
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/README.md +9 -1
- package/dist/client/discovery.d.ts +2 -1
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/entities.d.ts +6 -0
- package/dist/client/entities.js +13 -0
- package/dist/client/entities.js.map +1 -1
- package/dist/client/generated/routes.d.ts +26 -0
- package/dist/client/generated/routes.js +44 -0
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +7 -10
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/http.d.ts +1 -0
- package/dist/client/http.js +5 -4
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/reader-preferences.js +3 -7
- package/dist/client/reader-preferences.js.map +1 -1
- package/dist/components/admin/content-manager.d.ts +3 -1
- package/dist/components/admin/content-manager.js +241 -239
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/admin/group-manager.js +133 -119
- package/dist/components/admin/group-manager.js.map +1 -1
- package/dist/components/content/editors.d.ts +1 -0
- package/dist/components/content/editors.js +1 -0
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/filters.d.ts +1 -1
- package/dist/components/content/filters.js +1 -1
- package/dist/components/content/filters.js.map +1 -1
- package/dist/components/content/popular.js +37 -32
- package/dist/components/content/popular.js.map +1 -1
- package/dist/components/groups/banner.d.ts +3 -1
- package/dist/components/groups/banner.js +29 -26
- package/dist/components/groups/banner.js.map +1 -1
- package/dist/components/groups/editor.d.ts +4 -1
- package/dist/components/groups/editor.js +369 -315
- package/dist/components/groups/editor.js.map +1 -1
- package/dist/components/groups/memberships.d.ts +2 -0
- package/dist/components/groups/memberships.js +1 -0
- package/dist/components/groups/memberships.js.map +1 -1
- package/dist/components/groups/parts.d.ts +4 -1
- package/dist/components/groups/parts.js +32 -30
- package/dist/components/groups/parts.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/locales/en.d.ts +2 -0
- package/dist/locales/groups/de.js +2 -0
- package/dist/locales/groups/de.js.map +1 -1
- package/dist/locales/groups/en.d.ts +2 -0
- package/dist/locales/groups/en.js +2 -0
- package/dist/locales/groups/en.js.map +1 -1
- package/dist/locales/groups/es.js +2 -0
- package/dist/locales/groups/es.js.map +1 -1
- package/dist/locales/groups/ja.js +2 -0
- package/dist/locales/groups/ja.js.map +1 -1
- package/dist/locales/groups/ko.js +2 -0
- package/dist/locales/groups/ko.js.map +1 -1
- package/dist/locales/groups/zh.js +2 -0
- package/dist/locales/groups/zh.js.map +1 -1
- package/dist/react/discovery.d.ts +2 -1
- package/dist/react/discovery.js +54 -29
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/groups.d.ts +3 -1
- package/dist/react/groups.js +7 -7
- package/dist/react/groups.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wire.js","names":[],"sources":["../../../src/client/generated/wire.ts"],"sourcesContent":["// Generated by `go generate ./internal/contract` from ContentKit's route catalog. Do not edit.\n\nimport type { ErrorCode } from \"./error-codes.js\";\n\nexport type { ErrorCode };\n\n// Upload sizes: one PUT up to MAX_SINGLE_PUT bytes, else multipart parts.\nexport const MAX_SINGLE_PUT = 67108864;\nexport const MIN_PART_SIZE = 8388608;\nexport const MAX_PART_SIZE = 16777216;\n\nexport type OpName = \"put\" | \"edit\" | \"move\" | \"rename\" | \"remove\" | \"attach\" | \"copy\" | \"frame\" | \"meta\" | \"regenerate\";\nexport type Access = \"full\" | \"none\";\nexport type ItemState = \"ready\" | \"processing\" | \"failed\";\nexport type EncodePhase = \"queued\" | \"downloading\" | \"probing\" | \"encoding\" | \"muxing\" | \"uploading\" | \"publishing\" | \"images\";\nexport type PollKind = \"multiple_choice\" | \"free_text\";\nexport type ModerationState = \"approved\" | \"held\" | \"rejected\";\nexport type ContentState = \"draft\" | \"published\" | \"deleted\";\nexport type VersionState = \"draft\" | \"published\";\nexport type Listing = \"listed\" | \"members\" | \"unlisted\";\nexport type AliasStatus = \"found\" | \"not_found\" | \"gone\";\n\nexport interface Activity {\n days: ActivityDay[];\n}\n\nexport interface ActivityDay {\n date: string;\n views: number;\n viewers: number;\n users: number;\n}\n\nexport interface AdminComment {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n deleted_at?: string;\n}\n\nexport interface AliasKey {\n source: string;\n kind: string;\n key: string;\n}\n\nexport interface AliasLookup {\n aliases: AliasKey[];\n}\n\nexport interface AliasRecord {\n kind: string;\n key: string;\n locator?: string;\n target: TargetRef;\n}\n\nexport interface AliasResult {\n source: string;\n kind: string;\n key: string;\n status: AliasStatus;\n resolved?: Resolved;\n locator?: string;\n}\n\nexport interface AliasResults {\n aliases: AliasResult[];\n}\n\nexport interface Anchor {\n id: string;\n page: string;\n offset_percent: number;\n duration_seconds?: number;\n}\n\nexport interface Anonymous {\n comments: boolean;\n reactions: boolean;\n votes: boolean;\n}\n\nexport interface AnswerGroup {\n id: string;\n label: string;\n count: number;\n}\n\nexport interface AnswerRecord {\n poll: Ref;\n user_id: string;\n text: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface Archive {\n name: string;\n size: number;\n sha256: string;\n}\n\nexport interface Attribute {\n type: string;\n values?: string[];\n filterable?: boolean;\n sortable?: boolean;\n}\n\nexport interface Avatar {\n image?: string;\n renditions?: Rendition[];\n}\n\nexport interface BackgroundCue {\n file: string;\n from_page?: string;\n to_page?: string;\n from_anchor?: string;\n to_anchor?: string;\n loop?: boolean;\n layer?: string;\n}\n\nexport interface BanInput {\n reason?: string;\n until?: string;\n}\n\nexport interface BanNotice {\n scope: string;\n reason?: string;\n until?: string;\n}\n\nexport interface BannedWord {\n word: string;\n action: \"mask\" | \"reject\";\n created_by: string;\n created_at: string;\n}\n\nexport interface BannedWordInput {\n word: string;\n action?: \"mask\" | \"reject\";\n}\n\nexport interface Batch {\n source: string;\n preference_floor?: number;\n provision_scopes?: boolean;\n entities?: GroupRecord[];\n contents?: ContentRecord[];\n memberships?: MembershipSet[];\n offers?: OfferRecord[];\n aliases?: AliasRecord[];\n comments?: CommentRecord[];\n reactions?: ReactionRecord[];\n favorites?: FavoriteRecord[];\n polls?: PollRecord[];\n votes?: VoteRecord[];\n answers?: AnswerRecord[];\n signals?: SignalRecord[];\n deletes?: DeleteRecord[];\n}\n\nexport interface BodyImageInput {\n image?: string;\n version: string;\n}\n\nexport interface Card {\n id: string;\n kind: string;\n code: string;\n path: string;\n title: string;\n language: string;\n cover: PublicRendition[];\n version: CardVersion;\n entities: Record<string, Chip[]>;\n owner?: GroupCard;\n counts: Counts;\n access: CardAccess;\n viewer?: ViewerState;\n published_at?: string;\n attributes: Record<string, unknown>;\n}\n\nexport interface CardAccess {\n allowed: boolean;\n level: \"group\" | \"group_ppv\" | \"ppv\" | \"public\" | \"tier\";\n tiers?: string[];\n unknown?: boolean;\n sell?: string[];\n requires?: string;\n preview?: Preview;\n free_after?: string;\n offers?: Sale[];\n}\n\nexport interface CardVersion {\n id: string;\n code: string;\n languages: string[];\n traits: string[];\n label?: string;\n pages?: number;\n duration_ms?: number;\n has_audio: boolean;\n hls?: string;\n}\n\nexport interface CatalogCover {\n image?: string;\n url?: string;\n renditions?: PublicRendition[];\n}\n\nexport interface CatalogText {\n title: string;\n slug?: string;\n description?: string;\n body?: string;\n sort_key?: string;\n aliases?: string[];\n}\n\nexport interface Chip {\n id: string;\n slug: string;\n name: string;\n path?: string;\n}\n\nexport interface Comment {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CommentBan {\n user_id: string;\n user?: PublicUser;\n scope: string;\n reason?: string;\n until?: string;\n banned_by: string;\n banned_at: string;\n expired: boolean;\n}\n\nexport interface CommentEdit {\n body: string;\n}\n\nexport interface CommentInput {\n body: string;\n reply_to_id?: string;\n anon_name?: string;\n language?: string;\n}\n\nexport interface CommentRecord {\n external_id: string;\n id?: string;\n target: TargetRef;\n language?: string;\n reply_to?: Ref;\n user_id?: string;\n anon_name?: string;\n body: string;\n deleted_at?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface CommentStanding {\n can_comment: boolean;\n comments: string;\n locked: boolean;\n ban?: BanNotice;\n anonymous: boolean;\n max_length: number;\n user_id?: string;\n moderate: boolean;\n ban_scopes: (\"global\" | \"owner\")[];\n}\n\nexport interface CommitBody {\n ref: RefBody;\n operation_id: string;\n ops: Op[];\n}\n\nexport interface CommitReply {\n files: FileInfo[];\n}\n\nexport interface CompleteReply {\n blob: string;\n type: string;\n size: number;\n}\n\nexport type CompleteRequest = Record<string, never>;\n\nexport interface Config {\n anonymous: Anonymous;\n comment_max_length: number;\n}\n\nexport interface Content {\n id: string;\n kind: string;\n code: string;\n path: string;\n language: string;\n title: string;\n slug?: string;\n description?: string;\n body?: string;\n decision: Decision;\n images?: Record<string, string>;\n cover?: CatalogCover;\n state: ContentState;\n listing: Listing;\n comments: string;\n publish_at?: string;\n published_at?: string;\n live: boolean;\n access: Rule;\n restrictions: string[];\n attributes: Record<string, unknown>;\n owner_group_id?: string;\n owner?: GroupCard;\n creators: Creator[];\n entities: GroupSummary[];\n versions: Version[];\n views?: number;\n viewer?: ViewerState;\n editor: boolean;\n text?: Record<string, CatalogText>;\n moderation?: ModerationState;\n moderation_reason?: string;\n ever_sold?: boolean;\n offer?: Offer;\n revision: number;\n created_at: string;\n updated_at: string;\n deleted_at?: string;\n}\n\nexport interface ContentFilter {\n entity: GroupRef;\n default_visible: boolean;\n}\n\nexport interface ContentFilterState {\n entity: GroupCard;\n label: string;\n default_visible: boolean;\n visible: boolean;\n overridden: boolean;\n}\n\nexport interface ContentFilters {\n filters: ContentFilterState[];\n include_deleted: boolean;\n}\n\nexport interface ContentFiltersInitialization {\n account_id: string;\n filters: FilterSetting[];\n include_deleted: boolean;\n}\n\nexport interface ContentFiltersUpdate {\n filters: FilterSetting[];\n include_deleted: boolean;\n}\n\nexport interface ContentGroups {\n kinds?: string[];\n memberships: Membership[];\n}\n\nexport interface ContentInput {\n kind: string;\n text?: Record<string, CatalogText>;\n listing?: Listing;\n comments?: string;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n owner_group_id?: string;\n creators?: Creator[];\n versions?: VersionInput[];\n}\n\nexport interface ContentMemberships {\n content_id: string;\n memberships: Membership[];\n entities: GroupCard[];\n}\n\nexport interface ContentModel {\n languages: string[];\n tiers: string[];\n kinds: Record<string, Kind>;\n entity_kinds: Record<string, GroupKind>;\n content_filters: ContentFilter[];\n signals: boolean;\n avatars?: PresetRule;\n}\n\nexport interface ContentPage {\n contents: Card[];\n next_cursor?: string;\n}\n\nexport interface ContentPatch {\n listing?: Listing;\n comments?: string;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n creators?: Creator[];\n revision?: number;\n}\n\nexport interface ContentRecord {\n external_id: string;\n id?: string;\n kind: string;\n state: string;\n publish_at?: string;\n published_at?: string;\n deleted_at?: string;\n listing?: string;\n comments?: string;\n view_baseline?: number;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n owner_group?: Ref;\n creators?: Creator[];\n text?: Record<string, CatalogText>;\n versions?: VersionRecord[];\n code?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface ContentRef {\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n}\n\nexport interface CopyBody {\n ref: RefBody;\n files: CopyRequest[];\n}\n\nexport interface CopyFrom {\n id: string;\n version?: string;\n path: string;\n}\n\nexport interface CopyReply {\n files: StagedCopy[];\n}\n\nexport interface CopyRequest {\n path: string;\n type: string;\n from: string;\n size?: number;\n}\n\nexport interface Count {\n content_kind: string;\n language: string;\n count: number;\n}\n\nexport interface Counts {\n likes?: number;\n dislikes?: number;\n favorites?: number;\n views?: number;\n}\n\nexport interface Creator {\n user_id: string;\n role?: string;\n position: number;\n}\n\nexport interface CreatorsInput {\n creators: Creator[];\n}\n\nexport interface Crop {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface DailyReleases {\n time_zone: string;\n from_date: string;\n through_date: string;\n days: ReleaseDay[];\n}\n\nexport interface DateCount {\n date: string;\n count: number;\n free: number;\n}\n\nexport interface Decision {\n allowed: boolean;\n unknown?: boolean;\n sell?: string[];\n requires?: string;\n preview?: Preview;\n free_after?: string;\n offers?: Sale[];\n}\n\nexport interface DeleteRecord {\n entity: string;\n external_id: string;\n}\n\nexport interface Download {\n off?: boolean;\n serve?: string;\n}\n\nexport interface Edge {\n from: string;\n relation: string;\n to: string;\n}\n\nexport interface EdgeInput {\n relation: string;\n to: string;\n}\n\nexport interface EdgeRecord {\n relation: string;\n to: Ref;\n}\n\nexport interface Edit {\n crop?: Crop;\n rotate?: number;\n}\n\nexport interface EncodeProgress {\n phase: EncodePhase;\n queue_position?: number;\n segments_done?: number;\n segments_total?: number;\n percent: number;\n speed?: number;\n eta?: number;\n at: number;\n stalled?: boolean;\n stage?: number;\n stages?: number;\n}\n\nexport interface EntityReference {\n id?: string;\n kind?: string;\n name?: string;\n language?: string;\n scope?: EntityReference;\n}\n\nexport interface EntityResolution {\n id: string;\n kind: string;\n name: string;\n created: boolean;\n scope?: EntityResolution;\n}\n\nexport interface ErrorDetails {\n width?: number;\n height?: number;\n min_width?: number;\n max_pixels?: number;\n type?: string;\n allowed?: string[];\n size?: number;\n max_bytes?: number;\n frames?: number;\n max_frames?: number;\n seconds?: number;\n max_seconds?: number;\n min_aspect?: number;\n max_aspect?: number;\n max?: number;\n}\n\nexport interface ErrorReply {\n error: string;\n code: ErrorCode;\n retry_after?: number;\n action?: \"comment\" | \"comment_reaction\" | \"favorite\" | \"poll_vote\" | \"reaction\";\n ban?: BanNotice;\n blobs?: string[];\n details?: ErrorDetails;\n reason?: string;\n available_at?: string;\n}\n\nexport interface ExposureInput {\n render_id: string;\n stage: string;\n revision?: number;\n query_id?: string;\n surface?: string;\n ranker?: string;\n language?: string;\n occurred_at?: string;\n shown: Placement[];\n}\n\nexport interface Exposures {\n session?: string;\n exposures: ExposureInput[];\n}\n\nexport interface ExternalID {\n external_id: string;\n id: string;\n deleted: boolean;\n}\n\nexport interface ExternalIDList {\n entity: string;\n cursor?: string;\n limit?: number;\n}\n\nexport interface ExternalIDPage {\n entity: string;\n ids: ExternalID[];\n next_cursor?: string;\n}\n\nexport interface ExternalIDs {\n lists: ExternalIDPage[];\n}\n\nexport interface ExternalIDsQuery {\n source: string;\n lists: ExternalIDList[];\n}\n\nexport interface Failure {\n of: string;\n message: string;\n code?: ErrorCode;\n details?: ErrorDetails;\n}\n\nexport interface FavoriteRecord {\n target: TargetRef;\n user_id: string;\n created_at?: string;\n}\n\nexport interface FavoriteState {\n favorited: boolean;\n count?: number;\n}\n\nexport interface FeedItem {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n}\n\nexport interface FileDownload {\n url: string;\n name: string;\n type: string;\n size?: number;\n expires_at: string;\n}\n\nexport interface FileInfo {\n path: string;\n type: string;\n size?: number;\n w?: number;\n h?: number;\n dur?: number;\n download?: string;\n url?: string;\n upload?: boolean;\n staged?: boolean;\n from?: string;\n edit?: Edit;\n frame?: Frame;\n meta?: Record<string, unknown>;\n unattached?: boolean;\n pending?: string[];\n failed?: Failure;\n editor_url?: string;\n progress?: EncodeProgress;\n}\n\nexport interface FilterSetting {\n group_id: string;\n visible: boolean;\n}\n\nexport interface ForegroundCue {\n file: string;\n page?: string;\n anchor?: string;\n}\n\nexport interface ForkBody {\n from: string;\n playback?: boolean;\n segments?: boolean;\n}\n\nexport interface Frame {\n t?: number;\n auto?: boolean;\n of?: string;\n}\n\nexport interface Group {\n id: string;\n kind: string;\n slug: string;\n scope_id?: string;\n parent_id?: string;\n state: \"active\" | \"deleted\" | \"merged\";\n merged_into?: string;\n attributes: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n created_at: string;\n updated_at: string;\n revision: number;\n}\n\nexport interface GroupAccess {\n key: string;\n offer?: Sale;\n member: boolean;\n editor?: boolean;\n unknown?: boolean;\n}\n\nexport interface GroupCard {\n id: string;\n kind: string;\n slug: string;\n scope_id?: string;\n parent_id?: string;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n cover?: GroupsCover;\n avatar?: Avatar;\n count: number;\n attributes: Record<string, unknown>;\n access?: GroupAccess;\n created_at: string;\n}\n\nexport interface GroupDetail {\n id: string;\n kind: string;\n slug: string;\n scope_id?: string;\n parent_id?: string;\n state: \"active\" | \"deleted\" | \"merged\";\n merged_into?: string;\n attributes: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n created_at: string;\n updated_at: string;\n revision: number;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n names: Name[];\n text: GroupsText[];\n parent?: GroupCard;\n scope?: GroupCard;\n children: GroupCard[];\n edges: Edge[];\n counts: Count[];\n access?: GroupAccess;\n offer?: Offer;\n}\n\nexport interface GroupInput {\n id?: string;\n kind: string;\n slug: string;\n scope_id?: string;\n parent_id?: string;\n attributes?: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n names?: Name[];\n text?: GroupsText[];\n}\n\nexport interface GroupJoin {\n group_id: string;\n key: string;\n member: boolean;\n}\n\nexport interface GroupKind {\n route?: string;\n ordered?: boolean;\n parent?: string;\n scoped_by?: string;\n owner?: string;\n max_per_owner?: number;\n uploads?: UploadLimits;\n sellable?: boolean;\n auth_scope?: boolean;\n windows?: boolean;\n version_level?: boolean;\n roles?: string[];\n attributes?: Record<string, Attribute>;\n}\n\nexport interface GroupPage {\n entities: GroupCard[];\n next_cursor?: string;\n}\n\nexport interface GroupRecord {\n external_id: string;\n id?: string;\n kind: string;\n slug: string;\n scope?: Ref;\n parent?: Ref;\n state?: string;\n names?: Name[];\n text?: GroupsText[];\n attributes?: Record<string, unknown>;\n cover_image?: string;\n cover_content?: Ref;\n avatar?: string;\n owner_user_id?: string;\n auth_scope?: string;\n edges?: EdgeRecord[];\n code?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface GroupRef {\n kind: string;\n slug: string;\n}\n\nexport interface GroupSummary {\n id: string;\n kind: string;\n slug: string;\n name: string;\n code?: string;\n path?: string;\n}\n\nexport interface GroupUpdate {\n slug?: string;\n scope_id?: string;\n parent_id?: string;\n state?: \"active\" | \"deleted\" | \"merged\";\n attributes?: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n names?: Name[];\n text?: GroupsText[];\n}\n\nexport interface GroupsCover {\n image?: string;\n content_id?: string;\n auto?: boolean;\n renditions?: Rendition[];\n}\n\nexport interface GroupsText {\n language: string;\n description?: string;\n sort_key?: string;\n}\n\nexport interface HeldItem {\n kind: string;\n revision: number;\n id: string;\n ref: ContentRef;\n author_id?: string;\n author?: PublicUser;\n anon_name?: string;\n title?: string;\n body: string;\n reason: string;\n model?: string;\n prompt_version?: string;\n confidence?: number;\n error?: string;\n held_at: string;\n created_at: string;\n}\n\nexport interface HeldPage {\n items: HeldItem[];\n next?: string;\n}\n\nexport interface IPBan {\n network: string;\n reason?: string;\n until?: string;\n banned_by: string;\n banned_at: string;\n expired: boolean;\n}\n\nexport interface IPBanInput {\n network: string;\n reason?: string;\n until?: string;\n}\n\nexport interface ImageInput {\n image?: string;\n}\n\nexport interface InlineImage {\n ref: string;\n url: string | null;\n}\n\nexport interface Input {\n recipient: Recipient;\n origin: Origin;\n kind: string;\n data: unknown;\n created_at: string;\n visibility?: string;\n app_id?: string;\n status?: string;\n action_requested?: boolean;\n severity?: string;\n}\n\nexport interface Interaction {\n content?: Card;\n entity?: GroupCard;\n value: number;\n at: string;\n}\n\nexport interface InteractionPage {\n items: Interaction[];\n next_cursor?: string;\n}\n\nexport interface Item {\n id: string;\n recipient: Recipient;\n origin: Origin;\n kind: string;\n data: unknown;\n created_at: string;\n visibility?: string;\n app_id?: string;\n status?: string;\n action_requested?: boolean;\n severity?: string;\n read_at: string | null;\n dismissed_at: string | null;\n resolved_at: string | null;\n updated_at: string;\n revision: number;\n}\n\nexport interface Kind {\n route: string;\n presentation: string;\n versions: VersionRules;\n segments?: boolean;\n entities?: string[];\n attributes?: Record<string, Attribute>;\n sort?: string;\n locked?: Locked;\n draft_ttl?: number;\n download?: Download;\n}\n\nexport interface LanguageTotal {\n public: number;\n tiers: Record<string, number>;\n}\n\nexport interface LibraryItem {\n content_id: string;\n kind: string;\n title: string;\n language?: string;\n deleted: boolean;\n whole: boolean;\n version_ids: string[];\n}\n\nexport interface LibraryPage {\n items: LibraryItem[];\n next_cursor?: string;\n complete: boolean;\n}\n\nexport interface Locked {\n show: string[];\n preview?: Preview;\n}\n\nexport interface MemberPage {\n members: Membership[];\n next_cursor?: string;\n}\n\nexport interface MemberRef {\n content_id: string;\n version_id?: string;\n}\n\nexport interface Membership {\n group_id?: string;\n content_id?: string;\n version_id?: string;\n role?: string;\n position?: number;\n active_from?: string;\n active_until?: string;\n state?: \"active\" | \"proposed\";\n}\n\nexport interface MembershipRecord {\n group: Ref;\n version?: Ref;\n role?: string;\n position?: number;\n active_from?: string;\n active_until?: string;\n state?: string;\n}\n\nexport interface MembershipSet {\n content: Ref;\n kinds: string[];\n memberships: MembershipRecord[];\n}\n\nexport interface MergeInput {\n into: string;\n}\n\nexport interface MergeReport {\n from: string;\n into: string;\n memberships_moved: number;\n names_moved: number;\n edges_moved: number;\n groups_moved: number;\n}\n\nexport interface MultipartReply {\n ticket: string;\n min_part_size: number;\n max_part_size: number;\n max_parts: number;\n}\n\nexport interface MyGroup {\n id: string;\n kind: string;\n slug: string;\n scope_id?: string;\n parent_id?: string;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n cover?: GroupsCover;\n avatar?: Avatar;\n count: number;\n attributes: Record<string, unknown>;\n access?: GroupAccess;\n created_at: string;\n owner: boolean;\n editor: boolean;\n writer: boolean;\n moderator: boolean;\n member: boolean;\n}\n\nexport interface MyGroupPage {\n entities: MyGroup[];\n next_cursor?: string;\n}\n\nexport interface MyStats {\n completed: Record<string, number>;\n access_seconds?: Record<string, number>;\n comments: number;\n comment_likes: number;\n comment_dislikes: number;\n}\n\nexport interface Name {\n language: string;\n kind: \"alias\" | \"name\";\n name: string;\n}\n\nexport interface Offer {\n id: string;\n target: Target;\n key: string;\n terms: Terms;\n state: \"active\" | \"withdrawn\";\n synced: boolean;\n product_id?: string;\n price_id?: string;\n last_error?: string;\n revision: number;\n updated_at: string;\n}\n\nexport interface OfferPage {\n offers: Offer[];\n next_cursor?: string;\n}\n\nexport interface OfferRecord {\n target: TargetRef;\n terms: Terms;\n}\n\nexport interface Op {\n op: OpName;\n path?: string;\n blob?: string;\n create_id?: string;\n index?: number;\n meta?: Record<string, unknown>;\n edit?: Edit;\n unattached?: boolean;\n to?: string;\n from?: CopyFrom;\n t?: number;\n auto?: boolean;\n preset?: string;\n force?: boolean;\n takedown?: boolean;\n}\n\nexport interface Operation {\n id: string;\n state: \"awaiting_upload\" | \"blocked\" | \"failed\" | \"processing\" | \"published\" | \"publishing\" | \"ready\" | \"review_required\" | \"scheduled\";\n content_id: string;\n version_id: string;\n publish_at?: string;\n entities: EntityResolution[];\n progress: Progress;\n result?: OperationResult;\n error?: OperationError;\n upload?: PresignReply;\n created_at: string;\n updated_at: string;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n retryable: boolean;\n field?: string;\n}\n\nexport interface OperationResult {\n path: string;\n pages: number;\n}\n\nexport interface Order {\n members: MemberRef[];\n}\n\nexport interface OrderInput {\n ids: string[];\n}\n\nexport interface Origin {\n system: string;\n scope: string;\n id: string;\n subject?: string;\n}\n\nexport interface Page {\n items: Item[];\n next_cursor?: string;\n}\n\nexport interface PartBody {\n number: number;\n size: number;\n sha256: string;\n}\n\nexport interface PartReply {\n number: number;\n size?: number;\n sha256?: string;\n request?: RequestReply;\n}\n\nexport interface PartsBody {\n ticket: string;\n parts: PartBody[];\n}\n\nexport interface PartsReply {\n parts: PartReply[];\n}\n\nexport interface Pending {\n status: string;\n}\n\nexport interface Placement {\n content_id: string;\n position: number;\n}\n\nexport interface PlanPage {\n name: string;\n w: number;\n h: number;\n files: Record<string, string>;\n}\n\nexport interface PlanPlayback {\n item: RefBody;\n tracks: PlanTrack[];\n}\n\nexport interface PlanPreview {\n index: number;\n name: string;\n url: string;\n w: number;\n h: number;\n}\n\nexport interface PlanSegment {\n position?: number;\n title?: string;\n start: number;\n end: number;\n released: boolean;\n release_at?: string;\n locked: boolean;\n item?: RefBody;\n pages?: PlanPage[];\n}\n\nexport interface PlanTrack {\n name: string;\n path: string;\n duration?: number;\n}\n\nexport interface Poll {\n id: string;\n kind: PollKind;\n question: string;\n language: string;\n is_active: boolean;\n image_url?: string;\n live_at: string;\n closes_at?: string;\n closed: boolean;\n total_votes: number;\n options: PollOption[];\n voted: boolean;\n my_option?: string;\n answer_count?: number;\n groups?: AnswerGroup[];\n my_answer?: PollAnswer;\n}\n\nexport interface PollAnswer {\n id: string;\n text: string;\n classified: boolean;\n updated_at: string;\n}\n\nexport interface PollAnswerInput {\n text: string;\n}\n\nexport interface PollImage {\n image_url: string | null;\n}\n\nexport interface PollInput {\n kind?: PollKind;\n question: string;\n language: string;\n live_at?: string;\n closes_at?: string;\n options?: PollOptionInput[];\n}\n\nexport interface PollOption {\n id: string;\n label: string;\n image_url?: string;\n position: number;\n vote_count: number;\n}\n\nexport interface PollOptionInput {\n label: string;\n position: number;\n}\n\nexport interface PollOptionPatch {\n label?: string;\n position?: number;\n}\n\nexport interface PollOptionRecord {\n external_id: string;\n id?: string;\n label: string;\n position: number;\n}\n\nexport interface PollRecord {\n external_id: string;\n id?: string;\n kind?: string;\n question: string;\n language?: string;\n active?: boolean;\n live_at?: string;\n closes_at?: string;\n deleted_at?: string;\n created_at?: string;\n updated_at?: string;\n options?: PollOptionRecord[];\n}\n\nexport interface PollUpdate {\n question?: string;\n is_active?: boolean;\n live_at?: string;\n closes_at?: string | null;\n}\n\nexport interface PollVote {\n option_id: string;\n}\n\nexport interface PresetRule {\n kind: string;\n name: string;\n from: string;\n base: string;\n namespace: string;\n root?: string;\n to: string;\n widths: number[];\n aspect?: string;\n min_width?: number;\n first?: number;\n default: boolean;\n stable?: boolean;\n}\n\nexport interface PresignBody {\n ref: RefBody;\n path: string;\n type: string;\n size: number;\n sha256: string;\n}\n\nexport interface PresignReply {\n path: string;\n blob: string;\n exists?: boolean;\n put?: RequestReply;\n multipart?: MultipartReply;\n process_on_upload?: boolean;\n}\n\nexport interface Preview {\n pages?: number;\n segments?: number;\n}\n\nexport interface Progress {\n stage: string;\n completed: number;\n total: number;\n}\n\nexport interface PublicImage {\n from: string;\n preset: string;\n renditions: PublicRendition[];\n}\n\nexport interface PublicRendition {\n url: string;\n w: number;\n h: number;\n}\n\nexport interface PublicUser {\n id: string;\n name?: string;\n username: string;\n avatar?: string;\n avatar_srcset?: string;\n}\n\nexport interface Publication {\n notifications: Input[];\n}\n\nexport interface PublishInput {\n publish_at?: string;\n}\n\nexport interface Published {\n items: Item[];\n}\n\nexport interface RankedContent {\n id: string;\n title: string;\n path?: string;\n value: number;\n}\n\nexport interface ReactionCounts {\n likes?: number;\n dislikes?: number;\n mine: number;\n}\n\nexport interface ReactionRecord {\n target: TargetRef;\n user_id?: string;\n ip?: string;\n value: number;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface ReadResult {\n access: Access;\n expires: number;\n meta?: Record<string, unknown>;\n previews?: string[];\n public?: PublicImage[];\n locked?: boolean;\n total: number;\n offset: number;\n limit: number;\n hls?: string[];\n state?: ItemState;\n full?: boolean;\n uploads?: UploadRule[];\n files: FileInfo[];\n}\n\nexport interface ReaderDefaults {\n auto_advance_seconds?: number;\n}\n\nexport interface ReaderMeta {\n schema_version: number;\n defaults?: ReaderDefaults;\n anchors?: Anchor[];\n background?: BackgroundCue[];\n foreground?: ForegroundCue[];\n}\n\nexport interface ReaderPlan {\n content_id: string;\n version_id: string;\n publication_id: string;\n pages?: number;\n segments: PlanSegment[];\n previews: PlanPreview[];\n playback?: PlanPlayback;\n reader?: ReaderMeta;\n}\n\nexport interface RecentSearch {\n query: string;\n results: number;\n searched_at: string;\n}\n\nexport interface RecentSearches {\n searches: RecentSearch[];\n}\n\nexport interface Recipient {\n audience: string;\n id: string;\n}\n\nexport interface RecordFailure {\n section: string;\n index: number;\n external_id?: string;\n code: string;\n error: string;\n}\n\nexport interface Ref {\n id?: string;\n external_id?: string;\n}\n\nexport interface RefBody {\n kind: string;\n id: string;\n version?: string;\n}\n\nexport interface ReleaseDates {\n dates: DateCount[];\n next_cursor?: string;\n}\n\nexport interface ReleaseDay {\n date: string;\n contents: Card[];\n}\n\nexport interface Rendition {\n url: string;\n w: number;\n h: number;\n}\n\nexport interface Request {\n content: ContentInput;\n entities?: EntityReference[];\n archive: Archive;\n publish?: \"draft\" | \"when_ready\";\n publish_at?: string;\n create_missing_entities?: boolean;\n source?: Source;\n}\n\nexport interface RequestReply {\n method: string;\n url: string;\n headers: Record<string, string>;\n expires: string;\n}\n\nexport interface ResolveInput {\n decision: \"approve\" | \"reject\" | \"review\";\n revision: number;\n reason?: string;\n}\n\nexport interface Resolved {\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n code: string;\n slug: string;\n slugs?: Record<string, string>;\n path: string;\n version_id?: string;\n}\n\nexport interface Restored {\n restored: boolean;\n}\n\nexport interface Result {\n written: Record<string, number>;\n skipped?: Record<string, number>;\n failed: RecordFailure[];\n ids: Record<string, Record<string, string>>;\n}\n\nexport interface ReviewOutcome {\n decision: \"approve\" | \"reject\" | \"review\";\n}\n\nexport interface Rule {\n level: \"group\" | \"group_ppv\" | \"ppv\" | \"public\" | \"tier\";\n tiers?: string[];\n group_id?: string;\n preview?: Preview;\n free_after?: string;\n}\n\nexport interface Sale {\n key: string;\n target: Target;\n terms: Terms;\n price_id?: string;\n}\n\nexport interface Segment {\n position: number;\n title?: string;\n start: number;\n end: number;\n release_at?: string;\n released: boolean;\n}\n\nexport interface SegmentsInput {\n segments: Segment[];\n}\n\nexport interface SignalInput {\n content_id: string;\n version_id?: string;\n type: string;\n event_id: string;\n revision?: number;\n occurred_at: string;\n duration_s?: number;\n progress?: number;\n resume?: string;\n render_id?: string;\n surface?: string;\n position?: number;\n}\n\nexport interface SignalRecord {\n target: TargetRef;\n user_id?: string;\n anon_key?: string;\n type: string;\n event_id: string;\n revision?: number;\n occurred_at: string;\n duration_s?: number;\n progress?: number;\n resume?: string;\n}\n\nexport interface Signals {\n session?: string;\n signals: SignalInput[];\n}\n\nexport interface SitemapAlias {\n language: string;\n path: string;\n image?: string;\n}\n\nexport interface SitemapEntry {\n id: string;\n code: string;\n path: string;\n lastmod: string;\n languages: SitemapAlias[];\n}\n\nexport interface SitemapPage {\n entries: SitemapEntry[];\n next_cursor?: string;\n}\n\nexport interface Source {\n provider: string;\n id: string;\n url?: string;\n}\n\nexport interface StagedCopy {\n path: string;\n blob: string;\n size: number;\n}\n\nexport interface Target {\n kind: \"content\" | \"group\" | \"version\";\n id: string;\n content_id?: string;\n}\n\nexport interface TargetRef {\n content?: Ref;\n version?: Ref;\n group?: Ref;\n comment?: Ref;\n}\n\nexport interface Terms {\n amount: string;\n currency: string;\n access_hours?: number;\n renew_hours?: number;\n}\n\nexport interface TicketBody {\n ticket: string;\n}\n\nexport interface TopContents {\n contents: RankedContent[];\n}\n\nexport interface Total {\n public: number;\n tiers: Record<string, number>;\n languages: Record<string, LanguageTotal>;\n}\n\nexport interface Totals {\n kinds: Record<string, Total>;\n}\n\nexport interface Typeahead {\n contents: Card[];\n entities: GroupCard[];\n}\n\nexport interface UploadLimits {\n files_per_hour?: number;\n bytes_per_day?: number;\n quota_bytes?: number;\n}\n\nexport interface UploadRule {\n path: string;\n types: string[];\n max_bytes: number;\n max?: number;\n named?: boolean;\n body?: boolean;\n frames?: string;\n aspect?: string;\n min_width?: number;\n video?: VideoLimits;\n min_aspect?: number;\n max_aspect?: number;\n}\n\nexport interface Version {\n id: string;\n code: string;\n position: number;\n languages: string[];\n traits: string[];\n label?: string;\n title?: string;\n description?: string;\n state?: ContentState;\n publish_at?: string;\n published_at?: string;\n live: boolean;\n access?: Rule;\n attributes: Record<string, unknown>;\n pages?: number;\n duration_ms?: number;\n width?: number;\n height?: number;\n has_audio: boolean;\n ordinal?: number;\n cover?: CatalogCover;\n segments: Segment[];\n decision: Decision;\n text?: Record<string, VersionText>;\n offer?: Offer;\n viewer?: ViewerState;\n}\n\nexport interface VersionFork {\n from: string;\n playback?: boolean;\n segments?: boolean;\n}\n\nexport interface VersionInput {\n languages?: string[];\n traits?: string[];\n label?: string;\n state?: VersionState;\n publish_at?: string;\n access?: Rule;\n clear_access?: boolean;\n attributes?: Record<string, unknown>;\n text?: Record<string, VersionText>;\n segments?: Segment[];\n ordinal?: number;\n cover?: string;\n fork?: VersionFork;\n}\n\nexport interface VersionRecord {\n external_id: string;\n id?: string;\n code?: string;\n languages: string[];\n traits?: string[];\n label?: string;\n state?: string;\n publish_at?: string;\n published_at?: string;\n deleted_at?: string;\n access?: Rule;\n attributes?: Record<string, unknown>;\n ordinal?: number;\n cover?: string;\n text?: Record<string, VersionText>;\n segments?: Segment[];\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface VersionRules {\n languages: string;\n traits?: string[];\n hidden?: boolean;\n}\n\nexport interface VersionText {\n title?: string;\n description?: string;\n}\n\nexport interface VideoLimits {\n max_seconds?: number;\n max_fps?: number;\n max_pixels?: number;\n max_work?: number;\n}\n\nexport interface ViewerState {\n favorited: boolean;\n seen: boolean;\n completed: boolean;\n progress: number;\n progress_max: number;\n resume?: string;\n last_view_at?: string;\n}\n\nexport interface VoteRecord {\n poll: Ref;\n option: Ref;\n user_id?: string;\n ip?: string;\n created_at?: string;\n}\n\nexport interface Written {\n count: number;\n}\n"],"mappings":";AAOA,IAAa,IAAiB,UACjB,IAAgB,SAChB,IAAgB"}
|
|
1
|
+
{"version":3,"file":"wire.js","names":[],"sources":["../../../src/client/generated/wire.ts"],"sourcesContent":["// Generated by `go generate ./internal/contract` from ContentKit's route catalog. Do not edit.\n\nimport type { ErrorCode } from \"./error-codes.js\";\n\nexport type { ErrorCode };\n\n// Upload sizes: one PUT up to MAX_SINGLE_PUT bytes, else multipart parts.\nexport const MAX_SINGLE_PUT = 67108864;\nexport const MIN_PART_SIZE = 8388608;\nexport const MAX_PART_SIZE = 16777216;\n\nexport type OpName = \"put\" | \"edit\" | \"move\" | \"rename\" | \"remove\" | \"attach\" | \"copy\" | \"frame\" | \"meta\" | \"regenerate\";\nexport type Access = \"full\" | \"none\";\nexport type ItemState = \"ready\" | \"processing\" | \"failed\";\nexport type EncodePhase = \"queued\" | \"downloading\" | \"probing\" | \"encoding\" | \"muxing\" | \"uploading\" | \"publishing\" | \"images\";\nexport type PollKind = \"multiple_choice\" | \"free_text\";\nexport type ModerationState = \"approved\" | \"held\" | \"rejected\";\nexport type ContentState = \"draft\" | \"published\" | \"deleted\";\nexport type VersionState = \"draft\" | \"published\";\nexport type Listing = \"listed\" | \"members\" | \"unlisted\";\nexport type AliasStatus = \"found\" | \"not_found\" | \"gone\";\n\nexport interface Activity {\n days: ActivityDay[];\n}\n\nexport interface ActivityDay {\n date: string;\n views: number;\n viewers: number;\n users: number;\n}\n\nexport interface AdminComment {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n deleted_at?: string;\n}\n\nexport interface AliasKey {\n source: string;\n kind: string;\n key: string;\n}\n\nexport interface AliasLookup {\n aliases: AliasKey[];\n}\n\nexport interface AliasRecord {\n kind: string;\n key: string;\n locator?: string;\n target: TargetRef;\n}\n\nexport interface AliasResult {\n source: string;\n kind: string;\n key: string;\n status: AliasStatus;\n resolved?: Resolved;\n locator?: string;\n}\n\nexport interface AliasResults {\n aliases: AliasResult[];\n}\n\nexport interface Anchor {\n id: string;\n page: string;\n offset_percent: number;\n duration_seconds?: number;\n}\n\nexport interface Anonymous {\n comments: boolean;\n reactions: boolean;\n votes: boolean;\n}\n\nexport interface AnswerGroup {\n id: string;\n label: string;\n count: number;\n}\n\nexport interface AnswerRecord {\n poll: Ref;\n user_id: string;\n text: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface Archive {\n name: string;\n size: number;\n sha256: string;\n}\n\nexport interface Attribute {\n type: string;\n values?: string[];\n filterable?: boolean;\n sortable?: boolean;\n}\n\nexport interface Avatar {\n image?: string;\n renditions?: Rendition[];\n}\n\nexport interface BackgroundCue {\n file: string;\n from_page?: string;\n to_page?: string;\n from_anchor?: string;\n to_anchor?: string;\n loop?: boolean;\n layer?: string;\n}\n\nexport interface BanInput {\n reason?: string;\n until?: string;\n}\n\nexport interface BanNotice {\n scope: string;\n reason?: string;\n until?: string;\n}\n\nexport interface BannedWord {\n word: string;\n action: \"mask\" | \"reject\";\n created_by: string;\n created_at: string;\n}\n\nexport interface BannedWordInput {\n word: string;\n action?: \"mask\" | \"reject\";\n}\n\nexport interface Batch {\n source: string;\n preference_floor?: number;\n provision_scopes?: boolean;\n entities?: GroupRecord[];\n contents?: ContentRecord[];\n memberships?: MembershipSet[];\n offers?: OfferRecord[];\n aliases?: AliasRecord[];\n comments?: CommentRecord[];\n reactions?: ReactionRecord[];\n favorites?: FavoriteRecord[];\n polls?: PollRecord[];\n votes?: VoteRecord[];\n answers?: AnswerRecord[];\n signals?: SignalRecord[];\n deletes?: DeleteRecord[];\n}\n\nexport interface BodyImageInput {\n image?: string;\n version: string;\n}\n\nexport interface Card {\n id: string;\n kind: string;\n code: string;\n path: string;\n title: string;\n language: string;\n cover: PublicRendition[];\n version: CardVersion;\n entities: Record<string, Chip[]>;\n owner?: GroupCard;\n counts: Counts;\n access: CardAccess;\n viewer?: ViewerState;\n published_at?: string;\n attributes: Record<string, unknown>;\n}\n\nexport interface CardAccess {\n allowed: boolean;\n level: \"group\" | \"group_ppv\" | \"ppv\" | \"public\" | \"tier\";\n tiers?: string[];\n unknown?: boolean;\n sell?: string[];\n requires?: string;\n preview?: Preview;\n free_after?: string;\n offers?: Sale[];\n}\n\nexport interface CardVersion {\n id: string;\n code: string;\n languages: string[];\n traits: string[];\n label?: string;\n pages?: number;\n duration_ms?: number;\n has_audio: boolean;\n hls?: string;\n}\n\nexport interface CatalogCover {\n image?: string;\n url?: string;\n renditions?: PublicRendition[];\n}\n\nexport interface CatalogText {\n title: string;\n slug?: string;\n description?: string;\n body?: string;\n sort_key?: string;\n aliases?: string[];\n}\n\nexport interface Chip {\n id: string;\n slug: string;\n name: string;\n path?: string;\n}\n\nexport interface Comment {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CommentBan {\n user_id: string;\n user?: PublicUser;\n scope: string;\n reason?: string;\n until?: string;\n banned_by: string;\n banned_at: string;\n expired: boolean;\n}\n\nexport interface CommentEdit {\n body: string;\n}\n\nexport interface CommentInput {\n body: string;\n reply_to_id?: string;\n anon_name?: string;\n language?: string;\n}\n\nexport interface CommentRecord {\n external_id: string;\n id?: string;\n target: TargetRef;\n language?: string;\n reply_to?: Ref;\n user_id?: string;\n anon_name?: string;\n body: string;\n deleted_at?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface CommentStanding {\n can_comment: boolean;\n comments: string;\n locked: boolean;\n ban?: BanNotice;\n anonymous: boolean;\n max_length: number;\n user_id?: string;\n moderate: boolean;\n ban_scopes: (\"global\" | \"owner\")[];\n}\n\nexport interface CommitBody {\n ref: RefBody;\n operation_id: string;\n ops: Op[];\n}\n\nexport interface CommitReply {\n files: FileInfo[];\n}\n\nexport interface CompleteReply {\n blob: string;\n type: string;\n size: number;\n}\n\nexport type CompleteRequest = Record<string, never>;\n\nexport interface Config {\n anonymous: Anonymous;\n comment_max_length: number;\n}\n\nexport interface Content {\n id: string;\n kind: string;\n code: string;\n path: string;\n language: string;\n title: string;\n slug?: string;\n description?: string;\n body?: string;\n decision: Decision;\n images?: Record<string, string>;\n cover?: CatalogCover;\n state: ContentState;\n listing: Listing;\n comments: string;\n publish_at?: string;\n published_at?: string;\n live: boolean;\n access: Rule;\n restrictions: string[];\n attributes: Record<string, unknown>;\n owner_group_id?: string;\n owner?: GroupCard;\n creators: Creator[];\n entities: GroupSummary[];\n versions: Version[];\n views?: number;\n viewer?: ViewerState;\n editor: boolean;\n text?: Record<string, CatalogText>;\n moderation?: ModerationState;\n moderation_reason?: string;\n ever_sold?: boolean;\n offer?: Offer;\n revision: number;\n created_at: string;\n updated_at: string;\n deleted_at?: string;\n}\n\nexport interface ContentFilterState {\n entity: GroupCard;\n default_visible: boolean;\n visible: boolean;\n overridden: boolean;\n}\n\nexport interface ContentFilters {\n filters: ContentFilterState[];\n include_deleted: boolean;\n}\n\nexport interface ContentFiltersInitialization {\n account_id: string;\n filters: FilterSetting[];\n include_deleted: boolean;\n}\n\nexport interface ContentFiltersUpdate {\n filters: FilterSetting[];\n include_deleted: boolean;\n}\n\nexport interface ContentGroups {\n kinds?: string[];\n memberships: Membership[];\n}\n\nexport interface ContentInput {\n kind: string;\n text?: Record<string, CatalogText>;\n listing?: Listing;\n comments?: string;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n owner_group_id?: string;\n creators?: Creator[];\n versions?: VersionInput[];\n}\n\nexport interface ContentMemberships {\n content_id: string;\n memberships: Membership[];\n entities: GroupCard[];\n}\n\nexport interface ContentModel {\n languages: string[];\n tiers: string[];\n kinds: Record<string, Kind>;\n entity_kinds: Record<string, GroupKind>;\n signals: boolean;\n avatars?: PresetRule;\n}\n\nexport interface ContentPage {\n contents: Card[];\n next_cursor?: string;\n}\n\nexport interface ContentPatch {\n listing?: Listing;\n comments?: string;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n creators?: Creator[];\n revision?: number;\n}\n\nexport interface ContentRecord {\n external_id: string;\n id?: string;\n kind: string;\n state: string;\n publish_at?: string;\n published_at?: string;\n deleted_at?: string;\n listing?: string;\n comments?: string;\n view_baseline?: number;\n access?: Rule;\n restrictions?: string[];\n attributes?: Record<string, unknown>;\n owner_group?: Ref;\n creators?: Creator[];\n text?: Record<string, CatalogText>;\n versions?: VersionRecord[];\n code?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface ContentRef {\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n}\n\nexport interface CopyBody {\n ref: RefBody;\n files: CopyRequest[];\n}\n\nexport interface CopyFrom {\n id: string;\n version?: string;\n path: string;\n}\n\nexport interface CopyReply {\n files: StagedCopy[];\n}\n\nexport interface CopyRequest {\n path: string;\n type: string;\n from: string;\n size?: number;\n}\n\nexport interface Count {\n content_kind: string;\n language: string;\n count: number;\n}\n\nexport interface Counts {\n likes?: number;\n dislikes?: number;\n favorites?: number;\n views?: number;\n}\n\nexport interface Creator {\n user_id: string;\n role?: string;\n position: number;\n}\n\nexport interface CreatorsInput {\n creators: Creator[];\n}\n\nexport interface Crop {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface DailyReleases {\n time_zone: string;\n from_date: string;\n through_date: string;\n days: ReleaseDay[];\n}\n\nexport interface DateCount {\n date: string;\n count: number;\n free: number;\n}\n\nexport interface Decision {\n allowed: boolean;\n unknown?: boolean;\n sell?: string[];\n requires?: string;\n preview?: Preview;\n free_after?: string;\n offers?: Sale[];\n}\n\nexport interface DeleteRecord {\n entity: string;\n external_id: string;\n}\n\nexport interface Download {\n off?: boolean;\n serve?: string;\n}\n\nexport interface Edge {\n from: string;\n relation: string;\n to: string;\n}\n\nexport interface EdgeInput {\n relation: string;\n to: string;\n}\n\nexport interface EdgeRecord {\n relation: string;\n to: Ref;\n}\n\nexport interface Edit {\n crop?: Crop;\n rotate?: number;\n}\n\nexport interface EncodeProgress {\n phase: EncodePhase;\n queue_position?: number;\n segments_done?: number;\n segments_total?: number;\n percent: number;\n speed?: number;\n eta?: number;\n at: number;\n stalled?: boolean;\n stage?: number;\n stages?: number;\n}\n\nexport interface EntityReference {\n id?: string;\n kind?: string;\n name?: string;\n language?: string;\n scope?: EntityReference;\n}\n\nexport interface EntityResolution {\n id: string;\n kind: string;\n name: string;\n created: boolean;\n scope?: EntityResolution;\n}\n\nexport interface ErrorDetails {\n width?: number;\n height?: number;\n min_width?: number;\n max_pixels?: number;\n type?: string;\n allowed?: string[];\n size?: number;\n max_bytes?: number;\n frames?: number;\n max_frames?: number;\n seconds?: number;\n max_seconds?: number;\n min_aspect?: number;\n max_aspect?: number;\n max?: number;\n}\n\nexport interface ErrorReply {\n error: string;\n code: ErrorCode;\n retry_after?: number;\n action?: \"comment\" | \"comment_reaction\" | \"favorite\" | \"poll_vote\" | \"reaction\";\n ban?: BanNotice;\n blobs?: string[];\n details?: ErrorDetails;\n reason?: string;\n available_at?: string;\n}\n\nexport interface ExposureInput {\n render_id: string;\n stage: string;\n revision?: number;\n query_id?: string;\n surface?: string;\n ranker?: string;\n language?: string;\n occurred_at?: string;\n shown: Placement[];\n}\n\nexport interface Exposures {\n session?: string;\n exposures: ExposureInput[];\n}\n\nexport interface ExternalID {\n external_id: string;\n id: string;\n deleted: boolean;\n}\n\nexport interface ExternalIDList {\n entity: string;\n cursor?: string;\n limit?: number;\n}\n\nexport interface ExternalIDPage {\n entity: string;\n ids: ExternalID[];\n next_cursor?: string;\n}\n\nexport interface ExternalIDs {\n lists: ExternalIDPage[];\n}\n\nexport interface ExternalIDsQuery {\n source: string;\n lists: ExternalIDList[];\n}\n\nexport interface Failure {\n of: string;\n message: string;\n code?: ErrorCode;\n details?: ErrorDetails;\n}\n\nexport interface FavoriteRecord {\n target: TargetRef;\n user_id: string;\n created_at?: string;\n}\n\nexport interface FavoriteState {\n favorited: boolean;\n count?: number;\n}\n\nexport interface FeedItem {\n id: string;\n reply_to_id?: string;\n user_id?: string;\n anon_name?: string;\n language?: string;\n body: string;\n deleted: boolean;\n likes: number;\n dislikes: number;\n mine: number;\n reply_count: number;\n author?: PublicUser;\n moderation?: ModerationState;\n moderation_reason?: string;\n created_at: string;\n updated_at: string;\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n}\n\nexport interface FileDownload {\n url: string;\n name: string;\n type: string;\n size?: number;\n expires_at: string;\n}\n\nexport interface FileInfo {\n path: string;\n type: string;\n size?: number;\n w?: number;\n h?: number;\n dur?: number;\n download?: string;\n url?: string;\n upload?: boolean;\n staged?: boolean;\n from?: string;\n edit?: Edit;\n frame?: Frame;\n meta?: Record<string, unknown>;\n unattached?: boolean;\n pending?: string[];\n failed?: Failure;\n editor_url?: string;\n progress?: EncodeProgress;\n}\n\nexport interface FilterSetting {\n group_id: string;\n visible: boolean;\n}\n\nexport interface ForegroundCue {\n file: string;\n page?: string;\n anchor?: string;\n}\n\nexport interface ForkBody {\n from: string;\n playback?: boolean;\n segments?: boolean;\n}\n\nexport interface Frame {\n t?: number;\n auto?: boolean;\n of?: string;\n}\n\nexport interface Group {\n id: string;\n kind: string;\n slug: string;\n internal: boolean;\n scope_id?: string;\n parent_id?: string;\n state: \"active\" | \"deleted\" | \"merged\";\n merged_into?: string;\n attributes: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n created_at: string;\n updated_at: string;\n revision: number;\n}\n\nexport interface GroupAccess {\n key: string;\n offer?: Sale;\n member: boolean;\n editor?: boolean;\n unknown?: boolean;\n}\n\nexport interface GroupCard {\n id: string;\n kind: string;\n slug: string;\n internal: boolean;\n scope_id?: string;\n parent_id?: string;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n cover?: GroupsCover;\n avatar?: Avatar;\n count: number;\n attributes: Record<string, unknown>;\n access?: GroupAccess;\n created_at: string;\n}\n\nexport interface GroupDetail {\n id: string;\n kind: string;\n slug: string;\n internal: boolean;\n scope_id?: string;\n parent_id?: string;\n state: \"active\" | \"deleted\" | \"merged\";\n merged_into?: string;\n attributes: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n created_at: string;\n updated_at: string;\n revision: number;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n names: Name[];\n text: GroupsText[];\n parent?: GroupCard;\n scope?: GroupCard;\n children: GroupCard[];\n edges: Edge[];\n counts: Count[];\n access?: GroupAccess;\n offer?: Offer;\n}\n\nexport interface GroupInput {\n id?: string;\n kind: string;\n slug: string;\n internal?: boolean;\n scope_id?: string;\n parent_id?: string;\n attributes?: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n names?: Name[];\n text?: GroupsText[];\n}\n\nexport interface GroupJoin {\n group_id: string;\n key: string;\n member: boolean;\n}\n\nexport interface GroupKind {\n route?: string;\n ordered?: boolean;\n parent?: string;\n scoped_by?: string;\n owner?: string;\n max_per_owner?: number;\n uploads?: UploadLimits;\n sellable?: boolean;\n auth_scope?: boolean;\n windows?: boolean;\n version_level?: boolean;\n roles?: string[];\n attributes?: Record<string, Attribute>;\n}\n\nexport interface GroupPage {\n entities: GroupCard[];\n next_cursor?: string;\n}\n\nexport interface GroupRecord {\n external_id: string;\n id?: string;\n kind: string;\n slug: string;\n internal?: boolean;\n scope?: Ref;\n parent?: Ref;\n state?: string;\n names?: Name[];\n text?: GroupsText[];\n attributes?: Record<string, unknown>;\n cover_image?: string;\n cover_content?: Ref;\n avatar?: string;\n owner_user_id?: string;\n auth_scope?: string;\n edges?: EdgeRecord[];\n code?: string;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface GroupSummary {\n id: string;\n kind: string;\n slug: string;\n name: string;\n code?: string;\n path?: string;\n}\n\nexport interface GroupUpdate {\n slug?: string;\n internal?: boolean;\n scope_id?: string;\n parent_id?: string;\n state?: \"active\" | \"deleted\" | \"merged\";\n attributes?: Record<string, unknown>;\n cover?: GroupsCover;\n avatar?: Avatar;\n owner_user_id?: string;\n auth_scope?: string;\n names?: Name[];\n text?: GroupsText[];\n}\n\nexport interface GroupsCover {\n image?: string;\n content_id?: string;\n auto?: boolean;\n renditions?: Rendition[];\n}\n\nexport interface GroupsText {\n language: string;\n description?: string;\n sort_key?: string;\n}\n\nexport interface HeldItem {\n kind: string;\n revision: number;\n id: string;\n ref: ContentRef;\n author_id?: string;\n author?: PublicUser;\n anon_name?: string;\n title?: string;\n body: string;\n reason: string;\n model?: string;\n prompt_version?: string;\n confidence?: number;\n error?: string;\n held_at: string;\n created_at: string;\n}\n\nexport interface HeldPage {\n items: HeldItem[];\n next?: string;\n}\n\nexport interface IPBan {\n network: string;\n reason?: string;\n until?: string;\n banned_by: string;\n banned_at: string;\n expired: boolean;\n}\n\nexport interface IPBanInput {\n network: string;\n reason?: string;\n until?: string;\n}\n\nexport interface ImageInput {\n image?: string;\n}\n\nexport interface InlineImage {\n ref: string;\n url: string | null;\n}\n\nexport interface Input {\n recipient: Recipient;\n origin: Origin;\n kind: string;\n data: unknown;\n created_at: string;\n visibility?: string;\n app_id?: string;\n status?: string;\n action_requested?: boolean;\n severity?: string;\n}\n\nexport interface Interaction {\n content?: Card;\n entity?: GroupCard;\n value: number;\n at: string;\n}\n\nexport interface InteractionPage {\n items: Interaction[];\n next_cursor?: string;\n}\n\nexport interface Item {\n id: string;\n recipient: Recipient;\n origin: Origin;\n kind: string;\n data: unknown;\n created_at: string;\n visibility?: string;\n app_id?: string;\n status?: string;\n action_requested?: boolean;\n severity?: string;\n read_at: string | null;\n dismissed_at: string | null;\n resolved_at: string | null;\n updated_at: string;\n revision: number;\n}\n\nexport interface Kind {\n route: string;\n presentation: string;\n versions: VersionRules;\n segments?: boolean;\n entities?: string[];\n attributes?: Record<string, Attribute>;\n sort?: string;\n locked?: Locked;\n draft_ttl?: number;\n download?: Download;\n}\n\nexport interface LanguageTotal {\n public: number;\n tiers: Record<string, number>;\n}\n\nexport interface LibraryItem {\n content_id: string;\n kind: string;\n title: string;\n language?: string;\n deleted: boolean;\n whole: boolean;\n version_ids: string[];\n}\n\nexport interface LibraryPage {\n items: LibraryItem[];\n next_cursor?: string;\n complete: boolean;\n}\n\nexport interface Locked {\n show: string[];\n preview?: Preview;\n}\n\nexport interface MemberPage {\n members: Membership[];\n next_cursor?: string;\n}\n\nexport interface MemberRef {\n content_id: string;\n version_id?: string;\n}\n\nexport interface Membership {\n group_id?: string;\n content_id?: string;\n version_id?: string;\n role?: string;\n position?: number;\n active_from?: string;\n active_until?: string;\n state?: \"active\" | \"proposed\";\n}\n\nexport interface MembershipRecord {\n group: Ref;\n version?: Ref;\n role?: string;\n position?: number;\n active_from?: string;\n active_until?: string;\n state?: string;\n}\n\nexport interface MembershipSet {\n content: Ref;\n kinds: string[];\n memberships: MembershipRecord[];\n}\n\nexport interface MergeInput {\n into: string;\n}\n\nexport interface MergeReport {\n from: string;\n into: string;\n memberships_moved: number;\n names_moved: number;\n edges_moved: number;\n groups_moved: number;\n}\n\nexport interface MultipartReply {\n ticket: string;\n min_part_size: number;\n max_part_size: number;\n max_parts: number;\n}\n\nexport interface MyGroup {\n id: string;\n kind: string;\n slug: string;\n internal: boolean;\n scope_id?: string;\n parent_id?: string;\n name: string;\n name_language?: string;\n code?: string;\n path?: string;\n cover?: GroupsCover;\n avatar?: Avatar;\n count: number;\n attributes: Record<string, unknown>;\n access?: GroupAccess;\n created_at: string;\n owner: boolean;\n editor: boolean;\n writer: boolean;\n moderator: boolean;\n member: boolean;\n}\n\nexport interface MyGroupPage {\n entities: MyGroup[];\n next_cursor?: string;\n}\n\nexport interface MyStats {\n completed: Record<string, number>;\n access_seconds?: Record<string, number>;\n comments: number;\n comment_likes: number;\n comment_dislikes: number;\n}\n\nexport interface Name {\n language: string;\n kind: \"alias\" | \"name\";\n name: string;\n}\n\nexport interface Offer {\n id: string;\n target: Target;\n key: string;\n terms: Terms;\n state: \"active\" | \"withdrawn\";\n synced: boolean;\n product_id?: string;\n price_id?: string;\n last_error?: string;\n revision: number;\n updated_at: string;\n}\n\nexport interface OfferPage {\n offers: Offer[];\n next_cursor?: string;\n}\n\nexport interface OfferRecord {\n target: TargetRef;\n terms: Terms;\n}\n\nexport interface Op {\n op: OpName;\n path?: string;\n blob?: string;\n create_id?: string;\n index?: number;\n meta?: Record<string, unknown>;\n edit?: Edit;\n unattached?: boolean;\n to?: string;\n from?: CopyFrom;\n t?: number;\n auto?: boolean;\n preset?: string;\n force?: boolean;\n takedown?: boolean;\n}\n\nexport interface Operation {\n id: string;\n state: \"awaiting_upload\" | \"blocked\" | \"failed\" | \"processing\" | \"published\" | \"publishing\" | \"ready\" | \"review_required\" | \"scheduled\";\n content_id: string;\n version_id: string;\n publish_at?: string;\n entities: EntityResolution[];\n progress: Progress;\n result?: OperationResult;\n error?: OperationError;\n upload?: PresignReply;\n created_at: string;\n updated_at: string;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n retryable: boolean;\n field?: string;\n}\n\nexport interface OperationResult {\n path: string;\n pages: number;\n}\n\nexport interface Order {\n members: MemberRef[];\n}\n\nexport interface OrderInput {\n ids: string[];\n}\n\nexport interface Origin {\n system: string;\n scope: string;\n id: string;\n subject?: string;\n}\n\nexport interface Page {\n items: Item[];\n next_cursor?: string;\n}\n\nexport interface PartBody {\n number: number;\n size: number;\n sha256: string;\n}\n\nexport interface PartReply {\n number: number;\n size?: number;\n sha256?: string;\n request?: RequestReply;\n}\n\nexport interface PartsBody {\n ticket: string;\n parts: PartBody[];\n}\n\nexport interface PartsReply {\n parts: PartReply[];\n}\n\nexport interface Pending {\n status: string;\n}\n\nexport interface Placement {\n content_id: string;\n position: number;\n}\n\nexport interface PlanPage {\n name: string;\n w: number;\n h: number;\n files: Record<string, string>;\n}\n\nexport interface PlanPlayback {\n item: RefBody;\n tracks: PlanTrack[];\n}\n\nexport interface PlanPreview {\n index: number;\n name: string;\n url: string;\n w: number;\n h: number;\n}\n\nexport interface PlanSegment {\n position?: number;\n title?: string;\n start: number;\n end: number;\n released: boolean;\n release_at?: string;\n locked: boolean;\n item?: RefBody;\n pages?: PlanPage[];\n}\n\nexport interface PlanTrack {\n name: string;\n path: string;\n duration?: number;\n}\n\nexport interface Poll {\n id: string;\n kind: PollKind;\n question: string;\n language: string;\n is_active: boolean;\n image_url?: string;\n live_at: string;\n closes_at?: string;\n closed: boolean;\n total_votes: number;\n options: PollOption[];\n voted: boolean;\n my_option?: string;\n answer_count?: number;\n groups?: AnswerGroup[];\n my_answer?: PollAnswer;\n}\n\nexport interface PollAnswer {\n id: string;\n text: string;\n classified: boolean;\n updated_at: string;\n}\n\nexport interface PollAnswerInput {\n text: string;\n}\n\nexport interface PollImage {\n image_url: string | null;\n}\n\nexport interface PollInput {\n kind?: PollKind;\n question: string;\n language: string;\n live_at?: string;\n closes_at?: string;\n options?: PollOptionInput[];\n}\n\nexport interface PollOption {\n id: string;\n label: string;\n image_url?: string;\n position: number;\n vote_count: number;\n}\n\nexport interface PollOptionInput {\n label: string;\n position: number;\n}\n\nexport interface PollOptionPatch {\n label?: string;\n position?: number;\n}\n\nexport interface PollOptionRecord {\n external_id: string;\n id?: string;\n label: string;\n position: number;\n}\n\nexport interface PollRecord {\n external_id: string;\n id?: string;\n kind?: string;\n question: string;\n language?: string;\n active?: boolean;\n live_at?: string;\n closes_at?: string;\n deleted_at?: string;\n created_at?: string;\n updated_at?: string;\n options?: PollOptionRecord[];\n}\n\nexport interface PollUpdate {\n question?: string;\n is_active?: boolean;\n live_at?: string;\n closes_at?: string | null;\n}\n\nexport interface PollVote {\n option_id: string;\n}\n\nexport interface PresetRule {\n kind: string;\n name: string;\n from: string;\n base: string;\n namespace: string;\n root?: string;\n to: string;\n widths: number[];\n aspect?: string;\n min_width?: number;\n first?: number;\n default: boolean;\n stable?: boolean;\n}\n\nexport interface PresignBody {\n ref: RefBody;\n path: string;\n type: string;\n size: number;\n sha256: string;\n}\n\nexport interface PresignReply {\n path: string;\n blob: string;\n exists?: boolean;\n put?: RequestReply;\n multipart?: MultipartReply;\n process_on_upload?: boolean;\n}\n\nexport interface Preview {\n pages?: number;\n segments?: number;\n}\n\nexport interface Progress {\n stage: string;\n completed: number;\n total: number;\n}\n\nexport interface PublicImage {\n from: string;\n preset: string;\n renditions: PublicRendition[];\n}\n\nexport interface PublicRendition {\n url: string;\n w: number;\n h: number;\n}\n\nexport interface PublicUser {\n id: string;\n name?: string;\n username: string;\n avatar?: string;\n avatar_srcset?: string;\n}\n\nexport interface Publication {\n notifications: Input[];\n}\n\nexport interface PublishInput {\n publish_at?: string;\n}\n\nexport interface Published {\n items: Item[];\n}\n\nexport interface RankedContent {\n id: string;\n title: string;\n path?: string;\n value: number;\n}\n\nexport interface ReactionCounts {\n likes?: number;\n dislikes?: number;\n mine: number;\n}\n\nexport interface ReactionRecord {\n target: TargetRef;\n user_id?: string;\n ip?: string;\n value: number;\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface ReadResult {\n access: Access;\n expires: number;\n meta?: Record<string, unknown>;\n previews?: string[];\n public?: PublicImage[];\n locked?: boolean;\n total: number;\n offset: number;\n limit: number;\n hls?: string[];\n state?: ItemState;\n full?: boolean;\n uploads?: UploadRule[];\n files: FileInfo[];\n}\n\nexport interface ReaderDefaults {\n auto_advance_seconds?: number;\n}\n\nexport interface ReaderMeta {\n schema_version: number;\n defaults?: ReaderDefaults;\n anchors?: Anchor[];\n background?: BackgroundCue[];\n foreground?: ForegroundCue[];\n}\n\nexport interface ReaderPlan {\n content_id: string;\n version_id: string;\n publication_id: string;\n pages?: number;\n segments: PlanSegment[];\n previews: PlanPreview[];\n playback?: PlanPlayback;\n reader?: ReaderMeta;\n}\n\nexport interface RecentSearch {\n query: string;\n results: number;\n searched_at: string;\n}\n\nexport interface RecentSearches {\n searches: RecentSearch[];\n}\n\nexport interface Recipient {\n audience: string;\n id: string;\n}\n\nexport interface RecordFailure {\n section: string;\n index: number;\n external_id?: string;\n code: string;\n error: string;\n}\n\nexport interface Ref {\n id?: string;\n external_id?: string;\n}\n\nexport interface RefBody {\n kind: string;\n id: string;\n version?: string;\n}\n\nexport interface ReleaseDates {\n dates: DateCount[];\n next_cursor?: string;\n}\n\nexport interface ReleaseDay {\n date: string;\n contents: Card[];\n}\n\nexport interface Rendition {\n url: string;\n w: number;\n h: number;\n}\n\nexport interface Request {\n content: ContentInput;\n entities?: EntityReference[];\n archive: Archive;\n publish?: \"draft\" | \"when_ready\";\n publish_at?: string;\n create_missing_entities?: boolean;\n source?: Source;\n}\n\nexport interface RequestReply {\n method: string;\n url: string;\n headers: Record<string, string>;\n expires: string;\n}\n\nexport interface ResolveInput {\n decision: \"approve\" | \"reject\" | \"review\";\n revision: number;\n reason?: string;\n}\n\nexport interface Resolved {\n tenant_id: string;\n content_kind: string;\n content_id: string;\n content_version_id?: string;\n code: string;\n slug: string;\n slugs?: Record<string, string>;\n path: string;\n version_id?: string;\n}\n\nexport interface Restored {\n restored: boolean;\n}\n\nexport interface Result {\n written: Record<string, number>;\n skipped?: Record<string, number>;\n failed: RecordFailure[];\n ids: Record<string, Record<string, string>>;\n}\n\nexport interface ReviewOutcome {\n decision: \"approve\" | \"reject\" | \"review\";\n}\n\nexport interface Rule {\n level: \"group\" | \"group_ppv\" | \"ppv\" | \"public\" | \"tier\";\n tiers?: string[];\n group_id?: string;\n preview?: Preview;\n free_after?: string;\n}\n\nexport interface Sale {\n key: string;\n target: Target;\n terms: Terms;\n price_id?: string;\n}\n\nexport interface Segment {\n position: number;\n title?: string;\n start: number;\n end: number;\n release_at?: string;\n released: boolean;\n}\n\nexport interface SegmentsInput {\n segments: Segment[];\n}\n\nexport interface SignalInput {\n content_id: string;\n version_id?: string;\n type: string;\n event_id: string;\n revision?: number;\n occurred_at: string;\n duration_s?: number;\n progress?: number;\n resume?: string;\n render_id?: string;\n surface?: string;\n position?: number;\n}\n\nexport interface SignalRecord {\n target: TargetRef;\n user_id?: string;\n anon_key?: string;\n type: string;\n event_id: string;\n revision?: number;\n occurred_at: string;\n duration_s?: number;\n progress?: number;\n resume?: string;\n}\n\nexport interface Signals {\n session?: string;\n signals: SignalInput[];\n}\n\nexport interface SitemapAlias {\n language: string;\n path: string;\n image?: string;\n}\n\nexport interface SitemapEntry {\n id: string;\n code: string;\n path: string;\n lastmod: string;\n languages: SitemapAlias[];\n}\n\nexport interface SitemapPage {\n entries: SitemapEntry[];\n next_cursor?: string;\n}\n\nexport interface Source {\n provider: string;\n id: string;\n url?: string;\n}\n\nexport interface StagedCopy {\n path: string;\n blob: string;\n size: number;\n}\n\nexport interface Target {\n kind: \"content\" | \"group\" | \"version\";\n id: string;\n content_id?: string;\n}\n\nexport interface TargetRef {\n content?: Ref;\n version?: Ref;\n group?: Ref;\n comment?: Ref;\n}\n\nexport interface Terms {\n amount: string;\n currency: string;\n access_hours?: number;\n renew_hours?: number;\n}\n\nexport interface TicketBody {\n ticket: string;\n}\n\nexport interface TopContents {\n contents: RankedContent[];\n}\n\nexport interface Total {\n public: number;\n tiers: Record<string, number>;\n languages: Record<string, LanguageTotal>;\n}\n\nexport interface Totals {\n kinds: Record<string, Total>;\n}\n\nexport interface Typeahead {\n contents: Card[];\n entities: GroupCard[];\n}\n\nexport interface UploadLimits {\n files_per_hour?: number;\n bytes_per_day?: number;\n quota_bytes?: number;\n}\n\nexport interface UploadRule {\n path: string;\n types: string[];\n max_bytes: number;\n max?: number;\n named?: boolean;\n body?: boolean;\n frames?: string;\n aspect?: string;\n min_width?: number;\n video?: VideoLimits;\n min_aspect?: number;\n max_aspect?: number;\n}\n\nexport interface Version {\n id: string;\n code: string;\n position: number;\n languages: string[];\n traits: string[];\n label?: string;\n title?: string;\n description?: string;\n state?: ContentState;\n publish_at?: string;\n published_at?: string;\n live: boolean;\n access?: Rule;\n attributes: Record<string, unknown>;\n pages?: number;\n duration_ms?: number;\n width?: number;\n height?: number;\n has_audio: boolean;\n ordinal?: number;\n cover?: CatalogCover;\n segments: Segment[];\n decision: Decision;\n text?: Record<string, VersionText>;\n offer?: Offer;\n viewer?: ViewerState;\n}\n\nexport interface VersionFork {\n from: string;\n playback?: boolean;\n segments?: boolean;\n}\n\nexport interface VersionInput {\n languages?: string[];\n traits?: string[];\n label?: string;\n state?: VersionState;\n publish_at?: string;\n access?: Rule;\n clear_access?: boolean;\n attributes?: Record<string, unknown>;\n text?: Record<string, VersionText>;\n segments?: Segment[];\n ordinal?: number;\n cover?: string;\n fork?: VersionFork;\n}\n\nexport interface VersionRecord {\n external_id: string;\n id?: string;\n code?: string;\n languages: string[];\n traits?: string[];\n label?: string;\n state?: string;\n publish_at?: string;\n published_at?: string;\n deleted_at?: string;\n access?: Rule;\n attributes?: Record<string, unknown>;\n ordinal?: number;\n cover?: string;\n text?: Record<string, VersionText>;\n segments?: Segment[];\n created_at?: string;\n updated_at?: string;\n}\n\nexport interface VersionRules {\n languages: string;\n traits?: string[];\n hidden?: boolean;\n}\n\nexport interface VersionText {\n title?: string;\n description?: string;\n}\n\nexport interface VideoLimits {\n max_seconds?: number;\n max_fps?: number;\n max_pixels?: number;\n max_work?: number;\n}\n\nexport interface ViewerState {\n favorited: boolean;\n seen: boolean;\n completed: boolean;\n progress: number;\n progress_max: number;\n resume?: string;\n last_view_at?: string;\n}\n\nexport interface VoteRecord {\n poll: Ref;\n option: Ref;\n user_id?: string;\n ip?: string;\n created_at?: string;\n}\n\nexport interface Written {\n count: number;\n}\n"],"mappings":";AAOA,IAAa,IAAiB,UACjB,IAAgB,SAChB,IAAgB"}
|
package/dist/client/http.d.ts
CHANGED
package/dist/client/http.js
CHANGED
|
@@ -21,8 +21,9 @@ var a = (e) => e.replace(/\/+$/, ""), o = class {
|
|
|
21
21
|
}
|
|
22
22
|
acceptGuestFilters(e) {
|
|
23
23
|
this.filterIDs = new Set(e.map((e) => e.entity.id));
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
}
|
|
25
|
+
guestFilters() {
|
|
26
|
+
return this.browserPreferences.snapshot().filters.filter((e) => this.filterIDs?.has(e.group_id));
|
|
26
27
|
}
|
|
27
28
|
async validateGuestFilters() {
|
|
28
29
|
!this.filterIDs && this.browserPreferences.snapshot().filters.length && (this.filterInventory ??= this.request(`${this.mount("discovery")}/content-filters`, { guestPreferences: !1 }).then((e) => this.acceptGuestFilters(e.filters)).finally(() => {
|
|
@@ -46,7 +47,7 @@ var a = (e) => e.replace(/\/+$/, ""), o = class {
|
|
|
46
47
|
m && !p.has("Authorization") && p.set("Authorization", `Bearer ${m}`);
|
|
47
48
|
let h = this.o.language?.();
|
|
48
49
|
if (h && p.set("Accept-Language", h), this.viewer === null && l) {
|
|
49
|
-
let e = this.
|
|
50
|
+
let e = this.guestFilters();
|
|
50
51
|
e.length && p.set("ContentKit-Reader-Preferences", JSON.stringify({ filters: e }));
|
|
51
52
|
}
|
|
52
53
|
if (d !== this.viewerRevision) throw new e("aborted", "The account changed.");
|
|
@@ -67,7 +68,7 @@ var a = (e) => e.replace(/\/+$/, ""), o = class {
|
|
|
67
68
|
let n = await t(g), f = p.get("ContentKit-Reader-Preferences");
|
|
68
69
|
if ((i ?? (a === void 0 ? "GET" : "POST")) === "GET" && n.code === "invalid_request" && f && this.viewer === null && u) {
|
|
69
70
|
if (this.filterIDs = void 0, await this.validateGuestFilters(), d !== this.viewerRevision) throw new e("aborted", "The account changed.");
|
|
70
|
-
let t = this.
|
|
71
|
+
let t = this.guestFilters();
|
|
71
72
|
if ((t.length ? JSON.stringify({ filters: t }) : null) !== f) return this.request(r, {
|
|
72
73
|
method: i,
|
|
73
74
|
body: a,
|
package/dist/client/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":[],"sources":["../../src/client/http.ts"],"sourcesContent":["import { ContentKitError, readContentKitError, requestFailure } from \"./errors.js\";\nimport type { ContentChange } from \"./content/types.js\";\nimport { CONTENTKIT_MODULES } from \"./generated/routes.js\";\nimport type { FileInfo, Item, RefBody } from \"./generated/wire.js\";\nimport { browserReaderPreferences, type BrowserReaderPreferences } from \"./browser-reader-preferences.js\";\n\n/** A module's base URL, or one per item (a host that splits uploads by kind). */\nexport type Mount = string | ((ref: RefBody) => string);\n\n/**\n * Where each module lives when the host does not serve them all under\n * baseUrl's fixed sub-paths (CONTENTKIT_MODULES: the API version, then the\n * module's path). A mount is the module's full base URL.\n */\nexport interface ContentKitMounts {\n /** Comments, reactions, favorites, polls, bans, moderation. Default `{baseUrl}/v1`. */\n content?: string;\n /** Content items and catalog totals. Default `{baseUrl}/v1`. */\n contents?: string;\n /** Media reads and HLS playlists. Default `{baseUrl}/v1/media`. */\n media?: Mount;\n /** Uploads and commits. Default `{baseUrl}/v1/media/upload`. */\n upload?: Mount;\n /** Content-code lookup. Default `{baseUrl}/v1/codes`. */\n codes?: string;\n /** Entities. Default `{baseUrl}/v1`. */\n entities?: string;\n /** The site's content model. Default `{baseUrl}/v1`. */\n kinds?: string;\n /** User inbox. Default `{baseUrl}/v1/notifications`. */\n notifications?: string;\n /** Content versions: reader plans, reader metadata, forks, downloads. Default `{baseUrl}/v1`. */\n versions?: string;\n /** Offers, group joins and the library. Default `{baseUrl}/v1`. */\n offers?: string;\n /** Discovery: lists, search, typeahead, similar, recommendations, history, signals. Default `{baseUrl}/v1`. */\n discovery?: string;\n /** Bulk import (a service's). Default `{baseUrl}/v1`. */\n import?: string;\n /** Durable archive publishing operations. Default `{baseUrl}/v1`. */\n publishing?: string;\n}\n\nexport type ContentKitModule = keyof ContentKitMounts;\n\n/** A mutation made through the client: the host's cache-invalidation hook gets each one. */\nexport type ContentKitChange =\n /** A commit applied; files are the item's uploads as an editor reads them, without URLs. */\n | { type: \"media.committed\"; ref: RefBody; files: FileInfo[] }\n /** An upload finished processing, as an editor read returns it. */\n | { type: \"media.processed\"; ref: RefBody; file: FileInfo }\n | { type: \"notifications.changed\" }\n | { type: \"notifications.updated\"; item: Item }\n | ContentChange;\n\nexport type TokenSource = () => string | null | undefined | Promise<string | null | undefined>;\n\nexport interface HttpOptions {\n /** Where the host mounts ContentKit's routes (contentkit.Routes.Prefix), e.g. \"/api/contentkit\". */\n baseUrl: string;\n mounts?: ContentKitMounts;\n /** Transport for API calls; pass an authenticating fetch (auth-ui's authFetch). */\n fetch?: typeof fetch;\n /** Bearer for API calls and HLS playlists. An authenticating fetch overrides it. */\n token?: TokenSource;\n /** Sent as Accept-Language. */\n language?: () => string | null | undefined;\n /** Extra headers per call (CSRF). */\n headers?: () => HeadersInit | Promise<HeadersInit>;\n /** Default \"same-origin\"; \"include\" also sends cookies with HLS segment requests. */\n credentials?: RequestCredentials;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: AbortSignal;\n /** Read the body as a Blob instead of JSON. */\n blob?: boolean;\n keepalive?: boolean;\n /** Internal preference inventory reads never send unvalidated overrides. */\n guestPreferences?: boolean;\n /** Internal: avoid repeating recovery if a refreshed override is rejected. */\n retryGuestPreferences?: boolean;\n}\n\nconst trim = (u: string) => u.replace(/\\/+$/, \"\");\n\n/** How a player loads HLS: the media client's `hls`. */\nexport interface HlsLoader {\n /** Fetches a playlist or sprite VTT with the app's credentials. */\n playlist(url: string, signal?: AbortSignal): Promise<Response>;\n /** hls.js `xhrSetup` for segments: cookies, never the app's credentials. */\n segment(xhr: XMLHttpRequest, url: string): void;\n}\n\n/** The transport every module shares: mounts, auth, language, errors and change events. */\nexport class Http {\n private readonly listeners = new Set<(change: ContentKitChange, scope: string | null) => void>();\n private readScope = { key: \"{}\" };\n private readonly base: string;\n readonly browserPreferences: BrowserReaderPreferences;\n private viewer?: string | null;\n private viewerRevision = 0;\n private filterIDs?: Set<string>;\n private filterInventory?: Promise<void>;\n\n constructor(private readonly o: HttpOptions) {\n if (typeof o.baseUrl !== \"string\") throw new Error(\"contentkit: createContentKitClient needs baseUrl\");\n this.base = trim(o.baseUrl);\n this.browserPreferences = browserReaderPreferences(this.mount(\"discovery\"));\n }\n\n setViewer(viewer: string | null | undefined): void {\n if (viewer !== this.viewer) this.viewerRevision++;\n this.viewer = viewer;\n }\n\n acceptGuestFilters(filters: readonly { entity: { id: string } }[]): void {\n this.filterIDs = new Set(filters.map((f) => f.entity.id));\n const saved = this.browserPreferences.snapshot().filters;\n const valid = saved.filter((f) => this.filterIDs!.has(f.group_id));\n if (valid.length !== saved.length) this.browserPreferences.setFilters(valid);\n }\n\n private async validateGuestFilters(): Promise<void> {\n if (this.filterIDs || !this.browserPreferences.snapshot().filters.length) return;\n this.filterInventory ??= this.request<{ filters: { entity: { id: string } }[] }>(`${this.mount(\"discovery\")}/content-filters`, { guestPreferences: false })\n .then((result) => this.acceptGuestFilters(result.filters))\n .finally(() => { this.filterInventory = undefined; });\n await this.filterInventory;\n }\n\n /** The module's base URL, without a trailing slash. */\n mount(module: ContentKitModule, ref?: RefBody): string {\n const m = this.o.mounts?.[module];\n if (typeof m === \"function\") {\n if (!ref) throw new Error(`contentkit: the ${module} mount is per item; pass a ref`);\n return trim(m(ref));\n }\n if (m !== undefined) return trim(m);\n return this.base + CONTENTKIT_MODULES[module];\n }\n\n async request<T>(url: string, { method, body, signal, blob, keepalive, guestPreferences = true, retryGuestPreferences = true }: RequestOptions = {}): Promise<T> {\n const viewerRevision = this.viewerRevision;\n if (this.viewer === null && guestPreferences) await this.validateGuestFilters();\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n const f = this.o.fetch ?? fetch;\n const headers = new Headers(await this.o.headers?.());\n headers.delete(\"ContentKit-Reader-Preferences\");\n if (body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n const token = await this.o.token?.();\n if (token && !headers.has(\"Authorization\")) headers.set(\"Authorization\", `Bearer ${token}`);\n const lang = this.o.language?.();\n if (lang) headers.set(\"Accept-Language\", lang);\n if (this.viewer === null && guestPreferences) {\n const filters = this.browserPreferences.snapshot().filters;\n if (filters.length) headers.set(\"ContentKit-Reader-Preferences\", JSON.stringify({ filters }));\n }\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n let res: Response;\n try {\n res = await f(url, {\n method: method ?? (body === undefined ? \"GET\" : \"POST\"),\n headers,\n body: body === undefined ? null : JSON.stringify(body),\n credentials: this.o.credentials ?? \"same-origin\",\n signal: signal ?? null,\n ...(keepalive ? { keepalive } : {}),\n });\n } catch (err) {\n throw requestFailure(err, signal, `ContentKit API ${new URL(url, \"http://x\").pathname}`);\n }\n if (!res.ok) {\n const error = await readContentKitError(res);\n const old = headers.get(\"ContentKit-Reader-Preferences\");\n if ((method ?? (body === undefined ? \"GET\" : \"POST\")) === \"GET\" && error.code === \"invalid_request\" && old && this.viewer === null && retryGuestPreferences) {\n this.filterIDs = undefined;\n await this.validateGuestFilters();\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n const filters = this.browserPreferences.snapshot().filters;\n const current = filters.length ? JSON.stringify({ filters }) : null;\n if (current !== old) return this.request(url, { method, body, signal, blob, keepalive, guestPreferences, retryGuestPreferences: false });\n }\n throw error;\n }\n if (blob) return (await res.blob()) as T;\n return (res.status === 204 ? undefined : await res.json()) as T;\n }\n\n /**\n * How players load this API's HLS. Playlists and sprite VTTs go through\n * the client's fetch, so they carry what its other calls carry (a DPoP\n * proof when that fetch adds one); segments only carry cookies.\n */\n readonly hls: HlsLoader = {\n playlist: async (url, signal) => {\n const init: RequestInit = { credentials: this.o.credentials ?? \"same-origin\", signal: signal ?? null };\n if (!this.onApiOrigin(url)) return fetch(url, init);\n const token = await this.o.token?.();\n return (this.o.fetch ?? fetch)(url, token ? { ...init, headers: { Authorization: `Bearer ${token}` } } : init);\n },\n segment: (xhr, url) => {\n if (!xhr.readyState) xhr.open(\"GET\", url, true);\n if (this.o.credentials === \"include\") xhr.withCredentials = true;\n },\n };\n\n setReadScope(key: string): void {\n if (key !== this.readScope.key) this.readScope = { key };\n }\n\n /** Capture before awaiting a write; null tells caches to refetch after a scope change. */\n captureChanges(): (change: ContentKitChange) => void {\n const scope = this.readScope;\n return (change) => this.emit(change, scope === this.readScope ? scope.key : null);\n }\n\n subscribe(listener: (change: ContentKitChange, scope: string | null) => void): () => void {\n this.listeners.add(listener);\n return () => void this.listeners.delete(listener);\n }\n\n private emit(change: ContentKitChange, scope: string | null): void {\n for (const l of this.listeners) {\n try {\n l(change, scope);\n } catch (e) {\n // A host listener's fault must not fail the mutation that succeeded.\n console.error(\"contentkit: change listener failed\", e);\n }\n }\n }\n\n private onApiOrigin(url: string): boolean {\n const here = typeof location === \"undefined\" ? \"http://localhost\" : location.href;\n try {\n return new URL(url, here).origin === new URL(this.base || \"/\", here).origin;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"http.js","names":[],"sources":["../../src/client/http.ts"],"sourcesContent":["import { ContentKitError, readContentKitError, requestFailure } from \"./errors.js\";\nimport type { ContentChange } from \"./content/types.js\";\nimport { CONTENTKIT_MODULES } from \"./generated/routes.js\";\nimport type { FileInfo, Item, RefBody } from \"./generated/wire.js\";\nimport { browserReaderPreferences, type BrowserReaderPreferences } from \"./browser-reader-preferences.js\";\n\n/** A module's base URL, or one per item (a host that splits uploads by kind). */\nexport type Mount = string | ((ref: RefBody) => string);\n\n/**\n * Where each module lives when the host does not serve them all under\n * baseUrl's fixed sub-paths (CONTENTKIT_MODULES: the API version, then the\n * module's path). A mount is the module's full base URL.\n */\nexport interface ContentKitMounts {\n /** Comments, reactions, favorites, polls, bans, moderation. Default `{baseUrl}/v1`. */\n content?: string;\n /** Content items and catalog totals. Default `{baseUrl}/v1`. */\n contents?: string;\n /** Media reads and HLS playlists. Default `{baseUrl}/v1/media`. */\n media?: Mount;\n /** Uploads and commits. Default `{baseUrl}/v1/media/upload`. */\n upload?: Mount;\n /** Content-code lookup. Default `{baseUrl}/v1/codes`. */\n codes?: string;\n /** Entities. Default `{baseUrl}/v1`. */\n entities?: string;\n /** The site's content model. Default `{baseUrl}/v1`. */\n kinds?: string;\n /** User inbox. Default `{baseUrl}/v1/notifications`. */\n notifications?: string;\n /** Content versions: reader plans, reader metadata, forks, downloads. Default `{baseUrl}/v1`. */\n versions?: string;\n /** Offers, group joins and the library. Default `{baseUrl}/v1`. */\n offers?: string;\n /** Discovery: lists, search, typeahead, similar, recommendations, history, signals. Default `{baseUrl}/v1`. */\n discovery?: string;\n /** Bulk import (a service's). Default `{baseUrl}/v1`. */\n import?: string;\n /** Durable archive publishing operations. Default `{baseUrl}/v1`. */\n publishing?: string;\n}\n\nexport type ContentKitModule = keyof ContentKitMounts;\n\n/** A mutation made through the client: the host's cache-invalidation hook gets each one. */\nexport type ContentKitChange =\n /** A commit applied; files are the item's uploads as an editor reads them, without URLs. */\n | { type: \"media.committed\"; ref: RefBody; files: FileInfo[] }\n /** An upload finished processing, as an editor read returns it. */\n | { type: \"media.processed\"; ref: RefBody; file: FileInfo }\n | { type: \"notifications.changed\" }\n | { type: \"notifications.updated\"; item: Item }\n | ContentChange;\n\nexport type TokenSource = () => string | null | undefined | Promise<string | null | undefined>;\n\nexport interface HttpOptions {\n /** Where the host mounts ContentKit's routes (contentkit.Routes.Prefix), e.g. \"/api/contentkit\". */\n baseUrl: string;\n mounts?: ContentKitMounts;\n /** Transport for API calls; pass an authenticating fetch (auth-ui's authFetch). */\n fetch?: typeof fetch;\n /** Bearer for API calls and HLS playlists. An authenticating fetch overrides it. */\n token?: TokenSource;\n /** Sent as Accept-Language. */\n language?: () => string | null | undefined;\n /** Extra headers per call (CSRF). */\n headers?: () => HeadersInit | Promise<HeadersInit>;\n /** Default \"same-origin\"; \"include\" also sends cookies with HLS segment requests. */\n credentials?: RequestCredentials;\n}\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n signal?: AbortSignal;\n /** Read the body as a Blob instead of JSON. */\n blob?: boolean;\n keepalive?: boolean;\n /** Internal preference inventory reads never send unvalidated overrides. */\n guestPreferences?: boolean;\n /** Internal: avoid repeating recovery if a refreshed override is rejected. */\n retryGuestPreferences?: boolean;\n}\n\nconst trim = (u: string) => u.replace(/\\/+$/, \"\");\n\n/** How a player loads HLS: the media client's `hls`. */\nexport interface HlsLoader {\n /** Fetches a playlist or sprite VTT with the app's credentials. */\n playlist(url: string, signal?: AbortSignal): Promise<Response>;\n /** hls.js `xhrSetup` for segments: cookies, never the app's credentials. */\n segment(xhr: XMLHttpRequest, url: string): void;\n}\n\n/** The transport every module shares: mounts, auth, language, errors and change events. */\nexport class Http {\n private readonly listeners = new Set<(change: ContentKitChange, scope: string | null) => void>();\n private readScope = { key: \"{}\" };\n private readonly base: string;\n readonly browserPreferences: BrowserReaderPreferences;\n private viewer?: string | null;\n private viewerRevision = 0;\n private filterIDs?: Set<string>;\n private filterInventory?: Promise<void>;\n\n constructor(private readonly o: HttpOptions) {\n if (typeof o.baseUrl !== \"string\") throw new Error(\"contentkit: createContentKitClient needs baseUrl\");\n this.base = trim(o.baseUrl);\n this.browserPreferences = browserReaderPreferences(this.mount(\"discovery\"));\n }\n\n setViewer(viewer: string | null | undefined): void {\n if (viewer !== this.viewer) this.viewerRevision++;\n this.viewer = viewer;\n }\n\n acceptGuestFilters(filters: readonly { entity: { id: string } }[]): void {\n this.filterIDs = new Set(filters.map((f) => f.entity.id));\n // Other domains may offer different entities. Keep their saved choices,\n // but send only the current domain's public, configurable filters.\n }\n\n private guestFilters() {\n return this.browserPreferences.snapshot().filters.filter((f) => this.filterIDs?.has(f.group_id));\n }\n\n private async validateGuestFilters(): Promise<void> {\n if (this.filterIDs || !this.browserPreferences.snapshot().filters.length) return;\n this.filterInventory ??= this.request<{ filters: { entity: { id: string } }[] }>(`${this.mount(\"discovery\")}/content-filters`, { guestPreferences: false })\n .then((result) => this.acceptGuestFilters(result.filters))\n .finally(() => { this.filterInventory = undefined; });\n await this.filterInventory;\n }\n\n /** The module's base URL, without a trailing slash. */\n mount(module: ContentKitModule, ref?: RefBody): string {\n const m = this.o.mounts?.[module];\n if (typeof m === \"function\") {\n if (!ref) throw new Error(`contentkit: the ${module} mount is per item; pass a ref`);\n return trim(m(ref));\n }\n if (m !== undefined) return trim(m);\n return this.base + CONTENTKIT_MODULES[module];\n }\n\n async request<T>(url: string, { method, body, signal, blob, keepalive, guestPreferences = true, retryGuestPreferences = true }: RequestOptions = {}): Promise<T> {\n const viewerRevision = this.viewerRevision;\n if (this.viewer === null && guestPreferences) await this.validateGuestFilters();\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n const f = this.o.fetch ?? fetch;\n const headers = new Headers(await this.o.headers?.());\n headers.delete(\"ContentKit-Reader-Preferences\");\n if (body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n const token = await this.o.token?.();\n if (token && !headers.has(\"Authorization\")) headers.set(\"Authorization\", `Bearer ${token}`);\n const lang = this.o.language?.();\n if (lang) headers.set(\"Accept-Language\", lang);\n if (this.viewer === null && guestPreferences) {\n const filters = this.guestFilters();\n if (filters.length) headers.set(\"ContentKit-Reader-Preferences\", JSON.stringify({ filters }));\n }\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n let res: Response;\n try {\n res = await f(url, {\n method: method ?? (body === undefined ? \"GET\" : \"POST\"),\n headers,\n body: body === undefined ? null : JSON.stringify(body),\n credentials: this.o.credentials ?? \"same-origin\",\n signal: signal ?? null,\n ...(keepalive ? { keepalive } : {}),\n });\n } catch (err) {\n throw requestFailure(err, signal, `ContentKit API ${new URL(url, \"http://x\").pathname}`);\n }\n if (!res.ok) {\n const error = await readContentKitError(res);\n const old = headers.get(\"ContentKit-Reader-Preferences\");\n if ((method ?? (body === undefined ? \"GET\" : \"POST\")) === \"GET\" && error.code === \"invalid_request\" && old && this.viewer === null && retryGuestPreferences) {\n this.filterIDs = undefined;\n await this.validateGuestFilters();\n if (viewerRevision !== this.viewerRevision) throw new ContentKitError(\"aborted\", \"The account changed.\");\n const filters = this.guestFilters();\n const current = filters.length ? JSON.stringify({ filters }) : null;\n if (current !== old) return this.request(url, { method, body, signal, blob, keepalive, guestPreferences, retryGuestPreferences: false });\n }\n throw error;\n }\n if (blob) return (await res.blob()) as T;\n return (res.status === 204 ? undefined : await res.json()) as T;\n }\n\n /**\n * How players load this API's HLS. Playlists and sprite VTTs go through\n * the client's fetch, so they carry what its other calls carry (a DPoP\n * proof when that fetch adds one); segments only carry cookies.\n */\n readonly hls: HlsLoader = {\n playlist: async (url, signal) => {\n const init: RequestInit = { credentials: this.o.credentials ?? \"same-origin\", signal: signal ?? null };\n if (!this.onApiOrigin(url)) return fetch(url, init);\n const token = await this.o.token?.();\n return (this.o.fetch ?? fetch)(url, token ? { ...init, headers: { Authorization: `Bearer ${token}` } } : init);\n },\n segment: (xhr, url) => {\n if (!xhr.readyState) xhr.open(\"GET\", url, true);\n if (this.o.credentials === \"include\") xhr.withCredentials = true;\n },\n };\n\n setReadScope(key: string): void {\n if (key !== this.readScope.key) this.readScope = { key };\n }\n\n /** Capture before awaiting a write; null tells caches to refetch after a scope change. */\n captureChanges(): (change: ContentKitChange) => void {\n const scope = this.readScope;\n return (change) => this.emit(change, scope === this.readScope ? scope.key : null);\n }\n\n subscribe(listener: (change: ContentKitChange, scope: string | null) => void): () => void {\n this.listeners.add(listener);\n return () => void this.listeners.delete(listener);\n }\n\n private emit(change: ContentKitChange, scope: string | null): void {\n for (const l of this.listeners) {\n try {\n l(change, scope);\n } catch (e) {\n // A host listener's fault must not fail the mutation that succeeded.\n console.error(\"contentkit: change listener failed\", e);\n }\n }\n }\n\n private onApiOrigin(url: string): boolean {\n const here = typeof location === \"undefined\" ? \"http://localhost\" : location.href;\n try {\n return new URL(url, here).origin === new URL(this.base || \"/\", here).origin;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":";;;;AAsFA,IAAM,KAAQ,MAAc,EAAE,QAAQ,QAAQ,EAAE,GAWnC,IAAb,MAAkB;CAUa;CAT7B,4BAA6B,IAAI,IAA8D;CAC/F,YAAoB,EAAE,KAAK,KAAK;CAChC;CACA;CACA;CACA,iBAAyB;CACzB;CACA;CAEA,YAAY,GAAiC;EAC3C,IAD2B,KAAA,IAAA,GACvB,OAAO,EAAE,WAAY,UAAU,MAAU,MAAM,kDAAkD;EAErG,AADA,KAAK,OAAO,EAAK,EAAE,OAAO,GAC1B,KAAK,qBAAqB,EAAyB,KAAK,MAAM,WAAW,CAAC;CAC5E;CAEA,UAAU,GAAyC;EAEjD,AADI,MAAW,KAAK,UAAQ,KAAK,kBACjC,KAAK,SAAS;CAChB;CAEA,mBAAmB,GAAsD;EACvE,KAAK,YAAY,IAAI,IAAI,EAAQ,KAAK,MAAM,EAAE,OAAO,EAAE,CAAC;CAG1D;CAEA,eAAuB;EACrB,OAAO,KAAK,mBAAmB,SAAS,CAAC,CAAC,QAAQ,QAAQ,MAAM,KAAK,WAAW,IAAI,EAAE,QAAQ,CAAC;CACjG;CAEA,MAAc,uBAAsC;EAC9C,MAAK,aAAc,KAAK,mBAAmB,SAAS,CAAC,CAAC,QAAQ,WAClE,KAAK,oBAAoB,KAAK,QAAmD,GAAG,KAAK,MAAM,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,GAAM,CAAC,CAAC,CACxJ,MAAM,MAAW,KAAK,mBAAmB,EAAO,OAAO,CAAC,CAAC,CACzD,cAAc;GAAE,KAAK,kBAAkB,KAAA;EAAW,CAAC,GACtD,MAAM,KAAK;CACb;CAGA,MAAM,GAA0B,GAAuB;EACrD,IAAM,IAAI,KAAK,EAAE,SAAS;EAC1B,IAAI,OAAO,KAAM,YAAY;GAC3B,IAAI,CAAC,GAAK,MAAU,MAAM,mBAAmB,EAAO,+BAA+B;GACnF,OAAO,EAAK,EAAE,CAAG,CAAC;EACpB;EAEA,OADI,MAAM,KAAA,IACH,KAAK,OAAO,EAAmB,KADV,EAAK,CAAC;CAEpC;CAEA,MAAM,QAAW,GAAa,EAAE,WAAQ,SAAM,WAAQ,SAAM,cAAW,sBAAmB,IAAM,2BAAwB,OAAyB,CAAC,GAAe;EAC/J,IAAM,IAAiB,KAAK;EAE5B,IADI,KAAK,WAAW,QAAQ,KAAkB,MAAM,KAAK,qBAAqB,GAC1E,MAAmB,KAAK,gBAAgB,MAAM,IAAI,EAAgB,WAAW,sBAAsB;EACvG,IAAM,IAAI,KAAK,EAAE,SAAS,OACpB,IAAU,IAAI,QAAQ,MAAM,KAAK,EAAE,UAAU,CAAC;EAEpD,AADA,EAAQ,OAAO,+BAA+B,GAC1C,MAAS,KAAA,KAAW,EAAQ,IAAI,gBAAgB,kBAAkB;EACtE,IAAM,IAAQ,MAAM,KAAK,EAAE,QAAQ;EACnC,AAAI,KAAS,CAAC,EAAQ,IAAI,eAAe,KAAG,EAAQ,IAAI,iBAAiB,UAAU,GAAO;EAC1F,IAAM,IAAO,KAAK,EAAE,WAAW;EAE/B,IADI,KAAM,EAAQ,IAAI,mBAAmB,CAAI,GACzC,KAAK,WAAW,QAAQ,GAAkB;GAC5C,IAAM,IAAU,KAAK,aAAa;GAClC,AAAI,EAAQ,UAAQ,EAAQ,IAAI,iCAAiC,KAAK,UAAU,EAAE,WAAQ,CAAC,CAAC;EAC9F;EACA,IAAI,MAAmB,KAAK,gBAAgB,MAAM,IAAI,EAAgB,WAAW,sBAAsB;EACvG,IAAI;EACJ,IAAI;GACF,IAAM,MAAM,EAAE,GAAK;IACjB,QAAQ,MAAW,MAAS,KAAA,IAAY,QAAQ;IAChD;IACA,MAAM,MAAS,KAAA,IAAY,OAAO,KAAK,UAAU,CAAI;IACrD,aAAa,KAAK,EAAE,eAAe;IACnC,QAAQ,KAAU;IAClB,GAAI,IAAY,EAAE,aAAU,IAAI,CAAC;GACnC,CAAC;EACH,SAAS,GAAK;GACZ,MAAM,EAAe,GAAK,GAAQ,kBAAkB,IAAI,IAAI,GAAK,UAAU,CAAC,CAAC,UAAU;EACzF;EACA,IAAI,CAAC,EAAI,IAAI;GACX,IAAM,IAAQ,MAAM,EAAoB,CAAG,GACrC,IAAM,EAAQ,IAAI,+BAA+B;GACvD,KAAK,MAAW,MAAS,KAAA,IAAY,QAAQ,aAAa,SAAS,EAAM,SAAS,qBAAqB,KAAO,KAAK,WAAW,QAAQ,GAAuB;IAG3J,IAFA,KAAK,YAAY,KAAA,GACjB,MAAM,KAAK,qBAAqB,GAC5B,MAAmB,KAAK,gBAAgB,MAAM,IAAI,EAAgB,WAAW,sBAAsB;IACvG,IAAM,IAAU,KAAK,aAAa;IAElC,KADgB,EAAQ,SAAS,KAAK,UAAU,EAAE,WAAQ,CAAC,IAAI,UAC/C,GAAK,OAAO,KAAK,QAAQ,GAAK;KAAE;KAAQ;KAAM;KAAQ;KAAM;KAAW;KAAkB,uBAAuB;IAAM,CAAC;GACzI;GACA,MAAM;EACR;EAEA,OADI,IAAc,MAAM,EAAI,KAAK,IACzB,EAAI,WAAW,MAAM,KAAA,IAAY,MAAM,EAAI,KAAK;CAC1D;CAOA,MAA0B;EACxB,UAAU,OAAO,GAAK,MAAW;GAC/B,IAAM,IAAoB;IAAE,aAAa,KAAK,EAAE,eAAe;IAAe,QAAQ,KAAU;GAAK;GACrG,IAAI,CAAC,KAAK,YAAY,CAAG,GAAG,OAAO,MAAM,GAAK,CAAI;GAClD,IAAM,IAAQ,MAAM,KAAK,EAAE,QAAQ;GACnC,QAAQ,KAAK,EAAE,SAAS,MAAA,CAAO,GAAK,IAAQ;IAAE,GAAG;IAAM,SAAS,EAAE,eAAe,UAAU,IAAQ;GAAE,IAAI,CAAI;EAC/G;EACA,UAAU,GAAK,MAAQ;GAErB,AADK,EAAI,cAAY,EAAI,KAAK,OAAO,GAAK,EAAI,GAC1C,KAAK,EAAE,gBAAgB,cAAW,EAAI,kBAAkB;EAC9D;CACF;CAEA,aAAa,GAAmB;EAC9B,AAAI,MAAQ,KAAK,UAAU,QAAK,KAAK,YAAY,EAAE,OAAI;CACzD;CAGA,iBAAqD;EACnD,IAAM,IAAQ,KAAK;EACnB,QAAQ,MAAW,KAAK,KAAK,GAAQ,MAAU,KAAK,YAAY,EAAM,MAAM,IAAI;CAClF;CAEA,UAAU,GAAgF;EAExF,OADA,KAAK,UAAU,IAAI,CAAQ,SACd,KAAK,KAAK,UAAU,OAAO,CAAQ;CAClD;CAEA,KAAa,GAA0B,GAA4B;EACjE,KAAK,IAAM,KAAK,KAAK,WACnB,IAAI;GACF,EAAE,GAAQ,CAAK;EACjB,SAAS,GAAG;GAEV,QAAQ,MAAM,sCAAsC,CAAC;EACvD;CAEJ;CAEA,YAAoB,GAAsB;EACxC,IAAM,IAAO,OAAO,WAAa,MAAc,qBAAqB,SAAS;EAC7E,IAAI;GACF,OAAO,IAAI,IAAI,GAAK,CAAI,CAAC,CAAC,WAAW,IAAI,IAAI,KAAK,QAAQ,KAAK,CAAI,CAAC,CAAC;EACvE,QAAQ;GACN,OAAO;EACT;CACF;AACF"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { PollsClient, type PollAdminQuery, type PollQuery, type PollState } from
|
|
|
10
10
|
export { BansClient } from './content/bans.js';
|
|
11
11
|
export { ModerationClient, type HeldQuery } from './content/moderation.js';
|
|
12
12
|
export { reactionVerb, sameTarget, type BanScope, type ContentChange, type Decision, type HeldKind, type Reaction, type RuleSet, type Sort, type Target } from './content/types.js';
|
|
13
|
-
export { EntitiesClient, type EntityImageSlot, type EntityQuery, type MemberQuery, type MyEntityQuery } from './entities.js';
|
|
13
|
+
export { EntitiesClient, type EntityImageSlot, type EntityQuery, type ManageEntityQuery, type MemberQuery, type MyEntityQuery } from './entities.js';
|
|
14
14
|
export { DiscoveryClient, popularQuery, type AccessMode, type CardQuery, type ContentFilterQuery, type ContentQuery, type HistoryQuery, type ListSort, type Period, type PopularPeriod, type PopularQuery, type RailQuery, type ReaderQuery, type RecentSearchesQuery, type ReleaseDatesQuery, type DailyReleasesQuery, type SearchQuery, type TypeaheadQuery, } from './discovery.js';
|
|
15
15
|
export { VersionsClient, isPending } from './versions.js';
|
|
16
16
|
export { emptyReaderMeta, matchAudio, readerMetaProblems, readerNames, type AudioMatch, type ReaderMetaProblem, type ReaderNames } from './reader-meta.js';
|
|
@@ -102,15 +102,11 @@ var r = class {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
if (t = this.browser.pending(e), t && !t.filtersDone) {
|
|
105
|
-
if (r !== this.generation
|
|
106
|
-
let i = await this.http.request(`${this.http.mount("discovery")}/content-filters`, { guestPreferences: !1 });
|
|
107
|
-
if (r !== this.generation) return;
|
|
108
|
-
let a = new Set(i.filters.map((e) => e.entity.id));
|
|
109
|
-
if (await n(this.http, "POST", "/me/content-filters/initialize", { body: {
|
|
105
|
+
if (r !== this.generation || (await n(this.http, "POST", "/me/content-filters/initialize", { body: {
|
|
110
106
|
account_id: e,
|
|
111
|
-
filters: t.filters
|
|
107
|
+
filters: [...t.filters],
|
|
112
108
|
include_deleted: !1
|
|
113
|
-
} }), r !== this.generation) return;
|
|
109
|
+
} }), r !== this.generation)) return;
|
|
114
110
|
this.browser.complete(e, "filters");
|
|
115
111
|
}
|
|
116
112
|
r === this.generation && this.http.captureChanges()({ type: "contentFilters.changed" });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reader-preferences.js","names":[],"sources":["../../src/client/reader-preferences.ts"],"sourcesContent":["import { ContentKitError, toContentKitError } from \"./errors.js\";\nimport type { ContentFilters, ContentFiltersUpdate } from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call } from \"./route.js\";\n\n/** The host's account-owned preferred language, without a route fallback. */\nexport interface LanguagePreference {\n load(accountId: string): Promise<string | null | undefined>;\n save(language: string, accountId: string): Promise<void>;\n}\n\nexport interface ReaderPreferenceState {\n language?: string;\n loading: boolean;\n saving: boolean;\n pending: boolean;\n error?: ContentKitError;\n}\n\n/** Guest storage and explicit, retryable registration inheritance. */\nexport class ReaderPreferencesClient {\n readonly browser;\n private viewer?: string | null;\n private adapter?: LanguagePreference;\n private accountLanguage?: string;\n private loading = false;\n private saving = false;\n private failure?: ContentKitError;\n private generation = 0;\n private syncing?: Promise<void>;\n private syncingGeneration = -1;\n private state: ReaderPreferenceState = Object.freeze({ loading: false, saving: false, pending: false });\n private readonly listeners = new Set<() => void>();\n private stopBrowser?: () => void;\n private guestValue: string;\n\n constructor(private readonly http: Http) {\n this.browser = http.browserPreferences;\n this.guestValue = JSON.stringify(this.browser.snapshot());\n }\n\n readonly snapshot = (): ReaderPreferenceState => this.state;\n readonly subscribe = (listener: () => void): (() => void) => {\n if (!this.listeners.size) {\n this.stopBrowser = this.browser.subscribe(this.browserChanged);\n if (typeof window !== \"undefined\") window.addEventListener(\"online\", this.retryOnline);\n }\n this.listeners.add(listener);\n this.refresh();\n return () => {\n this.listeners.delete(listener);\n if (!this.listeners.size) {\n this.stopBrowser?.();\n if (typeof window !== \"undefined\") window.removeEventListener(\"online\", this.retryOnline);\n }\n };\n };\n\n configure(viewer: string | null | undefined, adapter?: LanguagePreference): void {\n this.http.setViewer(viewer);\n if (viewer === this.viewer && adapter === this.adapter) return;\n this.viewer = viewer;\n this.adapter = adapter;\n const generation = ++this.generation;\n this.accountLanguage = undefined;\n this.failure = undefined;\n this.saving = false;\n this.loading = !!viewer && !!adapter;\n this.refresh();\n if (viewer) void this.activate(generation).catch(() => {});\n }\n\n async setLanguage(language: string): Promise<void> {\n try { language = Intl.getCanonicalLocales(language)[0]!; }\n catch { throw new ContentKitError(\"invalid_request\", \"Invalid preferred language.\"); }\n if (!language) throw new ContentKitError(\"invalid_request\", \"Invalid preferred language.\");\n const account = this.viewer;\n if (account == null) { this.browser.setLanguage(language); this.refresh(); return; }\n if (!this.adapter) throw new Error(\"contentkit: account language preference adapter is required\");\n const generation = this.generation;\n this.saving = true;\n this.failure = undefined;\n this.refresh();\n try {\n await this.adapter.save(language, account);\n if (generation !== this.generation) throw new ContentKitError(\"aborted\", \"The account changed.\");\n this.accountLanguage = language;\n this.browser.complete(account, \"language\");\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n throw error;\n } finally {\n if (generation === this.generation) { this.saving = false; this.refresh(); }\n }\n }\n\n /** Call only after a confirmed registration event, never on ordinary login. */\n async inheritAfterRegistration(account: string): Promise<void> {\n this.browser.register(account);\n this.refresh();\n return this.viewer === account ? this.retryInheritance() : Promise.resolve();\n }\n\n async retry(): Promise<void> {\n if (!this.viewer) return;\n const generation = this.generation;\n this.failure = undefined;\n this.loading = true;\n this.refresh();\n await this.activate(generation);\n if (generation === this.generation && this.failure) throw this.failure;\n }\n\n retryInheritance(): Promise<void> {\n if (!this.viewer || !this.browser.pending(this.viewer)) return Promise.resolve();\n if (this.syncing && this.syncingGeneration === this.generation) return this.syncing;\n const account = this.viewer, generation = this.generation;\n const task = this.inherit(account, generation).finally(() => {\n if (this.syncing === task) this.syncing = undefined;\n this.refresh();\n });\n this.syncing = task;\n this.syncingGeneration = generation;\n this.refresh();\n return this.syncing;\n }\n\n private async activate(generation: number): Promise<void> {\n try {\n await this.retryInheritance();\n if (generation !== this.generation) return;\n const language = this.viewer ? await this.adapter?.load(this.viewer) : undefined;\n if (generation === this.generation) this.accountLanguage = language ?? undefined;\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n } finally {\n if (generation === this.generation) { this.loading = false; this.refresh(); }\n }\n }\n\n private async inherit(account: string, generation: number): Promise<void> {\n this.failure = undefined;\n try {\n let pending = this.browser.pending(account)!;\n if (!pending.languageDone) {\n if (!this.adapter) throw new Error(\"contentkit: account language preference adapter is required\");\n const language = (await this.adapter.load(account)) ?? null;\n if (generation !== this.generation) return;\n const live = this.browser.pending(account);\n if (live && !live.languageDone) {\n if (!live.languageObserved) this.browser.observeLanguage(account, language);\n pending = this.browser.pending(account)!;\n // The initial registration default may be non-null. A later different\n // choice wins over a retry of the captured guest preference.\n const changedLater = language !== pending.initialLanguage && language !== pending.language;\n if (!changedLater && language !== pending.language && pending.language) await this.adapter.save(pending.language, account);\n if (generation !== this.generation) return;\n this.accountLanguage = changedLater ? language ?? undefined : pending.language;\n this.browser.complete(account, \"language\");\n }\n }\n pending = this.browser.pending(account)!;\n if (pending && !pending.filtersDone) {\n if (generation !== this.generation) return;\n const inventory = await this.http.request<ContentFilters>(`${this.http.mount(\"discovery\")}/content-filters`, { guestPreferences: false });\n if (generation !== this.generation) return;\n const known = new Set(inventory.filters.map((f) => f.entity.id));\n await call<\"POST\", \"/me/content-filters/initialize\", ContentFilters>(this.http, \"POST\", \"/me/content-filters/initialize\", {\n body: { account_id: account, filters: pending.filters.filter((f) => known.has(f.group_id)), include_deleted: false } satisfies ContentFiltersUpdate & { account_id: string },\n });\n if (generation !== this.generation) return;\n this.browser.complete(account, \"filters\");\n }\n if (generation === this.generation) this.http.captureChanges()({ type: \"contentFilters.changed\" });\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n throw error;\n }\n }\n\n private readonly retryOnline = (): void => {\n if (this.state.pending || this.state.error) void this.retry().catch(() => {});\n };\n private readonly browserChanged = (): void => {\n const value = JSON.stringify(this.browser.snapshot());\n if (this.viewer === null && value !== this.guestValue) this.http.captureChanges()({ type: \"contentFilters.changed\" });\n this.guestValue = value;\n this.refresh();\n };\n\n private refresh(): void {\n const next: ReaderPreferenceState = {\n language: this.viewer == null ? this.browser.snapshot().language : this.accountLanguage,\n loading: this.loading, saving: this.saving,\n pending: !!this.viewer && !!this.browser.pending(this.viewer), error: this.failure,\n };\n if (next.language === this.state.language && next.loading === this.state.loading && next.saving === this.state.saving && next.pending === this.state.pending && next.error === this.state.error) return;\n this.state = Object.freeze(next);\n for (const listener of this.listeners) { try { listener(); } catch { /* Observers do not own persistence. */ } }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reader-preferences.js","names":[],"sources":["../../src/client/reader-preferences.ts"],"sourcesContent":["import { ContentKitError, toContentKitError } from \"./errors.js\";\nimport type { ContentFilters, ContentFiltersUpdate } from \"./generated/wire.js\";\nimport type { Http } from \"./http.js\";\nimport { call } from \"./route.js\";\n\n/** The host's account-owned preferred language, without a route fallback. */\nexport interface LanguagePreference {\n load(accountId: string): Promise<string | null | undefined>;\n save(language: string, accountId: string): Promise<void>;\n}\n\nexport interface ReaderPreferenceState {\n language?: string;\n loading: boolean;\n saving: boolean;\n pending: boolean;\n error?: ContentKitError;\n}\n\n/** Guest storage and explicit, retryable registration inheritance. */\nexport class ReaderPreferencesClient {\n readonly browser;\n private viewer?: string | null;\n private adapter?: LanguagePreference;\n private accountLanguage?: string;\n private loading = false;\n private saving = false;\n private failure?: ContentKitError;\n private generation = 0;\n private syncing?: Promise<void>;\n private syncingGeneration = -1;\n private state: ReaderPreferenceState = Object.freeze({ loading: false, saving: false, pending: false });\n private readonly listeners = new Set<() => void>();\n private stopBrowser?: () => void;\n private guestValue: string;\n\n constructor(private readonly http: Http) {\n this.browser = http.browserPreferences;\n this.guestValue = JSON.stringify(this.browser.snapshot());\n }\n\n readonly snapshot = (): ReaderPreferenceState => this.state;\n readonly subscribe = (listener: () => void): (() => void) => {\n if (!this.listeners.size) {\n this.stopBrowser = this.browser.subscribe(this.browserChanged);\n if (typeof window !== \"undefined\") window.addEventListener(\"online\", this.retryOnline);\n }\n this.listeners.add(listener);\n this.refresh();\n return () => {\n this.listeners.delete(listener);\n if (!this.listeners.size) {\n this.stopBrowser?.();\n if (typeof window !== \"undefined\") window.removeEventListener(\"online\", this.retryOnline);\n }\n };\n };\n\n configure(viewer: string | null | undefined, adapter?: LanguagePreference): void {\n this.http.setViewer(viewer);\n if (viewer === this.viewer && adapter === this.adapter) return;\n this.viewer = viewer;\n this.adapter = adapter;\n const generation = ++this.generation;\n this.accountLanguage = undefined;\n this.failure = undefined;\n this.saving = false;\n this.loading = !!viewer && !!adapter;\n this.refresh();\n if (viewer) void this.activate(generation).catch(() => {});\n }\n\n async setLanguage(language: string): Promise<void> {\n try { language = Intl.getCanonicalLocales(language)[0]!; }\n catch { throw new ContentKitError(\"invalid_request\", \"Invalid preferred language.\"); }\n if (!language) throw new ContentKitError(\"invalid_request\", \"Invalid preferred language.\");\n const account = this.viewer;\n if (account == null) { this.browser.setLanguage(language); this.refresh(); return; }\n if (!this.adapter) throw new Error(\"contentkit: account language preference adapter is required\");\n const generation = this.generation;\n this.saving = true;\n this.failure = undefined;\n this.refresh();\n try {\n await this.adapter.save(language, account);\n if (generation !== this.generation) throw new ContentKitError(\"aborted\", \"The account changed.\");\n this.accountLanguage = language;\n this.browser.complete(account, \"language\");\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n throw error;\n } finally {\n if (generation === this.generation) { this.saving = false; this.refresh(); }\n }\n }\n\n /** Call only after a confirmed registration event, never on ordinary login. */\n async inheritAfterRegistration(account: string): Promise<void> {\n this.browser.register(account);\n this.refresh();\n return this.viewer === account ? this.retryInheritance() : Promise.resolve();\n }\n\n async retry(): Promise<void> {\n if (!this.viewer) return;\n const generation = this.generation;\n this.failure = undefined;\n this.loading = true;\n this.refresh();\n await this.activate(generation);\n if (generation === this.generation && this.failure) throw this.failure;\n }\n\n retryInheritance(): Promise<void> {\n if (!this.viewer || !this.browser.pending(this.viewer)) return Promise.resolve();\n if (this.syncing && this.syncingGeneration === this.generation) return this.syncing;\n const account = this.viewer, generation = this.generation;\n const task = this.inherit(account, generation).finally(() => {\n if (this.syncing === task) this.syncing = undefined;\n this.refresh();\n });\n this.syncing = task;\n this.syncingGeneration = generation;\n this.refresh();\n return this.syncing;\n }\n\n private async activate(generation: number): Promise<void> {\n try {\n await this.retryInheritance();\n if (generation !== this.generation) return;\n const language = this.viewer ? await this.adapter?.load(this.viewer) : undefined;\n if (generation === this.generation) this.accountLanguage = language ?? undefined;\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n } finally {\n if (generation === this.generation) { this.loading = false; this.refresh(); }\n }\n }\n\n private async inherit(account: string, generation: number): Promise<void> {\n this.failure = undefined;\n try {\n let pending = this.browser.pending(account)!;\n if (!pending.languageDone) {\n if (!this.adapter) throw new Error(\"contentkit: account language preference adapter is required\");\n const language = (await this.adapter.load(account)) ?? null;\n if (generation !== this.generation) return;\n const live = this.browser.pending(account);\n if (live && !live.languageDone) {\n if (!live.languageObserved) this.browser.observeLanguage(account, language);\n pending = this.browser.pending(account)!;\n // The initial registration default may be non-null. A later different\n // choice wins over a retry of the captured guest preference.\n const changedLater = language !== pending.initialLanguage && language !== pending.language;\n if (!changedLater && language !== pending.language && pending.language) await this.adapter.save(pending.language, account);\n if (generation !== this.generation) return;\n this.accountLanguage = changedLater ? language ?? undefined : pending.language;\n this.browser.complete(account, \"language\");\n }\n }\n pending = this.browser.pending(account)!;\n if (pending && !pending.filtersDone) {\n if (generation !== this.generation) return;\n // Registration initializes account-wide choices. Only the server knows\n // which saved entities are toggleable on another domain or now stale.\n await call<\"POST\", \"/me/content-filters/initialize\", ContentFilters>(this.http, \"POST\", \"/me/content-filters/initialize\", {\n body: { account_id: account, filters: [...pending.filters], include_deleted: false } satisfies ContentFiltersUpdate & { account_id: string },\n });\n if (generation !== this.generation) return;\n this.browser.complete(account, \"filters\");\n }\n if (generation === this.generation) this.http.captureChanges()({ type: \"contentFilters.changed\" });\n } catch (error) {\n if (generation === this.generation) this.failure = toContentKitError(error);\n throw error;\n }\n }\n\n private readonly retryOnline = (): void => {\n if (this.state.pending || this.state.error) void this.retry().catch(() => {});\n };\n private readonly browserChanged = (): void => {\n const value = JSON.stringify(this.browser.snapshot());\n if (this.viewer === null && value !== this.guestValue) this.http.captureChanges()({ type: \"contentFilters.changed\" });\n this.guestValue = value;\n this.refresh();\n };\n\n private refresh(): void {\n const next: ReaderPreferenceState = {\n language: this.viewer == null ? this.browser.snapshot().language : this.accountLanguage,\n loading: this.loading, saving: this.saving,\n pending: !!this.viewer && !!this.browser.pending(this.viewer), error: this.failure,\n };\n if (next.language === this.state.language && next.loading === this.state.loading && next.saving === this.state.saving && next.pending === this.state.pending && next.error === this.state.error) return;\n this.state = Object.freeze(next);\n for (const listener of this.listeners) { try { listener(); } catch { /* Observers do not own persistence. */ } }\n }\n}\n"],"mappings":"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"}
|
|
@@ -53,6 +53,8 @@ export declare function contentStatus(c: Content): ContentStatus;
|
|
|
53
53
|
*/
|
|
54
54
|
export declare function ContentManager({ client: own, baseUrl, auth, guard, appearance, className, language, messages, ...p }: ContentManagerProps): import('react').JSX.Element;
|
|
55
55
|
export interface ContentEditorProps {
|
|
56
|
+
/** Staff entity lookup, including internal classifications. */
|
|
57
|
+
management?: boolean;
|
|
56
58
|
/** The item edited; null creates one of kind. */
|
|
57
59
|
id: string | null;
|
|
58
60
|
kind: string;
|
|
@@ -76,5 +78,5 @@ export interface ContentEditorProps {
|
|
|
76
78
|
* schedule, cover and body per language, publish, unpublish and delete;
|
|
77
79
|
* then listing and attributes, access rule and price, versions and groups.
|
|
78
80
|
*/
|
|
79
|
-
export declare function ContentEditor({ id, client: own, kind, languages: offered, renderEditor, contentHref, labels, ownerGroup, onCreated, onDeleted, onError }: ContentEditorProps): import('react').JSX.Element;
|
|
81
|
+
export declare function ContentEditor({ id, client: own, kind, languages: offered, renderEditor, contentHref, labels, ownerGroup, onCreated, onDeleted, onError, management }: ContentEditorProps): import('react').JSX.Element;
|
|
80
82
|
export {};
|