@expo/entity-database-adapter-knex 0.55.0 → 0.57.0
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/build/src/AuthorizationResultBasedKnexEntityLoader.d.ts +279 -0
- package/build/src/AuthorizationResultBasedKnexEntityLoader.js +127 -0
- package/build/src/AuthorizationResultBasedKnexEntityLoader.js.map +1 -0
- package/build/src/BasePostgresEntityDatabaseAdapter.d.ts +150 -0
- package/build/src/BasePostgresEntityDatabaseAdapter.js +119 -0
- package/build/src/BasePostgresEntityDatabaseAdapter.js.map +1 -0
- package/build/src/BaseSQLQueryBuilder.d.ts +61 -0
- package/build/src/BaseSQLQueryBuilder.js +87 -0
- package/build/src/BaseSQLQueryBuilder.js.map +1 -0
- package/build/src/EnforcingKnexEntityLoader.d.ts +124 -0
- package/build/src/EnforcingKnexEntityLoader.js +166 -0
- package/build/src/EnforcingKnexEntityLoader.js.map +1 -0
- package/build/src/KnexEntityLoaderFactory.d.ts +25 -0
- package/build/src/KnexEntityLoaderFactory.js +39 -0
- package/build/src/KnexEntityLoaderFactory.js.map +1 -0
- package/build/src/PaginationStrategy.d.ts +30 -0
- package/build/src/PaginationStrategy.js +35 -0
- package/build/src/PaginationStrategy.js.map +1 -0
- package/build/src/PostgresEntity.d.ts +25 -0
- package/build/src/PostgresEntity.js +39 -0
- package/build/src/PostgresEntity.js.map +1 -0
- package/build/src/PostgresEntityDatabaseAdapter.d.ts +12 -5
- package/build/src/PostgresEntityDatabaseAdapter.js +32 -11
- package/build/src/PostgresEntityDatabaseAdapter.js.map +1 -1
- package/build/src/PostgresEntityDatabaseAdapterProvider.d.ts +9 -0
- package/build/src/PostgresEntityDatabaseAdapterProvider.js +5 -1
- package/build/src/PostgresEntityDatabaseAdapterProvider.js.map +1 -1
- package/build/src/ReadonlyPostgresEntity.d.ts +25 -0
- package/build/src/ReadonlyPostgresEntity.js +39 -0
- package/build/src/ReadonlyPostgresEntity.js.map +1 -0
- package/build/src/SQLOperator.d.ts +261 -0
- package/build/src/SQLOperator.js +464 -0
- package/build/src/SQLOperator.js.map +1 -0
- package/build/src/index.d.ts +15 -0
- package/build/src/index.js +15 -0
- package/build/src/index.js.map +1 -1
- package/build/src/internal/EntityKnexDataManager.d.ts +147 -0
- package/build/src/internal/EntityKnexDataManager.js +453 -0
- package/build/src/internal/EntityKnexDataManager.js.map +1 -0
- package/build/src/internal/getKnexDataManager.d.ts +3 -0
- package/build/src/internal/getKnexDataManager.js +19 -0
- package/build/src/internal/getKnexDataManager.js.map +1 -0
- package/build/src/internal/getKnexEntityLoaderFactory.d.ts +3 -0
- package/build/src/internal/getKnexEntityLoaderFactory.js +11 -0
- package/build/src/internal/getKnexEntityLoaderFactory.js.map +1 -0
- package/build/src/internal/utilityTypes.d.ts +5 -0
- package/build/src/internal/utilityTypes.js +5 -0
- package/build/src/internal/utilityTypes.js.map +1 -0
- package/build/src/internal/weakMaps.d.ts +9 -0
- package/build/src/internal/weakMaps.js +20 -0
- package/build/src/internal/weakMaps.js.map +1 -0
- package/build/src/knexLoader.d.ts +18 -0
- package/build/src/knexLoader.js +31 -0
- package/build/src/knexLoader.js.map +1 -0
- package/package.json +6 -5
- package/src/AuthorizationResultBasedKnexEntityLoader.ts +538 -0
- package/src/BasePostgresEntityDatabaseAdapter.ts +317 -0
- package/src/BaseSQLQueryBuilder.ts +114 -0
- package/src/EnforcingKnexEntityLoader.ts +271 -0
- package/src/KnexEntityLoaderFactory.ts +130 -0
- package/src/PaginationStrategy.ts +32 -0
- package/src/PostgresEntity.ts +118 -0
- package/src/PostgresEntityDatabaseAdapter.ts +78 -24
- package/src/PostgresEntityDatabaseAdapterProvider.ts +11 -1
- package/src/ReadonlyPostgresEntity.ts +115 -0
- package/src/SQLOperator.ts +603 -0
- package/src/__integration-tests__/EntityCreationUtils-test.ts +25 -31
- package/src/__integration-tests__/PostgresEntityIntegration-test.ts +3192 -330
- package/src/__integration-tests__/PostgresEntityQueryContextProvider-test.ts +7 -7
- package/src/__testfixtures__/PostgresTestEntity.ts +17 -3
- package/src/__tests__/AuthorizationResultBasedKnexEntityLoader-test.ts +1167 -0
- package/src/__tests__/BasePostgresEntityDatabaseAdapter-test.ts +160 -0
- package/src/__tests__/EnforcingKnexEntityLoader-test.ts +384 -0
- package/src/__tests__/EntityFields-test.ts +1 -1
- package/src/__tests__/PostgresEntity-test.ts +172 -0
- package/src/__tests__/ReadonlyEntity-test.ts +32 -0
- package/src/__tests__/SQLOperator-test.ts +831 -0
- package/src/__tests__/fixtures/StubPostgresDatabaseAdapter.ts +302 -0
- package/src/__tests__/fixtures/StubPostgresDatabaseAdapterProvider.ts +17 -0
- package/src/__tests__/fixtures/TestEntity.ts +131 -0
- package/src/__tests__/fixtures/TestPaginationEntity.ts +107 -0
- package/src/__tests__/fixtures/createUnitTestPostgresEntityCompanionProvider.ts +42 -0
- package/src/index.ts +15 -0
- package/src/internal/EntityKnexDataManager.ts +832 -0
- package/src/internal/__tests__/EntityKnexDataManager-test.ts +378 -0
- package/src/internal/__tests__/weakMaps-test.ts +25 -0
- package/src/internal/getKnexDataManager.ts +43 -0
- package/src/internal/getKnexEntityLoaderFactory.ts +60 -0
- package/src/internal/utilityTypes.ts +11 -0
- package/src/internal/weakMaps.ts +19 -0
- package/src/knexLoader.ts +110 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EntityKnexDataManager = void 0;
|
|
7
|
+
const entity_1 = require("@expo/entity");
|
|
8
|
+
const assert_1 = __importDefault(require("assert"));
|
|
9
|
+
const BasePostgresEntityDatabaseAdapter_1 = require("../BasePostgresEntityDatabaseAdapter");
|
|
10
|
+
const PaginationStrategy_1 = require("../PaginationStrategy");
|
|
11
|
+
const SQLOperator_1 = require("../SQLOperator");
|
|
12
|
+
function isDataManagerSearchFieldSQLFragmentFnSpecification(obj) {
|
|
13
|
+
return typeof obj === 'object' && obj !== null && 'fieldConstructor' in obj;
|
|
14
|
+
}
|
|
15
|
+
var PaginationDirection;
|
|
16
|
+
(function (PaginationDirection) {
|
|
17
|
+
PaginationDirection["FORWARD"] = "forward";
|
|
18
|
+
PaginationDirection["BACKWARD"] = "backward";
|
|
19
|
+
})(PaginationDirection || (PaginationDirection = {}));
|
|
20
|
+
const CURSOR_ROW_TABLE_ALIAS = 'cursor_row';
|
|
21
|
+
/**
|
|
22
|
+
* A knex data manager is responsible for handling non-dataloader-based
|
|
23
|
+
* database operations.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
class EntityKnexDataManager {
|
|
28
|
+
entityConfiguration;
|
|
29
|
+
databaseAdapter;
|
|
30
|
+
metricsAdapter;
|
|
31
|
+
entityClassName;
|
|
32
|
+
constructor(entityConfiguration, databaseAdapter, metricsAdapter, entityClassName) {
|
|
33
|
+
this.entityConfiguration = entityConfiguration;
|
|
34
|
+
this.databaseAdapter = databaseAdapter;
|
|
35
|
+
this.metricsAdapter = metricsAdapter;
|
|
36
|
+
this.entityClassName = entityClassName;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Loads many objects matching the conjunction of where clauses constructed from
|
|
40
|
+
* specified field equality operands.
|
|
41
|
+
*
|
|
42
|
+
* @param queryContext - query context in which to perform the load
|
|
43
|
+
* @param fieldEqualityOperands - list of field equality where clause operand specifications
|
|
44
|
+
* @param querySelectionModifiers - limit, offset, and orderBy for the query
|
|
45
|
+
* @returns array of objects matching the query
|
|
46
|
+
*/
|
|
47
|
+
async loadManyByFieldEqualityConjunctionAsync(queryContext, fieldEqualityOperands, querySelectionModifiers) {
|
|
48
|
+
EntityKnexDataManager.validateOrderByClauses(querySelectionModifiers.orderBy);
|
|
49
|
+
return await (0, entity_1.timeAndLogLoadEventAsync)(this.metricsAdapter, entity_1.EntityMetricsLoadType.LOAD_MANY_EQUALITY_CONJUNCTION, this.entityClassName, queryContext)(this.databaseAdapter.fetchManyByFieldEqualityConjunctionAsync(queryContext, fieldEqualityOperands, querySelectionModifiers));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Loads many objects matching the raw WHERE clause.
|
|
53
|
+
*
|
|
54
|
+
* @param queryContext - query context in which to perform the load
|
|
55
|
+
* @param rawWhereClause - parameterized SQL WHERE clause with positional binding placeholders or named binding placeholders
|
|
56
|
+
* @param bindings - array of positional bindings or object of named bindings
|
|
57
|
+
* @param querySelectionModifiers - limit, offset, orderBy, and orderByRaw for the query
|
|
58
|
+
* @returns array of objects matching the query
|
|
59
|
+
*/
|
|
60
|
+
async loadManyByRawWhereClauseAsync(queryContext, rawWhereClause, bindings, querySelectionModifiers) {
|
|
61
|
+
EntityKnexDataManager.validateOrderByClauses(querySelectionModifiers.orderBy);
|
|
62
|
+
return await (0, entity_1.timeAndLogLoadEventAsync)(this.metricsAdapter, entity_1.EntityMetricsLoadType.LOAD_MANY_RAW, this.entityClassName, queryContext)(this.databaseAdapter.fetchManyByRawWhereClauseAsync(queryContext, rawWhereClause, bindings, querySelectionModifiers));
|
|
63
|
+
}
|
|
64
|
+
async loadManyBySQLFragmentAsync(queryContext, sqlFragment, querySelectionModifiers) {
|
|
65
|
+
EntityKnexDataManager.validateOrderByClauses(querySelectionModifiers.orderBy);
|
|
66
|
+
return await (0, entity_1.timeAndLogLoadEventAsync)(this.metricsAdapter, entity_1.EntityMetricsLoadType.LOAD_MANY_SQL, this.entityClassName, queryContext)(this.databaseAdapter.fetchManyBySQLFragmentAsync(queryContext, sqlFragment, querySelectionModifiers));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Load a page of objects using cursor-based pagination with unified pagination specification.
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
*
|
|
73
|
+
* This method implements cursor-based pagination using the seek method for efficient pagination even on large datasets
|
|
74
|
+
* given appropriate indexes. Cursors are opaque and encode the necessary information to fetch the next page based on the
|
|
75
|
+
* specified pagination strategy (standard, ILIKE search, or trigram search). For this implementation in particular,
|
|
76
|
+
* the cursor encodes the ID of the last entity in the page to ensure correct pagination for all strategies, even in cases
|
|
77
|
+
* where multiple rows have the same value for all fields other than the ID. If the entity referenced by a cursor has been
|
|
78
|
+
* deleted, the load will return an empty page with `hasNextPage: false`.
|
|
79
|
+
*
|
|
80
|
+
* @param queryContext - query context in which to perform the load
|
|
81
|
+
* @param args - pagination arguments including pagination and first/after or last/before
|
|
82
|
+
* @returns connection with edges containing field objects and page info
|
|
83
|
+
*/
|
|
84
|
+
async loadPageAsync(queryContext, args) {
|
|
85
|
+
const { where, pagination } = args;
|
|
86
|
+
if (pagination.strategy === PaginationStrategy_1.PaginationStrategy.STANDARD) {
|
|
87
|
+
// Standard pagination
|
|
88
|
+
EntityKnexDataManager.validateOrderByClauses(pagination.orderBy);
|
|
89
|
+
EntityKnexDataManager.validateOrderByClausesHaveConsistentDirection(pagination.orderBy);
|
|
90
|
+
const idField = this.entityConfiguration.idField;
|
|
91
|
+
const augmentedOrderByClauses = this.augmentOrderByIfNecessary(pagination.orderBy, idField);
|
|
92
|
+
const fieldsToUseInPostgresTupleCursor = augmentedOrderByClauses.map((order) => 'fieldName' in order ? order.fieldName : order.fieldFragment);
|
|
93
|
+
// Create strategy for regular pagination
|
|
94
|
+
const strategy = {
|
|
95
|
+
whereClause: where,
|
|
96
|
+
buildOrderBy: (direction) => {
|
|
97
|
+
// For backward pagination, we flip the ORDER BY and NULLS direction to fetch records
|
|
98
|
+
// in reverse order. This allows us to use a simple "less than" cursor comparison
|
|
99
|
+
// instead of complex SQL. We'll reverse the results array later to restore
|
|
100
|
+
// the original requested order.
|
|
101
|
+
// Example: If user wants last 3 items ordered by name ASC, we:
|
|
102
|
+
// 1. Flip to name DESC to get the last items first
|
|
103
|
+
// 2. Apply cursor with < comparison
|
|
104
|
+
// 3. Reverse the final array to present items in name ASC order
|
|
105
|
+
return direction === PaginationDirection.FORWARD
|
|
106
|
+
? augmentedOrderByClauses
|
|
107
|
+
: augmentedOrderByClauses.map((clause) => ({
|
|
108
|
+
...clause,
|
|
109
|
+
order: clause.order === BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING
|
|
110
|
+
? BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING
|
|
111
|
+
: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING,
|
|
112
|
+
nulls: clause.nulls
|
|
113
|
+
? EntityKnexDataManager.flipNullsOrderingSpread(clause.nulls)
|
|
114
|
+
: undefined,
|
|
115
|
+
}));
|
|
116
|
+
},
|
|
117
|
+
buildCursorCondition: (decodedCursorId, _direction, orderByClauses) => {
|
|
118
|
+
// all clauses are guaranteed to have the same order due to validation, so we can just look at the first one for effective ordering
|
|
119
|
+
const effectiveOrdering = orderByClauses[0]?.order ?? BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING;
|
|
120
|
+
return this.buildCursorCondition(decodedCursorId, fieldsToUseInPostgresTupleCursor, effectiveOrdering);
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
return await this.loadPageInternalAsync(queryContext, args, strategy);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Search pagination (ILIKE or TRIGRAM)
|
|
127
|
+
const search = pagination;
|
|
128
|
+
// Validate search parameters
|
|
129
|
+
(0, assert_1.default)(search.term.length > 0, 'Search term must be a non-empty string');
|
|
130
|
+
(0, assert_1.default)(search.fields.length > 0, 'Search fields must be a non-empty array');
|
|
131
|
+
const { searchWhere, searchOrderByClauses } = this.buildSearchConditionAndOrderBy(search);
|
|
132
|
+
// Combine WHERE conditions: base where + search where
|
|
133
|
+
const whereClause = where && searchWhere ? SQLOperator_1.SQLFragmentHelpers.and(where, searchWhere) : (where ?? searchWhere);
|
|
134
|
+
const fieldsToUseInPostgresTupleCursor = search.strategy === PaginationStrategy_1.PaginationStrategy.TRIGRAM_SEARCH
|
|
135
|
+
? // For trigram search, cursor includes extra order by fields (if specified) + ID to ensure stable ordering that matches ORDER BY clause
|
|
136
|
+
[...(search.extraOrderByFields ?? []), this.entityConfiguration.idField]
|
|
137
|
+
: // For ILIKE search, cursor includes search fields + ID to ensure stable ordering that matches ORDER BY clause
|
|
138
|
+
[...search.fields, this.entityConfiguration.idField];
|
|
139
|
+
// Create strategy for search pagination
|
|
140
|
+
const strategy = {
|
|
141
|
+
whereClause,
|
|
142
|
+
buildOrderBy: (direction) => {
|
|
143
|
+
return direction === PaginationDirection.FORWARD
|
|
144
|
+
? searchOrderByClauses
|
|
145
|
+
: searchOrderByClauses.map((clause) => ({
|
|
146
|
+
...clause,
|
|
147
|
+
order: clause.order === BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING
|
|
148
|
+
? BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING
|
|
149
|
+
: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING,
|
|
150
|
+
}));
|
|
151
|
+
},
|
|
152
|
+
buildCursorCondition: (decodedCursorId, direction) => search.strategy === PaginationStrategy_1.PaginationStrategy.TRIGRAM_SEARCH
|
|
153
|
+
? this.buildTrigramCursorCondition(search, decodedCursorId, direction)
|
|
154
|
+
: this.buildCursorCondition(decodedCursorId, fieldsToUseInPostgresTupleCursor,
|
|
155
|
+
// ILIKE search always orders ASC, so effective ordering matches direction
|
|
156
|
+
direction === PaginationDirection.FORWARD
|
|
157
|
+
? BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING
|
|
158
|
+
: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING),
|
|
159
|
+
};
|
|
160
|
+
return await this.loadPageInternalAsync(queryContext, args, strategy);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
getCursorForEntityID(entityID) {
|
|
164
|
+
return this.encodeOpaqueCursor(entityID);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Internal method for loading a page with cursor-based pagination.
|
|
168
|
+
* Shared logic for both regular and search pagination.
|
|
169
|
+
*/
|
|
170
|
+
async loadPageInternalAsync(queryContext, args, paginationProvider) {
|
|
171
|
+
const idField = this.entityConfiguration.idField;
|
|
172
|
+
// Validate pagination arguments
|
|
173
|
+
const maxPageSize = this.databaseAdapter.paginationMaxPageSize;
|
|
174
|
+
const isForward = 'first' in args && args.first !== undefined;
|
|
175
|
+
if (isForward) {
|
|
176
|
+
(0, assert_1.default)(Number.isInteger(args.first) && args.first > 0, 'first must be an integer greater than 0');
|
|
177
|
+
if (maxPageSize !== undefined) {
|
|
178
|
+
(0, assert_1.default)(args.first <= maxPageSize, `first must not exceed maximum page size of ${maxPageSize}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
(0, assert_1.default)(Number.isInteger(args.last) && args.last > 0, 'last must be an integer greater than 0');
|
|
183
|
+
if (maxPageSize !== undefined) {
|
|
184
|
+
(0, assert_1.default)(args.last <= maxPageSize, `last must not exceed maximum page size of ${maxPageSize}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const direction = isForward ? PaginationDirection.FORWARD : PaginationDirection.BACKWARD;
|
|
188
|
+
const limit = isForward ? args.first : args.last;
|
|
189
|
+
const cursor = isForward ? args.after : args.before;
|
|
190
|
+
// Decode cursor
|
|
191
|
+
const decodedExternalCursorEntityID = cursor ? this.decodeOpaqueCursor(cursor) : null;
|
|
192
|
+
// Get ordering from strategy
|
|
193
|
+
const orderByClauses = paginationProvider.buildOrderBy(direction);
|
|
194
|
+
// Build WHERE clause with cursor condition
|
|
195
|
+
const baseWhere = paginationProvider.whereClause;
|
|
196
|
+
const cursorCondition = decodedExternalCursorEntityID
|
|
197
|
+
? paginationProvider.buildCursorCondition(decodedExternalCursorEntityID, direction, orderByClauses)
|
|
198
|
+
: null;
|
|
199
|
+
const whereClause = this.combineWhereConditions(baseWhere, cursorCondition);
|
|
200
|
+
// Determine query modifiers
|
|
201
|
+
const queryModifiers = {
|
|
202
|
+
...(orderByClauses !== undefined && { orderBy: orderByClauses }),
|
|
203
|
+
limit: limit + 1, // Fetch data with limit + 1 to check for more pages
|
|
204
|
+
};
|
|
205
|
+
const fieldObjects = await (0, entity_1.timeAndLogLoadEventAsync)(this.metricsAdapter, entity_1.EntityMetricsLoadType.LOAD_PAGE, this.entityClassName, queryContext)(this.databaseAdapter.fetchManyBySQLFragmentAsync(queryContext, whereClause, queryModifiers));
|
|
206
|
+
// Process results
|
|
207
|
+
const hasMore = fieldObjects.length > limit;
|
|
208
|
+
const pageFieldObjects = hasMore ? fieldObjects.slice(0, limit) : [...fieldObjects];
|
|
209
|
+
if (direction === PaginationDirection.BACKWARD) {
|
|
210
|
+
// Restore the original requested order by reversing the results.
|
|
211
|
+
// We fetched with flipped ORDER BY for efficient cursor comparison,
|
|
212
|
+
// so now we reverse to match the order the user expects.
|
|
213
|
+
pageFieldObjects.reverse();
|
|
214
|
+
}
|
|
215
|
+
// Build edges with cursors
|
|
216
|
+
const edges = pageFieldObjects.map((fieldObject) => ({
|
|
217
|
+
node: fieldObject,
|
|
218
|
+
cursor: this.encodeOpaqueCursor(fieldObject[idField]),
|
|
219
|
+
}));
|
|
220
|
+
const pageInfo = {
|
|
221
|
+
hasNextPage: direction === PaginationDirection.FORWARD ? hasMore : false,
|
|
222
|
+
hasPreviousPage: direction === PaginationDirection.BACKWARD ? hasMore : false,
|
|
223
|
+
startCursor: edges[0]?.cursor ?? null,
|
|
224
|
+
endCursor: edges[edges.length - 1]?.cursor ?? null,
|
|
225
|
+
};
|
|
226
|
+
return {
|
|
227
|
+
edges,
|
|
228
|
+
pageInfo,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
combineWhereConditions(baseWhere, cursorCondition) {
|
|
232
|
+
const conditions = [baseWhere, cursorCondition].filter((it) => !!it);
|
|
233
|
+
if (conditions.length === 0) {
|
|
234
|
+
return (0, SQLOperator_1.sql) `1 = 1`;
|
|
235
|
+
}
|
|
236
|
+
if (conditions.length === 1) {
|
|
237
|
+
return conditions[0];
|
|
238
|
+
}
|
|
239
|
+
// Wrap baseWhere in parens if combining with cursor condition
|
|
240
|
+
// We know we have exactly 2 conditions at this point
|
|
241
|
+
const [first, second] = conditions;
|
|
242
|
+
return (0, SQLOperator_1.sql) `(${first}) AND ${second}`;
|
|
243
|
+
}
|
|
244
|
+
augmentOrderByIfNecessary(orderBy, idField) {
|
|
245
|
+
const clauses = orderBy ?? [];
|
|
246
|
+
// Always ensure ID is included for stability and cursor correctness. Note that this may add a redundant order by
|
|
247
|
+
// if ID is already included as a fragment, but that is preferable to the risk of incorrect pagination behavior.
|
|
248
|
+
const hasId = clauses.some((spec) => 'fieldName' in spec && spec.fieldName === idField);
|
|
249
|
+
if (!hasId) {
|
|
250
|
+
const lastClauseOrder = clauses.length > 0 ? clauses[clauses.length - 1].order : BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING;
|
|
251
|
+
return [...clauses, { fieldName: idField, order: lastClauseOrder }];
|
|
252
|
+
}
|
|
253
|
+
return clauses;
|
|
254
|
+
}
|
|
255
|
+
static flipNullsOrderingSpread(nulls) {
|
|
256
|
+
return nulls === BasePostgresEntityDatabaseAdapter_1.NullsOrdering.FIRST ? BasePostgresEntityDatabaseAdapter_1.NullsOrdering.LAST : BasePostgresEntityDatabaseAdapter_1.NullsOrdering.FIRST;
|
|
257
|
+
}
|
|
258
|
+
static validateOrderByClauses(orderBy) {
|
|
259
|
+
if (orderBy === undefined) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (const clause of orderBy) {
|
|
263
|
+
if ('fieldFragment' in clause) {
|
|
264
|
+
const trimmedSql = clause.fieldFragment.sql.trimEnd();
|
|
265
|
+
(0, assert_1.default)(!/\b(ASC|DESC)\s*$/i.test(trimmedSql), 'fieldFragment must not contain ASC or DESC at the end. Use the order property to specify ordering direction.');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Cursor-based pagination uses Postgres tuple comparison (e.g., (a, b) \> (x, y)) which
|
|
271
|
+
* applies a single comparison direction to all columns. Mixed ordering directions would
|
|
272
|
+
* produce incorrect pagination results.
|
|
273
|
+
*/
|
|
274
|
+
static validateOrderByClausesHaveConsistentDirection(orderBy) {
|
|
275
|
+
if (orderBy === undefined || orderBy.length <= 1) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const firstOrder = orderBy[0].order;
|
|
279
|
+
(0, assert_1.default)(orderBy.every((clause) => clause.order === firstOrder), 'All orderBy clauses must have the same ordering direction. Mixed ordering directions are not supported with cursor-based pagination.');
|
|
280
|
+
}
|
|
281
|
+
encodeOpaqueCursor(idField) {
|
|
282
|
+
return Buffer.from(JSON.stringify({ id: idField })).toString('base64url');
|
|
283
|
+
}
|
|
284
|
+
decodeOpaqueCursor(cursor) {
|
|
285
|
+
let parsedCursor;
|
|
286
|
+
try {
|
|
287
|
+
const decoded = Buffer.from(cursor, 'base64url').toString();
|
|
288
|
+
parsedCursor = JSON.parse(decoded);
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
throw new entity_1.EntityDatabaseAdapterPaginationCursorInvalidError(`Failed to decode cursor`, e instanceof Error ? e : undefined);
|
|
292
|
+
}
|
|
293
|
+
if (!('id' in parsedCursor)) {
|
|
294
|
+
throw new entity_1.EntityDatabaseAdapterPaginationCursorInvalidError(`Cursor is missing required 'id' field. Parsed cursor: ${JSON.stringify(parsedCursor)}`);
|
|
295
|
+
}
|
|
296
|
+
return parsedCursor.id;
|
|
297
|
+
}
|
|
298
|
+
resolveSearchFieldToSQLFragment(field, tableAlias) {
|
|
299
|
+
if (field instanceof SQLOperator_1.SQLFragment) {
|
|
300
|
+
return field;
|
|
301
|
+
}
|
|
302
|
+
if (isDataManagerSearchFieldSQLFragmentFnSpecification(field)) {
|
|
303
|
+
return field.fieldConstructor((fieldName) => {
|
|
304
|
+
const dbField = (0, entity_1.getDatabaseFieldForEntityField)(this.entityConfiguration, fieldName);
|
|
305
|
+
return tableAlias
|
|
306
|
+
? (0, SQLOperator_1.sql) `${(0, SQLOperator_1.unsafeRaw)(tableAlias)}.${(0, SQLOperator_1.identifier)(dbField)}`
|
|
307
|
+
: (0, SQLOperator_1.sql) `${(0, SQLOperator_1.identifier)(dbField)}`;
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const dbField = (0, entity_1.getDatabaseFieldForEntityField)(this.entityConfiguration, field);
|
|
311
|
+
return tableAlias
|
|
312
|
+
? (0, SQLOperator_1.sql) `${(0, SQLOperator_1.unsafeRaw)(tableAlias)}.${(0, SQLOperator_1.identifier)(dbField)}`
|
|
313
|
+
: (0, SQLOperator_1.sql) `${(0, SQLOperator_1.identifier)(dbField)}`;
|
|
314
|
+
}
|
|
315
|
+
buildCursorCondition(decodedExternalCursorEntityID, fieldsToUseInPostgresTupleCursor, effectiveOrdering) {
|
|
316
|
+
// We build a tuple comparison for fieldsToUseInPostgresTupleCursor fields of the
|
|
317
|
+
// entity identified by the external cursor to ensure correct pagination behavior
|
|
318
|
+
// even in cases where multiple rows have the same value all fields other than id.
|
|
319
|
+
// If the cursor entity has been deleted, the subquery returns no rows and the
|
|
320
|
+
// comparison evaluates to NULL, filtering out all results (empty page).
|
|
321
|
+
const operator = effectiveOrdering === BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING ? '>' : '<';
|
|
322
|
+
const idField = (0, entity_1.getDatabaseFieldForEntityField)(this.entityConfiguration, this.entityConfiguration.idField);
|
|
323
|
+
const tableName = this.entityConfiguration.tableName;
|
|
324
|
+
const postgresCursorFieldIdentifiers = fieldsToUseInPostgresTupleCursor.map((f) => this.resolveSearchFieldToSQLFragment(f));
|
|
325
|
+
// Build left side of comparison (current row's computed values)
|
|
326
|
+
const leftSide = SQLOperator_1.SQLFragment.joinWithCommaSeparator(...postgresCursorFieldIdentifiers);
|
|
327
|
+
// Build right side using subquery to get computed values for cursor entity.
|
|
328
|
+
// For field names, qualify with the cursor row alias. For SQL fragments,
|
|
329
|
+
// use as-is since unqualified column names resolve to the only table in the subquery.
|
|
330
|
+
const postgresCursorRowFieldIdentifiers = fieldsToUseInPostgresTupleCursor.map((f) => this.resolveSearchFieldToSQLFragment(f, CURSOR_ROW_TABLE_ALIAS));
|
|
331
|
+
// Build SELECT fields for subquery
|
|
332
|
+
const rightSideSubquery = (0, SQLOperator_1.sql) `
|
|
333
|
+
SELECT ${SQLOperator_1.SQLFragment.joinWithCommaSeparator(...postgresCursorRowFieldIdentifiers)}
|
|
334
|
+
FROM ${(0, SQLOperator_1.identifier)(tableName)} AS ${(0, SQLOperator_1.unsafeRaw)(CURSOR_ROW_TABLE_ALIAS)}
|
|
335
|
+
WHERE ${(0, SQLOperator_1.unsafeRaw)(CURSOR_ROW_TABLE_ALIAS)}.${(0, SQLOperator_1.identifier)(idField)} = ${decodedExternalCursorEntityID}
|
|
336
|
+
`;
|
|
337
|
+
return (0, SQLOperator_1.sql) `(${leftSide}) ${(0, SQLOperator_1.unsafeRaw)(operator)} (${rightSideSubquery})`;
|
|
338
|
+
}
|
|
339
|
+
buildILikeConditions(search, tableAlias) {
|
|
340
|
+
return search.fields.map((field) => {
|
|
341
|
+
const fieldFragment = this.resolveSearchFieldToSQLFragment(field, tableAlias);
|
|
342
|
+
return (0, SQLOperator_1.sql) `${fieldFragment} ILIKE ${'%' + EntityKnexDataManager.escapeILikePattern(search.term) + '%'}`;
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
buildTrigramSimilarityExpressions(search, tableAlias) {
|
|
346
|
+
return search.fields.map((field) => {
|
|
347
|
+
const fieldFragment = this.resolveSearchFieldToSQLFragment(field, tableAlias);
|
|
348
|
+
return (0, SQLOperator_1.sql) `similarity(${fieldFragment}, ${search.term})`;
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
buildTrigramExactMatchCaseExpression(search, tableAlias) {
|
|
352
|
+
const ilikeConditions = this.buildILikeConditions(search, tableAlias);
|
|
353
|
+
return (0, SQLOperator_1.sql) `CASE WHEN ${SQLOperator_1.SQLFragmentHelpers.or(...ilikeConditions)} THEN 1 ELSE 0 END`;
|
|
354
|
+
}
|
|
355
|
+
buildTrigramSimilarityGreatestExpression(search, tableAlias) {
|
|
356
|
+
const similarityExprs = this.buildTrigramSimilarityExpressions(search, tableAlias);
|
|
357
|
+
return (0, SQLOperator_1.sql) `GREATEST(${SQLOperator_1.SQLFragment.joinWithCommaSeparator(...similarityExprs)})`;
|
|
358
|
+
}
|
|
359
|
+
buildTrigramCursorCondition(search, decodedExternalCursorEntityID, direction) {
|
|
360
|
+
// For TRIGRAM search, we compute the similarity values using a subquery, similar to normal cursor.
|
|
361
|
+
// If the cursor entity has been deleted, the subquery returns no rows and the
|
|
362
|
+
// comparison evaluates to NULL, filtering out all results (empty page).
|
|
363
|
+
const operator = direction === PaginationDirection.FORWARD ? '<' : '>';
|
|
364
|
+
const idField = (0, entity_1.getDatabaseFieldForEntityField)(this.entityConfiguration, this.entityConfiguration.idField);
|
|
365
|
+
const exactMatchExpr = this.buildTrigramExactMatchCaseExpression(search);
|
|
366
|
+
const similarityExpr = this.buildTrigramSimilarityGreatestExpression(search);
|
|
367
|
+
// Build extra order by fields
|
|
368
|
+
const extraOrderByFields = search.extraOrderByFields;
|
|
369
|
+
const extraFields = extraOrderByFields?.map((f) => this.resolveSearchFieldToSQLFragment(f)) ?? [];
|
|
370
|
+
// Build left side of comparison (current row's computed values)
|
|
371
|
+
const leftSide = SQLOperator_1.SQLFragment.joinWithCommaSeparator(exactMatchExpr, similarityExpr, ...extraFields, (0, SQLOperator_1.sql) `${(0, SQLOperator_1.identifier)(idField)}`);
|
|
372
|
+
// Build right side using subquery to get computed values for cursor entity
|
|
373
|
+
// We need to rebuild the same expressions for the cursor row
|
|
374
|
+
const cursorExactMatchExpr = this.buildTrigramExactMatchCaseExpression(search, CURSOR_ROW_TABLE_ALIAS);
|
|
375
|
+
const cursorSimilarityExpr = this.buildTrigramSimilarityGreatestExpression(search, CURSOR_ROW_TABLE_ALIAS);
|
|
376
|
+
const cursorExtraFields = extraOrderByFields?.map((f) => this.resolveSearchFieldToSQLFragment(f, CURSOR_ROW_TABLE_ALIAS)) ?? [];
|
|
377
|
+
// Build SELECT fields for subquery
|
|
378
|
+
const selectFields = [
|
|
379
|
+
cursorExactMatchExpr,
|
|
380
|
+
cursorSimilarityExpr,
|
|
381
|
+
...cursorExtraFields,
|
|
382
|
+
(0, SQLOperator_1.sql) `${(0, SQLOperator_1.unsafeRaw)(CURSOR_ROW_TABLE_ALIAS)}.${(0, SQLOperator_1.identifier)(idField)}`,
|
|
383
|
+
];
|
|
384
|
+
const rightSideSubquery = (0, SQLOperator_1.sql) `
|
|
385
|
+
SELECT ${SQLOperator_1.SQLFragment.joinWithCommaSeparator(...selectFields)}
|
|
386
|
+
FROM ${(0, SQLOperator_1.identifier)(this.entityConfiguration.tableName)} AS ${(0, SQLOperator_1.unsafeRaw)(CURSOR_ROW_TABLE_ALIAS)}
|
|
387
|
+
WHERE ${(0, SQLOperator_1.unsafeRaw)(CURSOR_ROW_TABLE_ALIAS)}.${(0, SQLOperator_1.identifier)(idField)} = ${decodedExternalCursorEntityID}
|
|
388
|
+
`;
|
|
389
|
+
return (0, SQLOperator_1.sql) `(${leftSide}) ${(0, SQLOperator_1.unsafeRaw)(operator)} (${rightSideSubquery})`;
|
|
390
|
+
}
|
|
391
|
+
buildSearchConditionAndOrderBy(search) {
|
|
392
|
+
switch (search.strategy) {
|
|
393
|
+
case PaginationStrategy_1.PaginationStrategy.ILIKE_SEARCH: {
|
|
394
|
+
const conditions = this.buildILikeConditions(search);
|
|
395
|
+
// Order by search fields + ID to match cursor fields
|
|
396
|
+
const searchOrderByClauses = [
|
|
397
|
+
...search.fields.map((field) => ({
|
|
398
|
+
fieldFragment: this.resolveSearchFieldToSQLFragment(field),
|
|
399
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING,
|
|
400
|
+
})),
|
|
401
|
+
{
|
|
402
|
+
fieldName: this.entityConfiguration.idField,
|
|
403
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.ASCENDING,
|
|
404
|
+
},
|
|
405
|
+
];
|
|
406
|
+
return {
|
|
407
|
+
searchWhere: conditions.length > 0 ? SQLOperator_1.SQLFragmentHelpers.or(...conditions) : (0, SQLOperator_1.sql) `1 = 0`,
|
|
408
|
+
searchOrderByClauses,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
case PaginationStrategy_1.PaginationStrategy.TRIGRAM_SEARCH: {
|
|
412
|
+
// PostgreSQL trigram similarity
|
|
413
|
+
const ilikeConditions = this.buildILikeConditions(search);
|
|
414
|
+
const similarityExprs = this.buildTrigramSimilarityExpressions(search);
|
|
415
|
+
(0, assert_1.default)(search.threshold >= 0 && search.threshold <= 1, `Trigram similarity threshold must be between 0 and 1, got ${search.threshold}`);
|
|
416
|
+
const conditions = similarityExprs.map((expr) => (0, SQLOperator_1.sql) `${expr} > ${search.threshold}`);
|
|
417
|
+
// Combine exact matches (ILIKE) with similarity
|
|
418
|
+
const allConditions = [...ilikeConditions, ...conditions];
|
|
419
|
+
// Build ORDER BY clauses for trigram search:
|
|
420
|
+
// 1. Exact matches first (ILIKE)
|
|
421
|
+
// 2. Then by similarity score
|
|
422
|
+
// 3. Then by extra fields and ID field for stability
|
|
423
|
+
const searchOrderByClauses = [
|
|
424
|
+
{
|
|
425
|
+
fieldFragment: this.buildTrigramExactMatchCaseExpression(search),
|
|
426
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING,
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
fieldFragment: this.buildTrigramSimilarityGreatestExpression(search),
|
|
430
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING,
|
|
431
|
+
},
|
|
432
|
+
...(search.extraOrderByFields ?? []).map((field) => ({
|
|
433
|
+
fieldFragment: this.resolveSearchFieldToSQLFragment(field),
|
|
434
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING,
|
|
435
|
+
})),
|
|
436
|
+
{
|
|
437
|
+
fieldName: this.entityConfiguration.idField,
|
|
438
|
+
order: BasePostgresEntityDatabaseAdapter_1.OrderByOrdering.DESCENDING,
|
|
439
|
+
},
|
|
440
|
+
];
|
|
441
|
+
return {
|
|
442
|
+
searchWhere: SQLOperator_1.SQLFragmentHelpers.or(...allConditions),
|
|
443
|
+
searchOrderByClauses,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
static escapeILikePattern(term) {
|
|
449
|
+
return term.replace(/[%_\\]/g, '\\$&');
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
exports.EntityKnexDataManager = EntityKnexDataManager;
|
|
453
|
+
//# sourceMappingURL=EntityKnexDataManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityKnexDataManager.js","sourceRoot":"","sources":["../../../src/internal/EntityKnexDataManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { EntityTableDataCoordinator } from '@expo/entity';
|
|
2
|
+
import { EntityKnexDataManager } from './EntityKnexDataManager';
|
|
3
|
+
export declare function getKnexDataManager<TFields extends Record<string, any>, TIDField extends keyof TFields>(tableDataCoordinator: EntityTableDataCoordinator<TFields, TIDField>): EntityKnexDataManager<TFields, TIDField>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getKnexDataManager = getKnexDataManager;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const BasePostgresEntityDatabaseAdapter_1 = require("../BasePostgresEntityDatabaseAdapter");
|
|
9
|
+
const EntityKnexDataManager_1 = require("./EntityKnexDataManager");
|
|
10
|
+
const weakMaps_1 = require("./weakMaps");
|
|
11
|
+
const knexDataManagerCache = new WeakMap();
|
|
12
|
+
function getKnexDataManager(tableDataCoordinator) {
|
|
13
|
+
return (0, weakMaps_1.computeIfAbsentInWeakMap)(knexDataManagerCache, tableDataCoordinator, (coordinator) => new EntityKnexDataManager_1.EntityKnexDataManager(coordinator.entityConfiguration, requireBasePostgresAdapter(coordinator.databaseAdapter), coordinator.metricsAdapter, coordinator.entityClassName));
|
|
14
|
+
}
|
|
15
|
+
function requireBasePostgresAdapter(databaseAdapter) {
|
|
16
|
+
(0, assert_1.default)(databaseAdapter instanceof BasePostgresEntityDatabaseAdapter_1.BasePostgresEntityDatabaseAdapter, `Cannot create KnexDataManager for EntityTableDataCoordinator with non-Postgres database adapter.`);
|
|
17
|
+
return databaseAdapter;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=getKnexDataManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getKnexDataManager.js","sourceRoot":"","sources":["../../../src/internal/getKnexDataManager.ts"],"names":[],"mappings":";;;;;AAYA,gDAiBC;AA5BD,oDAA4B;AAE5B,4FAAyF;AACzF,mEAAgE;AAChE,yCAAsD;AAEtD,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAGrC,CAAC;AAEJ,SAAgB,kBAAkB,CAIhC,oBAAmE;IAEnE,OAAO,IAAA,mCAAwB,EAC7B,oBAAoB,EACpB,oBAAoB,EACpB,CAAC,WAAW,EAAE,EAAE,CACd,IAAI,6CAAqB,CACvB,WAAW,CAAC,mBAAmB,EAC/B,0BAA0B,CAAC,WAAW,CAAC,eAAe,CAAC,EACvD,WAAW,CAAC,cAAc,EAC1B,WAAW,CAAC,eAAe,CAC5B,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAIjC,eAAyD;IAEzD,IAAA,gBAAM,EACJ,eAAe,YAAY,qEAAiC,EAC5D,kGAAkG,CACnG,CAAC;IACF,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { EntityPrivacyPolicy, IEntityClass, ReadonlyEntity, ViewerContext } from '@expo/entity';
|
|
2
|
+
import { KnexEntityLoaderFactory } from '../KnexEntityLoaderFactory';
|
|
3
|
+
export declare function getKnexEntityLoaderFactory<TFields extends Record<string, any>, TIDField extends keyof NonNullable<Pick<TFields, TSelectedFields>>, TViewerContext extends ViewerContext, TViewerContext2 extends TViewerContext, TEntity extends ReadonlyEntity<TFields, TIDField, TViewerContext, TSelectedFields>, TPrivacyPolicy extends EntityPrivacyPolicy<TFields, TIDField, TViewerContext, TEntity, TSelectedFields>, TSelectedFields extends keyof TFields = keyof TFields>(entityClass: IEntityClass<TFields, TIDField, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields>, viewerContext: TViewerContext2): KnexEntityLoaderFactory<TFields, TIDField, TViewerContext, TEntity, TPrivacyPolicy, TSelectedFields>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getKnexEntityLoaderFactory = getKnexEntityLoaderFactory;
|
|
4
|
+
const KnexEntityLoaderFactory_1 = require("../KnexEntityLoaderFactory");
|
|
5
|
+
const getKnexDataManager_1 = require("./getKnexDataManager");
|
|
6
|
+
const weakMaps_1 = require("./weakMaps");
|
|
7
|
+
const knexEntityLoaderFactoryCache = new WeakMap();
|
|
8
|
+
function getKnexEntityLoaderFactory(entityClass, viewerContext) {
|
|
9
|
+
return (0, weakMaps_1.computeIfAbsentInWeakMap)(knexEntityLoaderFactoryCache, viewerContext.entityCompanionProvider.getCompanionForEntity(entityClass), (companion) => new KnexEntityLoaderFactory_1.KnexEntityLoaderFactory(companion, (0, getKnexDataManager_1.getKnexDataManager)(companion.tableDataCoordinator), companion.metricsAdapter));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=getKnexEntityLoaderFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getKnexEntityLoaderFactory.js","sourceRoot":"","sources":["../../../src/internal/getKnexEntityLoaderFactory.ts"],"names":[],"mappings":";;AAiBA,gEA0CC;AAnDD,wEAAqE;AACrE,6DAA0D;AAC1D,yCAAsD;AAEtD,MAAM,4BAA4B,GAAG,IAAI,OAAO,EAG7C,CAAC;AAEJ,SAAgB,0BAA0B,CAexC,WAOC,EACD,aAA8B;IAS9B,OAAO,IAAA,mCAAwB,EAC7B,4BAA4B,EAC5B,aAAa,CAAC,uBAAuB,CAAC,qBAAqB,CAAC,WAAW,CAAC,EACxE,CAAC,SAAS,EAAE,EAAE,CACZ,IAAI,iDAAuB,CACzB,SAAS,EACT,IAAA,uCAAkB,EAAC,SAAS,CAAC,oBAAoB,CAAC,EAClD,SAAS,CAAC,cAAc,CACzB,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilityTypes.js","sourceRoot":"","sources":["../../../src/internal/utilityTypes.ts"],"names":[],"mappings":";AAAA,kCAAkC;;AAUlC,iCAAiC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If the specified key is not already associated with a value in this weak map, computes
|
|
3
|
+
* its value using the given mapping function and enters it into this map.
|
|
4
|
+
*
|
|
5
|
+
* @param map - map from which to get the key's value or compute and associate
|
|
6
|
+
* @param key - key for which to get the value or with which the computed value is to be associated
|
|
7
|
+
* @param mappingFunction - function to compute a value for key
|
|
8
|
+
*/
|
|
9
|
+
export declare const computeIfAbsentInWeakMap: <K extends WeakKey, V>(map: WeakMap<K, V>, key: K, mappingFunction: (key: K) => V) => V;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeIfAbsentInWeakMap = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* If the specified key is not already associated with a value in this weak map, computes
|
|
6
|
+
* its value using the given mapping function and enters it into this map.
|
|
7
|
+
*
|
|
8
|
+
* @param map - map from which to get the key's value or compute and associate
|
|
9
|
+
* @param key - key for which to get the value or with which the computed value is to be associated
|
|
10
|
+
* @param mappingFunction - function to compute a value for key
|
|
11
|
+
*/
|
|
12
|
+
const computeIfAbsentInWeakMap = (map, key, mappingFunction) => {
|
|
13
|
+
if (!map.has(key)) {
|
|
14
|
+
const value = mappingFunction(key);
|
|
15
|
+
map.set(key, value);
|
|
16
|
+
}
|
|
17
|
+
return map.get(key);
|
|
18
|
+
};
|
|
19
|
+
exports.computeIfAbsentInWeakMap = computeIfAbsentInWeakMap;
|
|
20
|
+
//# sourceMappingURL=weakMaps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weakMaps.js","sourceRoot":"","sources":["../../../src/internal/weakMaps.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACI,MAAM,wBAAwB,GAAG,CACtC,GAAkB,EAClB,GAAM,EACN,eAA8B,EAC3B,EAAE;IACL,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACnC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;AACvB,CAAC,CAAC;AAVW,QAAA,wBAAwB,4BAUnC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EntityPrivacyPolicy, EntityQueryContext, IEntityClass, ReadonlyEntity, ViewerContext } from '@expo/entity';
|
|
2
|
+
import { AuthorizationResultBasedKnexEntityLoader } from './AuthorizationResultBasedKnexEntityLoader';
|
|
3
|
+
import { EnforcingKnexEntityLoader } from './EnforcingKnexEntityLoader';
|
|
4
|
+
/**
|
|
5
|
+
* Vend knex loader for loading entities via non-data-loader methods in a given query context.
|
|
6
|
+
* @param entityClass - entity class to load
|
|
7
|
+
* @param viewerContext - viewer context of loading user
|
|
8
|
+
* @param queryContext - query context in which to perform the load
|
|
9
|
+
*/
|
|
10
|
+
export declare function knexLoader<TMFields extends object, TMIDField extends keyof NonNullable<Pick<TMFields, TMSelectedFields>>, TMViewerContext extends ViewerContext, TMViewerContext2 extends TMViewerContext, TMEntity extends ReadonlyEntity<TMFields, TMIDField, TMViewerContext, TMSelectedFields>, TMPrivacyPolicy extends EntityPrivacyPolicy<TMFields, TMIDField, TMViewerContext, TMEntity, TMSelectedFields>, TMSelectedFields extends keyof TMFields = keyof TMFields>(entityClass: IEntityClass<TMFields, TMIDField, TMViewerContext, TMEntity, TMPrivacyPolicy, TMSelectedFields>, viewerContext: TMViewerContext2, queryContext?: EntityQueryContext): EnforcingKnexEntityLoader<TMFields, TMIDField, TMViewerContext, TMEntity, TMPrivacyPolicy, TMSelectedFields>;
|
|
11
|
+
/**
|
|
12
|
+
* Vend knex loader for loading entities via non-data-loader methods in a given query context.
|
|
13
|
+
* Returns authorization results instead of throwing on authorization errors.
|
|
14
|
+
* @param entityClass - entity class to load
|
|
15
|
+
* @param viewerContext - viewer context of loading user
|
|
16
|
+
* @param queryContext - query context in which to perform the load
|
|
17
|
+
*/
|
|
18
|
+
export declare function knexLoaderWithAuthorizationResults<TMFields extends object, TMIDField extends keyof NonNullable<Pick<TMFields, TMSelectedFields>>, TMViewerContext extends ViewerContext, TMViewerContext2 extends TMViewerContext, TMEntity extends ReadonlyEntity<TMFields, TMIDField, TMViewerContext, TMSelectedFields>, TMPrivacyPolicy extends EntityPrivacyPolicy<TMFields, TMIDField, TMViewerContext, TMEntity, TMSelectedFields>, TMSelectedFields extends keyof TMFields = keyof TMFields>(entityClass: IEntityClass<TMFields, TMIDField, TMViewerContext, TMEntity, TMPrivacyPolicy, TMSelectedFields>, viewerContext: TMViewerContext2, queryContext?: EntityQueryContext): AuthorizationResultBasedKnexEntityLoader<TMFields, TMIDField, TMViewerContext, TMEntity, TMPrivacyPolicy, TMSelectedFields>;
|