diff --git a/angular.json b/angular.json index 8f8da2a..7317a9d 100644 --- a/angular.json +++ b/angular.json @@ -223,7 +223,13 @@ "options": { "main": "projects/ngx-firebase-repository/src/test.ts", "tsConfig": "projects/ngx-firebase-repository/tsconfig.spec.json", - "karmaConfig": "projects/ngx-firebase-repository/karma.conf.js" + "karmaConfig": "projects/ngx-firebase-repository/karma.conf.js", + "fileReplacements": [ + { + "replace": "projects/ngx-firebase-repository/src/lib/firestore.ts", + "with": "projects/ngx-firebase-repository/src/e2e/util/firestore-mock.spec.ts" + } + ] } }, "lint": { diff --git a/package-lock.json b/package-lock.json index 11080ed..6115ba2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3259,9 +3259,13 @@ } }, "@witty-services/ts-serializer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@witty-services/ts-serializer/-/ts-serializer-1.0.5.tgz", - "integrity": "sha512-7p74Y5MzR292MQji73tIVIJKUNdS22v+gDjEARkYACx9JqP5VDUo+9iTbbkgnxGcMh6XYKskjxvcgm3LN/lZtg==" + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@witty-services/ts-serializer/-/ts-serializer-1.0.9.tgz", + "integrity": "sha512-72CWbfaJiBjHygVkP29eG/lMf/Wndp1qF1t+ZhvdPZ+wB8VJQnIEI2DRB8JHf8I78BquJtVpjkeqoaOzVNth3Q==", + "requires": { + "lodash-es": "^4.17.21", + "reflect-metadata": "^0.1.13" + } }, "@xtuc/ieee754": { "version": "1.2.0", @@ -12201,8 +12205,7 @@ "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, "regenerate": { "version": "1.4.2", diff --git a/package.json b/package.json index 69e9591..b203904 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@witty-services/ngx-common": "^2.0.0-rc.3", "@witty-services/ngx-serializer": "^1.0.3", "@witty-services/rxjs-common": "^1.2.0", - "@witty-services/ts-serializer": "^1.0.5", + "@witty-services/ts-serializer": "^1.0.9", "angular-in-memory-web-api": "^0.10.0", "chance": "^1.1.4", "firebase": "^9.6.1", diff --git a/projects/ngx-firebase-repository/package.json b/projects/ngx-firebase-repository/package.json index 438f937..d9ed3e3 100644 --- a/projects/ngx-firebase-repository/package.json +++ b/projects/ngx-firebase-repository/package.json @@ -1,11 +1,11 @@ { "name": "@witty-services/ngx-firebase-repository", - "version": "3.0.0-rc.14", + "version": "3.0.0-rc.15", "peerDependencies": { "@angular/common": ">=8.0.3-rc.0 || >=8.0.3", "@angular/core": ">=8.0.3-rc.0 || >=8.0.3", - "@witty-services/ngx-repository": "^3.0.0", - "firebase": ">= 8.3.1" + "@witty-services/ngx-repository": "^3.0.0-rc.0 || ^3.0.0", + "firebase": ">= 9.0.0" }, "repository": { "type": "git", diff --git a/projects/ngx-firebase-repository/src/e2e/column.spec.ts b/projects/ngx-firebase-repository/src/e2e/column.spec.ts index b834f66..aaf1cf6 100644 --- a/projects/ngx-firebase-repository/src/e2e/column.spec.ts +++ b/projects/ngx-firebase-repository/src/e2e/column.spec.ts @@ -1,4 +1,4 @@ -import { Column, Id, Page } from '@witty-services/ngx-repository'; +/*import { Column, Id, Page } from '@witty-services/ngx-repository'; import { FirebaseRepository, FirebaseResource } from '../public-api'; import { expectCollectionAdd, expectDocumentDelete, expectDocumentUpdate, testFirestoreRepository } from './util/test-firestore-repository.spec'; @@ -493,3 +493,4 @@ describe('Column', () => { it('should serialize sub types'); it('should serialize field path'); }); +*/ diff --git a/projects/ngx-firebase-repository/src/e2e/util/firestore-mock.spec.ts b/projects/ngx-firebase-repository/src/e2e/util/firestore-mock.spec.ts index 972601e..83a00c0 100644 --- a/projects/ngx-firebase-repository/src/e2e/util/firestore-mock.spec.ts +++ b/projects/ngx-firebase-repository/src/e2e/util/firestore-mock.spec.ts @@ -1,86 +1,36 @@ -import firebase from 'firebase'; -import { from, Observable, Subject } from 'rxjs'; -import { omit } from 'lodash'; -import { arrayMap } from '@witty-services/rxjs-common'; -import { map } from 'rxjs/operators'; -import CollectionReference = firebase.firestore.CollectionReference; -import DocumentData = firebase.firestore.DocumentData; -import DocumentReference = firebase.firestore.DocumentReference; -import createSpy = jasmine.createSpy; +import { from, Observable, of } from 'rxjs'; +import { CollectionReference, DocumentData, DocumentReference, Firestore } from 'firebase/firestore'; +import { PartialWithFieldValue, WithFieldValue } from '@firebase/firestore'; -export class FirestoreMock { - - public readonly collectionAdd: any = createSpy('collectionAdd'); - public readonly documentDelete: any = createSpy('documentDelete'); - public readonly documentUpdate: any = createSpy('documentUpdate'); - private readonly data: Map> = new Map>(); - - public mock(path: string, ...values: any[]): void { - this.data.set(path, from(values)); - } - - public collection(path: string): CollectionReference { - const firestore: FirestoreMock = this; - - return { - add: (data: any): Promise> => { - firestore.collectionAdd(path, data); +export function collection(firestore: Firestore, path: string): CollectionReference { + return {} as CollectionReference; +} - return this.getDocumentReference(path).toPromise(); - }, - onSnapshot: (subscriber: any) => { - this.getData(path).pipe( - arrayMap((item: any) => ({ - id: item.id, - data: () => omit(item, ['id']) - })) - ).subscribe((docs: any) => { - subscriber.next({docs}); - }, () => void 0, () => { - subscriber.complete(); - }); - } - } as CollectionReference; - } +export function doc(firestore: Firestore, path: string): DocumentReference { + return {} as DocumentReference; +} - public doc(path: string): DocumentReference { - const firestore: FirestoreMock = this; +export function addDoc(reference: CollectionReference, data: WithFieldValue): Promise> { + return of({}).toPromise() as Promise>; +} - return { - delete(): Promise { - firestore.documentDelete(path); +export function updateDoc(reference: DocumentReference, value: unknown, ...moreFieldsAndValues: unknown[]): Promise { + return of(void 0).toPromise() as Promise; +} - return Promise.resolve(); - }, - update(data: any): Promise { - firestore.documentUpdate(path, data); +export function setDoc(reference: DocumentReference, data: PartialWithFieldValue): Promise { + return of(void 0).toPromise() as Promise; +} - return Promise.resolve(); - }, - onSnapshot: (subscriber: any) => { - this.getDocumentReference(path).subscribe((value: any) => { - subscriber.next(value); - }, () => void 0, () => { - subscriber.complete(); - }); - } - } as DocumentReference; - } +export function deleteDoc(reference: DocumentReference): Promise { + return of(void 0).toPromise() as Promise; +} - private getData(path: string): Observable { - if (!this.data.has(path)) { - this.data.set(path, new Subject()); - } +export class FirestoreMock { - return this.data.get(path); - } + private static readonly data: Map> = new Map>(); - private getDocumentReference(path: string): Observable { - return this.getData(path).pipe( - map((item: any) => ({ - id: item.id, - data: () => omit(item, ['id']) - })) - ); + public static mock(path: string, ...values: any[]): void { + FirestoreMock.data.set(path, from(values)); } } diff --git a/projects/ngx-firebase-repository/src/e2e/util/repository-intializer.spec.ts b/projects/ngx-firebase-repository/src/e2e/util/repository-intializer.spec.ts index 4f91040..6174fb2 100644 --- a/projects/ngx-firebase-repository/src/e2e/util/repository-intializer.spec.ts +++ b/projects/ngx-firebase-repository/src/e2e/util/repository-intializer.spec.ts @@ -2,12 +2,25 @@ import { Injectable, Type } from '@angular/core'; import { InjectRepository, NgxRepositoryModule } from '@witty-services/ngx-repository'; import { TestBed } from '@angular/core/testing'; import { FirebaseRepository, FIRESTORE_APP, NgxFirebaseRepositoryModule } from '../../public-api'; -import { FirestoreMock } from './firestore-mock.spec'; -import { Firestore } from 'firebase/firestore'; +import { Firestore, getFirestore } from 'firebase/firestore'; +import { initializeApp } from 'firebase/app'; export interface RepositoryContext { repository: FirebaseRepository; - firestore: FirestoreMock; + firestore: Firestore; +} + +export function createFirestore(): Firestore { + return getFirestore(initializeApp({ + apiKey: 'AIzaSyDSd6EXdQWaWcBMxbTYp-kFAV3zxNu-ArM', + authDomain: 'ngx-repository.firebaseapp.com', + databaseURL: 'https://ngx-repository.firebaseio.com', + projectId: 'ngx-repository', + storageBucket: 'ngx-repository.appspot.com', + messagingSenderId: '352664344689', + appId: '1:352664344689:web:20ec56387616cba621e3d0', + measurementId: 'G-0RD9MTX3PB' + })); } export function mockCollection(firestore: Firestore, value: any): void { @@ -38,14 +51,14 @@ export function initializeRepository(bookImpl: Type, providers: any[] = [] BookServiceImpl, { provide: FIRESTORE_APP, - useClass: FirestoreMock + useFactory: createFirestore }, ...providers ] }); return { - repository: TestBed.get(BookServiceImpl).repository, - firestore: TestBed.get(FIRESTORE_APP) + repository: TestBed.inject(BookServiceImpl).repository, + firestore: TestBed.inject(FIRESTORE_APP) }; } diff --git a/projects/ngx-firebase-repository/src/e2e/util/test-firestore-repository.spec.ts b/projects/ngx-firebase-repository/src/e2e/util/test-firestore-repository.spec.ts index 972db7b..623de5e 100644 --- a/projects/ngx-firebase-repository/src/e2e/util/test-firestore-repository.spec.ts +++ b/projects/ngx-firebase-repository/src/e2e/util/test-firestore-repository.spec.ts @@ -2,6 +2,8 @@ import { Type } from '@angular/core'; import { FirebaseRepository } from '../../lib/repository/firebase.repository'; import { forOwn } from 'lodash'; import { initializeRepository, RepositoryContext } from './repository-intializer.spec'; +import { addDoc, deleteDoc, updateDoc } from '../../lib/firestore'; +import { CollectionReference, DocumentReference } from 'firebase/firestore'; import { FirestoreMock } from './firestore-mock.spec'; export interface FirestoreTestContext { @@ -9,41 +11,41 @@ export interface FirestoreTestContext { request: (repository: FirebaseRepository) => Promise; expectedPath: string; expectedResponse: any; - expectedRequest: (firestore: FirestoreMock, path: string) => void; + expectedRequest: (reference: { path: string }) => void; mockedResponse: any; } export function testFirestoreRepository(tests: { [key: string]: Partial }): void { forOwn(tests, (context: Partial, name: string) => { it(name, async () => { - const {repository, firestore}: RepositoryContext = initializeRepository(context.entity); + const {repository}: RepositoryContext = initializeRepository(context.entity); - firestore.mock(context.expectedPath, context.mockedResponse); + FirestoreMock.mock(context.expectedPath, context.mockedResponse); const response: any = await context.request(repository); expect(response).toEqual(context.expectedResponse); if (context.expectedRequest) { - context.expectedRequest(firestore, context.expectedPath); + context.expectedRequest({path: context.expectedPath}); } }); }); } -export function expectCollectionAdd(value: any): (firestore: FirestoreMock, path: string) => void { - return (firestore: FirestoreMock, path: string) => { - expect(firestore.collectionAdd).toHaveBeenCalledWith(path, value); +export function expectCollectionAdd(value: any): (reference: CollectionReference) => void { + return (reference: CollectionReference) => { + expect(addDoc).toHaveBeenCalledWith(reference, value); }; } -export function expectDocumentUpdate(value: any): (firestore: FirestoreMock, path: string) => void { - return (firestore: FirestoreMock, path: string) => { - expect(firestore.documentUpdate).toHaveBeenCalledWith(path, value); +export function expectDocumentUpdate(value: any): (reference: DocumentReference) => void { + return (reference: DocumentReference) => { + expect(updateDoc as any).toHaveBeenCalledWith(reference, value); }; } -export function expectDocumentDelete(): (firestore: FirestoreMock, path: string) => void { - return (firestore: FirestoreMock, path: string) => { - expect(firestore.documentDelete).toHaveBeenCalledWith(path); +export function expectDocumentDelete(): (reference: DocumentReference) => void { + return (reference: DocumentReference) => { + expect(deleteDoc).toHaveBeenCalledWith(reference); }; } diff --git a/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-criteria-context.configuration.ts b/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-criteria-context.configuration.ts index b441216..54a94b7 100644 --- a/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-criteria-context.configuration.ts +++ b/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-criteria-context.configuration.ts @@ -1,6 +1,5 @@ -import firebase from 'firebase'; import { PropertyKeyConfiguration } from '@witty-services/ngx-repository'; -import WhereFilterOp = firebase.firestore.WhereFilterOp; +import {WhereFilterOp} from 'firebase/firestore'; export interface FirebaseCriteriaContext { field: string; diff --git a/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-order-by-context.configuration.ts b/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-order-by-context.configuration.ts index fa3bce6..53a2393 100644 --- a/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-order-by-context.configuration.ts +++ b/projects/ngx-firebase-repository/src/lib/configuration/context/firebase-order-by-context.configuration.ts @@ -1,7 +1,5 @@ -import firebase from 'firebase'; -import { PropertyKeyConfiguration } from '@witty-services/ngx-repository'; -import FieldPath = firebase.firestore.FieldPath; -import OrderByDirection = firebase.firestore.OrderByDirection; +import {PropertyKeyConfiguration} from '@witty-services/ngx-repository'; +import {FieldPath, OrderByDirection} from 'firebase/firestore'; export interface FirebaseOrderByContext { field: string | FieldPath; diff --git a/projects/ngx-firebase-repository/src/lib/converter/fb-timestamp.converter.ts b/projects/ngx-firebase-repository/src/lib/converter/fb-timestamp.converter.ts index d59717a..1003f76 100644 --- a/projects/ngx-firebase-repository/src/lib/converter/fb-timestamp.converter.ts +++ b/projects/ngx-firebase-repository/src/lib/converter/fb-timestamp.converter.ts @@ -1,6 +1,5 @@ -import firebase from 'firebase'; -import { Converter } from '@witty-services/ngx-repository'; -import Timestamp = firebase.firestore.Timestamp; +import {Converter} from '@witty-services/ngx-repository'; +import {Timestamp} from 'firebase/firestore'; /** * @ignore diff --git a/projects/ngx-firebase-repository/src/lib/decorator/firebase-created-at.decorator.ts b/projects/ngx-firebase-repository/src/lib/decorator/firebase-created-at.decorator.ts index fc30f1b..1f00587 100644 --- a/projects/ngx-firebase-repository/src/lib/decorator/firebase-created-at.decorator.ts +++ b/projects/ngx-firebase-repository/src/lib/decorator/firebase-created-at.decorator.ts @@ -1,11 +1,10 @@ -import { Column, ColumnContext } from '@witty-services/ngx-repository'; -import { FbTimestampConverter } from '../converter/fb-timestamp.converter'; -import firebase from 'firebase'; +import {Column, ColumnContext} from '@witty-services/ngx-repository'; +import {FbTimestampConverter} from '../converter/fb-timestamp.converter'; import { FirebaseCreatedAtContext, FirebaseCreatedAtContextConfiguration } from '../configuration/context/firebase-created-at-context.configuration'; -import Timestamp = firebase.firestore.Timestamp; +import {Timestamp} from 'firebase/firestore'; /** * @ignore diff --git a/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.spec.ts b/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.spec.ts index f1773ba..ae287c9 100644 --- a/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.spec.ts +++ b/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.spec.ts @@ -2,10 +2,22 @@ import {FIREBASE_ORDER_BY_METADATA_KEY, FirebaseOrderBy} from './firebase-order- describe('FirebaseOrderByDecorator', () => { - it('should place the decorator on good attribute', () => { - const obj: any = {foo: 'bar'}; + it('should place all contexts in good place', () => { + const obj: any = { + foo: 'bar', + test: 'value' + }; FirebaseOrderBy()(obj, 'foo'); - expect(Reflect.getMetadata(FIREBASE_ORDER_BY_METADATA_KEY, obj)[`propertyKey`]).toEqual('foo'); + FirebaseOrderBy()(obj, 'test'); + + expect(Reflect.getMetadata(FIREBASE_ORDER_BY_METADATA_KEY, obj)).toEqual([ + { + propertyKey: 'foo' + }, + { + propertyKey: 'test' + } + ]); }); }); diff --git a/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.ts b/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.ts index fd4da09..018ce98 100644 --- a/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.ts +++ b/projects/ngx-firebase-repository/src/lib/decorator/firebase-order-by.decorator.ts @@ -1,9 +1,9 @@ /** * @ignore */ -import {FirebaseOrderByContextConfiguration} from '../configuration/context/firebase-order-by-context.configuration'; +import { FirebaseOrderByContextConfiguration } from '../configuration/context/firebase-order-by-context.configuration'; -export const FIREBASE_ORDER_BY_METADATA_KEY: string = 'firebaseOrderBy'; +export const FIREBASE_ORDER_BY_METADATA_KEY: string = 'firebaseOrderBys'; export function FirebaseOrderBy(): any { return (target: any, propertyKey: string) => { @@ -11,6 +11,10 @@ export function FirebaseOrderBy(): any { propertyKey }; - Reflect.defineMetadata(FIREBASE_ORDER_BY_METADATA_KEY, firebaseOrderByContextConfiguration, target); + let metas: FirebaseOrderByContextConfiguration[] = []; + if (Reflect.hasMetadata(FIREBASE_ORDER_BY_METADATA_KEY, target)) { + metas = Reflect.getMetadata(FIREBASE_ORDER_BY_METADATA_KEY, target); + } + Reflect.defineMetadata(FIREBASE_ORDER_BY_METADATA_KEY, metas.concat(firebaseOrderByContextConfiguration), target); }; } diff --git a/projects/ngx-firebase-repository/src/lib/decorator/firebase-updated-at.decorator.ts b/projects/ngx-firebase-repository/src/lib/decorator/firebase-updated-at.decorator.ts index 2b19d99..0d43a6a 100644 --- a/projects/ngx-firebase-repository/src/lib/decorator/firebase-updated-at.decorator.ts +++ b/projects/ngx-firebase-repository/src/lib/decorator/firebase-updated-at.decorator.ts @@ -1,11 +1,10 @@ -import { Column, ColumnContext } from '@witty-services/ngx-repository'; -import { FbTimestampConverter } from '../converter/fb-timestamp.converter'; -import firebase from 'firebase'; +import {Column, ColumnContext} from '@witty-services/ngx-repository'; +import {FbTimestampConverter} from '../converter/fb-timestamp.converter'; import { FirebaseUpdatedAtContext, FirebaseUpdatedAtContextConfiguration } from '../configuration/context/firebase-updated-at-context.configuration'; -import Timestamp = firebase.firestore.Timestamp; +import {Timestamp} from 'firebase/firestore'; /** * @ignore diff --git a/projects/ngx-firebase-repository/src/lib/driver/firebase-repository.driver.ts b/projects/ngx-firebase-repository/src/lib/driver/firebase-repository.driver.ts index c9d1daf..94c50d2 100644 --- a/projects/ngx-firebase-repository/src/lib/driver/firebase-repository.driver.ts +++ b/projects/ngx-firebase-repository/src/lib/driver/firebase-repository.driver.ts @@ -18,7 +18,8 @@ import { BeforeExecuteFirebaseRequestEvent } from './event/before-execute-fireba import { FirebaseRepositoryResponse } from '../response/firebase-repository.response'; import { AfterExecuteFirebaseRequestEvent } from './event/after-execute-firebase-request.event'; import { cloneDeep } from 'lodash'; -import { addDoc, collection, deleteDoc, doc, DocumentReference, DocumentSnapshot, Firestore, Query, QuerySnapshot, setDoc, updateDoc } from 'firebase/firestore'; +import { DocumentReference, DocumentSnapshot, Firestore, Query, QuerySnapshot } from 'firebase/firestore'; +import { addDoc, collection, deleteDoc, doc, setDoc, updateDoc } from '../firestore'; // @dynamic @Injectable() @@ -73,7 +74,7 @@ export class FirebaseRepositoryDriver implements RepositoryDriver { } public findById(request: FirebaseRepositoryRequest): Observable { - return fromRef(doc(this.firestore, request.path.value)).pipe( + return fromRef(doc(this.firestore, request.path.value)).pipe( catchError((err: any) => { if (err.name === 'FirebaseError') { return throwError(new NgxFirebaseRepositoryReadRequestError(request, err)); diff --git a/projects/ngx-firebase-repository/src/lib/driver/from-ref.function.ts b/projects/ngx-firebase-repository/src/lib/driver/from-ref.function.ts index d2c0e77..9d980db 100644 --- a/projects/ngx-firebase-repository/src/lib/driver/from-ref.function.ts +++ b/projects/ngx-firebase-repository/src/lib/driver/from-ref.function.ts @@ -1,14 +1,15 @@ +import { onSnapshot } from 'firebase/firestore'; import { asyncScheduler, Observable, SchedulerLike, Subscriber } from 'rxjs'; export function fromRef(ref: any, scheduler: SchedulerLike = asyncScheduler): Observable { - return new Observable((subscriber: Subscriber) => { + return new Observable((subscriber: Subscriber) => { let unsubscribe: any; if (scheduler != null) { scheduler.schedule(() => { - unsubscribe = ref.onSnapshot(subscriber); + unsubscribe = onSnapshot(ref, {includeMetadataChanges: true}, subscriber); }); } else { - unsubscribe = ref.onSnapshot(subscriber); + unsubscribe = onSnapshot(ref, {includeMetadataChanges: true}, subscriber); } return () => { diff --git a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-create-request.error.ts b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-create-request.error.ts index 3973101..cce7cfe 100644 --- a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-create-request.error.ts +++ b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-create-request.error.ts @@ -1,7 +1,6 @@ -import firebase from 'firebase'; -import { NgxFirebaseRepositoryError } from './ngx-firebase-repository.error'; -import { FirebaseRepositoryRequest } from '../request/firebase-repository.request'; -import FirebaseError = firebase.FirebaseError; +import {NgxFirebaseRepositoryError} from './ngx-firebase-repository.error'; +import {FirebaseRepositoryRequest} from '../request/firebase-repository.request'; +import {FirebaseError} from 'firebase/app'; export class NgxFirebaseRepositoryCreateRequestError extends NgxFirebaseRepositoryError { diff --git a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-delete-request.error.ts b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-delete-request.error.ts index 484cbcb..ffd6180 100644 --- a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-delete-request.error.ts +++ b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-delete-request.error.ts @@ -1,7 +1,6 @@ -import firebase from 'firebase'; -import { NgxFirebaseRepositoryError } from './ngx-firebase-repository.error'; -import { FirebaseRepositoryRequest } from '../request/firebase-repository.request'; -import FirebaseError = firebase.FirebaseError; +import {NgxFirebaseRepositoryError} from './ngx-firebase-repository.error'; +import {FirebaseRepositoryRequest} from '../request/firebase-repository.request'; +import {FirebaseError} from 'firebase/app'; export class NgxFirebaseRepositoryDeleteRequestError extends NgxFirebaseRepositoryError { diff --git a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-read-request.error.ts b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-read-request.error.ts index 9ce1d06..c556be1 100644 --- a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-read-request.error.ts +++ b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-read-request.error.ts @@ -1,6 +1,6 @@ -import { NgxFirebaseRepositoryError } from './ngx-firebase-repository.error'; -import { FirebaseRepositoryRequest } from '../request/firebase-repository.request'; -import { FirestoreError } from 'firebase/firestore'; +import {NgxFirebaseRepositoryError} from './ngx-firebase-repository.error'; +import {FirebaseRepositoryRequest} from '../request/firebase-repository.request'; +import {FirestoreError} from 'firebase/firestore'; export class NgxFirebaseRepositoryReadRequestError extends NgxFirebaseRepositoryError { diff --git a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-update-request.error.ts b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-update-request.error.ts index 4aee1d6..4455957 100644 --- a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-update-request.error.ts +++ b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository-update-request.error.ts @@ -1,7 +1,6 @@ -import firebase from 'firebase'; -import { NgxFirebaseRepositoryError } from './ngx-firebase-repository.error'; -import { FirebaseRepositoryRequest } from '../request/firebase-repository.request'; -import FirebaseError = firebase.FirebaseError; +import {NgxFirebaseRepositoryError} from './ngx-firebase-repository.error'; +import {FirebaseRepositoryRequest} from '../request/firebase-repository.request'; +import {FirebaseError} from 'firebase/app'; export class NgxFirebaseRepositoryUpdateRequestError extends NgxFirebaseRepositoryError { diff --git a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository.error.ts b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository.error.ts index 372ed3d..677ff0e 100644 --- a/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository.error.ts +++ b/projects/ngx-firebase-repository/src/lib/error/ngx-firebase-repository.error.ts @@ -1,13 +1,11 @@ -import firebase from 'firebase'; import { omitBy } from 'lodash'; import { FirebaseRepositoryRequest } from '../request/firebase-repository.request'; -import FirebaseError = firebase.FirebaseError; const IGNORED_KEYS: string[] = ['paths', 'readPath', 'createPath', 'updatePath', 'deletePath', 'pathParams', 'replaceParams']; export class NgxFirebaseRepositoryError extends Error { - public constructor(request: FirebaseRepositoryRequest, firebaseError: FirebaseError) { + public constructor(request: FirebaseRepositoryRequest, firebaseError: Error) { let message: string = `An error occurred when the path '${request.path.value}' was requested : ${firebaseError.message}`; const r: any = omitBy(request, (v: any, key: string) => { return IGNORED_KEYS.indexOf(key) !== -1 || v == null || (Array.isArray(v) && v.length === 0); diff --git a/projects/ngx-firebase-repository/src/lib/firestore.ts b/projects/ngx-firebase-repository/src/lib/firestore.ts new file mode 100644 index 0000000..a55108e --- /dev/null +++ b/projects/ngx-firebase-repository/src/lib/firestore.ts @@ -0,0 +1 @@ +export { doc, collection, deleteDoc, addDoc, updateDoc, setDoc } from 'firebase/firestore'; diff --git a/projects/ngx-firebase-repository/src/lib/normalizer/firebase.normalizer.ts b/projects/ngx-firebase-repository/src/lib/normalizer/firebase.normalizer.ts index 88b0b69..fb81fc4 100644 --- a/projects/ngx-firebase-repository/src/lib/normalizer/firebase.normalizer.ts +++ b/projects/ngx-firebase-repository/src/lib/normalizer/firebase.normalizer.ts @@ -1,13 +1,12 @@ import {Inject, Injectable} from '@angular/core'; import {set} from 'lodash'; -import firebase from 'firebase'; import {FIREBASE_CREATED_AT_METADATA_KEY} from '../decorator/firebase-created-at.decorator'; import {FIREBASE_UPDATED_AT_METADATA_KEY} from '../decorator/firebase-updated-at.decorator'; import {NormalizerConfiguration, RepositoryNormalizer} from '@witty-services/ngx-repository'; import {FirebaseCreatedAtContextConfiguration} from '../configuration/context/firebase-created-at-context.configuration'; import {FirebaseUpdatedAtContextConfiguration} from '../configuration/context/firebase-updated-at-context.configuration'; -import FieldValue = firebase.firestore.FieldValue; import {NORMALIZER_CONFIGURATION_TOKEN} from '@witty-services/ngx-serializer'; +import {serverTimestamp} from 'firebase/firestore'; /** * @ignore @@ -24,12 +23,12 @@ export class FirebaseNormalizer extends RepositoryNormalizer { const createdAts: FirebaseCreatedAtContextConfiguration[] = Reflect.getMetadata(FIREBASE_CREATED_AT_METADATA_KEY, object) || []; createdAts.forEach((createdAt: FirebaseCreatedAtContextConfiguration) => { - set(result, createdAt.field, FieldValue.serverTimestamp()); + set(result, createdAt.field, serverTimestamp()); }); const updatedAts: FirebaseUpdatedAtContextConfiguration[] = Reflect.getMetadata(FIREBASE_UPDATED_AT_METADATA_KEY, object) || []; updatedAts.forEach((updatedAt: FirebaseUpdatedAtContextConfiguration) => { - set(result, updatedAt.field, FieldValue.serverTimestamp()); + set(result, updatedAt.field, serverTimestamp()); }); return result; diff --git a/projects/ngx-firebase-repository/src/lib/request/firebase.criteria.ts b/projects/ngx-firebase-repository/src/lib/request/firebase.criteria.ts index ba0c75e..5966304 100644 --- a/projects/ngx-firebase-repository/src/lib/request/firebase.criteria.ts +++ b/projects/ngx-firebase-repository/src/lib/request/firebase.criteria.ts @@ -3,7 +3,6 @@ import { getDeepQueryMetadataValues, PropertyKeyConfiguration } from '@witty-services/ngx-repository'; -import firebase from 'firebase'; import { FIREBASE_CRITERIA_METADATA_KEY } from '../decorator/firebase-criteria.decorator'; import { FIREBASE_ORDER_BY_METADATA_KEY } from '../decorator/firebase-order-by.decorator'; import { FIREBASE_START_AT_METADATA_KEY } from '../decorator/firebase-start-at.decorator'; @@ -17,10 +16,7 @@ import { FirebaseOrderByContext, FirebaseOrderByContextConfiguration } from '../configuration/context/firebase-order-by-context.configuration'; -import OrderByDirection = firebase.firestore.OrderByDirection; -import FieldPath = firebase.firestore.FieldPath; -import WhereFilterOp = firebase.firestore.WhereFilterOp; - +import {FieldPath, OrderByDirection, WhereFilterOp} from 'firebase/firestore'; export interface FirebaseRequestQuery { @@ -70,54 +66,60 @@ export class FirebaseCriteria { } } - protected getQueries(query: any): FirebaseRequestQuery[] { const queries: FirebaseRequestQuery[] = []; - const firebaseCriterias: FirebaseCriteriaContextConfiguration[] = getDeepQueryMetadataValues(FIREBASE_CRITERIA_METADATA_KEY, query); - firebaseCriterias.forEach((firebaseCriteria: FirebaseCriteriaContextConfiguration) => { - if (query[firebaseCriteria.propertyKey] == null) { - return; - } - queries.push({ - field: firebaseCriteria.field, - operator: firebaseCriteria.operator, - value: query[firebaseCriteria.propertyKey] + if (query) { + const firebaseCriterias: FirebaseCriteriaContextConfiguration[] = getDeepQueryMetadataValues(FIREBASE_CRITERIA_METADATA_KEY, query); + + firebaseCriterias.forEach((firebaseCriteria: FirebaseCriteriaContextConfiguration) => { + if (query[firebaseCriteria.propertyKey] == null) { + return; + } + + queries.push({ + field: firebaseCriteria.field, + operator: firebaseCriteria.operator, + value: query[firebaseCriteria.propertyKey] + }); }); - }); + } return queries; } protected getOrderBy(query: any): FirebaseRequestOrderBy[] { const orderBys: FirebaseRequestOrderBy[] = []; - const firebaseOrderBy: FirebaseOrderByContextConfiguration = getDeepQueryMetadataValue(FIREBASE_ORDER_BY_METADATA_KEY, query); - if (!firebaseOrderBy || query[firebaseOrderBy.propertyKey] == null) { - return orderBys; - } - - const value: string | FirebaseOrderByContext | (string | FirebaseOrderByContext)[] = query[firebaseOrderBy.propertyKey]; - function addOrderBy(v: string | FirebaseOrderByContext): void { - let sort: FirebaseOrderByContext; - if (!(v instanceof Object)) { - sort = { - field: v as string - }; - } else { - sort = v as FirebaseOrderByContext; + if (query) { + const firebaseOrderBy: FirebaseOrderByContextConfiguration = getDeepQueryMetadataValue(FIREBASE_ORDER_BY_METADATA_KEY, query); + if (!firebaseOrderBy || query[firebaseOrderBy.propertyKey] == null) { + return orderBys; } - orderBys.push({ - fieldPath: sort.field, - directionStr: sort.directionStr - }); - } + const value: string | FirebaseOrderByContext | (string | FirebaseOrderByContext)[] = query[firebaseOrderBy.propertyKey]; + + function addOrderBy(v: string | FirebaseOrderByContext): void { + let sort: FirebaseOrderByContext; + if (!(v instanceof Object)) { + sort = { + field: v as string + }; + } else { + sort = v as FirebaseOrderByContext; + } + + orderBys.push({ + fieldPath: sort.field, + directionStr: sort.directionStr + }); + } - if (Array.isArray(value)) { - value.forEach(addOrderBy); - } else { - addOrderBy(value); + if (Array.isArray(value)) { + value.forEach(addOrderBy); + } else { + addOrderBy(value); + } } return orderBys; diff --git a/projects/ngx-firebase-repository/src/lib/response/firebase-collection-repository.response.ts b/projects/ngx-firebase-repository/src/lib/response/firebase-collection-repository.response.ts index c52a947..eeab2e6 100644 --- a/projects/ngx-firebase-repository/src/lib/response/firebase-collection-repository.response.ts +++ b/projects/ngx-firebase-repository/src/lib/response/firebase-collection-repository.response.ts @@ -1,8 +1,6 @@ -import firebase from 'firebase'; -import { FirebaseRepositoryResponse } from './firebase-repository.response'; -import { RepositoryRequest } from '@witty-services/ngx-repository'; -import QuerySnapshot = firebase.firestore.QuerySnapshot; -import DocumentSnapshot = firebase.firestore.DocumentSnapshot; +import {FirebaseRepositoryResponse} from './firebase-repository.response'; +import {RepositoryRequest} from '@witty-services/ngx-repository'; +import {DocumentSnapshot, QuerySnapshot} from 'firebase/firestore'; export class FirebaseCollectionRepositoryResponse implements FirebaseRepositoryResponse { diff --git a/projects/ngx-firebase-repository/src/lib/response/firebase-document-reference-repository.response.ts b/projects/ngx-firebase-repository/src/lib/response/firebase-document-reference-repository.response.ts index bd651d9..c8f549f 100644 --- a/projects/ngx-firebase-repository/src/lib/response/firebase-document-reference-repository.response.ts +++ b/projects/ngx-firebase-repository/src/lib/response/firebase-document-reference-repository.response.ts @@ -1,7 +1,6 @@ -import firebase from 'firebase'; -import { FirebaseRepositoryResponse } from './firebase-repository.response'; -import { RepositoryRequest } from '@witty-services/ngx-repository'; -import DocumentReference = firebase.firestore.DocumentReference; +import {FirebaseRepositoryResponse} from './firebase-repository.response'; +import {RepositoryRequest} from '@witty-services/ngx-repository'; +import {DocumentReference} from 'firebase/firestore'; export class FirebaseDocumentReferenceRepositoryResponse implements FirebaseRepositoryResponse { diff --git a/projects/ngx-firebase-repository/src/lib/response/firebase-document-repository.response.ts b/projects/ngx-firebase-repository/src/lib/response/firebase-document-repository.response.ts index 98cc797..ea8ed85 100644 --- a/projects/ngx-firebase-repository/src/lib/response/firebase-document-repository.response.ts +++ b/projects/ngx-firebase-repository/src/lib/response/firebase-document-repository.response.ts @@ -1,7 +1,6 @@ -import firebase from 'firebase'; -import { FirebaseRepositoryResponse } from './firebase-repository.response'; -import { RepositoryRequest } from '@witty-services/ngx-repository'; -import DocumentSnapshot = firebase.firestore.DocumentSnapshot; +import {FirebaseRepositoryResponse} from './firebase-repository.response'; +import {RepositoryRequest} from '@witty-services/ngx-repository'; +import {DocumentSnapshot} from 'firebase/firestore'; export class FirebaseDocumentRepositoryResponse implements FirebaseRepositoryResponse { diff --git a/projects/ngx-http-repository/package.json b/projects/ngx-http-repository/package.json index 9c07edc..93738f9 100644 --- a/projects/ngx-http-repository/package.json +++ b/projects/ngx-http-repository/package.json @@ -1,10 +1,10 @@ { "name": "@witty-services/ngx-http-repository", - "version": "3.0.0-rc.14", + "version": "3.0.0-rc.15", "peerDependencies": { "@angular/common": ">=8.0.3-rc.0 || >=8.0.3", "@angular/core": ">=8.0.3-rc.0 || >=8.0.3", - "@witty-services/ngx-repository": "^3.0.0" + "@witty-services/ngx-repository": "^3.0.0-rc.0 || ^3.0.0" }, "repository": { "type": "git", diff --git a/projects/ngx-repository/package.json b/projects/ngx-repository/package.json index fd9d559..cf97861 100644 --- a/projects/ngx-repository/package.json +++ b/projects/ngx-repository/package.json @@ -1,12 +1,12 @@ { "name": "@witty-services/ngx-repository", - "version": "3.0.0-rc.14", + "version": "3.0.0-rc.15", "peerDependencies": { "@angular/common": ">=8.0.3-rc.0 || >=8.0.3", "@angular/core": ">=8.0.3-rc.0 || >=8.0.3" }, "dependencies": { - "@witty-services/ngx-serializer": "^1.0.3", + "@witty-services/ngx-serializer": "^1.0.6", "@witty-services/rxjs-common": "^1.0.6", "object-hash": "^2.0.3", "tslib": "^2.0.0" diff --git a/projects/ngx-repository/src/lib/core/configuration/context/column-context.configuration.ts b/projects/ngx-repository/src/lib/core/configuration/context/column-context.configuration.ts index 8c36306..d6b5a06 100644 --- a/projects/ngx-repository/src/lib/core/configuration/context/column-context.configuration.ts +++ b/projects/ngx-repository/src/lib/core/configuration/context/column-context.configuration.ts @@ -1,4 +1,5 @@ -import {Converter, JsonPropertyContext, JsonPropertyContextConfiguration} from '@witty-services/ts-serializer'; +import {ConstructorFunction, Converter, JsonPropertyContext, JsonPropertyContextConfiguration} from '@witty-services/ts-serializer'; +import {SerializeType} from '@witty-services/ts-serializer/dist/common'; /** * Describe advanced configuration for Column decorator. @@ -13,7 +14,7 @@ export interface ColumnContext extends JsonPropertyContext { /** * Field type after deserialization. */ - type?: () => new(...args: any[]) => T; + type?: () => SerializeType|SerializeType[]; /** * Boolean to indicate to not send the value in json to the server. @@ -28,7 +29,7 @@ export interface ColumnContext extends JsonPropertyContext { /** * A converter to make a custom serialization/deserialization */ - customConverter?: () => new(...args: any[]) => Converter; + customConverter?: () => ConstructorFunction>; /** * Boolean to override global configuration to denormalize the column when is set to null value diff --git a/projects/ngx-repository/src/lib/core/configuration/context/id-context.configuration.ts b/projects/ngx-repository/src/lib/core/configuration/context/id-context.configuration.ts index d164181..1475eee 100644 --- a/projects/ngx-repository/src/lib/core/configuration/context/id-context.configuration.ts +++ b/projects/ngx-repository/src/lib/core/configuration/context/id-context.configuration.ts @@ -1,4 +1,4 @@ -import { Converter } from '@witty-services/ts-serializer'; +import {ConstructorFunction, Converter} from '@witty-services/ts-serializer'; export interface IdContext { @@ -40,5 +40,5 @@ export interface IdContext { /** * A converter to make a custom serialization/deserialization */ - customConverter?: () => new(...args: any[]) => Converter; + customConverter?: () => ConstructorFunction>; } diff --git a/projects/ngx-repository/src/lib/core/configuration/context/join-column-context.configuration.ts b/projects/ngx-repository/src/lib/core/configuration/context/join-column-context.configuration.ts index 54b3ba7..b764f81 100644 --- a/projects/ngx-repository/src/lib/core/configuration/context/join-column-context.configuration.ts +++ b/projects/ngx-repository/src/lib/core/configuration/context/join-column-context.configuration.ts @@ -1,12 +1,13 @@ import {Type} from '@angular/core'; import {AbstractRepository} from '../../repository/abstract-repository'; import {PropertyKeyConfiguration} from '../../common/decorator/property-key-configuration'; +import {SerializeType} from '@witty-services/ts-serializer/dist/common'; export interface JoinColumnContext { attribute: string; - resourceType: () => new(...args: any[]) => T; + resourceType: () => SerializeType; repository?: () => Type>; } diff --git a/projects/ngx-repository/src/lib/core/decorator/column.decorator.ts b/projects/ngx-repository/src/lib/core/decorator/column.decorator.ts index de29aa9..a608319 100644 --- a/projects/ngx-repository/src/lib/core/decorator/column.decorator.ts +++ b/projects/ngx-repository/src/lib/core/decorator/column.decorator.ts @@ -1,5 +1,6 @@ import {JSON_PROPERTY_METADATA_KEY, JsonProperty} from '@witty-services/ts-serializer'; import {ColumnContext} from '../configuration/context/column-context.configuration'; +import {SerializeType} from '@witty-services/ts-serializer/dist/common'; /** * @ignore @@ -30,7 +31,7 @@ export const COLUMNS_METADATA_KEY: string = JSON_PROPERTY_METADATA_KEY; * * @param columnContext Decorator configuration */ -export function Column(columnContext?: ColumnContext|string|(() => new(...args: any[]) => T)): any { +export function Column(columnContext?: ColumnContext|string|(() => SerializeType|SerializeType[])): any { return (target: any, propertyKey: string) => { JsonProperty(columnContext)(target, propertyKey); }; diff --git a/projects/ngx-repository/src/lib/core/decorator/sub-query.decorator.ts b/projects/ngx-repository/src/lib/core/decorator/sub-query.decorator.ts index 25c74f1..56002e4 100644 --- a/projects/ngx-repository/src/lib/core/decorator/sub-query.decorator.ts +++ b/projects/ngx-repository/src/lib/core/decorator/sub-query.decorator.ts @@ -1,4 +1,4 @@ -import { first, flattenDeep, isString } from 'lodash'; +import { first, flattenDeep, isArray, isString } from 'lodash'; import { PropertyKeyConfiguration } from '../common/decorator/property-key-configuration'; /** @@ -21,7 +21,12 @@ export function getDeepQueryMetadataValues(m } const childMetadata: T[] = subQueries.map((subQuery: string) => getDeepQueryMetadataValues(metadataKey, query[subQuery], parent ? `${ parent }.${ subQuery }` : subQuery)); - const metadata: T[] = Reflect.getMetadata(metadataKey, query) || []; + + let metadata: T[]|T = Reflect.getMetadata(metadataKey, query) || []; + + if (!isArray(metadata)) { + metadata = [metadata]; + } const modifiedMetadata: T[] = metadata .map((property: PropertyKeyConfiguration) => ({