@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.
- package/cjs/src/database.js +13 -18
- package/cjs/src/dbDecorators.js +1 -60
- package/cjs/src/documentInfo.js +105 -0
- package/cjs/src/filterMeta.js +182 -0
- package/cjs/src/index.js +5 -1
- package/esm/src/database.js +8 -19
- package/esm/src/dbDecorators.js +2 -58
- package/esm/src/documentInfo.js +80 -0
- package/esm/src/filterMeta.js +148 -0
- package/esm/src/index.js +2 -0
- package/package.json +1 -1
- package/src/database.d.ts +10 -7
- package/src/dbDecorators.d.ts +4 -30
- package/src/documentInfo.d.ts +56 -0
- package/src/filterMeta.d.ts +71 -0
- package/src/index.d.ts +2 -0
- package/src/types.d.ts +53 -2
package/cjs/src/database.js
CHANGED
|
@@ -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(
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
};
|
package/cjs/src/dbDecorators.js
CHANGED
|
@@ -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
|
|
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
|
});
|
package/esm/src/database.js
CHANGED
|
@@ -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(
|
|
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
|
};
|
package/esm/src/dbDecorators.js
CHANGED
|
@@ -1,54 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
package/package.json
CHANGED
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
|
|
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,
|
|
9
|
-
import type {
|
|
10
|
-
|
|
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 {};
|
package/src/dbDecorators.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BaseObject, type MergeAllActionTypes, PromiseOrObject, Type } from "@akanjs/base";
|
|
2
|
-
import { type ConstantModel, type DocumentModel
|
|
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
|
|
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
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
|
+
}
|