@lenne.tech/nest-server 11.27.6 → 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/package-management.md +23 -14
- package/CLAUDE.md +8 -2
- package/FRAMEWORK-API.md +1 -1
- 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/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 +6 -0
- 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/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/migration-guides/11.27.6-to-11.27.7.md +374 -0
- package/package.json +6 -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/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/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/better-auth-roles.guard.ts +11 -5
- package/src/core/modules/better-auth/better-auth.config.ts +16 -0
- 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/tus/tus.constants.ts +25 -0
- package/src/core/modules/tus/tus.module.ts +7 -2
|
@@ -60,6 +60,72 @@ Key areas: JWT, MongoDB, GraphQL, email, security, static assets
|
|
|
60
60
|
- `CheckResponseInterceptor` - Filters restricted fields
|
|
61
61
|
- `CheckSecurityInterceptor` - Processes `securityCheck()` methods
|
|
62
62
|
|
|
63
|
+
## DI Token Placement (SWC-Safe)
|
|
64
|
+
|
|
65
|
+
**Rule: DI tokens belong in an import-free leaf file (`*.constants.ts` / `*.enums.ts`) — never in `*.module.ts` or `*.service.ts`.**
|
|
66
|
+
|
|
67
|
+
A token declared in a module that the service imports (or vice versa) makes the two files import each other. That cycle compiles fine under tsc, but `@Inject(TOKEN)` is a constructor-parameter decorator evaluated at **class-definition time** — so on the cycle it reads a `const` that is still in its temporal dead zone. Under SWC → CommonJS (`nest start -b swc`) the app dies at startup:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**This is invisible to `tsc`, to `pnpm test` (vitest runs SWC through Vite's cycle-tolerant module runner) and to `oxlint` (which has no `import/no-cycle` rule).** It is caught only by `pnpm run check:swc-tdz`.
|
|
74
|
+
|
|
75
|
+
### The general rule: a cycle is fatal only when dereferenced at evaluation time
|
|
76
|
+
|
|
77
|
+
The cycle alone is survivable. What kills it is **reading a TDZ-subject binding (`const` / `class` / `let`) while the module is still initializing**:
|
|
78
|
+
|
|
79
|
+
| Deref location | Evaluated | Danger |
|
|
80
|
+
|----------------|-----------|--------|
|
|
81
|
+
| Decorator argument (`@UnifiedField({ type: X })`, `@Inject(TOKEN)`) | class-definition time | ☠️ **fatal on a cycle** |
|
|
82
|
+
| `design:type` / `design:paramtypes` metadata (from `emitDecoratorMetadata`) | class-definition time | ☠️ **fatal on a cycle** — and userland cannot make it lazy |
|
|
83
|
+
| Static / class field initializer | class-definition time | ☠️ **fatal on a cycle** |
|
|
84
|
+
| Top-level `const alias = X` | module-evaluation time | ☠️ **fatal on a cycle** |
|
|
85
|
+
| Inside a function or method body | call time | ✅ safe (both modules are done by then) |
|
|
86
|
+
| `export function` declaration | hoisted | ✅ TDZ-immune — prefer over `const` arrows on cycle-adjacent files |
|
|
87
|
+
| `import type` | erased | ✅ not a runtime edge at all |
|
|
88
|
+
|
|
89
|
+
**A lazy thunk is often NOT enough.** `type: () => X` defers the decorator argument, but `emitDecoratorMetadata` still emits an eager `design:type` for the property, and SWC's `typeof` guard does not protect the member expression it compiles to. To be safe you must remove the **import edge** — merge the modules, or extract the shared binding into a leaf.
|
|
90
|
+
|
|
91
|
+
### `check:swc-tdz` loads every module as its own entry point
|
|
92
|
+
|
|
93
|
+
Whether such a cycle throws depends on **which module the graph is entered through**. A barrel-only check is not enough: `filter.input` ↔ `combined-filter.input` crashed on a direct `require()` of `combined-filter.input` while the barrel loaded green, because the barrel happened to pull `filter.input` in first. So the guard requires each compiled file separately (`scripts/check-swc-tdz.mjs`).
|
|
94
|
+
|
|
95
|
+
### Status per module
|
|
96
|
+
|
|
97
|
+
Repo-wide cycles went from **10 → 5**, and **every DI token in `src/core/` now lives in an import-free leaf**. The five that remain are, per an SWC-emit audit, **not runtime cycles at all** — type-only imports that madge reports but both compilers erase (their emits are empty).
|
|
98
|
+
|
|
99
|
+
Both invariants are enforced by `tests/unit/import-cycle-invariants.spec.ts`, which fails if a token reappears in a `*.module.ts` / `*.service.ts` or if a leaf grows an import. That matters, because the guard below catches the *crash*, not the *disarming* of a safety property — those are different things, and only the second one is silent.
|
|
100
|
+
|
|
101
|
+
| Module | Token / type leaf |
|
|
102
|
+
|--------|-------------------|
|
|
103
|
+
| `better-auth` | `core-better-auth.constants.ts` (tokens) + `core-better-auth.registry.ts` (static service refs, `import type` only, deliberately **not** barrel-exported) |
|
|
104
|
+
| `ai` | `core-ai.constants.ts` (all 22 `AI_*` tokens) + `interfaces/ai-interaction-record.interface.ts` |
|
|
105
|
+
| `tus` | `tus.constants.ts` (`TUS_CONFIG`) |
|
|
106
|
+
| `tenant` | `core-tenant.enums.ts` |
|
|
107
|
+
| `auth` | `interfaces/auth-provider.interface.ts` |
|
|
108
|
+
| `common/helpers` | `id.helper.ts` (ID cluster, out of `db.helper`) + `clone.helper.ts` (`clone`/`deepFreeze`, out of `input.helper`) |
|
|
109
|
+
| `common/inputs` | `FilterInput` + `CombinedFilterInput` merged into `filter.input.ts` — declaration order is load-bearing |
|
|
110
|
+
| `common/decorators` | `restricted.decorator` is on **zero** cycles; its exports are hoisted `function` declarations (TDZ-immune) as defense in depth |
|
|
111
|
+
|
|
112
|
+
Every old location re-exports what it lost, so no import path broke — the public API is byte-identical (472 exports, verified by diffing both versions).
|
|
113
|
+
|
|
114
|
+
### What each of these actually was
|
|
115
|
+
|
|
116
|
+
Worth knowing, because the pattern repeats:
|
|
117
|
+
|
|
118
|
+
- **`CombinedFilterInput` was already crashing.** `require('.../combined-filter.input.js')` threw. It stayed hidden because the barrel happens to pull `filter.input` in first — a deep import or a reordering of `src/index.ts` would have surfaced it. A lazy thunk does **not** fix that shape: `emitDecoratorMetadata` still emits an eager `design:type`.
|
|
119
|
+
- **`restricted.decorator` sat on two cycles at once**, in the file that drives field-level access control. Removing the `db.helper` edge felt like the fix and left the `config.service` one fully intact. **Removing one edge is not removing the cycle** — re-run madge and confirm the file appears in *zero* cycles.
|
|
120
|
+
- **The AI interaction record was held apart by one keyword.** `import type` erases the edge; an IDE "organize imports" widening it to a value import would have armed a `design:paramtypes` deref, silently.
|
|
121
|
+
- **`TUS_CONFIG` and the 22 `AI_*` tokens** never crashed — their graphs happened to be acyclic. Each was one back-import away, with nothing watching.
|
|
122
|
+
|
|
123
|
+
### The lesson that cost the most time
|
|
124
|
+
|
|
125
|
+
Removing one edge is not the same as removing the cycle. `restricted.decorator` was on **two** cycles through different paths; extracting the ID helpers out of `db.helper` felt like the fix and left the second one (via `config.service`) fully intact — with `madge` happily reporting the file as still cyclic. Always re-run `npx madge --circular --extensions ts src/` after an extraction and check the file appears in **zero** cycles, rather than assuming the edge you removed was the only one.
|
|
126
|
+
|
|
127
|
+
Full background, failure analysis and the mistakes table: `.claude/rules/better-auth.md` §6.
|
|
128
|
+
|
|
63
129
|
## Model Inheritance
|
|
64
130
|
|
|
65
131
|
- `CorePersistenceModel` - Base for database entities
|
|
@@ -199,6 +199,8 @@ The BetterAuth module provides two RolesGuard implementations:
|
|
|
199
199
|
**Solution:** `BetterAuthRolesGuard` with NO constructor dependencies:
|
|
200
200
|
|
|
201
201
|
```typescript
|
|
202
|
+
import { getBetterAuthTokenService } from './core-better-auth.registry';
|
|
203
|
+
|
|
202
204
|
@Injectable()
|
|
203
205
|
export class BetterAuthRolesGuard implements CanActivate {
|
|
204
206
|
// NO constructor dependencies - avoids mixin DI conflict
|
|
@@ -207,14 +209,19 @@ export class BetterAuthRolesGuard implements CanActivate {
|
|
|
207
209
|
// Use Reflect.getMetadata directly (not NestJS Reflector)
|
|
208
210
|
const roles = Reflect.getMetadata('roles', context.getHandler());
|
|
209
211
|
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
+
// Read the token service from the registry LEAF — never from CoreBetterAuthModule.
|
|
213
|
+
// Importing the module here re-creates the guard <-> module import cycle (see §6).
|
|
214
|
+
const tokenService = getBetterAuthTokenService();
|
|
212
215
|
|
|
213
216
|
// ... role checking logic identical to RolesGuard
|
|
214
217
|
}
|
|
215
218
|
}
|
|
216
219
|
```
|
|
217
220
|
|
|
221
|
+
> The guard must NOT do `CoreBetterAuthModule.getTokenServiceInstance()`. That static accessor is
|
|
222
|
+
> still public API and still works — but calling it *from the guard* means importing the module,
|
|
223
|
+
> which is exactly the cycle §6 exists to prevent. Everywhere else, the static accessor is fine.
|
|
224
|
+
|
|
218
225
|
### Guard Selection Logic
|
|
219
226
|
|
|
220
227
|
In `CoreBetterAuthModule.createDeferredModule()`:
|
|
@@ -250,6 +257,84 @@ Both guards implement identical security logic:
|
|
|
250
257
|
2. **New system roles** → Add to BOTH guards
|
|
251
258
|
3. **Token verification changes** → Update `BetterAuthTokenService` (shared by both)
|
|
252
259
|
4. **Testing** → Test both Legacy Mode and IAM-Only Mode
|
|
260
|
+
5. **Reaching services from `BetterAuthRolesGuard`** → go through `core-better-auth.registry.ts`,
|
|
261
|
+
**never** through `CoreBetterAuthModule` (see §6 — importing the module from the guard
|
|
262
|
+
re-creates an import cycle)
|
|
263
|
+
|
|
264
|
+
## 6. DI Token Placement (SWC-Safe)
|
|
265
|
+
|
|
266
|
+
### The rule
|
|
267
|
+
|
|
268
|
+
**DI tokens and static service references belong in an import-free leaf file — never in
|
|
269
|
+
`*.module.ts` or `*.service.ts`.**
|
|
270
|
+
|
|
271
|
+
| File | Contents | Imports |
|
|
272
|
+
|------|----------|---------|
|
|
273
|
+
| `core-better-auth.constants.ts` | `BETTER_AUTH_INSTANCE`, `BETTER_AUTH_CONFIG`, `BETTER_AUTH_COOKIE_DOMAIN` | **none** |
|
|
274
|
+
| `core-better-auth.registry.ts` | `BetterAuthTokenService` reference for `BetterAuthRolesGuard` | **`import type` only** (erased by tsc and SWC) |
|
|
275
|
+
|
|
276
|
+
### The problem
|
|
277
|
+
|
|
278
|
+
The tokens used to live in the module (`BETTER_AUTH_INSTANCE`) and the service (`BETTER_AUTH_CONFIG`,
|
|
279
|
+
`BETTER_AUTH_COOKIE_DOMAIN`), so module and service imported each other.
|
|
280
|
+
|
|
281
|
+
**Error (only under `nest start -b swc` / `nest build -b swc`):**
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The lethal ingredient is **not the cycle by itself** — it is a cycle **plus a read of the cyclic
|
|
288
|
+
binding at module-evaluation time**. `@Inject(BETTER_AUTH_INSTANCE)` is a constructor-parameter
|
|
289
|
+
decorator, and decorator arguments are evaluated when the class is *defined*, i.e. while the module
|
|
290
|
+
is still initializing. On a cycle, the importing side then reads a `const` that is still in its
|
|
291
|
+
temporal dead zone.
|
|
292
|
+
|
|
293
|
+
This is why the same cycle is harmless when both sides only dereference each other **inside method
|
|
294
|
+
bodies** (deferred to call time) — and why such a cycle is nonetheless a loaded gun: hoisting a
|
|
295
|
+
lazy lookup into a static field, or adding a typed constructor parameter (which emits
|
|
296
|
+
`design:paramtypes` at top level), weaponizes it instantly.
|
|
297
|
+
|
|
298
|
+
### The solution
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
// core-better-auth.constants.ts — imports NOTHING
|
|
302
|
+
export const BETTER_AUTH_INSTANCE = 'BETTER_AUTH_INSTANCE';
|
|
303
|
+
|
|
304
|
+
// core-better-auth.module.ts AND core-better-auth.service.ts
|
|
305
|
+
import { BETTER_AUTH_INSTANCE } from './core-better-auth.constants';
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
A file with zero imports can never be mid-evaluation when someone imports it — in any module
|
|
309
|
+
system, under any compiler.
|
|
310
|
+
|
|
311
|
+
### Why you cannot rely on the test suite here
|
|
312
|
+
|
|
313
|
+
This bug class is **invisible** to everything except one specific step:
|
|
314
|
+
|
|
315
|
+
| Tool | Sees it? | Why |
|
|
316
|
+
|------|:--------:|-----|
|
|
317
|
+
| `tsc` / `pnpm run build` | ❌ | Compiles the cycle without complaint |
|
|
318
|
+
| `pnpm test` (vitest) | ❌ | vitest runs SWC through **Vite's module runner**, whose getter-based live bindings tolerate cycles |
|
|
319
|
+
| `oxlint` | ❌ | oxlint does **not** implement `import/no-cycle` |
|
|
320
|
+
| `pnpm run check:swc-tdz` | ✅ | SWC → CommonJS → `require()`: the exact path consumers hit |
|
|
321
|
+
| `tests/unit/better-auth-di-tokens.spec.ts` | ✅ | Asserts the leaf invariant structurally |
|
|
322
|
+
|
|
323
|
+
The bug shipped to `develop` with a fully green CI. Treat a green `pnpm test` as **no evidence** on
|
|
324
|
+
this question.
|
|
325
|
+
|
|
326
|
+
### Common mistakes
|
|
327
|
+
|
|
328
|
+
| Mistake | Symptom | Fix |
|
|
329
|
+
|---------|---------|-----|
|
|
330
|
+
| Importing a token from `./core-better-auth.module` or `./core-better-auth.service` inside the better-auth module | Green tsc + green tests; `ReferenceError` for consumers on SWC | Import from `./core-better-auth.constants` |
|
|
331
|
+
| Adding any runtime `import` to `core-better-auth.constants.ts` | `better-auth-di-tokens.spec.ts` fails | Keep it a leaf; move whatever you needed elsewhere |
|
|
332
|
+
| Importing `CoreBetterAuthModule` into `better-auth-roles.guard.ts` | Re-creates the guard ↔ module cycle | Use `getBetterAuthTokenService()` from `./core-better-auth.registry` |
|
|
333
|
+
| Hoisting `getBetterAuthTokenService()` into a static field / class property initializer | Evaluation-time deref → TDZ crash returns | Keep the lookup inside the method body |
|
|
334
|
+
|
|
335
|
+
> The backward-compat re-exports in `core-better-auth.module.ts` / `core-better-auth.service.ts` are
|
|
336
|
+
> marked `@deprecated` and exist **only** for external deep importers. Never use them from inside
|
|
337
|
+
> the module — that is precisely the path that re-creates the cycle.
|
|
253
338
|
|
|
254
339
|
## Summary
|
|
255
340
|
|
|
@@ -260,3 +345,4 @@ Both guards implement identical security logic:
|
|
|
260
345
|
| Testing | Full coverage, all tests pass, security tests included |
|
|
261
346
|
| Customization | Use correct registration pattern, re-declare Resolver decorators |
|
|
262
347
|
| Guards | Maintain both RolesGuard and BetterAuthRolesGuard in sync |
|
|
348
|
+
| DI Tokens | Import-free leaf file only — never in `*.module.ts` / `*.service.ts` (§6) |
|
|
@@ -97,9 +97,23 @@ peerDependencies may use ranges when necessary for compatibility with consuming
|
|
|
97
97
|
|
|
98
98
|
The `pnpm-lock.yaml` file must always be committed. It provides additional reproducibility even if someone accidentally introduces a version range.
|
|
99
99
|
|
|
100
|
+
## Package Manager: pnpm 11
|
|
101
|
+
|
|
102
|
+
This repo is pinned to **pnpm 11** via the `packageManager` field (corepack/`pnpm/action-setup` follow it, so CI and Docker use it automatically — no version is hardcoded anywhere else).
|
|
103
|
+
|
|
104
|
+
pnpm 11 **no longer reads the `pnpm` field in `package.json`**, and `.npmrc` is auth/registry only. All pnpm-specific settings live in **`pnpm-workspace.yaml`**:
|
|
105
|
+
|
|
106
|
+
- `overrides:` — the security overrides (see below)
|
|
107
|
+
- `allowBuilds:` — a **map** of `pkg: true|false` classifying every package that has an install script (canonical v11 form; replaces `onlyBuiltDependencies`). Native builds we need are `true` (`bcrypt`, `@swc/core`, …); telemetry like `@scarf/scarf` is `false`. **Every build-script package must be classified**, or `pnpm install` exits non-zero with `ERR_PNPM_IGNORED_BUILDS` and appends a broken stub.
|
|
108
|
+
- `nodeLinker`, `autoInstallPeers`, `strictPeerDependencies`, `peerDependencyRules` — moved here from `.npmrc` (camelCase).
|
|
109
|
+
|
|
110
|
+
`pnpm audit`: pnpm 10.x is broken (npm retired the legacy audit endpoint → HTTP 410); pnpm 11 uses the working bulk-advisory endpoint. `scripts/check.mjs` degrades the retired-endpoint failure to a non-blocking warning as a safety net, so `check` stays green + honest even if a future endpoint change lands.
|
|
111
|
+
|
|
100
112
|
## Overrides
|
|
101
113
|
|
|
102
|
-
Package overrides
|
|
114
|
+
Package overrides live in the `overrides:` section of **`pnpm-workspace.yaml`** (they moved out of `package.json`'s `pnpm.overrides` in the pnpm 11 upgrade). They force transitive dependencies to a security-patched version.
|
|
115
|
+
|
|
116
|
+
**Keep the set minimal.** On the pnpm 11 upgrade the list was pruned from 36 to the 9 still load-bearing — an override is only necessary if removing it lets the package resolve back INTO its vulnerable range (verify with a with/without lockfile diff; `pnpm audit` is the arbiter). Each surviving entry carries its CVE rationale as a comment. Remove an entry once its parent dependency ships a fixed version.
|
|
103
117
|
|
|
104
118
|
### Rule: Override Targets MUST Be Fixed Versions
|
|
105
119
|
|
|
@@ -115,19 +129,14 @@ The **target** of an override (the value on the right-hand side) MUST be a fixed
|
|
|
115
129
|
|
|
116
130
|
The **key** (left-hand side) of an override entry selects which installed versions the override applies to. Both forms are valid:
|
|
117
131
|
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
"minimatch@<3.1.4": "3.1.4",
|
|
127
|
-
"path-to-regexp@>=8.0.0 <8.4.0": "8.4.2"
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
132
|
+
```yaml
|
|
133
|
+
# pnpm-workspace.yaml
|
|
134
|
+
overrides:
|
|
135
|
+
# Form 1: Replace ALL versions of a package with a fixed one
|
|
136
|
+
'lodash': '4.17.23'
|
|
137
|
+
# Form 2: Replace only vulnerable versions with a fixed patched one
|
|
138
|
+
'minimatch@<3.1.4': '3.1.4'
|
|
139
|
+
'path-to-regexp@>=8.0.0 <8.4.0': '8.4.2'
|
|
131
140
|
```
|
|
132
141
|
|
|
133
142
|
Form 2 is preferred for security-driven overrides because it leaves non-vulnerable versions untouched, which reduces the blast radius of the override.
|
package/CLAUDE.md
CHANGED
|
@@ -114,9 +114,15 @@ npx vitest run --config vitest-e2e.config.ts --reporter=hanging-process # Debu
|
|
|
114
114
|
pnpm run test:cleanup # Remove leftover test artifacts (.txt, .bin)
|
|
115
115
|
|
|
116
116
|
# Linting & Formatting
|
|
117
|
-
pnpm run lint #
|
|
117
|
+
pnpm run lint # oxlint check
|
|
118
118
|
pnpm run lint:fix # Auto-fix
|
|
119
|
-
pnpm run format #
|
|
119
|
+
pnpm run format # oxfmt format
|
|
120
|
+
|
|
121
|
+
# Import-cycle / SWC safety (part of `check`)
|
|
122
|
+
pnpm run check:swc-tdz # SWC→CJS build, loads EVERY module as its own entry point.
|
|
123
|
+
# The only step that catches a temporal-dead-zone crash from an
|
|
124
|
+
# import cycle — tsc, vitest and oxlint are all blind to it.
|
|
125
|
+
# See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)"
|
|
120
126
|
|
|
121
127
|
# Package Development
|
|
122
128
|
pnpm run build:dev # Build for local development (use with pnpm link)
|
package/FRAMEWORK-API.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lenne.tech/nest-server — Framework API Reference
|
|
2
2
|
|
|
3
|
-
> Auto-generated from source code on 2026-07-
|
|
3
|
+
> Auto-generated from source code on 2026-07-15 (v11.27.7)
|
|
4
4
|
> File: `FRAMEWORK-API.md` — compact, machine-readable API surface for Claude Code
|
|
5
5
|
|
|
6
6
|
## CoreModule.forRoot()
|
|
@@ -6,9 +6,9 @@ export type RestrictedType = (RequireAtLeastOne<{
|
|
|
6
6
|
processType?: ProcessType;
|
|
7
7
|
roles?: string | string[];
|
|
8
8
|
}, 'memberOf' | 'roles'> | string | string[])[];
|
|
9
|
-
export declare
|
|
10
|
-
export declare
|
|
11
|
-
export declare
|
|
9
|
+
export declare function Restricted(...rolesOrMember: RestrictedType): ClassDecorator & PropertyDecorator;
|
|
10
|
+
export declare function getRestricted(object: unknown, propertyKey?: string): RestrictedType;
|
|
11
|
+
export declare function checkRestricted(data: any, user: {
|
|
12
12
|
emailVerified?: any;
|
|
13
13
|
hasRole: (roles: string[]) => boolean;
|
|
14
14
|
id: any;
|
|
@@ -28,4 +28,4 @@ export declare const checkRestricted: (data: any, user: {
|
|
|
28
28
|
processType?: ProcessType;
|
|
29
29
|
removeUndefinedFromResultArray?: boolean;
|
|
30
30
|
throwError?: boolean;
|
|
31
|
-
}, processedObjects?: WeakSet<object>)
|
|
31
|
+
}, processedObjects?: WeakSet<object>): any;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Restricted = Restricted;
|
|
4
|
+
exports.getRestricted = getRestricted;
|
|
5
|
+
exports.checkRestricted = checkRestricted;
|
|
4
6
|
const common_1 = require("@nestjs/common");
|
|
5
7
|
require("reflect-metadata");
|
|
6
8
|
const _ = require("lodash");
|
|
7
9
|
const role_enum_1 = require("../enums/role.enum");
|
|
8
|
-
const
|
|
10
|
+
const id_helper_1 = require("../helpers/id.helper");
|
|
9
11
|
const request_context_service_1 = require("../services/request-context.service");
|
|
10
12
|
const core_tenant_helpers_1 = require("../../modules/tenant/core-tenant.helpers");
|
|
11
13
|
const restrictedMetaKey = Symbol('restricted');
|
|
12
|
-
|
|
14
|
+
function Restricted(...rolesOrMember) {
|
|
13
15
|
return Reflect.metadata(restrictedMetaKey, rolesOrMember);
|
|
14
|
-
}
|
|
15
|
-
exports.Restricted = Restricted;
|
|
16
|
+
}
|
|
16
17
|
const restrictedMetadataCache = new WeakMap();
|
|
17
|
-
|
|
18
|
+
function getRestricted(object, propertyKey) {
|
|
18
19
|
if (!object) {
|
|
19
20
|
return null;
|
|
20
21
|
}
|
|
@@ -38,9 +39,8 @@ const getRestricted = (object, propertyKey) => {
|
|
|
38
39
|
: Reflect.getMetadata(restrictedMetaKey, object);
|
|
39
40
|
classCache.set(cacheKey, metadata);
|
|
40
41
|
return metadata;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const checkRestricted = (data, user, options = {}, processedObjects = new WeakSet()) => {
|
|
42
|
+
}
|
|
43
|
+
function checkRestricted(data, user, options = {}, processedObjects = new WeakSet()) {
|
|
44
44
|
const config = {
|
|
45
45
|
allowCreatorOfParent: true,
|
|
46
46
|
checkObjectItself: false,
|
|
@@ -70,7 +70,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
70
70
|
!Array.isArray(sample) &&
|
|
71
71
|
sample.constructor &&
|
|
72
72
|
sample.constructor !== Object) {
|
|
73
|
-
const classRestrictions =
|
|
73
|
+
const classRestrictions = getRestricted(sample.constructor) || [];
|
|
74
74
|
if (classRestrictions.length) {
|
|
75
75
|
const hasCreatorOrSelf = classRestrictions.some((r) => r === role_enum_1.RoleEnum.S_CREATOR ||
|
|
76
76
|
r === role_enum_1.RoleEnum.S_SELF ||
|
|
@@ -84,7 +84,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
84
84
|
r.roles === role_enum_1.RoleEnum.S_CREATOR ||
|
|
85
85
|
r.roles === role_enum_1.RoleEnum.S_SELF)));
|
|
86
86
|
if (!hasCreatorOrSelf) {
|
|
87
|
-
const sampleResult =
|
|
87
|
+
const sampleResult = checkRestricted(sample, user, config, processedObjects);
|
|
88
88
|
if (sampleResult === undefined || sampleResult === null) {
|
|
89
89
|
if (config.throwError) {
|
|
90
90
|
return data;
|
|
@@ -93,7 +93,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
93
93
|
}
|
|
94
94
|
const result = [sampleResult];
|
|
95
95
|
for (let i = 1; i < data.length; i++) {
|
|
96
|
-
result.push(
|
|
96
|
+
result.push(checkRestricted(data[i], user, config, processedObjects));
|
|
97
97
|
}
|
|
98
98
|
if (!config.throwError && config.removeUndefinedFromResultArray) {
|
|
99
99
|
return result.filter((item) => item !== undefined);
|
|
@@ -102,7 +102,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
let result = data.map((item) =>
|
|
105
|
+
let result = data.map((item) => checkRestricted(item, user, config, processedObjects));
|
|
106
106
|
if (!config.throwError && config.removeUndefinedFromResultArray) {
|
|
107
107
|
result = result.filter((item) => item !== undefined);
|
|
108
108
|
}
|
|
@@ -141,9 +141,9 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
141
141
|
if (roles.includes(role_enum_1.RoleEnum.S_EVERYONE) ||
|
|
142
142
|
user?.hasRole?.(roles) ||
|
|
143
143
|
(user?.id && roles.includes(role_enum_1.RoleEnum.S_USER)) ||
|
|
144
|
-
(roles.includes(role_enum_1.RoleEnum.S_SELF) && (0,
|
|
144
|
+
(roles.includes(role_enum_1.RoleEnum.S_SELF) && (0, id_helper_1.equalIds)(data, user)) ||
|
|
145
145
|
(roles.includes(role_enum_1.RoleEnum.S_CREATOR) &&
|
|
146
|
-
(('createdBy' in data && (0,
|
|
146
|
+
(('createdBy' in data && (0, id_helper_1.equalIds)(data.createdBy, user)) ||
|
|
147
147
|
(config.allowCreatorOfParent && !('createdBy' in data) && config.isCreatorOfParent))) ||
|
|
148
148
|
(roles.includes(role_enum_1.RoleEnum.S_VERIFIED) && (user?.verified || user?.verifiedAt || user?.emailVerified)) ||
|
|
149
149
|
(user?.id && (0, core_tenant_helpers_1.checkRoleAccess)(roles, user?.roles, request_context_service_1.RequestContext.get()?.tenantRole))) {
|
|
@@ -175,7 +175,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
if ((0,
|
|
178
|
+
if ((0, id_helper_1.getIncludedIds)(members, user)) {
|
|
179
179
|
valid = true;
|
|
180
180
|
}
|
|
181
181
|
}
|
|
@@ -185,7 +185,7 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
185
185
|
}
|
|
186
186
|
return valid;
|
|
187
187
|
};
|
|
188
|
-
const objectRestrictions =
|
|
188
|
+
const objectRestrictions = getRestricted(data.constructor) || [];
|
|
189
189
|
if (config.checkObjectItself) {
|
|
190
190
|
const objectIsValid = validateRestricted(objectRestrictions);
|
|
191
191
|
if (!objectIsValid) {
|
|
@@ -205,13 +205,13 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
205
205
|
if (data[propertyKey] === undefined && config.ignoreUndefined) {
|
|
206
206
|
continue;
|
|
207
207
|
}
|
|
208
|
-
const restricted =
|
|
208
|
+
const restricted = getRestricted(data, propertyKey) || [];
|
|
209
209
|
const concatenatedRestrictions = config.mergeRoles && objectRestrictions.length ? _.uniq(objectRestrictions.concat(restricted)) : restricted;
|
|
210
210
|
const valid = validateRestricted(concatenatedRestrictions);
|
|
211
211
|
if (valid) {
|
|
212
212
|
config.isCreatorOfParent =
|
|
213
|
-
(0,
|
|
214
|
-
data[propertyKey] =
|
|
213
|
+
(0, id_helper_1.equalIds)(data, user) || ('createdBy' in data ? (0, id_helper_1.equalIds)(data.createdBy, user) : config.isCreatorOfParent);
|
|
214
|
+
data[propertyKey] = checkRestricted(data[propertyKey], user, config, processedObjects);
|
|
215
215
|
}
|
|
216
216
|
else {
|
|
217
217
|
if (config.debug) {
|
|
@@ -224,6 +224,5 @@ const checkRestricted = (data, user, options = {}, processedObjects = new WeakSe
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
return data;
|
|
227
|
-
}
|
|
228
|
-
exports.checkRestricted = checkRestricted;
|
|
227
|
+
}
|
|
229
228
|
//# sourceMappingURL=restricted.decorator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restricted.decorator.js","sourceRoot":"","sources":["../../../../src/core/common/decorators/restricted.decorator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"restricted.decorator.js","sourceRoot":"","sources":["../../../../src/core/common/decorators/restricted.decorator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clone = clone;
|
|
4
|
+
exports.deepFreeze = deepFreeze;
|
|
5
|
+
const inspector = require("inspector");
|
|
6
|
+
const _ = require("lodash");
|
|
7
|
+
const rfdc = require("rfdc");
|
|
8
|
+
const util = require("util");
|
|
9
|
+
function clone(object, options) {
|
|
10
|
+
const config = {
|
|
11
|
+
checkResult: true,
|
|
12
|
+
circles: true,
|
|
13
|
+
debug: inspector.url() !== undefined,
|
|
14
|
+
proto: false,
|
|
15
|
+
...options,
|
|
16
|
+
};
|
|
17
|
+
try {
|
|
18
|
+
const cloned = rfdc(config)(object);
|
|
19
|
+
if (config.checkResult && !util.isDeepStrictEqual(object, cloned)) {
|
|
20
|
+
throw new Error('Cloned object differs from original object');
|
|
21
|
+
}
|
|
22
|
+
return cloned;
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
if (!config.circles) {
|
|
26
|
+
if (config.debug) {
|
|
27
|
+
console.debug(e, config, object, 'automatic try to use rfdc with circles');
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const clonedWithCircles = rfdc({
|
|
31
|
+
...config,
|
|
32
|
+
circles: true,
|
|
33
|
+
})(object);
|
|
34
|
+
if (config.checkResult && !util.isDeepStrictEqual(object, clonedWithCircles)) {
|
|
35
|
+
throw new Error('Cloned object differs from original object', { cause: e });
|
|
36
|
+
}
|
|
37
|
+
return clonedWithCircles;
|
|
38
|
+
}
|
|
39
|
+
catch (innerError) {
|
|
40
|
+
if (config.debug) {
|
|
41
|
+
console.debug(innerError, 'rfcd with circles did not work => automatic use of _.clone!');
|
|
42
|
+
}
|
|
43
|
+
return _.cloneDeep(object);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
if (config.debug) {
|
|
48
|
+
console.debug(e, config, object, 'automatic try to use _.clone instead rfdc');
|
|
49
|
+
}
|
|
50
|
+
return _.cloneDeep(object);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function deepFreeze(object, visited = new WeakSet()) {
|
|
55
|
+
if (!object || typeof object !== 'object') {
|
|
56
|
+
return object;
|
|
57
|
+
}
|
|
58
|
+
if (visited.has(object)) {
|
|
59
|
+
return object;
|
|
60
|
+
}
|
|
61
|
+
visited.add(object);
|
|
62
|
+
for (const [key, value] of Object.entries(object)) {
|
|
63
|
+
object[key] = deepFreeze(value, visited);
|
|
64
|
+
}
|
|
65
|
+
return Object.freeze(object);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=clone.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.helper.js","sourceRoot":"","sources":["../../../../src/core/common/helpers/clone.helper.ts"],"names":[],"mappings":";;AAkDA,sBA0CC;AAKD,gCAYC;AAjFD,uCAAuC;AACvC,4BAA6B;AAC7B,6BAA8B;AAC9B,6BAA6B;AAmB7B,SAAgB,KAAK,CAAC,MAAW,EAAE,OAAuE;IACxG,MAAM,MAAM,GAAG;QACb,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,KAAK,SAAS;QACpC,KAAK,EAAE,KAAK;QACZ,GAAG,OAAO;KACX,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,wCAAwC,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,iBAAiB,GAAG,IAAI,CAAC;oBAC7B,GAAG,MAAM;oBACT,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC,MAAM,CAAC,CAAC;gBACX,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAAE,CAAC;oBAC7E,MAAM,IAAI,KAAK,CAAC,4CAA4C,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9E,CAAC;gBACD,OAAO,iBAAiB,CAAC;YAC3B,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,6DAA6D,CAAC,CAAC;gBAC3F,CAAC;gBACD,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,2CAA2C,CAAC,CAAC;YAChF,CAAC;YACD,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC;AAKD,SAAgB,UAAU,CAAC,MAAW,EAAE,UAA2B,IAAI,OAAO,EAAE;IAC9E,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -1,35 +1,23 @@
|
|
|
1
1
|
import { FieldNode, GraphQLResolveInfo, SelectionNode } from 'graphql';
|
|
2
|
-
import { Document, Model, PopulateOptions, Query
|
|
2
|
+
import { Document, Model, PopulateOptions, Query } from 'mongoose';
|
|
3
3
|
import { CoreModel } from '../models/core-model.model';
|
|
4
4
|
import { FieldSelection } from '../types/field-selection.type';
|
|
5
5
|
import { IdsType } from '../types/ids.type';
|
|
6
6
|
import { StringOrObjectId } from '../types/string-or-object-id.type';
|
|
7
|
+
export { equalIds, getIncludedIds, getObjectIds, getStringIds } from './id.helper';
|
|
7
8
|
export declare function addIds(target: any, ids: StringOrObjectId | StringOrObjectId[], convert?: 'auto' | 'object' | 'string' | false, options?: {
|
|
8
9
|
unique?: boolean;
|
|
9
10
|
}): any[];
|
|
10
11
|
export declare function checkStringIds(ids: string | string[]): boolean;
|
|
11
|
-
export declare function equalIds(...ids: IdsType[]): boolean;
|
|
12
12
|
export declare function getElementsViaIds<T = any>(ids: any | any[], array: T[], options?: {
|
|
13
13
|
splice?: boolean;
|
|
14
14
|
unique?: boolean;
|
|
15
15
|
}): T[];
|
|
16
|
-
export declare function getIncludedIds(includes: IdsType, ids: IdsType, convert?: 'string'): string[];
|
|
17
|
-
export declare function getIncludedIds(includes: IdsType, ids: IdsType, convert?: 'object'): Types.ObjectId[];
|
|
18
16
|
export declare function getIndexesViaIds(ids: IdsType, array: IdsType): number[];
|
|
19
17
|
export declare function getJSONClone<T = any>(obj: T): Partial<T>;
|
|
20
18
|
export declare function getNextFieldNodes(nodes: readonly SelectionNode[]): FieldNode[];
|
|
21
|
-
export declare function getObjectIds(ids: any[]): Types.ObjectId[];
|
|
22
|
-
export declare function getObjectIds(ids: any): Types.ObjectId;
|
|
23
19
|
export declare function getPopulateOptions(info: GraphQLResolveInfo, dotSeparatedSelect?: string): PopulateOptions[];
|
|
24
20
|
export declare function getPopulatOptionsFromSelections(selectionNodes: readonly SelectionNode[]): PopulateOptions[];
|
|
25
|
-
export declare function getStringIds(elements: any[], options?: {
|
|
26
|
-
deep?: boolean;
|
|
27
|
-
unique?: boolean;
|
|
28
|
-
}): string[];
|
|
29
|
-
export declare function getStringIds(elements: any, options?: {
|
|
30
|
-
deep?: boolean;
|
|
31
|
-
unique?: boolean;
|
|
32
|
-
}): string;
|
|
33
21
|
export declare function objectIdsToStrings(element: any, prepared?: WeakMap<any, any>): any;
|
|
34
22
|
export declare function popAndMap<T extends CoreModel>(queryOrDocument: Document | Document[] | Query<any, any>, populate: FieldSelection, modelClass: new (...args: any[]) => T, mongooseModel?: Model<any>, options?: {
|
|
35
23
|
ignoreSelections?: boolean;
|