aws-service-stack 0.18.447 → 0.18.450
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/README.md +79 -7
- package/dist/controller/base-controller.d.ts +2 -1
- package/dist/controller/base-controller.d.ts.map +1 -1
- package/dist/controller/base-controller.js +64 -15
- package/dist/controller/base-controller.js.map +1 -1
- package/dist/controller/controller-api.d.ts +13 -2
- package/dist/controller/controller-api.d.ts.map +1 -1
- package/dist/controller/controller-api.js +77 -10
- package/dist/controller/controller-api.js.map +1 -1
- package/dist/controller/controller-request.d.ts +3 -0
- package/dist/controller/controller-request.d.ts.map +1 -1
- package/dist/controller/controller-request.js +5 -0
- package/dist/controller/controller-request.js.map +1 -1
- package/dist/controller/controller-role.d.ts +2 -1
- package/dist/controller/controller-role.d.ts.map +1 -1
- package/dist/controller/controller-role.js +12 -3
- package/dist/controller/controller-role.js.map +1 -1
- package/dist/exception/exception-handler.d.ts.map +1 -1
- package/dist/exception/exception-handler.js +17 -2
- package/dist/exception/exception-handler.js.map +1 -1
- package/dist/model/base.config.d.ts +4 -1
- package/dist/model/base.config.d.ts.map +1 -1
- package/dist/model/base.config.js +1 -0
- package/dist/model/base.config.js.map +1 -1
- package/dist/model/base.model.d.ts +3 -0
- package/dist/model/base.model.d.ts.map +1 -1
- package/dist/model/base.model.js.map +1 -1
- package/dist/model/caller.model.d.ts +22 -0
- package/dist/model/caller.model.d.ts.map +1 -0
- package/dist/model/caller.model.js +12 -0
- package/dist/model/caller.model.js.map +1 -0
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.d.ts.map +1 -1
- package/dist/model/index.js +1 -0
- package/dist/model/index.js.map +1 -1
- package/dist/model/validation.model.d.ts +15 -1
- package/dist/model/validation.model.d.ts.map +1 -1
- package/dist/model/validation.model.js +3 -1
- package/dist/model/validation.model.js.map +1 -1
- package/dist/repositories/base-es.repo.d.ts.map +1 -1
- package/dist/repositories/base-es.repo.js +4 -0
- package/dist/repositories/base-es.repo.js.map +1 -1
- package/dist/utils/auth/caller.d.ts +9 -0
- package/dist/utils/auth/caller.d.ts.map +1 -0
- package/dist/utils/auth/caller.js +108 -0
- package/dist/utils/auth/caller.js.map +1 -0
- package/dist/utils/auth/policy-view.d.ts +42 -0
- package/dist/utils/auth/policy-view.d.ts.map +1 -0
- package/dist/utils/auth/policy-view.js +170 -0
- package/dist/utils/auth/policy-view.js.map +1 -0
- package/dist/utils/http/api-event.d.ts +23 -0
- package/dist/utils/http/api-event.d.ts.map +1 -0
- package/dist/utils/http/api-event.js +84 -0
- package/dist/utils/http/api-event.js.map +1 -0
- package/dist/utils/http/http.util.d.ts +12 -2
- package/dist/utils/http/http.util.d.ts.map +1 -1
- package/dist/utils/http/http.util.js +50 -24
- package/dist/utils/http/http.util.js.map +1 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/opensearch/opensearch.mapping.d.ts +35 -0
- package/dist/utils/opensearch/opensearch.mapping.d.ts.map +1 -0
- package/dist/utils/opensearch/opensearch.mapping.js +95 -0
- package/dist/utils/opensearch/opensearch.mapping.js.map +1 -0
- package/dist/utils/opensearch/opensearch.parser.aggs.d.ts +2 -1
- package/dist/utils/opensearch/opensearch.parser.aggs.d.ts.map +1 -1
- package/dist/utils/opensearch/opensearch.parser.aggs.js +38 -4
- package/dist/utils/opensearch/opensearch.parser.aggs.js.map +1 -1
- package/dist/utils/opensearch/opensearch.parser.d.ts +1 -1
- package/dist/utils/reflection.util.d.ts +4 -0
- package/dist/utils/reflection.util.d.ts.map +1 -1
- package/dist/utils/reflection.util.js +17 -0
- package/dist/utils/reflection.util.js.map +1 -1
- package/package.json +76 -19
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export * from "./http/http.util";
|
|
2
2
|
export * from "./http/http-request";
|
|
3
|
+
export * from "./http/api-event";
|
|
3
4
|
export * from "./array.util";
|
|
4
5
|
export * from "./auth.util";
|
|
6
|
+
export * from "./auth/caller";
|
|
7
|
+
export * from "./auth/policy-view";
|
|
5
8
|
export * from "./date.util";
|
|
6
9
|
export * from "./dynamodb.utils";
|
|
7
10
|
export * from "./env.util";
|
|
@@ -10,6 +13,7 @@ export * from "./json.util";
|
|
|
10
13
|
export * from "./opensearch.utils";
|
|
11
14
|
export * from "./reflection.util";
|
|
12
15
|
export * from "./validation.util";
|
|
16
|
+
export * from "./opensearch/opensearch.mapping";
|
|
13
17
|
export * from "./opensearch/opensearch.parser";
|
|
14
18
|
export * from "./opensearch/opensearch.transform";
|
|
15
19
|
export * from "./data.util";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,aAAa,CAAC;AAE5B,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,aAAa,CAAC;AAE5B,cAAc,oBAAoB,CAAC"}
|
package/dist/utils/index.js
CHANGED
|
@@ -16,8 +16,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./http/http.util"), exports);
|
|
18
18
|
__exportStar(require("./http/http-request"), exports);
|
|
19
|
+
__exportStar(require("./http/api-event"), exports);
|
|
19
20
|
__exportStar(require("./array.util"), exports);
|
|
20
21
|
__exportStar(require("./auth.util"), exports);
|
|
22
|
+
__exportStar(require("./auth/caller"), exports);
|
|
23
|
+
__exportStar(require("./auth/policy-view"), exports);
|
|
21
24
|
__exportStar(require("./date.util"), exports);
|
|
22
25
|
__exportStar(require("./dynamodb.utils"), exports);
|
|
23
26
|
__exportStar(require("./env.util"), exports);
|
|
@@ -26,6 +29,7 @@ __exportStar(require("./json.util"), exports);
|
|
|
26
29
|
__exportStar(require("./opensearch.utils"), exports);
|
|
27
30
|
__exportStar(require("./reflection.util"), exports);
|
|
28
31
|
__exportStar(require("./validation.util"), exports);
|
|
32
|
+
__exportStar(require("./opensearch/opensearch.mapping"), exports);
|
|
29
33
|
__exportStar(require("./opensearch/opensearch.parser"), exports);
|
|
30
34
|
__exportStar(require("./opensearch/opensearch.transform"), exports);
|
|
31
35
|
__exportStar(require("./data.util"), exports);
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,sDAAoC;AACpC,+CAA6B;AAC7B,8CAA4B;AAC5B,8CAA4B;AAC5B,mDAAiC;AACjC,6CAA2B;AAC3B,+CAA6B;AAC7B,8CAA4B;AAC5B,qDAAmC;AACnC,oDAAkC;AAClC,oDAAkC;AAClC,iEAA+C;AAC/C,oEAAkD;AAClD,8CAA4B;AAE5B,qDAAmC","sourcesContent":["export * from \"./http/http.util\";\nexport * from \"./http/http-request\";\nexport * from \"./array.util\";\nexport * from \"./auth.util\";\nexport * from \"./date.util\";\nexport * from \"./dynamodb.utils\";\nexport * from \"./env.util\";\nexport * from \"./error.util\";\nexport * from \"./json.util\";\nexport * from \"./opensearch.utils\";\nexport * from \"./reflection.util\";\nexport * from \"./validation.util\";\nexport * from \"./opensearch/opensearch.parser\";\nexport * from \"./opensearch/opensearch.transform\";\nexport * from \"./data.util\";\n\nexport * from \"../function/logger\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,sDAAoC;AACpC,mDAAiC;AACjC,+CAA6B;AAC7B,8CAA4B;AAC5B,gDAA8B;AAC9B,qDAAmC;AACnC,8CAA4B;AAC5B,mDAAiC;AACjC,6CAA2B;AAC3B,+CAA6B;AAC7B,8CAA4B;AAC5B,qDAAmC;AACnC,oDAAkC;AAClC,oDAAkC;AAClC,kEAAgD;AAChD,iEAA+C;AAC/C,oEAAkD;AAClD,8CAA4B;AAE5B,qDAAmC","sourcesContent":["export * from \"./http/http.util\";\nexport * from \"./http/http-request\";\nexport * from \"./http/api-event\";\nexport * from \"./array.util\";\nexport * from \"./auth.util\";\nexport * from \"./auth/caller\";\nexport * from \"./auth/policy-view\";\nexport * from \"./date.util\";\nexport * from \"./dynamodb.utils\";\nexport * from \"./env.util\";\nexport * from \"./error.util\";\nexport * from \"./json.util\";\nexport * from \"./opensearch.utils\";\nexport * from \"./reflection.util\";\nexport * from \"./validation.util\";\nexport * from \"./opensearch/opensearch.mapping\";\nexport * from \"./opensearch/opensearch.parser\";\nexport * from \"./opensearch/opensearch.transform\";\nexport * from \"./data.util\";\n\nexport * from \"../function/logger\";\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type MappingNode = {
|
|
2
|
+
type?: string;
|
|
3
|
+
fields?: Record<string, {
|
|
4
|
+
type?: string;
|
|
5
|
+
}>;
|
|
6
|
+
properties?: Record<string, MappingNode>;
|
|
7
|
+
};
|
|
8
|
+
type MappingProperties = Record<string, MappingNode>;
|
|
9
|
+
type MappingClient = {
|
|
10
|
+
indices: {
|
|
11
|
+
getMapping: (params: {
|
|
12
|
+
index: string;
|
|
13
|
+
}) => Promise<any>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Rewrite sort entries that target an analysed `text` field onto its keyword sub-field.
|
|
18
|
+
*
|
|
19
|
+
* OpenSearch cannot sort on a `text` field (fielddata is disabled by default), so sorting on one
|
|
20
|
+
* fails the whole search. The correct target is decided from the index mapping rather than guessed:
|
|
21
|
+
* `keyword`, numeric and date fields are left alone, and an unknown field is left alone too, so a
|
|
22
|
+
* genuine mapping mistake still surfaces as a real error instead of being silently swallowed.
|
|
23
|
+
*/
|
|
24
|
+
export declare const applyKeywordSortFields: (sort: any[], properties: MappingProperties) => any[];
|
|
25
|
+
/**
|
|
26
|
+
* Resolve a query's sort fields against the live index mapping, caching the mapping per index.
|
|
27
|
+
*
|
|
28
|
+
* Fails open: if the mapping cannot be read the sort is returned untouched, so a mapping-service
|
|
29
|
+
* hiccup degrades to today's behaviour instead of breaking search.
|
|
30
|
+
*/
|
|
31
|
+
export declare const resolveSortFields: (client: MappingClient, index: string, sort: any[]) => Promise<any[]>;
|
|
32
|
+
/** Exposed for tests and for callers that rebuild an index. */
|
|
33
|
+
export declare const clearMappingCache: (index?: string) => void;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=opensearch.mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.mapping.d.ts","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.mapping.ts"],"names":[],"mappings":"AAEA,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC1C,CAAC;AAEF,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAErD,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE;QAAE,UAAU,EAAE,CAAC,MAAM,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAA;KAAE,CAAC;CACtE,CAAC;AAyBF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,SAAU,GAAG,EAAE,cAAc,iBAAiB,KAAG,GAAG,EAetF,CAAC;AAYF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,WAAkB,aAAa,SAAS,MAAM,QAAQ,GAAG,EAAE,KAAG,OAAO,CAAC,GAAG,EAAE,CAsBxG,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,WAAY,MAAM,KAAG,IAGlD,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clearMappingCache = exports.resolveSortFields = exports.applyKeywordSortFields = void 0;
|
|
4
|
+
const KEYWORD_SUFFIX = ".keyword";
|
|
5
|
+
/** One in-flight/resolved mapping lookup per index, for the lifetime of the container. */
|
|
6
|
+
const mappingCache = new Map();
|
|
7
|
+
/** Walk a dotted path such as `location.area` through nested `properties` blocks. */
|
|
8
|
+
const findMappingNode = (properties, path) => {
|
|
9
|
+
const segments = path.split(".");
|
|
10
|
+
let node = properties[segments[0]];
|
|
11
|
+
for (const segment of segments.slice(1)) {
|
|
12
|
+
if (!node?.properties)
|
|
13
|
+
return undefined;
|
|
14
|
+
node = node.properties[segment];
|
|
15
|
+
}
|
|
16
|
+
return node;
|
|
17
|
+
};
|
|
18
|
+
/** The name of a keyword sub-field, if this node is a text field that has one. */
|
|
19
|
+
const keywordSubField = (node) => {
|
|
20
|
+
if (node?.type !== "text" || !node.fields)
|
|
21
|
+
return undefined;
|
|
22
|
+
return Object.entries(node.fields).find(([, subField]) => subField?.type === "keyword")?.[0];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Rewrite sort entries that target an analysed `text` field onto its keyword sub-field.
|
|
26
|
+
*
|
|
27
|
+
* OpenSearch cannot sort on a `text` field (fielddata is disabled by default), so sorting on one
|
|
28
|
+
* fails the whole search. The correct target is decided from the index mapping rather than guessed:
|
|
29
|
+
* `keyword`, numeric and date fields are left alone, and an unknown field is left alone too, so a
|
|
30
|
+
* genuine mapping mistake still surfaces as a real error instead of being silently swallowed.
|
|
31
|
+
*/
|
|
32
|
+
const applyKeywordSortFields = (sort, properties) => {
|
|
33
|
+
if (!Array.isArray(sort) || sort.length === 0)
|
|
34
|
+
return [];
|
|
35
|
+
if (!properties)
|
|
36
|
+
return sort;
|
|
37
|
+
return sort.map((entry) => {
|
|
38
|
+
if (!entry || typeof entry !== "object")
|
|
39
|
+
return entry;
|
|
40
|
+
const [field, order] = Object.entries(entry)[0] ?? [];
|
|
41
|
+
if (typeof field !== "string" || field.endsWith(KEYWORD_SUFFIX))
|
|
42
|
+
return entry;
|
|
43
|
+
const subField = keywordSubField(findMappingNode(properties, field));
|
|
44
|
+
if (!subField)
|
|
45
|
+
return entry;
|
|
46
|
+
return { [`${field}.${subField}`]: order };
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
exports.applyKeywordSortFields = applyKeywordSortFields;
|
|
50
|
+
const readMappingProperties = async (client, index) => {
|
|
51
|
+
const response = await client.indices.getMapping({ index });
|
|
52
|
+
const body = response?.body ?? response;
|
|
53
|
+
// getMapping is keyed by concrete index name, which may differ from the alias we asked for.
|
|
54
|
+
const indexBlock = body?.[index] ?? Object.values(body ?? {})[0];
|
|
55
|
+
return indexBlock?.mappings?.properties;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Resolve a query's sort fields against the live index mapping, caching the mapping per index.
|
|
59
|
+
*
|
|
60
|
+
* Fails open: if the mapping cannot be read the sort is returned untouched, so a mapping-service
|
|
61
|
+
* hiccup degrades to today's behaviour instead of breaking search.
|
|
62
|
+
*/
|
|
63
|
+
const resolveSortFields = async (client, index, sort) => {
|
|
64
|
+
if (!Array.isArray(sort) || sort.length === 0)
|
|
65
|
+
return sort;
|
|
66
|
+
if (!client?.indices?.getMapping || !index)
|
|
67
|
+
return sort;
|
|
68
|
+
try {
|
|
69
|
+
let pending = mappingCache.get(index);
|
|
70
|
+
if (!pending) {
|
|
71
|
+
pending = readMappingProperties(client, index).catch((err) => {
|
|
72
|
+
mappingCache.delete(index); // a failed lookup must not be cached forever
|
|
73
|
+
throw err;
|
|
74
|
+
});
|
|
75
|
+
mappingCache.set(index, pending);
|
|
76
|
+
}
|
|
77
|
+
const properties = await pending;
|
|
78
|
+
if (!properties)
|
|
79
|
+
return sort;
|
|
80
|
+
return (0, exports.applyKeywordSortFields)(sort, properties);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return sort;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
exports.resolveSortFields = resolveSortFields;
|
|
87
|
+
/** Exposed for tests and for callers that rebuild an index. */
|
|
88
|
+
const clearMappingCache = (index) => {
|
|
89
|
+
if (index)
|
|
90
|
+
mappingCache.delete(index);
|
|
91
|
+
else
|
|
92
|
+
mappingCache.clear();
|
|
93
|
+
};
|
|
94
|
+
exports.clearMappingCache = clearMappingCache;
|
|
95
|
+
//# sourceMappingURL=opensearch.mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opensearch.mapping.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.mapping.ts"],"names":[],"mappings":"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","sourcesContent":["const KEYWORD_SUFFIX = \".keyword\";\n\ntype MappingNode = {\n type?: string;\n fields?: Record<string, { type?: string }>;\n properties?: Record<string, MappingNode>;\n};\n\ntype MappingProperties = Record<string, MappingNode>;\n\ntype MappingClient = {\n indices: { getMapping: (params: { index: string }) => Promise<any> };\n};\n\n/** One in-flight/resolved mapping lookup per index, for the lifetime of the container. */\nconst mappingCache = new Map<string, Promise<MappingProperties | undefined>>();\n\n/** Walk a dotted path such as `location.area` through nested `properties` blocks. */\nconst findMappingNode = (properties: MappingProperties, path: string): MappingNode | undefined => {\n const segments = path.split(\".\");\n let node: MappingNode | undefined = properties[segments[0]];\n\n for (const segment of segments.slice(1)) {\n if (!node?.properties) return undefined;\n node = node.properties[segment];\n }\n\n return node;\n};\n\n/** The name of a keyword sub-field, if this node is a text field that has one. */\nconst keywordSubField = (node: MappingNode | undefined): string | undefined => {\n if (node?.type !== \"text\" || !node.fields) return undefined;\n\n return Object.entries(node.fields).find(([, subField]) => subField?.type === \"keyword\")?.[0];\n};\n\n/**\n * Rewrite sort entries that target an analysed `text` field onto its keyword sub-field.\n *\n * OpenSearch cannot sort on a `text` field (fielddata is disabled by default), so sorting on one\n * fails the whole search. The correct target is decided from the index mapping rather than guessed:\n * `keyword`, numeric and date fields are left alone, and an unknown field is left alone too, so a\n * genuine mapping mistake still surfaces as a real error instead of being silently swallowed.\n */\nexport const applyKeywordSortFields = (sort: any[], properties: MappingProperties): any[] => {\n if (!Array.isArray(sort) || sort.length === 0) return [];\n if (!properties) return sort;\n\n return sort.map((entry) => {\n if (!entry || typeof entry !== \"object\") return entry;\n\n const [field, order] = Object.entries(entry)[0] ?? [];\n if (typeof field !== \"string\" || field.endsWith(KEYWORD_SUFFIX)) return entry;\n\n const subField = keywordSubField(findMappingNode(properties, field));\n if (!subField) return entry;\n\n return { [`${field}.${subField}`]: order };\n });\n};\n\nconst readMappingProperties = async (client: MappingClient, index: string): Promise<MappingProperties | undefined> => {\n const response = await client.indices.getMapping({ index });\n const body = response?.body ?? response;\n\n // getMapping is keyed by concrete index name, which may differ from the alias we asked for.\n const indexBlock = body?.[index] ?? Object.values(body ?? {})[0];\n\n return (indexBlock as any)?.mappings?.properties;\n};\n\n/**\n * Resolve a query's sort fields against the live index mapping, caching the mapping per index.\n *\n * Fails open: if the mapping cannot be read the sort is returned untouched, so a mapping-service\n * hiccup degrades to today's behaviour instead of breaking search.\n */\nexport const resolveSortFields = async (client: MappingClient, index: string, sort: any[]): Promise<any[]> => {\n if (!Array.isArray(sort) || sort.length === 0) return sort;\n if (!client?.indices?.getMapping || !index) return sort;\n\n try {\n let pending = mappingCache.get(index);\n\n if (!pending) {\n pending = readMappingProperties(client, index).catch((err) => {\n mappingCache.delete(index); // a failed lookup must not be cached forever\n throw err;\n });\n mappingCache.set(index, pending);\n }\n\n const properties = await pending;\n if (!properties) return sort;\n\n return applyKeywordSortFields(sort, properties);\n } catch {\n return sort;\n }\n};\n\n/** Exposed for tests and for callers that rebuild an index. */\nexport const clearMappingCache = (index?: string): void => {\n if (index) mappingCache.delete(index);\n else mappingCache.clear();\n};\n"]}
|
|
@@ -2,8 +2,9 @@ import { AggTypeOS } from "../../model/index.js";
|
|
|
2
2
|
export interface AggInstruction {
|
|
3
3
|
type: AggTypeOS;
|
|
4
4
|
field: string;
|
|
5
|
+
name?: string;
|
|
5
6
|
sub?: string;
|
|
6
7
|
}
|
|
7
|
-
export declare function buildAggregations(params: Record<string, string>):
|
|
8
|
+
export declare function buildAggregations(params: Record<string, string>): Record<string, any>;
|
|
8
9
|
export declare function buildNativeOSQuery(instructions: AggInstruction[]): any;
|
|
9
10
|
//# sourceMappingURL=opensearch.parser.aggs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opensearch.parser.aggs.d.ts","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.aggs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"opensearch.parser.aggs.d.ts","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.aggs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAsCrF;AAmDD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,cAAc,EAAE,OAqBhE"}
|
|
@@ -38,6 +38,7 @@ function buildAggregations(params) {
|
|
|
38
38
|
instructions.push({
|
|
39
39
|
type,
|
|
40
40
|
field: value,
|
|
41
|
+
name: parts[2],
|
|
41
42
|
});
|
|
42
43
|
continue;
|
|
43
44
|
}
|
|
@@ -59,13 +60,41 @@ function buildQuery(type, field) {
|
|
|
59
60
|
// ----------------------------
|
|
60
61
|
// Build final aggregations
|
|
61
62
|
// ----------------------------
|
|
63
|
+
/**
|
|
64
|
+
* The response key for one instruction.
|
|
65
|
+
*
|
|
66
|
+
* Metric aggregations used to be keyed by their field alone, so asking for the min and the max
|
|
67
|
+
* of one field in a single request silently produced a single aggregation - whichever came last
|
|
68
|
+
* won, and the caller read the same number for both bounds. A metric is keyed by the name the
|
|
69
|
+
* caller supplied in `agg__<type>__<name>`, or by `<field>__<type>` when it supplied none.
|
|
70
|
+
* Terms and tree aggregations keep their existing field-based keys.
|
|
71
|
+
*/
|
|
72
|
+
function resolveAggName(inst) {
|
|
73
|
+
if (inst.type === types_1.AggTypeOS.TREE)
|
|
74
|
+
return inst.field.split(",")[0];
|
|
75
|
+
if (inst.type === types_1.AggTypeOS.TERMS)
|
|
76
|
+
return inst.field;
|
|
77
|
+
return inst.name ?? `${inst.field}__${inst.type}`;
|
|
78
|
+
}
|
|
79
|
+
/** Metrics that are the only one on their field also answer to the old bare-field key. */
|
|
80
|
+
function legacyMetricNames(instructions) {
|
|
81
|
+
const byField = new Map();
|
|
82
|
+
for (const inst of instructions) {
|
|
83
|
+
if (inst.type === types_1.AggTypeOS.TERMS || inst.type === types_1.AggTypeOS.TREE)
|
|
84
|
+
continue;
|
|
85
|
+
byField.set(inst.field, [...(byField.get(inst.field) ?? []), inst]);
|
|
86
|
+
}
|
|
87
|
+
const unambiguous = new Map();
|
|
88
|
+
for (const [field, forField] of byField) {
|
|
89
|
+
if (forField.length === 1)
|
|
90
|
+
unambiguous.set(field, forField[0]);
|
|
91
|
+
}
|
|
92
|
+
return unambiguous;
|
|
93
|
+
}
|
|
62
94
|
function buildNativeOSQuery(instructions) {
|
|
63
95
|
const aggs = {};
|
|
64
96
|
for (const inst of instructions) {
|
|
65
|
-
|
|
66
|
-
if (inst.type === types_1.AggTypeOS.TREE) {
|
|
67
|
-
aggName = inst.field.split(",")[0];
|
|
68
|
-
}
|
|
97
|
+
const aggName = resolveAggName(inst);
|
|
69
98
|
aggs[aggName] = buildQuery(inst.type, inst.field);
|
|
70
99
|
if (inst.sub && aggs[aggName]) {
|
|
71
100
|
aggs[aggName].aggs = {
|
|
@@ -73,6 +102,11 @@ function buildNativeOSQuery(instructions) {
|
|
|
73
102
|
};
|
|
74
103
|
}
|
|
75
104
|
}
|
|
105
|
+
for (const [field, inst] of legacyMetricNames(instructions)) {
|
|
106
|
+
if (aggs[field])
|
|
107
|
+
continue;
|
|
108
|
+
aggs[field] = buildQuery(inst.type, inst.field);
|
|
109
|
+
}
|
|
76
110
|
return aggs;
|
|
77
111
|
}
|
|
78
112
|
function buildTreeQuery(tree) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opensearch.parser.aggs.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.aggs.ts"],"names":[],"mappings":";AAAA,wCAAwC;AACxC,4CAA4C;AAC5C,wCAAwC;;;;AAExC,2CAA4C;
|
|
1
|
+
{"version":3,"file":"opensearch.parser.aggs.js","sourceRoot":"","sources":["../../../src/utils/opensearch/opensearch.parser.aggs.ts"],"names":[],"mappings":"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","sourcesContent":["// =====================================\n// AGG BUILDER (MULTI ROOT + 1 SUB PER ROOT)\n// =====================================\n\nimport { AggTypeOS } from \"@chinggis/types\";\n\nexport interface AggInstruction {\n type: AggTypeOS;\n field: string;\n name?: string; // caller-supplied from agg__<type>__<name>\n sub?: string; // only for agg__xxx__sub\n}\n\n// ----------------------------\n// Parse aggregations\n// ----------------------------\nexport function buildAggregations(params: Record<string, string>): Record<string, any> {\n const instructions: AggInstruction[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (!key.startsWith(\"agg__\")) continue;\n\n const parts = key.split(\"__\"); // [\"agg\", \"terms\", \"sub\"?]\n const type = parts[1] as AggTypeOS;\n\n if (!Object.values(AggTypeOS).includes(type)) continue;\n\n // root = agg__terms=status\n if (parts.length === 2) {\n instructions.push({\n type,\n field: value,\n });\n continue;\n }\n\n // sub = agg__terms__sub=customerId\n if (parts.length === 3 && parts[2] === \"sub\") {\n // attach to last root\n const lastRoot = instructions.find((i) => i.type === type && !i.sub);\n\n if (lastRoot) lastRoot.sub = value;\n continue;\n } else {\n instructions.push({\n type,\n field: value,\n name: parts[2],\n });\n continue;\n }\n }\n\n return buildNativeOSQuery(instructions);\n}\n\n// ----------------------------\n// Build ES agg object\n// ----------------------------\nfunction buildQuery(type: AggTypeOS, field: string) {\n if (type === AggTypeOS.TERMS)\n return {\n [AggTypeOS.TERMS]: { size: 1000, field: field },\n };\n\n if (type === AggTypeOS.TREE) return buildTreeQuery(field);\n return { [type]: { field: field } };\n}\n\n// ----------------------------\n// Build final aggregations\n// ----------------------------\n/**\n * The response key for one instruction.\n *\n * Metric aggregations used to be keyed by their field alone, so asking for the min and the max\n * of one field in a single request silently produced a single aggregation - whichever came last\n * won, and the caller read the same number for both bounds. A metric is keyed by the name the\n * caller supplied in `agg__<type>__<name>`, or by `<field>__<type>` when it supplied none.\n * Terms and tree aggregations keep their existing field-based keys.\n */\nfunction resolveAggName(inst: AggInstruction): string {\n if (inst.type === AggTypeOS.TREE) return inst.field.split(\",\")[0];\n if (inst.type === AggTypeOS.TERMS) return inst.field;\n\n return inst.name ?? `${inst.field}__${inst.type}`;\n}\n\n/** Metrics that are the only one on their field also answer to the old bare-field key. */\nfunction legacyMetricNames(instructions: AggInstruction[]): Map<string, AggInstruction> {\n const byField = new Map<string, AggInstruction[]>();\n\n for (const inst of instructions) {\n if (inst.type === AggTypeOS.TERMS || inst.type === AggTypeOS.TREE) continue;\n byField.set(inst.field, [...(byField.get(inst.field) ?? []), inst]);\n }\n\n const unambiguous = new Map<string, AggInstruction>();\n for (const [field, forField] of byField) {\n if (forField.length === 1) unambiguous.set(field, forField[0]);\n }\n\n return unambiguous;\n}\n\nexport function buildNativeOSQuery(instructions: AggInstruction[]) {\n const aggs: any = {};\n\n for (const inst of instructions) {\n const aggName = resolveAggName(inst);\n\n aggs[aggName] = buildQuery(inst.type, inst.field);\n\n if (inst.sub && aggs[aggName]) {\n aggs[aggName].aggs = {\n [inst.sub]: buildQuery(inst.type, inst.sub),\n };\n }\n }\n\n for (const [field, inst] of legacyMetricNames(instructions)) {\n if (aggs[field]) continue;\n aggs[field] = buildQuery(inst.type, inst.field);\n }\n\n return aggs;\n}\n\nfunction buildTreeQuery(tree: string) {\n let include = \".*\\\\/.*\";\n let exclude = \".*\\\\/.*\\\\/.*\";\n const [field, treeValue] = tree.split(\",\");\n\n if (treeValue) {\n let level = treeValue.split(\"/\").length;\n include = treeValue + include;\n\n if (level > 1) {\n include = treeValue + \".*\\\\/.*\";\n exclude = \"\";\n }\n\n return {\n terms: {\n field: `${field}.tree`,\n include: include,\n exclude: exclude,\n size: 300,\n },\n };\n } else {\n return {\n terms: {\n field: `${field}.tree`,\n exclude: exclude,\n size: 300,\n },\n };\n }\n}\n"]}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { ChangedField, DynamoIndexMap, Filter, TraceChange } from "../model/index.js";
|
|
2
|
+
/** Tags a forced-view array (non-enumerable, survives object spreads) and returns it */
|
|
3
|
+
export declare function markForcedIn<T extends unknown[]>(values: T): T;
|
|
4
|
+
/** True for an array marked by markForcedIn */
|
|
5
|
+
export declare function isForcedIn(value: unknown): boolean;
|
|
2
6
|
export declare const hasField: (obj: object, fieldName: string) => boolean;
|
|
3
7
|
export declare function isMethodeHasKeyword(methodName: string, keywords: string[]): boolean;
|
|
4
8
|
export declare function handleRangeFilters(filter: Filter): Filter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reflection.util.d.ts","sourceRoot":"","sources":["../../src/utils/reflection.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAiB,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"reflection.util.d.ts","sourceRoot":"","sources":["../../src/utils/reflection.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAiB,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAOnG,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAG9D;AAED,+CAA+C;AAC/C,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAElD;AAED,eAAO,MAAM,QAAQ,QAAS,MAAM,aAAa,MAAM,KAAG,OAEzD,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAGnF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA6CzD;AAoDD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,MAAM,CAkD3F;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,uBAS5E;AAKD,eAAO,MAAM,aAAa,WAAY,GAAG,aAAa,MAAM,EAAE,KAAG,GAehE,CAAC;AAEF,eAAO,MAAM,SAAS,WAAY,GAAG,iBAAiB,MAAM,eAAe,MAAM,KAAG,GAGnF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CA8BpH;AA8BD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAU5C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAoB/C;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,WAAW,EAAE,WAAW,GACvB,YAAY,EAAE,CAShB;AAiJD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAU7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA0BvD"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.copyField = exports.fieldsInclude = exports.hasField = void 0;
|
|
4
|
+
exports.markForcedIn = markForcedIn;
|
|
5
|
+
exports.isForcedIn = isForcedIn;
|
|
4
6
|
exports.isMethodeHasKeyword = isMethodeHasKeyword;
|
|
5
7
|
exports.handleRangeFilters = handleRangeFilters;
|
|
6
8
|
exports.parseIndexFilter = parseIndexFilter;
|
|
@@ -14,6 +16,17 @@ exports.pickDefinedDeep = pickDefinedDeep;
|
|
|
14
16
|
const types_1 = require("../model/index.js");
|
|
15
17
|
const http_util_1 = require("./http/http.util");
|
|
16
18
|
const string_util_1 = require("./string.util");
|
|
19
|
+
/** Marks an array that comes from a forced policy-view key (an IN list that must never become an index key) */
|
|
20
|
+
const FORCED_IN = Symbol.for("aws-service-stack.forcedIn");
|
|
21
|
+
/** Tags a forced-view array (non-enumerable, survives object spreads) and returns it */
|
|
22
|
+
function markForcedIn(values) {
|
|
23
|
+
Object.defineProperty(values, FORCED_IN, { value: true, enumerable: false });
|
|
24
|
+
return values;
|
|
25
|
+
}
|
|
26
|
+
/** True for an array marked by markForcedIn */
|
|
27
|
+
function isForcedIn(value) {
|
|
28
|
+
return Array.isArray(value) && value[FORCED_IN] === true;
|
|
29
|
+
}
|
|
17
30
|
const hasField = (obj, fieldName) => {
|
|
18
31
|
return Object.hasOwn(obj, fieldName);
|
|
19
32
|
};
|
|
@@ -119,6 +132,10 @@ function parseIndexFilter(filter, indexMap) {
|
|
|
119
132
|
const allFieldsPresent = rFields.every((field) => Object.hasOwn(filter, field));
|
|
120
133
|
if (!allFieldsPresent)
|
|
121
134
|
continue;
|
|
135
|
+
// A forced-view array (IN list) cannot be a key condition: joined it would query one bogus key.
|
|
136
|
+
// It stays in the filter expression as an IN condition. Other arrays keep the joined index value.
|
|
137
|
+
if ([...rFields, sortKeyField].some((field) => field && isForcedIn(filter[field])))
|
|
138
|
+
continue;
|
|
122
139
|
const hasSortField = !!sortKeyField && Object.hasOwn(filter, sortKeyField);
|
|
123
140
|
const bestIndexInfo = bestMatch ? indexMap.get(bestMatch.indexName) : undefined;
|
|
124
141
|
const bestHasSortField = !!bestIndexInfo?.sortKeyField && Object.hasOwn(filter, bestIndexInfo.sortKeyField);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reflection.util.js","sourceRoot":"","sources":["../../src/utils/reflection.util.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangedField, DynamoIndexMap, Filter, InclusionMode, TraceChange } from \"@chinggis/types\";\nimport { parseFilter } from \"./http/http.util\";\nimport { extractChangedSnippet } from \"./string.util\";\n\nexport const hasField = (obj: object, fieldName: string): boolean => {\n return Object.hasOwn(obj, fieldName);\n};\n\nexport function isMethodeHasKeyword(methodName: string, keywords: string[]): boolean {\n if (!methodName) return false;\n return keywords.some((keyword) => methodName.toLowerCase().includes(keyword));\n}\n\nexport function handleRangeFilters(filter: Filter): Filter {\n // Use regex to match keys like ageMin, ageMax, tempFrom, etc.\n const rangeFilters: any[] = [];\n const rangeFieldMap: Record<string, { minValue?: any; maxValue?: any }> = {};\n // Suffix mapping\n const minSuffixes = [\"Min\", \"From\", \"Start\"];\n const maxSuffixes = [\"Max\", \"To\", \"End\"];\n const suffixToType: Record<string, \"minValue\" | \"maxValue\"> = {};\n for (const s of minSuffixes) {\n suffixToType[s] = \"minValue\";\n }\n for (const s of maxSuffixes) {\n suffixToType[s] = \"maxValue\";\n }\n // Build regex: (field)(Min|Max|From|To|Start|End)\n const suffixPattern = [...minSuffixes, ...maxSuffixes].join(\"|\");\n const regex = new RegExp(`^(.*)(${suffixPattern})$`);\n\n for (const key of Object.keys(filter)) {\n const match = regex.exec(key); // <- use exec instead of match\n if (match) {\n const fieldName = match[1];\n const suffix = match[2];\n const type = suffixToType[suffix];\n if (!rangeFieldMap[fieldName]) rangeFieldMap[fieldName] = {};\n rangeFieldMap[fieldName][type] = filter[key];\n }\n }\n\n // Remove the original min/max keys from filter and build rangeFilters\n for (const fieldName in rangeFieldMap) {\n const { minValue, maxValue } = rangeFieldMap[fieldName];\n if (minValue !== undefined || maxValue !== undefined) {\n rangeFilters.push({ fieldName, minValue, maxValue });\n for (const suffix of [...minSuffixes, ...maxSuffixes]) {\n delete filter[`${fieldName}${suffix}`];\n }\n }\n }\n\n if (rangeFilters.length > 0) {\n filter.rangeFilters = rangeFilters;\n }\n\n return filter;\n}\n\nfunction handleOperatorRangeFilters(filter: Filter): Filter {\n const rangeFilters = [...(filter.rangeFilters ?? [])];\n const operatorRegex = /^(.*)__(gte|lte|gt|lt)$/;\n const rangeFieldMap = new Map<\n string,\n {\n fieldName: string;\n minValue?: any;\n maxValue?: any;\n minExclude?: boolean;\n maxExclude?: boolean;\n }\n >();\n\n for (const existing of rangeFilters) {\n rangeFieldMap.set(existing.fieldName, { ...existing });\n }\n\n for (const [key, value] of Object.entries(filter)) {\n const match = operatorRegex.exec(key);\n if (!match) continue;\n\n const [, fieldName, operator] = match;\n const rangeFilter = rangeFieldMap.get(fieldName) ?? { fieldName };\n\n if (operator === \"gte\") {\n rangeFilter.minValue = value;\n rangeFilter.minExclude = false;\n } else if (operator === \"gt\") {\n rangeFilter.minValue = value;\n rangeFilter.minExclude = true;\n } else if (operator === \"lte\") {\n rangeFilter.maxValue = value;\n rangeFilter.maxExclude = false;\n } else if (operator === \"lt\") {\n rangeFilter.maxValue = value;\n rangeFilter.maxExclude = true;\n }\n\n rangeFieldMap.set(fieldName, rangeFilter);\n delete filter[key];\n }\n\n if (rangeFieldMap.size > 0) {\n filter.rangeFilters = Array.from(rangeFieldMap.values());\n }\n\n return filter;\n}\n\nexport function parseIndexFilter(filter: Filter | string, indexMap?: DynamoIndexMap): Filter {\n if (!filter) return undefined;\n if (typeof filter === \"string\") {\n filter = parseFilter(filter);\n }\n let result: Filter = { ...filter };\n\n result = handleRangeFilters(result);\n result = handleOperatorRangeFilters(result);\n\n if (indexMap === undefined || !indexMap || (filter?.indexName && filter?.indexValue)) return result;\n\n let bestMatch: {\n indexName: string;\n rFields: string[];\n fieldSeparator?: string;\n } | null = null;\n\n for (const [indexName, { rFields, fieldSeparator, sortKeyField }] of indexMap.entries()) {\n const allFieldsPresent = rFields.every((field) => Object.hasOwn(filter, field));\n if (!allFieldsPresent) continue;\n\n const hasSortField = !!sortKeyField && Object.hasOwn(filter, sortKeyField);\n const bestIndexInfo = bestMatch ? indexMap.get(bestMatch.indexName) : undefined;\n const bestHasSortField = !!bestIndexInfo?.sortKeyField && Object.hasOwn(filter, bestIndexInfo.sortKeyField);\n\n if (\n !bestMatch ||\n rFields.length > bestMatch.rFields.length ||\n (rFields.length === bestMatch.rFields.length && hasSortField && !bestHasSortField)\n ) {\n bestMatch = { indexName, rFields, fieldSeparator: fieldSeparator };\n }\n }\n\n if (bestMatch) {\n const indexValues = bestMatch.rFields.map((field) => filter[field]);\n result.indexName = bestMatch.indexName;\n result.indexValue = indexValues.join(bestMatch.fieldSeparator ?? \"\");\n\n // rFields-ийг result-аас хасна\n for (const field of bestMatch.rFields) {\n delete result[field];\n }\n }\n\n return result;\n}\n\nexport function excludeKeys(obj: Record<string, any>, keysToExclude: string[]) {\n if (!obj) return obj;\n const result: Record<string, any> = {};\n for (const key in obj) {\n if (!keysToExclude.includes(key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/*\n * remove all fields except the ones in the fieldName array\n * */\nexport const fieldsInclude = (object: any, fieldName: string[]): any => {\n if (typeof object !== \"object\" || object === null) {\n throw new Error(\"Input must be an object\");\n }\n\n // Create a new object with only the specified fields\n return fieldName.reduce(\n (result, field) => {\n if (field in object) {\n result[field] = object[field];\n }\n return result;\n },\n {} as Record<string, any>,\n );\n};\n\nexport const copyField = (object: any, fromFieldName: string, toFieldName: string): any => {\n if (typeof object !== \"object\" || object === null) throw new Error(\"Input must be an object\");\n object[toFieldName] = object[fromFieldName];\n};\n\n/**\n * Removes or keeps specific fields from a list of objects.\n *\n * @param dataList - Array of objects to process\n * @param includes - Optional list of fields to include (whitelist)\n * @param excludes - Optional list of fields to exclude (blacklist)\n * @returns New array of objects with filtered fields\n */\nexport function removeFields<T extends object>(dataList: T[], includes?: string[], excludes?: string[]): Partial<T>[] {\n if (!includes && !excludes) return dataList;\n\n return dataList.map((item) => {\n // If includes are provided, only keep those fields\n if (includes && includes.length > 0) {\n const included: Partial<T> = {};\n for (const path of includes) {\n const value = getByPath(item, path);\n if (value !== undefined) {\n setByPath(included, path, value);\n }\n }\n\n return included;\n }\n\n // If excludes are provided, remove those fields\n if (excludes && excludes.length > 0) {\n const cloned: Partial<T> = { ...item };\n\n for (const path of excludes) {\n deleteByPath(cloned, path);\n }\n\n return cloned;\n }\n\n return item;\n });\n}\n\nfunction getByPath(obj: any, path: string) {\n return path.split(\".\").reduce((acc, key) => acc?.[key], obj);\n}\n\nfunction setByPath(obj: any, path: string, value: any) {\n const keys = path.split(\".\");\n let current = obj;\n\n keys.forEach((key, index) => {\n if (index === keys.length - 1) {\n current[key] = value;\n } else {\n current[key] ??= {};\n current = current[key];\n }\n });\n}\n\nfunction deleteByPath(obj: any, path: string) {\n const keys = path.split(\".\");\n const lastKey = keys.pop();\n const parent = keys.reduce((acc, key) => acc?.[key], obj);\n\n if (parent && lastKey) {\n delete parent[lastKey];\n }\n}\n\n/**\n * Recursively checks if an object contains any meaningful content.\n * - Returns false for null, undefined, empty objects, or empty arrays.\n * - Returns true for primitive values (string, number, boolean, etc.).\n * - Recursively checks arrays and nested objects to determine if at least one value is meaningful.\n *\n * This ensures that objects like { bool: {} } are considered empty,\n * and only objects with actual values (e.g., { bool: { must: [...] } }) are considered meaningful.\n */\nexport function hasContent(obj: any): boolean {\n if (obj == null) return false; // null/undefined\n if (typeof obj !== \"object\") return true; // primitive values are meaningful\n if (Array.isArray(obj)) return obj.some(hasContent);\n\n const values = Object.values(obj);\n if (values.length === 0) return false; // empty object\n\n // recursively check if any value is meaningful\n return values.some(hasContent);\n}\n\n/**\n * Recursively removes all \"empty\" fields from an object.\n *\n * Definition of empty:\n * - null or undefined\n * - empty objects {}\n * - empty arrays []\n *\n * Primitives (number, string, boolean) and non-empty objects/arrays are preserved.\n *\n * Usage:\n * ```ts\n * const input = { a: 1, b: null, c: {}, d: [], e: { f: null, g: { h: [] }, i: 2 }, j: [null, {}, 3] };\n * const cleaned = removeEmptyFields(input);\n * // cleaned => { a: 1, e: { i: 2 }, j: [3] }\n * ```\n *\n * This is especially useful when preparing Elasticsearch/OpenSearch queries:\n * - Removes empty objects like `{ bool: {} }`\n * - Removes empty arrays in filters\n * - Ensures the `body` only contains meaningful fields before sending\n */\nexport function removeEmptyFields(obj: any): any {\n if (obj == null) return undefined; // null or undefined -> remove\n if (typeof obj !== \"object\") return obj; // primitives remain\n\n if (Array.isArray(obj)) {\n const arr = obj\n .map(removeEmptyFields) // recursive\n .filter((v) => v !== undefined); // remove empty elements\n return arr.length > 0 ? arr : undefined;\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n const cleaned = removeEmptyFields(value);\n if (cleaned !== undefined) {\n result[key] = cleaned;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nexport function computeChangedFields<T extends Record<string, any>>(\n oldItem: Partial<T>,\n newItem: Partial<T>,\n traceChange: TraceChange,\n): ChangedField[] {\n const diff = diffObjects(oldItem as Record<string, any>, newItem as Record<string, any>);\n const flattened = flattenDiff(diff);\n\n console.log(\"flattened\", flattened);\n\n return traceChange.mode === InclusionMode.INCLUDE\n ? flattened.filter((f) => traceChange.fields.includes(f.fieldName))\n : flattened.filter((f) => !traceChange.fields.includes(f.fieldName));\n}\n\n/**\n * Flatten nested diff object into a ChangedField[] list\n * e.g. { address: { city: { old, new } } } => [{ fieldName: \"address.city\", oldValue, newValue }]\n */\nfunction flattenDiff(diff: Record<string, any>, prefix = \"\"): ChangedField[] {\n const changes: ChangedField[] = [];\n\n for (const [key, value] of Object.entries(diff)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === \"object\" && \"old\" in value && \"new\" in value) {\n // direct primitive/string diff\n changes.push({\n fieldName: fullKey,\n oldValue: value.old,\n newValue: JSON.stringify(value.new),\n });\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // nested object diff (recursive)\n changes.push(...flattenDiff(value, fullKey));\n } else {\n // fallback: primitive or unexpected shape\n changes.push({\n fieldName: fullKey,\n oldValue: value?.old ?? null,\n newValue: JSON.stringify(value?.new) ?? null,\n });\n }\n }\n\n return changes;\n}\n\n/* helpers */\nfunction isObject(v: any): v is Record<string, any> {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\nfunction isPrimitive(v: any): boolean {\n return v === null || (typeof v !== \"object\" && typeof v !== \"function\");\n}\nfunction stableStringify(value: any): string {\n if (isPrimitive(value)) return JSON.stringify(value);\n if (Array.isArray(value)) return \"[\" + value.map((v) => stableStringify(v)).join(\",\") + \"]\";\n // object: sort keys\n const keys = Object.keys(value).sort();\n return \"{\" + keys.map((k) => JSON.stringify(k) + \":\" + stableStringify(value[k])).join(\",\") + \"}\";\n}\nfunction deepEqualIgnoreKeyOrder(a: any, b: any): boolean {\n return stableStringify(a) === stableStringify(b);\n}\n\n/**\n * Only iterate keys from newObj (so fields not provided in the update are ignored).\n * Skip keys where newVal === undefined (treat as \"not provided\" -> no change recorded).\n */\nfunction diffObjects(oldObj: Record<string, any>, newObj: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n const skipKeys = new Set([\"history\", \"createdAt\", \"updatedAt\"]);\n\n for (const key of Object.keys(newObj)) {\n if (skipKeys.has(key)) continue;\n\n const newVal = newObj[key];\n\n // if caller didn't supply the key (explicitly undefined) -> skip\n if (newVal === undefined) continue;\n\n const oldVal = oldObj[key];\n\n // equal -> skip\n if (deepEqualIgnoreKeyOrder(oldVal, newVal)) continue;\n\n // both objects -> nested diff\n if (isObject(oldVal) && isObject(newVal)) {\n const nested = diffObjects(oldVal, newVal);\n if (Object.keys(nested).length > 0) result[key] = nested;\n continue;\n }\n\n // both arrays -> array diff\n if (Array.isArray(oldVal) && Array.isArray(newVal)) {\n const arrDiff = diffArrays(oldVal, newVal);\n if (arrDiff && Object.keys(arrDiff).length > 0) result[key] = arrDiff;\n continue;\n }\n\n // strings: summarize long text changes\n if (typeof oldVal === \"string\" && typeof newVal === \"string\") {\n const oldSnippet = oldVal.length > 200 ? extractChangedSnippet(oldVal, newVal) : oldVal;\n const newSnippet = newVal.length > 200 ? extractChangedSnippet(newVal, oldVal) : newVal;\n result[key] = { old: oldSnippet, new: newSnippet };\n continue;\n }\n\n // fallback: primitive change or type change\n result[key] = { old: oldVal, new: newVal };\n }\n\n return result;\n}\n\n/** array diff similar to earlier, but kept compact */\nfunction diffArrays(oldArr: any[], newArr: any[]): any {\n if (deepEqualIgnoreKeyOrder(oldArr, newArr)) return {};\n\n const allPrimitives = oldArr.every(isPrimitive) && newArr.every(isPrimitive);\n if (allPrimitives) {\n const removed = oldArr.filter((x) => !newArr.includes(x));\n const added = newArr.filter((x) => !oldArr.includes(x));\n const out: any = {};\n if (added.length) out.added = added;\n if (removed.length) out.removed = removed;\n return out;\n }\n\n // complex arrays: index-wise diff\n const maxLen = Math.max(oldArr.length, newArr.length);\n const idxDiffs: Record<string, any> = {};\n for (let i = 0; i < maxLen; i++) {\n const a = oldArr[i];\n const b = newArr[i];\n if (deepEqualIgnoreKeyOrder(a, b)) continue;\n\n if (isObject(a) && isObject(b)) {\n const nested = diffObjects(a, b);\n if (Object.keys(nested).length > 0) idxDiffs[i] = nested;\n continue;\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n const nestedArr = diffArrays(a, b);\n if (Object.keys(nestedArr || {}).length > 0) idxDiffs[i] = nestedArr;\n continue;\n }\n\n idxDiffs[i] = { old: a, new: b };\n }\n\n if (Object.keys(idxDiffs).length === 0) {\n return { oldLength: oldArr.length, newLength: newArr.length };\n }\n return idxDiffs;\n}\n\n/**\n * Returns a shallow copy of the object, removing any keys with:\n * - undefined\n * - null\n * - empty objects\n * - empty arrays\n *\n * Only the top-level keys are processed; nested objects are not cleaned.\n *\n * @template T\n * @param {T} obj - The input object to clean\n * @returns {Partial<T>} A new object containing only meaningful values\n */\nexport function pickDefined<T extends Record<string, any>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(\n ([, value]) =>\n value !== undefined &&\n value !== null &&\n !(typeof value === \"object\" && !Array.isArray(value) && Object.keys(value).length === 0) &&\n !(Array.isArray(value) && value.length === 0),\n ),\n ) as Partial<T>;\n}\n\n/**\n * Recursively removes undefined, null, empty objects, and empty arrays\n * from a nested object or array structure.\n *\n * This function returns a new object or array where all irrelevant or empty\n * fields have been stripped. Primitive values (numbers, strings, booleans)\n * are preserved.\n *\n * @template T\n * @param {T} value - The object, array, or primitive value to clean\n * @returns {Partial<T> | undefined} A cleaned version of the input or undefined if empty\n */\nexport function pickDefinedDeep<T>(value: T): Partial<T> {\n if (value === undefined || value === null) {\n return undefined as any;\n }\n\n if (Array.isArray(value)) {\n const cleaned = value.map(pickDefinedDeep).filter((v) => v !== undefined);\n\n return cleaned.length > 0 ? (cleaned as any) : undefined;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(value)) {\n const cleaned = pickDefinedDeep(val);\n if (cleaned !== undefined) {\n result[key] = cleaned;\n }\n }\n\n return Object.keys(result).length > 0 ? (result as Partial<T>) : undefined;\n }\n\n // primitive (number, boolean, string, etc.)\n return value as Partial<T>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reflection.util.js","sourceRoot":"","sources":["../../src/utils/reflection.util.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmG;AACnG,gDAA+C;AAC/C,+CAAsD;AAEtD,+GAA+G;AAC/G,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAE3D,wFAAwF;AACxF,sBAAkD,MAAS;IACzD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+CAA+C;AAC/C,oBAA2B,KAAc;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAK,KAAa,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC;AACpE,CAAC;AAEM,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,SAAiB,EAAW,EAAE;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC,CAAC;AAFW,QAAA,QAAQ,GAAR,QAAQ,CAEnB;AAEF,6BAAoC,UAAkB,EAAE,QAAkB;IACxE,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,4BAAmC,MAAc;IAC/C,8DAA8D;IAC9D,MAAM,YAAY,GAAU,EAAE,CAAC;IAC/B,MAAM,aAAa,GAAuD,EAAE,CAAC;IAC7E,iBAAiB;IACjB,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,YAAY,GAA4C,EAAE,CAAC;IACjE,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,YAAY,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;IAC/B,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,YAAY,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;IAC/B,CAAC;IACD,kDAAkD;IAClD,MAAM,aAAa,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,SAAS,aAAa,IAAI,CAAC,CAAC;IAErD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,+BAA+B;QAC9D,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;gBAAE,aAAa,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YAC7D,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;QACtC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACxD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACrD,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YACrD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,WAAW,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;gBACtD,OAAO,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,0BAA0B,CAAC,MAAc;IAChD,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC;IACtD,MAAM,aAAa,GAAG,yBAAyB,CAAC;IAChD,MAAM,aAAa,GAAG,IAAI,GAAG,EAS1B,CAAC;IAEJ,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;QACpC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;QACtC,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QAElE,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC7B,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC;QACjC,CAAC;aAAM,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC7B,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC7B,WAAW,CAAC,UAAU,GAAG,IAAI,CAAC;QAChC,CAAC;aAAM,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC9B,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC7B,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC;QACjC,CAAC;aAAM,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC7B,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC;YAC7B,WAAW,CAAC,UAAU,GAAG,IAAI,CAAC;QAChC,CAAC;QAED,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,0BAAiC,MAAuB,EAAE,QAAyB;IACjF,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,GAAG,IAAA,uBAAW,EAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,MAAM,GAAW,EAAE,GAAG,MAAM,EAAE,CAAC;IAEnC,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,MAAM,EAAE,UAAU,CAAC;QAAE,OAAO,MAAM,CAAC;IAEpG,IAAI,SAAS,GAIF,IAAI,CAAC;IAEhB,KAAK,MAAM,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QACxF,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAChF,IAAI,CAAC,gBAAgB;YAAE,SAAS;QAChC,gGAAgG;QAChG,kGAAkG;QAClG,IAAI,CAAC,GAAG,OAAO,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAAE,SAAS;QAE7F,MAAM,YAAY,GAAG,CAAC,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3E,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,MAAM,gBAAgB,GAAG,CAAC,CAAC,aAAa,EAAE,YAAY,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QAE5G,IACE,CAAC,SAAS;YACV,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM;YACzC,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,OAAO,CAAC,MAAM,IAAI,YAAY,IAAI,CAAC,gBAAgB,CAAC,EAClF,CAAC;YACD,SAAS,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;QACrE,CAAC;IACH,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;QACvC,MAAM,CAAC,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAErE,+BAA+B;QAC/B,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qBAA4B,GAAwB,EAAE,aAAuB;IAC3E,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;KAEK;AACE,MAAM,aAAa,GAAG,CAAC,MAAW,EAAE,SAAmB,EAAO,EAAE;IACrE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,qDAAqD;IACrD,OAAO,SAAS,CAAC,MAAM,CACrB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChB,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,EAAyB,CAC1B,CAAC;AACJ,CAAC,CAAC;AAfW,QAAA,aAAa,GAAb,aAAa,CAexB;AAEK,MAAM,SAAS,GAAG,CAAC,MAAW,EAAE,aAAqB,EAAE,WAAmB,EAAO,EAAE;IACxF,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC9F,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAC9C,CAAC,CAAC;AAHW,QAAA,SAAS,GAAT,SAAS,CAGpB;AAEF;;;;;;;GAOG;AACH,sBAA+C,QAAa,EAAE,QAAmB,EAAE,QAAmB;IACpG,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE5C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,mDAAmD;QACnD,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAe,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACxB,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,gDAAgD;QAChD,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,MAAM,GAAe,EAAE,GAAG,IAAI,EAAE,CAAC;YAEvC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC5B,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC7B,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,GAAQ,EAAE,IAAY;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,SAAS,CAAC,GAAQ,EAAE,IAAY,EAAE,KAAU;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,OAAO,GAAG,GAAG,CAAC;IAElB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QAC1B,IAAI,KAAK,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ,EAAE,IAAY;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAE1D,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,oBAA2B,GAAQ;IACjC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC,CAAC,iBAAiB;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,CAAC,kCAAkC;IAC5E,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,eAAe;IAEtD,+CAA+C;IAC/C,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,2BAAkC,GAAQ;IACxC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,CAAC,8BAA8B;IACjE,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,CAAC,oBAAoB;IAE7D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG;aACZ,GAAG,CAAC,iBAAiB,CAAC,CAAC,YAAY;aACnC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,wBAAwB;QAC3D,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,8BACE,OAAmB,EACnB,OAAmB,EACnB,WAAwB;IAExB,MAAM,IAAI,GAAG,WAAW,CAAC,OAA8B,EAAE,OAA8B,CAAC,CAAC;IACzF,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAEpC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAEpC,OAAO,WAAW,CAAC,IAAI,KAAK,qBAAa,CAAC,OAAO;QAC/C,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACnE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,IAAyB,EAAE,MAAM,GAAG,EAAE;IACzD,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAElD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;YAC3E,+BAA+B;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,OAAO;gBAClB,QAAQ,EAAE,KAAK,CAAC,GAAG;gBACnB,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC;aACpC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,iCAAiC;YACjC,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,OAAO;gBAClB,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,IAAI;gBAC5B,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,IAAI;aAC7C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,aAAa;AACb,SAAS,QAAQ,CAAC,CAAM;IACtB,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AACD,SAAS,WAAW,CAAC,CAAM;IACzB,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC;AAC1E,CAAC;AACD,SAAS,eAAe,CAAC,KAAU;IACjC,IAAI,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAC5F,oBAAoB;IACpB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACpG,CAAC;AACD,SAAS,uBAAuB,CAAC,CAAM,EAAE,CAAM;IAC7C,OAAO,eAAe,CAAC,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,MAA2B,EAAE,MAA2B;IAC3E,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAEhE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAEhC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3B,iEAAiE;QACjE,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS;QAEnC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3B,gBAAgB;QAChB,IAAI,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC;YAAE,SAAS;QAEtD,8BAA8B;QAC9B,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;YACzD,SAAS;QACX,CAAC;QAED,4BAA4B;QAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC3C,IAAI,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;YACtE,SAAS;QACX,CAAC;QAED,uCAAuC;QACvC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAA,mCAAqB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACxF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAA,mCAAqB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACxF,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;YACnD,SAAS;QACX,CAAC;QAED,4CAA4C;QAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,sDAAsD;AACtD,SAAS,UAAU,CAAC,MAAa,EAAE,MAAa;IAC9C,IAAI,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvD,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC7E,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,MAAM;YAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC;QACpC,IAAI,OAAO,CAAC,MAAM;YAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;QAC1C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,kCAAkC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,uBAAuB,CAAC,CAAC,EAAE,CAAC,CAAC;YAAE,SAAS;QAE5C,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACjC,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;YACzD,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;YACrE,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAChE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,qBAA2D,GAAM;IAC/D,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CACxB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CACZ,KAAK,KAAK,SAAS;QACnB,KAAK,KAAK,IAAI;QACd,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QACxF,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAChD,CACY,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,yBAAmC,KAAQ;IACzC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,SAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;QAE1E,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,OAAe,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAwB,EAAE,CAAC;QAEvC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,MAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,CAAC;IAED,4CAA4C;IAC5C,OAAO,KAAmB,CAAC;AAC7B,CAAC","sourcesContent":["import { ChangedField, DynamoIndexMap, Filter, InclusionMode, TraceChange } from \"@chinggis/types\";\nimport { parseFilter } from \"./http/http.util\";\nimport { extractChangedSnippet } from \"./string.util\";\n\n/** Marks an array that comes from a forced policy-view key (an IN list that must never become an index key) */\nconst FORCED_IN = Symbol.for(\"aws-service-stack.forcedIn\");\n\n/** Tags a forced-view array (non-enumerable, survives object spreads) and returns it */\nexport function markForcedIn<T extends unknown[]>(values: T): T {\n Object.defineProperty(values, FORCED_IN, { value: true, enumerable: false });\n return values;\n}\n\n/** True for an array marked by markForcedIn */\nexport function isForcedIn(value: unknown): boolean {\n return Array.isArray(value) && (value as any)[FORCED_IN] === true;\n}\n\nexport const hasField = (obj: object, fieldName: string): boolean => {\n return Object.hasOwn(obj, fieldName);\n};\n\nexport function isMethodeHasKeyword(methodName: string, keywords: string[]): boolean {\n if (!methodName) return false;\n return keywords.some((keyword) => methodName.toLowerCase().includes(keyword));\n}\n\nexport function handleRangeFilters(filter: Filter): Filter {\n // Use regex to match keys like ageMin, ageMax, tempFrom, etc.\n const rangeFilters: any[] = [];\n const rangeFieldMap: Record<string, { minValue?: any; maxValue?: any }> = {};\n // Suffix mapping\n const minSuffixes = [\"Min\", \"From\", \"Start\"];\n const maxSuffixes = [\"Max\", \"To\", \"End\"];\n const suffixToType: Record<string, \"minValue\" | \"maxValue\"> = {};\n for (const s of minSuffixes) {\n suffixToType[s] = \"minValue\";\n }\n for (const s of maxSuffixes) {\n suffixToType[s] = \"maxValue\";\n }\n // Build regex: (field)(Min|Max|From|To|Start|End)\n const suffixPattern = [...minSuffixes, ...maxSuffixes].join(\"|\");\n const regex = new RegExp(`^(.*)(${suffixPattern})$`);\n\n for (const key of Object.keys(filter)) {\n const match = regex.exec(key); // <- use exec instead of match\n if (match) {\n const fieldName = match[1];\n const suffix = match[2];\n const type = suffixToType[suffix];\n if (!rangeFieldMap[fieldName]) rangeFieldMap[fieldName] = {};\n rangeFieldMap[fieldName][type] = filter[key];\n }\n }\n\n // Remove the original min/max keys from filter and build rangeFilters\n for (const fieldName in rangeFieldMap) {\n const { minValue, maxValue } = rangeFieldMap[fieldName];\n if (minValue !== undefined || maxValue !== undefined) {\n rangeFilters.push({ fieldName, minValue, maxValue });\n for (const suffix of [...minSuffixes, ...maxSuffixes]) {\n delete filter[`${fieldName}${suffix}`];\n }\n }\n }\n\n if (rangeFilters.length > 0) {\n filter.rangeFilters = rangeFilters;\n }\n\n return filter;\n}\n\nfunction handleOperatorRangeFilters(filter: Filter): Filter {\n const rangeFilters = [...(filter.rangeFilters ?? [])];\n const operatorRegex = /^(.*)__(gte|lte|gt|lt)$/;\n const rangeFieldMap = new Map<\n string,\n {\n fieldName: string;\n minValue?: any;\n maxValue?: any;\n minExclude?: boolean;\n maxExclude?: boolean;\n }\n >();\n\n for (const existing of rangeFilters) {\n rangeFieldMap.set(existing.fieldName, { ...existing });\n }\n\n for (const [key, value] of Object.entries(filter)) {\n const match = operatorRegex.exec(key);\n if (!match) continue;\n\n const [, fieldName, operator] = match;\n const rangeFilter = rangeFieldMap.get(fieldName) ?? { fieldName };\n\n if (operator === \"gte\") {\n rangeFilter.minValue = value;\n rangeFilter.minExclude = false;\n } else if (operator === \"gt\") {\n rangeFilter.minValue = value;\n rangeFilter.minExclude = true;\n } else if (operator === \"lte\") {\n rangeFilter.maxValue = value;\n rangeFilter.maxExclude = false;\n } else if (operator === \"lt\") {\n rangeFilter.maxValue = value;\n rangeFilter.maxExclude = true;\n }\n\n rangeFieldMap.set(fieldName, rangeFilter);\n delete filter[key];\n }\n\n if (rangeFieldMap.size > 0) {\n filter.rangeFilters = Array.from(rangeFieldMap.values());\n }\n\n return filter;\n}\n\nexport function parseIndexFilter(filter: Filter | string, indexMap?: DynamoIndexMap): Filter {\n if (!filter) return undefined;\n if (typeof filter === \"string\") {\n filter = parseFilter(filter);\n }\n let result: Filter = { ...filter };\n\n result = handleRangeFilters(result);\n result = handleOperatorRangeFilters(result);\n\n if (indexMap === undefined || !indexMap || (filter?.indexName && filter?.indexValue)) return result;\n\n let bestMatch: {\n indexName: string;\n rFields: string[];\n fieldSeparator?: string;\n } | null = null;\n\n for (const [indexName, { rFields, fieldSeparator, sortKeyField }] of indexMap.entries()) {\n const allFieldsPresent = rFields.every((field) => Object.hasOwn(filter, field));\n if (!allFieldsPresent) continue;\n // A forced-view array (IN list) cannot be a key condition: joined it would query one bogus key.\n // It stays in the filter expression as an IN condition. Other arrays keep the joined index value.\n if ([...rFields, sortKeyField].some((field) => field && isForcedIn(filter[field]))) continue;\n\n const hasSortField = !!sortKeyField && Object.hasOwn(filter, sortKeyField);\n const bestIndexInfo = bestMatch ? indexMap.get(bestMatch.indexName) : undefined;\n const bestHasSortField = !!bestIndexInfo?.sortKeyField && Object.hasOwn(filter, bestIndexInfo.sortKeyField);\n\n if (\n !bestMatch ||\n rFields.length > bestMatch.rFields.length ||\n (rFields.length === bestMatch.rFields.length && hasSortField && !bestHasSortField)\n ) {\n bestMatch = { indexName, rFields, fieldSeparator: fieldSeparator };\n }\n }\n\n if (bestMatch) {\n const indexValues = bestMatch.rFields.map((field) => filter[field]);\n result.indexName = bestMatch.indexName;\n result.indexValue = indexValues.join(bestMatch.fieldSeparator ?? \"\");\n\n // rFields-ийг result-аас хасна\n for (const field of bestMatch.rFields) {\n delete result[field];\n }\n }\n\n return result;\n}\n\nexport function excludeKeys(obj: Record<string, any>, keysToExclude: string[]) {\n if (!obj) return obj;\n const result: Record<string, any> = {};\n for (const key in obj) {\n if (!keysToExclude.includes(key)) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/*\n * remove all fields except the ones in the fieldName array\n * */\nexport const fieldsInclude = (object: any, fieldName: string[]): any => {\n if (typeof object !== \"object\" || object === null) {\n throw new Error(\"Input must be an object\");\n }\n\n // Create a new object with only the specified fields\n return fieldName.reduce(\n (result, field) => {\n if (field in object) {\n result[field] = object[field];\n }\n return result;\n },\n {} as Record<string, any>,\n );\n};\n\nexport const copyField = (object: any, fromFieldName: string, toFieldName: string): any => {\n if (typeof object !== \"object\" || object === null) throw new Error(\"Input must be an object\");\n object[toFieldName] = object[fromFieldName];\n};\n\n/**\n * Removes or keeps specific fields from a list of objects.\n *\n * @param dataList - Array of objects to process\n * @param includes - Optional list of fields to include (whitelist)\n * @param excludes - Optional list of fields to exclude (blacklist)\n * @returns New array of objects with filtered fields\n */\nexport function removeFields<T extends object>(dataList: T[], includes?: string[], excludes?: string[]): Partial<T>[] {\n if (!includes && !excludes) return dataList;\n\n return dataList.map((item) => {\n // If includes are provided, only keep those fields\n if (includes && includes.length > 0) {\n const included: Partial<T> = {};\n for (const path of includes) {\n const value = getByPath(item, path);\n if (value !== undefined) {\n setByPath(included, path, value);\n }\n }\n\n return included;\n }\n\n // If excludes are provided, remove those fields\n if (excludes && excludes.length > 0) {\n const cloned: Partial<T> = { ...item };\n\n for (const path of excludes) {\n deleteByPath(cloned, path);\n }\n\n return cloned;\n }\n\n return item;\n });\n}\n\nfunction getByPath(obj: any, path: string) {\n return path.split(\".\").reduce((acc, key) => acc?.[key], obj);\n}\n\nfunction setByPath(obj: any, path: string, value: any) {\n const keys = path.split(\".\");\n let current = obj;\n\n keys.forEach((key, index) => {\n if (index === keys.length - 1) {\n current[key] = value;\n } else {\n current[key] ??= {};\n current = current[key];\n }\n });\n}\n\nfunction deleteByPath(obj: any, path: string) {\n const keys = path.split(\".\");\n const lastKey = keys.pop();\n const parent = keys.reduce((acc, key) => acc?.[key], obj);\n\n if (parent && lastKey) {\n delete parent[lastKey];\n }\n}\n\n/**\n * Recursively checks if an object contains any meaningful content.\n * - Returns false for null, undefined, empty objects, or empty arrays.\n * - Returns true for primitive values (string, number, boolean, etc.).\n * - Recursively checks arrays and nested objects to determine if at least one value is meaningful.\n *\n * This ensures that objects like { bool: {} } are considered empty,\n * and only objects with actual values (e.g., { bool: { must: [...] } }) are considered meaningful.\n */\nexport function hasContent(obj: any): boolean {\n if (obj == null) return false; // null/undefined\n if (typeof obj !== \"object\") return true; // primitive values are meaningful\n if (Array.isArray(obj)) return obj.some(hasContent);\n\n const values = Object.values(obj);\n if (values.length === 0) return false; // empty object\n\n // recursively check if any value is meaningful\n return values.some(hasContent);\n}\n\n/**\n * Recursively removes all \"empty\" fields from an object.\n *\n * Definition of empty:\n * - null or undefined\n * - empty objects {}\n * - empty arrays []\n *\n * Primitives (number, string, boolean) and non-empty objects/arrays are preserved.\n *\n * Usage:\n * ```ts\n * const input = { a: 1, b: null, c: {}, d: [], e: { f: null, g: { h: [] }, i: 2 }, j: [null, {}, 3] };\n * const cleaned = removeEmptyFields(input);\n * // cleaned => { a: 1, e: { i: 2 }, j: [3] }\n * ```\n *\n * This is especially useful when preparing Elasticsearch/OpenSearch queries:\n * - Removes empty objects like `{ bool: {} }`\n * - Removes empty arrays in filters\n * - Ensures the `body` only contains meaningful fields before sending\n */\nexport function removeEmptyFields(obj: any): any {\n if (obj == null) return undefined; // null or undefined -> remove\n if (typeof obj !== \"object\") return obj; // primitives remain\n\n if (Array.isArray(obj)) {\n const arr = obj\n .map(removeEmptyFields) // recursive\n .filter((v) => v !== undefined); // remove empty elements\n return arr.length > 0 ? arr : undefined;\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n const cleaned = removeEmptyFields(value);\n if (cleaned !== undefined) {\n result[key] = cleaned;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nexport function computeChangedFields<T extends Record<string, any>>(\n oldItem: Partial<T>,\n newItem: Partial<T>,\n traceChange: TraceChange,\n): ChangedField[] {\n const diff = diffObjects(oldItem as Record<string, any>, newItem as Record<string, any>);\n const flattened = flattenDiff(diff);\n\n console.log(\"flattened\", flattened);\n\n return traceChange.mode === InclusionMode.INCLUDE\n ? flattened.filter((f) => traceChange.fields.includes(f.fieldName))\n : flattened.filter((f) => !traceChange.fields.includes(f.fieldName));\n}\n\n/**\n * Flatten nested diff object into a ChangedField[] list\n * e.g. { address: { city: { old, new } } } => [{ fieldName: \"address.city\", oldValue, newValue }]\n */\nfunction flattenDiff(diff: Record<string, any>, prefix = \"\"): ChangedField[] {\n const changes: ChangedField[] = [];\n\n for (const [key, value] of Object.entries(diff)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === \"object\" && \"old\" in value && \"new\" in value) {\n // direct primitive/string diff\n changes.push({\n fieldName: fullKey,\n oldValue: value.old,\n newValue: JSON.stringify(value.new),\n });\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // nested object diff (recursive)\n changes.push(...flattenDiff(value, fullKey));\n } else {\n // fallback: primitive or unexpected shape\n changes.push({\n fieldName: fullKey,\n oldValue: value?.old ?? null,\n newValue: JSON.stringify(value?.new) ?? null,\n });\n }\n }\n\n return changes;\n}\n\n/* helpers */\nfunction isObject(v: any): v is Record<string, any> {\n return v !== null && typeof v === \"object\" && !Array.isArray(v);\n}\nfunction isPrimitive(v: any): boolean {\n return v === null || (typeof v !== \"object\" && typeof v !== \"function\");\n}\nfunction stableStringify(value: any): string {\n if (isPrimitive(value)) return JSON.stringify(value);\n if (Array.isArray(value)) return \"[\" + value.map((v) => stableStringify(v)).join(\",\") + \"]\";\n // object: sort keys\n const keys = Object.keys(value).sort();\n return \"{\" + keys.map((k) => JSON.stringify(k) + \":\" + stableStringify(value[k])).join(\",\") + \"}\";\n}\nfunction deepEqualIgnoreKeyOrder(a: any, b: any): boolean {\n return stableStringify(a) === stableStringify(b);\n}\n\n/**\n * Only iterate keys from newObj (so fields not provided in the update are ignored).\n * Skip keys where newVal === undefined (treat as \"not provided\" -> no change recorded).\n */\nfunction diffObjects(oldObj: Record<string, any>, newObj: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n const skipKeys = new Set([\"history\", \"createdAt\", \"updatedAt\"]);\n\n for (const key of Object.keys(newObj)) {\n if (skipKeys.has(key)) continue;\n\n const newVal = newObj[key];\n\n // if caller didn't supply the key (explicitly undefined) -> skip\n if (newVal === undefined) continue;\n\n const oldVal = oldObj[key];\n\n // equal -> skip\n if (deepEqualIgnoreKeyOrder(oldVal, newVal)) continue;\n\n // both objects -> nested diff\n if (isObject(oldVal) && isObject(newVal)) {\n const nested = diffObjects(oldVal, newVal);\n if (Object.keys(nested).length > 0) result[key] = nested;\n continue;\n }\n\n // both arrays -> array diff\n if (Array.isArray(oldVal) && Array.isArray(newVal)) {\n const arrDiff = diffArrays(oldVal, newVal);\n if (arrDiff && Object.keys(arrDiff).length > 0) result[key] = arrDiff;\n continue;\n }\n\n // strings: summarize long text changes\n if (typeof oldVal === \"string\" && typeof newVal === \"string\") {\n const oldSnippet = oldVal.length > 200 ? extractChangedSnippet(oldVal, newVal) : oldVal;\n const newSnippet = newVal.length > 200 ? extractChangedSnippet(newVal, oldVal) : newVal;\n result[key] = { old: oldSnippet, new: newSnippet };\n continue;\n }\n\n // fallback: primitive change or type change\n result[key] = { old: oldVal, new: newVal };\n }\n\n return result;\n}\n\n/** array diff similar to earlier, but kept compact */\nfunction diffArrays(oldArr: any[], newArr: any[]): any {\n if (deepEqualIgnoreKeyOrder(oldArr, newArr)) return {};\n\n const allPrimitives = oldArr.every(isPrimitive) && newArr.every(isPrimitive);\n if (allPrimitives) {\n const removed = oldArr.filter((x) => !newArr.includes(x));\n const added = newArr.filter((x) => !oldArr.includes(x));\n const out: any = {};\n if (added.length) out.added = added;\n if (removed.length) out.removed = removed;\n return out;\n }\n\n // complex arrays: index-wise diff\n const maxLen = Math.max(oldArr.length, newArr.length);\n const idxDiffs: Record<string, any> = {};\n for (let i = 0; i < maxLen; i++) {\n const a = oldArr[i];\n const b = newArr[i];\n if (deepEqualIgnoreKeyOrder(a, b)) continue;\n\n if (isObject(a) && isObject(b)) {\n const nested = diffObjects(a, b);\n if (Object.keys(nested).length > 0) idxDiffs[i] = nested;\n continue;\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n const nestedArr = diffArrays(a, b);\n if (Object.keys(nestedArr || {}).length > 0) idxDiffs[i] = nestedArr;\n continue;\n }\n\n idxDiffs[i] = { old: a, new: b };\n }\n\n if (Object.keys(idxDiffs).length === 0) {\n return { oldLength: oldArr.length, newLength: newArr.length };\n }\n return idxDiffs;\n}\n\n/**\n * Returns a shallow copy of the object, removing any keys with:\n * - undefined\n * - null\n * - empty objects\n * - empty arrays\n *\n * Only the top-level keys are processed; nested objects are not cleaned.\n *\n * @template T\n * @param {T} obj - The input object to clean\n * @returns {Partial<T>} A new object containing only meaningful values\n */\nexport function pickDefined<T extends Record<string, any>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(\n ([, value]) =>\n value !== undefined &&\n value !== null &&\n !(typeof value === \"object\" && !Array.isArray(value) && Object.keys(value).length === 0) &&\n !(Array.isArray(value) && value.length === 0),\n ),\n ) as Partial<T>;\n}\n\n/**\n * Recursively removes undefined, null, empty objects, and empty arrays\n * from a nested object or array structure.\n *\n * This function returns a new object or array where all irrelevant or empty\n * fields have been stripped. Primitive values (numbers, strings, booleans)\n * are preserved.\n *\n * @template T\n * @param {T} value - The object, array, or primitive value to clean\n * @returns {Partial<T> | undefined} A cleaned version of the input or undefined if empty\n */\nexport function pickDefinedDeep<T>(value: T): Partial<T> {\n if (value === undefined || value === null) {\n return undefined as any;\n }\n\n if (Array.isArray(value)) {\n const cleaned = value.map(pickDefinedDeep).filter((v) => v !== undefined);\n\n return cleaned.length > 0 ? (cleaned as any) : undefined;\n }\n\n if (typeof value === \"object\") {\n const result: Record<string, any> = {};\n\n for (const [key, val] of Object.entries(value)) {\n const cleaned = pickDefinedDeep(val);\n if (cleaned !== undefined) {\n result[key] = cleaned;\n }\n }\n\n return Object.keys(result).length > 0 ? (result as Partial<T>) : undefined;\n }\n\n // primitive (number, boolean, string, etc.)\n return value as Partial<T>;\n}\n"]}
|