From 921229ed2d270d88720ff6de2b1c814391e30296 Mon Sep 17 00:00:00 2001 From: Wesley Finck Date: Fri, 23 Jan 2026 14:28:46 -0800 Subject: [PATCH] formatting and linting --- .../20260122_open_collection_removal_logic.md | 10 ++ .../ProcessCollectionFirehoseEventUseCase.ts | 8 +- ...llectionLinkRemovalFirehoseEventUseCase.ts | 3 +- .../useCases/ProcessFirehoseEventUseCase.ts | 4 +- .../atproto/infrastructure/lexicon/index.ts | 84 ++++++++--------- .../infrastructure/lexicon/lexicons.ts | 18 ++-- .../types/com/atproto/repo/strongRef.ts | 24 ++--- .../lexicon/types/network/cosmik/card.ts | 94 ++++++++++--------- .../types/network/cosmik/collection.ts | 38 ++++---- .../types/network/cosmik/collectionLink.ts | 44 +++++---- .../network/cosmik/collectionLinkRemoval.ts | 34 ++++--- .../lexicon/types/network/cosmik/defs.ts | 28 +++--- .../atproto/infrastructure/lexicon/util.ts | 32 +++---- .../cards/domain/ICardQueryRepository.ts | 7 +- .../http/routes/collectionRoutes.ts | 3 +- .../utils/InMemoryCardQueryRepository.ts | 7 +- 16 files changed, 241 insertions(+), 197 deletions(-) diff --git a/.agent/logs/20260122_open_collection_removal_logic.md b/.agent/logs/20260122_open_collection_removal_logic.md index 1a6dbb0b..208f4245 100644 --- a/.agent/logs/20260122_open_collection_removal_logic.md +++ b/.agent/logs/20260122_open_collection_removal_logic.md @@ -55,6 +55,7 @@ Created `src/modules/atproto/infrastructure/lexicons/collectionLinkRemoval.json` ``` **Design Notes:** + - No `removedBy` field - user identity is derived from the AT-URI of the removal record - No `reason` field - kept the schema minimal and focused - Uses StrongRef to ensure content-addressable references (URI + CID) @@ -64,6 +65,7 @@ Created `src/modules/atproto/infrastructure/lexicons/collectionLinkRemoval.json` ### Removal Permissions **For OPEN Collections:** + - ✅ Collection author can remove any card (including cards added by others) - ✅ Users can only remove cards they themselves added - ❌ Non-authors cannot remove cards added by others @@ -235,10 +237,12 @@ static toCreateRecordDTO( ## Files Modified ### Created + 1. `src/modules/atproto/infrastructure/lexicons/collectionLinkRemoval.json` - Lexicon schema 2. `src/modules/atproto/infrastructure/mappers/CollectionLinkRemovalMapper.ts` - Mapper for removal records ### Modified + 1. `src/modules/cards/domain/Collection.ts` - Updated `removeCard()` method with proper permissions 2. `src/modules/cards/domain/services/CardCollectionService.ts` - Updated removal logic with publishing decisions 3. `src/modules/cards/application/ports/ICollectionPublisher.ts` - Added `publishCollectionLinkRemoval` method signature @@ -249,11 +253,13 @@ static toCreateRecordDTO( 8. `src/modules/cards/tests/application/RemoveCardFromCollectionUseCase.test.ts` - Updated/added tests ### Generated + - TypeScript types regenerated via `npm run lexgen` ## Test Coverage ### Test Results + - ✅ 20 tests passed in RemoveCardFromCollectionUseCase - ✅ 2 tests skipped (CLOSED collections with collaborators - out of scope) - ✅ 148 total collection-related tests passed @@ -268,6 +274,7 @@ static toCreateRecordDTO( ### Skipped Tests (Out of Scope) The following tests were skipped as CLOSED collection scenarios with collaborators are deferred: + - `should allow collaborator to remove cards from closed collection` - `should handle mixed collection permissions when removing cards` @@ -283,12 +290,15 @@ This ensures business rules are properly encapsulated in the domain model where ## Future Work ### CLOSED Collections with Collaborators + Deferred for future implementation: + - How collaborators can remove cards from CLOSED collections - Whether collaborators can remove any card or only their own - Permission rules for multi-user CLOSED collection scenarios ### Potential Enhancements + - Add a `reason` field to collectionLinkRemoval for moderation use cases - Implement bulk removal operations - Add notifications when cards are removed from collections diff --git a/src/modules/atproto/application/useCases/ProcessCollectionFirehoseEventUseCase.ts b/src/modules/atproto/application/useCases/ProcessCollectionFirehoseEventUseCase.ts index 6cb7ced3..9081a8ac 100644 --- a/src/modules/atproto/application/useCases/ProcessCollectionFirehoseEventUseCase.ts +++ b/src/modules/atproto/application/useCases/ProcessCollectionFirehoseEventUseCase.ts @@ -85,7 +85,9 @@ export class ProcessCollectionFirehoseEventUseCase const result = await this.createCollectionUseCase.execute({ name: request.record.name, description: request.record.description, - accessType: request.record.accessType as CollectionAccessType | undefined, + accessType: request.record.accessType as + | CollectionAccessType + | undefined, curatorId: authorDid, publishedRecordId: publishedRecordId, }); @@ -170,7 +172,9 @@ export class ProcessCollectionFirehoseEventUseCase collectionId: collectionIdResult.value.getStringValue(), name: request.record.name, description: request.record.description, - accessType: request.record.accessType as CollectionAccessType | undefined, + accessType: request.record.accessType as + | CollectionAccessType + | undefined, curatorId: authorDid, publishedRecordId: publishedRecordId, }); diff --git a/src/modules/atproto/application/useCases/ProcessCollectionLinkRemovalFirehoseEventUseCase.ts b/src/modules/atproto/application/useCases/ProcessCollectionLinkRemovalFirehoseEventUseCase.ts index 8db549fb..0d3a8b2d 100644 --- a/src/modules/atproto/application/useCases/ProcessCollectionLinkRemovalFirehoseEventUseCase.ts +++ b/src/modules/atproto/application/useCases/ProcessCollectionLinkRemovalFirehoseEventUseCase.ts @@ -19,8 +19,7 @@ export interface ProcessCollectionLinkRemovalFirehoseEventDTO { const ENABLE_FIREHOSE_LOGGING = true; export class ProcessCollectionLinkRemovalFirehoseEventUseCase - implements - UseCase> + implements UseCase> { constructor( private atUriResolutionService: IAtUriResolutionService, diff --git a/src/modules/atproto/application/useCases/ProcessFirehoseEventUseCase.ts b/src/modules/atproto/application/useCases/ProcessFirehoseEventUseCase.ts index 6215255b..b321bc78 100644 --- a/src/modules/atproto/application/useCases/ProcessFirehoseEventUseCase.ts +++ b/src/modules/atproto/application/useCases/ProcessFirehoseEventUseCase.ts @@ -137,7 +137,9 @@ export class ProcessFirehoseEventUseCase !removalRecord.removedAt ) { return err( - new ValidationError('Invalid collection link removal record structure'), + new ValidationError( + 'Invalid collection link removal record structure', + ), ); } } diff --git a/src/modules/atproto/infrastructure/lexicon/index.ts b/src/modules/atproto/infrastructure/lexicon/index.ts index 9d24d6c3..21d14790 100644 --- a/src/modules/atproto/infrastructure/lexicon/index.ts +++ b/src/modules/atproto/infrastructure/lexicon/index.ts @@ -7,93 +7,93 @@ import { type Options as XrpcOptions, type AuthVerifier, type StreamAuthVerifier, -} from '@atproto/xrpc-server' -import { schemas } from './lexicons.js' +} from '@atproto/xrpc-server'; +import { schemas } from './lexicons.js'; export function createServer(options?: XrpcOptions): Server { - return new Server(options) + return new Server(options); } export class Server { - xrpc: XrpcServer - network: NetworkNS - com: ComNS + xrpc: XrpcServer; + network: NetworkNS; + com: ComNS; constructor(options?: XrpcOptions) { - this.xrpc = createXrpcServer(schemas, options) - this.network = new NetworkNS(this) - this.com = new ComNS(this) + this.xrpc = createXrpcServer(schemas, options); + this.network = new NetworkNS(this); + this.com = new ComNS(this); } } export class NetworkNS { - _server: Server - cosmik: NetworkCosmikNS + _server: Server; + cosmik: NetworkCosmikNS; constructor(server: Server) { - this._server = server - this.cosmik = new NetworkCosmikNS(server) + this._server = server; + this.cosmik = new NetworkCosmikNS(server); } } export class NetworkCosmikNS { - _server: Server + _server: Server; constructor(server: Server) { - this._server = server + this._server = server; } } export class ComNS { - _server: Server - atproto: ComAtprotoNS + _server: Server; + atproto: ComAtprotoNS; constructor(server: Server) { - this._server = server - this.atproto = new ComAtprotoNS(server) + this._server = server; + this.atproto = new ComAtprotoNS(server); } } export class ComAtprotoNS { - _server: Server - repo: ComAtprotoRepoNS + _server: Server; + repo: ComAtprotoRepoNS; constructor(server: Server) { - this._server = server - this.repo = new ComAtprotoRepoNS(server) + this._server = server; + this.repo = new ComAtprotoRepoNS(server); } } export class ComAtprotoRepoNS { - _server: Server + _server: Server; constructor(server: Server) { - this._server = server + this._server = server; } } type SharedRateLimitOpts = { - name: string - calcKey?: (ctx: T) => string | null - calcPoints?: (ctx: T) => number -} + name: string; + calcKey?: (ctx: T) => string | null; + calcPoints?: (ctx: T) => number; +}; type RouteRateLimitOpts = { - durationMs: number - points: number - calcKey?: (ctx: T) => string | null - calcPoints?: (ctx: T) => number -} -type HandlerOpts = { blobLimit?: number } -type HandlerRateLimitOpts = SharedRateLimitOpts | RouteRateLimitOpts + durationMs: number; + points: number; + calcKey?: (ctx: T) => string | null; + calcPoints?: (ctx: T) => number; +}; +type HandlerOpts = { blobLimit?: number }; +type HandlerRateLimitOpts = SharedRateLimitOpts | RouteRateLimitOpts; type ConfigOf = | Handler | { - auth?: Auth - opts?: HandlerOpts - rateLimit?: HandlerRateLimitOpts | HandlerRateLimitOpts[] - handler: Handler - } + auth?: Auth; + opts?: HandlerOpts; + rateLimit?: HandlerRateLimitOpts | HandlerRateLimitOpts[]; + handler: Handler; + }; type ExtractAuth = Extract< Awaited>, { credentials: unknown } -> +>; diff --git a/src/modules/atproto/infrastructure/lexicon/lexicons.ts b/src/modules/atproto/infrastructure/lexicon/lexicons.ts index e198eb74..75b0370d 100644 --- a/src/modules/atproto/infrastructure/lexicon/lexicons.ts +++ b/src/modules/atproto/infrastructure/lexicon/lexicons.ts @@ -6,8 +6,8 @@ import { Lexicons, ValidationError, type ValidationResult, -} from '@atproto/lexicon' -import { type $Typed, is$typed, maybe$typed } from './util.js' +} from '@atproto/lexicon'; +import { type $Typed, is$typed, maybe$typed } from './util.js'; export const schemaDict = { NetworkCosmikCard: { @@ -337,22 +337,22 @@ export const schemaDict = { }, }, }, -} as const satisfies Record -export const schemas = Object.values(schemaDict) satisfies LexiconDoc[] -export const lexicons: Lexicons = new Lexicons(schemas) +} as const satisfies Record; +export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]; +export const lexicons: Lexicons = new Lexicons(schemas); export function validate( v: unknown, id: string, hash: string, requiredType: true, -): ValidationResult +): ValidationResult; export function validate( v: unknown, id: string, hash: string, requiredType?: false, -): ValidationResult +): ValidationResult; export function validate( v: unknown, id: string, @@ -366,7 +366,7 @@ export function validate( error: new ValidationError( `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`, ), - } + }; } export const ids = { @@ -376,4 +376,4 @@ export const ids = { NetworkCosmikCollectionLinkRemoval: 'network.cosmik.collectionLinkRemoval', NetworkCosmikDefs: 'network.cosmik.defs', ComAtprotoRepoStrongRef: 'com.atproto.repo.strongRef', -} as const +} as const; diff --git a/src/modules/atproto/infrastructure/lexicon/types/com/atproto/repo/strongRef.ts b/src/modules/atproto/infrastructure/lexicon/types/com/atproto/repo/strongRef.ts index eac0bc16..e0149a5b 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/com/atproto/repo/strongRef.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/com/atproto/repo/strongRef.ts @@ -1,31 +1,31 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../../lexicons' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../../lexicons'; import { type $Typed, is$typed as _is$typed, type OmitKey, -} from '../../../../util' +} from '../../../../util'; const is$typed = _is$typed, - validate = _validate -const id = 'com.atproto.repo.strongRef' + validate = _validate; +const id = 'com.atproto.repo.strongRef'; export interface Main { - $type?: 'com.atproto.repo.strongRef' - cid: string - uri: string + $type?: 'com.atproto.repo.strongRef'; + cid: string; + uri: string; } -const hashMain = 'main' +const hashMain = 'main'; export function isMain(v: V) { - return is$typed(v, id, hashMain) + return is$typed(v, id, hashMain); } export function validateMain(v: V) { - return validate
(v, id, hashMain) + return validate
(v, id, hashMain); } diff --git a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/card.ts b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/card.ts index ebf4c1af..7455e1aa 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/card.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/card.ts @@ -1,108 +1,112 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' -import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js' -import type * as NetworkCosmikDefs from './defs.js' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../lexicons'; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../util'; +import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js'; +import type * as NetworkCosmikDefs from './defs.js'; const is$typed = _is$typed, - validate = _validate -const id = 'network.cosmik.card' + validate = _validate; +const id = 'network.cosmik.card'; export interface Record { - $type: 'network.cosmik.card' + $type: 'network.cosmik.card'; /** The type of card */ - type: 'URL' | 'NOTE' | (string & {}) - content: $Typed | $Typed | { $type: string } + type: 'URL' | 'NOTE' | (string & {}); + content: $Typed | $Typed | { $type: string }; /** Optional URL associated with the card. Required for URL cards, optional for NOTE cards. */ - url?: string - parentCard?: ComAtprotoRepoStrongRef.Main + url?: string; + parentCard?: ComAtprotoRepoStrongRef.Main; /** Timestamp when this card was created (usually set by PDS). */ - createdAt?: string - originalCard?: ComAtprotoRepoStrongRef.Main - provenance?: NetworkCosmikDefs.Provenance - [k: string]: unknown + createdAt?: string; + originalCard?: ComAtprotoRepoStrongRef.Main; + provenance?: NetworkCosmikDefs.Provenance; + [k: string]: unknown; } -const hashRecord = 'main' +const hashRecord = 'main'; export function isRecord(v: V) { - return is$typed(v, id, hashRecord) + return is$typed(v, id, hashRecord); } export function validateRecord(v: V) { - return validate(v, id, hashRecord, true) + return validate(v, id, hashRecord, true); } /** Content structure for a URL card. */ export interface UrlContent { - $type?: 'network.cosmik.card#urlContent' + $type?: 'network.cosmik.card#urlContent'; /** The URL being saved */ - url: string - metadata?: UrlMetadata + url: string; + metadata?: UrlMetadata; } -const hashUrlContent = 'urlContent' +const hashUrlContent = 'urlContent'; export function isUrlContent(v: V) { - return is$typed(v, id, hashUrlContent) + return is$typed(v, id, hashUrlContent); } export function validateUrlContent(v: V) { - return validate(v, id, hashUrlContent) + return validate(v, id, hashUrlContent); } /** Content structure for a note card. */ export interface NoteContent { - $type?: 'network.cosmik.card#noteContent' + $type?: 'network.cosmik.card#noteContent'; /** The note text content */ - text: string + text: string; } -const hashNoteContent = 'noteContent' +const hashNoteContent = 'noteContent'; export function isNoteContent(v: V) { - return is$typed(v, id, hashNoteContent) + return is$typed(v, id, hashNoteContent); } export function validateNoteContent(v: V) { - return validate(v, id, hashNoteContent) + return validate(v, id, hashNoteContent); } /** Metadata about a URL. */ export interface UrlMetadata { - $type?: 'network.cosmik.card#urlMetadata' + $type?: 'network.cosmik.card#urlMetadata'; /** Title of the page */ - title?: string + title?: string; /** Description of the page */ - description?: string + description?: string; /** Author of the content */ - author?: string + author?: string; /** When the content was published */ - publishedDate?: string + publishedDate?: string; /** Name of the site */ - siteName?: string + siteName?: string; /** URL of a representative image */ - imageUrl?: string + imageUrl?: string; /** Type of content (e.g., 'video', 'article') */ - type?: string + type?: string; /** When the metadata was retrieved */ - retrievedAt?: string + retrievedAt?: string; /** Digital Object Identifier (DOI) for academic content */ - doi?: string + doi?: string; /** International Standard Book Number (ISBN) for books */ - isbn?: string + isbn?: string; } -const hashUrlMetadata = 'urlMetadata' +const hashUrlMetadata = 'urlMetadata'; export function isUrlMetadata(v: V) { - return is$typed(v, id, hashUrlMetadata) + return is$typed(v, id, hashUrlMetadata); } export function validateUrlMetadata(v: V) { - return validate(v, id, hashUrlMetadata) + return validate(v, id, hashUrlMetadata); } diff --git a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collection.ts b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collection.ts index ee696f15..06751324 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collection.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collection.ts @@ -1,38 +1,42 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../lexicons'; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../util'; const is$typed = _is$typed, - validate = _validate -const id = 'network.cosmik.collection' + validate = _validate; +const id = 'network.cosmik.collection'; export interface Record { - $type: 'network.cosmik.collection' + $type: 'network.cosmik.collection'; /** Name of the collection */ - name: string + name: string; /** Description of the collection */ - description?: string + description?: string; /** Access control for the collection */ - accessType: 'OPEN' | 'CLOSED' | (string & {}) + accessType: 'OPEN' | 'CLOSED' | (string & {}); /** List of collaborator DIDs who can add cards to closed collections */ - collaborators?: string[] + collaborators?: string[]; /** Timestamp when this collection was created (usually set by PDS). */ - createdAt?: string + createdAt?: string; /** Timestamp when this collection was last updated. */ - updatedAt?: string - [k: string]: unknown + updatedAt?: string; + [k: string]: unknown; } -const hashRecord = 'main' +const hashRecord = 'main'; export function isRecord(v: V) { - return is$typed(v, id, hashRecord) + return is$typed(v, id, hashRecord); } export function validateRecord(v: V) { - return validate(v, id, hashRecord, true) + return validate(v, id, hashRecord, true); } diff --git a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLink.ts b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLink.ts index 0ba065ea..2a747a73 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLink.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLink.ts @@ -1,38 +1,42 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' -import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js' -import type * as NetworkCosmikDefs from './defs.js' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../lexicons'; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../util'; +import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js'; +import type * as NetworkCosmikDefs from './defs.js'; const is$typed = _is$typed, - validate = _validate -const id = 'network.cosmik.collectionLink' + validate = _validate; +const id = 'network.cosmik.collectionLink'; export interface Record { - $type: 'network.cosmik.collectionLink' - collection: ComAtprotoRepoStrongRef.Main - card: ComAtprotoRepoStrongRef.Main - originalCard?: ComAtprotoRepoStrongRef.Main + $type: 'network.cosmik.collectionLink'; + collection: ComAtprotoRepoStrongRef.Main; + card: ComAtprotoRepoStrongRef.Main; + originalCard?: ComAtprotoRepoStrongRef.Main; /** DID of the user who added the card to the collection */ - addedBy: string + addedBy: string; /** Timestamp when the card was added to the collection. */ - addedAt: string + addedAt: string; /** Timestamp when this link record was created (usually set by PDS). */ - createdAt?: string - provenance?: NetworkCosmikDefs.Provenance - [k: string]: unknown + createdAt?: string; + provenance?: NetworkCosmikDefs.Provenance; + [k: string]: unknown; } -const hashRecord = 'main' +const hashRecord = 'main'; export function isRecord(v: V) { - return is$typed(v, id, hashRecord) + return is$typed(v, id, hashRecord); } export function validateRecord(v: V) { - return validate(v, id, hashRecord, true) + return validate(v, id, hashRecord, true); } diff --git a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLinkRemoval.ts b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLinkRemoval.ts index a396ac41..cc742591 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLinkRemoval.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/collectionLinkRemoval.ts @@ -1,31 +1,35 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' -import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../lexicons'; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../util'; +import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js'; const is$typed = _is$typed, - validate = _validate -const id = 'network.cosmik.collectionLinkRemoval' + validate = _validate; +const id = 'network.cosmik.collectionLinkRemoval'; export interface Record { - $type: 'network.cosmik.collectionLinkRemoval' - collection: ComAtprotoRepoStrongRef.Main - removedLink: ComAtprotoRepoStrongRef.Main + $type: 'network.cosmik.collectionLinkRemoval'; + collection: ComAtprotoRepoStrongRef.Main; + removedLink: ComAtprotoRepoStrongRef.Main; /** Timestamp when the link was removed from the collection. */ - removedAt: string - [k: string]: unknown + removedAt: string; + [k: string]: unknown; } -const hashRecord = 'main' +const hashRecord = 'main'; export function isRecord(v: V) { - return is$typed(v, id, hashRecord) + return is$typed(v, id, hashRecord); } export function validateRecord(v: V) { - return validate(v, id, hashRecord, true) + return validate(v, id, hashRecord, true); } diff --git a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/defs.ts b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/defs.ts index d81b1c7e..b2176f46 100644 --- a/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/defs.ts +++ b/src/modules/atproto/infrastructure/lexicon/types/network/cosmik/defs.ts @@ -1,28 +1,32 @@ /** * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult, BlobRef } from '@atproto/lexicon' -import { CID } from 'multiformats/cid' -import { validate as _validate } from '../../../lexicons' -import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' -import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js' +import { type ValidationResult, BlobRef } from '@atproto/lexicon'; +import { CID } from 'multiformats/cid'; +import { validate as _validate } from '../../../lexicons'; +import { + type $Typed, + is$typed as _is$typed, + type OmitKey, +} from '../../../util'; +import type * as ComAtprotoRepoStrongRef from '../../com/atproto/repo/strongRef.js'; const is$typed = _is$typed, - validate = _validate -const id = 'network.cosmik.defs' + validate = _validate; +const id = 'network.cosmik.defs'; /** Represents the provenance or source of a record. */ export interface Provenance { - $type?: 'network.cosmik.defs#provenance' - via?: ComAtprotoRepoStrongRef.Main + $type?: 'network.cosmik.defs#provenance'; + via?: ComAtprotoRepoStrongRef.Main; } -const hashProvenance = 'provenance' +const hashProvenance = 'provenance'; export function isProvenance(v: V) { - return is$typed(v, id, hashProvenance) + return is$typed(v, id, hashProvenance); } export function validateProvenance(v: V) { - return validate(v, id, hashProvenance) + return validate(v, id, hashProvenance); } diff --git a/src/modules/atproto/infrastructure/lexicon/util.ts b/src/modules/atproto/infrastructure/lexicon/util.ts index 816ca10c..f7e33604 100644 --- a/src/modules/atproto/infrastructure/lexicon/util.ts +++ b/src/modules/atproto/infrastructure/lexicon/util.ts @@ -2,21 +2,21 @@ * GENERATED CODE - DO NOT MODIFY */ -import { type ValidationResult } from '@atproto/lexicon' +import { type ValidationResult } from '@atproto/lexicon'; export type OmitKey = { - [K2 in keyof T as K2 extends K ? never : K2]: T[K2] -} + [K2 in keyof T as K2 extends K ? never : K2]: T[K2]; +}; -export type $Typed = V & { $type: T } -export type Un$Typed = OmitKey +export type $Typed = V & { $type: T }; +export type Un$Typed = OmitKey; export type $Type = Hash extends 'main' ? Id - : `${Id}#${Hash}` + : `${Id}#${Hash}`; function isObject(v: V): v is V & object { - return v != null && typeof v === 'object' + return v != null && typeof v === 'object'; } function is$type( @@ -31,7 +31,7 @@ function is$type( $type.length === id.length + 1 + hash.length && $type.charCodeAt(id.length) === 35 /* '#' */ && $type.startsWith(id) && - $type.endsWith(hash) + $type.endsWith(hash); } export type $TypedObject< @@ -39,21 +39,21 @@ export type $TypedObject< Id extends string, Hash extends string, > = V extends { - $type: $Type + $type: $Type; } ? V : V extends { $type?: string } ? V extends { $type?: infer T extends $Type } ? V & { $type: T } : never - : V & { $type: $Type } + : V & { $type: $Type }; export function is$typed( v: V, id: Id, hash: Hash, ): v is $TypedObject { - return isObject(v) && '$type' in v && is$type(v.$type, id, hash) + return isObject(v) && '$type' in v && is$type(v.$type, id, hash); } export function maybe$typed( @@ -64,12 +64,12 @@ export function maybe$typed( return ( isObject(v) && ('$type' in v ? v.$type === undefined || is$type(v.$type, id, hash) : true) - ) + ); } -export type Validator = (v: unknown) => ValidationResult +export type Validator = (v: unknown) => ValidationResult; export type ValidatorParam = - V extends Validator ? R : never + V extends Validator ? R : never; /** * Utility function that allows to convert a "validate*" utility function into a @@ -77,6 +77,6 @@ export type ValidatorParam = */ export function asPredicate(validate: V) { return function (v: T): v is T & ValidatorParam { - return validate(v).success - } + return validate(v).success; + }; } diff --git a/src/modules/cards/domain/ICardQueryRepository.ts b/src/modules/cards/domain/ICardQueryRepository.ts index 31e6598e..163d88e4 100644 --- a/src/modules/cards/domain/ICardQueryRepository.ts +++ b/src/modules/cards/domain/ICardQueryRepository.ts @@ -59,7 +59,12 @@ export interface UrlCardView { export type CollectionCardQueryResultDTO = UrlCardView; // Raw data from repository - minimal, just what's stored export interface WithCollections { - collections: { id: string; name: string; authorId: string; accessType: string }[]; + collections: { + id: string; + name: string; + authorId: string; + accessType: string; + }[]; } export interface WithLibraries { diff --git a/src/modules/cards/infrastructure/http/routes/collectionRoutes.ts b/src/modules/cards/infrastructure/http/routes/collectionRoutes.ts index a6d0898f..9af6ac4f 100644 --- a/src/modules/cards/infrastructure/http/routes/collectionRoutes.ts +++ b/src/modules/cards/infrastructure/http/routes/collectionRoutes.ts @@ -51,8 +51,7 @@ export function createCollectionRoutes( router.get( '/contributed/:identifier', authMiddleware.optionalAuth(), - (req, res) => - getOpenCollectionsWithContributorController.execute(req, res), + (req, res) => getOpenCollectionsWithContributorController.execute(req, res), ); // GET /api/collections/at/:handle/:recordKey - Get collection by AT URI diff --git a/src/modules/cards/tests/utils/InMemoryCardQueryRepository.ts b/src/modules/cards/tests/utils/InMemoryCardQueryRepository.ts index 17ab7775..80786021 100644 --- a/src/modules/cards/tests/utils/InMemoryCardQueryRepository.ts +++ b/src/modules/cards/tests/utils/InMemoryCardQueryRepository.ts @@ -110,7 +110,12 @@ export class InMemoryCardQueryRepository implements ICardQueryRepository { // Find collections this card belongs to by querying the collection repository const allCollections = this.collectionRepository.getAllCollections(); - const collections: { id: string; name: string; authorId: string; accessType: string }[] = []; + const collections: { + id: string; + name: string; + authorId: string; + accessType: string; + }[] = []; for (const collection of allCollections) { if ( -- 2.51.2