-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Paul Le Cam
committed
Apr 15, 2024
1 parent
4f7821b
commit ad6bbb6
Showing
6 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import type { BaseQuery } from '@ceramicnetwork/common' | ||
import { DocumentLoader } from '@composedb/loader' | ||
import type { CeramicAPI } from '@composedb/types' | ||
import type { PointsContent } from '@ceramic-solutions/points-composite' | ||
|
||
import { getCeramic } from './ceramic.js' | ||
import { getQueryForRecipient, queryConnection } from './query.js' | ||
import type { QueryDocumentsOptions, QueryDocumentsResult } from './types.js' | ||
|
||
export type PointsBaseReaderParams = { | ||
issuer: string | ||
modelID: string | ||
ceramic?: CeramicAPI | string | ||
loader?: DocumentLoader | ||
} | ||
|
||
export class PointsBaseReader<Content extends PointsContent = PointsContent> { | ||
#baseQuery: BaseQuery | ||
#issuer: string | ||
#ceramic: CeramicAPI | ||
#loader: DocumentLoader | ||
#modelID: string | ||
|
||
constructor(params: PointsBaseReaderParams) { | ||
const ceramic = getCeramic(params.ceramic) | ||
this.#baseQuery = { account: params.issuer, models: [params.modelID] } | ||
this.#modelID = params.modelID | ||
this.#ceramic = ceramic | ||
this.#issuer = params.issuer | ||
this.#loader = params.loader ?? new DocumentLoader({ ceramic }) | ||
} | ||
|
||
get issuer(): string { | ||
return this.#issuer | ||
} | ||
|
||
get modelID(): string { | ||
return this.#modelID | ||
} | ||
|
||
get ceramic(): CeramicAPI { | ||
return this.#ceramic | ||
} | ||
|
||
get loader(): DocumentLoader { | ||
return this.#loader | ||
} | ||
|
||
async queryDocuments(options?: QueryDocumentsOptions): Promise<QueryDocumentsResult<Content>> { | ||
return await queryConnection(this.#loader, this.#baseQuery, options) | ||
} | ||
|
||
async queryDocumentsFor( | ||
did: string, | ||
options?: QueryDocumentsOptions, | ||
): Promise<QueryDocumentsResult<Content>> { | ||
const query = getQueryForRecipient(this.#baseQuery, did) | ||
return await queryConnection(this.#loader, query, options) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,18 @@ | ||
import { CeramicClient } from '@ceramicnetwork/http-client' | ||
import type { CeramicAPI } from '@composedb/types' | ||
|
||
import { getAuthenticatedDID } from './did.js' | ||
|
||
export function getCeramic(ceramic?: CeramicAPI | string): CeramicAPI { | ||
return ceramic == null || typeof ceramic === 'string' ? new CeramicClient(ceramic) : ceramic | ||
} | ||
|
||
export async function getAuthenticatedCeramic( | ||
seed: Uint8Array, | ||
ceramicClientOrURL?: CeramicAPI | string, | ||
): Promise<CeramicAPI> { | ||
const ceramic = getCeramic(ceramicClientOrURL) | ||
const did = await getAuthenticatedDID(seed) | ||
ceramic.did = did | ||
return ceramic | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import type { CeramicAPI, ModelInstanceDocument } from '@composedb/types' | ||
import type { PointsContent } from '@ceramic-solutions/points-composite' | ||
|
||
import { getAuthenticatedCeramic } from './ceramic.js' | ||
import { PointsBaseReader, type PointsBaseReaderParams } from './base-reader.js' | ||
|
||
export type PointsListWriterFromSeedParams = PointsBaseReaderParams & { | ||
seed: Uint8Array | ||
} | ||
|
||
export type PointsListWriterParams = Omit<PointsBaseReaderParams, 'ceramic'> & { | ||
ceramic: CeramicAPI | ||
} | ||
|
||
export class PointsListWriter< | ||
Content extends PointsContent = PointsContent, | ||
> extends PointsBaseReader<Content> { | ||
static async fromSeed<Content extends PointsContent = PointsContent>( | ||
params: PointsListWriterFromSeedParams, | ||
): Promise<PointsListWriter<Content>> { | ||
const ceramic = await getAuthenticatedCeramic(params.seed, params.ceramic) | ||
return new PointsListWriter({ ...params, ceramic }) | ||
} | ||
|
||
constructor(params: PointsListWriterParams) { | ||
if (!params.ceramic.did?.authenticated) { | ||
throw new Error(`An authenticated DID instance must be set on the Ceramic client`) | ||
} | ||
super({ ...params, issuer: params.ceramic.did.id }) | ||
} | ||
|
||
async createDocument(content: Content): Promise<ModelInstanceDocument<Content>> { | ||
return await this.loader.create(this.modelID, content) | ||
} | ||
|
||
async removeDocument(id: string): Promise<void> { | ||
const doc = await this.loader.load({ id }) | ||
if (doc.metadata.model.toString() !== this.modelID) { | ||
throw new Error(`Document ${id} is not using the expected model ${this.modelID}`) | ||
} | ||
await doc.shouldIndex(false) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { DeterministicLoadOptions } from '@composedb/loader' | ||
import type { ModelInstanceDocument } from '@composedb/types' | ||
import type { PointsContent } from '@ceramic-solutions/points-composite' | ||
|
||
import { PointsBaseReader, type PointsBaseReaderParams } from './base-reader.js' | ||
|
||
export function toUniqueArg(value: string | Array<string>): Array<string> { | ||
return Array.isArray(value) ? value : [value] | ||
} | ||
|
||
export type PointsSetReaderParams = PointsBaseReaderParams | ||
|
||
export class PointsSetReader< | ||
Content extends PointsContent = PointsContent, | ||
> extends PointsBaseReader<Content> { | ||
async loadDocumentFor( | ||
didOrValues: string | Array<string>, | ||
options: DeterministicLoadOptions = {}, | ||
): Promise<ModelInstanceDocument<Content> | null> { | ||
return await this.loader.loadSet(this.issuer, this.modelID, toUniqueArg(didOrValues), { | ||
ignoreEmpty: true, | ||
...options, | ||
}) | ||
} | ||
|
||
async loadPointsFor( | ||
didOrValues: string | Array<string>, | ||
options?: DeterministicLoadOptions, | ||
): Promise<number> { | ||
const doc = await this.loadDocumentFor(didOrValues, options) | ||
return doc?.content?.points ?? 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import type { CeramicAPI, ModelInstanceDocument } from '@composedb/types' | ||
import type { PointsContent } from '@ceramic-solutions/points-composite' | ||
|
||
import { getAuthenticatedCeramic } from './ceramic.js' | ||
import { PointsSetReader, type PointsSetReaderParams, toUniqueArg } from './set-reader.js' | ||
|
||
export type PointsSetWriterFromSeedParams = PointsSetReaderParams & { | ||
seed: Uint8Array | ||
} | ||
|
||
export type PointsSetWriterParams = Omit<PointsSetReaderParams, 'ceramic'> & { | ||
ceramic: CeramicAPI | ||
} | ||
|
||
export class PointsSetWriter< | ||
Content extends PointsContent = PointsContent, | ||
> extends PointsSetReader<Content> { | ||
static async fromSeed<Content extends PointsContent = PointsContent>( | ||
params: PointsSetWriterFromSeedParams, | ||
): Promise<PointsSetWriter<Content>> { | ||
const ceramic = await getAuthenticatedCeramic(params.seed, params.ceramic) | ||
return new PointsSetWriter({ ...params, ceramic }) | ||
} | ||
|
||
constructor(params: PointsSetWriterParams) { | ||
if (!params.ceramic.did?.authenticated) { | ||
throw new Error(`An authenticated DID instance must be set on the Ceramic client`) | ||
} | ||
super({ ...params, issuer: params.ceramic.did.id }) | ||
} | ||
|
||
async _loadDocumentFor( | ||
didOrValues: string | Array<string>, | ||
): Promise<ModelInstanceDocument<Content>> { | ||
const doc = await this.loadDocumentFor(didOrValues, { ignoreEmpty: false, onlyIndexed: false }) | ||
return doc! | ||
} | ||
|
||
async setDocumentFor( | ||
didOrValues: string | Array<string>, | ||
updateContent: (content: Content | null) => Partial<Content>, | ||
): Promise<ModelInstanceDocument<Content>> { | ||
const unique = toUniqueArg(didOrValues) | ||
const doc = await this._loadDocumentFor(didOrValues) | ||
const content = doc!.content | ||
await doc!.replace({ | ||
// Copy existing content or set recipient (assuming it's the first value) | ||
...(content ?? { recipient: unique[0] }), | ||
// Apply content update | ||
...updateContent(content), | ||
} as Content) | ||
return doc! | ||
} | ||
|
||
async removeDocument(id: string): Promise<void> { | ||
const doc = await this.loader.load({ id }) | ||
if (doc.metadata.model.toString() !== this.modelID) { | ||
throw new Error(`Document ${id} is not using the expected model ${this.modelID}`) | ||
} | ||
await doc.shouldIndex(false) | ||
} | ||
|
||
async removeDocumentFor(didOrValues: string | Array<string>): Promise<void> { | ||
const doc = await this._loadDocumentFor(didOrValues) | ||
await doc.shouldIndex(false) | ||
} | ||
} |