@aeriajs/core 0.0.87 → 0.0.89

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.
Files changed (37) hide show
  1. package/dist/assets.d.ts +3 -3
  2. package/dist/assets.js +4 -11
  3. package/dist/assets.mjs +6 -13
  4. package/dist/collection/define.d.ts +2 -3
  5. package/dist/collection/fill.d.ts +2 -0
  6. package/dist/collection/fill.js +14 -0
  7. package/dist/collection/fill.mjs +11 -0
  8. package/dist/collection/index.d.ts +3 -1
  9. package/dist/collection/index.js +3 -1
  10. package/dist/collection/index.mjs +3 -1
  11. package/dist/collection/normalizeProjection.d.ts +2 -0
  12. package/dist/collection/normalizeProjection.js +22 -0
  13. package/dist/collection/normalizeProjection.mjs +17 -0
  14. package/dist/collection/pagination.js +1 -1
  15. package/dist/collection/pagination.mjs +1 -1
  16. package/dist/collection/prepareInsert.d.ts +2 -0
  17. package/dist/collection/prepareInsert.js +46 -0
  18. package/dist/collection/prepareInsert.mjs +41 -0
  19. package/dist/collection/traverseDocument.d.ts +4 -3
  20. package/dist/collection/traverseDocument.js +15 -14
  21. package/dist/collection/traverseDocument.mjs +13 -12
  22. package/dist/context.d.ts +1 -1
  23. package/dist/context.js +1 -1
  24. package/dist/context.mjs +1 -1
  25. package/dist/functions/builtin/get.d.ts +2 -2
  26. package/dist/functions/builtin/get.js +4 -1
  27. package/dist/functions/builtin/get.mjs +4 -1
  28. package/dist/functions/builtin/insert.d.ts +27 -2
  29. package/dist/functions/builtin/insert.js +51 -18
  30. package/dist/functions/builtin/insert.mjs +50 -18
  31. package/dist/functions/builtin/remove.js +5 -4
  32. package/dist/functions/builtin/remove.mjs +6 -5
  33. package/dist/use.d.ts +1 -1
  34. package/package.json +8 -8
  35. package/dist/collection/utils.d.ts +0 -4
  36. package/dist/collection/utils.js +0 -89
  37. package/dist/collection/utils.mjs +0 -76
package/dist/assets.d.ts CHANGED
@@ -1,7 +1,7 @@
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<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Left<ACError.AssetNotFound> | import("@aeriajs/types").Right<any>>;
4
- export declare const getCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Left<ACError.AssetNotFound> | import("@aeriajs/types").Right<NonNullable<Collection[TAssetName]>>>;
3
+ export declare const internalGetCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Right<any>>;
4
+ export declare const getCollectionAsset: <TCollectionName extends string, TAssetName extends "item" | "description" | "security" | "functions" | "contracts" | "exposedFunctions">(collectionName: TCollectionName, assetName: TAssetName) => Promise<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Right<NonNullable<Collection[TAssetName]>>>;
5
5
  export declare const getFunction: <TCollectionName extends string, TFunctionName extends string>(collectionName: TCollectionName, functionName: TFunctionName, token?: Token, options?: {
6
6
  exposedOnly: boolean;
7
- }) => Promise<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Left<ACError.AssetNotFound> | import("@aeriajs/types").Left<ACError.FunctionNotFound> | import("@aeriajs/types").Left<ACError.FunctionNotExposed> | import("@aeriajs/types").Left<ACError.AuthorizationError> | import("@aeriajs/types").Right<(payload: unknown, context: Context) => Promise<any>>>;
7
+ }) => Promise<import("@aeriajs/types").Left<ACError.ResourceNotFound> | import("@aeriajs/types").Left<ACError.FunctionNotFound> | import("@aeriajs/types").Left<ACError.FunctionNotExposed> | import("@aeriajs/types").Left<ACError.AuthorizationError> | import("@aeriajs/types").Right<(payload: unknown, context: Context) => Promise<any>>>;
package/dist/assets.js CHANGED
@@ -13,10 +13,7 @@ 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
- if (!collection) {
17
- return (0, common_1.left)(types_1.ACError.ResourceNotFound);
18
- }
19
- return (0, common_1.left)(types_1.ACError.AssetNotFound);
16
+ return (0, common_1.left)(types_1.ACError.ResourceNotFound);
20
17
  }
21
18
  return (0, common_1.right)(asset);
22
19
  };
@@ -63,13 +60,9 @@ const getFunction = async (collectionName, functionName, token, options = {
63
60
  const securityPolicy = collection.security?.functions?.[functionName];
64
61
  if (securityPolicy) {
65
62
  if (securityPolicy.rateLimiting) {
66
- const rateLimitingEither = await (0, security_1.limitRate)(securityPolicy.rateLimiting, context);
67
- if ((0, common_1.isLeft)(rateLimitingEither)) {
68
- const error = (0, common_1.unwrapEither)(rateLimitingEither);
69
- return context.error(types_1.HTTPStatus.TooManyRequests, {
70
- code: error,
71
- message: 'rate limit was achieved for this resource',
72
- });
63
+ const rate = await (0, security_1.limitRate)(securityPolicy.rateLimiting, context);
64
+ if ((0, common_1.isError)(rate)) {
65
+ return rate;
73
66
  }
74
67
  }
75
68
  }
package/dist/assets.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
- import { ACError, HTTPStatus } from "@aeriajs/types";
3
- import { left, right, isLeft, unwrapEither } from "@aeriajs/common";
2
+ import { ACError } from "@aeriajs/types";
3
+ import { isError, left, right, isLeft, unwrapEither } 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,10 +11,7 @@ export const internalGetCollectionAsset = async (collectionName, assetName) => {
11
11
  const collection = await getCollection(collectionName);
12
12
  const asset = collection?.[assetName];
13
13
  if (!asset) {
14
- if (!collection) {
15
- return left(ACError.ResourceNotFound);
16
- }
17
- return left(ACError.AssetNotFound);
14
+ return left(ACError.ResourceNotFound);
18
15
  }
19
16
  return right(asset);
20
17
  };
@@ -61,13 +58,9 @@ export const getFunction = async (collectionName, functionName, token, options =
61
58
  const securityPolicy = collection.security?.functions?.[functionName];
62
59
  if (securityPolicy) {
63
60
  if (securityPolicy.rateLimiting) {
64
- const rateLimitingEither = await limitRate(securityPolicy.rateLimiting, context);
65
- if (isLeft(rateLimitingEither)) {
66
- const error = unwrapEither(rateLimitingEither);
67
- return context.error(HTTPStatus.TooManyRequests, {
68
- code: error,
69
- message: "rate limit was achieved for this resource"
70
- });
61
+ const rate = await limitRate(securityPolicy.rateLimiting, context);
62
+ if (isError(rate)) {
63
+ return rate;
71
64
  }
72
65
  }
73
66
  }
@@ -8,8 +8,7 @@ export declare const defineCollection: <TCollection extends Omit<Collection<TCol
8
8
  contracts?: TContracts;
9
9
  exposedFunctions?: TExposedFunctions;
10
10
  security?: CollectionSecurityPolicy<{
11
- description: NoInfer<TDescription>;
12
- functions: NoInfer<TFunctions>;
11
+ functions: TFunctions;
13
12
  }>;
14
13
  }) => TCollection & {
15
14
  item: SchemaWithId<TDescription>;
@@ -21,7 +20,7 @@ export declare const extendCollection: <const TLeftCollection extends Collection
21
20
  description?: Partial<Description> | undefined;
22
21
  item?: Partial<any> | undefined;
23
22
  security?: Partial<CollectionSecurityPolicy<any> | undefined>;
24
- functions?: Partial<Record<string, (payload: any, context: import("@aeriajs/types").Context, ...args: any[]) => any> | undefined>;
23
+ functions?: Partial<Record<string, (payload: any, context: import("@aeriajs/types").Context<any>, ...args: any[]) => any> | undefined>;
25
24
  contracts?: Partial<Record<string, Contract> | undefined>;
26
25
  exposedFunctions?: Partial<Record<string, AccessCondition> | undefined>;
27
26
  }>(left: TLeftCollection, right: TRightCollection) => ExtendCollection<TLeftCollection, TRightCollection>;
@@ -0,0 +1,2 @@
1
+ import type { Description } from '@aeriajs/types';
2
+ export declare const fill: <TDocument extends OptionalId<any>>(doc: TDocument & Record<string, any>, description: Description) => Record<string, any> & TDocument;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fill = void 0;
4
+ const common_1 = require("@aeriajs/common");
5
+ const fill = (doc, description) => {
6
+ const docCopy = Object.assign({}, doc);
7
+ for (const key in docCopy) {
8
+ if (docCopy[key] === null) {
9
+ delete docCopy[key];
10
+ }
11
+ }
12
+ return Object.assign((0, common_1.freshItem)(description), docCopy);
13
+ };
14
+ exports.fill = fill;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ import { freshItem } from "@aeriajs/common";
3
+ export const fill = (doc, description) => {
4
+ const docCopy = Object.assign({}, doc);
5
+ for (const key in docCopy) {
6
+ if (docCopy[key] === null) {
7
+ delete docCopy[key];
8
+ }
9
+ }
10
+ return Object.assign(freshItem(description), docCopy);
11
+ };
@@ -1,8 +1,10 @@
1
1
  export * from './cascadingRemove.js';
2
2
  export * from './define.js';
3
3
  export * from './description.js';
4
+ export * from './fill.js';
5
+ export * from './normalizeProjection.js';
4
6
  export * from './pagination.js';
5
7
  export * from './preload.js';
8
+ export * from './prepareInsert.js';
6
9
  export * from './reference.js';
7
10
  export * from './traverseDocument.js';
8
- export * from './utils.js';
@@ -17,8 +17,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./cascadingRemove.js"), exports);
18
18
  __exportStar(require("./define.js"), exports);
19
19
  __exportStar(require("./description.js"), exports);
20
+ __exportStar(require("./fill.js"), exports);
21
+ __exportStar(require("./normalizeProjection.js"), exports);
20
22
  __exportStar(require("./pagination.js"), exports);
21
23
  __exportStar(require("./preload.js"), exports);
24
+ __exportStar(require("./prepareInsert.js"), exports);
22
25
  __exportStar(require("./reference.js"), exports);
23
26
  __exportStar(require("./traverseDocument.js"), exports);
24
- __exportStar(require("./utils.js"), exports);
@@ -2,8 +2,10 @@
2
2
  export * from "./cascadingRemove.mjs";
3
3
  export * from "./define.mjs";
4
4
  export * from "./description.mjs";
5
+ export * from "./fill.mjs";
6
+ export * from "./normalizeProjection.mjs";
5
7
  export * from "./pagination.mjs";
6
8
  export * from "./preload.mjs";
9
+ export * from "./prepareInsert.mjs";
7
10
  export * from "./reference.mjs";
8
11
  export * from "./traverseDocument.mjs";
9
- export * from "./utils.mjs";
@@ -0,0 +1,2 @@
1
+ import type { Description } from '@aeriajs/types';
2
+ export declare const normalizeProjection: <TDescription extends Pick<Description, "properties">, TProjectedProperties extends (keyof TDescription["properties"])[]>(properties: TProjectedProperties, description: TDescription) => {} | null;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeProjection = void 0;
4
+ const normalizeProjection = (properties, description) => {
5
+ const target = Array.from(properties);
6
+ if (target.length === 0) {
7
+ target.push(...Object.keys(description.properties));
8
+ }
9
+ const projection = target.reduce((a, key) => {
10
+ if (key !== '_id' && description.properties[key].hidden) {
11
+ return a;
12
+ }
13
+ return {
14
+ ...a,
15
+ [key]: 1,
16
+ };
17
+ }, {});
18
+ return Object.keys(projection).length === 0
19
+ ? null
20
+ : projection;
21
+ };
22
+ exports.normalizeProjection = normalizeProjection;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ export const normalizeProjection = (properties, description) => {
3
+ const target = Array.from(properties);
4
+ if (target.length === 0) {
5
+ target.push(...Object.keys(description.properties));
6
+ }
7
+ const projection = target.reduce((a, key) => {
8
+ if (key !== "_id" && description.properties[key].hidden) {
9
+ return a;
10
+ }
11
+ return {
12
+ ...a,
13
+ [key]: 1
14
+ };
15
+ }, {});
16
+ return Object.keys(projection).length === 0 ? null : projection;
17
+ };
@@ -6,7 +6,7 @@ const makePagination = async (payload, documents, context) => {
6
6
  ? payload.limit
7
7
  : context.config.paginationLimit;
8
8
  const offset = payload.offset || 0;
9
- const recordsTotal = context.collection.functions.count
9
+ const recordsTotal = context.collection.originalFunctions.count
10
10
  ? await context.collection.functions.count({
11
11
  filters: payload.filters,
12
12
  })
@@ -2,7 +2,7 @@
2
2
  export const makePagination = async (payload, documents, context) => {
3
3
  const limit = payload.limit ? payload.limit : context.config.paginationLimit;
4
4
  const offset = payload.offset || 0;
5
- const recordsTotal = context.collection.functions.count ? await context.collection.functions.count({
5
+ const recordsTotal = context.collection.originalFunctions.count ? await context.collection.functions.count({
6
6
  filters: payload.filters
7
7
  }) : await context.collection.model.countDocuments(payload.filters);
8
8
  return {
@@ -0,0 +1,2 @@
1
+ import type { Description } from '@aeriajs/types';
2
+ export declare const prepareInsert: <TPayload extends Record<string, any>>(payload: TPayload, description: Description) => Record<string, any>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareInsert = void 0;
4
+ const prepareCreate = (doc, description) => {
5
+ const result = Object.assign({}, description.defaults || {});
6
+ for (const propName in doc) {
7
+ const value = doc[propName];
8
+ if (value === null || value === undefined) {
9
+ continue;
10
+ }
11
+ result[propName] = value;
12
+ }
13
+ return result;
14
+ };
15
+ const prepareUpdate = (doc) => {
16
+ const result = {
17
+ $set: {},
18
+ $unset: {},
19
+ };
20
+ for (const propName in doc) {
21
+ const value = doc[propName];
22
+ if (value === null || value === undefined) {
23
+ result.$unset[propName] = value;
24
+ continue;
25
+ }
26
+ result.$set[propName] = value;
27
+ }
28
+ return result;
29
+ };
30
+ const prepareInsert = (payload, description) => {
31
+ const doc = Object.assign({}, payload);
32
+ const docId = payload._id;
33
+ delete doc._id;
34
+ delete doc.created_at;
35
+ delete doc.updated_at;
36
+ const what = docId
37
+ ? prepareUpdate(doc)
38
+ : prepareCreate(doc, description);
39
+ Object.keys(what).forEach((k) => {
40
+ if (typeof what[k] === 'object' && Object.keys(what[k]).length === 0) {
41
+ delete what[k];
42
+ }
43
+ });
44
+ return what;
45
+ };
46
+ exports.prepareInsert = prepareInsert;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ const prepareCreate = (doc, description) => {
3
+ const result = Object.assign({}, description.defaults || {});
4
+ for (const propName in doc) {
5
+ const value = doc[propName];
6
+ if (value === null || value === void 0) {
7
+ continue;
8
+ }
9
+ result[propName] = value;
10
+ }
11
+ return result;
12
+ };
13
+ const prepareUpdate = (doc) => {
14
+ const result = {
15
+ $set: {},
16
+ $unset: {}
17
+ };
18
+ for (const propName in doc) {
19
+ const value = doc[propName];
20
+ if (value === null || value === void 0) {
21
+ result.$unset[propName] = value;
22
+ continue;
23
+ }
24
+ result.$set[propName] = value;
25
+ }
26
+ return result;
27
+ };
28
+ export const prepareInsert = (payload, description) => {
29
+ const doc = Object.assign({}, payload);
30
+ const docId = payload._id;
31
+ delete doc._id;
32
+ delete doc.created_at;
33
+ delete doc.updated_at;
34
+ const what = docId ? prepareUpdate(doc) : prepareCreate(doc, description);
35
+ Object.keys(what).forEach((k) => {
36
+ if (typeof what[k] === "object" && Object.keys(what[k]).length === 0) {
37
+ delete what[k];
38
+ }
39
+ });
40
+ return what;
41
+ };
@@ -1,10 +1,11 @@
1
- import type { Description, Property, ACError, ValidationError, Context } from '@aeriajs/types';
1
+ import type { Description, Property, ValidationError, Context } from '@aeriajs/types';
2
+ import { ACError } from '@aeriajs/types';
2
3
  import { ObjectId } from 'mongodb';
3
4
  export type TraverseOptions = {
4
5
  autoCast?: boolean;
5
6
  getters?: boolean;
6
7
  validate?: boolean;
7
- validateRequired?: string[];
8
+ validateRequired?: Description['required'];
8
9
  moveFiles?: boolean;
9
10
  fromProperties?: boolean;
10
11
  allowOperators?: boolean;
@@ -16,7 +17,7 @@ export type TraverseNormalized = {
16
17
  description: Description;
17
18
  pipe: <T = unknown>(value: unknown, phaseContext: PhaseContext) => T | Promise<T>;
18
19
  };
19
- export declare enum TraverseErrors {
20
+ export declare enum TraverseError {
20
21
  InvalidDocumentId = "INVALID_DOCUMENT_ID",
21
22
  InvalidTempfile = "INVALID_TEMPFILE"
22
23
  }
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.traverseDocument = exports.TraverseErrors = void 0;
26
+ exports.traverseDocument = exports.TraverseError = void 0;
27
27
  const types_1 = require("@aeriajs/types");
28
28
  const common_1 = require("@aeriajs/common");
29
29
  const validation_1 = require("@aeriajs/validation");
@@ -31,11 +31,11 @@ const mongodb_1 = require("mongodb");
31
31
  const assets_js_1 = require("../assets.js");
32
32
  const preload_js_1 = require("./preload.js");
33
33
  const fs = __importStar(require("fs/promises"));
34
- var TraverseErrors;
35
- (function (TraverseErrors) {
36
- TraverseErrors["InvalidDocumentId"] = "INVALID_DOCUMENT_ID";
37
- TraverseErrors["InvalidTempfile"] = "INVALID_TEMPFILE";
38
- })(TraverseErrors || (exports.TraverseErrors = TraverseErrors = {}));
34
+ var TraverseError;
35
+ (function (TraverseError) {
36
+ TraverseError["InvalidDocumentId"] = "INVALID_DOCUMENT_ID";
37
+ TraverseError["InvalidTempfile"] = "INVALID_TEMPFILE";
38
+ })(TraverseError || (exports.TraverseError = TraverseError = {}));
39
39
  const getProperty = (propertyName, parentProperty) => {
40
40
  if (propertyName === '_id') {
41
41
  return {
@@ -65,7 +65,7 @@ const disposeOldFiles = async (ctx, options = {}) => {
65
65
  },
66
66
  });
67
67
  if (!doc) {
68
- return (0, common_1.left)(TraverseErrors.InvalidDocumentId);
68
+ return (0, common_1.left)(TraverseError.InvalidDocumentId);
69
69
  }
70
70
  let fileIds = (0, common_1.getValueFromPath)(doc, ctx.propPath);
71
71
  if (options.fromIds) {
@@ -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 (0, common_1.left)(TraverseErrors.InvalidTempfile);
199
+ return (0, common_1.left)(TraverseError.InvalidTempfile);
200
200
  }
201
201
  if (ctx.root._id) {
202
202
  await disposeOldFiles(ctx);
@@ -268,12 +268,13 @@ const recurse = async (target, ctx) => {
268
268
  // if first propName is preceded by '$' we assume
269
269
  // it contains MongoDB query operators
270
270
  if (Object.keys(value)[0]?.startsWith('$')) {
271
- if (ctx.options.allowOperators) {
272
- entries.push([
273
- propName,
274
- value,
275
- ]);
271
+ if (!ctx.options.allowOperators) {
272
+ return (0, common_1.left)(types_1.ACError.InsecureOperator);
276
273
  }
274
+ entries.push([
275
+ propName,
276
+ value,
277
+ ]);
277
278
  continue;
278
279
  }
279
280
  if (Array.isArray(value)) {
@@ -412,7 +413,7 @@ const traverseDocument = async (what, description, _options) => {
412
413
  }
413
414
  if (validationError) {
414
415
  return (0, common_1.left)((0, validation_1.makeValidationError)({
415
- code: types_1.ValidationErrorCodes.InvalidProperties,
416
+ code: types_1.ValidationErrorCode.InvalidProperties,
416
417
  errors: validationError,
417
418
  }));
418
419
  }
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
- import { ValidationErrorCodes } from "@aeriajs/types";
2
+ import { ACError, ValidationErrorCode } from "@aeriajs/types";
3
3
  import { left, right, isLeft, unwrapEither, unsafe, pipe, isReference, getValueFromPath, isObjectId } from "@aeriajs/common";
4
4
  import { makeValidationError, validateProperty, validateWholeness } from "@aeriajs/validation";
5
5
  import { ObjectId } from "mongodb";
6
6
  import { getCollectionAsset } from "../assets.mjs";
7
7
  import { preloadDescription } from "./preload.mjs";
8
8
  import * as fs from "fs/promises";
9
- export var TraverseErrors = /* @__PURE__ */ ((TraverseErrors2) => {
10
- TraverseErrors2["InvalidDocumentId"] = "INVALID_DOCUMENT_ID";
11
- TraverseErrors2["InvalidTempfile"] = "INVALID_TEMPFILE";
12
- return TraverseErrors2;
13
- })(TraverseErrors || {});
9
+ export var TraverseError = /* @__PURE__ */ ((TraverseError2) => {
10
+ TraverseError2["InvalidDocumentId"] = "INVALID_DOCUMENT_ID";
11
+ TraverseError2["InvalidTempfile"] = "INVALID_TEMPFILE";
12
+ return TraverseError2;
13
+ })(TraverseError || {});
14
14
  const getProperty = (propertyName, parentProperty) => {
15
15
  if (propertyName === "_id") {
16
16
  return {
@@ -230,12 +230,13 @@ const recurse = async (target, ctx) => {
230
230
  }
231
231
  if (!property && value && (value.constructor === Object || value.constructor === Array)) {
232
232
  if (Object.keys(value)[0]?.startsWith("$")) {
233
- if (ctx.options.allowOperators) {
234
- entries.push([
235
- propName,
236
- value
237
- ]);
233
+ if (!ctx.options.allowOperators) {
234
+ return left(ACError.InsecureOperator);
238
235
  }
236
+ entries.push([
237
+ propName,
238
+ value
239
+ ]);
239
240
  continue;
240
241
  }
241
242
  if (Array.isArray(value)) {
@@ -370,7 +371,7 @@ export const traverseDocument = async (what, description, _options) => {
370
371
  }
371
372
  if (validationError) {
372
373
  return left(makeValidationError({
373
- code: ValidationErrorCodes.InvalidProperties,
374
+ code: ValidationErrorCode.InvalidProperties,
374
375
  errors: validationError
375
376
  }));
376
377
  }
package/dist/context.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import type { ContextOptions } from '@aeriajs/types';
2
- export declare const createContext: (options?: ContextOptions) => Promise<import("@aeriajs/types").RouteContext<null> & import("@aeriajs/types").CollectionContext<any, any>>;
2
+ export declare const createContext: (options?: ContextOptions) => Promise<import("@aeriajs/types").RouteContext<null> & import("@aeriajs/types").CollectionContext<import("@aeriajs/types").Description, any>>;
package/dist/context.js CHANGED
@@ -79,7 +79,7 @@ const createContext = async (options = {}) => {
79
79
  context.error = (httpStatus, endpointError) => {
80
80
  return (0, common_1.error)(Object.assign({
81
81
  httpStatus,
82
- }, endpointError), context);
82
+ }, endpointError));
83
83
  };
84
84
  context.limitRate = (params) => {
85
85
  return (0, security_1.limitRate)(params, context);
package/dist/context.mjs CHANGED
@@ -54,7 +54,7 @@ export const createContext = async (options = {}) => {
54
54
  context.error = (httpStatus, endpointError) => {
55
55
  return error(Object.assign({
56
56
  httpStatus
57
- }, endpointError), context);
57
+ }, endpointError));
58
58
  };
59
59
  context.limitRate = (params) => {
60
60
  return limitRate(params, context);
@@ -1,5 +1,5 @@
1
- import type { Context, SchemaWithId, GetPayload } from '@aeriajs/types';
1
+ import type { Context, SchemaWithId, GetPayload, GetReturnType } from '@aeriajs/types';
2
2
  export type GetOptions = {
3
3
  bypassSecurity?: boolean;
4
4
  };
5
- export declare const get: <TContext extends Context>(payload: GetPayload<SchemaWithId<TContext['description']>>, context: TContext extends Context<any> ? TContext : never, options?: GetOptions) => Promise<SchemaWithId<TContext['description']> | null>;
5
+ export declare const get: <TContext extends Context>(payload: GetPayload<SchemaWithId<TContext['description']>>, context: TContext extends Context<any> ? TContext : never, options?: GetOptions) => Promise<GetReturnType<TContext['description']>>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.get = void 0;
4
+ const types_1 = require("@aeriajs/types");
4
5
  const security_1 = require("@aeriajs/security");
5
6
  const common_1 = require("@aeriajs/common");
6
7
  const index_js_1 = require("../../collection/index.js");
@@ -35,7 +36,9 @@ const get = async (payload, context, options) => {
35
36
  }));
36
37
  const result = await context.collection.model.aggregate(pipeline).next();
37
38
  if (!result) {
38
- return null;
39
+ return context.error(types_1.HTTPStatus.NotFound, {
40
+ code: types_1.ACError.ResourceNotFound,
41
+ });
39
42
  }
40
43
  return (0, index_js_1.fill)((0, common_1.unsafe)(await (0, index_js_1.traverseDocument)(result, context.description, {
41
44
  getters: true,
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ import { HTTPStatus, ACError } from "@aeriajs/types";
2
3
  import { useSecurity } from "@aeriajs/security";
3
4
  import { unsafe } from "@aeriajs/common";
4
5
  import {
@@ -40,7 +41,9 @@ export const get = async (payload, context, options) => {
40
41
  }));
41
42
  const result = await context.collection.model.aggregate(pipeline).next();
42
43
  if (!result) {
43
- return null;
44
+ return context.error(HTTPStatus.NotFound, {
45
+ code: ACError.ResourceNotFound
46
+ });
44
47
  }
45
48
  return fill(unsafe(await traverseDocument(result, context.description, {
46
49
  getters: true,
@@ -1,5 +1,30 @@
1
- import type { Context, SchemaWithId, InsertPayload } from '@aeriajs/types';
1
+ import type { Context, SchemaWithId, InsertPayload, InsertReturnType } from '@aeriajs/types';
2
+ import { HTTPStatus, ACError, ValidationErrorCode } from '@aeriajs/types';
2
3
  export type InsertOptions = {
3
4
  bypassSecurity?: boolean;
4
5
  };
5
- export declare const insert: <TContext extends Context>(payload: InsertPayload<SchemaWithId<TContext['description']>>, context: TContext, options?: InsertOptions) => Promise<import("@aeriajs/types").Left<import("@aeriajs/types").ACError | import("@aeriajs/types").ValidationError> | import("@aeriajs/types").Right<SchemaWithId<TContext["description"]>>>;
6
+ export declare const insertErrorSchema: {
7
+ readonly type: "object";
8
+ readonly properties: {
9
+ readonly value: {
10
+ readonly type: "object";
11
+ readonly required: readonly ["httpStatus", "code"];
12
+ readonly properties: {
13
+ readonly httpStatus: {
14
+ readonly enum: (HTTPStatus.NotFound | HTTPStatus.UnprocessableContent)[];
15
+ };
16
+ readonly code: {
17
+ readonly enum: (ACError | ValidationErrorCode)[];
18
+ };
19
+ readonly message: {
20
+ readonly type: "string";
21
+ };
22
+ readonly details: {
23
+ readonly type: "object";
24
+ readonly variable: true;
25
+ };
26
+ };
27
+ };
28
+ };
29
+ };
30
+ export declare const insert: <TContext extends Context>(payload: InsertPayload<SchemaWithId<TContext['description']>>, context: TContext, options?: InsertOptions) => Promise<InsertReturnType<SchemaWithId<TContext['description']>>>;
@@ -1,9 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.insert = void 0;
3
+ exports.insert = exports.insertErrorSchema = void 0;
4
+ const types_1 = require("@aeriajs/types");
4
5
  const security_1 = require("@aeriajs/security");
5
6
  const common_1 = require("@aeriajs/common");
6
7
  const index_js_1 = require("../../collection/index.js");
8
+ exports.insertErrorSchema = (0, common_1.endpointErrorSchema)({
9
+ httpStatus: [
10
+ types_1.HTTPStatus.UnprocessableContent,
11
+ types_1.HTTPStatus.NotFound,
12
+ ],
13
+ code: [
14
+ types_1.ACError.InsecureOperator,
15
+ types_1.ACError.OwnershipError,
16
+ types_1.ACError.ResourceNotFound,
17
+ types_1.ACError.TargetImmutable,
18
+ types_1.ValidationErrorCode.EmptyTarget,
19
+ types_1.ValidationErrorCode.InvalidProperties,
20
+ types_1.ValidationErrorCode.MissingProperties,
21
+ ],
22
+ });
7
23
  const insert = async (payload, context, options) => {
8
24
  const security = (0, security_1.useSecurity)(context);
9
25
  const query = !options?.bypassSecurity
@@ -21,52 +37,69 @@ const insert = async (payload, context, options) => {
21
37
  });
22
38
  if ((0, common_1.isLeft)(whatEither)) {
23
39
  const error = (0, common_1.unwrapEither)(whatEither);
24
- return (0, common_1.left)(error);
40
+ if (typeof error === 'string') {
41
+ return context.error(types_1.HTTPStatus.UnprocessableContent, {
42
+ code: error,
43
+ });
44
+ }
45
+ return context.error(types_1.HTTPStatus.UnprocessableContent, {
46
+ code: error.code,
47
+ details: error.errors,
48
+ });
25
49
  }
26
50
  const what = (0, common_1.unwrapEither)(whatEither);
27
51
  const docId = '_id' in what
28
52
  ? what._id
29
53
  : null;
30
- const readyWhat = (0, index_js_1.prepareInsert)(what, context.description);
54
+ const content = (0, index_js_1.prepareInsert)(what, context.description);
31
55
  const projection = payload.project
32
56
  ? (0, index_js_1.normalizeProjection)(payload.project, context.description)
33
57
  : {};
34
58
  let newId = docId;
35
59
  if (!newId) {
36
60
  const now = new Date();
37
- Object.assign(readyWhat, {
61
+ Object.assign(content, {
38
62
  created_at: now,
39
63
  updated_at: now,
40
64
  });
41
- newId = (await context.collection.model.insertOne(readyWhat)).insertedId;
65
+ newId = (await context.collection.model.insertOne(content)).insertedId;
42
66
  }
43
67
  else {
44
- readyWhat.$set ??= {};
45
- readyWhat.$set.updated_at = new Date();
68
+ content.$set ??= {};
69
+ content.$set.updated_at = new Date();
46
70
  await context.collection.model.updateOne({
47
71
  _id: docId,
48
- }, readyWhat);
72
+ }, content);
49
73
  }
74
+ let doc;
50
75
  if (context.collection.originalFunctions.get) {
51
- const document = await context.collection.originalFunctions.get({
76
+ doc = await context.collection.originalFunctions.get({
52
77
  filters: {
53
78
  _id: newId,
54
79
  },
55
- }, context, {
80
+ }, Object.assign({
81
+ inherited: true,
82
+ }, context), {
56
83
  bypassSecurity: true,
57
84
  });
58
- return (0, common_1.right)(document);
59
85
  }
60
- const document = await context.collection.model.findOne({
61
- _id: newId,
62
- }, {
63
- projection,
64
- });
65
- const result = (0, common_1.unsafe)(await (0, index_js_1.traverseDocument)(document, context.description, {
86
+ else {
87
+ doc = await context.collection.model.findOne({
88
+ _id: newId,
89
+ }, {
90
+ projection,
91
+ });
92
+ }
93
+ if (!doc) {
94
+ return context.error(types_1.HTTPStatus.NotFound, {
95
+ code: types_1.ACError.ResourceNotFound,
96
+ });
97
+ }
98
+ const result = (0, common_1.unsafe)(await (0, index_js_1.traverseDocument)(doc, context.description, {
66
99
  getters: true,
67
100
  fromProperties: true,
68
101
  recurseReferences: true,
69
102
  }));
70
- return (0, common_1.right)(result);
103
+ return result;
71
104
  };
72
105
  exports.insert = insert;
@@ -1,7 +1,23 @@
1
1
  "use strict";
2
+ import { HTTPStatus, ACError, ValidationErrorCode } from "@aeriajs/types";
2
3
  import { useSecurity } from "@aeriajs/security";
3
- import { left, right, isLeft, unwrapEither, unsafe } from "@aeriajs/common";
4
+ import { isLeft, unwrapEither, unsafe, endpointErrorSchema } from "@aeriajs/common";
4
5
  import { traverseDocument, normalizeProjection, prepareInsert } from "../../collection/index.mjs";
6
+ export const insertErrorSchema = endpointErrorSchema({
7
+ httpStatus: [
8
+ HTTPStatus.UnprocessableContent,
9
+ HTTPStatus.NotFound
10
+ ],
11
+ code: [
12
+ ACError.InsecureOperator,
13
+ ACError.OwnershipError,
14
+ ACError.ResourceNotFound,
15
+ ACError.TargetImmutable,
16
+ ValidationErrorCode.EmptyTarget,
17
+ ValidationErrorCode.InvalidProperties,
18
+ ValidationErrorCode.MissingProperties
19
+ ]
20
+ });
5
21
  export const insert = async (payload, context, options) => {
6
22
  const security = useSecurity(context);
7
23
  const query = !options?.bypassSecurity ? unsafe(await security.beforeWrite(payload)) : payload;
@@ -15,46 +31,62 @@ export const insert = async (payload, context, options) => {
15
31
  });
16
32
  if (isLeft(whatEither)) {
17
33
  const error = unwrapEither(whatEither);
18
- return left(error);
34
+ if (typeof error === "string") {
35
+ return context.error(HTTPStatus.UnprocessableContent, {
36
+ code: error
37
+ });
38
+ }
39
+ return context.error(HTTPStatus.UnprocessableContent, {
40
+ code: error.code,
41
+ details: error.errors
42
+ });
19
43
  }
20
44
  const what = unwrapEither(whatEither);
21
45
  const docId = "_id" in what ? what._id : null;
22
- const readyWhat = prepareInsert(what, context.description);
46
+ const content = prepareInsert(what, context.description);
23
47
  const projection = payload.project ? normalizeProjection(payload.project, context.description) : {};
24
48
  let newId = docId;
25
49
  if (!newId) {
26
50
  const now = /* @__PURE__ */ new Date();
27
- Object.assign(readyWhat, {
51
+ Object.assign(content, {
28
52
  created_at: now,
29
53
  updated_at: now
30
54
  });
31
- newId = (await context.collection.model.insertOne(readyWhat)).insertedId;
55
+ newId = (await context.collection.model.insertOne(content)).insertedId;
32
56
  } else {
33
- readyWhat.$set ??= {};
34
- readyWhat.$set.updated_at = /* @__PURE__ */ new Date();
57
+ content.$set ??= {};
58
+ content.$set.updated_at = /* @__PURE__ */ new Date();
35
59
  await context.collection.model.updateOne({
36
60
  _id: docId
37
- }, readyWhat);
61
+ }, content);
38
62
  }
63
+ let doc;
39
64
  if (context.collection.originalFunctions.get) {
40
- const document2 = await context.collection.originalFunctions.get({
65
+ doc = await context.collection.originalFunctions.get({
41
66
  filters: {
42
67
  _id: newId
43
68
  }
44
- }, context, {
69
+ }, Object.assign({
70
+ inherited: true
71
+ }, context), {
45
72
  bypassSecurity: true
46
73
  });
47
- return right(document2);
74
+ } else {
75
+ doc = await context.collection.model.findOne({
76
+ _id: newId
77
+ }, {
78
+ projection
79
+ });
48
80
  }
49
- const document = await context.collection.model.findOne({
50
- _id: newId
51
- }, {
52
- projection
53
- });
54
- const result = unsafe(await traverseDocument(document, context.description, {
81
+ if (!doc) {
82
+ return context.error(HTTPStatus.NotFound, {
83
+ code: ACError.ResourceNotFound
84
+ });
85
+ }
86
+ const result = unsafe(await traverseDocument(doc, context.description, {
55
87
  getters: true,
56
88
  fromProperties: true,
57
89
  recurseReferences: true
58
90
  }));
59
- return right(result);
91
+ return result;
60
92
  };
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.remove = void 0;
4
+ const types_1 = require("@aeriajs/types");
4
5
  const common_1 = require("@aeriajs/common");
5
6
  const index_js_1 = require("../../collection/index.js");
6
7
  const remove = async (payload, context) => {
7
8
  if (!payload.filters._id) {
8
- return (0, common_1.left)({
9
- message: 'you must pass an _id as filter',
9
+ return context.error(types_1.HTTPStatus.NotFound, {
10
+ code: types_1.ACError.ResourceNotFound,
10
11
  });
11
12
  }
12
13
  const filters = (0, common_1.unsafe)(await (0, index_js_1.traverseDocument)(payload.filters, context.description, {
@@ -14,8 +15,8 @@ const remove = async (payload, context) => {
14
15
  }));
15
16
  const target = await context.collection.model.findOne(filters);
16
17
  if (!target) {
17
- return (0, common_1.left)({
18
- message: 'target not found',
18
+ return context.error(types_1.HTTPStatus.NotFound, {
19
+ code: types_1.ACError.ResourceNotFound,
19
20
  });
20
21
  }
21
22
  await (0, index_js_1.cascadingRemove)(target, context);
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
- import { left, unsafe } from "@aeriajs/common";
2
+ import { HTTPStatus, ACError } from "@aeriajs/types";
3
+ import { unsafe } from "@aeriajs/common";
3
4
  import { traverseDocument, cascadingRemove } from "../../collection/index.mjs";
4
5
  export const remove = async (payload, context) => {
5
6
  if (!payload.filters._id) {
6
- return left({
7
- message: "you must pass an _id as filter"
7
+ return context.error(HTTPStatus.NotFound, {
8
+ code: ACError.ResourceNotFound
8
9
  });
9
10
  }
10
11
  const filters = unsafe(await traverseDocument(payload.filters, context.description, {
@@ -12,8 +13,8 @@ export const remove = async (payload, context) => {
12
13
  }));
13
14
  const target = await context.collection.model.findOne(filters);
14
15
  if (!target) {
15
- return left({
16
- message: "target not found"
16
+ return context.error(HTTPStatus.NotFound, {
17
+ code: ACError.ResourceNotFound
17
18
  });
18
19
  }
19
20
  await cascadingRemove(target, context);
package/dist/use.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const createAeria: () => Promise<import("@aeriajs/types").RouteContext<null> & import("@aeriajs/types").CollectionContext<any, any>>;
1
+ export declare const createAeria: () => Promise<import("@aeriajs/types").RouteContext<null> & import("@aeriajs/types").CollectionContext<import("@aeriajs/types").Description, any>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeriajs/core",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -41,13 +41,13 @@
41
41
  "mongodb-memory-server": "^9.2.0"
42
42
  },
43
43
  "peerDependencies": {
44
- "@aeriajs/builtins": "^0.0.87",
45
- "@aeriajs/common": "^0.0.53",
46
- "@aeriajs/entrypoint": "^0.0.53",
47
- "@aeriajs/http": "^0.0.61",
48
- "@aeriajs/security": "^0.0.87",
49
- "@aeriajs/types": "^0.0.50",
50
- "@aeriajs/validation": "^0.0.56"
44
+ "@aeriajs/builtins": "^0.0.89",
45
+ "@aeriajs/common": "^0.0.55",
46
+ "@aeriajs/entrypoint": "^0.0.55",
47
+ "@aeriajs/http": "^0.0.63",
48
+ "@aeriajs/security": "^0.0.89",
49
+ "@aeriajs/types": "^0.0.52",
50
+ "@aeriajs/validation": "^0.0.58"
51
51
  },
52
52
  "dependencies": {
53
53
  "mongodb": "^6.5.0",
@@ -1,4 +0,0 @@
1
- import type { Description } from '@aeriajs/types';
2
- export declare const normalizeProjection: <TDescription extends Pick<Description, "properties">, TProjectedProperties extends (keyof TDescription["properties"])[]>(properties: TProjectedProperties, description: TDescription) => {} | null;
3
- export declare const fill: <TDocument extends OptionalId<any>>(item: TDocument & Record<string, any>, description: Pick<Description, 'properties' | 'freshItem'>) => Record<string, any> & TDocument;
4
- export declare const prepareInsert: (payload: any, description: Pick<Description, 'properties' | 'form' | 'writable' | 'owned' | 'defaults'>) => Record<string, any>;
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prepareInsert = exports.fill = exports.normalizeProjection = void 0;
4
- const common_1 = require("@aeriajs/common");
5
- const normalizeProjection = (properties, description) => {
6
- const target = Array.from(properties);
7
- if (target.length === 0) {
8
- target.push(...Object.keys(description.properties));
9
- }
10
- const projection = target.reduce((a, key) => {
11
- if (key !== '_id' && description.properties[key].hidden) {
12
- return a;
13
- }
14
- return {
15
- ...a,
16
- [key]: 1,
17
- };
18
- }, {});
19
- return Object.keys(projection).length === 0
20
- ? null
21
- : projection;
22
- };
23
- exports.normalizeProjection = normalizeProjection;
24
- const fill = (item, description) => {
25
- const itemCopy = Object.assign({}, item);
26
- for (const key in itemCopy) {
27
- if (itemCopy[key] === null) {
28
- delete itemCopy[key];
29
- }
30
- }
31
- return Object.assign((0, common_1.freshItem)(description), itemCopy);
32
- };
33
- exports.fill = fill;
34
- const prepareInsert = (payload, description) => {
35
- const rest = Object.assign({}, payload);
36
- const docId = payload._id;
37
- delete rest._id;
38
- delete rest.created_at;
39
- delete rest.updated_at;
40
- const forbidden = (key) => {
41
- return description.properties[key].readOnly
42
- || (description.writable && !description.writable.includes(key));
43
- };
44
- const prepareUpdate = () => Object.entries(rest).reduce((a, [key, value]) => {
45
- // it's a mongodb operator
46
- if (key[0] === '$') {
47
- // it's not possible to use mongodb operators when user specifies
48
- // writable properties nor when it is a creation operation
49
- if (!description.writable && docId) {
50
- a[key] = value;
51
- }
52
- return a;
53
- }
54
- if (forbidden(key)) {
55
- return a;
56
- }
57
- if (value === null || value === undefined) {
58
- a.$unset[key] = 1;
59
- return a;
60
- }
61
- a.$set[key] = value;
62
- return a;
63
- }, {
64
- $set: description.defaults || {},
65
- $unset: {},
66
- });
67
- const prepareCreate = () => Object.entries(rest).reduce((a, [key, value]) => {
68
- if (forbidden(key) || [
69
- undefined,
70
- null,
71
- ].includes(value)) {
72
- return a;
73
- }
74
- return {
75
- ...a,
76
- [key]: value,
77
- };
78
- }, description.defaults || {});
79
- const what = docId
80
- ? prepareUpdate()
81
- : prepareCreate();
82
- Object.keys(what).forEach((k) => {
83
- if (typeof what[k] === 'object' && JSON.stringify(what) === '{}') {
84
- delete what[k];
85
- }
86
- });
87
- return what;
88
- };
89
- exports.prepareInsert = prepareInsert;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- import { freshItem } from "@aeriajs/common";
3
- export const normalizeProjection = (properties, description) => {
4
- const target = Array.from(properties);
5
- if (target.length === 0) {
6
- target.push(...Object.keys(description.properties));
7
- }
8
- const projection = target.reduce((a, key) => {
9
- if (key !== "_id" && description.properties[key].hidden) {
10
- return a;
11
- }
12
- return {
13
- ...a,
14
- [key]: 1
15
- };
16
- }, {});
17
- return Object.keys(projection).length === 0 ? null : projection;
18
- };
19
- export const fill = (item, description) => {
20
- const itemCopy = Object.assign({}, item);
21
- for (const key in itemCopy) {
22
- if (itemCopy[key] === null) {
23
- delete itemCopy[key];
24
- }
25
- }
26
- return Object.assign(freshItem(description), itemCopy);
27
- };
28
- export const prepareInsert = (payload, description) => {
29
- const rest = Object.assign({}, payload);
30
- const docId = payload._id;
31
- delete rest._id;
32
- delete rest.created_at;
33
- delete rest.updated_at;
34
- const forbidden = (key) => {
35
- return description.properties[key].readOnly || description.writable && !description.writable.includes(key);
36
- };
37
- const prepareUpdate = () => Object.entries(rest).reduce((a, [key, value]) => {
38
- if (key[0] === "$") {
39
- if (!description.writable && docId) {
40
- a[key] = value;
41
- }
42
- return a;
43
- }
44
- if (forbidden(key)) {
45
- return a;
46
- }
47
- if (value === null || value === void 0) {
48
- a.$unset[key] = 1;
49
- return a;
50
- }
51
- a.$set[key] = value;
52
- return a;
53
- }, {
54
- $set: description.defaults || {},
55
- $unset: {}
56
- });
57
- const prepareCreate = () => Object.entries(rest).reduce((a, [key, value]) => {
58
- if (forbidden(key) || [
59
- void 0,
60
- null
61
- ].includes(value)) {
62
- return a;
63
- }
64
- return {
65
- ...a,
66
- [key]: value
67
- };
68
- }, description.defaults || {});
69
- const what = docId ? prepareUpdate() : prepareCreate();
70
- Object.keys(what).forEach((k) => {
71
- if (typeof what[k] === "object" && JSON.stringify(what) === "{}") {
72
- delete what[k];
73
- }
74
- });
75
- return what;
76
- };