@lenne.tech/nest-server 11.27.5 → 11.27.7
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/.claude/rules/architecture.md +66 -0
- package/.claude/rules/better-auth.md +88 -2
- package/.claude/rules/configurable-features.md +2 -2
- package/.claude/rules/package-management.md +23 -14
- package/.claude/rules/testing.md +27 -9
- package/CLAUDE.md +12 -4
- package/FRAMEWORK-API.md +1 -1
- package/bin/migrate.js +84 -25
- package/dist/core/common/decorators/restricted.decorator.d.ts +4 -4
- package/dist/core/common/decorators/restricted.decorator.js +21 -22
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/helpers/clone.helper.d.ts +6 -0
- package/dist/core/common/helpers/clone.helper.js +67 -0
- package/dist/core/common/helpers/clone.helper.js.map +1 -0
- package/dist/core/common/helpers/cookies.helper.d.ts +1 -0
- package/dist/core/common/helpers/cookies.helper.js +33 -16
- package/dist/core/common/helpers/cookies.helper.js.map +1 -1
- package/dist/core/common/helpers/db.helper.d.ts +2 -14
- package/dist/core/common/helpers/db.helper.js +13 -106
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/id.helper.d.ts +15 -0
- package/dist/core/common/helpers/id.helper.js +104 -0
- package/dist/core/common/helpers/id.helper.js.map +1 -0
- package/dist/core/common/helpers/input.helper.d.ts +1 -6
- package/dist/core/common/helpers/input.helper.js +11 -70
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/inputs/combined-filter.input.d.ts +1 -12
- package/dist/core/common/inputs/combined-filter.input.js +2 -51
- package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
- package/dist/core/common/inputs/filter.input.d.ts +10 -1
- package/dist/core/common/inputs/filter.input.js +40 -5
- package/dist/core/common/inputs/filter.input.js.map +1 -1
- package/dist/core/common/services/config.service.js +5 -5
- package/dist/core/common/services/config.service.js.map +1 -1
- package/dist/core/modules/ai/core-ai.constants.d.ts +22 -0
- package/dist/core/modules/ai/core-ai.constants.js +26 -0
- package/dist/core/modules/ai/core-ai.constants.js.map +1 -0
- package/dist/core/modules/ai/index.d.ts +1 -0
- package/dist/core/modules/ai/index.js +1 -0
- package/dist/core/modules/ai/index.js.map +1 -1
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.d.ts +17 -0
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-budget.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-connection.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-conversation.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +2 -3
- package/dist/core/modules/ai/services/core-ai-interaction.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-mode.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +1 -3
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-prompt.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-slot.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai.service.d.ts +2 -17
- package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-roles.guard.js +2 -2
- package/dist/core/modules/better-auth/better-auth-roles.guard.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +12 -8
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.constants.d.ts +3 -0
- package/dist/core/modules/better-auth/core-better-auth.constants.js +7 -0
- package/dist/core/modules/better-auth/core-better-auth.constants.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.module.d.ts +1 -2
- package/dist/core/modules/better-auth/core-better-auth.module.js +23 -20
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.registry.d.ts +4 -0
- package/dist/core/modules/better-auth/core-better-auth.registry.js +16 -0
- package/dist/core/modules/better-auth/core-better-auth.registry.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.service.d.ts +1 -2
- package/dist/core/modules/better-auth/core-better-auth.service.js +7 -6
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/better-auth/index.d.ts +1 -0
- package/dist/core/modules/better-auth/index.js +1 -0
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core/modules/migrate/migration-runner.d.ts +1 -0
- package/dist/core/modules/migrate/migration-runner.js +3 -2
- package/dist/core/modules/migrate/migration-runner.js.map +1 -1
- package/dist/core/modules/tus/tus.constants.d.ts +1 -0
- package/dist/core/modules/tus/tus.constants.js +5 -0
- package/dist/core/modules/tus/tus.constants.js.map +1 -0
- package/dist/core/modules/tus/tus.module.d.ts +1 -1
- package/dist/core/modules/tus/tus.module.js +8 -6
- package/dist/core/modules/tus/tus.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +17 -4
- package/migration-guides/11.27.5-to-11.27.6.md +359 -0
- package/migration-guides/11.27.6-to-11.27.7.md +374 -0
- package/package.json +11 -104
- package/src/core/common/decorators/restricted.decorator.ts +33 -8
- package/src/core/common/helpers/clone.helper.ts +110 -0
- package/src/core/common/helpers/cookies.helper.ts +101 -26
- package/src/core/common/helpers/db.helper.ts +14 -161
- package/src/core/common/helpers/id.helper.ts +198 -0
- package/src/core/common/helpers/input.helper.ts +12 -84
- package/src/core/common/inputs/combined-filter.input.ts +10 -57
- package/src/core/common/inputs/filter.input.ts +92 -1
- package/src/core/common/interfaces/server-options.interface.ts +35 -6
- package/src/core/common/services/config.service.ts +4 -1
- package/src/core/modules/ai/core-ai.constants.ts +92 -0
- package/src/core/modules/ai/index.ts +1 -0
- package/src/core/modules/ai/interfaces/ai-interaction-record.interface.ts +34 -0
- package/src/core/modules/ai/services/core-ai-budget.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-connection.service.ts +5 -6
- package/src/core/modules/ai/services/core-ai-conversation.service.ts +5 -6
- package/src/core/modules/ai/services/core-ai-interaction.service.ts +6 -7
- package/src/core/modules/ai/services/core-ai-mode.service.ts +8 -2
- package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +7 -4
- package/src/core/modules/ai/services/core-ai-prompt.service.ts +8 -2
- package/src/core/modules/ai/services/core-ai-slot.service.ts +7 -4
- package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai.service.ts +8 -11
- package/src/core/modules/better-auth/README.md +10 -4
- package/src/core/modules/better-auth/better-auth-roles.guard.ts +11 -5
- package/src/core/modules/better-auth/better-auth.config.ts +90 -15
- package/src/core/modules/better-auth/core-better-auth.constants.ts +73 -0
- package/src/core/modules/better-auth/core-better-auth.module.ts +34 -8
- package/src/core/modules/better-auth/core-better-auth.registry.ts +53 -0
- package/src/core/modules/better-auth/core-better-auth.service.ts +19 -12
- package/src/core/modules/better-auth/index.ts +9 -0
- package/src/core/modules/migrate/migration-runner.ts +16 -2
- package/src/core/modules/tus/tus.constants.ts +25 -0
- package/src/core/modules/tus/tus.module.ts +7 -2
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ID helpers.
|
|
3
|
+
*
|
|
4
|
+
* These live in their own file — instead of `db.helper.ts` — so that files which need nothing but
|
|
5
|
+
* ID comparison can reach them without importing `db.helper`, which drags in GraphQL, Mongoose
|
|
6
|
+
* models and `input.helper` behind it.
|
|
7
|
+
*
|
|
8
|
+
* That was not an aesthetic choice. `restricted.decorator.ts` needs exactly two of these functions
|
|
9
|
+
* (`equalIds`, `getIncludedIds`), and importing them from `db.helper` put it on a real runtime
|
|
10
|
+
* cycle:
|
|
11
|
+
*
|
|
12
|
+
* restricted.decorator → db.helper → input.helper → restricted.decorator
|
|
13
|
+
*
|
|
14
|
+
* `input.helper` therefore evaluated while `restricted.decorator` was still initializing. Nothing
|
|
15
|
+
* crashed, but only because every cross-cycle dereference happened to sit inside a function body:
|
|
16
|
+
* a single top-level line in `input.helper` (a module-level alias, an `@Restricted`-decorated class,
|
|
17
|
+
* `design:type` metadata) would have thrown under SWC → CommonJS:
|
|
18
|
+
*
|
|
19
|
+
* ReferenceError: Cannot access 'checkRestricted' before initialization
|
|
20
|
+
*
|
|
21
|
+
* …in the file that drives field-level access control, on a compiler this repo's default build never
|
|
22
|
+
* runs. Moving the ID cluster into this leaf removes the `restricted.decorator → db.helper` edge
|
|
23
|
+
* outright, so the cycle no longer exists rather than merely being disarmed.
|
|
24
|
+
*
|
|
25
|
+
* This file imports only Mongoose's `Types`, lodash, and a type — no framework code — so it can
|
|
26
|
+
* never be part of a cycle itself. Keep it that way.
|
|
27
|
+
*
|
|
28
|
+
* `db.helper` re-exports all four public functions, so every existing import path keeps working.
|
|
29
|
+
* See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)".
|
|
30
|
+
*/
|
|
31
|
+
import _ = require('lodash');
|
|
32
|
+
import { Types } from 'mongoose';
|
|
33
|
+
|
|
34
|
+
import { IdsType } from '../types/ids.type';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Checks if all IDs are equal
|
|
38
|
+
*/
|
|
39
|
+
export function equalIds(...ids: IdsType[]): boolean {
|
|
40
|
+
if (!ids) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const compare = getStringIds(ids[0]);
|
|
44
|
+
if (!compare) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return ids.every((id) => getStringIds(id) === compare);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get included ids
|
|
52
|
+
* @param includes IdsType, which should be checked if it contains the ID
|
|
53
|
+
* @param ids IdsType, which should be included
|
|
54
|
+
* @param convert If set the result array will be converted to pure type String array or ObjectId array
|
|
55
|
+
* @return IdsType with IDs which are included, undefined if includes or ids are missing or null if none is included
|
|
56
|
+
*/
|
|
57
|
+
export function getIncludedIds(includes: IdsType, ids: IdsType, convert?: 'string'): string[];
|
|
58
|
+
export function getIncludedIds(includes: IdsType, ids: IdsType, convert?: 'object'): Types.ObjectId[];
|
|
59
|
+
|
|
60
|
+
export function getIncludedIds<T = IdsType>(
|
|
61
|
+
includes: IdsType,
|
|
62
|
+
ids: IdsType | T,
|
|
63
|
+
convert?: 'object' | 'string',
|
|
64
|
+
): null | T[] | undefined {
|
|
65
|
+
if (!includes || !ids) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!Array.isArray(includes)) {
|
|
70
|
+
includes = [includes];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!Array.isArray(ids)) {
|
|
74
|
+
ids = [ids];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let result = [];
|
|
78
|
+
const includesStrings = getStringIds(includes);
|
|
79
|
+
for (const id of ids) {
|
|
80
|
+
if (includesStrings.includes(getStringIds(id))) {
|
|
81
|
+
result.push(id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (convert) {
|
|
86
|
+
result = convert === 'string' ? getStringIds(result) : getObjectIds(result);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result.length ? result : null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Convert string(s) to ObjectId(s)
|
|
94
|
+
*/
|
|
95
|
+
export function getObjectIds(ids: any[]): Types.ObjectId[];
|
|
96
|
+
export function getObjectIds(ids: any): Types.ObjectId;
|
|
97
|
+
export function getObjectIds<T extends any | any[]>(ids: T): Types.ObjectId | Types.ObjectId[] {
|
|
98
|
+
if (Array.isArray(ids)) {
|
|
99
|
+
return ids.map((id) => new Types.ObjectId(getStringId(id)));
|
|
100
|
+
}
|
|
101
|
+
return new Types.ObjectId(getStringId(ids));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get IDs from string of ObjectId array in a flat string array
|
|
106
|
+
*/
|
|
107
|
+
export function getStringIds(elements: any[], options?: { deep?: boolean; unique?: boolean }): string[];
|
|
108
|
+
|
|
109
|
+
export function getStringIds(elements: any, options?: { deep?: boolean; unique?: boolean }): string;
|
|
110
|
+
|
|
111
|
+
export function getStringIds<T extends any | any[]>(
|
|
112
|
+
elements: T,
|
|
113
|
+
options?: { deep?: boolean; unique?: boolean },
|
|
114
|
+
): string | string[] {
|
|
115
|
+
// Process options
|
|
116
|
+
const { deep, unique } = {
|
|
117
|
+
deep: false,
|
|
118
|
+
unique: false,
|
|
119
|
+
...options,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Check elements
|
|
123
|
+
if (!elements) {
|
|
124
|
+
return elements as any;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Init ids
|
|
128
|
+
let ids = [];
|
|
129
|
+
|
|
130
|
+
// Process non array
|
|
131
|
+
if (!Array.isArray(elements)) {
|
|
132
|
+
return getStringId(elements);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Process array
|
|
136
|
+
for (const element of elements) {
|
|
137
|
+
if (Array.isArray(element)) {
|
|
138
|
+
if (deep) {
|
|
139
|
+
ids = ids.concat(getStringIds(element, { deep }));
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
const id = getStringId(element);
|
|
143
|
+
if (id) {
|
|
144
|
+
ids.push(id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Return (unique) ID array
|
|
150
|
+
return unique ? _.uniq(ids) : ids;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// =====================================================================================================================
|
|
154
|
+
// Not exported helper functions
|
|
155
|
+
// =====================================================================================================================
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get ID of element as string
|
|
159
|
+
*/
|
|
160
|
+
function getStringId(element: any): string {
|
|
161
|
+
// Check element
|
|
162
|
+
if (!element) {
|
|
163
|
+
return element;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Buffer handling
|
|
167
|
+
if (element instanceof Buffer) {
|
|
168
|
+
return element.toString();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// String handling
|
|
172
|
+
if (typeof element === 'string') {
|
|
173
|
+
return element;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Object handling
|
|
177
|
+
if (typeof element === 'object') {
|
|
178
|
+
if (element instanceof Types.ObjectId) {
|
|
179
|
+
return element.toHexString();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (element.id) {
|
|
183
|
+
if (element.id instanceof Buffer && element.toHexString) {
|
|
184
|
+
return element.toHexString();
|
|
185
|
+
}
|
|
186
|
+
return getStringId(element.id);
|
|
187
|
+
} else if (element._id) {
|
|
188
|
+
return getStringId(element._id);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Other types
|
|
193
|
+
if (typeof element.toString === 'function') {
|
|
194
|
+
return element.toString();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
@@ -3,16 +3,23 @@ import { plainToInstance } from 'class-transformer';
|
|
|
3
3
|
import { validate } from 'class-validator';
|
|
4
4
|
import { ValidatorOptions } from 'class-validator/types/validation/ValidatorOptions';
|
|
5
5
|
import { Kind } from 'graphql/index';
|
|
6
|
-
import * as inspector from 'inspector';
|
|
7
|
-
import _ = require('lodash');
|
|
8
|
-
import rfdc = require('rfdc');
|
|
9
|
-
import * as util from 'util';
|
|
10
6
|
|
|
11
7
|
import { checkRestricted } from '../decorators/restricted.decorator';
|
|
12
8
|
import { ProcessType } from '../enums/process-type.enum';
|
|
13
9
|
import { RoleEnum } from '../enums/role.enum';
|
|
10
|
+
import { clone } from './clone.helper';
|
|
14
11
|
import { merge } from './config.helper';
|
|
15
|
-
import { equalIds } from './
|
|
12
|
+
import { equalIds } from './id.helper';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `clone` and `deepFreeze` moved to `./clone.helper` and are re-exported here so every existing
|
|
16
|
+
* import path keeps working. They were extracted because `config.service` needs `clone`/`deepFreeze`,
|
|
17
|
+
* and pulling them from HERE put it on a runtime import cycle
|
|
18
|
+
* (restricted.decorator → core-tenant.helpers → config.service → input.helper → restricted.decorator)
|
|
19
|
+
* that is one top-level line away from an SWC temporal-dead-zone crash. `clone.helper` imports no
|
|
20
|
+
* framework code, so it can never be part of a cycle. Do NOT move them back.
|
|
21
|
+
*/
|
|
22
|
+
export { clone, deepFreeze } from './clone.helper';
|
|
16
23
|
|
|
17
24
|
/**
|
|
18
25
|
* Helper class for inputs
|
|
@@ -341,68 +348,6 @@ export function checkAndGetDate(input: any): Date {
|
|
|
341
348
|
return date;
|
|
342
349
|
}
|
|
343
350
|
|
|
344
|
-
/**
|
|
345
|
-
* Clone object
|
|
346
|
-
* @param object Any object
|
|
347
|
-
* @param options Finetuning of rfdc cloning
|
|
348
|
-
* @param options.checkResult Whether to compare object and cloned object via JSON.stringify and try alternative cloning
|
|
349
|
-
* methods if they are not equal
|
|
350
|
-
* @param options.circles Keeping track of circular references will slow down performance with an additional 25% overhead.
|
|
351
|
-
* Even if an object doesn't have any circular references, the tracking overhead is the cost.
|
|
352
|
-
* By default if an object with a circular reference is passed to rfdc, it will throw
|
|
353
|
-
* (similar to how JSON.stringify would throw). Use the circles option to detect and preserve
|
|
354
|
-
* circular references in the object. If performance is important, try removing the circular
|
|
355
|
-
* reference from the object (set to undefined) and then add it back manually after cloning
|
|
356
|
-
* instead of using this option.
|
|
357
|
-
* @param options.debug Whether to shoe console.debug messages
|
|
358
|
-
* @param options.proto Copy prototype properties as well as own properties into the new object.
|
|
359
|
-
* It's marginally faster to allow enumerable properties on the prototype to be copied into the
|
|
360
|
-
* cloned object (not onto it's prototype, directly onto the object).
|
|
361
|
-
*/
|
|
362
|
-
export function clone(object: any, options?: { checkResult?: boolean; circles?: boolean; proto?: boolean }) {
|
|
363
|
-
const config = {
|
|
364
|
-
checkResult: true,
|
|
365
|
-
circles: true,
|
|
366
|
-
debug: inspector.url() !== undefined,
|
|
367
|
-
proto: false,
|
|
368
|
-
...options,
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
try {
|
|
372
|
-
const cloned = rfdc(config)(object);
|
|
373
|
-
if (config.checkResult && !util.isDeepStrictEqual(object, cloned)) {
|
|
374
|
-
throw new Error('Cloned object differs from original object');
|
|
375
|
-
}
|
|
376
|
-
return cloned;
|
|
377
|
-
} catch (e) {
|
|
378
|
-
if (!config.circles) {
|
|
379
|
-
if (config.debug) {
|
|
380
|
-
console.debug(e, config, object, 'automatic try to use rfdc with circles');
|
|
381
|
-
}
|
|
382
|
-
try {
|
|
383
|
-
const clonedWithCircles = rfdc({
|
|
384
|
-
...config,
|
|
385
|
-
circles: true,
|
|
386
|
-
})(object);
|
|
387
|
-
if (config.checkResult && !util.isDeepStrictEqual(object, clonedWithCircles)) {
|
|
388
|
-
throw new Error('Cloned object differs from original object', { cause: e });
|
|
389
|
-
}
|
|
390
|
-
return clonedWithCircles;
|
|
391
|
-
} catch (innerError) {
|
|
392
|
-
if (config.debug) {
|
|
393
|
-
console.debug(innerError, 'rfcd with circles did not work => automatic use of _.clone!');
|
|
394
|
-
}
|
|
395
|
-
return _.cloneDeep(object);
|
|
396
|
-
}
|
|
397
|
-
} else {
|
|
398
|
-
if (config.debug) {
|
|
399
|
-
console.debug(e, config, object, 'automatic try to use _.clone instead rfdc');
|
|
400
|
-
}
|
|
401
|
-
return _.cloneDeep(object);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
351
|
/**
|
|
407
352
|
* Combines objects to a new single plain object and ignores undefined
|
|
408
353
|
*/
|
|
@@ -410,23 +355,6 @@ export function combinePlain(...args: Record<any, any>[]): any {
|
|
|
410
355
|
return assignPlain({}, ...args);
|
|
411
356
|
}
|
|
412
357
|
|
|
413
|
-
/**
|
|
414
|
-
* Get deep frozen object
|
|
415
|
-
*/
|
|
416
|
-
export function deepFreeze(object: any, visited: WeakSet<object> = new WeakSet()) {
|
|
417
|
-
if (!object || typeof object !== 'object') {
|
|
418
|
-
return object;
|
|
419
|
-
}
|
|
420
|
-
if (visited.has(object)) {
|
|
421
|
-
return object;
|
|
422
|
-
}
|
|
423
|
-
visited.add(object);
|
|
424
|
-
for (const [key, value] of Object.entries(object)) {
|
|
425
|
-
object[key] = deepFreeze(value, visited);
|
|
426
|
-
}
|
|
427
|
-
return Object.freeze(object);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
358
|
/**
|
|
431
359
|
* Standard error function
|
|
432
360
|
*/
|
|
@@ -1,57 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@InputType({
|
|
12
|
-
description: 'Combination of multiple filters via logical operator',
|
|
13
|
-
})
|
|
14
|
-
@Restricted(RoleEnum.S_EVERYONE)
|
|
15
|
-
export class CombinedFilterInput extends CoreInput {
|
|
16
|
-
/**
|
|
17
|
-
* Logical Operator to combine filters
|
|
18
|
-
*/
|
|
19
|
-
@UnifiedField({
|
|
20
|
-
description: 'Logical Operator to combine filters',
|
|
21
|
-
enum: LogicalOperatorEnum,
|
|
22
|
-
roles: RoleEnum.S_EVERYONE,
|
|
23
|
-
})
|
|
24
|
-
logicalOperator: LogicalOperatorEnum = undefined;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Filters to combine via logical operator
|
|
28
|
-
*/
|
|
29
|
-
@UnifiedField({
|
|
30
|
-
description: 'Filters to combine via logical operator',
|
|
31
|
-
isOptional: true,
|
|
32
|
-
roles: RoleEnum.S_EVERYONE,
|
|
33
|
-
type: () => FilterInput,
|
|
34
|
-
})
|
|
35
|
-
filters: FilterInput[] = undefined;
|
|
36
|
-
|
|
37
|
-
// ===================================================================================================================
|
|
38
|
-
// Methods
|
|
39
|
-
// ===================================================================================================================
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Mapping for Subtypes
|
|
43
|
-
*/
|
|
44
|
-
override map(
|
|
45
|
-
data: Partial<this> | Record<string, any>,
|
|
46
|
-
options: {
|
|
47
|
-
cloneDeep?: boolean;
|
|
48
|
-
funcAllowed?: boolean;
|
|
49
|
-
mapId?: boolean;
|
|
50
|
-
} = {},
|
|
51
|
-
): this {
|
|
52
|
-
super.map(data, options);
|
|
53
|
-
this.filters = maps(data.filters, FilterInput, options.cloneDeep);
|
|
54
|
-
Object.keys(this).forEach((key) => this[key] === undefined && delete this[key]);
|
|
55
|
-
return this;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* `CombinedFilterInput` is declared in `./filter.input` — the two classes are mutually recursive
|
|
3
|
+
* and must live in one module, or the cycle between them crashes SWC-compiled builds with
|
|
4
|
+
* `ReferenceError: Cannot access 'CombinedFilterInput' before initialization`. See the docblock in
|
|
5
|
+
* `./filter.input` for the full analysis.
|
|
6
|
+
*
|
|
7
|
+
* This file remains only so existing deep imports of `.../inputs/combined-filter.input` keep
|
|
8
|
+
* resolving. Do NOT move the class back here.
|
|
9
|
+
*/
|
|
10
|
+
export { CombinedFilterInput } from './filter.input';
|
|
@@ -1,12 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter inputs.
|
|
3
|
+
*
|
|
4
|
+
* `CombinedFilterInput` and `FilterInput` are mutually recursive: a filter may contain a combined
|
|
5
|
+
* filter, and a combined filter contains a list of filters. They therefore live in ONE module, and
|
|
6
|
+
* `CombinedFilterInput` is declared FIRST — that ordering is load-bearing, not cosmetic.
|
|
7
|
+
*
|
|
8
|
+
* They used to sit in two files that imported each other. `FilterInput` referenced
|
|
9
|
+
* `CombinedFilterInput` EAGERLY — in a decorator argument (`type: CombinedFilterInput`) and in the
|
|
10
|
+
* `design:type` metadata `emitDecoratorMetadata` emits for `combinedFilter?: CombinedFilterInput`.
|
|
11
|
+
* Decorator arguments and that metadata are evaluated at CLASS-DEFINITION time, i.e. while the
|
|
12
|
+
* module is still initializing. On a cycle that reads a class binding still in its temporal dead
|
|
13
|
+
* zone, and under SWC → CommonJS it threw:
|
|
14
|
+
*
|
|
15
|
+
* ReferenceError: Cannot access 'CombinedFilterInput' before initialization
|
|
16
|
+
*
|
|
17
|
+
* That was not hypothetical — `require('.../combined-filter.input.js')` crashed. It only stayed
|
|
18
|
+
* hidden because the package barrel happens to pull `filter.input` in first via other importers
|
|
19
|
+
* (`filter.args`, `filter.helper`), so entering through the barrel masked it. A deep import, a unit
|
|
20
|
+
* test importing the input directly, or a reordering of `src/index.ts` would all have detonated it.
|
|
21
|
+
*
|
|
22
|
+
* Making the reference lazy does NOT fix it: `type: () => CombinedFilterInput` still leaves the
|
|
23
|
+
* eager `design:type` metadata behind, and SWC's `typeof` guard does not protect the member
|
|
24
|
+
* expression it compiles to. The only real fix is to remove the import edge — hence one module.
|
|
25
|
+
*
|
|
26
|
+
* Within a single module the problem disappears: `FilterInput` reads `CombinedFilterInput` at
|
|
27
|
+
* definition time, and by then it is already initialized. The reverse direction is safe because
|
|
28
|
+
* `CombinedFilterInput` only reaches `FilterInput` lazily (a `() => FilterInput` thunk and a method
|
|
29
|
+
* body), never at definition time.
|
|
30
|
+
*
|
|
31
|
+
* `combined-filter.input.ts` remains as a re-export so existing deep imports keep working.
|
|
32
|
+
* See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)" for the general rule.
|
|
33
|
+
*/
|
|
1
34
|
import { InputType } from '@nestjs/graphql';
|
|
2
35
|
|
|
3
36
|
import { Restricted } from '../decorators/restricted.decorator';
|
|
4
37
|
import { UnifiedField } from '../decorators/unified-field.decorator';
|
|
38
|
+
import { LogicalOperatorEnum } from '../enums/logical-operator.enum';
|
|
5
39
|
import { RoleEnum } from '../enums/role.enum';
|
|
6
|
-
import {
|
|
40
|
+
import { maps } from '../helpers/model.helper';
|
|
7
41
|
import { CoreInput } from './core-input.input';
|
|
8
42
|
import { SingleFilterInput } from './single-filter.input';
|
|
9
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Combination of multiple filters via logical operator.
|
|
46
|
+
*
|
|
47
|
+
* Declared BEFORE `FilterInput` on purpose — `FilterInput` dereferences this class at
|
|
48
|
+
* class-definition time, so it must already be initialized. See the module docblock.
|
|
49
|
+
*/
|
|
50
|
+
@InputType({
|
|
51
|
+
description: 'Combination of multiple filters via logical operator',
|
|
52
|
+
})
|
|
53
|
+
@Restricted(RoleEnum.S_EVERYONE)
|
|
54
|
+
export class CombinedFilterInput extends CoreInput {
|
|
55
|
+
/**
|
|
56
|
+
* Logical Operator to combine filters
|
|
57
|
+
*/
|
|
58
|
+
@UnifiedField({
|
|
59
|
+
description: 'Logical Operator to combine filters',
|
|
60
|
+
enum: LogicalOperatorEnum,
|
|
61
|
+
roles: RoleEnum.S_EVERYONE,
|
|
62
|
+
})
|
|
63
|
+
logicalOperator: LogicalOperatorEnum = undefined;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Filters to combine via logical operator
|
|
67
|
+
*
|
|
68
|
+
* The `() => FilterInput` thunk is required: `FilterInput` is declared below, so an eager
|
|
69
|
+
* reference here would read it before initialization.
|
|
70
|
+
*/
|
|
71
|
+
@UnifiedField({
|
|
72
|
+
description: 'Filters to combine via logical operator',
|
|
73
|
+
isOptional: true,
|
|
74
|
+
roles: RoleEnum.S_EVERYONE,
|
|
75
|
+
type: () => FilterInput,
|
|
76
|
+
})
|
|
77
|
+
filters: FilterInput[] = undefined;
|
|
78
|
+
|
|
79
|
+
// ===================================================================================================================
|
|
80
|
+
// Methods
|
|
81
|
+
// ===================================================================================================================
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Mapping for Subtypes
|
|
85
|
+
*/
|
|
86
|
+
override map(
|
|
87
|
+
data: Partial<this> | Record<string, any>,
|
|
88
|
+
options: {
|
|
89
|
+
cloneDeep?: boolean;
|
|
90
|
+
funcAllowed?: boolean;
|
|
91
|
+
mapId?: boolean;
|
|
92
|
+
} = {},
|
|
93
|
+
): this {
|
|
94
|
+
super.map(data, options);
|
|
95
|
+
this.filters = maps(data.filters, FilterInput, options.cloneDeep);
|
|
96
|
+
Object.keys(this).forEach((key) => this[key] === undefined && delete this[key]);
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
10
101
|
/**
|
|
11
102
|
* Input for filtering. The `singleFilter` will be ignored if the `combinedFilter` is set.
|
|
12
103
|
*/
|
|
@@ -1012,8 +1012,17 @@ export interface ICorsConfig {
|
|
|
1012
1012
|
* Convenient for development but NOT recommended for production as it enables
|
|
1013
1013
|
* CSRF-like attacks from any domain.
|
|
1014
1014
|
*
|
|
1015
|
-
* When true, overrides `allowedOrigins`.
|
|
1016
|
-
*
|
|
1015
|
+
* When true, overrides `allowedOrigins`.
|
|
1016
|
+
*
|
|
1017
|
+
* **This does NOT disable BetterAuth's origin check.** BetterAuth keeps
|
|
1018
|
+
* verifying the `Origin` header against its `trustedOrigins`, which are derived
|
|
1019
|
+
* from `appUrl` (and the passkey config). Leaving `trustedOrigins` empty would
|
|
1020
|
+
* not "allow everything" — BetterAuth then trusts only its own `baseURL`, and
|
|
1021
|
+
* origin-checked endpoints such as `two-factor/enable` or passkey registration
|
|
1022
|
+
* answer `403 INVALID_ORIGIN` for a separately hosted frontend.
|
|
1023
|
+
*
|
|
1024
|
+
* To accept arbitrary origins for auth as well, set `betterAuth.trustedOrigins`
|
|
1025
|
+
* explicitly — an origin check has no meaningful "allow everything" mode.
|
|
1017
1026
|
*
|
|
1018
1027
|
* @default false
|
|
1019
1028
|
*/
|
|
@@ -1337,13 +1346,19 @@ export interface IServerOptions {
|
|
|
1337
1346
|
* - Frontend redirect URLs
|
|
1338
1347
|
*
|
|
1339
1348
|
* **Auto-Detection from `baseUrl`:**
|
|
1340
|
-
* If not set, `appUrl` is derived from `baseUrl
|
|
1349
|
+
* If not set, `appUrl` is derived from `baseUrl` (the port is preserved):
|
|
1341
1350
|
* - `https://api.example.com` → `https://example.com` (removes 'api.' prefix)
|
|
1342
1351
|
* - `https://example.com` → `https://example.com` (unchanged)
|
|
1343
1352
|
*
|
|
1344
1353
|
* **Localhost Environment Defaults:**
|
|
1345
|
-
* When `env` is 'local', 'ci', or 'e2e'
|
|
1346
|
-
*
|
|
1354
|
+
* When `env` is 'local', 'ci', or 'e2e', `appUrl` is not set, and `baseUrl` is unset or points at
|
|
1355
|
+
* localhost, `appUrl` defaults to `http://localhost:3001`. These defaults encode a PORT split:
|
|
1356
|
+
* one host, API on `:3000`, app on `:3001`.
|
|
1357
|
+
*
|
|
1358
|
+
* A localhost `baseUrl` whose `api.` label strips to a SIBLING host is a HOST split and is
|
|
1359
|
+
* derived instead — `https://api.crm.localhost` → `https://crm.localhost`, as served by
|
|
1360
|
+
* `lt dev up` behind Caddy. `https://api.localhost` strips to the bare `localhost` the API
|
|
1361
|
+
* already answers on, so it keeps the `http://localhost:3001` default.
|
|
1347
1362
|
*
|
|
1348
1363
|
* **Environment Variable:** `APP_URL` (only needed if not auto-derivable from `BASE_URL`)
|
|
1349
1364
|
*
|
|
@@ -1362,6 +1377,11 @@ export interface IServerOptions {
|
|
|
1362
1377
|
* env: 'local', // or 'ci' or 'e2e'
|
|
1363
1378
|
* // baseUrl defaults to 'http://localhost:3000'
|
|
1364
1379
|
* // appUrl defaults to 'http://localhost:3001'
|
|
1380
|
+
*
|
|
1381
|
+
* // Local/CI/E2E behind `lt dev up` (host split — appUrl auto-derived)
|
|
1382
|
+
* env: 'local',
|
|
1383
|
+
* baseUrl: 'https://api.crm.localhost',
|
|
1384
|
+
* // → appUrl auto-derived: 'https://crm.localhost'
|
|
1365
1385
|
* ```
|
|
1366
1386
|
*/
|
|
1367
1387
|
appUrl?: string;
|
|
@@ -2784,7 +2804,8 @@ interface IBetterAuthBase {
|
|
|
2784
2804
|
* },
|
|
2785
2805
|
* advanced: {
|
|
2786
2806
|
* cookiePrefix: 'my-app',
|
|
2787
|
-
* useSecureCookies: true,
|
|
2807
|
+
* useSecureCookies: true, // re-enables the __Secure- prefix; safe ONLY when Better-Auth
|
|
2808
|
+
* // fully manages your cookies — see the note below.
|
|
2788
2809
|
* crossSubDomainCookies: {
|
|
2789
2810
|
* domain: 'example.com', // Cookies shared across *.example.com
|
|
2790
2811
|
* },
|
|
@@ -2795,6 +2816,14 @@ interface IBetterAuthBase {
|
|
|
2795
2816
|
* **Note on `advanced` options:** The `advanced` object is deep-merged with internal defaults
|
|
2796
2817
|
* (e.g., `cookiePrefix` derived from `basePath`). You do not need to re-specify `cookiePrefix`
|
|
2797
2818
|
* when adding other `advanced` options like `crossSubDomainCookies`.
|
|
2819
|
+
*
|
|
2820
|
+
* **`useSecureCookies` is pinned to `false` by default (since v11.27.6).** The framework keeps
|
|
2821
|
+
* Better-Auth's native handlers on the same UNPREFIXED cookie name the nest-server cookie helper
|
|
2822
|
+
* writes; the `Secure` attribute is still applied on an `https://` baseURL via
|
|
2823
|
+
* `advanced.defaultCookieAttributes`, so transport security is unchanged. Only set
|
|
2824
|
+
* `useSecureCookies: true` if Better-Auth manages your session cookies entirely (not the
|
|
2825
|
+
* nest-server helper) — otherwise its native handlers look for a `__Secure-`-prefixed cookie the
|
|
2826
|
+
* helper never writes and answer `401` on 2FA / passkey / `/token`.
|
|
2798
2827
|
*/
|
|
2799
2828
|
options?: Record<string, unknown>;
|
|
2800
2829
|
|
|
@@ -4,7 +4,10 @@ import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
|
|
4
4
|
import { filter, map } from 'rxjs/operators';
|
|
5
5
|
|
|
6
6
|
import { merge } from '../helpers/config.helper';
|
|
7
|
-
|
|
7
|
+
// Import from the clone.helper LEAF, never from input.helper: input.helper imports
|
|
8
|
+
// restricted.decorator, which reaches back here via core-tenant.helpers — that cycle is what the
|
|
9
|
+
// extraction removed. See clone.helper's docblock.
|
|
10
|
+
import { clone, deepFreeze } from '../helpers/clone.helper';
|
|
8
11
|
import { IServerOptions } from '../interfaces/server-options.interface';
|
|
9
12
|
|
|
10
13
|
/**
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency-injection tokens of the AI module.
|
|
3
|
+
*
|
|
4
|
+
* They live in a dedicated, import-free leaf file — never in a service or in `core-ai.module.ts` —
|
|
5
|
+
* so that no file needing a token has to import the file that declares it, and no import cycle can
|
|
6
|
+
* form around one.
|
|
7
|
+
*
|
|
8
|
+
* On a cycle, a token read at MODULE-EVALUATION time — inside an `@Inject()` decorator argument, in
|
|
9
|
+
* the `design:paramtypes` metadata `emitDecoratorMetadata` emits, or in a static field initializer —
|
|
10
|
+
* reads a `const` still in its temporal dead zone, and SWC-compiled builds (`nest start -b swc`) die
|
|
11
|
+
* at startup with:
|
|
12
|
+
*
|
|
13
|
+
* ReferenceError: Cannot access 'AI_CONNECTION_MODEL' before initialization
|
|
14
|
+
*
|
|
15
|
+
* These tokens were previously declared across eleven `*.service.ts` files, every one of which is
|
|
16
|
+
* imported by `core-ai.module.ts` and injects tokens through constructor decorators. Nothing had
|
|
17
|
+
* crashed — the graph happened to be acyclic — but a single back-import from any of those services
|
|
18
|
+
* would have armed it, and `tsc`, `pnpm test` and `oxlint` are ALL blind to that. Only
|
|
19
|
+
* `pnpm run check:swc-tdz` sees it.
|
|
20
|
+
*
|
|
21
|
+
* A file that imports nothing can never be mid-evaluation when someone imports it, in any module
|
|
22
|
+
* system, under any compiler. Keep this file import-free.
|
|
23
|
+
*
|
|
24
|
+
* The old locations re-export their tokens, so every existing import path still resolves.
|
|
25
|
+
* See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)".
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// ---- budget ----
|
|
29
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
30
|
+
export const AI_BUDGET_LIMIT_CLASS = 'AI_BUDGET_LIMIT_CLASS';
|
|
31
|
+
/** Mongoose injection token. */
|
|
32
|
+
export const AI_BUDGET_LIMIT_MODEL = 'AiBudgetLimit';
|
|
33
|
+
|
|
34
|
+
// ---- connection-preference ----
|
|
35
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
36
|
+
export const AI_CONNECTION_PREFERENCE_CLASS = 'AI_CONNECTION_PREFERENCE_CLASS';
|
|
37
|
+
/** Mongoose injection token. */
|
|
38
|
+
export const AI_CONNECTION_PREFERENCE_MODEL = 'AiConnectionPreference';
|
|
39
|
+
|
|
40
|
+
// ---- connection ----
|
|
41
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
42
|
+
export const AI_CONNECTION_CLASS = 'AI_CONNECTION_CLASS';
|
|
43
|
+
/** Mongoose injection token. */
|
|
44
|
+
export const AI_CONNECTION_MODEL = 'AiConnection';
|
|
45
|
+
|
|
46
|
+
// ---- conversation ----
|
|
47
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
48
|
+
export const AI_CONVERSATION_CLASS = 'AI_CONVERSATION_CLASS';
|
|
49
|
+
/** Mongoose injection token. */
|
|
50
|
+
export const AI_CONVERSATION_MODEL = 'AiConversation';
|
|
51
|
+
|
|
52
|
+
// ---- interaction ----
|
|
53
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
54
|
+
export const AI_INTERACTION_CLASS = 'AI_INTERACTION_CLASS';
|
|
55
|
+
/** Mongoose injection token. */
|
|
56
|
+
export const AI_INTERACTION_MODEL = 'AiInteraction';
|
|
57
|
+
|
|
58
|
+
// ---- mode ----
|
|
59
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
60
|
+
export const AI_MODE_CLASS = 'AI_MODE_CLASS';
|
|
61
|
+
/** Mongoose injection token. */
|
|
62
|
+
export const AI_MODE_MODEL = 'AiMode';
|
|
63
|
+
|
|
64
|
+
// ---- prompt-hint ----
|
|
65
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
66
|
+
export const AI_PROMPT_HINT_CLASS = 'AI_PROMPT_HINT_CLASS';
|
|
67
|
+
/** Mongoose injection token. */
|
|
68
|
+
export const AI_PROMPT_HINT_MODEL = 'AiPromptHint';
|
|
69
|
+
|
|
70
|
+
// ---- prompt ----
|
|
71
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
72
|
+
export const AI_PROMPT_CLASS = 'AI_PROMPT_CLASS';
|
|
73
|
+
/** Mongoose injection token. */
|
|
74
|
+
export const AI_PROMPT_MODEL = 'AiPrompt';
|
|
75
|
+
|
|
76
|
+
// ---- slot ----
|
|
77
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
78
|
+
export const AI_SLOT_CLASS = 'AI_SLOT_CLASS';
|
|
79
|
+
/** Mongoose injection token. */
|
|
80
|
+
export const AI_SLOT_MODEL = 'AiSlot';
|
|
81
|
+
|
|
82
|
+
// ---- tool-grant ----
|
|
83
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
84
|
+
export const AI_TOOL_GRANT_CLASS = 'AI_TOOL_GRANT_CLASS';
|
|
85
|
+
/** Mongoose injection token. */
|
|
86
|
+
export const AI_TOOL_GRANT_MODEL = 'AiToolGrant';
|
|
87
|
+
|
|
88
|
+
// ---- tool-policy ----
|
|
89
|
+
/** DI token for the model constructor (used by CrudService mapping). */
|
|
90
|
+
export const AI_TOOL_POLICY_CLASS = 'AI_TOOL_POLICY_CLASS';
|
|
91
|
+
/** Mongoose injection token. */
|
|
92
|
+
export const AI_TOOL_POLICY_MODEL = 'AiToolPolicy';
|