rads-db 3.1.8 → 3.1.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/README.md +19 -0
- package/dist/config.d.ts +1 -1
- package/dist/index.cjs +37 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +37 -13
- package/dist/{types-5bfcdf8f.d.ts → types-9c3659f0.d.ts} +1 -1
- package/drivers/azureCosmos.cjs +35 -7
- package/drivers/azureCosmos.d.ts +1 -0
- package/drivers/azureCosmos.mjs +46 -33
- package/drivers/azureStorageBlob.cjs +2 -2
- package/drivers/azureStorageBlob.d.ts +1 -0
- package/drivers/azureStorageBlob.mjs +4 -8
- package/drivers/indexedDb.cjs +2 -2
- package/drivers/indexedDb.d.ts +1 -0
- package/drivers/indexedDb.mjs +6 -12
- package/drivers/memory.cjs +18 -11
- package/drivers/memory.d.ts +1 -0
- package/drivers/memory.mjs +46 -73
- package/drivers/restApi.cjs +1 -1
- package/drivers/restApi.d.ts +2 -1
- package/drivers/restApi.mjs +2 -4
- package/features/cache.cjs +2 -2
- package/features/cache.mjs +15 -30
- package/features/eventSourcing.cjs +2 -2
- package/features/eventSourcing.d.ts +1 -0
- package/features/eventSourcing.mjs +8 -16
- package/features/softDelete.cjs +1 -1
- package/features/softDelete.mjs +2 -4
- package/fileUploadDrivers/azureStorageBlob.cjs +1 -1
- package/fileUploadDrivers/cloudinary.cjs +1 -1
- package/fileUploadDrivers/memory.cjs +1 -1
- package/fileUploadDrivers/restApi.cjs +1 -1
- package/fileUploadDrivers/restApi.d.ts +1 -0
- package/fileUploadDrivers/restApi.mjs +1 -2
- package/fileUploadDrivers/supabaseStorage.cjs +1 -1
- package/fileUploadDrivers/supabaseStorage.mjs +3 -6
- package/integrations/node.cjs +2 -2
- package/integrations/node.mjs +12 -22
- package/integrations/nuxtModule.cjs +2 -3
- package/integrations/restEndpoints.cjs +1 -1
- package/integrations/restEndpoints.mjs +8 -16
- package/integrations/restEndpointsDev/restEndpointsDevLint.cjs +2 -3
- package/integrations/restEndpointsDev/restEndpointsDevLint.d.ts +1 -1
- package/integrations/restEndpointsDev/restEndpointsDevLint.mjs +5 -10
- package/integrations/restEndpointsDev.cjs +3 -4
- package/integrations/restEndpointsDev.d.ts +1 -1
- package/integrations/restEndpointsDev.mjs +9 -18
- package/integrations/restEndpointsDev2.cjs +3 -4
- package/integrations/restEndpointsDev2.d.ts +0 -1
- package/integrations/restEndpointsDev2.mjs +3 -6
- package/integrations/vite.mjs +3 -6
- package/package.json +2 -2
package/drivers/indexedDb.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DexieOptions } from 'dexie';
|
|
2
|
+
import type { MinimalDriver, Schema } from 'rads-db';
|
|
2
3
|
declare const _default: (options?: IndexedDbDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
3
4
|
export default _default;
|
|
4
5
|
export interface IndexedDbDriverOptions {
|
package/drivers/indexedDb.mjs
CHANGED
|
@@ -22,8 +22,7 @@ export default (options) => {
|
|
|
22
22
|
const dbWrapper = getDb(options);
|
|
23
23
|
return (schema, entity) => {
|
|
24
24
|
const handle = schema[entity]?.handle;
|
|
25
|
-
if (!handle)
|
|
26
|
-
throw new Error(`Entity ${entity} not found`);
|
|
25
|
+
if (!handle) throw new Error(`Entity ${entity} not found`);
|
|
27
26
|
dbWrapper.entities[handle] = true;
|
|
28
27
|
async function getMany(args, ctx) {
|
|
29
28
|
await initDbIfNeeded(dbName);
|
|
@@ -79,8 +78,7 @@ function applyArgsToDexieTable(table, args) {
|
|
|
79
78
|
if (!collection && orderByProp) {
|
|
80
79
|
if (indexedProps.includes(orderByProp)) {
|
|
81
80
|
collection = table.orderBy(orderByProp);
|
|
82
|
-
if (orderByDirection === "desc")
|
|
83
|
-
collection = collection.reverse();
|
|
81
|
+
if (orderByDirection === "desc") collection = collection.reverse();
|
|
84
82
|
orderByProp = "";
|
|
85
83
|
}
|
|
86
84
|
}
|
|
@@ -92,8 +90,7 @@ function applyArgsToDexieTable(table, args) {
|
|
|
92
90
|
collection = collection.filter((x) => f(x) || false);
|
|
93
91
|
}
|
|
94
92
|
if (maxItemCount && !orderByProp) {
|
|
95
|
-
if (args.cursor)
|
|
96
|
-
collection = collection.offset(_.toNumber(args.cursor));
|
|
93
|
+
if (args.cursor) collection = collection.offset(_.toNumber(args.cursor));
|
|
97
94
|
collection = collection.limit(maxItemCount);
|
|
98
95
|
}
|
|
99
96
|
return { collection, orderByProp, orderByDirection, maxItemCount };
|
|
@@ -125,12 +122,10 @@ function applyTableFiltering(table, where, fieldName) {
|
|
|
125
122
|
}
|
|
126
123
|
}
|
|
127
124
|
function normalizeArgs(args) {
|
|
128
|
-
if (!args)
|
|
129
|
-
args = {};
|
|
125
|
+
if (!args) args = {};
|
|
130
126
|
const where = _.cloneDeep(args.where) || {};
|
|
131
127
|
let orderBy = args.orderBy || "";
|
|
132
|
-
if (_.isArray(orderBy))
|
|
133
|
-
orderBy = orderBy[0] || "";
|
|
128
|
+
if (_.isArray(orderBy)) orderBy = orderBy[0] || "";
|
|
134
129
|
const orderByParts = orderBy.split("_");
|
|
135
130
|
const orderByProperty = orderByParts.slice(0, -1).join(".");
|
|
136
131
|
const orderByDirection = orderByParts.slice(-1)[0];
|
|
@@ -180,8 +175,7 @@ async function initDbInner(dbName) {
|
|
|
180
175
|
}
|
|
181
176
|
function getDb(options) {
|
|
182
177
|
const dbName = options?.dbName || "db";
|
|
183
|
-
if (dbs[dbName]?.db)
|
|
184
|
-
dbs[dbName].db?.close();
|
|
178
|
+
if (dbs[dbName]?.db) dbs[dbName].db?.close();
|
|
185
179
|
dbs[dbName] = { entities: {}, driverOptions: { dbName, dexieOptions: void 0, invalidateCounter: 0, ...options } };
|
|
186
180
|
return dbs[dbName];
|
|
187
181
|
}
|
package/drivers/memory.cjs
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
exports.getAggFromArray = getAggFromArray;
|
|
8
8
|
exports.getFilter = getFilter;
|
|
9
9
|
exports.queryArray = queryArray;
|
|
10
10
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
11
|
-
function _interopRequireDefault(
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
const operatorFns = {
|
|
13
13
|
eq: (x, w) => x === w,
|
|
14
14
|
ieq: (x, w) => x?.toLowerCase() === w?.toLowerCase(),
|
|
@@ -76,14 +76,20 @@ var _default = options => (schema, entity) => {
|
|
|
76
76
|
const where = args.where || {};
|
|
77
77
|
const whereKeys = _lodash.default.keys(where);
|
|
78
78
|
if (whereKeys.length === 1) {
|
|
79
|
-
if (whereKeys[0] === "id")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
if (whereKeys[0] === "id") {
|
|
80
|
+
const node = _lodash.default.cloneDeep([getItemById(where.id)].filter(x => x));
|
|
81
|
+
return {
|
|
82
|
+
nodes: node,
|
|
83
|
+
cursor: null
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (whereKeys[0] === "id_in") {
|
|
87
|
+
const nodes = _lodash.default.cloneDeep(getItemByIds(where.id_in).filter(x => x));
|
|
88
|
+
return {
|
|
89
|
+
nodes,
|
|
90
|
+
cursor: null
|
|
91
|
+
};
|
|
92
|
+
}
|
|
87
93
|
}
|
|
88
94
|
return queryArray(Object.values(itemsById), args);
|
|
89
95
|
}
|
|
@@ -237,6 +243,7 @@ function prepareArgs(args) {
|
|
|
237
243
|
orderByProperty,
|
|
238
244
|
orderByDirection,
|
|
239
245
|
maxItemCount,
|
|
240
|
-
cursor: args.cursor
|
|
246
|
+
cursor: args.cursor,
|
|
247
|
+
pick: args.include
|
|
241
248
|
};
|
|
242
249
|
}
|
package/drivers/memory.d.ts
CHANGED
package/drivers/memory.mjs
CHANGED
|
@@ -12,36 +12,26 @@ const operatorFns = {
|
|
|
12
12
|
jsonContains: (x, w) => {
|
|
13
13
|
const { path, isNull, value } = w;
|
|
14
14
|
const val = _.get(x, path);
|
|
15
|
-
if (val === void 0)
|
|
16
|
-
|
|
17
|
-
if (isNull ===
|
|
18
|
-
|
|
19
|
-
if (isNull === true && val !== null)
|
|
20
|
-
return false;
|
|
21
|
-
if (value != null && val !== value)
|
|
22
|
-
return false;
|
|
15
|
+
if (val === void 0) return false;
|
|
16
|
+
if (isNull === false && val === null) return false;
|
|
17
|
+
if (isNull === true && val !== null) return false;
|
|
18
|
+
if (value != null && val !== value) return false;
|
|
23
19
|
return true;
|
|
24
20
|
},
|
|
25
21
|
arrayContains: (x, w) => x?.includes(w),
|
|
26
22
|
isEmpty: (x, w) => {
|
|
27
23
|
if (!x) {
|
|
28
|
-
if (w === true)
|
|
29
|
-
|
|
30
|
-
if (w === false)
|
|
31
|
-
return false;
|
|
24
|
+
if (w === true) return true;
|
|
25
|
+
if (w === false) return false;
|
|
32
26
|
return true;
|
|
33
27
|
}
|
|
34
|
-
if (w === true)
|
|
35
|
-
|
|
36
|
-
if (w === false)
|
|
37
|
-
return x?.length > 0;
|
|
28
|
+
if (w === true) return x?.length === 0;
|
|
29
|
+
if (w === false) return x?.length > 0;
|
|
38
30
|
return true;
|
|
39
31
|
},
|
|
40
32
|
isNull: (x, w) => {
|
|
41
|
-
if (w === true)
|
|
42
|
-
|
|
43
|
-
if (w === false)
|
|
44
|
-
return x != null;
|
|
33
|
+
if (w === true) return x == null;
|
|
34
|
+
if (w === false) return x != null;
|
|
45
35
|
return true;
|
|
46
36
|
},
|
|
47
37
|
gt: (x, w) => x > w,
|
|
@@ -51,10 +41,8 @@ const operatorFns = {
|
|
|
51
41
|
between: (x, w) => {
|
|
52
42
|
const { start, end } = w || {};
|
|
53
43
|
let result = true;
|
|
54
|
-
if (start)
|
|
55
|
-
|
|
56
|
-
if (end)
|
|
57
|
-
result = result && x >= end;
|
|
44
|
+
if (start) result = result && x >= start;
|
|
45
|
+
if (end) result = result && x >= end;
|
|
58
46
|
return result;
|
|
59
47
|
}
|
|
60
48
|
};
|
|
@@ -71,10 +59,17 @@ export default (options) => (schema, entity) => {
|
|
|
71
59
|
const where = args.where || {};
|
|
72
60
|
const whereKeys = _.keys(where);
|
|
73
61
|
if (whereKeys.length === 1) {
|
|
74
|
-
if (whereKeys[0] === "id")
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
if (whereKeys[0] === "id") {
|
|
63
|
+
const node = _.cloneDeep([getItemById(where.id)].filter((x) => x));
|
|
64
|
+
return { nodes: node, cursor: null };
|
|
65
|
+
}
|
|
66
|
+
if (whereKeys[0] === "id_in") {
|
|
67
|
+
const nodes = _.cloneDeep(getItemByIds(where.id_in).filter((x) => x));
|
|
68
|
+
return {
|
|
69
|
+
nodes,
|
|
70
|
+
cursor: null
|
|
71
|
+
};
|
|
72
|
+
}
|
|
78
73
|
}
|
|
79
74
|
return queryArray(Object.values(itemsById), args);
|
|
80
75
|
}
|
|
@@ -93,8 +88,7 @@ export default (options) => (schema, entity) => {
|
|
|
93
88
|
},
|
|
94
89
|
putMany(items) {
|
|
95
90
|
for (const item of items) {
|
|
96
|
-
if (!item?.id)
|
|
97
|
-
throw new Error(`You must provide an id`);
|
|
91
|
+
if (!item?.id) throw new Error(`You must provide an id`);
|
|
98
92
|
itemsById[item.id] = item;
|
|
99
93
|
}
|
|
100
94
|
}
|
|
@@ -106,67 +100,51 @@ export function getAggFromArray(array, args) {
|
|
|
106
100
|
const result = {};
|
|
107
101
|
for (const key of agg) {
|
|
108
102
|
const [field, operator] = key.split("_");
|
|
109
|
-
if (operator === "count")
|
|
110
|
-
result[key] = array.length;
|
|
103
|
+
if (operator === "count") result[key] = array.length;
|
|
111
104
|
else {
|
|
112
105
|
const values = array.map((x) => x[field]).filter((x) => x != null);
|
|
113
|
-
if (operator === "min")
|
|
114
|
-
|
|
115
|
-
else if (operator === "
|
|
116
|
-
|
|
117
|
-
else
|
|
118
|
-
result[key] = values.length ? _.max(values) : void 0;
|
|
119
|
-
else if (operator === "sum")
|
|
120
|
-
result[key] = values.length ? _.sum(values) : void 0;
|
|
121
|
-
else
|
|
122
|
-
throw new Error(`Unknown operator: ${operator} (${key})`);
|
|
106
|
+
if (operator === "min") result[key] = values.length ? _.min(values) : void 0;
|
|
107
|
+
else if (operator === "avg") result[key] = values.length ? _.mean(values) : void 0;
|
|
108
|
+
else if (operator === "max") result[key] = values.length ? _.max(values) : void 0;
|
|
109
|
+
else if (operator === "sum") result[key] = values.length ? _.sum(values) : void 0;
|
|
110
|
+
else throw new Error(`Unknown operator: ${operator} (${key})`);
|
|
123
111
|
}
|
|
124
112
|
}
|
|
125
113
|
return result;
|
|
126
114
|
}
|
|
127
115
|
export function queryArray(array, args) {
|
|
128
|
-
if (!array)
|
|
129
|
-
return array;
|
|
116
|
+
if (!array) return array;
|
|
130
117
|
let result = array;
|
|
131
118
|
const { where, orderByProperty, orderByDirection, maxItemCount, cursor } = prepareArgs(args);
|
|
132
119
|
const startIndex = Number(cursor) || 0;
|
|
133
120
|
const endIndex = startIndex + maxItemCount;
|
|
134
121
|
const f = getFilter(where);
|
|
135
|
-
if (f)
|
|
136
|
-
|
|
137
|
-
if (
|
|
138
|
-
result = _.orderBy(result, [orderByProperty], [orderByDirection]);
|
|
139
|
-
if (maxItemCount)
|
|
140
|
-
result = result.slice(startIndex, endIndex);
|
|
122
|
+
if (f) result = result.filter(f);
|
|
123
|
+
if (orderByProperty) result = _.orderBy(result, [orderByProperty], [orderByDirection]);
|
|
124
|
+
if (maxItemCount) result = result.slice(startIndex, endIndex);
|
|
141
125
|
const newCursor = endIndex >= array.length ? null : endIndex;
|
|
142
126
|
return { nodes: _.cloneDeep(result), cursor: newCursor?.toString() || null };
|
|
143
127
|
}
|
|
144
128
|
export function getFilter(where, namePrefix = "") {
|
|
145
|
-
if (_.isEmpty(where))
|
|
146
|
-
return null;
|
|
129
|
+
if (_.isEmpty(where)) return null;
|
|
147
130
|
const andClauses = [];
|
|
148
131
|
for (const key in where) {
|
|
149
132
|
const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
|
|
150
133
|
const name = [namePrefix, nameFromWhere].filter((x) => x).join(".");
|
|
151
134
|
const whereVal = where[key];
|
|
152
|
-
if (whereVal == null)
|
|
153
|
-
continue;
|
|
135
|
+
if (whereVal == null) continue;
|
|
154
136
|
const f = getFilterInner(operator, whereVal, name, namePrefix);
|
|
155
|
-
if (f)
|
|
156
|
-
andClauses.push(f);
|
|
137
|
+
if (f) andClauses.push(f);
|
|
157
138
|
}
|
|
158
|
-
if (andClauses.length === 0)
|
|
159
|
-
return null;
|
|
139
|
+
if (andClauses.length === 0) return null;
|
|
160
140
|
return (x) => resolveAndClauses(andClauses, x);
|
|
161
141
|
}
|
|
162
142
|
function resolveAndClauses(andClauses, x) {
|
|
163
143
|
let result = true;
|
|
164
144
|
for (const ac of andClauses) {
|
|
165
145
|
const clauseResult = ac(x);
|
|
166
|
-
if (clauseResult === false)
|
|
167
|
-
|
|
168
|
-
if (clauseResult == null)
|
|
169
|
-
result = void 0;
|
|
146
|
+
if (clauseResult === false) return false;
|
|
147
|
+
if (clauseResult == null) result = void 0;
|
|
170
148
|
}
|
|
171
149
|
return result;
|
|
172
150
|
}
|
|
@@ -193,11 +171,9 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
193
171
|
return f && ((x) => !_.get(x, name)?.some(f));
|
|
194
172
|
}
|
|
195
173
|
if (operator === "and") {
|
|
196
|
-
if (!_.isArray(whereVal))
|
|
197
|
-
throw new Error(`Value for where._and must be an array`);
|
|
174
|
+
if (!_.isArray(whereVal)) throw new Error(`Value for where._and must be an array`);
|
|
198
175
|
const newAndClauses = whereVal.map((whereValAnd) => getFilter(whereValAnd, namePrefix)).flatMap((x) => x ? [x] : []);
|
|
199
|
-
if (!newAndClauses.length)
|
|
200
|
-
return null;
|
|
176
|
+
if (!newAndClauses.length) return null;
|
|
201
177
|
return (x) => newAndClauses.every((ac) => ac(x));
|
|
202
178
|
}
|
|
203
179
|
if (operator === "not") {
|
|
@@ -205,11 +181,9 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
205
181
|
return f && ((x) => f(x) === false);
|
|
206
182
|
}
|
|
207
183
|
if (operator === "or") {
|
|
208
|
-
if (!_.isArray(whereVal))
|
|
209
|
-
throw new Error(`Value for where._or must be an array`);
|
|
184
|
+
if (!_.isArray(whereVal)) throw new Error(`Value for where._or must be an array`);
|
|
210
185
|
const orClauses = whereVal.map((whereValOr) => getFilter(whereValOr, namePrefix)).flatMap((x) => x ? [x] : []);
|
|
211
|
-
if (!orClauses.length)
|
|
212
|
-
return null;
|
|
186
|
+
if (!orClauses.length) return null;
|
|
213
187
|
return (x) => orClauses.some((oc) => oc(x));
|
|
214
188
|
}
|
|
215
189
|
const operatorFn = operatorFns[operator || "eq"];
|
|
@@ -223,12 +197,11 @@ function prepareArgs(args) {
|
|
|
223
197
|
args = args || {};
|
|
224
198
|
const where = { ...args.where };
|
|
225
199
|
let orderBy = args.orderBy || "";
|
|
226
|
-
if (Array.isArray(orderBy))
|
|
227
|
-
orderBy = orderBy[0] || "";
|
|
200
|
+
if (Array.isArray(orderBy)) orderBy = orderBy[0] || "";
|
|
228
201
|
const orderByParts = orderBy.split("_");
|
|
229
202
|
const orderByProperty = orderByParts.slice(0, -1).join(".");
|
|
230
203
|
const orderByDirection = orderByParts.slice(-1)[0];
|
|
231
204
|
let maxItemCount = args.maxItemCount;
|
|
232
205
|
maxItemCount = maxItemCount || 100;
|
|
233
|
-
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
|
|
206
|
+
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor, pick: args.include };
|
|
234
207
|
}
|
package/drivers/restApi.cjs
CHANGED
package/drivers/restApi.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RestDriverOptions, Schema } from '@/types';
|
|
2
|
+
declare const _default: (options?: RestDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
2
3
|
export default _default;
|
package/drivers/restApi.mjs
CHANGED
|
@@ -15,16 +15,14 @@ export default (options) => (schema, entity) => {
|
|
|
15
15
|
if (!response.ok) {
|
|
16
16
|
const msg = responseJson?.message || responseJson?.statusMessage || response.statusText || "Server error.";
|
|
17
17
|
const err = new Error(msg);
|
|
18
|
-
if (responseJson?.code)
|
|
19
|
-
err.code = responseJson?.code;
|
|
18
|
+
if (responseJson?.code) err.code = responseJson?.code;
|
|
20
19
|
err.fetchResponseJson = responseJson;
|
|
21
20
|
throw err;
|
|
22
21
|
}
|
|
23
22
|
return responseJson;
|
|
24
23
|
}
|
|
25
24
|
const { handlePlural } = schema[entity] || {};
|
|
26
|
-
if (!handlePlural)
|
|
27
|
-
throw new Error(`Entity ${entity} was not found in schema`);
|
|
25
|
+
if (!handlePlural) throw new Error(`Entity ${entity} was not found in schema`);
|
|
28
26
|
const instance = {
|
|
29
27
|
driverName: "restApi",
|
|
30
28
|
async getMany(args, ctx) {
|
package/features/cache.cjs
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
var _memory = _interopRequireDefault(require("rads-db/drivers/memory"));
|
|
8
8
|
var _radsDb = require("rads-db");
|
|
9
|
-
function _interopRequireDefault(
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
var _default = options => {
|
|
11
11
|
const normalizedOptions = normalizeOptions(options);
|
|
12
12
|
const cacheDrivers = {};
|
package/features/cache.mjs
CHANGED
|
@@ -13,8 +13,7 @@ export default (options) => {
|
|
|
13
13
|
for (const typeName in entitiesToPreload) {
|
|
14
14
|
const { where } = entitiesToPreload[typeName];
|
|
15
15
|
const handle = schema[typeName]?.handle;
|
|
16
|
-
if (!handle)
|
|
17
|
-
throw new Error(`Entity ${typeName} was not found`);
|
|
16
|
+
if (!handle) throw new Error(`Entity ${typeName} was not found`);
|
|
18
17
|
cacheStatus[handle].preloadStatus = "loading";
|
|
19
18
|
try {
|
|
20
19
|
const allData = await db[handle].getAll({ where }, { noCache: true });
|
|
@@ -29,8 +28,7 @@ export default (options) => {
|
|
|
29
28
|
}
|
|
30
29
|
for (const typeName of entitiesToCache) {
|
|
31
30
|
const handle = schema[typeName].handle;
|
|
32
|
-
if (!handle)
|
|
33
|
-
throw new Error(`Entity ${typeName} was not found`);
|
|
31
|
+
if (!handle) throw new Error(`Entity ${typeName} was not found`);
|
|
34
32
|
const cacheEntityName = `Cache_${typeName}`;
|
|
35
33
|
schema[cacheEntityName] = {
|
|
36
34
|
...schema[typeName],
|
|
@@ -49,18 +47,15 @@ export default (options) => {
|
|
|
49
47
|
const entitiesToPreloadNoAwait = {};
|
|
50
48
|
for (const typeName in options2.entities) {
|
|
51
49
|
const entityOpts = options2.entities[typeName];
|
|
52
|
-
if (!entityOpts)
|
|
53
|
-
continue;
|
|
50
|
+
if (!entityOpts) continue;
|
|
54
51
|
const entitySettings = entityOpts === true ? {} : entityOpts;
|
|
55
52
|
const normalizedEntitySettings = {
|
|
56
53
|
noAwait: entitySettings.noAwait ?? options2.noAwait,
|
|
57
54
|
revalidateInterval: entitySettings.revalidateInterval ?? options2.revalidateInterval,
|
|
58
55
|
where: entitySettings.where ?? options2.where
|
|
59
56
|
};
|
|
60
|
-
if (normalizedEntitySettings.noAwait)
|
|
61
|
-
|
|
62
|
-
else
|
|
63
|
-
entitiesToPreloadAwait[typeName] = normalizedEntitySettings;
|
|
57
|
+
if (normalizedEntitySettings.noAwait) entitiesToPreloadNoAwait[typeName] = normalizedEntitySettings;
|
|
58
|
+
else entitiesToPreloadAwait[typeName] = normalizedEntitySettings;
|
|
64
59
|
}
|
|
65
60
|
await preloadEntities(entitiesToPreloadAwait);
|
|
66
61
|
preloadEntities(entitiesToPreloadNoAwait);
|
|
@@ -68,16 +63,13 @@ export default (options) => {
|
|
|
68
63
|
};
|
|
69
64
|
},
|
|
70
65
|
async beforeGet(args, ctx, context) {
|
|
71
|
-
if (ctx.noCache)
|
|
72
|
-
return;
|
|
66
|
+
if (ctx.noCache) return;
|
|
73
67
|
const { handle, typeName } = context;
|
|
74
68
|
const d = cacheDrivers[handle];
|
|
75
|
-
if (!d)
|
|
76
|
-
return;
|
|
69
|
+
if (!d) return;
|
|
77
70
|
if (ctx.method === "get") {
|
|
78
71
|
const result2 = await d[ctx.method](args, ctx);
|
|
79
|
-
if (!result2)
|
|
80
|
-
return;
|
|
72
|
+
if (!result2) return;
|
|
81
73
|
const ageMs = Date.now() - result2._cacheUpdatedAt;
|
|
82
74
|
const maxAge = ctx.maxAge ?? normalizedOptions[typeName].maxAge;
|
|
83
75
|
const staleWhileRevalidate = ctx.staleWhileRevalidate ?? normalizedOptions[typeName].staleWhileRevalidate;
|
|
@@ -94,26 +86,22 @@ export default (options) => {
|
|
|
94
86
|
}
|
|
95
87
|
return result2;
|
|
96
88
|
}
|
|
97
|
-
if (cacheStatus[handle].preloadStatus !== "upToDate")
|
|
98
|
-
return;
|
|
89
|
+
if (cacheStatus[handle].preloadStatus !== "upToDate") return;
|
|
99
90
|
const result = await d[ctx.method](args, ctx);
|
|
100
91
|
return result;
|
|
101
92
|
},
|
|
102
93
|
async afterGet(items, args, ctx, context) {
|
|
103
94
|
const { handle } = context;
|
|
104
95
|
const d = cacheDrivers[handle];
|
|
105
|
-
if (!d || !items?.length)
|
|
106
|
-
|
|
107
|
-
if (items[0]._cacheUpdatedAt)
|
|
108
|
-
return;
|
|
96
|
+
if (!d || !items?.length) return;
|
|
97
|
+
if (items[0]._cacheUpdatedAt) return;
|
|
109
98
|
const now = Date.now();
|
|
110
99
|
await d.putMany(items.map((item) => ({ ...item, _cacheUpdatedAt: now })));
|
|
111
100
|
},
|
|
112
101
|
async afterPut(items, ctx, computedContext) {
|
|
113
102
|
const { handle } = computedContext;
|
|
114
103
|
const d = cacheDrivers[handle];
|
|
115
|
-
if (!d)
|
|
116
|
-
return;
|
|
104
|
+
if (!d) return;
|
|
117
105
|
const now = Date.now();
|
|
118
106
|
await d.putMany(items.map((item) => item.doc).map((item) => ({ ...item, _cacheUpdatedAt: now })));
|
|
119
107
|
}
|
|
@@ -130,12 +118,9 @@ function normalizeOptions(options) {
|
|
|
130
118
|
const result = {};
|
|
131
119
|
for (const entity in entities) {
|
|
132
120
|
const v = entities[entity];
|
|
133
|
-
if (!v)
|
|
134
|
-
|
|
135
|
-
else
|
|
136
|
-
result[entity] = defaults;
|
|
137
|
-
else
|
|
138
|
-
result[entity] = { ...defaults, ...v };
|
|
121
|
+
if (!v) continue;
|
|
122
|
+
else if (v === true) result[entity] = defaults;
|
|
123
|
+
else result[entity] = { ...defaults, ...v };
|
|
139
124
|
}
|
|
140
125
|
return result;
|
|
141
126
|
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
8
|
var _radsDb = require("rads-db");
|
|
9
|
-
function _interopRequireDefault(
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
var _default = () => {
|
|
11
11
|
return {
|
|
12
12
|
name: "eventSourcing",
|
|
@@ -10,10 +10,8 @@ export default () => {
|
|
|
10
10
|
};
|
|
11
11
|
function verifyEventSourcingSetup(schema, effects) {
|
|
12
12
|
for (const entityName in schema) {
|
|
13
|
-
if (!schema[entityName].decorators.entity)
|
|
14
|
-
|
|
15
|
-
if (schema[entityName].decorators.precomputed?.preset !== "eventSourcing")
|
|
16
|
-
continue;
|
|
13
|
+
if (!schema[entityName].decorators.entity) continue;
|
|
14
|
+
if (schema[entityName].decorators.precomputed?.preset !== "eventSourcing") continue;
|
|
17
15
|
const eventEntityName = `${entityName}Event`;
|
|
18
16
|
const aggregateRelationField = _.lowerFirst(entityName);
|
|
19
17
|
validateEventSourcingSetup(schema, entityName, eventEntityName, aggregateRelationField);
|
|
@@ -27,17 +25,14 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
27
25
|
const docsByAggId = {};
|
|
28
26
|
const docsById = {};
|
|
29
27
|
for (const d of docs) {
|
|
30
|
-
if (!d.doc.id || docsById[d.doc.id])
|
|
31
|
-
continue;
|
|
28
|
+
if (!d.doc.id || docsById[d.doc.id]) continue;
|
|
32
29
|
docsById[d.doc.id] = d.doc;
|
|
33
30
|
const aggId = d.doc[aggregateRelationField].id;
|
|
34
|
-
if (!aggId)
|
|
35
|
-
throw new Error(`Missing ${entityName}.${aggregateRelationField}.id`);
|
|
31
|
+
if (!aggId) throw new Error(`Missing ${entityName}.${aggregateRelationField}.id`);
|
|
36
32
|
if (d.oldDoc && aggId !== d.oldDoc[aggregateRelationField].id) {
|
|
37
33
|
throw new Error(`Field ${entityName}.${aggregateRelationField}.id cannot be changed`);
|
|
38
34
|
}
|
|
39
|
-
if (!docsByAggId[aggId])
|
|
40
|
-
docsByAggId[aggId] = [];
|
|
35
|
+
if (!docsByAggId[aggId]) docsByAggId[aggId] = [];
|
|
41
36
|
docsByAggId[aggId].push(d.doc);
|
|
42
37
|
}
|
|
43
38
|
const existingEvents = await context.drivers[eventEntityName].getAll(
|
|
@@ -71,8 +66,7 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
71
66
|
ev.change = diff(newAggDoc, aggDoc);
|
|
72
67
|
handleKeepHistory(schema[entityName].keepHistoryFields, originalChange, ev);
|
|
73
68
|
aggDoc = newAggDoc;
|
|
74
|
-
if (!context.options.keepNulls)
|
|
75
|
-
cleanUndefinedAndNull(aggDoc);
|
|
69
|
+
if (!context.options.keepNulls) cleanUndefinedAndNull(aggDoc);
|
|
76
70
|
}
|
|
77
71
|
result.push({
|
|
78
72
|
aggDoc,
|
|
@@ -119,8 +113,7 @@ function validateEventSourcingSetup(schema, entityName, eventEntityName, aggrega
|
|
|
119
113
|
throw new Error(
|
|
120
114
|
`You must create entity with name "${eventEntityName}" to use eventSourcing feature with "${entityName}"`
|
|
121
115
|
);
|
|
122
|
-
if (!eventEntity.decorators.entity)
|
|
123
|
-
throw new Error(`"${eventEntityName}" must have "@entity()" decorator.`);
|
|
116
|
+
if (!eventEntity.decorators.entity) throw new Error(`"${eventEntityName}" must have "@entity()" decorator.`);
|
|
124
117
|
const expectedFields = {
|
|
125
118
|
id: { type: "string" },
|
|
126
119
|
change: { type: entityName, isChange: true },
|
|
@@ -136,8 +129,7 @@ function validateEventSourcingSetup(schema, entityName, eventEntityName, aggrega
|
|
|
136
129
|
function validateSchemaField(fieldName, eventEntityName, expectedFields, schema) {
|
|
137
130
|
const eventEntity = schema[eventEntityName];
|
|
138
131
|
const field = eventEntity.fields?.[fieldName];
|
|
139
|
-
if (!field)
|
|
140
|
-
throw new Error(`"${eventEntityName}" must have field "${fieldName}"`);
|
|
132
|
+
if (!field) throw new Error(`"${eventEntityName}" must have field "${fieldName}"`);
|
|
141
133
|
const expectedField = expectedFields[fieldName];
|
|
142
134
|
if (expectedField.type && expectedField.type !== field.type) {
|
|
143
135
|
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedField.type}"`);
|
package/features/softDelete.cjs
CHANGED
package/features/softDelete.mjs
CHANGED
|
@@ -2,10 +2,8 @@ export default () => {
|
|
|
2
2
|
return {
|
|
3
3
|
name: "softDelete",
|
|
4
4
|
beforeGet(args, ctx, context) {
|
|
5
|
-
if (!context.schema[context.typeName]?.fields?.isDeleted)
|
|
6
|
-
|
|
7
|
-
if (args.where.isDeleted || args.where.isDeleted_in)
|
|
8
|
-
return;
|
|
5
|
+
if (!context.schema[context.typeName]?.fields?.isDeleted) return;
|
|
6
|
+
if (args.where.isDeleted || args.where.isDeleted_in) return;
|
|
9
7
|
args.where._and = [...args.where._and || [], { isDeleted: false }];
|
|
10
8
|
}
|
|
11
9
|
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export default (options) => {
|
|
2
2
|
options = { baseUrl: "/api", fetch: globalThis.fetch, ...options };
|
|
3
3
|
const fetch = options.fetch || globalThis.fetch;
|
|
4
|
-
if (!options.fetch)
|
|
5
|
-
throw new Error('Please provide "fetch" argument to rest driver definition');
|
|
4
|
+
if (!options.fetch) throw new Error('Please provide "fetch" argument to rest driver definition');
|
|
6
5
|
const driver = {
|
|
7
6
|
driverName: "restApi",
|
|
8
7
|
async uploadFile(args) {
|