adding database changes & models.
This commit is contained in:
parent
349b627845
commit
5442063c17
|
@ -1,6 +1,6 @@
|
|||
# lib
|
||||
|
||||
This directory contains Typescript libraries/packages that are intended to be used in both Angular & WebWorkers.
|
||||
This directory contains Typescript libraries/packages that are intended to be used in both Angular & WebWorkers (and potentially NodeJS).
|
||||
That means they cannot contain any browser context/DOM specific code, as they will break in Web Workers.
|
||||
|
||||
## conduit
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import {Source} from '../models/database/source';
|
||||
import {ResourceFhir} from '../models/database/resource_fhir';
|
||||
import {SourceSummary} from '../models/fasten/source-summary';
|
||||
import {Summary} from '../models/fasten/summary';
|
||||
// import {SourceSummary} from '../../app/models/fasten/source-summary';
|
||||
|
||||
export interface IDatabaseDocument {
|
||||
|
@ -22,21 +24,20 @@ export interface IDatabaseRepository {
|
|||
// GetUserByEmail(context.Context, string) (*models.User, error)
|
||||
// GetCurrentUser(context.Context) *models.User
|
||||
|
||||
// GetSummary(ctx context.Context) (*models.Summary, error)
|
||||
GetSummary(): Promise<Summary>
|
||||
|
||||
CreateSource(source: Source): Promise<string>
|
||||
GetSource(source_id: string): Promise<Source>
|
||||
DeleteSource(source_id: string): Promise<boolean>
|
||||
GetSourceSummary(source_id: string): Promise<SourceSummary>
|
||||
GetSources(): Promise<IDatabasePaginatedResponse>
|
||||
|
||||
|
||||
// UpsertResource(context.Context, *models.ResourceFhir) error
|
||||
// GetResourceBySourceType(context.Context, string, string) (*models.ResourceFhir, error)
|
||||
// GetResourceBySourceId(context.Context, string, string) (*models.ResourceFhir, error)
|
||||
// ListResources(context.Context, models.ListResourceQueryOptions) ([]models.ResourceFhir, error)
|
||||
// GetPatientForSources(ctx context.Context) ([]models.ResourceFhir, error)
|
||||
|
||||
CreateSource(source: Source): Promise<string>
|
||||
GetSource(source_id: string): Promise<Source>
|
||||
DeleteSource(source_id: string): Promise<boolean>
|
||||
// GetSourceSummary(source_id: string): Promise<SourceSummary>
|
||||
GetSources(): Promise<IDatabasePaginatedResponse>
|
||||
|
||||
|
||||
CreateResource(resource: ResourceFhir): Promise<string>
|
||||
CreateResources(resources: ResourceFhir[]): Promise<string[]>
|
||||
GetResource(resource_id: string): Promise<ResourceFhir>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {IDatabaseRepository} from './interface';
|
||||
import {NewRepositiory} from './pouchdb_repository';
|
||||
import {SourceType} from '../models/database/types';
|
||||
import {SourceType} from '../models/database/source_types';
|
||||
import {Source} from '../models/database/source';
|
||||
import {DocType} from './constants';
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import {Source} from '../models/database/source';
|
||||
import {IDatabasePaginatedResponse, IDatabaseDocument, IDatabaseRepository} from './interface';
|
||||
import * as PouchDB from 'pouchdb/dist/pouchdb';
|
||||
import PouchFind from 'pouchdb/dist/pouchdb.find';
|
||||
// import * as PouchDB from 'pouchdb';
|
||||
import {DocType} from './constants';
|
||||
import {ResourceFhir} from '../models/database/resource_fhir';
|
||||
import {ResourceTypeCounts, SourceSummary} from '../models/fasten/source-summary';
|
||||
import {Base64} from '../utils/base64';
|
||||
import {Summary} from '../models/fasten/summary';
|
||||
|
||||
export function NewRepositiory(databaseName: string = 'fasten'): IDatabaseRepository {
|
||||
return new PouchdbRepository(databaseName)
|
||||
|
@ -13,12 +17,71 @@ export class PouchdbRepository implements IDatabaseRepository {
|
|||
|
||||
localPouchDb: PouchDB.Database
|
||||
constructor(public databaseName: string) {
|
||||
//setup PouchDB Plugins
|
||||
PouchDB.plugin(PouchFind); //https://pouchdb.com/guides/mango-queries.html
|
||||
|
||||
this.localPouchDb = new PouchDB(databaseName);
|
||||
|
||||
//create any necessary indexes
|
||||
// this index allows us to group by source_resource_type
|
||||
this.localPouchDb.createIndex({
|
||||
index: {fields: [
|
||||
//global
|
||||
'doc_type',
|
||||
//only relevant for resource_fhir documents
|
||||
'source_resource_type',
|
||||
]}
|
||||
}, (msg) => {console.log("DB createIndex complete", msg)});
|
||||
|
||||
|
||||
}
|
||||
public Close(): void {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Summary
|
||||
|
||||
public async GetSummary(): Promise<Summary> {
|
||||
const summary = new Summary()
|
||||
summary.sources = await this.GetSources()
|
||||
.then((paginatedResp) => paginatedResp.rows)
|
||||
|
||||
summary.patients = await this.GetDB().find({
|
||||
selector: {
|
||||
doc_type: DocType.ResourceFhir,
|
||||
source_resource_type: "Patient",
|
||||
}
|
||||
})
|
||||
|
||||
summary.resource_type_counts = await this.findDocumentByPrefix(`${DocType.ResourceFhir}`, true)
|
||||
.then((paginatedResp) => {
|
||||
const lookup: {[name: string]: ResourceTypeCounts} = {}
|
||||
paginatedResp?.rows.forEach((resource: ResourceFhir) => {
|
||||
let currentResourceStats = lookup[resource.source_resource_type] || {
|
||||
count: 0,
|
||||
source_id: resource.source_id,
|
||||
resource_type: resource.source_resource_type
|
||||
}
|
||||
currentResourceStats.count += 1
|
||||
lookup[resource.source_resource_type] = currentResourceStats
|
||||
})
|
||||
|
||||
const arr = []
|
||||
for(let key in lookup){
|
||||
arr.push(lookup[key])
|
||||
}
|
||||
return arr
|
||||
})
|
||||
|
||||
|
||||
return summary
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Source
|
||||
|
||||
public async CreateSource(source: Source): Promise<string> {
|
||||
return this.createDocument(source);
|
||||
}
|
||||
|
@ -41,10 +104,41 @@ export class PouchdbRepository implements IDatabaseRepository {
|
|||
})
|
||||
}
|
||||
|
||||
public async GetSourceSummary(source_id: string): Promise<SourceSummary> {
|
||||
const sourceSummary = new SourceSummary()
|
||||
sourceSummary.source = await this.GetSource(source_id)
|
||||
sourceSummary.patient = await this.findDocumentByPrefix(`${DocType.ResourceFhir}:${Base64.Encode(source_id)}:Patient`, true)
|
||||
.then((paginatedResp) => paginatedResp?.rows[0])
|
||||
|
||||
sourceSummary.resource_type_counts = await this.findDocumentByPrefix(`${DocType.ResourceFhir}:${Base64.Encode(source_id)}`, true)
|
||||
.then((paginatedResp) => {
|
||||
const lookup: {[name: string]: ResourceTypeCounts} = {}
|
||||
paginatedResp?.rows.forEach((resource: ResourceFhir) => {
|
||||
let currentResourceStats = lookup[resource.source_resource_type] || {
|
||||
count: 0,
|
||||
source_id: resource.source_id,
|
||||
resource_type: resource.source_resource_type
|
||||
}
|
||||
currentResourceStats.count += 1
|
||||
lookup[resource.source_resource_type] = currentResourceStats
|
||||
})
|
||||
|
||||
const arr = []
|
||||
for(let key in lookup){
|
||||
arr.push(lookup[key])
|
||||
}
|
||||
return arr
|
||||
})
|
||||
return sourceSummary
|
||||
}
|
||||
|
||||
public async DeleteSource(source_id: string): Promise<boolean> {
|
||||
return this.deleteDocument(source_id)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Resource
|
||||
|
||||
public async CreateResource(resource: ResourceFhir): Promise<string> {
|
||||
return this.createDocument(resource);
|
||||
}
|
||||
|
@ -114,12 +208,16 @@ export class PouchdbRepository implements IDatabaseRepository {
|
|||
.get(id)
|
||||
}
|
||||
|
||||
|
||||
private findDocumentByDocType(docType: DocType, includeDocs: boolean = true): Promise<IDatabasePaginatedResponse> {
|
||||
return this.findDocumentByPrefix(docType, includeDocs)
|
||||
}
|
||||
private findDocumentByPrefix(prefix: string, includeDocs: boolean = true): Promise<IDatabasePaginatedResponse> {
|
||||
return this.GetDB()
|
||||
.allDocs({
|
||||
include_docs: includeDocs,
|
||||
startkey: `${docType}:`,
|
||||
endkey: `${docType}:\uffff`
|
||||
startkey: `${prefix}:`,
|
||||
endkey: `${prefix}:\uffff`
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// export class RecordBase {
|
||||
// _id: string
|
||||
// entry_type: DatabaseRecordType
|
||||
// source_id: string
|
||||
// source_resource_type: string
|
||||
// source_resource_id: string
|
||||
//
|
||||
// constructor(database_record_type: DatabaseRecordType, source_resource_type: string, source_id: string, source_resource_id: string ) {
|
||||
// this.source_record_type = source_resource_type
|
||||
// this.source_id = source_id
|
||||
// this.source_resource_id = source_resource_id
|
||||
// }
|
||||
// }
|
||||
|
||||
// interface LabeledValue {
|
||||
// label: string;
|
||||
// }
|
|
@ -1,5 +1,5 @@
|
|||
import {LighthouseSourceMetadata} from '../lighthouse/lighthouse-source-metadata';
|
||||
import {SourceType} from './types';
|
||||
import {SourceType} from './source_types';
|
||||
import {DocType} from '../../../lib/database/constants';
|
||||
|
||||
export class Source extends LighthouseSourceMetadata{
|
||||
|
|
|
@ -16,4 +16,5 @@ export class LighthouseSourceMetadata {
|
|||
redirect_uri: string
|
||||
|
||||
confidential: boolean
|
||||
cors_relay_required: boolean
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
export class Base64 {
|
||||
public static Encode(data: string): string {
|
||||
return btoa(data)
|
||||
return `b64.${btoa(data)}`
|
||||
}
|
||||
public static Decode(data: string): string {
|
||||
return atob(data)
|
||||
const parts = data.split(".")
|
||||
if(parts.length != 2){
|
||||
throw new Error(`invalid base64 encoded string: ${data}`)
|
||||
}
|
||||
return atob(parts[1])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue