@akanjs/document 0.9.48 → 0.9.49

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.
@@ -23,8 +23,8 @@ module.exports = __toCommonJS(database_exports);
23
23
  var import_base = require("@akanjs/base");
24
24
  var import_common = require("@akanjs/common");
25
25
  var import_constant = require("@akanjs/constant");
26
- var import_nest = require("@akanjs/nest");
27
26
  var import_dataLoader = require("./dataLoader");
27
+ var import_filterMeta = require("./filterMeta");
28
28
  var import_schema = require("./schema");
29
29
  class CacheDatabase {
30
30
  constructor(refName, redis) {
@@ -85,20 +85,21 @@ class SearchDatabase {
85
85
  }
86
86
  }
87
87
  class DatabaseModelStorage {
88
- __ModelType__ = "DatabaseModelStorage";
89
88
  }
90
89
  const databaseModelOf = (database, model, redis, meili) => {
91
90
  const [modelName, className] = [database.refName, (0, import_common.capitalize)(database.refName)];
92
91
  const insightFieldMetas = (0, import_constant.getFieldMetas)(database.Insight);
93
92
  const accumulator = Object.fromEntries(insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.accumulate]));
94
- const defaultInsight = Object.fromEntries(insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.default]));
93
+ const defaultInsight = Object.fromEntries(
94
+ insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.default])
95
+ );
95
96
  const makeSafeQuery = (query) => ({ removedAt: { $exists: false }, ...query ?? {} });
96
97
  const makeSafeMatchStage = (query) => ({
97
98
  $match: { removedAt: { $exists: false }, ...(0, import_schema.convertAggregateMatch)(query) }
98
99
  });
