@goatlab/fluent-firebase 0.6.8 → 0.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FirebaseConnector.d.ts +5 -4
- package/dist/FirebaseConnector.js +48 -9
- package/dist/firebaseConnector.http_spec.js +1 -1
- package/dist/test/advanced/advancedTestSuite.js +14 -14
- package/dist/test/advanced/firebase.repository.js +2 -1
- package/dist/test/relations/relationsTestsSuite.js +10 -10
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as admin from 'firebase-admin';
|
|
2
2
|
import { BaseFirestoreRepository } from 'fireorm';
|
|
3
3
|
import type { Filter, DaoOutput, BaseDataElement, PaginatedData, Paginator, Sure } from '@goatlab/fluent';
|
|
4
|
-
import { BaseConnector, FluentConnectorInterface } from '@goatlab/fluent';
|
|
5
|
-
export declare const createFirebaseRepository: (Entity: any) => {
|
|
4
|
+
import { BaseConnector, DataSource, FluentConnectorInterface } from '@goatlab/fluent';
|
|
5
|
+
export declare const createFirebaseRepository: (Entity: any, dataSource: DataSource) => {
|
|
6
6
|
repository: BaseFirestoreRepository<import("fireorm").IEntity>;
|
|
7
7
|
name: string;
|
|
8
8
|
path: string;
|
|
@@ -11,8 +11,8 @@ export declare const createFirebaseRepository: (Entity: any) => {
|
|
|
11
11
|
};
|
|
12
12
|
export declare class FirebaseConnector<ModelDTO = BaseDataElement, InputDTO = ModelDTO, OutputDTO = InputDTO> extends BaseConnector<ModelDTO, InputDTO, OutputDTO> implements FluentConnectorInterface<InputDTO, DaoOutput<InputDTO, OutputDTO>> {
|
|
13
13
|
private repository;
|
|
14
|
-
private collection;
|
|
15
|
-
constructor(Entity: any, relationQuery?: any);
|
|
14
|
+
private readonly collection;
|
|
15
|
+
constructor(Entity: any, dataSource: DataSource, relationQuery?: any);
|
|
16
16
|
get(): Promise<DaoOutput<InputDTO, OutputDTO>[]>;
|
|
17
17
|
getPaginated(): Promise<PaginatedData<DaoOutput<InputDTO, OutputDTO>>>;
|
|
18
18
|
all(): Promise<DaoOutput<InputDTO, OutputDTO>[]>;
|
|
@@ -27,6 +27,7 @@ export declare class FirebaseConnector<ModelDTO = BaseDataElement, InputDTO = Mo
|
|
|
27
27
|
clear({ sure }: Sure): Promise<unknown>;
|
|
28
28
|
deleteById(id: string): Promise<string>;
|
|
29
29
|
findById(id: string): Promise<DaoOutput<InputDTO, OutputDTO>>;
|
|
30
|
+
findByIds(ids: string[]): Promise<DaoOutput<InputDTO, OutputDTO>[] | null>;
|
|
30
31
|
private getPage;
|
|
31
32
|
private getPaginatorLimit;
|
|
32
33
|
private getPopulate;
|
|
@@ -7,14 +7,14 @@ const fireorm_1 = require("fireorm");
|
|
|
7
7
|
const firestore_1 = require("@google-cloud/firestore");
|
|
8
8
|
const fluent_1 = require("@goatlab/fluent");
|
|
9
9
|
const js_utils_1 = require("@goatlab/js-utils");
|
|
10
|
-
const createFirebaseRepository = Entity => {
|
|
11
|
-
const typeOrmRepo =
|
|
10
|
+
const createFirebaseRepository = (Entity, dataSource) => {
|
|
11
|
+
const typeOrmRepo = dataSource.getRepository(Entity);
|
|
12
12
|
const repository = (0, fireorm_1.getRepository)(Entity);
|
|
13
13
|
let name = '';
|
|
14
14
|
let path = '';
|
|
15
15
|
const relations = {};
|
|
16
16
|
for (const relation of typeOrmRepo.metadata.relations) {
|
|
17
|
-
relations[relation.
|
|
17
|
+
relations[relation.propertyName] = {
|
|
18
18
|
isOneToMany: relation.isOneToMany,
|
|
19
19
|
isManyToOne: relation.isManyToOne,
|
|
20
20
|
isManyToMany: relation.isManyToMany,
|
|
@@ -45,9 +45,9 @@ const createFirebaseRepository = Entity => {
|
|
|
45
45
|
};
|
|
46
46
|
exports.createFirebaseRepository = createFirebaseRepository;
|
|
47
47
|
class FirebaseConnector extends fluent_1.BaseConnector {
|
|
48
|
-
constructor(Entity, relationQuery) {
|
|
48
|
+
constructor(Entity, dataSource, relationQuery) {
|
|
49
49
|
super();
|
|
50
|
-
const { repository, keys, name, relations } = (0, exports.createFirebaseRepository)(Entity);
|
|
50
|
+
const { repository, keys, name, relations } = (0, exports.createFirebaseRepository)(Entity, dataSource);
|
|
51
51
|
this.relationQuery = relationQuery;
|
|
52
52
|
this.repository = repository;
|
|
53
53
|
this.collection = admin.firestore().collection(name);
|
|
@@ -56,9 +56,28 @@ class FirebaseConnector extends fluent_1.BaseConnector {
|
|
|
56
56
|
}
|
|
57
57
|
async get() {
|
|
58
58
|
let query = this.getGeneratedQuery();
|
|
59
|
-
|
|
59
|
+
let pivotData = [];
|
|
60
|
+
if (this.relationQuery && this.relationQuery.data && this.relationQuery.relation) {
|
|
60
61
|
const ids = this.relationQuery.data.map(d => d.id);
|
|
61
|
-
|
|
62
|
+
if (this.relationQuery?.relation?.isManyToMany) {
|
|
63
|
+
const pivotForeignKey = this.relationQuery.relation.joinColumns[0].propertyName;
|
|
64
|
+
const pivotInverseKey = this.relationQuery.relation.inverseJoinColumns[0].propertyName;
|
|
65
|
+
const { pivot } = this.relationQuery;
|
|
66
|
+
pivotData = await pivot.where(key => key[pivotForeignKey], "in", ids).get();
|
|
67
|
+
if (!pivotData.length) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const inverseIds = [...new Set(pivotData.map(d => d[pivotInverseKey]))];
|
|
71
|
+
if (!inverseIds.length) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
if (inverseIds.length) {
|
|
75
|
+
query = query.where("id", 'in', inverseIds);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
query = query.where(this.relationQuery.relation.inverseSidePropertyPath, 'in', ids);
|
|
80
|
+
}
|
|
62
81
|
}
|
|
63
82
|
const snapshot = await query.get();
|
|
64
83
|
const result = [];
|
|
@@ -71,8 +90,15 @@ class FirebaseConnector extends fluent_1.BaseConnector {
|
|
|
71
90
|
relations: this.relations,
|
|
72
91
|
modelRelations: this.modelRelations,
|
|
73
92
|
provider: 'firebase',
|
|
74
|
-
self: this
|
|
93
|
+
self: this,
|
|
94
|
+
returnPivot: Boolean(this.relationQuery?.returnPivot)
|
|
75
95
|
});
|
|
96
|
+
if (pivotData.length && this.relationQuery?.returnPivot) {
|
|
97
|
+
const pivotInverseKey = this.relationQuery.relation.inverseJoinColumns[0].propertyName;
|
|
98
|
+
data = data.map(d => {
|
|
99
|
+
return { ...d, pivot: pivotData.find(p => p[pivotInverseKey] === d.id) };
|
|
100
|
+
});
|
|
101
|
+
}
|
|
76
102
|
this.reset();
|
|
77
103
|
return data;
|
|
78
104
|
}
|
|
@@ -215,10 +241,23 @@ class FirebaseConnector extends fluent_1.BaseConnector {
|
|
|
215
241
|
const result = this.jsApplySelect(data);
|
|
216
242
|
this.reset();
|
|
217
243
|
if (result.length === 0) {
|
|
218
|
-
return
|
|
244
|
+
return null;
|
|
219
245
|
}
|
|
220
246
|
return result[0];
|
|
221
247
|
}
|
|
248
|
+
async findByIds(ids) {
|
|
249
|
+
const data = await this.raw().where('id', 'in', ids).get();
|
|
250
|
+
if (data.empty) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
const res = [];
|
|
254
|
+
data.forEach(doc => {
|
|
255
|
+
res.push(doc.data());
|
|
256
|
+
});
|
|
257
|
+
const results = this.jsApplySelect(res);
|
|
258
|
+
this.reset();
|
|
259
|
+
return results;
|
|
260
|
+
}
|
|
222
261
|
getPage() {
|
|
223
262
|
const page = 'page=';
|
|
224
263
|
if (this.paginator && this.paginator.page) {
|
|
@@ -17,7 +17,7 @@ const basicTestSuite_1 = require("./test/basic/basicTestSuite");
|
|
|
17
17
|
const relationsTestsSuite_1 = require("./test/relations/relationsTestsSuite");
|
|
18
18
|
jest.setTimeout(3 * 60 * 1000);
|
|
19
19
|
beforeAll(async () => {
|
|
20
|
-
await fluent_1.Fluent.
|
|
20
|
+
await fluent_1.Fluent.initialize([], [
|
|
21
21
|
goat_entity_1.GoatEntity,
|
|
22
22
|
typeOrm_entity_1.TypeORMDataModel,
|
|
23
23
|
car_entity_1.CarsEntity,
|
|
@@ -48,40 +48,40 @@ const advancedTestSuite = Model => {
|
|
|
48
48
|
});
|
|
49
49
|
it('pluck() should return a single array', async () => {
|
|
50
50
|
await insertTestData(Model);
|
|
51
|
-
const data = await Model.pluck(
|
|
51
|
+
const data = await Model.pluck(keys => keys.test);
|
|
52
52
|
expect(typeof data[0]).toBe('boolean');
|
|
53
53
|
});
|
|
54
54
|
it('orderBy() should order results desc', async () => {
|
|
55
55
|
await insertTestData(Model);
|
|
56
|
-
const forms = await Model.select(
|
|
57
|
-
.orderBy(
|
|
56
|
+
const forms = await Model.select(keys => [keys.test, keys.nestedTest.b.c, keys.order])
|
|
57
|
+
.orderBy(keys => keys.order, 'desc')
|
|
58
58
|
.get();
|
|
59
59
|
expect(forms[0].order).toBe(3);
|
|
60
60
|
expect(forms[0].nestedTest.b.c).toBe(true);
|
|
61
61
|
});
|
|
62
62
|
it('orderBy() should order results asc', async () => {
|
|
63
63
|
await insertTestData(Model);
|
|
64
|
-
const forms = await Model.select(
|
|
65
|
-
.orderBy(
|
|
64
|
+
const forms = await Model.select(keys => [keys.test, keys.nestedTest.b.c, keys.order])
|
|
65
|
+
.orderBy(keys => keys.order, 'asc')
|
|
66
66
|
.get();
|
|
67
67
|
expect(forms[0].order).toBe(1);
|
|
68
68
|
});
|
|
69
69
|
it('orderBy() should order by Dates with Select()', async () => {
|
|
70
70
|
await insertTestData(Model);
|
|
71
|
-
const forms = await Model.select(
|
|
72
|
-
.orderBy(
|
|
71
|
+
const forms = await Model.select(keys => [keys.created, keys.order])
|
|
72
|
+
.orderBy(keys => keys.created, 'asc', 'date')
|
|
73
73
|
.get();
|
|
74
74
|
expect(forms[0].order).toBe(3);
|
|
75
75
|
});
|
|
76
76
|
it('orderBy() should order by Dates without Select()', async () => {
|
|
77
77
|
await insertTestData(Model);
|
|
78
|
-
const forms = await Model.orderBy(
|
|
78
|
+
const forms = await Model.orderBy(keys => keys.created, 'asc', 'date').get();
|
|
79
79
|
expect(forms[0].order).toBe(3);
|
|
80
80
|
});
|
|
81
81
|
it('limit() should limit the amount of results', async () => {
|
|
82
82
|
await insertTestData(Model);
|
|
83
|
-
const forms = await Model.select(
|
|
84
|
-
.orderBy(
|
|
83
|
+
const forms = await Model.select(keys => [keys.created, keys.order])
|
|
84
|
+
.orderBy(keys => keys.created, 'asc', 'date')
|
|
85
85
|
.limit(2)
|
|
86
86
|
.get();
|
|
87
87
|
expect(forms.length > 0).toBe(true);
|
|
@@ -89,7 +89,7 @@ const advancedTestSuite = Model => {
|
|
|
89
89
|
});
|
|
90
90
|
it('offset() should start at the given position', async () => {
|
|
91
91
|
await insertTestData(Model);
|
|
92
|
-
const forms = await Model.select(
|
|
92
|
+
const forms = await Model.select(keys => [keys.created, keys.order])
|
|
93
93
|
.offset(1)
|
|
94
94
|
.limit(1)
|
|
95
95
|
.get();
|
|
@@ -97,7 +97,7 @@ const advancedTestSuite = Model => {
|
|
|
97
97
|
});
|
|
98
98
|
it('where() should filter the data', async () => {
|
|
99
99
|
await insertTestData(Model);
|
|
100
|
-
const forms = await Model.where(
|
|
100
|
+
const forms = await Model.where(keys => keys.nestedTest.c, '>=', 3).get();
|
|
101
101
|
expect(forms.length > 0).toBe(true);
|
|
102
102
|
forms.forEach(form => {
|
|
103
103
|
expect(form.nestedTest.c >= 3).toBe(true);
|
|
@@ -105,8 +105,8 @@ const advancedTestSuite = Model => {
|
|
|
105
105
|
});
|
|
106
106
|
it('first() should take the first result from data', async () => {
|
|
107
107
|
await insertTestData(Model);
|
|
108
|
-
const form = await Model.select(
|
|
109
|
-
.where(
|
|
108
|
+
const form = await Model.select(keys => [keys.nestedTest.c, keys.id])
|
|
109
|
+
.where(keys => keys.nestedTest.c, '>=', 3)
|
|
110
110
|
.first();
|
|
111
111
|
expect(typeof form.nestedTest.c).toBe('number');
|
|
112
112
|
});
|
|
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.FirebaseRepository = void 0;
|
|
4
4
|
const FirebaseConnector_1 = require("../../FirebaseConnector");
|
|
5
5
|
const typeOrm_entity_1 = require("./typeOrm.entity");
|
|
6
|
+
const fluent_1 = require("@goatlab/fluent");
|
|
6
7
|
class FirebaseRepository extends FirebaseConnector_1.FirebaseConnector {
|
|
7
8
|
constructor(relations) {
|
|
8
|
-
super(typeOrm_entity_1.TypeORMDataModel,
|
|
9
|
+
super(typeOrm_entity_1.TypeORMDataModel, fluent_1.modelGeneratorDataSource, relations);
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
12
|
exports.FirebaseRepository = FirebaseRepository;
|
|
@@ -13,7 +13,7 @@ const relationsTestSuite = (Model, BelongsToModel, ManyToManyModel) => {
|
|
|
13
13
|
age: 20
|
|
14
14
|
});
|
|
15
15
|
expect(typeof insertedUser.id).toBe('string');
|
|
16
|
-
const user = await Model.where(
|
|
16
|
+
const user = await Model.where(keys => keys.id, '=', insertedUser.id).load();
|
|
17
17
|
const cars = await user.cars().attach({ name: 'Another new car' });
|
|
18
18
|
expect(Array.isArray(cars)).toBe(true);
|
|
19
19
|
expect(cars[0].name).toBe('Another new car');
|
|
@@ -24,23 +24,23 @@ const relationsTestSuite = (Model, BelongsToModel, ManyToManyModel) => {
|
|
|
24
24
|
age: 20
|
|
25
25
|
});
|
|
26
26
|
expect(typeof insertedUser.id).toBe('string');
|
|
27
|
-
const user1 = await Model.where(
|
|
27
|
+
const user1 = await Model.where(keys => keys.id, '=', insertedUser.id).load();
|
|
28
28
|
const cars = await user1.cars().attach({ name: 'My new car' });
|
|
29
29
|
expect(Array.isArray(cars)).toBe(true);
|
|
30
|
-
const searchUserWithRelation = await Model.where(
|
|
31
|
-
.with({ cars:
|
|
30
|
+
const searchUserWithRelation = await Model.where(keys => keys.id, '=', insertedUser.id)
|
|
31
|
+
.with({ cars: ManyToManyModel })
|
|
32
32
|
.get();
|
|
33
33
|
expect(Array.isArray(searchUserWithRelation[0].cars)).toBe(true);
|
|
34
34
|
expect(searchUserWithRelation[0].cars.length > 0).toBe(true);
|
|
35
35
|
const searchCar = await user1
|
|
36
36
|
.cars()
|
|
37
|
-
.where(
|
|
37
|
+
.where(keys => keys.name, '=', 'My new car')
|
|
38
38
|
.get();
|
|
39
39
|
expect(Array.isArray(searchCar)).toBe(true);
|
|
40
40
|
expect(searchCar.length > 0).toBe(true);
|
|
41
41
|
const searchCar2 = await user1
|
|
42
42
|
.cars()
|
|
43
|
-
.where(
|
|
43
|
+
.where(keys => keys.name, '=', 'My.......')
|
|
44
44
|
.get();
|
|
45
45
|
expect(Array.isArray(searchCar2)).toBe(true);
|
|
46
46
|
expect(searchCar2.length === 0).toBe(true);
|
|
@@ -51,7 +51,7 @@ const relationsTestSuite = (Model, BelongsToModel, ManyToManyModel) => {
|
|
|
51
51
|
age: 20
|
|
52
52
|
});
|
|
53
53
|
expect(typeof insertedUser.id).toBe('string');
|
|
54
|
-
const user1 = await Model.where(
|
|
54
|
+
const user1 = await Model.where(keys => keys.id, '=', insertedUser.id).load();
|
|
55
55
|
await user1.cars().attach({ name: 'My new car' });
|
|
56
56
|
const results = await BelongsToModel.with({ users: true }).get();
|
|
57
57
|
expect(Array.isArray(results)).toBe(true);
|
|
@@ -67,11 +67,11 @@ const relationsTestSuite = (Model, BelongsToModel, ManyToManyModel) => {
|
|
|
67
67
|
const adminRole = await ManyToManyModel.insert({
|
|
68
68
|
name: 'Administrator'
|
|
69
69
|
});
|
|
70
|
-
const user = await Model.where(
|
|
70
|
+
const user = await Model.where(keys => keys.id, '=', insertedUser.id).load();
|
|
71
71
|
const associated = await user.roles().associate(adminRole.id);
|
|
72
72
|
expect(associated[0].userId).toBe(insertedUser.id);
|
|
73
73
|
expect(associated[0].roleId).toBe(adminRole.id);
|
|
74
|
-
const searchUserWithRelation = await Model.where(
|
|
74
|
+
const searchUserWithRelation = await Model.where(keys => keys.id, '=', insertedUser.id)
|
|
75
75
|
.with({
|
|
76
76
|
roles: true
|
|
77
77
|
})
|
|
@@ -79,7 +79,7 @@ const relationsTestSuite = (Model, BelongsToModel, ManyToManyModel) => {
|
|
|
79
79
|
expect(Array.isArray(searchUserWithRelation[0].roles)).toBe(true);
|
|
80
80
|
expect(searchUserWithRelation[0].roles.length > 0).toBe(true);
|
|
81
81
|
expect(typeof searchUserWithRelation[0].roles[0].name).toBe('string');
|
|
82
|
-
const roles = await ManyToManyModel.where(
|
|
82
|
+
const roles = await ManyToManyModel.where(keys => keys.name, '=', 'Administrator')
|
|
83
83
|
.with({
|
|
84
84
|
users: true
|
|
85
85
|
})
|