@aeriajs/core 0.0.181 → 0.0.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collection/cascadingRemove.d.ts +20 -1
- package/dist/collection/cascadingRemove.js +31 -29
- package/dist/collection/cascadingRemove.mjs +29 -29
- package/dist/collection/reference.js +5 -3
- package/dist/collection/reference.mjs +3 -3
- package/dist/collection/traverseDocument.d.ts +1 -0
- package/dist/collection/traverseDocument.js +41 -55
- package/dist/collection/traverseDocument.mjs +42 -53
- package/dist/database.js +1 -0
- package/dist/database.mjs +2 -1
- package/dist/functions/insert.js +1 -0
- package/dist/functions/insert.mjs +1 -0
- package/dist/functions/removeAll.js +2 -4
- package/dist/functions/removeAll.mjs +2 -4
- package/package.json +8 -8
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
import type { Context } from '@aeriajs/types';
|
|
1
|
+
import type { Context, RouteContext } from '@aeriajs/types';
|
|
2
|
+
import { ObjectId } from 'mongodb';
|
|
3
|
+
import { type Reference } from './reference.js';
|
|
4
|
+
export declare const preferredRemove: (targetId: ObjectId | (ObjectId | null)[], reference: Reference, parentContext: RouteContext) => Promise<import("mongodb").DeleteResult | {
|
|
5
|
+
readonly _tag: "Result";
|
|
6
|
+
readonly error: undefined;
|
|
7
|
+
readonly result: import("mongodb").DeleteResult;
|
|
8
|
+
} | import("@aeriajs/types").Result.Error<{
|
|
9
|
+
readonly code: import("@aeriajs/types").ACError.OwnershipError;
|
|
10
|
+
} & {
|
|
11
|
+
httpStatus: import("@aeriajs/types").HTTPStatus.Forbidden;
|
|
12
|
+
}> | {
|
|
13
|
+
readonly _tag: "Result";
|
|
14
|
+
readonly error: undefined;
|
|
15
|
+
readonly result: import("mongodb").WithId<Omit<import("@aeriajs/types").PackReferences<import("@aeriajs/types").SchemaWithId<import("@aeriajs/types").Description>>, "_id">> | null;
|
|
16
|
+
} | import("@aeriajs/types").Result.Error<{
|
|
17
|
+
readonly code: import("@aeriajs/types").ACError.ResourceNotFound;
|
|
18
|
+
} & {
|
|
19
|
+
httpStatus: import("@aeriajs/types").HTTPStatus.NotFound;
|
|
20
|
+
}> | undefined>;
|
|
2
21
|
export declare const cascadingRemove: (target: Record<string, unknown>, context: Context) => Promise<void>;
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cascadingRemove = void 0;
|
|
3
|
+
exports.cascadingRemove = exports.preferredRemove = void 0;
|
|
4
4
|
const mongodb_1 = require("mongodb");
|
|
5
5
|
const context_js_1 = require("../context.js");
|
|
6
6
|
const assets_js_1 = require("../assets.js");
|
|
7
7
|
const database_js_1 = require("../database.js");
|
|
8
8
|
const reference_js_1 = require("./reference.js");
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
const internalCascadingRemove = async (target, refMap, context) => {
|
|
10
|
+
for (const refName in refMap) {
|
|
11
|
+
const reference = refMap[refName];
|
|
12
|
+
if (!target[refName]) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (reference.referencedCollection) {
|
|
16
|
+
if (reference.isInline || reference.referencedCollection === 'file') {
|
|
17
|
+
if (target[refName] instanceof mongodb_1.ObjectId || Array.isArray(target[refName])) {
|
|
18
|
+
await (0, exports.preferredRemove)(target[refName], reference, context);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else if (reference.deepReferences) {
|
|
23
|
+
if (Array.isArray(target[refName])) {
|
|
24
|
+
for (const elem of target[refName]) {
|
|
25
|
+
await internalCascadingRemove(elem, reference.deepReferences, context);
|
|
26
|
+
}
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
await internalCascadingRemove(target[refName], reference.deepReferences, context);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
11
32
|
};
|
|
12
33
|
const preferredRemove = async (targetId, reference, parentContext) => {
|
|
13
34
|
if (!reference.referencedCollection) {
|
|
@@ -19,15 +40,19 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
19
40
|
collectionName: reference.referencedCollection,
|
|
20
41
|
});
|
|
21
42
|
if (Array.isArray(targetId)) {
|
|
43
|
+
if (targetId.length === 0) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const nonNullable = targetId.filter((id) => !!id);
|
|
22
47
|
const { result: removeAll } = await (0, assets_js_1.getFunction)(reference.referencedCollection, 'removeAll');
|
|
23
48
|
if (removeAll) {
|
|
24
49
|
return removeAll({
|
|
25
|
-
filters:
|
|
50
|
+
filters: nonNullable,
|
|
26
51
|
}, context);
|
|
27
52
|
}
|
|
28
53
|
return coll.deleteMany({
|
|
29
54
|
_id: {
|
|
30
|
-
$in:
|
|
55
|
+
$in: nonNullable,
|
|
31
56
|
},
|
|
32
57
|
});
|
|
33
58
|
}
|
|
@@ -43,30 +68,7 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
43
68
|
_id: targetId,
|
|
44
69
|
});
|
|
45
70
|
};
|
|
46
|
-
|
|
47
|
-
for (const refName in refMap) {
|
|
48
|
-
const reference = refMap[refName];
|
|
49
|
-
if (!target[refName]) {
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
if (reference.isInline || reference.referencedCollection === 'file') {
|
|
53
|
-
if (target[refName] instanceof mongodb_1.ObjectId) {
|
|
54
|
-
await preferredRemove(target[refName], reference, context);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (reference.deepReferences) {
|
|
58
|
-
if (Array.isArray(target[refName])) {
|
|
59
|
-
for (const elem of target[refName]) {
|
|
60
|
-
await internalCascadingRemove(elem, reference.deepReferences, context);
|
|
61
|
-
}
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (isObject(target[refName])) {
|
|
65
|
-
await internalCascadingRemove(target[refName], reference.deepReferences, context);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
};
|
|
71
|
+
exports.preferredRemove = preferredRemove;
|
|
70
72
|
const cascadingRemove = async (target, context) => {
|
|
71
73
|
const refMap = await (0, reference_js_1.getReferences)(context.description.properties);
|
|
72
74
|
return internalCascadingRemove(target, refMap, context);
|
|
@@ -4,10 +4,30 @@ import { createContext } from "../context.mjs";
|
|
|
4
4
|
import { getFunction } from "../assets.mjs";
|
|
5
5
|
import { getDatabaseCollection } from "../database.mjs";
|
|
6
6
|
import { getReferences } from "./reference.mjs";
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const internalCascadingRemove = async (target, refMap, context) => {
|
|
8
|
+
for (const refName in refMap) {
|
|
9
|
+
const reference = refMap[refName];
|
|
10
|
+
if (!target[refName]) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (reference.referencedCollection) {
|
|
14
|
+
if (reference.isInline || reference.referencedCollection === "file") {
|
|
15
|
+
if (target[refName] instanceof ObjectId || Array.isArray(target[refName])) {
|
|
16
|
+
await preferredRemove(target[refName], reference, context);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
} else if (reference.deepReferences) {
|
|
20
|
+
if (Array.isArray(target[refName])) {
|
|
21
|
+
for (const elem of target[refName]) {
|
|
22
|
+
await internalCascadingRemove(elem, reference.deepReferences, context);
|
|
23
|
+
}
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
await internalCascadingRemove(target[refName], reference.deepReferences, context);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
9
29
|
};
|
|
10
|
-
const preferredRemove = async (targetId, reference, parentContext) => {
|
|
30
|
+
export const preferredRemove = async (targetId, reference, parentContext) => {
|
|
11
31
|
if (!reference.referencedCollection) {
|
|
12
32
|
return;
|
|
13
33
|
}
|
|
@@ -17,15 +37,19 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
17
37
|
collectionName: reference.referencedCollection
|
|
18
38
|
});
|
|
19
39
|
if (Array.isArray(targetId)) {
|
|
40
|
+
if (targetId.length === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const nonNullable = targetId.filter((id) => !!id);
|
|
20
44
|
const { result: removeAll } = await getFunction(reference.referencedCollection, "removeAll");
|
|
21
45
|
if (removeAll) {
|
|
22
46
|
return removeAll({
|
|
23
|
-
filters:
|
|
47
|
+
filters: nonNullable
|
|
24
48
|
}, context);
|
|
25
49
|
}
|
|
26
50
|
return coll.deleteMany({
|
|
27
51
|
_id: {
|
|
28
|
-
$in:
|
|
52
|
+
$in: nonNullable
|
|
29
53
|
}
|
|
30
54
|
});
|
|
31
55
|
}
|
|
@@ -41,30 +65,6 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
41
65
|
_id: targetId
|
|
42
66
|
});
|
|
43
67
|
};
|
|
44
|
-
const internalCascadingRemove = async (target, refMap, context) => {
|
|
45
|
-
for (const refName in refMap) {
|
|
46
|
-
const reference = refMap[refName];
|
|
47
|
-
if (!target[refName]) {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
if (reference.isInline || reference.referencedCollection === "file") {
|
|
51
|
-
if (target[refName] instanceof ObjectId) {
|
|
52
|
-
await preferredRemove(target[refName], reference, context);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (reference.deepReferences) {
|
|
56
|
-
if (Array.isArray(target[refName])) {
|
|
57
|
-
for (const elem of target[refName]) {
|
|
58
|
-
await internalCascadingRemove(elem, reference.deepReferences, context);
|
|
59
|
-
}
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
if (isObject(target[refName])) {
|
|
63
|
-
await internalCascadingRemove(target[refName], reference.deepReferences, context);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
68
|
export const cascadingRemove = async (target, context) => {
|
|
69
69
|
const refMap = await getReferences(context.description.properties);
|
|
70
70
|
return internalCascadingRemove(target, refMap, context);
|
|
@@ -24,15 +24,17 @@ const getReferences = async (properties, options = {}) => {
|
|
|
24
24
|
}
|
|
25
25
|
if (refProperty) {
|
|
26
26
|
const description = (0, common_1.throwIfError)(await (0, assets_js_1.getCollectionAsset)(refProperty.$ref, 'description'));
|
|
27
|
-
if (refProperty.populate) {
|
|
28
|
-
if (refProperty.populate.length === 0) {
|
|
27
|
+
if (refProperty.inline || refProperty.populate) {
|
|
28
|
+
if (refProperty.populate && refProperty.populate.length === 0) {
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
const deepReferences = await (0, exports.getReferences)(description.properties, {
|
|
32
32
|
depth: depth + 1,
|
|
33
33
|
maxDepth: refProperty.populateDepth || maxDepth,
|
|
34
34
|
memoize: `${memoize}.${propName}`,
|
|
35
|
-
populate:
|
|
35
|
+
populate: refProperty.populate
|
|
36
|
+
? Array.from(refProperty.populate)
|
|
37
|
+
: undefined,
|
|
36
38
|
isArrayElement: 'items' in property,
|
|
37
39
|
});
|
|
38
40
|
if (Object.keys(deepReferences).length > 0) {
|
|
@@ -28,15 +28,15 @@ export const getReferences = async (properties, options = {}) => {
|
|
|
28
28
|
}
|
|
29
29
|
if (refProperty) {
|
|
30
30
|
const description = throwIfError(await getCollectionAsset(refProperty.$ref, "description"));
|
|
31
|
-
if (refProperty.populate) {
|
|
32
|
-
if (refProperty.populate.length === 0) {
|
|
31
|
+
if (refProperty.inline || refProperty.populate) {
|
|
32
|
+
if (refProperty.populate && refProperty.populate.length === 0) {
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
35
35
|
const deepReferences = await getReferences(description.properties, {
|
|
36
36
|
depth: depth + 1,
|
|
37
37
|
maxDepth: refProperty.populateDepth || maxDepth,
|
|
38
38
|
memoize: `${memoize}.${propName}`,
|
|
39
|
-
populate: Array.from(refProperty.populate),
|
|
39
|
+
populate: refProperty.populate ? Array.from(refProperty.populate) : void 0,
|
|
40
40
|
isArrayElement: "items" in property
|
|
41
41
|
});
|
|
42
42
|
if (Object.keys(deepReferences).length > 0) {
|
|
@@ -30,7 +30,10 @@ const validation_1 = require("@aeriajs/validation");
|
|
|
30
30
|
const entrypoint_1 = require("@aeriajs/entrypoint");
|
|
31
31
|
const mongodb_1 = require("mongodb");
|
|
32
32
|
const assets_js_1 = require("../assets.js");
|
|
33
|
+
const context_js_1 = require("../context.js");
|
|
33
34
|
const preload_js_1 = require("./preload.js");
|
|
35
|
+
const reference_js_1 = require("./reference.js");
|
|
36
|
+
const cascadingRemove_js_1 = require("./cascadingRemove.js");
|
|
34
37
|
const path = __importStar(require("path"));
|
|
35
38
|
const fs = __importStar(require("fs/promises"));
|
|
36
39
|
const getProperty = (propName, parentProperty) => {
|
|
@@ -49,52 +52,43 @@ const getProperty = (propName, parentProperty) => {
|
|
|
49
52
|
return parentProperty.properties[propName];
|
|
50
53
|
}
|
|
51
54
|
};
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
let file;
|
|
89
|
-
while (file = await files.next()) {
|
|
90
|
-
try {
|
|
91
|
-
await fs.unlink(file.absolute_path);
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
console.trace(err);
|
|
55
|
+
const cleanupReferences = async (value, ctx) => {
|
|
56
|
+
if (ctx.root._id) {
|
|
57
|
+
const refProperty = (0, common_1.getReferenceProperty)(ctx.property);
|
|
58
|
+
if (refProperty && (refProperty.$ref === 'file' || refProperty.inline)) {
|
|
59
|
+
if (ctx.isArray && !Array.isArray(value)) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
const context = ctx.options.context;
|
|
63
|
+
const doc = await context.collections[ctx.options.description.$id].model.findOne({
|
|
64
|
+
_id: new mongodb_1.ObjectId(ctx.root._id),
|
|
65
|
+
}, {
|
|
66
|
+
projection: {
|
|
67
|
+
[ctx.propPath]: 1,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
if (!doc) {
|
|
71
|
+
return types_1.Result.error(types_1.TraverseError.InvalidDocumentId);
|
|
72
|
+
}
|
|
73
|
+
let referenceIds = (0, common_1.getValueFromPath)(doc, ctx.propPath);
|
|
74
|
+
if (!referenceIds) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(referenceIds)) {
|
|
78
|
+
if (!Array.isArray(value)) {
|
|
79
|
+
throw new Error;
|
|
80
|
+
}
|
|
81
|
+
referenceIds = referenceIds.filter((oldId) => !value.some((valueId) => valueId.equals(oldId)));
|
|
82
|
+
}
|
|
83
|
+
const refMap = await (0, reference_js_1.getReferences)(ctx.options.description.properties);
|
|
84
|
+
const reference = (0, common_1.getValueFromPath)(refMap, ctx.propPath);
|
|
85
|
+
await (0, cascadingRemove_js_1.preferredRemove)(referenceIds, reference, await (0, context_js_1.createContext)({
|
|
86
|
+
parentContext: context,
|
|
87
|
+
collectionName: refProperty.$ref,
|
|
88
|
+
}));
|
|
95
89
|
}
|
|
96
90
|
}
|
|
97
|
-
return
|
|
91
|
+
return value;
|
|
98
92
|
};
|
|
99
93
|
const autoCast = (value, ctx) => {
|
|
100
94
|
switch (typeof value) {
|
|
@@ -204,9 +198,6 @@ const moveFiles = async (value, ctx) => {
|
|
|
204
198
|
return types_1.Result.error(types_1.TraverseError.InvalidTempfile);
|
|
205
199
|
}
|
|
206
200
|
if (!value) {
|
|
207
|
-
if (ctx.root._id && !ctx.isArray) {
|
|
208
|
-
await disposeOldFiles(ctx);
|
|
209
|
-
}
|
|
210
201
|
return null;
|
|
211
202
|
}
|
|
212
203
|
if (value instanceof mongodb_1.ObjectId) {
|
|
@@ -221,9 +212,6 @@ const moveFiles = async (value, ctx) => {
|
|
|
221
212
|
if (!tempFile) {
|
|
222
213
|
return types_1.Result.error(types_1.TraverseError.InvalidTempfile);
|
|
223
214
|
}
|
|
224
|
-
if (ctx.root._id && !ctx.isArray) {
|
|
225
|
-
await disposeOldFiles(ctx);
|
|
226
|
-
}
|
|
227
215
|
const { _id: fileId, ...newFile } = tempFile;
|
|
228
216
|
newFile.absolute_path = `${ctx.options.context.config.storage.fs}/${tempFile.absolute_path.split(path.sep).at(-1)}`;
|
|
229
217
|
newFile.owner = ctx.options.context.token.sub;
|
|
@@ -255,11 +243,6 @@ const recurseDeep = async (value, ctx) => {
|
|
|
255
243
|
});
|
|
256
244
|
items.push(result);
|
|
257
245
|
}
|
|
258
|
-
if ('moveFiles' in ctx.options && ctx.options.moveFiles && '$ref' in ctx.property.items && ctx.property.items.$ref === 'file') {
|
|
259
|
-
await disposeOldFiles(ctx, {
|
|
260
|
-
preserveIds: items,
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
246
|
return items;
|
|
264
247
|
}
|
|
265
248
|
return value;
|
|
@@ -450,6 +433,9 @@ const traverseDocument = async (what, description, _options) => {
|
|
|
450
433
|
}
|
|
451
434
|
functions.push(validate);
|
|
452
435
|
}
|
|
436
|
+
if (options.cleanupReferences) {
|
|
437
|
+
functions.push(cleanupReferences);
|
|
438
|
+
}
|
|
453
439
|
if ('moveFiles' in options && options.moveFiles) {
|
|
454
440
|
functions.push(moveFiles);
|
|
455
441
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { Result, ACError, ValidationErrorCode, TraverseError } from "@aeriajs/types";
|
|
3
|
-
import { throwIfError, pipe, isReference, getValueFromPath, isError } from "@aeriajs/common";
|
|
3
|
+
import { throwIfError, pipe, isReference, getReferenceProperty, getValueFromPath, isError } from "@aeriajs/common";
|
|
4
4
|
import { makeValidationError, validateProperty, validateWholeness } from "@aeriajs/validation";
|
|
5
5
|
import { getCollection } from "@aeriajs/entrypoint";
|
|
6
6
|
import { ObjectId } from "mongodb";
|
|
7
7
|
import { getCollectionAsset } from "../assets.mjs";
|
|
8
|
+
import { createContext } from "../context.mjs";
|
|
8
9
|
import { preloadDescription } from "./preload.mjs";
|
|
10
|
+
import { getReferences } from "./reference.mjs";
|
|
11
|
+
import { preferredRemove } from "./cascadingRemove.mjs";
|
|
9
12
|
import * as path from "path";
|
|
10
13
|
import * as fs from "fs/promises";
|
|
11
14
|
const getProperty = (propName, parentProperty) => {
|
|
@@ -24,49 +27,43 @@ const getProperty = (propName, parentProperty) => {
|
|
|
24
27
|
return parentProperty.properties[propName];
|
|
25
28
|
}
|
|
26
29
|
};
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let file;
|
|
62
|
-
while (file = await files.next()) {
|
|
63
|
-
try {
|
|
64
|
-
await fs.unlink(file.absolute_path);
|
|
65
|
-
} catch (err) {
|
|
66
|
-
console.trace(err);
|
|
30
|
+
const cleanupReferences = async (value, ctx) => {
|
|
31
|
+
if (ctx.root._id) {
|
|
32
|
+
const refProperty = getReferenceProperty(ctx.property);
|
|
33
|
+
if (refProperty && (refProperty.$ref === "file" || refProperty.inline)) {
|
|
34
|
+
if (ctx.isArray && !Array.isArray(value)) {
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
const context = ctx.options.context;
|
|
38
|
+
const doc = await context.collections[ctx.options.description.$id].model.findOne({
|
|
39
|
+
_id: new ObjectId(ctx.root._id)
|
|
40
|
+
}, {
|
|
41
|
+
projection: {
|
|
42
|
+
[ctx.propPath]: 1
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
if (!doc) {
|
|
46
|
+
return Result.error(TraverseError.InvalidDocumentId);
|
|
47
|
+
}
|
|
48
|
+
let referenceIds = getValueFromPath(doc, ctx.propPath);
|
|
49
|
+
if (!referenceIds) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(referenceIds)) {
|
|
53
|
+
if (!Array.isArray(value)) {
|
|
54
|
+
throw new Error();
|
|
55
|
+
}
|
|
56
|
+
referenceIds = referenceIds.filter((oldId) => !value.some((valueId) => valueId.equals(oldId)));
|
|
57
|
+
}
|
|
58
|
+
const refMap = await getReferences(ctx.options.description.properties);
|
|
59
|
+
const reference = getValueFromPath(refMap, ctx.propPath);
|
|
60
|
+
await preferredRemove(referenceIds, reference, await createContext({
|
|
61
|
+
parentContext: context,
|
|
62
|
+
collectionName: refProperty.$ref
|
|
63
|
+
}));
|
|
67
64
|
}
|
|
68
65
|
}
|
|
69
|
-
return
|
|
66
|
+
return value;
|
|
70
67
|
};
|
|
71
68
|
const autoCast = (value, ctx) => {
|
|
72
69
|
switch (typeof value) {
|
|
@@ -169,9 +166,6 @@ const moveFiles = async (value, ctx) => {
|
|
|
169
166
|
return Result.error(TraverseError.InvalidTempfile);
|
|
170
167
|
}
|
|
171
168
|
if (!value) {
|
|
172
|
-
if (ctx.root._id && !ctx.isArray) {
|
|
173
|
-
await disposeOldFiles(ctx);
|
|
174
|
-
}
|
|
175
169
|
return null;
|
|
176
170
|
}
|
|
177
171
|
if (value instanceof ObjectId) {
|
|
@@ -186,9 +180,6 @@ const moveFiles = async (value, ctx) => {
|
|
|
186
180
|
if (!tempFile) {
|
|
187
181
|
return Result.error(TraverseError.InvalidTempfile);
|
|
188
182
|
}
|
|
189
|
-
if (ctx.root._id && !ctx.isArray) {
|
|
190
|
-
await disposeOldFiles(ctx);
|
|
191
|
-
}
|
|
192
183
|
const { _id: fileId, ...newFile } = tempFile;
|
|
193
184
|
newFile.absolute_path = `${ctx.options.context.config.storage.fs}/${tempFile.absolute_path.split(path.sep).at(-1)}`;
|
|
194
185
|
newFile.owner = ctx.options.context.token.sub;
|
|
@@ -220,11 +211,6 @@ const recurseDeep = async (value, ctx) => {
|
|
|
220
211
|
});
|
|
221
212
|
items.push(result);
|
|
222
213
|
}
|
|
223
|
-
if ("moveFiles" in ctx.options && ctx.options.moveFiles && "$ref" in ctx.property.items && ctx.property.items.$ref === "file") {
|
|
224
|
-
await disposeOldFiles(ctx, {
|
|
225
|
-
preserveIds: items
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
214
|
return items;
|
|
229
215
|
}
|
|
230
216
|
return value;
|
|
@@ -406,6 +392,9 @@ export const traverseDocument = async (what, description, _options) => {
|
|
|
406
392
|
}
|
|
407
393
|
functions.push(validate);
|
|
408
394
|
}
|
|
395
|
+
if (options.cleanupReferences) {
|
|
396
|
+
functions.push(cleanupReferences);
|
|
397
|
+
}
|
|
409
398
|
if ("moveFiles" in options && options.moveFiles) {
|
|
410
399
|
functions.push(moveFiles);
|
|
411
400
|
}
|
package/dist/database.js
CHANGED
package/dist/database.mjs
CHANGED
package/dist/functions/insert.js
CHANGED
|
@@ -41,6 +41,7 @@ const internalInsert = async (payload, context) => {
|
|
|
41
41
|
validate: true,
|
|
42
42
|
validateRequired: isUpdate ? [] : context.description.required,
|
|
43
43
|
moveFiles: true,
|
|
44
|
+
cleanupReferences: true,
|
|
44
45
|
fromProperties: !isUpdate,
|
|
45
46
|
undefinedToNull: true,
|
|
46
47
|
preserveHidden: true,
|
|
@@ -6,13 +6,11 @@ const common_1 = require("@aeriajs/common");
|
|
|
6
6
|
const security_1 = require("@aeriajs/security");
|
|
7
7
|
const index_js_1 = require("../collection/index.js");
|
|
8
8
|
const internalRemoveAll = async (payload, context) => {
|
|
9
|
-
const
|
|
10
|
-
...payload.filters,
|
|
9
|
+
const filters = (0, common_1.throwIfError)(await (0, index_js_1.traverseDocument)({
|
|
11
10
|
_id: {
|
|
12
11
|
$in: payload.filters,
|
|
13
12
|
},
|
|
14
|
-
}
|
|
15
|
-
const filters = (0, common_1.throwIfError)(await (0, index_js_1.traverseDocument)(filtersWithId, context.description, {
|
|
13
|
+
}, context.description, {
|
|
16
14
|
autoCast: true,
|
|
17
15
|
}));
|
|
18
16
|
const it = context.collection.model.find(filters);
|
|
@@ -4,13 +4,11 @@ import { throwIfError } from "@aeriajs/common";
|
|
|
4
4
|
import { useSecurity } from "@aeriajs/security";
|
|
5
5
|
import { traverseDocument, cascadingRemove } from "../collection/index.mjs";
|
|
6
6
|
const internalRemoveAll = async (payload, context) => {
|
|
7
|
-
const
|
|
8
|
-
...payload.filters,
|
|
7
|
+
const filters = throwIfError(await traverseDocument({
|
|
9
8
|
_id: {
|
|
10
9
|
$in: payload.filters
|
|
11
10
|
}
|
|
12
|
-
}
|
|
13
|
-
const filters = throwIfError(await traverseDocument(filtersWithId, context.description, {
|
|
11
|
+
}, context.description, {
|
|
14
12
|
autoCast: true
|
|
15
13
|
}));
|
|
16
14
|
const it = context.collection.model.find(filters);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeriajs/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.182",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"aeriaMain": "tests/fixtures/aeriaMain.js",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"mongodb-memory-server": "^9.2.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@aeriajs/builtins": "^0.0.
|
|
46
|
-
"@aeriajs/common": "^0.0.
|
|
47
|
-
"@aeriajs/entrypoint": "^0.0.
|
|
48
|
-
"@aeriajs/http": "^0.0.
|
|
49
|
-
"@aeriajs/security": "^0.0.
|
|
50
|
-
"@aeriajs/types": "^0.0.
|
|
51
|
-
"@aeriajs/validation": "^0.0.
|
|
45
|
+
"@aeriajs/builtins": "^0.0.182",
|
|
46
|
+
"@aeriajs/common": "^0.0.112",
|
|
47
|
+
"@aeriajs/entrypoint": "^0.0.115",
|
|
48
|
+
"@aeriajs/http": "^0.0.126",
|
|
49
|
+
"@aeriajs/security": "^0.0.182",
|
|
50
|
+
"@aeriajs/types": "^0.0.95",
|
|
51
|
+
"@aeriajs/validation": "^0.0.115"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"mongodb": "^6.5.0",
|