@zudojs/database 1.2.0 → 1.2.1
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.
|
@@ -303,19 +303,24 @@ export async function getOrSet(cache, key, loader, options) {
|
|
|
303
303
|
const pending = inflight.get(key);
|
|
304
304
|
if (pending)
|
|
305
305
|
return pending;
|
|
306
|
+
// The cleanup lives outside the promise: the body runs synchronously up to
|
|
307
|
+
// its first `await`, so a loader that throws synchronously would otherwise
|
|
308
|
+
// run the cleanup before the entry is registered and leave the rejected
|
|
309
|
+
// promise cached for the lifetime of the cache.
|
|
306
310
|
const promise = (async () => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return value;
|
|
312
|
-
}
|
|
313
|
-
finally {
|
|
314
|
-
inflight.delete(key);
|
|
315
|
-
}
|
|
311
|
+
const value = await loader();
|
|
312
|
+
if (value !== undefined)
|
|
313
|
+
cache.set(key, value, options);
|
|
314
|
+
return value;
|
|
316
315
|
})();
|
|
317
316
|
inflight.set(key, promise);
|
|
318
|
-
|
|
317
|
+
try {
|
|
318
|
+
return await promise;
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
if (inflight.get(key) === promise)
|
|
322
|
+
inflight.delete(key);
|
|
323
|
+
}
|
|
319
324
|
}
|
|
320
325
|
/**
|
|
321
326
|
* Invalidates all entries whose keys start with a prefix.
|
|
@@ -84,6 +84,23 @@ export function validateInclude(include) {
|
|
|
84
84
|
validateInclude(nested);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Validates a single include level: its shape, relation name and select
|
|
89
|
+
* fields, leaving nested includes to the caller.
|
|
90
|
+
*
|
|
91
|
+
* `buildInclude` uses this so the depth bound applies per level — a
|
|
92
|
+
* recursive validation would walk the whole caller-supplied subtree before
|
|
93
|
+
* the depth guard could refuse it.
|
|
94
|
+
*/
|
|
95
|
+
function validateIncludeLevel(include) {
|
|
96
|
+
if (!include || typeof include !== "object") {
|
|
97
|
+
throw new TypeError("A relation include is required.");
|
|
98
|
+
}
|
|
99
|
+
validateRelationName(include.relation);
|
|
100
|
+
for (const field of include.select ?? []) {
|
|
101
|
+
validateFieldName(field);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
87
104
|
/**
|
|
88
105
|
* Translates relation includes into a Prisma `include` object.
|
|
89
106
|
*
|
|
@@ -105,10 +122,13 @@ function buildInclude(includes, options, parent, depth, maxDepth, path) {
|
|
|
105
122
|
if (depth > maxDepth) {
|
|
106
123
|
throw new RangeError(`Relation include depth exceeds the maximum of ${maxDepth}.`);
|
|
107
124
|
}
|
|
108
|
-
|
|
125
|
+
// A null-prototype accumulator: relation names such as `toString` or
|
|
126
|
+
// `__proto__` must behave as ordinary keys. It is spread into a plain
|
|
127
|
+
// object before it is returned.
|
|
128
|
+
const result = Object.create(null);
|
|
109
129
|
for (const include of includes) {
|
|
110
|
-
|
|
111
|
-
if (include.relation
|
|
130
|
+
validateIncludeLevel(include);
|
|
131
|
+
if (Object.hasOwn(result, include.relation)) {
|
|
112
132
|
throw new TypeError(`Relation "${include.relation}" is included more than once.`);
|
|
113
133
|
}
|
|
114
134
|
let definition;
|
|
@@ -123,11 +143,11 @@ function buildInclude(includes, options, parent, depth, maxDepth, path) {
|
|
|
123
143
|
}
|
|
124
144
|
const entry = {};
|
|
125
145
|
if (include.select && include.select.length > 0) {
|
|
126
|
-
const select =
|
|
146
|
+
const select = Object.create(null);
|
|
127
147
|
for (const field of include.select) {
|
|
128
148
|
select[field] = true;
|
|
129
149
|
}
|
|
130
|
-
entry["select"] = select;
|
|
150
|
+
entry["select"] = { ...select };
|
|
131
151
|
}
|
|
132
152
|
if (include.include && include.include.length > 0) {
|
|
133
153
|
const nested = buildInclude(include.include, options, definition ? definition.child : undefined, depth + 1, maxDepth, definition ? [...path, definition] : path);
|
|
@@ -147,7 +167,7 @@ function buildInclude(includes, options, parent, depth, maxDepth, path) {
|
|
|
147
167
|
}
|
|
148
168
|
result[include.relation] = Object.keys(entry).length === 0 ? true : entry;
|
|
149
169
|
}
|
|
150
|
-
return result;
|
|
170
|
+
return { ...result };
|
|
151
171
|
}
|
|
152
172
|
/**
|
|
153
173
|
* Creates a nested relation include.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/database",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Database abstraction layer with clients, repositories, transactions, and query building for Zudojs applications.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"!dist/.tsbuildinfo"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@zudojs/errors": "1.
|
|
45
|
-
"@zudojs/logger": "1.
|
|
46
|
-
"@zudojs/types": "1.1.
|
|
44
|
+
"@zudojs/errors": "1.2.0",
|
|
45
|
+
"@zudojs/logger": "1.3.0",
|
|
46
|
+
"@zudojs/types": "1.1.1"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@prisma/client": ">=7.0.0 <8"
|