99
100
  const getListQuery = (query, queryOption) => {
100
101
  const find = makeSafeQuery(query);
101
- const sort = (0, import_constant.getFilterSort)(database.Filter, queryOption?.sort ?? "latest");
102
+ const sort = (0, import_filterMeta.getFilterSort)(database.Filter, queryOption?.sort ?? "latest");
102
103
  const skip = queryOption?.skip ?? 0;
103
104
  const limit = queryOption?.limit === null ? import_constant.DEFAULT_PAGE_SIZE : queryOption?.limit ?? 0;
104
105
  const select = queryOption?.select;
@@ -107,14 +108,14 @@ const databaseModelOf = (database, model, redis, meili) => {
107
108
  };
108
109
  const getFindQuery = (query, queryOption) => {
109
110
  const find = makeSafeQuery(query);
110
- const sort = (0, import_constant.getFilterSort)(database.Filter, queryOption?.sort ?? "latest");
111
+ const sort = (0, import_filterMeta.getFilterSort)(database.Filter, queryOption?.sort ?? "latest");
111
112
  const skip = queryOption?.skip ?? 0;
112
113
  const select = queryOption?.select;
113
114
  const sample = queryOption?.sample ?? false;
114
115
  return { find, sort, skip, select, sample };
115
116
  };
116
117
  const getSearchSort = (sortKey) => {
117
- const sort = (0, import_constant.getFilterSort)(database.Filter, sortKey ?? "latest");
118
+ const sort = (0, import_filterMeta.getFilterSort)(database.Filter, sortKey ?? "latest");
118
119
  return Object.entries(sort).map(([key, value]) => `${key}:${value === 1 ? "asc" : "desc"}`);
119
120
  };
120
121
  const loader = (0, import_dataLoader.createLoader)(model);
@@ -232,15 +233,15 @@ const databaseModelOf = (database, model, redis, meili) => {
232
233
  const getQueryDataFromKey = (queryKey, args) => {
233
234
  const lastArg = args.at(-1);
234
235
  const hasQueryOption = lastArg && typeof lastArg === "object" && (typeof lastArg.select === "object" || typeof lastArg.skip === "number" || typeof lastArg.limit === "number" || typeof lastArg.sort === "string");
235
- const queryFn = (0, import_constant.getFilterQuery)(database.Filter, queryKey);
236
+ const queryFn = (0, import_filterMeta.getFilterQuery)(database.Filter, queryKey);
236
237
  const query = queryFn(...hasQueryOption ? args.slice(0, -1) : args);
237
238
  const queryOption = hasQueryOption ? lastArg : {};
238
239
  return { query, queryOption };
239
240
  };
240
- const filterKeyMetaMap = (0, import_constant.getFilterKeyMetaMapOnPrototype)(database.Filter.prototype);
241
+ const filterKeyMetaMap = (0, import_filterMeta.getFilterKeyMetaMapOnPrototype)(database.Filter.prototype);
241
242
  const queryKeys = [...filterKeyMetaMap.keys()];
242
243
  queryKeys.forEach((queryKey) => {
243
- const queryFn = (0, import_constant.getFilterQuery)(database.Filter, queryKey);
244
+ const queryFn = (0, import_filterMeta.getFilterQuery)(database.Filter, queryKey);
244
245
  DatabaseModel.prototype[`list${(0, import_common.capitalize)(queryKey)}`] = async function(...args) {
245
246
  const { query, queryOption } = getQueryDataFromKey(queryKey, args);
246
247
  return this.__list(query, queryOption);
@@ -277,6 +278,9 @@ const databaseModelOf = (database, model, redis, meili) => {
277
278
  const query = queryFn(...args);
278
279
  return this.__insight(query);
279
280
  };
281
+ DatabaseModel.prototype[`query${(0, import_common.capitalize)(queryKey)}`] = async function(...args) {
282
+ return queryFn(...args);
283
+ };
280
284
  });
281
285
  const loaderMetas = (0, import_dataLoader.getLoaderMetas)(database.Model);
282
286
  loaderMetas.forEach((loaderMeta) => {
@@ -286,15 +290,6 @@ const databaseModelOf = (database, model, redis, meili) => {
286
290
  Object.getOwnPropertyNames(database.Model.prototype).forEach((key) => {
287
291
  DatabaseModel.prototype[key] = database.Model.prototype[key];
288
292
  });
289
- const createDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `create${className}`);
290
- if (createDescriptor)
291
- (0, import_nest.Transaction)()(DatabaseModel.prototype, `create${className}`, createDescriptor);
292
- const updateDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `update${className}`);
293
- if (updateDescriptor)
294
- (0, import_nest.Transaction)()(DatabaseModel.prototype, `update${className}`, updateDescriptor);
295
- const removeDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `remove${className}`);
296
- if (removeDescriptor)
297
- (0, import_nest.Transaction)()(DatabaseModel.prototype, `remove${className}`, removeDescriptor);
298
293
  Reflect.defineMetadata(database.refName, DatabaseModel, DatabaseModelStorage.prototype);
299
294
  return new DatabaseModel();
300
295
  };
@@ -17,65 +17,13 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
  var dbDecorators_exports = {};
19
19
  __export(dbDecorators_exports, {
20
- Database: () => Database,
21
- DocumentDatabaseStorage: () => DocumentDatabaseStorage,
22
- InputDatabaseStorage: () => InputDatabaseStorage,
23
- MiddlewareDatabaseStorage: () => MiddlewareDatabaseStorage,
24
- ModelDatabaseStorage: () => ModelDatabaseStorage,
25
20
  beyond: () => beyond,
26
21
  by: () => by,
27
- dbOf: () => dbOf,
28
- getAllDatabaseModelNames: () => getAllDatabaseModelNames,
29
22
  into: () => into
30
23
  });
31
24
  module.exports = __toCommonJS(dbDecorators_exports);
32
25
  var import_constant = require("@akanjs/constant");
33
- const dbOf = (refName, Input, Doc, Model2, Middleware, Obj, Insight, Filter) => {
34
- return { refName, Input, Doc, Model: Model2, Middleware, Obj, Insight, Filter };
35
- };
36
- class InputDatabaseStorage {
37
- }
38
- class DocumentDatabaseStorage {
39
- }
40
- class ModelDatabaseStorage {
41
- }
42
- class MiddlewareDatabaseStorage {
43
- }
44
- const getAllDatabaseModelNames = () => {
45
- const modelNames = Reflect.getMetadataKeys(ModelDatabaseStorage.prototype) ?? [];
46
- return modelNames;
47
- };
48
- const Database = {
49
- Input: (returns) => {
50
- return function(target) {
51
- const modelRef = returns();
52
- const classMeta = (0, import_constant.getClassMeta)(modelRef);
53
- Reflect.defineMetadata(classMeta.refName, target, InputDatabaseStorage.prototype);
54
- };
55
- },
56
- Document: (returns) => {
57
- return function(target) {
58
- const modelRef = returns();
59
- const classMeta = (0, import_constant.getClassMeta)(modelRef);
60
- Reflect.defineMetadata(classMeta.refName, target, DocumentDatabaseStorage.prototype);
61
- };
62
- },
63
- Model: (returns) => {
64
- return function(target) {
65
- const modelRef = returns();
66
- const classMeta = (0, import_constant.getClassMeta)(modelRef);
67
- Reflect.defineMetadata(classMeta.refName, target, ModelDatabaseStorage.prototype);
68
- };
69
- },
70
- Middleware: (returns) => {
71
- return function(target) {
72
- const modelRef = returns();
73
- const classMeta = (0, import_constant.getClassMeta)(modelRef);
74
- Reflect.defineMetadata(classMeta.refName, target, MiddlewareDatabaseStorage.prototype);
75
- };
76
- }
77
- };
78
- const Model = (docRef, cnst, ...addMdls) => {
26
+ const Model = (docRef, filterRef, cnst, ...addMdls) => {
79
27
  class DefaultModel {
80
28
  }
81
29
  return DefaultModel;
@@ -101,14 +49,7 @@ const beyond = (model, doc) => {
101
49
  };
102
50
  // Annotate the CommonJS export names for ESM import in node:
103
51
  0 && (module.exports = {
104
- Database,
105
- DocumentDatabaseStorage,
106
- InputDatabaseStorage,
107
- MiddlewareDatabaseStorage,
108
- ModelDatabaseStorage,
109
52
  beyond,
110
53
  by,
111
- dbOf,
112
- getAllDatabaseModelNames,
113
54
  into
114
55
  });
@@ -0,0 +1,105 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var documentInfo_exports = {};
19
+ __export(documentInfo_exports, {
20
+ dbOf: () => dbOf,
21
+ documentInfo: () => documentInfo,
22
+ scalarDbOf: () => scalarDbOf
23
+ });
24
+ module.exports = __toCommonJS(documentInfo_exports);
25
+ const documentInfo = {
26
+ database: /* @__PURE__ */ new Map(),
27
+ scalar: /* @__PURE__ */ new Map(),
28
+ modelSets: {
29
+ input: /* @__PURE__ */ new Set(),
30
+ doc: /* @__PURE__ */ new Set(),
31
+ model: /* @__PURE__ */ new Set(),
32
+ filter: /* @__PURE__ */ new Set(),
33
+ middleware: /* @__PURE__ */ new Set(),
34
+ scalar: /* @__PURE__ */ new Set()
35
+ },
36
+ modelRefNameMap: /* @__PURE__ */ new Map(),
37
+ getRefName(modelRef, { allowEmpty } = {}) {
38
+ const refName = documentInfo.modelRefNameMap.get(modelRef);
39
+ if (!refName && !allowEmpty)
40
+ throw new Error(`No ref name for modelRef: ${modelRef}`);
41
+ return refName;
42
+ },
43
+ isInput(modelRef) {
44
+ return documentInfo.modelSets.input.has(modelRef);
45
+ },
46
+ isDoc(modelRef) {
47
+ return documentInfo.modelSets.doc.has(modelRef);
48
+ },
49
+ isModel(modelRef) {
50
+ return documentInfo.modelSets.model.has(modelRef);
51
+ },
52
+ isMiddleware(modelRef) {
53
+ return documentInfo.modelSets.middleware.has(modelRef);
54
+ },
55
+ isScalar(modelRef) {
56
+ return documentInfo.modelSets.scalar.has(modelRef);
57
+ },
58
+ setDatabase(refName, { Input, Doc, Model, Middleware, Filter }) {
59
+ if (!documentInfo.database.has(refName))
60
+ documentInfo.database.set(refName, {
61
+ input: Input,
62
+ doc: Doc,
63
+ model: Model,
64
+ middleware: Middleware,
65
+ filter: Filter
66
+ });
67
+ [Input, Doc, Model, Middleware].forEach((modelRef) => {
68
+ documentInfo.modelRefNameMap.set(modelRef, refName);
69
+ });
70
+ },
71
+ getDatabase(refName, { allowEmpty } = {}) {
72
+ const info = documentInfo.database.get(refName);
73
+ if (!info && !allowEmpty)
74
+ throw new Error(`No database document model info for ${refName}`);
75
+ return info;
76
+ },
77
+ setScalar(refName, Model) {
78
+ if (documentInfo.scalar.has(refName))
79
+ return;
80
+ documentInfo.scalar.set(refName, Model);
81
+ documentInfo.modelRefNameMap.set(Model, refName);
82
+ },
83
+ getScalar(refName, { allowEmpty } = {}) {
84
+ const model = documentInfo.scalar.get(refName);
85
+ if (!model && !allowEmpty)
86
+ throw new Error(`No scalar model for ${refName}`);
87
+ return model;
88
+ }
89
+ };
90
+ const dbOf = (refName, Input, Doc, Model, Middleware, Obj, Insight, Filter) => {
91
+ const dbInfo = { refName, Input, Doc, Model, Middleware, Obj, Insight, Filter };
92
+ documentInfo.setDatabase(refName, dbInfo);
93
+ return dbInfo;
94
+ };
95
+ const scalarDbOf = (refName, Model) => {
96
+ const scalarInfo = { refName, Model };
97
+ documentInfo.setScalar(refName, Model);
98
+ return scalarInfo;
99
+ };
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ dbOf,
103
+ documentInfo,
104
+ scalarDbOf
105
+ });
@@ -0,0 +1,182 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from2, except, desc) => {
10
+ if (from2 && typeof from2 === "object" || typeof from2 === "function") {
11
+ for (let key of __getOwnPropNames(from2))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from2[key], enumerable: !(desc = __getOwnPropDesc(from2, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var filterMeta_exports = {};
19
+ __export(filterMeta_exports, {
20
+ FilterInfo: () => FilterInfo,
21
+ filter: () => filter,
22
+ from: () => from,
23
+ getFilterArgMetas: () => getFilterArgMetas,
24
+ getFilterKeyMetaMapOnPrototype: () => getFilterKeyMetaMapOnPrototype,
25
+ getFilterMeta: () => getFilterMeta,
26
+ getFilterQuery: () => getFilterQuery,
27
+ getFilterQueryMap: () => getFilterQueryMap,
28
+ getFilterSort: () => getFilterSort,
29
+ getFilterSortMap: () => getFilterSortMap,
30
+ isFilterModel: () => isFilterModel,
31
+ setFilterArgMetasOnPrototype: () => setFilterArgMetasOnPrototype,
32
+ setFilterKeyMetaMapOnPrototype: () => setFilterKeyMetaMapOnPrototype,
33
+ setFilterMeta: () => setFilterMeta
34
+ });
35
+ module.exports = __toCommonJS(filterMeta_exports);
36
+ var import_base = require("@akanjs/base");
37
+ var import_common = require("@akanjs/common");
38
+ var import_constant = require("@akanjs/constant");
39
+ const isFilterModel = (filterRef) => {
40
+ return Reflect.getMetadata("filter", filterRef.prototype) !== void 0;
41
+ };
42
+ const getFilterMeta = (filterRef) => {
43
+ const filterMeta = Reflect.getMetadata("filter", filterRef.prototype);
44
+ if (!filterMeta)
45
+ throw new Error("filterMeta is not defined");
46
+ return filterMeta;
47
+ };
48
+ const setFilterMeta = (filterRef, filterMeta) => {
49
+ const existingFilterMeta = Reflect.getMetadata("filter", filterRef.prototype);
50
+ if (existingFilterMeta)
51
+ Object.assign(existingFilterMeta, { ...filterMeta, sort: { ...existingFilterMeta.sort, ...filterMeta.sort } });
52
+ else
53
+ Reflect.defineMetadata("filter", filterMeta, filterRef.prototype);
54
+ };
55
+ const getFilterKeyMetaMapOnPrototype = (prototype) => {
56
+ const metadataMap = Reflect.getMetadata("filterKey", prototype) ?? /* @__PURE__ */ new Map();
57
+ return new Map(metadataMap);
58
+ };
59
+ const setFilterKeyMetaMapOnPrototype = (prototype, metadataMap) => {
60
+ Reflect.defineMetadata("filterKey", new Map(metadataMap), prototype);
61
+ };
62
+ const getFilterArgMetasOnPrototype = (prototype, key) => {
63
+ const filterArgMetas = Reflect.getMetadata("filterArg", prototype, key) ?? [];
64
+ return filterArgMetas;
65
+ };
66
+ const setFilterArgMetasOnPrototype = (prototype, key, filterArgMetas) => {
67
+ Reflect.defineMetadata("filterArg", filterArgMetas, prototype, key);
68
+ };
69
+ const getFilterArgMetas = (filterRef, key) => {
70
+ const filterArgMetas = getFilterArgMetasOnPrototype(filterRef.prototype, key);
71
+ return filterArgMetas;
72
+ };
73
+ const getFilterQuery = (filterRef, key) => {
74
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
75
+ const filterKeyMeta = filterKeyMetaMap.get(key);
76
+ if (!filterKeyMeta?.descriptor.value)
77
+ throw new Error(`filterKeyMeta is not defined for key: ${key}`);
78
+ return filterKeyMeta.descriptor.value;
79
+ };
80
+ const getFilterQueryMap = (filterRef) => {
81
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
82
+ return filterKeyMetaMap;
83
+ };
84
+ const getFilterSort = (filterRef, key) => {
85
+ const filterMeta = getFilterMeta(filterRef);
86
+ const sort = filterMeta.sort[key];
87
+ return sort;
88
+ };
89
+ const getFilterSortMap = (filterRef) => {
90
+ const filterMeta = getFilterMeta(filterRef);
91
+ return filterMeta.sort;
92
+ };
93
+ const from = (modelRef, filterSort, ...libFilterRefs) => {
94
+ const fieldMetaMap = (0, import_constant.getFieldMetaMap)(modelRef);
95
+ const statusFieldMeta = fieldMetaMap.get("status");
96
+ if (!statusFieldMeta)
97
+ throw new Error(`No status field meta fount in ${modelRef.name}`);
98
+ class Base {
99
+ }
100
+ const querySort = filterSort(filter);
101
+ Object.assign(Base.prototype, { latest: { createdAt: -1 }, oldest: { createdAt: 1 }, ...querySort.sort });
102
+ Object.entries({
103
+ byStatuses: filter().opt("statuses", [statusFieldMeta.enum]).query((statuses) => statuses?.length ? { status: { $in: statuses } } : {}),
104
+ any: filter().query(() => ({ removedAt: { $exists: false } })),
105
+ ...querySort.query
106
+ }).forEach(([key, filterInfo]) => {
107
+ filterInfo.applyFilterMeta(Base, key);
108
+ });
109
+ setFilterMeta(Base, {
110
+ refName: "Base",
111
+ sort: Object.assign({ latest: { createdAt: -1 }, oldest: { createdAt: 1 } }, querySort.sort)
112
+ });
113
+ (0, import_common.applyMixins)(Base, libFilterRefs);
114
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(Base.prototype);
115
+ libFilterRefs.forEach((libFilterRef) => {
116
+ const libFilterKeyMetaMap = getFilterKeyMetaMapOnPrototype(libFilterRef.prototype);
117
+ libFilterKeyMetaMap.forEach((value, key) => {
118
+ const libFilterArgMetas = getFilterArgMetas(libFilterRef, key);
119
+ filterKeyMetaMap.set(key, value);
120
+ setFilterArgMetasOnPrototype(Base.prototype, key, libFilterArgMetas);
121
+ });
122
+ });
123
+ return Base;
124
+ };
125
+ class FilterInfo {
126
+ args;
127
+ queryFn = null;
128
+ constructor() {
129
+ this.args = [];
130
+ }
131
+ arg(name, argRef, option) {
132
+ if (this.queryFn)
133
+ throw new Error("Query function is already set");
134
+ else if (this.args.at(-1)?.option?.nullable)
135
+ throw new Error("Last argument is nullable");
136
+ this.args.push({ name, argRef, option });
137
+ return this;
138
+ }
139
+ opt(name, argRef, option) {
140
+ if (this.queryFn)
141
+ throw new Error("Query function is already set");
142
+ this.args.push({ name, argRef, option: { ...option, nullable: true } });
143
+ return this;
144
+ }
145
+ query(query) {
146
+ if (this.queryFn)
147
+ throw new Error("Query function is already set");
148
+ this.queryFn = query;
149
+ return this;
150
+ }
151
+ applyFilterMeta(filterRef, key) {
152
+ const metadata = { key, type: "mongo", descriptor: { value: this.queryFn } };
153
+ const metadataMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
154
+ metadataMap.set(key, metadata);
155
+ filterRef.prototype[key] = this.queryFn;
156
+ setFilterKeyMetaMapOnPrototype(filterRef.prototype, metadataMap);
157
+ const filterArgMetas = this.args.map((argInfo) => {
158
+ const [modelRef, arrDepth] = (0, import_base.getNonArrayModel)(argInfo.argRef);
159
+ const [opt, optArrDepth] = (0, import_base.getNonArrayModel)(argInfo.option ?? {});
160
+ return { name: argInfo.name, ...opt, modelRef, arrDepth, isArray: arrDepth > 0, optArrDepth };
161
+ });
162
+ setFilterArgMetasOnPrototype(filterRef.prototype, key, filterArgMetas);
163
+ }
164
+ }
165
+ const filter = () => new FilterInfo();
166
+ // Annotate the CommonJS export names for ESM import in node:
167
+ 0 && (module.exports = {
168
+ FilterInfo,
169
+ filter,
170
+ from,
171
+ getFilterArgMetas,
172
+ getFilterKeyMetaMapOnPrototype,
173
+ getFilterMeta,
174
+ getFilterQuery,
175
+ getFilterQueryMap,
176
+ getFilterSort,
177
+ getFilterSortMap,
178
+ isFilterModel,
179
+ setFilterArgMetasOnPrototype,
180
+ setFilterKeyMetaMapOnPrototype,
181
+ setFilterMeta
182
+ });
package/cjs/src/index.js CHANGED
@@ -19,11 +19,15 @@ __reExport(src_exports, require("./schema"), module.exports);
19
19
  __reExport(src_exports, require("./types"), module.exports);
20
20
  __reExport(src_exports, require("./database"), module.exports);
21
21
  __reExport(src_exports, require("./dataLoader"), module.exports);
22
+ __reExport(src_exports, require("./documentInfo"), module.exports);
23
+ __reExport(src_exports, require("./filterMeta"), module.exports);
22
24
  // Annotate the CommonJS export names for ESM import in node:
23
25
  0 && (module.exports = {
24
26
  ...require("./dbDecorators"),
25
27
  ...require("./schema"),
26
28
  ...require("./types"),
27
29
  ...require("./database"),
28
- ...require("./dataLoader")
30
+ ...require("./dataLoader"),
31
+ ...require("./documentInfo"),
32
+ ...require("./filterMeta")
29
33
  });
@@ -1,14 +1,8 @@
1
1
  import { dayjs } from "@akanjs/base";
2
2
  import { capitalize, Logger, lowerlize } from "@akanjs/common";
3
- import {
4
- DEFAULT_PAGE_SIZE,
5
- getFieldMetas,
6
- getFilterKeyMetaMapOnPrototype,
7
- getFilterQuery,
8
- getFilterSort
9
- } from "@akanjs/constant";
10
- import { Transaction } from "@akanjs/nest";
3
+ import { DEFAULT_PAGE_SIZE, getFieldMetas } from "@akanjs/constant";
11
4
  import { createArrayLoader, createLoader, createQueryLoader, getLoaderMetas } from "./dataLoader";
5
+ import { getFilterKeyMetaMapOnPrototype, getFilterQuery, getFilterSort } from "./filterMeta";
12
6
  import { convertAggregateMatch } from "./schema";
13
7
  class CacheDatabase {
14
8
  constructor(refName, redis) {
@@ -69,13 +63,14 @@ class SearchDatabase {
69
63
  }
70
64
  }
71
65
  class DatabaseModelStorage {
72
- __ModelType__ = "DatabaseModelStorage";
73
66
  }
74
67
  const databaseModelOf = (database, model, redis, meili) => {
75
68
  const [modelName, className] = [database.refName, capitalize(database.refName)];
76
69
  const insightFieldMetas = getFieldMetas(database.Insight);
77
70
  const accumulator = Object.fromEntries(insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.accumulate]));
78
- const defaultInsight = Object.fromEntries(insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.default]));
71
+ const defaultInsight = Object.fromEntries(
72
+ insightFieldMetas.map((fieldMeta) => [fieldMeta.key, fieldMeta.default])
73
+ );
79
74
  const makeSafeQuery = (query) => ({ removedAt: { $exists: false }, ...query ?? {} });
80
75
  const makeSafeMatchStage = (query) => ({
81
76
  $match: { removedAt: { $exists: false }, ...convertAggregateMatch(query) }
@@ -261,6 +256,9 @@ const databaseModelOf = (database, model, redis, meili) => {
261
256
  const query = queryFn(...args);
262
257
  return this.__insight(query);
263
258
  };
259
+ DatabaseModel.prototype[`query${capitalize(queryKey)}`] = async function(...args) {
260
+ return queryFn(...args);
261
+ };
264
262
  });
265
263
  const loaderMetas = getLoaderMetas(database.Model);
266
264
  loaderMetas.forEach((loaderMeta) => {
@@ -270,15 +268,6 @@ const databaseModelOf = (database, model, redis, meili) => {
270
268
  Object.getOwnPropertyNames(database.Model.prototype).forEach((key) => {
271
269
  DatabaseModel.prototype[key] = database.Model.prototype[key];
272
270
  });
273
- const createDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `create${className}`);
274
- if (createDescriptor)
275
- Transaction()(DatabaseModel.prototype, `create${className}`, createDescriptor);
276
- const updateDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `update${className}`);
277
- if (updateDescriptor)
278
- Transaction()(DatabaseModel.prototype, `update${className}`, updateDescriptor);
279
- const removeDescriptor = Object.getOwnPropertyDescriptor(DatabaseModel.prototype, `remove${className}`);
280
- if (removeDescriptor)
281
- Transaction()(DatabaseModel.prototype, `remove${className}`, removeDescriptor);
282
271
  Reflect.defineMetadata(database.refName, DatabaseModel, DatabaseModelStorage.prototype);
283
272
  return new DatabaseModel();
284
273
  };
@@ -1,54 +1,5 @@
1
- import {
2
- getClassMeta,
3
- getFieldMetaMap,
4
- setFieldMetaMap
5
- } from "@akanjs/constant";
6
- const dbOf = (refName, Input, Doc, Model2, Middleware, Obj, Insight, Filter) => {
7
- return { refName, Input, Doc, Model: Model2, Middleware, Obj, Insight, Filter };
8
- };
9
- class InputDatabaseStorage {
10
- }
11
- class DocumentDatabaseStorage {
12
- }
13
- class ModelDatabaseStorage {
14
- }
15
- class MiddlewareDatabaseStorage {
16
- }
17
- const getAllDatabaseModelNames = () => {
18
- const modelNames = Reflect.getMetadataKeys(ModelDatabaseStorage.prototype) ?? [];
19
- return modelNames;
20
- };
21
- const Database = {
22
- Input: (returns) => {
23
- return function(target) {
24
- const modelRef = returns();
25
- const classMeta = getClassMeta(modelRef);
26
- Reflect.defineMetadata(classMeta.refName, target, InputDatabaseStorage.prototype);
27
- };
28
- },
29
- Document: (returns) => {
30
- return function(target) {
31
- const modelRef = returns();
32
- const classMeta = getClassMeta(modelRef);
33
- Reflect.defineMetadata(classMeta.refName, target, DocumentDatabaseStorage.prototype);
34
- };
35
- },
36
- Model: (returns) => {
37
- return function(target) {
38
- const modelRef = returns();
39
- const classMeta = getClassMeta(modelRef);
40
- Reflect.defineMetadata(classMeta.refName, target, ModelDatabaseStorage.prototype);
41
- };
42
- },
43
- Middleware: (returns) => {
44
- return function(target) {
45
- const modelRef = returns();
46
- const classMeta = getClassMeta(modelRef);
47
- Reflect.defineMetadata(classMeta.refName, target, MiddlewareDatabaseStorage.prototype);
48
- };
49
- }
50
- };
51
- const Model = (docRef, cnst, ...addMdls) => {
1
+ import { getFieldMetaMap, setFieldMetaMap } from "@akanjs/constant";
2
+ const Model = (docRef, filterRef, cnst, ...addMdls) => {
52
3
  class DefaultModel {
53
4
  }
54
5
  return DefaultModel;
@@ -73,14 +24,7 @@ const beyond = (model, doc) => {
73
24
  };
74
25
  };
75
26
  export {
76
- Database,
77
- DocumentDatabaseStorage,
78
- InputDatabaseStorage,
79
- MiddlewareDatabaseStorage,
80
- ModelDatabaseStorage,
81
27
  beyond,
82
28
  by,
83
- dbOf,
84
- getAllDatabaseModelNames,
85
29
  into
86
30
  };
@@ -0,0 +1,80 @@
1
+ const documentInfo = {
2
+ database: /* @__PURE__ */ new Map(),
3
+ scalar: /* @__PURE__ */ new Map(),
4
+ modelSets: {
5
+ input: /* @__PURE__ */ new Set(),
6
+ doc: /* @__PURE__ */ new Set(),
7
+ model: /* @__PURE__ */ new Set(),
8
+ filter: /* @__PURE__ */ new Set(),
9
+ middleware: /* @__PURE__ */ new Set(),
10
+ scalar: /* @__PURE__ */ new Set()
11
+ },
12
+ modelRefNameMap: /* @__PURE__ */ new Map(),
13
+ getRefName(modelRef, { allowEmpty } = {}) {
14
+ const refName = documentInfo.modelRefNameMap.get(modelRef);
15
+ if (!refName && !allowEmpty)
16
+ throw new Error(`No ref name for modelRef: ${modelRef}`);
17
+ return refName;
18
+ },
19
+ isInput(modelRef) {
20
+ return documentInfo.modelSets.input.has(modelRef);
21
+ },
22
+ isDoc(modelRef) {
23
+ return documentInfo.modelSets.doc.has(modelRef);
24
+ },
25
+ isModel(modelRef) {
26
+ return documentInfo.modelSets.model.has(modelRef);
27
+ },
28
+ isMiddleware(modelRef) {
29
+ return documentInfo.modelSets.middleware.has(modelRef);
30
+ },
31
+ isScalar(modelRef) {
32
+ return documentInfo.modelSets.scalar.has(modelRef);
33
+ },
34
+ setDatabase(refName, { Input, Doc, Model, Middleware, Filter }) {
35
+ if (!documentInfo.database.has(refName))
36
+ documentInfo.database.set(refName, {
37
+ input: Input,
38
+ doc: Doc,
39
+ model: Model,
40
+ middleware: Middleware,
41
+ filter: Filter
42
+ });
43
+ [Input, Doc, Model, Middleware].forEach((modelRef) => {
44
+ documentInfo.modelRefNameMap.set(modelRef, refName);
45
+ });
46
+ },
47
+ getDatabase(refName, { allowEmpty } = {}) {
48
+ const info = documentInfo.database.get(refName);
49
+ if (!info && !allowEmpty)
50
+ throw new Error(`No database document model info for ${refName}`);
51
+ return info;
52
+ },
53
+ setScalar(refName, Model) {
54
+ if (documentInfo.scalar.has(refName))
55
+ return;
56
+ documentInfo.scalar.set(refName, Model);
57
+ documentInfo.modelRefNameMap.set(Model, refName);
58
+ },
59
+ getScalar(refName, { allowEmpty } = {}) {
60
+ const model = documentInfo.scalar.get(refName);
61
+ if (!model && !allowEmpty)
62
+ throw new Error(`No scalar model for ${refName}`);
63
+ return model;
64
+ }
65
+ };
66
+ const dbOf = (refName, Input, Doc, Model, Middleware, Obj, Insight, Filter) => {
67
+ const dbInfo = { refName, Input, Doc, Model, Middleware, Obj, Insight, Filter };
68
+ documentInfo.setDatabase(refName, dbInfo);
69
+ return dbInfo;
70
+ };
71
+ const scalarDbOf = (refName, Model) => {
72
+ const scalarInfo = { refName, Model };
73
+ documentInfo.setScalar(refName, Model);
74
+ return scalarInfo;
75
+ };
76
+ export {
77
+ dbOf,
78
+ documentInfo,
79
+ scalarDbOf
80
+ };
@@ -0,0 +1,148 @@
1
+ import {
2
+ getNonArrayModel
3
+ } from "@akanjs/base";
4
+ import { applyMixins } from "@akanjs/common";
5
+ import { getFieldMetaMap } from "@akanjs/constant";
6
+ const isFilterModel = (filterRef) => {
7
+ return Reflect.getMetadata("filter", filterRef.prototype) !== void 0;
8
+ };
9
+ const getFilterMeta = (filterRef) => {
10
+ const filterMeta = Reflect.getMetadata("filter", filterRef.prototype);
11
+ if (!filterMeta)
12
+ throw new Error("filterMeta is not defined");
13
+ return filterMeta;
14
+ };
15
+ const setFilterMeta = (filterRef, filterMeta) => {
16
+ const existingFilterMeta = Reflect.getMetadata("filter", filterRef.prototype);
17
+ if (existingFilterMeta)
18
+ Object.assign(existingFilterMeta, { ...filterMeta, sort: { ...existingFilterMeta.sort, ...filterMeta.sort } });
19
+ else
20
+ Reflect.defineMetadata("filter", filterMeta, filterRef.prototype);
21
+ };
22
+ const getFilterKeyMetaMapOnPrototype = (prototype) => {
23
+ const metadataMap = Reflect.getMetadata("filterKey", prototype) ?? /* @__PURE__ */ new Map();
24
+ return new Map(metadataMap);
25
+ };
26
+ const setFilterKeyMetaMapOnPrototype = (prototype, metadataMap) => {
27
+ Reflect.defineMetadata("filterKey", new Map(metadataMap), prototype);
28
+ };
29
+ const getFilterArgMetasOnPrototype = (prototype, key) => {
30
+ const filterArgMetas = Reflect.getMetadata("filterArg", prototype, key) ?? [];
31
+ return filterArgMetas;
32
+ };
33
+ const setFilterArgMetasOnPrototype = (prototype, key, filterArgMetas) => {
34
+ Reflect.defineMetadata("filterArg", filterArgMetas, prototype, key);
35
+ };
36
+ const getFilterArgMetas = (filterRef, key) => {
37
+ const filterArgMetas = getFilterArgMetasOnPrototype(filterRef.prototype, key);
38
+ return filterArgMetas;
39
+ };
40
+ const getFilterQuery = (filterRef, key) => {
41
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
42
+ const filterKeyMeta = filterKeyMetaMap.get(key);
43
+ if (!filterKeyMeta?.descriptor.value)
44
+ throw new Error(`filterKeyMeta is not defined for key: ${key}`);
45
+ return filterKeyMeta.descriptor.value;
46
+ };
47
+ const getFilterQueryMap = (filterRef) => {
48
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
49
+ return filterKeyMetaMap;
50
+ };
51
+ const getFilterSort = (filterRef, key) => {
52
+ const filterMeta = getFilterMeta(filterRef);
53
+ const sort = filterMeta.sort[key];
54
+ return sort;
55
+ };
56
+ const getFilterSortMap = (filterRef) => {
57
+ const filterMeta = getFilterMeta(filterRef);
58
+ return filterMeta.sort;
59
+ };
60
+ const from = (modelRef, filterSort, ...libFilterRefs) => {
61
+ const fieldMetaMap = getFieldMetaMap(modelRef);
62
+ const statusFieldMeta = fieldMetaMap.get("status");
63
+ if (!statusFieldMeta)
64
+ throw new Error(`No status field meta fount in ${modelRef.name}`);
65
+ class Base {
66
+ }
67
+ const querySort = filterSort(filter);
68
+ Object.assign(Base.prototype, { latest: { createdAt: -1 }, oldest: { createdAt: 1 }, ...querySort.sort });
69
+ Object.entries({
70
+ byStatuses: filter().opt("statuses", [statusFieldMeta.enum]).query((statuses) => statuses?.length ? { status: { $in: statuses } } : {}),
71
+ any: filter().query(() => ({ removedAt: { $exists: false } })),
72
+ ...querySort.query
73
+ }).forEach(([key, filterInfo]) => {
74
+ filterInfo.applyFilterMeta(Base, key);
75
+ });
76
+ setFilterMeta(Base, {
77
+ refName: "Base",
78
+ sort: Object.assign({ latest: { createdAt: -1 }, oldest: { createdAt: 1 } }, querySort.sort)
79
+ });
80
+ applyMixins(Base, libFilterRefs);
81
+ const filterKeyMetaMap = getFilterKeyMetaMapOnPrototype(Base.prototype);
82
+ libFilterRefs.forEach((libFilterRef) => {
83
+ const libFilterKeyMetaMap = getFilterKeyMetaMapOnPrototype(libFilterRef.prototype);
84
+ libFilterKeyMetaMap.forEach((value, key) => {
85
+ const libFilterArgMetas = getFilterArgMetas(libFilterRef, key);
86
+ filterKeyMetaMap.set(key, value);
87
+ setFilterArgMetasOnPrototype(Base.prototype, key, libFilterArgMetas);
88
+ });
89
+ });
90
+ return Base;
91
+ };
92
+ class FilterInfo {
93
+ args;
94
+ queryFn = null;
95
+ constructor() {
96
+ this.args = [];
97
+ }
98
+ arg(name, argRef, option) {
99
+ if (this.queryFn)
100
+ throw new Error("Query function is already set");
101
+ else if (this.args.at(-1)?.option?.nullable)
102
+ throw new Error("Last argument is nullable");
103
+ this.args.push({ name, argRef, option });
104
+ return this;
105
+ }
106
+ opt(name, argRef, option) {
107
+ if (this.queryFn)
108
+ throw new Error("Query function is already set");
109
+ this.args.push({ name, argRef, option: { ...option, nullable: true } });
110
+ return this;
111
+ }
112
+ query(query) {
113
+ if (this.queryFn)
114
+ throw new Error("Query function is already set");
115
+ this.queryFn = query;
116
+ return this;
117
+ }
118
+ applyFilterMeta(filterRef, key) {
119
+ const metadata = { key, type: "mongo", descriptor: { value: this.queryFn } };
120
+ const metadataMap = getFilterKeyMetaMapOnPrototype(filterRef.prototype);
121
+ metadataMap.set(key, metadata);
122
+ filterRef.prototype[key] = this.queryFn;
123
+ setFilterKeyMetaMapOnPrototype(filterRef.prototype, metadataMap);
124
+ const filterArgMetas = this.args.map((argInfo) => {
125
+ const [modelRef, arrDepth] = getNonArrayModel(argInfo.argRef);
126
+ const [opt, optArrDepth] = getNonArrayModel(argInfo.option ?? {});
127
+ return { name: argInfo.name, ...opt, modelRef, arrDepth, isArray: arrDepth > 0, optArrDepth };
128
+ });
129
+ setFilterArgMetasOnPrototype(filterRef.prototype, key, filterArgMetas);
130
+ }
131
+ }
132
+ const filter = () => new FilterInfo();
133
+ export {
134
+ FilterInfo,
135
+ filter,
136
+ from,
137
+ getFilterArgMetas,
138
+ getFilterKeyMetaMapOnPrototype,
139
+ getFilterMeta,
140
+ getFilterQuery,
141
+ getFilterQueryMap,
142
+ getFilterSort,
143
+ getFilterSortMap,
144
+ isFilterModel,
145
+ setFilterArgMetasOnPrototype,
146
+ setFilterKeyMetaMapOnPrototype,
147
+ setFilterMeta
148
+ };
package/esm/src/index.js CHANGED
@@ -3,3 +3,5 @@ export * from "./schema";
3
3
  export * from "./types";
4
4
  export * from "./database";
5
5
  export * from "./dataLoader";
6
+ export * from "./documentInfo";
7
+ export * from "./filterMeta";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/document",
3
- "version": "0.9.48",
3
+ "version": "0.9.49",
4
4
  "sourceType": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/src/database.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import type { Dayjs, GetActionObject, MergedValues, PromiseOrObject } from "@akanjs/base";
2
2
  import { Logger } from "@akanjs/common";
3
- import { type DocumentModel, type FilterType, type FindQueryOption, type ListQueryOption, type QueryOf, type SortOf } from "@akanjs/constant";
3
+ import { type DocumentModel, type QueryOf } from "@akanjs/constant";
4
4
  import type DataLoader from "dataloader";
5
5
  import type { Filter, MeiliSearch } from "meilisearch";
6
6
  import type { HydratedDocument } from "mongoose";
7
7
  import type { RedisClientType } from "redis";
8
- import type { BaseMiddleware, CRUDEventType, Database, Mdl, SaveEventType } from "./dbDecorators";
9
- import type { DataInputOf } from "./types";
10
- interface RedisSetOptions {
8
+ import type { BaseMiddleware, CRUDEventType, Mdl, SaveEventType } from "./dbDecorators";
9
+ import type { Database } from "./documentInfo";
10
+ import type { DataInputOf, FilterType, FindQueryOption, ListQueryOption, SortOf } from "./types";
11
+ export interface RedisSetOptions {
11
12
  expireAt?: Dayjs;
12
13
  }
13
14
  declare class CacheDatabase<T = any> {
@@ -41,7 +42,7 @@ declare class SearchDatabase<T = any> {
41
42
  sort?: string | null;
42
43
  }): Promise<number>;
43
44
  }
44
- type QueryMethodOfKey<CapitalizedK extends string, Doc, Insight, _Args extends any[], _ListArgs extends any[], _FindArgs extends any[]> = {
45
+ type QueryMethodOfKey<CapitalizedK extends string, Doc, Insight, _Args extends any[], _ListArgs extends any[], _FindArgs extends any[], _QueryOfDoc = QueryOf<Doc>> = {
45
46
  [K in `list${CapitalizedK}`]: (...args: _ListArgs) => Promise<Doc[]>;
46
47
  } & {
47
48
  [K in `listIds${CapitalizedK}`]: (...args: _ListArgs) => Promise<string[]>;
@@ -59,8 +60,10 @@ type QueryMethodOfKey<CapitalizedK extends string, Doc, Insight, _Args extends a
59
60
  [K in `count${CapitalizedK}`]: (...args: _Args) => Promise<number>;
60
61
  } & {
61
62
  [K in `insight${CapitalizedK}`]: (...args: _Args) => Promise<Insight>;
63
+ } & {
64
+ [K in `query${CapitalizedK}`]: (...args: _Args) => _QueryOfDoc;
62
65
  };
63
- export type QueryMethodPart<Query, Sort, Obj, Doc, Insight, _FindQueryOption = FindQueryOption<Sort, Obj>, _ListQueryOption = ListQueryOption<Sort, Obj>> = MergedValues<{
66
+ export type QueryMethodPart<Query, Sort, Obj, Doc, Insight, _FindQueryOption = FindQueryOption<Sort, Obj>, _ListQueryOption = ListQueryOption<Sort, Obj>, _QueryOfDoc = QueryOf<Doc>> = MergedValues<{
64
67
  [K in keyof Query]: K extends string ? Query[K] extends (...args: infer Args) => any ? QueryMethodOfKey<Capitalize<K>, Doc, Insight, Args, [
65
68
  ...Args,
66
69
  queryOption?: _ListQueryOption
@@ -115,7 +118,7 @@ type DatabaseModelWithQuerySort<T extends string, Input, Doc, Obj, Insight, Quer
115
118
  [K in `searchDocs${_CapitalizedT}`]: (searchText: string, queryOption?: _ListQueryOption) => Promise<Doc[]>;
116
119
  } & {
117
120
  [K in `searchCount${_CapitalizedT}`]: (searchText: string) => Promise<number>;
118
- } & QueryMethodPart<Query, Sort, Obj, Doc, Insight, _FindQueryOption, _ListQueryOption>;
121
+ } & QueryMethodPart<Query, Sort, Obj, Doc, Insight, _FindQueryOption, _ListQueryOption, _QueryOfDoc>;
119
122
  export type DatabaseModel<T extends string, Input, Doc, Obj, Insight, Filter, _CapitalizedT extends string = Capitalize<T>, _QueryOfDoc = QueryOf<Doc>, _Query = GetActionObject<Filter>, _Sort = SortOf<Filter>, _DataInput = DataInputOf<Input, DocumentModel<Obj>>, _FindQueryOption = FindQueryOption<_Sort, Obj>, _ListQueryOption = ListQueryOption<_Sort, Obj>> = DatabaseModelWithQuerySort<T, Input, Doc, Obj, Insight, _Query, _Sort, _CapitalizedT, _QueryOfDoc, _DataInput, _FindQueryOption, _ListQueryOption>;
120
123
  export declare const databaseModelOf: <T extends string, Input, Doc extends HydratedDocument<any>, Model extends Mdl<any, any>, Middleware extends BaseMiddleware, Insight, Obj, Filter extends FilterType>(database: Database<T, Input, Doc, Model, Middleware, Insight, Obj, Filter>, model: Mdl<any, any>, redis: RedisClientType, meili: MeiliSearch) => DatabaseModel<T, Input, Doc, Model, Insight, Filter>;
121
124
  export {};
@@ -1,9 +1,9 @@
1
- import { BaseObject, type MergeAllActionTypes, PromiseOrObject, Type } from "@akanjs/base";
2
- import { type ConstantModel, type DocumentModel, type FilterType } from "@akanjs/constant";
1
+ import { BaseObject, GetActionObject, type MergeAllActionTypes, PromiseOrObject, Type } from "@akanjs/base";
2
+ import { type ConstantModel, type DocumentModel } from "@akanjs/constant";
3
3
  import type { FilterQuery, HydratedDocument, Model as MongooseModel, PipelineStage, ProjectionType, Schema } from "mongoose";
4
4
  import type { DatabaseModel } from "./database";
5
5
  export type { FilterQuery as QueryOf };
6
- interface DefaultDocMtds<TDocument> {
6
+ export interface DefaultDocMtds<TDocument> {
7
7
  refresh(): Promise<this>;
8
8
  set(data: Partial<TDocument>): this;
9
9
  save(): Promise<this>;
@@ -37,33 +37,7 @@ export type SchemaOf<Mdl, Doc> = Schema<null, Mdl, Doc, undefined, null, Mdl>;
37
37
  export interface BaseMiddleware {
38
38
  onSchema: (schema: SchemaOf<any, any>) => void;
39
39
  }
40
- export interface Database<T extends string, Input, Doc extends HydratedDocument<any>, Model, Middleware extends BaseMiddleware, Obj, Insight, Filter extends FilterType> {
41
- refName: T;
42
- Input: Type<Input>;
43
- Doc: Type<Doc>;
44
- Model: Type<Model>;
45
- Middleware: Type<Middleware>;
46
- Obj: Type<Obj>;
47
- Insight: Type<Insight>;
48
- Filter: Type<Filter>;
49
- }
50
- export declare const dbOf: <T extends string, Input, Doc extends HydratedDocument<any>, Model extends DatabaseModel<T, Input, any, Obj, Insight, Filter>, Middleware extends BaseMiddleware, Obj, Insight, Filter extends FilterType>(refName: T, Input: Type<Input>, Doc: Type<Doc>, Model: Type<Model>, Middleware: Type<Middleware>, Obj: Type<Obj>, Insight: Type<Insight>, Filter: Type<Filter>) => Database<T, Input, Doc, Model, Middleware, Obj, Insight, Filter>;
51
- export declare class InputDatabaseStorage {
52
- }
53
- export declare class DocumentDatabaseStorage {
54
- }
55
- export declare class ModelDatabaseStorage {
56
- }
57
- export declare class MiddlewareDatabaseStorage {
58
- }
59
- export declare const getAllDatabaseModelNames: () => string[];
60
- export declare const Database: {
61
- Input: (returns: () => Type) => (target: any) => void;
62
- Document: (returns: () => Type) => (target: any) => void;
63
- Model: (returns: () => Type) => (target: any) => void;
64
- Middleware: (returns: () => Type) => (target: any) => void;
65
- };
66
- export declare const into: <Doc, T extends string, Input, Full, Light, Insight, Filter extends FilterType, _CapitalizedT extends string, _Default, _DefaultInput, _DefaultState, _DefaultStateInput, _Doc, _DocInput, _QueryOfDoc, _Query, _Sort, AddDbModels extends Type[], _DatabaseModel = DatabaseModel<T, _DocInput, Doc, Full, Insight, Filter, _CapitalizedT, _QueryOfDoc, _Query, _Sort>>(docRef: Type<Doc>, cnst: ConstantModel<T, Input, Full, Light, Insight, Filter, _CapitalizedT, _Default, _DefaultInput, _DefaultState, _DefaultStateInput, _Doc, _DocInput, _QueryOfDoc, _Query, _Sort>, ...addMdls: AddDbModels) => Type<MergeAllActionTypes<AddDbModels, keyof _DatabaseModel & string> & _DatabaseModel>;
40
+ export declare const into: <Doc, Filter, T extends string, Input, Full, Light, Insight, AddDbModels extends Type[], _CapitalizedT extends string, _Default, _DefaultInput, _DefaultState, _DefaultStateInput, _DefaultInsight, _PurifiedInput, _Doc, _DocInput, _QueryOfDoc, _Query = GetActionObject<Filter>, _Sort = keyof import("@akanjs/base").GetStateObject<Filter>, _DatabaseModel = DatabaseModel<T, _DocInput, Doc, Full, Insight, Filter, _CapitalizedT, _QueryOfDoc, _Query, _Sort>>(docRef: Type<Doc>, filterRef: Type<Filter>, cnst: ConstantModel<T, Input, Full, Light, Insight, _CapitalizedT, _Default, _DefaultInput, _DefaultState, _DefaultStateInput, _DefaultInsight, _PurifiedInput, _Doc, _DocInput, _QueryOfDoc>, ...addMdls: AddDbModels) => Type<MergeAllActionTypes<AddDbModels, keyof _DatabaseModel & string> & _DatabaseModel>;
67
41
  export declare const by: <Model, AddDbModels extends Type[], _DocModel = Model extends BaseObject ? Doc<Model> : DocumentModel<Model>>(modelRef: Type<Model>, ...addRefs: AddDbModels) => Type<MergeAllActionTypes<AddDbModels, keyof _DocModel & string> & _DocModel>;
68
42
  export declare const beyond: <DbModel, Doc>(model: Type<DbModel>, doc: Type<Doc>) => {
69
43
  new (): {
@@ -0,0 +1,56 @@
1
+ import type { Type } from "@akanjs/base";
2
+ import type { HydratedDocument } from "mongoose";
3
+ import type { DatabaseModel } from "./database";
4
+ import type { BaseMiddleware } from "./dbDecorators";
5
+ import { FilterType } from "./types";
6
+ export interface DatabaseDocumentModelInfo {
7
+ input: Type;
8
+ doc: Type;
9
+ model: Type;
10
+ filter: Type;
11
+ middleware: Type;
12
+ }
13
+ export declare const documentInfo: {
14
+ database: Map<string, DatabaseDocumentModelInfo>;
15
+ scalar: Map<string, Type>;
16
+ modelSets: {
17
+ input: Set<Type>;
18
+ doc: Set<Type>;
19
+ model: Set<Type>;
20
+ filter: Set<Type>;
21
+ middleware: Set<Type>;
22
+ scalar: Set<Type>;
23
+ };
24
+ modelRefNameMap: Map<Type, string>;
25
+ getRefName<AllowEmpty extends boolean = false>(modelRef: Type, { allowEmpty }?: {
26
+ allowEmpty?: AllowEmpty;
27
+ }): AllowEmpty extends true ? string | undefined : string;
28
+ isInput(modelRef: Type): boolean;
29
+ isDoc(modelRef: Type): boolean;
30
+ isModel(modelRef: Type): boolean;
31
+ isMiddleware(modelRef: Type): boolean;
32
+ isScalar(modelRef: Type): boolean;
33
+ setDatabase(refName: string, { Input, Doc, Model, Middleware, Filter }: Database<any, any, any, any, any, any, any, any>): void;
34
+ getDatabase<AllowEmpty extends boolean = false>(refName: string, { allowEmpty }?: {
35
+ allowEmpty?: AllowEmpty;
36
+ }): AllowEmpty extends true ? DatabaseDocumentModelInfo | undefined : DatabaseDocumentModelInfo;
37
+ setScalar(refName: string, Model: Type): void;
38
+ getScalar<AllowEmpty extends boolean = false>(refName: string, { allowEmpty }?: {
39
+ allowEmpty?: AllowEmpty;
40
+ }): AllowEmpty extends true ? Type | undefined : Type;
41
+ };
42
+ export interface Database<T extends string, Input, Doc extends HydratedDocument<any>, Model, Middleware extends BaseMiddleware, Obj, Insight, Filter extends FilterType> {
43
+ refName: T;
44
+ Input: Type<Input>;
45
+ Doc: Type<Doc>;
46
+ Model: Type<Model>;
47
+ Middleware: Type<Middleware>;
48
+ Obj: Type<Obj>;
49
+ Insight: Type<Insight>;
50
+ Filter: Type<Filter>;
51
+ }
52
+ export declare const dbOf: <T extends string, Input, Doc extends HydratedDocument<any>, Model extends DatabaseModel<T, Input, any, Obj, Insight, Filter>, Middleware extends BaseMiddleware, Obj, Insight, Filter extends FilterType>(refName: T, Input: Type<Input>, Doc: Type<Doc>, Model: Type<Model>, Middleware: Type<Middleware>, Obj: Type<Obj>, Insight: Type<Insight>, Filter: Type<Filter>) => Database<T, Input, Doc, Model, Middleware, Obj, Insight, Filter>;
53
+ export declare const scalarDbOf: <T extends string, Model>(refName: T, Model: Type<Model>) => {
54
+ refName: T;
55
+ Model: Type<Model>;
56
+ };
@@ -0,0 +1,71 @@
1
+ import { type BaseObject, type MergeAllTypes, type Prettify, type Type } from "@akanjs/base";
2
+ import { ConstantFieldTypeInput, FieldToValue, PlainTypeToFieldType, QueryOf } from "@akanjs/constant";
3
+ import type { ConstantFilterMeta, FilterArgMeta, FilterKeyMeta, SortType } from "./types";
4
+ export declare const isFilterModel: (filterRef: Type) => boolean;
5
+ export declare const getFilterMeta: (filterRef: Type) => ConstantFilterMeta;
6
+ export declare const setFilterMeta: (filterRef: Type, filterMeta: ConstantFilterMeta) => void;
7
+ export declare const getFilterKeyMetaMapOnPrototype: (prototype: object) => Map<string, FilterKeyMeta>;
8
+ export declare const setFilterKeyMetaMapOnPrototype: (prototype: object, metadataMap: Map<string, FilterKeyMeta>) => void;
9
+ export declare const setFilterArgMetasOnPrototype: (prototype: object, key: string, filterArgMetas: FilterArgMeta[]) => void;
10
+ export declare const getFilterArgMetas: (filterRef: Type, key: string) => FilterArgMeta[];
11
+ export declare const getFilterQuery: (filterRef: Type, key: string) => (...args: any[]) => QueryOf<any>;
12
+ export declare const getFilterQueryMap: (filterRef: Type) => Map<string, FilterKeyMeta>;
13
+ export declare const getFilterSort: (filterRef: Type, key: string) => Partial<{
14
+ [x: string]: number;
15
+ }>;
16
+ export declare const getFilterSortMap: (filterRef: Type) => SortType<{
17
+ [key: string]: any;
18
+ }>;
19
+ export type BaseFilterKey = "latest" | "oldest" | "any" | "byStatuses";
20
+ interface BaseFilter<Status extends string = string> {
21
+ latest: {
22
+ createdAt: -1;
23
+ };
24
+ oldest: {
25
+ createdAt: 1;
26
+ };
27
+ any: () => {
28
+ removedAt: {
29
+ $exists: false;
30
+ };
31
+ };
32
+ byStatuses: (statuses?: Status[] | null) => {
33
+ status: {
34
+ $in: Status[];
35
+ };
36
+ };
37
+ }
38
+ type ExtractQuery<Query extends {
39
+ [key: string]: FilterInfo<any[]>;
40
+ }> = {
41
+ [K in keyof Query]: Query[K] extends FilterInfo<infer Args> ? (...args: Args) => QueryOf<any> : never;
42
+ };
43
+ export declare const from: <Full extends BaseObject, FilterSort extends {
44
+ query: {
45
+ [key: string]: FilterInfo<any[]>;
46
+ };
47
+ sort: SortType<Full>;
48
+ }, LibFilters extends Type[]>(modelRef: Type<Full>, filterSort: (filter: () => FilterInfo<[], Full>) => FilterSort, ...libFilterRefs: LibFilters) => Type<Prettify<MergeAllTypes<LibFilters> & BaseFilter<Full extends {
49
+ status: infer Status;
50
+ } ? Status : string> & ExtractQuery<FilterSort["query"]> & FilterSort["sort"]>>;
51
+ interface ArgProps<Value = any> {
52
+ nullable?: boolean;
53
+ ref?: string;
54
+ default?: Value;
55
+ renderOption?: (arg: any) => string;
56
+ }
57
+ export declare class FilterInfo<Args extends any[] = [], Model = any> {
58
+ readonly args: {
59
+ name: string;
60
+ argRef: any;
61
+ option?: ArgProps;
62
+ }[];
63
+ queryFn: ((...args: Args) => QueryOf<any>) | null;
64
+ constructor();
65
+ arg<ExplicitType, Arg extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>, _FieldToValue = FieldToValue<Arg>>(name: string, argRef: Arg, option?: Omit<ArgProps<_FieldToValue>, "nullable">): FilterInfo<[...Args, arg: _FieldToValue], Model>;
66
+ opt<ExplicitType, Arg extends ConstantFieldTypeInput = PlainTypeToFieldType<ExplicitType>, _FieldToValue = FieldToValue<Arg>>(name: string, argRef: Arg, option?: Omit<ArgProps<_FieldToValue>, "nullable">): FilterInfo<[...Args, opt?: _FieldToValue | null], Model>;
67
+ query(query: (...args: Args) => QueryOf<Model>): this;
68
+ applyFilterMeta(filterRef: Type, key: string): void;
69
+ }
70
+ export declare const filter: () => FilterInfo<[], any>;
71
+ export {};
package/src/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export * from "./schema";
3
3
  export * from "./types";
4
4
  export * from "./database";
5
5
  export * from "./dataLoader";
6
+ export * from "./documentInfo";
7
+ export * from "./filterMeta";
package/src/types.d.ts CHANGED
@@ -1,6 +1,57 @@
1
- import type { GetStateObject } from "@akanjs/base";
2
- import type { Document } from "mongoose";
1
+ import type { Enum, GetStateObject, Type } from "@akanjs/base";
2
+ import type { Document, ProjectionType } from "mongoose";
3
3
  export type DataInputOf<Input, Obj> = {
4
4
  [K in keyof Input as K extends K ? K : never]: Input[K] extends any[] ? Input[K] | undefined : Input[K];
5
5
  } & Partial<Obj>;
6
6
  export type GetDocObject<D> = GetStateObject<Omit<D, Exclude<keyof Document, "id"> | "__v">>;
7
+ export interface FilterType {
8
+ [key: string]: any;
9
+ }
10
+ export interface SortType<Model extends {
11
+ [key: string]: any;
12
+ } = {
13
+ [key: string]: any;
14
+ }> {
15
+ [key: string]: Partial<{
16
+ [K in keyof GetStateObject<Model>]: number;
17
+ }>;
18
+ }
19
+ export type SortOf<Filter> = keyof GetStateObject<Filter>;
20
+ export interface ConstantFilterMeta {
21
+ refName: string;
22
+ sort: SortType;
23
+ }
24
+ export interface FilterKeyProps {
25
+ type?: "mongo" | "meili";
26
+ }
27
+ export interface FilterKeyMeta extends FilterKeyProps {
28
+ key: string;
29
+ descriptor: PropertyDescriptor;
30
+ }
31
+ export interface FilterArgProps {
32
+ nullable?: boolean;
33
+ ref?: string;
34
+ default?: string | number | boolean | object | null | (() => string | number | boolean | object | null);
35
+ renderOption?: (value: any) => string;
36
+ enum?: Enum;
37
+ }
38
+ export interface FilterArgMeta extends FilterArgProps {
39
+ name: string;
40
+ modelRef: Type;
41
+ arrDepth: number;
42
+ isArray: boolean;
43
+ optArrDepth: number;
44
+ }
45
+ export interface ListQueryOption<Sort, Obj> {
46
+ skip?: number | null;
47
+ limit?: number | null;
48
+ sort?: Sort | null;
49
+ sample?: number;
50
+ select?: ProjectionType<Obj>;
51
+ }
52
+ export interface FindQueryOption<Sort, Obj> {
53
+ skip?: number | null;
54
+ sort?: Sort | null;
55
+ sample?: boolean;
56
+ select?: ProjectionType<Obj>;
57
+ }