@aeriajs/core 0.0.95 → 0.0.97
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/assets.d.ts +39 -3
- package/dist/assets.js +18 -20
- package/dist/assets.mjs +19 -21
- package/dist/collection/cascadingRemove.js +6 -7
- package/dist/collection/cascadingRemove.mjs +6 -7
- package/dist/collection/preload.js +5 -4
- package/dist/collection/preload.mjs +6 -5
- package/dist/collection/prepareInsert.js +2 -1
- package/dist/collection/prepareInsert.mjs +2 -1
- package/dist/collection/reference.js +4 -4
- package/dist/collection/reference.mjs +5 -5
- package/dist/collection/traverseDocument.d.ts +9 -1
- package/dist/collection/traverseDocument.js +37 -34
- package/dist/collection/traverseDocument.mjs +41 -38
- package/dist/context.js +4 -4
- package/dist/context.mjs +5 -5
- package/dist/functions/builtin/count.d.ts +5 -1
- package/dist/functions/builtin/count.js +5 -5
- package/dist/functions/builtin/count.mjs +5 -5
- package/dist/functions/builtin/get.js +9 -6
- package/dist/functions/builtin/get.mjs +10 -7
- package/dist/functions/builtin/getAll.d.ts +5 -1
- package/dist/functions/builtin/getAll.js +4 -4
- package/dist/functions/builtin/getAll.mjs +5 -5
- package/dist/functions/builtin/insert.d.ts +1 -20
- package/dist/functions/builtin/insert.js +6 -8
- package/dist/functions/builtin/insert.mjs +7 -9
- package/dist/functions/builtin/remove.d.ts +10 -1
- package/dist/functions/builtin/remove.js +2 -2
- package/dist/functions/builtin/remove.mjs +3 -3
- package/dist/functions/builtin/removeAll.d.ts +5 -1
- package/dist/functions/builtin/removeAll.js +5 -5
- package/dist/functions/builtin/removeAll.mjs +6 -6
- package/dist/functions/builtin/removeFile.d.ts +5 -1
- package/dist/functions/builtin/removeFile.js +3 -1
- package/dist/functions/builtin/removeFile.mjs +3 -1
- package/dist/functions/builtin/upload.d.ts +6 -2
- package/dist/functions/builtin/upload.js +9 -10
- package/dist/functions/builtin/upload.mjs +9 -10
- package/package.json +8 -8
package/dist/assets.d.ts
CHANGED
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
import type { Context, Collection, Token } from '@aeriajs/types';
|
|
2
2
|
import { ACError } from '@aeriajs/types';
|
|
3
|
-
export declare const internalGetCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<
|
|
4
|
-
|
|
3
|
+
export declare const internalGetCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<{
|
|
4
|
+
readonly _tag: "Error";
|
|
5
|
+
readonly error: ACError.ResourceNotFound;
|
|
6
|
+
readonly result: undefined;
|
|
7
|
+
} | {
|
|
8
|
+
readonly _tag: "Result";
|
|
9
|
+
readonly error: undefined;
|
|
10
|
+
readonly result: NonNullable<Collection[TAssetName]>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const getCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<{
|
|
13
|
+
readonly _tag: "Error";
|
|
14
|
+
readonly error: ACError.ResourceNotFound;
|
|
15
|
+
readonly result: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
readonly _tag: "Result";
|
|
18
|
+
readonly error: undefined;
|
|
19
|
+
readonly result: NonNullable<Collection[TAssetName]>;
|
|
20
|
+
}>;
|
|
5
21
|
export declare const getFunction: <TCollectionName extends string, TFunctionName extends string>(collectionName: TCollectionName, functionName: TFunctionName, token?: Token, options?: {
|
|
6
22
|
exposedOnly: boolean;
|
|
7
|
-
}) => Promise<
|
|
23
|
+
}) => Promise<{
|
|
24
|
+
readonly _tag: "Error";
|
|
25
|
+
readonly error: ACError.ResourceNotFound;
|
|
26
|
+
readonly result: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
readonly _tag: "Error";
|
|
29
|
+
readonly error: ACError.FunctionNotFound;
|
|
30
|
+
readonly result: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
readonly _tag: "Error";
|
|
33
|
+
readonly error: ACError.FunctionNotExposed;
|
|
34
|
+
readonly result: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
readonly _tag: "Error";
|
|
37
|
+
readonly error: ACError.AuthorizationError;
|
|
38
|
+
readonly result: undefined;
|
|
39
|
+
} | {
|
|
40
|
+
readonly _tag: "Result";
|
|
41
|
+
readonly error: undefined;
|
|
42
|
+
readonly result: (payload: unknown, context: Context) => Promise<any>;
|
|
43
|
+
}>;
|
package/dist/assets.js
CHANGED
|
@@ -13,61 +13,59 @@ const internalGetCollectionAsset = async (collectionName, assetName) => {
|
|
|
13
13
|
const collection = await (0, entrypoint_1.getCollection)(collectionName);
|
|
14
14
|
const asset = collection?.[assetName];
|
|
15
15
|
if (!asset) {
|
|
16
|
-
return
|
|
16
|
+
return common_1.Result.error(types_1.ACError.ResourceNotFound);
|
|
17
17
|
}
|
|
18
|
-
return
|
|
18
|
+
return common_1.Result.result(asset);
|
|
19
19
|
};
|
|
20
20
|
exports.internalGetCollectionAsset = internalGetCollectionAsset;
|
|
21
21
|
const getCollectionAsset = async (collectionName, assetName) => {
|
|
22
22
|
const cached = assetsMemo.assets[collectionName];
|
|
23
23
|
if (cached?.[assetName]) {
|
|
24
|
-
return
|
|
24
|
+
return common_1.Result.result(cached[assetName]);
|
|
25
25
|
}
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
return
|
|
26
|
+
const { error, result: asset } = await (0, exports.internalGetCollectionAsset)(collectionName, assetName);
|
|
27
|
+
if (error) {
|
|
28
|
+
return common_1.Result.error(error);
|
|
29
29
|
}
|
|
30
|
-
const asset = (0, common_1.unwrapEither)(assetEither);
|
|
31
30
|
assetsMemo.assets[collectionName] ??= {};
|
|
32
31
|
assetsMemo.assets[collectionName][assetName] = asset;
|
|
33
|
-
return
|
|
32
|
+
return common_1.Result.result(asset);
|
|
34
33
|
};
|
|
35
34
|
exports.getCollectionAsset = getCollectionAsset;
|
|
36
35
|
const getFunction = async (collectionName, functionName, token, options = {
|
|
37
36
|
exposedOnly: false,
|
|
38
37
|
}) => {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
return
|
|
38
|
+
const { error, result: functions } = await (0, exports.getCollectionAsset)(collectionName, 'functions');
|
|
39
|
+
if (error) {
|
|
40
|
+
return common_1.Result.error(error);
|
|
42
41
|
}
|
|
43
|
-
const functions = (0, common_1.unwrapEither)(functionsEither);
|
|
44
42
|
if (!(functionName in functions)) {
|
|
45
|
-
return
|
|
43
|
+
return common_1.Result.error(types_1.ACError.FunctionNotFound);
|
|
46
44
|
}
|
|
47
45
|
const collection = await (0, entrypoint_1.getCollection)(collectionName);
|
|
48
46
|
const fn = functions[functionName];
|
|
49
47
|
if (!collection) {
|
|
50
|
-
return
|
|
48
|
+
return common_1.Result.error(types_1.ACError.ResourceNotFound);
|
|
51
49
|
}
|
|
52
50
|
if (options.exposedOnly) {
|
|
53
51
|
const exposedStatus = await (0, accessControl_js_1.isFunctionExposed)(collection, functionName, token);
|
|
54
52
|
switch (exposedStatus) {
|
|
55
|
-
case accessControl_js_1.FunctionExposedStatus.FunctionNotExposed: return
|
|
56
|
-
case accessControl_js_1.FunctionExposedStatus.FunctionNotGranted: return
|
|
53
|
+
case accessControl_js_1.FunctionExposedStatus.FunctionNotExposed: return common_1.Result.error(types_1.ACError.FunctionNotExposed);
|
|
54
|
+
case accessControl_js_1.FunctionExposedStatus.FunctionNotGranted: return common_1.Result.error(types_1.ACError.AuthorizationError);
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
const wrapper = async (payload, context) => {
|
|
60
58
|
const securityPolicy = collection.security?.functions?.[functionName];
|
|
61
59
|
if (securityPolicy) {
|
|
62
60
|
if (securityPolicy.rateLimiting) {
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
return
|
|
61
|
+
const { error } = await (0, security_1.limitRate)(securityPolicy.rateLimiting, context);
|
|
62
|
+
if (error) {
|
|
63
|
+
return common_1.Result.error(error);
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
67
|
return fn(payload, context);
|
|
70
68
|
};
|
|
71
|
-
return
|
|
69
|
+
return common_1.Result.result(wrapper);
|
|
72
70
|
};
|
|
73
71
|
exports.getFunction = getFunction;
|
package/dist/assets.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { ACError } from "@aeriajs/types";
|
|
3
|
-
import {
|
|
3
|
+
import { Result } from "@aeriajs/common";
|
|
4
4
|
import { limitRate } from "@aeriajs/security";
|
|
5
5
|
import { getCollection } from "@aeriajs/entrypoint";
|
|
6
6
|
import { isFunctionExposed, FunctionExposedStatus } from "./accessControl.mjs";
|
|
@@ -11,60 +11,58 @@ export const internalGetCollectionAsset = async (collectionName, assetName) => {
|
|
|
11
11
|
const collection = await getCollection(collectionName);
|
|
12
12
|
const asset = collection?.[assetName];
|
|
13
13
|
if (!asset) {
|
|
14
|
-
return
|
|
14
|
+
return Result.error(ACError.ResourceNotFound);
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return Result.result(asset);
|
|
17
17
|
};
|
|
18
18
|
export const getCollectionAsset = async (collectionName, assetName) => {
|
|
19
19
|
const cached = assetsMemo.assets[collectionName];
|
|
20
20
|
if (cached?.[assetName]) {
|
|
21
|
-
return
|
|
21
|
+
return Result.result(cached[assetName]);
|
|
22
22
|
}
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
return
|
|
23
|
+
const { error, result: asset } = await internalGetCollectionAsset(collectionName, assetName);
|
|
24
|
+
if (error) {
|
|
25
|
+
return Result.error(error);
|
|
26
26
|
}
|
|
27
|
-
const asset = unwrapEither(assetEither);
|
|
28
27
|
assetsMemo.assets[collectionName] ??= {};
|
|
29
28
|
assetsMemo.assets[collectionName][assetName] = asset;
|
|
30
|
-
return
|
|
29
|
+
return Result.result(asset);
|
|
31
30
|
};
|
|
32
31
|
export const getFunction = async (collectionName, functionName, token, options = {
|
|
33
32
|
exposedOnly: false
|
|
34
33
|
}) => {
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
return
|
|
34
|
+
const { error, result: functions } = await getCollectionAsset(collectionName, "functions");
|
|
35
|
+
if (error) {
|
|
36
|
+
return Result.error(error);
|
|
38
37
|
}
|
|
39
|
-
const functions = unwrapEither(functionsEither);
|
|
40
38
|
if (!(functionName in functions)) {
|
|
41
|
-
return
|
|
39
|
+
return Result.error(ACError.FunctionNotFound);
|
|
42
40
|
}
|
|
43
41
|
const collection = await getCollection(collectionName);
|
|
44
42
|
const fn = functions[functionName];
|
|
45
43
|
if (!collection) {
|
|
46
|
-
return
|
|
44
|
+
return Result.error(ACError.ResourceNotFound);
|
|
47
45
|
}
|
|
48
46
|
if (options.exposedOnly) {
|
|
49
47
|
const exposedStatus = await isFunctionExposed(collection, functionName, token);
|
|
50
48
|
switch (exposedStatus) {
|
|
51
49
|
case FunctionExposedStatus.FunctionNotExposed:
|
|
52
|
-
return
|
|
50
|
+
return Result.error(ACError.FunctionNotExposed);
|
|
53
51
|
case FunctionExposedStatus.FunctionNotGranted:
|
|
54
|
-
return
|
|
52
|
+
return Result.error(ACError.AuthorizationError);
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
const wrapper = async (payload, context) => {
|
|
58
56
|
const securityPolicy = collection.security?.functions?.[functionName];
|
|
59
57
|
if (securityPolicy) {
|
|
60
58
|
if (securityPolicy.rateLimiting) {
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
return
|
|
59
|
+
const { error: error2 } = await limitRate(securityPolicy.rateLimiting, context);
|
|
60
|
+
if (error2) {
|
|
61
|
+
return Result.error(error2);
|
|
64
62
|
}
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
return fn(payload, context);
|
|
68
66
|
};
|
|
69
|
-
return
|
|
67
|
+
return Result.result(wrapper);
|
|
70
68
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cascadingRemove = void 0;
|
|
4
|
-
const common_1 = require("@aeriajs/common");
|
|
5
4
|
const context_js_1 = require("../context.js");
|
|
6
5
|
const assets_js_1 = require("../assets.js");
|
|
7
6
|
const database_js_1 = require("../database.js");
|
|
@@ -16,9 +15,9 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
16
15
|
collectionName: reference.referencedCollection,
|
|
17
16
|
});
|
|
18
17
|
if (Array.isArray(targetId)) {
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
const removeAll =
|
|
18
|
+
const { result } = await (0, assets_js_1.getFunction)(reference.referencedCollection, 'removeAll');
|
|
19
|
+
if (result) {
|
|
20
|
+
const removeAll = result;
|
|
22
21
|
return removeAll({
|
|
23
22
|
filters: targetId,
|
|
24
23
|
}, context);
|
|
@@ -29,9 +28,9 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
29
28
|
},
|
|
30
29
|
});
|
|
31
30
|
}
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
const remove =
|
|
31
|
+
const { result } = await (0, assets_js_1.getFunction)(reference.referencedCollection, 'remove');
|
|
32
|
+
if (result) {
|
|
33
|
+
const remove = result;
|
|
35
34
|
return remove({
|
|
36
35
|
filters: {
|
|
37
36
|
_id: targetId,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import { isRight, unwrapEither } from "@aeriajs/common";
|
|
3
2
|
import { createContext } from "../context.mjs";
|
|
4
3
|
import { getFunction } from "../assets.mjs";
|
|
5
4
|
import { getDatabaseCollection } from "../database.mjs";
|
|
@@ -14,9 +13,9 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
14
13
|
collectionName: reference.referencedCollection
|
|
15
14
|
});
|
|
16
15
|
if (Array.isArray(targetId)) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const removeAll =
|
|
16
|
+
const { result: result2 } = await getFunction(reference.referencedCollection, "removeAll");
|
|
17
|
+
if (result2) {
|
|
18
|
+
const removeAll = result2;
|
|
20
19
|
return removeAll({
|
|
21
20
|
filters: targetId
|
|
22
21
|
}, context);
|
|
@@ -27,9 +26,9 @@ const preferredRemove = async (targetId, reference, parentContext) => {
|
|
|
27
26
|
}
|
|
28
27
|
});
|
|
29
28
|
}
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
const remove =
|
|
29
|
+
const { result } = await getFunction(reference.referencedCollection, "remove");
|
|
30
|
+
if (result) {
|
|
31
|
+
const remove = result;
|
|
33
32
|
return remove({
|
|
34
33
|
filters: {
|
|
35
34
|
_id: targetId
|
|
@@ -49,12 +49,13 @@ const recurseProperty = async (_property, propertyName, description) => {
|
|
|
49
49
|
const reference = (0, common_1.getReferenceProperty)(property);
|
|
50
50
|
if (reference) {
|
|
51
51
|
if (!reference.indexes && !reference.inline) {
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
52
|
+
const { error, result: referenceDescription } = await (0, assets_js_1.getCollectionAsset)(reference.$ref, 'description');
|
|
53
|
+
if (error) {
|
|
54
54
|
throw new Error(`description of ${reference.$ref} not found`);
|
|
55
55
|
}
|
|
56
|
-
const
|
|
57
|
-
|
|
56
|
+
const indexes = reference.indexes = referenceDescription.indexes?.filter((index) => {
|
|
57
|
+
return typeof index === 'string';
|
|
58
|
+
});
|
|
58
59
|
if (!indexes) {
|
|
59
60
|
throw new Error(`neither indexes or inline are present on reference property or indexes is set on target description on ${description.$id}.${propertyName}`);
|
|
60
61
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import { getReferenceProperty, deepMerge, serialize
|
|
2
|
+
import { getReferenceProperty, deepMerge, serialize } from "@aeriajs/common";
|
|
3
3
|
import { getCollectionAsset } from "../assets.mjs";
|
|
4
4
|
import * as presets from "../presets/index.mjs";
|
|
5
5
|
const preloadMemo = {};
|
|
@@ -24,12 +24,13 @@ const recurseProperty = async (_property, propertyName, description) => {
|
|
|
24
24
|
const reference = getReferenceProperty(property);
|
|
25
25
|
if (reference) {
|
|
26
26
|
if (!reference.indexes && !reference.inline) {
|
|
27
|
-
const
|
|
28
|
-
if (
|
|
27
|
+
const { error, result: referenceDescription } = await getCollectionAsset(reference.$ref, "description");
|
|
28
|
+
if (error) {
|
|
29
29
|
throw new Error(`description of ${reference.$ref} not found`);
|
|
30
30
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
31
|
+
const indexes = reference.indexes = referenceDescription.indexes?.filter((index) => {
|
|
32
|
+
return typeof index === "string";
|
|
33
|
+
});
|
|
33
34
|
if (!indexes) {
|
|
34
35
|
throw new Error(`neither indexes or inline are present on reference property or indexes is set on target description on ${description.$id}.${propertyName}`);
|
|
35
36
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.prepareInsert = void 0;
|
|
4
|
+
const common_1 = require("@aeriajs/common");
|
|
4
5
|
const prepareCreate = (doc, description) => {
|
|
5
6
|
const result = Object.assign({}, description.defaults || {});
|
|
6
7
|
for (const propName in doc) {
|
|
@@ -37,7 +38,7 @@ const prepareInsert = (payload, description) => {
|
|
|
37
38
|
? prepareUpdate(doc)
|
|
38
39
|
: prepareCreate(doc, description);
|
|
39
40
|
Object.keys(what).forEach((k) => {
|
|
40
|
-
if (
|
|
41
|
+
if ((0, common_1.isEmptyObject)(what[k])) {
|
|
41
42
|
delete what[k];
|
|
42
43
|
}
|
|
43
44
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
import { isEmptyObject } from "@aeriajs/common";
|
|
2
3
|
const prepareCreate = (doc, description) => {
|
|
3
4
|
const result = Object.assign({}, description.defaults || {});
|
|
4
5
|
for (const propName in doc) {
|
|
@@ -33,7 +34,7 @@ export const prepareInsert = (payload, description) => {
|
|
|
33
34
|
delete doc.updated_at;
|
|
34
35
|
const what = docId ? prepareUpdate(doc) : prepareCreate(doc, description);
|
|
35
36
|
Object.keys(what).forEach((k) => {
|
|
36
|
-
if (
|
|
37
|
+
if (isEmptyObject(what[k])) {
|
|
37
38
|
delete what[k];
|
|
38
39
|
}
|
|
39
40
|
});
|
|
@@ -101,7 +101,7 @@ const getReferences = async (properties, options) => {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
|
-
const description = (0, common_1.
|
|
104
|
+
const description = (0, common_1.throwIfError)(await (0, assets_js_1.getCollectionAsset)(refProperty.$ref, 'description'));
|
|
105
105
|
const deepReferences = await (0, exports.getReferences)(description.properties, {
|
|
106
106
|
depth: depth + 1,
|
|
107
107
|
memoize: `${memoize}.${propName}`,
|
|
@@ -112,7 +112,7 @@ const getReferences = async (properties, options) => {
|
|
|
112
112
|
const indexes = refProperty.indexes
|
|
113
113
|
? refProperty.indexes
|
|
114
114
|
: description.indexes || [];
|
|
115
|
-
reference.populatedProperties = (refProperty.populate || []).concat(indexes);
|
|
115
|
+
reference.populatedProperties = (refProperty.populate || []).concat(indexes.filter((index) => typeof index === 'string'));
|
|
116
116
|
}
|
|
117
117
|
if (!refProperty?.$ref && !reference.deepReferences) {
|
|
118
118
|
continue;
|
|
@@ -159,7 +159,7 @@ const buildLookupStages = async (reference, propName, options) => {
|
|
|
159
159
|
else {
|
|
160
160
|
const subPipeline = [];
|
|
161
161
|
if (reference.deepReferences) {
|
|
162
|
-
const subProperties = (0, common_1.
|
|
162
|
+
const subProperties = (0, common_1.throwIfError)(await (0, assets_js_1.getCollectionAsset)(reference.referencedCollection, 'description')).properties;
|
|
163
163
|
subPipeline.push(...await (0, exports.buildLookupPipeline)(reference.deepReferences, {
|
|
164
164
|
project: reference.populatedProperties,
|
|
165
165
|
properties: subProperties,
|
|
@@ -227,7 +227,7 @@ const buildLookupStages = async (reference, propName, options) => {
|
|
|
227
227
|
continue;
|
|
228
228
|
}
|
|
229
229
|
if (refMap.referencedCollection) {
|
|
230
|
-
const description = (0, common_1.
|
|
230
|
+
const description = (0, common_1.throwIfError)(await (0, assets_js_1.getCollectionAsset)(refMap.referencedCollection, 'description'));
|
|
231
231
|
const { stages: result } = await buildLookupStages(refMap, refName, {
|
|
232
232
|
depth: depth + 1,
|
|
233
233
|
parent: withParent(propName),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import {
|
|
2
|
+
import { throwIfError, getReferenceProperty } from "@aeriajs/common";
|
|
3
3
|
import { getCollectionAsset } from "../assets.mjs";
|
|
4
4
|
import { prepareCollectionName } from "../database.mjs";
|
|
5
5
|
const referenceMemo = {};
|
|
@@ -90,7 +90,7 @@ export const getReferences = async (properties, options) => {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
} else {
|
|
93
|
-
const description =
|
|
93
|
+
const description = throwIfError(await getCollectionAsset(refProperty.$ref, "description"));
|
|
94
94
|
const deepReferences = await getReferences(description.properties, {
|
|
95
95
|
depth: depth + 1,
|
|
96
96
|
memoize: `${memoize}.${propName}`
|
|
@@ -99,7 +99,7 @@ export const getReferences = async (properties, options) => {
|
|
|
99
99
|
reference.deepReferences = deepReferences;
|
|
100
100
|
}
|
|
101
101
|
const indexes = refProperty.indexes ? refProperty.indexes : description.indexes || [];
|
|
102
|
-
reference.populatedProperties = (refProperty.populate || []).concat(indexes);
|
|
102
|
+
reference.populatedProperties = (refProperty.populate || []).concat(indexes.filter((index) => typeof index === "string"));
|
|
103
103
|
}
|
|
104
104
|
if (!refProperty?.$ref && !reference.deepReferences) {
|
|
105
105
|
continue;
|
|
@@ -147,7 +147,7 @@ const buildLookupStages = async (reference, propName, options) => {
|
|
|
147
147
|
} else {
|
|
148
148
|
const subPipeline = [];
|
|
149
149
|
if (reference.deepReferences) {
|
|
150
|
-
const subProperties =
|
|
150
|
+
const subProperties = throwIfError(await getCollectionAsset(reference.referencedCollection, "description")).properties;
|
|
151
151
|
subPipeline.push(...await buildLookupPipeline(reference.deepReferences, {
|
|
152
152
|
project: reference.populatedProperties,
|
|
153
153
|
properties: subProperties
|
|
@@ -210,7 +210,7 @@ const buildLookupStages = async (reference, propName, options) => {
|
|
|
210
210
|
continue;
|
|
211
211
|
}
|
|
212
212
|
if (refMap.referencedCollection) {
|
|
213
|
-
const description =
|
|
213
|
+
const description = throwIfError(await getCollectionAsset(refMap.referencedCollection, "description"));
|
|
214
214
|
const { stages: result2 } = await buildLookupStages(refMap, refName, {
|
|
215
215
|
depth: depth + 1,
|
|
216
216
|
parent: withParent(propName),
|
|
@@ -31,5 +31,13 @@ type PhaseContext = {
|
|
|
31
31
|
property: Property;
|
|
32
32
|
options: TraverseOptions & TraverseNormalized;
|
|
33
33
|
};
|
|
34
|
-
export declare const traverseDocument: <const TWhat extends Record<string, unknown>>(what: TWhat, description: Description, _options: TraverseOptions) => Promise<
|
|
34
|
+
export declare const traverseDocument: <const TWhat extends Record<string, unknown>>(what: TWhat, description: Description, _options: TraverseOptions) => Promise<{
|
|
35
|
+
readonly _tag: "Result";
|
|
36
|
+
readonly error: undefined;
|
|
37
|
+
readonly result: any;
|
|
38
|
+
} | {
|
|
39
|
+
readonly _tag: "Error";
|
|
40
|
+
readonly error: ACError.InsecureOperator | ValidationError;
|
|
41
|
+
readonly result: undefined;
|
|
42
|
+
}>;
|
|
35
43
|
export {};
|
|
@@ -65,7 +65,7 @@ const disposeOldFiles = async (ctx, options = {}) => {
|
|
|
65
65
|
},
|
|
66
66
|
});
|
|
67
67
|
if (!doc) {
|
|
68
|
-
return
|
|
68
|
+
return common_1.Result.error(TraverseError.InvalidDocumentId);
|
|
69
69
|
}
|
|
70
70
|
let fileIds = (0, common_1.getValueFromPath)(doc, ctx.propPath);
|
|
71
71
|
if (options.fromIds) {
|
|
@@ -171,10 +171,10 @@ const validate = (value, ctx) => {
|
|
|
171
171
|
return value;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
const
|
|
175
|
-
if (
|
|
176
|
-
return
|
|
177
|
-
[ctx.propName]:
|
|
174
|
+
const { error } = (0, validation_1.validateProperty)(ctx.propName, value, ctx.property);
|
|
175
|
+
if (error) {
|
|
176
|
+
return common_1.Result.error({
|
|
177
|
+
[ctx.propName]: error,
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
return value;
|
|
@@ -196,7 +196,7 @@ const moveFiles = async (value, ctx) => {
|
|
|
196
196
|
_id: new mongodb_1.ObjectId(value.tempId),
|
|
197
197
|
});
|
|
198
198
|
if (!tempFile) {
|
|
199
|
-
return
|
|
199
|
+
return common_1.Result.error(TraverseError.InvalidTempfile);
|
|
200
200
|
}
|
|
201
201
|
if (ctx.root._id) {
|
|
202
202
|
await disposeOldFiles(ctx);
|
|
@@ -212,8 +212,11 @@ const recurseDeep = async (value, ctx) => {
|
|
|
212
212
|
return value;
|
|
213
213
|
}
|
|
214
214
|
if ('properties' in ctx.property) {
|
|
215
|
-
const
|
|
216
|
-
|
|
215
|
+
const { error, result } = await recurse(value, ctx);
|
|
216
|
+
if (error) {
|
|
217
|
+
return common_1.Result.error(error);
|
|
218
|
+
}
|
|
219
|
+
return result;
|
|
217
220
|
}
|
|
218
221
|
if ('items' in ctx.property) {
|
|
219
222
|
if (!Array.isArray(value)) {
|
|
@@ -269,7 +272,7 @@ const recurse = async (target, ctx) => {
|
|
|
269
272
|
// it contains MongoDB query operators
|
|
270
273
|
if (Object.keys(value)[0]?.startsWith('$')) {
|
|
271
274
|
if (!ctx.options.allowOperators) {
|
|
272
|
-
return
|
|
275
|
+
return common_1.Result.error(types_1.ACError.InsecureOperator);
|
|
273
276
|
}
|
|
274
277
|
entries.push([
|
|
275
278
|
propName,
|
|
@@ -280,11 +283,11 @@ const recurse = async (target, ctx) => {
|
|
|
280
283
|
if (Array.isArray(value)) {
|
|
281
284
|
const operations = [];
|
|
282
285
|
for (const operation of value) {
|
|
283
|
-
const
|
|
284
|
-
if (
|
|
285
|
-
return
|
|
286
|
+
const { error, result } = await recurse(operation, ctx);
|
|
287
|
+
if (error) {
|
|
288
|
+
return common_1.Result.error(error);
|
|
286
289
|
}
|
|
287
|
-
operations.push(
|
|
290
|
+
operations.push(result);
|
|
288
291
|
}
|
|
289
292
|
entries.push([
|
|
290
293
|
propName,
|
|
@@ -292,13 +295,13 @@ const recurse = async (target, ctx) => {
|
|
|
292
295
|
]);
|
|
293
296
|
continue;
|
|
294
297
|
}
|
|
295
|
-
const
|
|
296
|
-
if (
|
|
297
|
-
return
|
|
298
|
+
const { error, result: operator } = await recurse(value, ctx);
|
|
299
|
+
if (error) {
|
|
300
|
+
return common_1.Result.error(error);
|
|
298
301
|
}
|
|
299
302
|
entries.push([
|
|
300
303
|
propName,
|
|
301
|
-
|
|
304
|
+
operator,
|
|
302
305
|
]);
|
|
303
306
|
}
|
|
304
307
|
if (property) {
|
|
@@ -307,7 +310,7 @@ const recurse = async (target, ctx) => {
|
|
|
307
310
|
? property.items
|
|
308
311
|
: property;
|
|
309
312
|
if ('$ref' in propCast && value && !(value instanceof mongodb_1.ObjectId)) {
|
|
310
|
-
const targetDescription = await (0, preload_js_1.preloadDescription)((0, common_1.
|
|
313
|
+
const targetDescription = await (0, preload_js_1.preloadDescription)((0, common_1.throwIfError)(await (0, assets_js_1.getCollectionAsset)(propCast.$ref, 'description')));
|
|
311
314
|
if (Array.isArray(value)) {
|
|
312
315
|
const documents = [];
|
|
313
316
|
for (const elem of value) {
|
|
@@ -315,11 +318,11 @@ const recurse = async (target, ctx) => {
|
|
|
315
318
|
documents.push(elem);
|
|
316
319
|
continue;
|
|
317
320
|
}
|
|
318
|
-
const
|
|
319
|
-
if (
|
|
320
|
-
return
|
|
321
|
+
const { error, result } = await (0, exports.traverseDocument)(elem, targetDescription, ctx.options);
|
|
322
|
+
if (error) {
|
|
323
|
+
return common_1.Result.error(error);
|
|
321
324
|
}
|
|
322
|
-
documents.push(
|
|
325
|
+
documents.push(result);
|
|
323
326
|
}
|
|
324
327
|
entries.push([
|
|
325
328
|
propName,
|
|
@@ -327,13 +330,13 @@ const recurse = async (target, ctx) => {
|
|
|
327
330
|
]);
|
|
328
331
|
continue;
|
|
329
332
|
}
|
|
330
|
-
const
|
|
331
|
-
if (
|
|
332
|
-
return
|
|
333
|
+
const { error, result: document } = await (0, exports.traverseDocument)(value, targetDescription, ctx.options);
|
|
334
|
+
if (error) {
|
|
335
|
+
return common_1.Result.error(error);
|
|
333
336
|
}
|
|
334
337
|
entries.push([
|
|
335
338
|
propName,
|
|
336
|
-
|
|
339
|
+
document,
|
|
337
340
|
]);
|
|
338
341
|
continue;
|
|
339
342
|
}
|
|
@@ -352,13 +355,13 @@ const recurse = async (target, ctx) => {
|
|
|
352
355
|
]);
|
|
353
356
|
}
|
|
354
357
|
}
|
|
355
|
-
return
|
|
358
|
+
return common_1.Result.result(Object.fromEntries(entries));
|
|
356
359
|
};
|
|
357
360
|
const traverseDocument = async (what, description, _options) => {
|
|
358
361
|
const options = Object.assign({}, _options);
|
|
359
362
|
const functions = [];
|
|
360
363
|
if (!options.validate && Object.keys(what).length === 0) {
|
|
361
|
-
return
|
|
364
|
+
return common_1.Result.result({});
|
|
362
365
|
}
|
|
363
366
|
if (options.recurseDeep) {
|
|
364
367
|
functions.push(recurseDeep);
|
|
@@ -376,7 +379,7 @@ const traverseDocument = async (what, description, _options) => {
|
|
|
376
379
|
}
|
|
377
380
|
const wholenessError = (0, validation_1.validateWholeness)(what, descriptionCopy);
|
|
378
381
|
if (wholenessError) {
|
|
379
|
-
return
|
|
382
|
+
return common_1.Result.error(wholenessError);
|
|
380
383
|
}
|
|
381
384
|
functions.push(validate);
|
|
382
385
|
}
|
|
@@ -402,21 +405,21 @@ const traverseDocument = async (what, description, _options) => {
|
|
|
402
405
|
},
|
|
403
406
|
}),
|
|
404
407
|
});
|
|
405
|
-
const
|
|
408
|
+
const { error, result } = await recurse(what, {
|
|
406
409
|
root: what,
|
|
407
410
|
property: description,
|
|
408
411
|
propPath: '',
|
|
409
412
|
options,
|
|
410
413
|
});
|
|
411
|
-
if (
|
|
412
|
-
return
|
|
414
|
+
if (error) {
|
|
415
|
+
return common_1.Result.error(error);
|
|
413
416
|
}
|
|
414
417
|
if (validationError) {
|
|
415
|
-
return
|
|
418
|
+
return common_1.Result.error((0, validation_1.makeValidationError)({
|
|
416
419
|
code: types_1.ValidationErrorCode.InvalidProperties,
|
|
417
420
|
errors: validationError,
|
|
418
421
|
}));
|
|
419
422
|
}
|
|
420
|
-
return
|
|
423
|
+
return common_1.Result.result(result);
|
|
421
424
|
};
|
|
422
425
|
exports.traverseDocument = traverseDocument;
|