diff --git a/src/modules/atproto/application/useCases/ProcessMarginCollectionItemFirehoseEventUseCase.ts b/src/modules/atproto/application/useCases/ProcessMarginCollectionItemFirehoseEventUseCase.ts index b7bea7de..d9413ee8 100644 --- a/src/modules/atproto/application/useCases/ProcessMarginCollectionItemFirehoseEventUseCase.ts +++ b/src/modules/atproto/application/useCases/ProcessMarginCollectionItemFirehoseEventUseCase.ts @@ -9,6 +9,7 @@ import { UpdateUrlCardAssociationsUseCase, OperationContext, } from '../../../cards/application/useCases/commands/UpdateUrlCardAssociationsUseCase'; +import { ATPROTO_NSID } from 'src/shared/constants/atproto'; export interface ProcessMarginCollectionItemFirehoseEventDTO { atUri: string; @@ -96,7 +97,7 @@ export class ProcessMarginCollectionItemFirehoseEventUseCase } const annotationCollection = annotationUriResult.value.collection; - if (annotationCollection !== 'at.margin.bookmark') { + if (annotationCollection !== ATPROTO_NSID.MARGIN.BOOKMARK) { if (ENABLE_FIREHOSE_LOGGING) { console.log( `[FirehoseWorker] Ignoring Margin collection item for non-bookmark annotation type: ${annotationCollection}, itemUri: ${request.atUri}`, diff --git a/src/modules/feeds/application/useCases/commands/AddActivityToFeedUseCase.ts b/src/modules/feeds/application/useCases/commands/AddActivityToFeedUseCase.ts index 3a663bf8..3655cbab 100644 --- a/src/modules/feeds/application/useCases/commands/AddActivityToFeedUseCase.ts +++ b/src/modules/feeds/application/useCases/commands/AddActivityToFeedUseCase.ts @@ -8,6 +8,8 @@ import { CollectionId } from '../../../../cards/domain/value-objects/CollectionI import { ActivityTypeEnum } from '../../../domain/value-objects/ActivityType'; import { FeedService } from 'src/modules/feeds/domain/services/FeedService'; import { ICardRepository } from '../../../../cards/domain/ICardRepository'; +import { SourceTypeEnum } from '../../../domain/value-objects/SourceType'; +import { ATPROTO_NSID } from '../../../../../shared/constants/atproto'; export interface AddCardCollectedActivityDTO { type: ActivityTypeEnum.CARD_COLLECTED; @@ -117,8 +119,8 @@ export class AddActivityToFeedUseCase const libraryInfo = cardResult.value.getLibraryInfo(actorId); if (libraryInfo?.publishedRecordId) { const uri = libraryInfo.publishedRecordId.uri; - if (uri.includes('/at.margin.')) { - source = 'margin'; + if (uri.includes(`/${ATPROTO_NSID.MARGIN.NAMESPACE}.`)) { + source = SourceTypeEnum.MARGIN; } // Cosmik activities remain undefined (default) } diff --git a/src/modules/feeds/domain/value-objects/SourceType.ts b/src/modules/feeds/domain/value-objects/SourceType.ts new file mode 100644 index 00000000..0990a8d8 --- /dev/null +++ b/src/modules/feeds/domain/value-objects/SourceType.ts @@ -0,0 +1,43 @@ +import { ValueObject } from '../../../../shared/domain/ValueObject'; +import { Result, ok, err } from '../../../../shared/core/Result'; + +export enum SourceTypeEnum { + MARGIN = 'margin', +} + +export class SourceTypeError extends Error { + constructor(message: string) { + super(message); + this.name = 'SourceTypeError'; + } +} + +interface SourceTypeProps { + value: SourceTypeEnum; +} + +export class SourceType extends ValueObject { + get value(): SourceTypeEnum { + return this.props.value; + } + + private constructor(props: SourceTypeProps) { + super(props); + } + + public static create(value: string): Result { + if (!Object.values(SourceTypeEnum).includes(value as SourceTypeEnum)) { + return err(new SourceTypeError(`Invalid source type: ${value}`)); + } + + return ok(new SourceType({ value: value as SourceTypeEnum })); + } + + public static margin(): Result { + return ok(new SourceType({ value: SourceTypeEnum.MARGIN })); + } + + public toString(): string { + return this.props.value; + } +} diff --git a/src/shared/constants/atproto.ts b/src/shared/constants/atproto.ts new file mode 100644 index 00000000..9ce1c725 --- /dev/null +++ b/src/shared/constants/atproto.ts @@ -0,0 +1,18 @@ +/** + * AT Protocol NSID constants + * Namespaced identifiers for AT Protocol collections + */ +export const ATPROTO_NSID = { + MARGIN: { + NAMESPACE: 'at.margin', + BOOKMARK: 'at.margin.bookmark', + COLLECTION: 'at.margin.collection', + COLLECTION_ITEM: 'at.margin.collectionItem', + }, + COSMIK: { + NAMESPACE: 'network.cosmik', + CARD: 'network.cosmik.card', + COLLECTION: 'network.cosmik.collection', + COLLECTION_LINK: 'network.cosmik.collectionLink', + }, +} as const; diff --git a/src/shared/infrastructure/config/EnvironmentConfigService.ts b/src/shared/infrastructure/config/EnvironmentConfigService.ts index 92fa5bb9..9d82e0e1 100644 --- a/src/shared/infrastructure/config/EnvironmentConfigService.ts +++ b/src/shared/infrastructure/config/EnvironmentConfigService.ts @@ -1,3 +1,5 @@ +import { ATPROTO_NSID } from 'src/shared/constants/atproto'; + export enum Environment { LOCAL = 'local', DEV = 'dev', @@ -106,25 +108,25 @@ export class EnvironmentConfigService { baseUrl: process.env.BASE_URL || 'http://127.0.0.1:3000', baseCollection: environment === Environment.PROD - ? 'network.cosmik' - : `network.cosmik.${environment}`, + ? ATPROTO_NSID.COSMIK.NAMESPACE + : `${ATPROTO_NSID.COSMIK.NAMESPACE}.${environment}`, collections: { card: environment === Environment.PROD - ? 'network.cosmik.card' - : `network.cosmik.${environment}.card`, + ? ATPROTO_NSID.COSMIK.CARD + : `${ATPROTO_NSID.COSMIK.NAMESPACE}.${environment}.card`, collection: environment === Environment.PROD - ? 'network.cosmik.collection' - : `network.cosmik.${environment}.collection`, + ? ATPROTO_NSID.COSMIK.COLLECTION + : `${ATPROTO_NSID.COSMIK.NAMESPACE}.${environment}.collection`, collectionLink: environment === Environment.PROD - ? 'network.cosmik.collectionLink' - : `network.cosmik.${environment}.collectionLink`, + ? ATPROTO_NSID.COSMIK.COLLECTION_LINK + : `${ATPROTO_NSID.COSMIK.NAMESPACE}.${environment}.collectionLink`, // Margin collections - no environment suffix - marginBookmark: 'at.margin.bookmark', - marginCollection: 'at.margin.collection', - marginCollectionItem: 'at.margin.collectionItem', + marginBookmark: ATPROTO_NSID.MARGIN.BOOKMARK, + marginCollection: ATPROTO_NSID.MARGIN.COLLECTION, + marginCollectionItem: ATPROTO_NSID.MARGIN.COLLECTION_ITEM, }, serviceAccount: { identifier: process.env.BSKY_SERVICE_ACCOUNT_IDENTIFIER || '',