emberflow 1.0.8
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/LICENSE +21 -0
- package/README.md +40 -0
- package/lib/db-structure.d.ts +7 -0
- package/lib/db-structure.js +67 -0
- package/lib/db-structure.js.map +1 -0
- package/lib/index-utils.d.ts +20 -0
- package/lib/index-utils.js +324 -0
- package/lib/index-utils.js.map +1 -0
- package/lib/index.d.ts +23 -0
- package/lib/index.js +197 -0
- package/lib/index.js.map +1 -0
- package/lib/init-db-structure.d.ts +17 -0
- package/lib/init-db-structure.js +111 -0
- package/lib/init-db-structure.js.map +1 -0
- package/lib/logics/index.d.ts +2 -0
- package/lib/logics/index.js +77 -0
- package/lib/logics/index.js.map +1 -0
- package/lib/logics/view-logics.d.ts +3 -0
- package/lib/logics/view-logics.js +167 -0
- package/lib/logics/view-logics.js.map +1 -0
- package/lib/sample-custom/business-logics.d.ts +3 -0
- package/lib/sample-custom/business-logics.js +67 -0
- package/lib/sample-custom/business-logics.js.map +1 -0
- package/lib/sample-custom/db-structure.d.ts +29 -0
- package/lib/sample-custom/db-structure.js +36 -0
- package/lib/sample-custom/db-structure.js.map +1 -0
- package/lib/sample-custom/security.d.ts +2 -0
- package/lib/sample-custom/security.js +63 -0
- package/lib/sample-custom/security.js.map +1 -0
- package/lib/sample-custom/validators.d.ts +9 -0
- package/lib/sample-custom/validators.js +42 -0
- package/lib/sample-custom/validators.js.map +1 -0
- package/lib/tests/index-utils.test.d.ts +1 -0
- package/lib/tests/index-utils.test.js +600 -0
- package/lib/tests/index-utils.test.js.map +1 -0
- package/lib/tests/index.test.d.ts +1 -0
- package/lib/tests/index.test.js +496 -0
- package/lib/tests/index.test.js.map +1 -0
- package/lib/tests/init-db-structure.test.d.ts +1 -0
- package/lib/tests/init-db-structure.test.js +114 -0
- package/lib/tests/init-db-structure.test.js.map +1 -0
- package/lib/tests/logics/index.test.d.ts +1 -0
- package/lib/tests/logics/index.test.js +127 -0
- package/lib/tests/logics/index.test.js.map +1 -0
- package/lib/tests/logics/view-logics.test.d.ts +1 -0
- package/lib/tests/logics/view-logics.test.js +211 -0
- package/lib/tests/logics/view-logics.test.js.map +1 -0
- package/lib/tests/utils/misc.test.d.ts +1 -0
- package/lib/tests/utils/misc.test.js +31 -0
- package/lib/tests/utils/misc.test.js.map +1 -0
- package/lib/tests/utils/paths.test.d.ts +1 -0
- package/lib/tests/utils/paths.test.js +258 -0
- package/lib/tests/utils/paths.test.js.map +1 -0
- package/lib/tests/utils/query.test.d.ts +1 -0
- package/lib/tests/utils/query.test.js +72 -0
- package/lib/tests/utils/query.test.js.map +1 -0
- package/lib/tests/utils/sample.test.d.ts +1 -0
- package/lib/tests/utils/sample.test.js +52 -0
- package/lib/tests/utils/sample.test.js.map +1 -0
- package/lib/types.d.ts +78 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/lib/utils/db-structure.d.ts +2 -0
- package/lib/utils/db-structure.js +9 -0
- package/lib/utils/db-structure.js.map +1 -0
- package/lib/utils/misc.d.ts +1 -0
- package/lib/utils/misc.js +53 -0
- package/lib/utils/misc.js.map +1 -0
- package/lib/utils/paths.d.ts +16 -0
- package/lib/utils/paths.js +136 -0
- package/lib/utils/paths.js.map +1 -0
- package/lib/utils/query.d.ts +2 -0
- package/lib/utils/query.js +41 -0
- package/lib/utils/query.js.map +1 -0
- package/lib/utils/sample.d.ts +5 -0
- package/lib/utils/sample.js +37 -0
- package/lib/utils/sample.js.map +1 -0
- package/lib/utils.d.ts +12 -0
- package/lib/utils.js +67 -0
- package/lib/utils.js.map +1 -0
- package/package.json +37 -0
- package/src/sample-custom/business-logics.ts +51 -0
- package/src/sample-custom/db-structure.ts +33 -0
- package/src/sample-custom/security.ts +77 -0
- package/src/sample-custom/validators.ts +46 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const paths_1 = require("../../utils/paths");
|
|
27
|
+
const query_1 = require("../../utils/query");
|
|
28
|
+
const index_1 = require("../../index");
|
|
29
|
+
const admin = __importStar(require("firebase-admin"));
|
|
30
|
+
const db_structure_1 = require("../../sample-custom/db-structure");
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
32
|
+
(0, index_1.initializeEmberFlow)(admin, db_structure_1.dbStructure, db_structure_1.Entity, {}, {}, []);
|
|
33
|
+
// Mock fetchIds function
|
|
34
|
+
jest.mock("../../utils/query", () => ({
|
|
35
|
+
fetchIds: jest.fn(),
|
|
36
|
+
}));
|
|
37
|
+
describe("hydrateDocPath", () => {
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
// Clear the mock before each test
|
|
40
|
+
query_1.fetchIds.mockClear();
|
|
41
|
+
});
|
|
42
|
+
it("should skip path segments when no IDs are found for a given condition", async () => {
|
|
43
|
+
// Mock fetchIds to return an empty array for the user entity
|
|
44
|
+
const mockFetchIds = query_1.fetchIds;
|
|
45
|
+
mockFetchIds
|
|
46
|
+
.mockResolvedValueOnce([])
|
|
47
|
+
.mockResolvedValue(["321", "654"]);
|
|
48
|
+
const destDocPath = "users/{userId}/posts/{postId}";
|
|
49
|
+
const userCondition = {
|
|
50
|
+
fieldName: "id",
|
|
51
|
+
operator: "in",
|
|
52
|
+
value: ["123", "456"],
|
|
53
|
+
};
|
|
54
|
+
// Execute the hydrateDocPath function
|
|
55
|
+
const result = await (0, paths_1.hydrateDocPath)(destDocPath, {
|
|
56
|
+
user: userCondition,
|
|
57
|
+
});
|
|
58
|
+
// Check the result, expecting an empty array since no user IDs were found
|
|
59
|
+
expect(result).toEqual([]);
|
|
60
|
+
// Check if the mocked fetchIds function was called correctly
|
|
61
|
+
expect(mockFetchIds).toHaveBeenCalledTimes(1);
|
|
62
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(1, "users", userCondition);
|
|
63
|
+
});
|
|
64
|
+
it("should handle hard-coded IDs and skip non-existent paths", async () => {
|
|
65
|
+
// Mock Firestore document fetching
|
|
66
|
+
const docGet = jest.fn();
|
|
67
|
+
const doc = jest.fn(() => ({ get: docGet }));
|
|
68
|
+
const firestoreInstance = {
|
|
69
|
+
doc,
|
|
70
|
+
settings: jest.fn(),
|
|
71
|
+
collection: jest.fn(),
|
|
72
|
+
collectionGroup: jest.fn(),
|
|
73
|
+
getAll: jest.fn(),
|
|
74
|
+
runTransaction: jest.fn(),
|
|
75
|
+
batch: jest.fn(),
|
|
76
|
+
terminate: jest.fn(),
|
|
77
|
+
};
|
|
78
|
+
const firestoreMock = jest.fn(() => firestoreInstance);
|
|
79
|
+
jest.spyOn(admin, "firestore").mockImplementation(firestoreMock);
|
|
80
|
+
// Mock Firestore document existence
|
|
81
|
+
const existingDoc = { exists: true };
|
|
82
|
+
const nonExistingDoc = { exists: false };
|
|
83
|
+
docGet
|
|
84
|
+
.mockReturnValueOnce(existingDoc)
|
|
85
|
+
.mockReturnValueOnce(nonExistingDoc)
|
|
86
|
+
.mockReturnValueOnce(existingDoc);
|
|
87
|
+
// Define the input document path with hardcoded IDs
|
|
88
|
+
const destDocPath = "users/{userId}/posts/321";
|
|
89
|
+
const mockFetchIds = query_1.fetchIds;
|
|
90
|
+
mockFetchIds
|
|
91
|
+
.mockResolvedValue(["123", "456", "789"]);
|
|
92
|
+
// Execute the hydrateDocPath function
|
|
93
|
+
const result = await (0, paths_1.hydrateDocPath)(destDocPath, {});
|
|
94
|
+
// Check the result
|
|
95
|
+
expect(result).toEqual(["users/123/posts/321", "users/789/posts/321"]);
|
|
96
|
+
// Check if the mocked Firestore functions were called correctly
|
|
97
|
+
expect(firestoreMock).toHaveBeenCalledTimes(3);
|
|
98
|
+
expect(doc).toHaveBeenCalledTimes(3);
|
|
99
|
+
expect(doc).toHaveBeenNthCalledWith(1, "users/123/posts/321");
|
|
100
|
+
expect(doc).toHaveBeenNthCalledWith(2, "users/456/posts/321");
|
|
101
|
+
expect(doc).toHaveBeenNthCalledWith(3, "users/789/posts/321");
|
|
102
|
+
expect(docGet).toHaveBeenCalledTimes(3);
|
|
103
|
+
});
|
|
104
|
+
it("should return all possible document paths", async () => {
|
|
105
|
+
const mockFetchIds = query_1.fetchIds;
|
|
106
|
+
mockFetchIds
|
|
107
|
+
.mockResolvedValueOnce(["123", "456"])
|
|
108
|
+
.mockResolvedValue(["321", "654"]);
|
|
109
|
+
const destDocPath = "users/{userId}/posts/{postId}";
|
|
110
|
+
const allowedUsers = ["321", "654"];
|
|
111
|
+
const userCondition = {
|
|
112
|
+
fieldName: "id",
|
|
113
|
+
operator: "in",
|
|
114
|
+
value: allowedUsers,
|
|
115
|
+
};
|
|
116
|
+
const result = await (0, paths_1.hydrateDocPath)(destDocPath, {
|
|
117
|
+
user: userCondition,
|
|
118
|
+
});
|
|
119
|
+
expect(result).toEqual([
|
|
120
|
+
"users/123/posts/321",
|
|
121
|
+
"users/123/posts/654",
|
|
122
|
+
"users/456/posts/321",
|
|
123
|
+
"users/456/posts/654",
|
|
124
|
+
]);
|
|
125
|
+
expect(mockFetchIds).toHaveBeenCalledTimes(3);
|
|
126
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(1, "users", userCondition);
|
|
127
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(2, "users/123/posts", undefined);
|
|
128
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(3, "users/456/posts", undefined);
|
|
129
|
+
});
|
|
130
|
+
it("should return filtered document paths based on the provided entityCondition", async () => {
|
|
131
|
+
const mockFetchIds = query_1.fetchIds;
|
|
132
|
+
mockFetchIds
|
|
133
|
+
.mockResolvedValueOnce(["123", "456"])
|
|
134
|
+
.mockResolvedValue(["321", "654"]);
|
|
135
|
+
const destDocPath = "users/{userId}/posts/{postId}";
|
|
136
|
+
const allowedUsers = ["321", "654"];
|
|
137
|
+
const userCondition = {
|
|
138
|
+
fieldName: "id",
|
|
139
|
+
operator: "in",
|
|
140
|
+
value: allowedUsers,
|
|
141
|
+
};
|
|
142
|
+
// Add a condition to filter the posts based on a specific field
|
|
143
|
+
const postCondition = {
|
|
144
|
+
fieldName: "category",
|
|
145
|
+
operator: "==",
|
|
146
|
+
value: "technology",
|
|
147
|
+
};
|
|
148
|
+
const result = await (0, paths_1.hydrateDocPath)(destDocPath, {
|
|
149
|
+
user: userCondition,
|
|
150
|
+
post: postCondition,
|
|
151
|
+
});
|
|
152
|
+
// Adjust the expected result based on the postCondition
|
|
153
|
+
expect(result).toEqual([
|
|
154
|
+
"users/123/posts/321",
|
|
155
|
+
"users/123/posts/654",
|
|
156
|
+
"users/456/posts/321",
|
|
157
|
+
"users/456/posts/654",
|
|
158
|
+
]);
|
|
159
|
+
expect(mockFetchIds).toHaveBeenCalledTimes(3);
|
|
160
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(1, "users", userCondition);
|
|
161
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(2, "users/123/posts", postCondition);
|
|
162
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(3, "users/456/posts", postCondition);
|
|
163
|
+
});
|
|
164
|
+
it("should return empty document paths if fetchIds returns an empty array for one of the entities", async () => {
|
|
165
|
+
const mockFetchIds = query_1.fetchIds;
|
|
166
|
+
mockFetchIds
|
|
167
|
+
.mockResolvedValueOnce(["123", "456"])
|
|
168
|
+
.mockResolvedValueOnce([])
|
|
169
|
+
.mockResolvedValue(["321", "654"]);
|
|
170
|
+
const destDocPath = "users/{userId}/posts/{postId}";
|
|
171
|
+
const allowedUsers = ["123", "456"];
|
|
172
|
+
const userCondition = {
|
|
173
|
+
fieldName: "id",
|
|
174
|
+
operator: "in",
|
|
175
|
+
value: allowedUsers,
|
|
176
|
+
};
|
|
177
|
+
const result = await (0, paths_1.hydrateDocPath)(destDocPath, {
|
|
178
|
+
user: userCondition,
|
|
179
|
+
});
|
|
180
|
+
expect(result).toEqual([
|
|
181
|
+
"users/456/posts/321",
|
|
182
|
+
"users/456/posts/654",
|
|
183
|
+
]);
|
|
184
|
+
expect(mockFetchIds).toHaveBeenCalledTimes(3);
|
|
185
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(1, "users", userCondition);
|
|
186
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(2, "users/123/posts", undefined);
|
|
187
|
+
expect(mockFetchIds).toHaveBeenNthCalledWith(3, "users/456/posts", undefined);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe("filterSubDocPathsByEntity", () => {
|
|
191
|
+
beforeEach(() => {
|
|
192
|
+
// Clear the mock before each test
|
|
193
|
+
query_1.fetchIds.mockClear();
|
|
194
|
+
});
|
|
195
|
+
it("should return sub-doc paths for a given entity", () => {
|
|
196
|
+
const result = (0, paths_1.filterSubDocPathsByEntity)(db_structure_1.Entity.Friend);
|
|
197
|
+
expect(result).toEqual([
|
|
198
|
+
"users/{userId}/friends/{friendId}",
|
|
199
|
+
"users/{userId}/friends/{friendId}/games/{gameId}",
|
|
200
|
+
]);
|
|
201
|
+
});
|
|
202
|
+
it("should return sub-doc paths excluding specified entities", () => {
|
|
203
|
+
const result = (0, paths_1.filterSubDocPathsByEntity)(db_structure_1.Entity.User, [db_structure_1.Entity.Friend]);
|
|
204
|
+
expect(result).toEqual([
|
|
205
|
+
"users/{userId}",
|
|
206
|
+
"users/{userId}/feeds/{feedId}",
|
|
207
|
+
]);
|
|
208
|
+
});
|
|
209
|
+
it("should return an empty array if the entity is not found", () => {
|
|
210
|
+
const result = (0, paths_1.filterSubDocPathsByEntity)("nonExistentEntity");
|
|
211
|
+
expect(result).toEqual([]);
|
|
212
|
+
});
|
|
213
|
+
it("should return an empty array if the entity does not have any sub-doc paths", () => {
|
|
214
|
+
const result = (0, paths_1.filterSubDocPathsByEntity)(db_structure_1.Entity.Game);
|
|
215
|
+
expect(result).toEqual(["users/{userId}/friends/{friendId}/games/{gameId}"]);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe("expandAndGroupDocPaths", () => {
|
|
219
|
+
beforeEach(() => {
|
|
220
|
+
// Clear the mock before each test
|
|
221
|
+
query_1.fetchIds.mockClear();
|
|
222
|
+
});
|
|
223
|
+
it("should expand and group doc paths based on the starting doc path", async () => {
|
|
224
|
+
// Setup
|
|
225
|
+
const startingDocPath = "users/456";
|
|
226
|
+
const entityCondition = {
|
|
227
|
+
[db_structure_1.Entity.Feed]: { fieldName: "status", operator: "==", value: "active" },
|
|
228
|
+
};
|
|
229
|
+
const excludeEntities = [db_structure_1.Entity.Friend];
|
|
230
|
+
// Mock fetchIds to return sample IDs
|
|
231
|
+
query_1.fetchIds.mockResolvedValueOnce([123, 321]);
|
|
232
|
+
// Mock filterSubDocPathsByEntity
|
|
233
|
+
const filterSubDocPathsByEntityMock = jest.fn().mockReturnValueOnce([
|
|
234
|
+
"users/{userId}",
|
|
235
|
+
"users/{userId}/feeds/{feedId}",
|
|
236
|
+
]);
|
|
237
|
+
paths_1._mockable.filterSubDocPathsByEntity = filterSubDocPathsByEntityMock;
|
|
238
|
+
// Execute the function
|
|
239
|
+
const result = await (0, paths_1.expandAndGroupDocPaths)(startingDocPath, entityCondition, excludeEntities);
|
|
240
|
+
// Check the result
|
|
241
|
+
const expected = {
|
|
242
|
+
[db_structure_1.Entity.User]: [
|
|
243
|
+
"users/456",
|
|
244
|
+
],
|
|
245
|
+
[db_structure_1.Entity.Feed]: [
|
|
246
|
+
"users/456/feeds/123",
|
|
247
|
+
"users/456/feeds/321",
|
|
248
|
+
],
|
|
249
|
+
};
|
|
250
|
+
expect(result).toEqual(expected);
|
|
251
|
+
// Check that fetchIds was called with the correct parameters
|
|
252
|
+
const fetchIdsCalls = query_1.fetchIds.mock.calls;
|
|
253
|
+
expect(fetchIdsCalls[0]).toEqual(["users/456/feeds", entityCondition[db_structure_1.Entity.Feed]]);
|
|
254
|
+
expect(filterSubDocPathsByEntityMock).toHaveBeenCalledTimes(1);
|
|
255
|
+
expect(filterSubDocPathsByEntityMock.mock.calls[0]).toEqual([db_structure_1.Entity.User, excludeEntities]);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
//# sourceMappingURL=paths.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.test.js","sourceRoot":"","sources":["../../../src/tests/utils/paths.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("../../index");
|
|
4
|
+
const query_1 = require("../../utils/query");
|
|
5
|
+
jest.mock("../../index", () => {
|
|
6
|
+
const mockQuery = {
|
|
7
|
+
select: jest.fn().mockReturnThis(),
|
|
8
|
+
where: jest.fn().mockReturnThis(),
|
|
9
|
+
get: jest.fn().mockReturnThis(),
|
|
10
|
+
docs: jest.fn().mockReturnThis(),
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
admin: {
|
|
14
|
+
firestore: jest.fn().mockReturnValue({
|
|
15
|
+
collection: jest.fn().mockReturnValue(mockQuery),
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
describe("fetchIds", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
it("should fetch document IDs from a collection with no condition", async () => {
|
|
25
|
+
const collectionPath = "testCollection";
|
|
26
|
+
const testDocSnapshots = [
|
|
27
|
+
{ id: "doc1", exists: true, data: () => null },
|
|
28
|
+
{ id: "doc2", exists: true, data: () => null },
|
|
29
|
+
];
|
|
30
|
+
const testQuerySnapshot = {
|
|
31
|
+
empty: false,
|
|
32
|
+
docs: testDocSnapshots,
|
|
33
|
+
size: testDocSnapshots.length,
|
|
34
|
+
};
|
|
35
|
+
index_1.admin.firestore().collection.mockReturnValue({
|
|
36
|
+
select: jest.fn().mockReturnThis(),
|
|
37
|
+
where: jest.fn().mockReturnThis(),
|
|
38
|
+
get: jest.fn().mockResolvedValue(testQuerySnapshot),
|
|
39
|
+
});
|
|
40
|
+
const ids = await (0, query_1.fetchIds)(collectionPath);
|
|
41
|
+
expect(ids).toEqual(["doc1", "doc2"]);
|
|
42
|
+
expect(index_1.admin.firestore().collection).toHaveBeenCalledWith(collectionPath);
|
|
43
|
+
});
|
|
44
|
+
// You can add more test cases for different conditions and operators, such as "in", "not-in", and "array-contains-any"
|
|
45
|
+
it("should handle 'in' operator with more than 10 values", async () => {
|
|
46
|
+
// Set up the mock data and firestore methods
|
|
47
|
+
const collectionPath = "messages";
|
|
48
|
+
const idsArray = Array.from({ length: 15 }, (_, i) => `id${i + 1}`);
|
|
49
|
+
const condition = {
|
|
50
|
+
fieldName: "id",
|
|
51
|
+
operator: "in",
|
|
52
|
+
value: idsArray,
|
|
53
|
+
};
|
|
54
|
+
const querySnapshot1 = {
|
|
55
|
+
docs: idsArray.slice(0, 10).map((id) => ({ id })),
|
|
56
|
+
};
|
|
57
|
+
const querySnapshot2 = {
|
|
58
|
+
docs: idsArray.slice(10).map((id) => ({ id })),
|
|
59
|
+
};
|
|
60
|
+
index_1.admin.firestore().collection.mockReturnValue({
|
|
61
|
+
select: jest.fn().mockReturnThis(),
|
|
62
|
+
where: jest.fn().mockReturnThis(),
|
|
63
|
+
get: jest.fn().mockResolvedValueOnce(querySnapshot1).mockResolvedValueOnce(querySnapshot2),
|
|
64
|
+
});
|
|
65
|
+
// Call the fetchIds function
|
|
66
|
+
const fetchedIds = await (0, query_1.fetchIds)(collectionPath, condition);
|
|
67
|
+
// Check the result
|
|
68
|
+
expect(fetchedIds).toEqual(idsArray);
|
|
69
|
+
expect(index_1.admin.firestore().collection("").where).toHaveBeenCalledTimes(2); // Two "in" conditions with 10 and 5 ids
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=query.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.test.js","sourceRoot":"","sources":["../../../src/tests/utils/query.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const admin = __importStar(require("firebase-admin"));
|
|
27
|
+
const sample_1 = require("../../utils/sample");
|
|
28
|
+
describe("Your test suite", () => {
|
|
29
|
+
let createNowTimestampMock;
|
|
30
|
+
let firestoreMock;
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
// Mock the createNowTimestamp function
|
|
33
|
+
createNowTimestampMock = jest.spyOn(sample_1._mockable, "createNowTimestamp");
|
|
34
|
+
createNowTimestampMock.mockReturnValue({ seconds: 1234567890, nanoseconds: 0 });
|
|
35
|
+
// Mock admin.firestore
|
|
36
|
+
firestoreMock = jest.spyOn(admin, "firestore");
|
|
37
|
+
firestoreMock.mockReturnValue({});
|
|
38
|
+
});
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
// Reset the mocks after each test
|
|
41
|
+
jest.resetAllMocks();
|
|
42
|
+
});
|
|
43
|
+
it("Your test case", () => {
|
|
44
|
+
// Redirect console.info to a jest function to capture its output
|
|
45
|
+
console.info = jest.fn();
|
|
46
|
+
(0, sample_1.sampleFunction)();
|
|
47
|
+
expect(console.info).toHaveBeenCalledWith(true, { seconds: 1234567890, nanoseconds: 0 });
|
|
48
|
+
expect(createNowTimestampMock).toHaveBeenCalledTimes(1);
|
|
49
|
+
expect(firestoreMock).toHaveBeenCalledTimes(1);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=sample.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sample.test.js","sourceRoot":"","sources":["../../../src/tests/utils/sample.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,sDAAwC;AACxC,+CAA6D;AAE7D,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,sBAAwC,CAAC;IAC7C,IAAI,aAA+B,CAAC;IAEpC,UAAU,CAAC,GAAG,EAAE;QACd,uCAAuC;QACvC,sBAAsB,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAS,EAAE,oBAAoB,CAAC,CAAC;QACrE,sBAAsB,CAAC,eAAe,CAAC,EAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAC,CAAC,CAAC;QAE9E,uBAAuB;QACvB,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/C,aAAa,CAAC,eAAe,CAAC,EAAS,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,kCAAkC;QAClC,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;QACxB,iEAAiE;QACjE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,IAAA,uBAAc,GAAE,CAAC;QAEjB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAAC,IAAI,EAAE,EAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAC,CAAC,CAAC;QACvF,MAAM,CAAC,sBAAsB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as admin from "firebase-admin";
|
|
2
|
+
import { firestore } from "firebase-admin";
|
|
3
|
+
import Timestamp = firestore.Timestamp;
|
|
4
|
+
import DocumentData = firestore.DocumentData;
|
|
5
|
+
export type FirebaseAdmin = typeof admin;
|
|
6
|
+
export interface Action {
|
|
7
|
+
actionType: string;
|
|
8
|
+
path: string;
|
|
9
|
+
document: FirebaseFirestore.DocumentData;
|
|
10
|
+
modifiedFields?: string[];
|
|
11
|
+
status: "new" | "processing" | "processed" | "processed-with-errors";
|
|
12
|
+
timeCreated: Timestamp;
|
|
13
|
+
message?: string;
|
|
14
|
+
}
|
|
15
|
+
export type LogicResultAction = "merge" | "delete" | "copy";
|
|
16
|
+
export interface LogicResultDoc {
|
|
17
|
+
action: LogicResultAction;
|
|
18
|
+
dstPath: string;
|
|
19
|
+
srcPath?: string;
|
|
20
|
+
doc?: FirebaseFirestore.DocumentData;
|
|
21
|
+
instructions?: {
|
|
22
|
+
[key: string]: string;
|
|
23
|
+
};
|
|
24
|
+
skipEntityDuringRecursiveCopy?: string[];
|
|
25
|
+
copyMode?: "shallow" | "recursive";
|
|
26
|
+
}
|
|
27
|
+
export interface LogicResult {
|
|
28
|
+
name: string;
|
|
29
|
+
status: "finished" | "error";
|
|
30
|
+
message?: string;
|
|
31
|
+
execTime?: number;
|
|
32
|
+
timeFinished: Timestamp;
|
|
33
|
+
documents: LogicResultDoc[];
|
|
34
|
+
}
|
|
35
|
+
export type LogicFn = (action: Action) => Promise<LogicResult>;
|
|
36
|
+
export type LogicActionType = "create" | "update" | "delete";
|
|
37
|
+
export interface LogicConfig {
|
|
38
|
+
name: string;
|
|
39
|
+
actionTypes: LogicActionType[] | "all";
|
|
40
|
+
modifiedFields: string[] | "all";
|
|
41
|
+
entities: string[] | "all";
|
|
42
|
+
logicFn: LogicFn;
|
|
43
|
+
}
|
|
44
|
+
export type ViewLogicFn = (logicResultDoc: LogicResultDoc) => Promise<LogicResult>;
|
|
45
|
+
export interface ViewLogicConfig {
|
|
46
|
+
name: string;
|
|
47
|
+
modifiedFields: string[];
|
|
48
|
+
entity: string;
|
|
49
|
+
viewLogicFn: ViewLogicFn;
|
|
50
|
+
}
|
|
51
|
+
export type SecurityStatus = "allowed" | "rejected";
|
|
52
|
+
export interface SecurityResult {
|
|
53
|
+
status: SecurityStatus;
|
|
54
|
+
message?: string;
|
|
55
|
+
}
|
|
56
|
+
export type SecurityFn = (entity: string, doc: DocumentData, actionType: LogicActionType, modifiedFields?: string[]) => Promise<SecurityResult>;
|
|
57
|
+
export type SecurityConfig = Record<string, SecurityFn>;
|
|
58
|
+
export interface ValidationResult {
|
|
59
|
+
[key: string]: string[];
|
|
60
|
+
}
|
|
61
|
+
export type ValidatorFn = (document: DocumentData, docPath: string) => Promise<ValidationResult>;
|
|
62
|
+
export type ValidatorConfig = Record<string, ValidatorFn>;
|
|
63
|
+
export type ValidateFormResult = [hasValidationErrors: boolean, validationResult: ValidationResult];
|
|
64
|
+
export interface ViewDefinition {
|
|
65
|
+
destEntity: string;
|
|
66
|
+
destProp?: string;
|
|
67
|
+
srcProps: string[];
|
|
68
|
+
srcEntity: string;
|
|
69
|
+
}
|
|
70
|
+
export type IdGenerator = (collectionPath: string) => Promise<string[]>;
|
|
71
|
+
export interface QueryCondition {
|
|
72
|
+
fieldName: string;
|
|
73
|
+
operator: firestore.WhereFilterOp;
|
|
74
|
+
value: any;
|
|
75
|
+
}
|
|
76
|
+
export type AnyObject = {
|
|
77
|
+
[key: string]: any;
|
|
78
|
+
};
|
package/lib/types.js
ADDED
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.view = void 0;
|
|
4
|
+
function view(entity, props) {
|
|
5
|
+
// concat entity and props
|
|
6
|
+
return `View:${entity}:${props.join(",")}`;
|
|
7
|
+
}
|
|
8
|
+
exports.view = view;
|
|
9
|
+
//# sourceMappingURL=db-structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-structure.js","sourceRoot":"","sources":["../../src/utils/db-structure.ts"],"names":[],"mappings":";;;AAAA,SAAS,IAAI,CAAC,MAAc,EAAE,KAAe;IAC3C,0BAA0B;IAC1B,OAAO,QAAQ,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC7C,CAAC;AAEO,oBAAI"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deepEqual(a: any, b: any): boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deepEqual = void 0;
|
|
4
|
+
const firebase_admin_1 = require("firebase-admin");
|
|
5
|
+
var Timestamp = firebase_admin_1.firestore.Timestamp;
|
|
6
|
+
var GeoPoint = firebase_admin_1.firestore.GeoPoint;
|
|
7
|
+
function isObject(item) {
|
|
8
|
+
return (typeof item === "object" && !Array.isArray(item) && item !== null);
|
|
9
|
+
}
|
|
10
|
+
function isArray(item) {
|
|
11
|
+
return Array.isArray(item);
|
|
12
|
+
}
|
|
13
|
+
function isFirestoreTimestamp(item) {
|
|
14
|
+
return item instanceof Timestamp;
|
|
15
|
+
}
|
|
16
|
+
function isFirestoreGeoPoint(item) {
|
|
17
|
+
return item instanceof GeoPoint;
|
|
18
|
+
}
|
|
19
|
+
function deepEqual(a, b) {
|
|
20
|
+
if (a === b)
|
|
21
|
+
return true;
|
|
22
|
+
if (isFirestoreTimestamp(a) && isFirestoreTimestamp(b)) {
|
|
23
|
+
return a.isEqual(b);
|
|
24
|
+
}
|
|
25
|
+
if (isFirestoreGeoPoint(a) && isFirestoreGeoPoint(b)) {
|
|
26
|
+
return a.latitude === b.latitude && a.longitude === b.longitude;
|
|
27
|
+
}
|
|
28
|
+
if (isArray(a) && isArray(b)) {
|
|
29
|
+
if (a.length !== b.length)
|
|
30
|
+
return false;
|
|
31
|
+
for (let i = 0; i < a.length; i++) {
|
|
32
|
+
if (!deepEqual(a[i], b[i]))
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
if (isObject(a) && isObject(b)) {
|
|
38
|
+
const keysA = Object.keys(a);
|
|
39
|
+
const keysB = Object.keys(b);
|
|
40
|
+
if (keysA.length !== keysB.length)
|
|
41
|
+
return false;
|
|
42
|
+
for (const key of keysA) {
|
|
43
|
+
if (!keysB.includes(key))
|
|
44
|
+
return false;
|
|
45
|
+
if (!deepEqual(a[key], b[key]))
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
exports.deepEqual = deepEqual;
|
|
53
|
+
//# sourceMappingURL=misc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/utils/misc.ts"],"names":[],"mappings":";;;AAAA,mDAAyC;AACzC,IAAO,SAAS,GAAG,0BAAS,CAAC,SAAS,CAAC;AACvC,IAAO,QAAQ,GAAG,0BAAS,CAAC,QAAQ,CAAC;AAErC,SAAS,QAAQ,CAAC,IAAS;IACzB,OAAO,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,OAAO,CAAC,IAAS;IACxB,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAS;IACrC,OAAO,IAAI,YAAY,SAAS,CAAC;AACnC,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAS;IACpC,OAAO,IAAI,YAAY,QAAQ,CAAC;AAClC,CAAC;AAED,SAAgB,SAAS,CAAC,CAAM,EAAE,CAAM;IACtC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzB,IAAI,oBAAoB,CAAC,CAAC,CAAC,IAAI,oBAAoB,CAAC,CAAC,CAAC,EAAE;QACtD,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;KACrB;IAED,IAAI,mBAAmB,CAAC,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,CAAC,EAAE;QACpD,OAAO,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,CAAC;KACjE;IAED,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE;QAC5B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACjC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;SAC1C;QACD,OAAO,IAAI,CAAC;KACb;IAED,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE7B,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAEhD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE;YACvB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YACvC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;SAC9C;QAED,OAAO,IAAI,CAAC;KACb;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAlCD,8BAkCC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryCondition } from "../types";
|
|
2
|
+
export declare const _mockable: {
|
|
3
|
+
filterSubDocPathsByEntity: (entity: string, excludeEntities?: string[]) => string[];
|
|
4
|
+
};
|
|
5
|
+
export declare function findMatchingDocPathRegex(docPath: string): {
|
|
6
|
+
entity: string;
|
|
7
|
+
regex: RegExp;
|
|
8
|
+
} | {
|
|
9
|
+
entity: null;
|
|
10
|
+
regex: null;
|
|
11
|
+
};
|
|
12
|
+
export declare function filterSubDocPathsByEntity(entity: string, excludeEntities?: string[]): string[];
|
|
13
|
+
export declare function expandAndGroupDocPaths(startingDocPath: string, entityCondition?: Record<string, QueryCondition>, excludeEntities?: string[]): Promise<{
|
|
14
|
+
[key: string]: string[];
|
|
15
|
+
}>;
|
|
16
|
+
export declare function hydrateDocPath(destDocPath: string, entityCondition: Record<string, QueryCondition>): Promise<string[]>;
|