a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
101
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(bluesky-moderation)!: replace enums with plain objects

Mary 4729dea3 5383d929

+101 -77
+10
.changeset/replace-enums-moderation.md
··· 1 + --- 2 + '@atcute/bluesky-moderation': major 3 + --- 4 + 5 + replace enums with plain objects 6 + 7 + exported enums are now `as const` objects with companion type aliases. enum member values are 8 + unchanged, so runtime behavior is identical. the main type-level difference is that string enums are 9 + no longer nominal — raw string literals are now assignable where enum types were previously 10 + required.
+9 -5
packages/bluesky/moderation/lib/_test-util/moderation-behavior.ts
··· 156 156 } 157 157 158 158 export class ModerationBehaviorSuiteRunner { 159 - constructor( 160 - public users: SuiteUsers, 161 - public configurations: SuiteConfigurations, 162 - public scenarios: SuiteScenarios, 163 - ) {} 159 + users: SuiteUsers; 160 + configurations: SuiteConfigurations; 161 + scenarios: SuiteScenarios; 162 + 163 + constructor(users: SuiteUsers, configurations: SuiteConfigurations, scenarios: SuiteScenarios) { 164 + this.users = users; 165 + this.configurations = configurations; 166 + this.scenarios = scenarios; 167 + } 164 168 165 169 postScenario(scenario: ModerationTestSuiteScenario) { 166 170 if (scenario.subject !== 'post') {
+21 -18
packages/bluesky/moderation/lib/behaviors.ts
··· 1 - export enum LabelTarget { 1 + export const LabelTarget = { 2 2 /** label is intended for account's content */ 3 - Content = 'content', 3 + Content: 'content', 4 4 /** label is intended for account's profile */ 5 - Profile = 'profile', 5 + Profile: 'profile', 6 6 /** label is intended for account's content and profile */ 7 - Account = 'account', 8 - } 7 + Account: 'account', 8 + } as const; 9 + export type LabelTarget = (typeof LabelTarget)[keyof typeof LabelTarget]; 9 10 10 - export enum DisplayContext { 11 + export const DisplayContext = { 11 12 /** content in expanded view */ 12 - ContentView = 'contentView', 13 + ContentView: 'contentView', 13 14 /** images or video contained in content */ 14 - ContentMedia = 'contentMedia', 15 + ContentMedia: 'contentMedia', 15 16 /** content in a list/feed */ 16 - ContentList = 'contentList', 17 + ContentList: 'contentList', 17 18 18 19 /** profile in expanded view */ 19 - ProfileView = 'profileView', 20 + ProfileView: 'profileView', 20 21 /** profile's avatar or banner */ 21 - ProfileMedia = 'profileMedia', 22 + ProfileMedia: 'profileMedia', 22 23 /** profile in a list */ 23 - ProfileList = 'profileList', 24 - } 24 + ProfileList: 'profileList', 25 + } as const; 26 + export type DisplayContext = (typeof DisplayContext)[keyof typeof DisplayContext]; 25 27 26 - export enum ModerationAction { 28 + export const ModerationAction = { 27 29 /** should cause blurring */ 28 - Blur = 'blur', 30 + Blur: 'blur', 29 31 /** should cause an alert */ 30 - Alert = 'alert', 32 + Alert: 'alert', 31 33 /** should cause a notice */ 32 - Inform = 'inform', 33 - } 34 + Inform: 'inform', 35 + } as const; 36 + export type ModerationAction = (typeof ModerationAction)[keyof typeof ModerationAction]; 34 37 35 38 export type BehaviorMapping = { [C in DisplayContext]?: ModerationAction }; 36 39 export type LabelBehaviorMatrix = { [T in LabelTarget]: BehaviorMapping };
+22 -21
packages/bluesky/moderation/lib/decision.ts
··· 12 12 } from './label.ts'; 13 13 import type { Label, LabelerPreference, ModerationOptions } from './types.ts'; 14 14 15 - const enum ModerationSeverity { 16 - High = 1, 17 - Medium = 2, 18 - Low = 3, 19 - } 15 + const ModerationSeverity = { 16 + High: 1, 17 + Medium: 2, 18 + Low: 3, 19 + } as const; 20 20 21 - export enum ModerationCauseType { 21 + export const ModerationCauseType = { 22 22 /** caused by a label */ 23 - Label = 1, 23 + Label: 1, 24 24 /** caused by viewer blocking the subject */ 25 - Blocking = 2, 25 + Blocking: 2, 26 26 /** caused by subject blocking the viewer */ 27 - BlockedBy = 3, 27 + BlockedBy: 3, 28 28 /** caused by viewer having a (permanent) mute on subject */ 29 - MutedPermanent = 4, 29 + MutedPermanent: 4, 30 30 /** caused by a temporary mute */ 31 - MutedTemporary = 5, 31 + MutedTemporary: 5, 32 32 /** caused by a keyword mute */ 33 - MutedKeyword = 6, 33 + MutedKeyword: 6, 34 34 /** caused by a hidden post */ 35 - Hidden = 7, 36 - } 35 + Hidden: 7, 36 + } as const; 37 + export type ModerationCauseType = (typeof ModerationCauseType)[keyof typeof ModerationCauseType]; 37 38 38 39 export interface BlockingModerationCause { 39 - type: ModerationCauseType.Blocking; 40 + type: typeof ModerationCauseType.Blocking; 40 41 priority: 3; 41 42 source: AppBskyGraphDefs.ListViewBasic | null; 42 43 ··· 44 45 } 45 46 46 47 export interface BlockedByModerationCause { 47 - type: ModerationCauseType.BlockedBy; 48 + type: typeof ModerationCauseType.BlockedBy; 48 49 priority: 4; 49 50 50 51 downgraded: boolean; 51 52 } 52 53 53 54 export interface HiddenModerationCause { 54 - type: ModerationCauseType.Hidden; 55 + type: typeof ModerationCauseType.Hidden; 55 56 priority: 6; 56 57 57 58 downgraded: boolean; 58 59 } 59 60 60 61 export interface LabelModerationCause { 61 - type: ModerationCauseType.Label; 62 + type: typeof ModerationCauseType.Label; 62 63 priority: 1 | 2 | 5 | 7 | 8; 63 64 source: Did | null; 64 65 ··· 74 75 } 75 76 76 77 export interface MutedPermanentModerationCause { 77 - type: ModerationCauseType.MutedPermanent; 78 + type: typeof ModerationCauseType.MutedPermanent; 78 79 priority: 6; 79 80 source: AppBskyGraphDefs.ListViewBasic | null; 80 81 ··· 82 83 } 83 84 84 85 export interface MutedTemporaryModerationCause { 85 - type: ModerationCauseType.MutedTemporary; 86 + type: typeof ModerationCauseType.MutedTemporary; 86 87 priority: 6; 87 88 88 89 downgraded: boolean; 89 90 } 90 91 91 92 export interface MutedKeywordModerationCause { 92 - type: ModerationCauseType.MutedKeyword; 93 + type: typeof ModerationCauseType.MutedKeyword; 93 94 priority: 6; 94 95 source: KeywordFilter; 95 96
+6 -5
packages/bluesky/moderation/lib/keyword-filter.ts
··· 51 51 return str.replace(ESCAPE_RE, '\\$&'); 52 52 }; 53 53 54 - export enum KeywordFilterFlags { 54 + export const KeywordFilterFlags = { 55 55 /** filter applies to content */ 56 - ApplyContent = 1 << 0, 56 + ApplyContent: 1 << 0, 57 57 /** filter applies to tags */ 58 - ApplyTopic = 1 << 1, 58 + ApplyTopic: 1 << 1, 59 59 /** filter shouldn't apply to following users */ 60 - NoFollowing = 1 << 2, 61 - } 60 + NoFollowing: 1 << 2, 61 + } as const; 62 + export type KeywordFilterFlags = (typeof KeywordFilterFlags)[keyof typeof KeywordFilterFlags]; 62 63 63 64 export interface KeywordFilter { 64 65 /** unique identifier for this filter */
+31 -27
packages/bluesky/moderation/lib/label.ts
··· 4 4 5 5 import { DisplayContext, LabelTarget, ModerationAction, type LabelBehaviorMatrix } from './behaviors.ts'; 6 6 7 - export enum LabelPreference { 7 + export const LabelPreference = { 8 8 /** ignore this label */ 9 - Ignore = 'ignore', 9 + Ignore: 'ignore', 10 10 /** warn when viewing content or profile with this label */ 11 - Warn = 'warn', 11 + Warn: 'warn', 12 12 /** hide content or profile containing this label */ 13 - Hide = 'hide', 14 - } 13 + Hide: 'hide', 14 + } as const; 15 + export type LabelPreference = (typeof LabelPreference)[keyof typeof LabelPreference]; 15 16 16 - export enum LabelFlags { 17 + export const LabelFlags = { 17 18 /** no flags */ 18 - None = 0, 19 + None: 0, 19 20 20 21 /** unblurring shouldn't be allowed */ 21 - NoOverride = 1 << 0, 22 + NoOverride: 1 << 0, 22 23 /** label can't be configured */ 23 - NoConfigurable = 1 << 1, 24 + NoConfigurable: 1 << 1, 24 25 /** label can't be applied as a self-label */ 25 - NoSelf = 1 << 2, 26 + NoSelf: 1 << 2, 26 27 /** label is adult-only */ 27 - AdultOnly = 1 << 3, 28 + AdultOnly: 1 << 3, 28 29 /** label can't be applied if authenticated */ 29 - UnauthenticatedOnly = 1 << 4, 30 - } 30 + UnauthenticatedOnly: 1 << 4, 31 + } as const; 32 + export type LabelFlags = (typeof LabelFlags)[keyof typeof LabelFlags]; 31 33 32 - export enum BlurLevel { 34 + export const BlurLevel = { 33 35 /** don't blur any parts of the content */ 34 - None = 'none', 36 + None: 'none', 35 37 /** only blur the media present in the content */ 36 - Media = 'media', 38 + Media: 'media', 37 39 /** blur the entire content */ 38 - Content = 'content', 40 + Content: 'content', 39 41 40 42 /** special blur value, guaranteed blurring of profile and content */ 41 - Forced = 'forced', 42 - } 43 + Forced: 'forced', 44 + } as const; 45 + export type BlurLevel = (typeof BlurLevel)[keyof typeof BlurLevel]; 43 46 44 - export enum SeverityLevel { 47 + export const SeverityLevel = { 45 48 /** don't inform the user */ 46 - None = 'none', 49 + None: 'none', 47 50 /** lightly inform the user about this label's presence */ 48 - Inform = 'inform', 51 + Inform: 'inform', 49 52 /** alert the user about this label's presence */ 50 - Alert = 'alert', 51 - } 53 + Alert: 'alert', 54 + } as const; 55 + export type SeverityLevel = (typeof SeverityLevel)[keyof typeof SeverityLevel]; 52 56 53 57 export interface LabelLocale { 54 58 /** language code */ ··· 253 257 export const interpretLabelValueDefinition = ( 254 258 def: ComAtprotoLabelDefs.LabelValueDefinition, 255 259 ): InterpretedLabelDefinition => { 256 - let defaultPref = LabelPreference.Warn; 257 - let blur = BlurLevel.None; 258 - let severity = SeverityLevel.None; 260 + let defaultPref: LabelPreference = LabelPreference.Warn; 261 + let blur: BlurLevel = BlurLevel.None; 262 + let severity: SeverityLevel = SeverityLevel.None; 259 263 let flags = LabelFlags.NoSelf; 260 264 261 265 switch (def.blurs) {
+2 -1
packages/bluesky/moderation/tsconfig.json
··· 21 21 "module": "NodeNext", 22 22 "sourceMap": true, 23 23 "declaration": true, 24 - "declarationMap": true 24 + "declarationMap": true, 25 + "erasableSyntaxOnly": true 25 26 }, 26 27 "include": ["lib"] 27 28 }