Skip to content

Commit

Permalink
fix: fully make models extendable and completely typed.
Browse files Browse the repository at this point in the history
  • Loading branch information
elribonazo committed Jan 8, 2024
1 parent 4166ab8 commit 7dc013a
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 595 deletions.
559 changes: 69 additions & 490 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@
"@pluto-encrypted/indexdb": "1.9.4",
"@pluto-encrypted/inmemory": "1.9.4",
"@pluto-encrypted/leveldb": "1.9.4",
"@pluto-encrypted/schemas": "^0.0.0",
"@pluto-encrypted/shared": "1.9.3",
"@vitest/coverage-v8": "^1.0.4",
"level": "^6.0.1"
},
"dependencies": {
"@atala/prism-wallet-sdk": "^4.0.0-rc.1",
"@pluto-encrypted/encryption": "1.9.3",
"@pluto-encrypted/schemas": "^0.0.0",
"@pluto-encrypted/shared": "1.9.3",
"rxdb": "^14.17.0",
"rxjs": "7.8.1",
"uuid": "^9.0.1"
Expand Down
31 changes: 18 additions & 13 deletions packages/database/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* @module database
*/
import SDK from '@atala/prism-wallet-sdk'
import { DatabaseBase, DatabaseCreateOptions } from '@pluto-encrypted/schemas'
import { DatabaseCreateOptions, PlutoCollections, getDefaultCollections } from '@pluto-encrypted/schemas'
import { DatabaseBase } from '@pluto-encrypted/shared'
import {
CollectionsOfDatabase,
RxCollection,
Expand All @@ -20,22 +21,33 @@ export type * from './types'
export const Database = {
createEncrypted: async function createEncrypted<
Collections = CollectionsOfDatabase
>(options: DatabaseCreateOptions<Collections>): Promise<DatabaseBase<Collections> & SDK.Domain.Pluto> {
>(options: DatabaseCreateOptions<Collections & PlutoCollections>): Promise<DatabaseBase<Collections & PlutoCollections, PlutoCollections> & SDK.Domain.Pluto> {
try {
const { name, storage, encryptionKey, importData, autoStart = true, collections } = options
const { name, storage, encryptionKey, importData, autoStart = true, collections, withDefaultCollections = true } = options
if (!storage) {
throw new Error('Please provide a valid storage.')
}

const instance = new DatabaseBase<Collections>({
const instance = new DatabaseBase<Collections & PlutoCollections, PlutoCollections>({
ignoreDuplicate: true,
name,
storage,
password: Buffer.from(encryptionKey).toString('hex')
});
})

if (withDefaultCollections) {
instance.defaultCollections = getDefaultCollections()
}

const proxy = new Proxy<DatabaseBase<Collections> & SDK.Domain.Pluto>(instance as any, {
if (autoStart) {
await instance.start(collections)
}

if (importData) {
await instance.db.importJSON(importData)
}

const proxy = new Proxy<DatabaseBase<Collections & PlutoCollections, PlutoCollections> & SDK.Domain.Pluto>(instance as any, {
get(target, prop) {
const staticMethodModels = Object.keys(target.db.collections).reduce<Map<string, Function>>((statics, collectionName) => {
const currentCollection: RxCollection = target.db.collections[collectionName];
Expand Down Expand Up @@ -64,13 +76,6 @@ export const Database = {
},
})

if (autoStart) {
await instance.start(collections)
}

if (importData) {
await instance.db.importJSON(importData)
}

return proxy;
} catch (err) {
Expand Down
5 changes: 2 additions & 3 deletions packages/database/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ExtendedCollections, PlutoCollections } from '@pluto-encrypted/schemas'
import { RxCollectionCreator, RxDatabase, RxDatabaseCreator, type MangoQuery, type MangoQueryNoLimit, type RxCollection, type RxDocument, type RxDumpDatabase, type RxStorage } from 'rxdb/dist/types/types'
import { PlutoCollections } from '@pluto-encrypted/schemas'
import { type MangoQuery, type MangoQueryNoLimit, type RxCollection, type RxDocument, type RxDumpDatabase, type RxStorage } from 'rxdb/dist/types/types'

export type NoKeys<T, K extends keyof T> = {
[P in Exclude<keyof T, K>]: T[P];
Expand All @@ -16,7 +16,6 @@ export interface GenericORMType<RxDocType> extends RxCollection<any, any, any> {
}



export interface createEncryptedOptions {
name: string
encryptionKey: Uint8Array
Expand Down
2 changes: 2 additions & 0 deletions packages/schemas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@
},
"devDependencies": {
"@pluto-encrypted/encryption": "^1.9.3",
"@pluto-encrypted/shared": "1.9.3",
"@vitest/coverage-v8": "^1.0.4"
},
"dependencies": {
"@atala/prism-wallet-sdk": "^4.0.0-rc.1",
"@pluto-encrypted/encryption": "^1.9.3",
"@pluto-encrypted/shared": "1.9.3",
"rxdb": "^14.17.0",
"rxjs": "7.8.1",
"uuid": "^9.0.1"
Expand Down
81 changes: 13 additions & 68 deletions packages/schemas/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
* @packageDocumentation
* @module database
*/
import { RxDBEncryptedMigrationPlugin } from '@pluto-encrypted/encryption'
import { RxDBJsonDumpPlugin } from 'rxdb/plugins/json-dump'
import { RxDBQueryBuilderPlugin } from 'rxdb/plugins/query-builder'
import { CollectionsOfDatabase, addRxPlugin, removeRxDatabase, RxCollectionCreator, createRxDatabase, RxDatabaseCreator, RxDumpDatabase, RxStorage } from 'rxdb'
import { PlutoDatabase, ExtendedCollections, DBOptions } from './types'
import { RxCollectionCreator } from 'rxdb'
import { CredentialSchema, CredentialMethods, CredentialStaticMethods } from './schemas/credential'
import { CredentialRequestMetadataSchema, CredentialRequestMetadataMethods, CredentialRequestMetadataStaticMethods } from './schemas/credentialRequestMetadata'
import { DIDSchema, DIDStaticMethods } from './schemas/did'
Expand All @@ -15,24 +11,9 @@ import { LinkSecretSchema, LinkSecretMethods, LinkSecretStaticMethods } from './
import { MediatorSchema, MediatorMethods, MediatorStaticMethods } from './schemas/mediator'
import { MessageSchema, MessageMethods, MessageStaticMethods } from './schemas/message'
import { PrivateKeySchema, PrivateKeyMethods, PrivateKeyStaticMethods } from './schemas/privatekey'
import { PlutoCollectionsCreator } from './types'



export * from './schemas/credential'
export * from './schemas/credentialRequestMetadata'
export * from './schemas/did'
export * from './schemas/didpair'
export * from './schemas/linksecret'
export * from './schemas/mediator'
export * from './schemas/message'
export * from './schemas/privatekey'


export * from './types'
export type { Domain as WALLET_SDK_DOMAIN } from '@atala/prism-wallet-sdk'


export function getDefaultCollections(extendedCollections: { [name: string]: RxCollectionCreator } = {}): { [name: string]: RxCollectionCreator } {
export function getDefaultCollections(extendedCollections: { [name: string]: RxCollectionCreator } = {}): { [name: string]: RxCollectionCreator } & PlutoCollectionsCreator {
return {
messages: {
schema: MessageSchema,
Expand Down Expand Up @@ -76,50 +57,14 @@ export function getDefaultCollections(extendedCollections: { [name: string]: RxC
}
}

export * from './schemas/credential'
export * from './schemas/credentialRequestMetadata'
export * from './schemas/did'
export * from './schemas/didpair'
export * from './schemas/linksecret'
export * from './schemas/mediator'
export * from './schemas/message'
export * from './schemas/privatekey'
export * from './types'

export class DatabaseBase<Collections = CollectionsOfDatabase> {
private _db!: PlutoDatabase<Collections>
get db() {
if (!this._db) {
throw new Error('Start Pluto first.')
}
return this._db
}

constructor(private readonly dbOptions: DBOptions) {
addRxPlugin(RxDBQueryBuilderPlugin)
addRxPlugin(RxDBJsonDumpPlugin)
addRxPlugin(RxDBEncryptedMigrationPlugin)
}

async backup() {
return await this.db.exportJSON()
}

/**
* Use with caution, this will remove all entries from database
* and then destroy the database itself.
*/
async clear() {
const storages = Array.from(this.db.storageInstances.values())
for (const storage of storages) {
await storage.cleanup(Infinity)
}
await removeRxDatabase(this.dbOptions.name, this.db.storage)
}

/**
* Start the database and build collections
*/
async start(collections?: {
[name: string]: RxCollectionCreator<any>
}): Promise<void> {
const { dbOptions } = this
const database = await createRxDatabase<ExtendedCollections<Collections>>({
...dbOptions,
multiInstance: false
})
await database.addCollections(getDefaultCollections(collections));
this._db = database
}
}
export type { Domain as WALLET_SDK_DOMAIN } from '@atala/prism-wallet-sdk'
1 change: 1 addition & 0 deletions packages/schemas/src/schemas/did/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface DIDSchemaType {
}

export type DIDDocument = RxDocument<DIDSchemaType>

export interface DIDStaticMethodTypes extends KeyFunctionMap {
getPrismLastKeyPathIndex(this: StaticRxCollectionContext<{ dids: DIDCollection }>): Promise<number>
getPrismDIDKeyPathIndex(this: StaticRxCollectionContext<{ dids: DIDCollection }>, did: SDK.Domain.DID): Promise<number | null>
Expand Down
39 changes: 23 additions & 16 deletions packages/schemas/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ import { CredentialRequestMetadataCollection } from "./schemas/credentialRequest

import { MessageColletion } from "./schemas/message"
import { PrivateKeyColletion } from "./schemas/privatekey"

import {
DatabaseBase
} from "."

import { DatabaseBase, ExtendedCollections } from '@pluto-encrypted/shared'

export type ValuesOf<T> = T[keyof T]
export type Schema<T> = RxJsonSchema<T> & {
encrypted: Array<keyof T>
}

export interface PlutoCollections {
messages: MessageColletion
dids: DIDCollection
Expand All @@ -42,21 +39,31 @@ export interface PlutoCollections {
credentialrequestmetadatas: CredentialRequestMetadataCollection
linksecrets: LinkSecretColletion
}
export type ExtendedCollections<T> = PlutoCollections & { [key in keyof T]: ValuesOf<T> }
export type PlutoDatabase<Collections> = RxDatabase<ExtendedCollections<Collections>, any, any>
export interface PlutoCollectionsCreator {
messages: RxCollectionCreator
dids: RxCollectionCreator
didpairs: RxCollectionCreator
mediators: RxCollectionCreator
privatekeys: RxCollectionCreator
credentials: RxCollectionCreator
credentialrequestmetadatas: RxCollectionCreator
linksecrets: RxCollectionCreator
}
export type PlutoDatabase<Collections> = RxDatabase<ExtendedCollections<Collections>, any, any>;
export type DatabaseCreateOptions<CreatedCollections> = {
name: string
encryptionKey: Uint8Array
importData?: RxDumpDatabase<ExtendedCollections<CreatedCollections>>
storage: RxStorage<any, any>
autoStart?: boolean
name: string;
encryptionKey: Uint8Array;
importData?: RxDumpDatabase<ExtendedCollections<CreatedCollections>>;
storage: RxStorage<any, any>;
autoStart?: boolean;
withDefaultCollections: boolean;
collections?: {
[key in keyof CreatedCollections]: RxCollectionCreator<any>
}
}
[key in keyof CreatedCollections]: RxCollectionCreator<any>;
};
};
export type DBOptions = RxDatabaseCreator;
export type PlutoInstance<
Collections = CollectionsOfDatabase,
> = DatabaseBase<Collections> & SDK.Domain.Pluto
> = DatabaseBase<Collections & PlutoCollections> & SDK.Domain.Pluto

export type StaticRxCollectionContext<Collections = { [name: string]: RxCollection }> = PlutoInstance<Collections>
5 changes: 3 additions & 2 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
"license": "Apache-2.0",
"dependencies": {
"rxdb": "^14.17.0",
"uuid": "^9.0.1"
"uuid": "^9.0.1",
"@pluto-encrypted/encryption": "1.9.3"
},
"files": [
"build/*"
],
"gitHead": "6aa4ce8bbb9938fc4c4e790efffa5b902631362c"
}
}
70 changes: 69 additions & 1 deletion packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
* @description Shared is used by other dependencies of pluto-encrypted to reduce code duplication.
*
*/
import { type MangoQuerySelector, type RxDocumentData, type RxJsonSchema } from 'rxdb'
import { RxDBEncryptedMigrationPlugin } from '@pluto-encrypted/encryption'
import { RxDBJsonDumpPlugin } from 'rxdb/plugins/json-dump'
import { RxDBQueryBuilderPlugin } from 'rxdb/plugins/query-builder'
import { CollectionsOfDatabase, RxCollectionCreator, addRxPlugin, createRxDatabase, removeRxDatabase, type MangoQuerySelector, type RxDocumentData, type RxJsonSchema, RxDatabase, RxDatabaseCreator, RxDumpDatabase, RxStorage } from 'rxdb'
export type { RxDocumentMeta, PlainJsonValue, PropertyType, PlainSimpleJsonObject } from 'rxdb/dist/types/types'
export type { MangoQuerySelector, RxAttachmentDataBase, MangoQueryOperators, RxDocumentData, RxAttachmentData } from 'rxdb'

Expand Down Expand Up @@ -234,3 +237,68 @@ export function getPrivateKeyValue<RxDocType>(document: RxDocumentData<RxDocType
const id = document[primaryKeyKey] as string
return id
}

export type ValuesOf<T> = T[keyof T]
export type DBOptions = RxDatabaseCreator;
export type ExtendedCollections<T> = { [key in keyof T]: ValuesOf<T> }

export class DatabaseBase<Collections = CollectionsOfDatabase, DefaultCollections = CollectionsOfDatabase> {
private _db!: RxDatabase<ExtendedCollections<Collections & DefaultCollections>, any, any>
public defaultCollections!: { [key in keyof DefaultCollections]: RxCollectionCreator<any> }

get db() {
if (!this._db) {
throw new Error('Start Pluto first.')
}
return this._db
}

constructor(
private readonly dbOptions: DBOptions,
) {
addRxPlugin(RxDBQueryBuilderPlugin)
addRxPlugin(RxDBJsonDumpPlugin)
addRxPlugin(RxDBEncryptedMigrationPlugin)
}

async backup() {
return await this.db.exportJSON()
}

/**
* Use with caution, this will remove all entries from database
* and then destroy the database itself.
*/
async clear() {
const storages = Array.from(this.db.storageInstances.values())
for (const storage of storages) {
await storage.cleanup(Infinity)
}
await removeRxDatabase(this.dbOptions.name, this.db.storage)
}

/**
* Start the database and build collections
*/
async start(collections?: {
[name: string]: RxCollectionCreator<any>
}): Promise<void> {
const { dbOptions } = this
const database = await createRxDatabase<ExtendedCollections<Collections & DefaultCollections>>({
...dbOptions,
multiInstance: false
})

const extendedCollections = collections ? collections : {};
if (this.defaultCollections) {
await database.addCollections({
...this.defaultCollections,
...extendedCollections
});
} else {
await database.addCollections(extendedCollections);
}

this._db = database
}
}

0 comments on commit 7dc013a

Please sign in to comment.