@lenne.tech/nest-server 11.33.1 → 11.34.0
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/testing.md +181 -3
- package/FRAMEWORK-API.md +1 -1
- package/dist/core/common/helpers/gridfs.helper.d.ts +1 -0
- package/dist/core/common/helpers/gridfs.helper.js +43 -5
- package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
- package/dist/core/common/services/core-s3.service.d.ts +4 -0
- package/dist/core/common/services/core-s3.service.js +28 -1
- package/dist/core/common/services/core-s3.service.js.map +1 -1
- package/dist/core/modules/file/core-file.service.d.ts +4 -2
- package/dist/core/modules/file/core-file.service.js +46 -47
- package/dist/core/modules/file/core-file.service.js.map +1 -1
- package/dist/core/modules/hub/helpers/hub-client-js.helper.js +12 -1
- package/dist/core/modules/hub/helpers/hub-client-js.helper.js.map +1 -1
- package/dist/core/modules/hub/hub-action-messages.d.ts +1 -0
- package/dist/core/modules/hub/hub-action-messages.js +1 -0
- package/dist/core/modules/hub/hub-action-messages.js.map +1 -1
- package/dist/core/modules/hub/interfaces/hub-panels.interface.d.ts +9 -0
- package/dist/core/modules/hub/services/core-hub-actions.service.d.ts +2 -0
- package/dist/core/modules/hub/services/core-hub-actions.service.js.map +1 -1
- package/dist/core/modules/hub/services/core-hub-db.service.d.ts +10 -2
- package/dist/core/modules/hub/services/core-hub-db.service.js +85 -29
- package/dist/core/modules/hub/services/core-hub-db.service.js.map +1 -1
- package/dist/server/modules/file/file.service.d.ts +2 -1
- package/dist/server/modules/file/file.service.js +2 -2
- package/dist/server/modules/file/file.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/migration-guides/11.23.x-to-11.24.0.md +1 -1
- package/migration-guides/11.32.x-to-11.33.x.md +2 -0
- package/migration-guides/11.33.x-to-11.34.x.md +394 -0
- package/package.json +3 -1
- package/src/core/common/helpers/gridfs.helper.ts +92 -7
- package/src/core/common/services/core-s3.service.ts +71 -9
- package/src/core/modules/file/README.md +42 -6
- package/src/core/modules/file/core-file.service.ts +131 -59
- package/src/core/modules/hub/README.md +35 -9
- package/src/core/modules/hub/helpers/hub-client-js.helper.ts +12 -1
- package/src/core/modules/hub/hub-action-messages.ts +9 -1
- package/src/core/modules/hub/interfaces/hub-panels.interface.ts +31 -1
- package/src/core/modules/hub/services/core-hub-actions.service.ts +10 -2
- package/src/core/modules/hub/services/core-hub-db.service.ts +155 -31
- package/src/server/modules/file/file.service.ts +20 -3
package/.claude/rules/testing.md
CHANGED
|
@@ -34,7 +34,7 @@ mis-named suite fails the build instead of silently passing. Type-only tests
|
|
|
34
34
|
|
|
35
35
|
## Infrastructure containers (Redis + S3)
|
|
36
36
|
|
|
37
|
-
**
|
|
37
|
+
**Eight** e2e suites talk to a **real** Redis and/or a **real** S3-compatible store rather than a
|
|
38
38
|
mock, and they **fail loudly** when it is missing — a silently skipped infrastructure test is how an
|
|
39
39
|
untested driver ships:
|
|
40
40
|
|
|
@@ -44,13 +44,14 @@ untested driver ships:
|
|
|
44
44
|
| `tests/redis-consumers.e2e-spec.ts` | Redis |
|
|
45
45
|
| `tests/multi-replica.e2e-spec.ts` | Redis |
|
|
46
46
|
| `tests/s3-infra.e2e-spec.ts` | S3 |
|
|
47
|
-
| `tests/file-storage-
|
|
47
|
+
| `tests/file-storage-parity.e2e-spec.ts` | S3 |
|
|
48
|
+
| `tests/file-storage-http-parity.e2e-spec.ts` | S3 |
|
|
48
49
|
| `tests/redis-s3-bootstrap.e2e-spec.ts` | Redis + S3 |
|
|
49
50
|
| `tests/graceful-shutdown.e2e-spec.ts` | Redis + S3 |
|
|
50
51
|
|
|
51
52
|
`tests/global-setup.ts` starts both containers automatically, so `pnpm test` works from a clean
|
|
52
53
|
machine with no manual docker command. It is idempotent (a running container is reused) and never
|
|
53
|
-
fatal: without Docker every other suite still runs, and the
|
|
54
|
+
fatal: without Docker every other suite still runs, and the eight above report their own actionable
|
|
54
55
|
error.
|
|
55
56
|
|
|
56
57
|
```bash
|
|
@@ -153,6 +154,179 @@ pnpm run test:cleanup
|
|
|
153
154
|
- Coverage: Collected from `src/**/*.{ts,js}`. The two runners are separate vitest processes, so
|
|
154
155
|
they write separate reports (`coverage/unit`, `coverage/e2e`) rather than overwriting each other.
|
|
155
156
|
|
|
157
|
+
## Behaviour matrices: test the CONTRACT once, against every implementation
|
|
158
|
+
|
|
159
|
+
**Rule: when one contract has several interchangeable implementations, there is ONE list of
|
|
160
|
+
behaviours and it runs against all of them. Never one suite per implementation.**
|
|
161
|
+
|
|
162
|
+
File storage is the worked example, and it is a worked example because getting it wrong shipped two
|
|
163
|
+
defects. Three drivers (`filesystem`, `gridfs`, `s3`) sat behind one `CoreFileService` contract with
|
|
164
|
+
one suite each — different files, different drivers, overlapping intent, no shared list. A behaviour
|
|
165
|
+
that was correct under GridFS and broken under `filesystem` had nowhere to surface. 11.33.0 shipped
|
|
166
|
+
exactly that (`getRawFileInfoByName()` consulted two of the three stores), and every suite was green.
|
|
167
|
+
|
|
168
|
+
| Piece | Where |
|
|
169
|
+
|-------|-------|
|
|
170
|
+
| The matrix — cases, drivers, exclusions, folded-in receipts | `tests/helpers/file-storage-matrix.ts` |
|
|
171
|
+
| Per-driver plumbing (config, planting into a non-active store, byte probes) | `tests/helpers/file-storage-drivers.ts` |
|
|
172
|
+
| Service-contract executor | `tests/file-storage-parity.e2e-spec.ts` |
|
|
173
|
+
| Route-contract executor (boots the real `ServerModule` per driver) | `tests/file-storage-http-parity.e2e-spec.ts` |
|
|
174
|
+
| Structural guard | `tests/unit/file-storage-parity-matrix.spec.ts` |
|
|
175
|
+
|
|
176
|
+
### A cell is EXECUTED, IMPOSSIBLE, or DIFFERENT-BY-DESIGN — never merely absent
|
|
177
|
+
|
|
178
|
+
Omitting a case for one implementation and declaring it impossible there produce the same artefact
|
|
179
|
+
in a report: nothing. That is how a gap hides, so the three states are declared and the guard fails
|
|
180
|
+
on anything else:
|
|
181
|
+
|
|
182
|
+
- **EXECUTED** — the case lists the driver; the executor registers a real `it()` via `parityIt()`.
|
|
183
|
+
- **IMPOSSIBLE:** — the behaviour has no equivalent primitive in that store. No `provenBy`, nothing
|
|
184
|
+
registered; there is nothing to assert instead.
|
|
185
|
+
- **DIFFERENT-BY-DESIGN:** — the driver behaves differently on purpose. MUST name a `provenBy` case
|
|
186
|
+
that runs for that driver, and MUST register a `parityComplement()` asserting what happens
|
|
187
|
+
instead. A design difference nobody asserts is indistinguishable from a bug nobody noticed.
|
|
188
|
+
|
|
189
|
+
An exclusion is a claim about the PRODUCT. If you are adding one to get green, you are writing down
|
|
190
|
+
a bug.
|
|
191
|
+
|
|
192
|
+
### Consolidating suites requires a receipt
|
|
193
|
+
|
|
194
|
+
Folding a per-implementation suite into the matrix must not trade breadth for tidiness. Each case
|
|
195
|
+
the old suite asserted gets an entry in `FOLDED_IN` (`from`, `was`, `into`), and the guard asserts
|
|
196
|
+
every `into` still names a live case, that the folded-in cases cover **all** drivers, and that the
|
|
197
|
+
origin files are gone rather than left behind to drift.
|
|
198
|
+
|
|
199
|
+
## Regression tests must carry their evidence
|
|
200
|
+
|
|
201
|
+
**Rule: a test that claims to pin a defect declares `@regression` AND `@seen-failing`, and the
|
|
202
|
+
`@seen-failing` line names a mutation registered in `tests/regression-mutations.json`.**
|
|
203
|
+
|
|
204
|
+
### Why — two vacuous tests, in the session that was fixing the bug
|
|
205
|
+
|
|
206
|
+
While fixing 11.33.1, two tests written specifically to pin the defect **passed with the defect
|
|
207
|
+
fully restored**:
|
|
208
|
+
|
|
209
|
+
1. The `deleteFileByName()` ownership case drove a rule that read a missing `currentUser` as
|
|
210
|
+
"internal, allow". The broken, context-less inner lookup therefore succeeded too, and the whole
|
|
211
|
+
assertion held with the bug present. It only detects anything because the rule now **fails
|
|
212
|
+
closed**.
|
|
213
|
+
2. A by-name lookup case asserted around the defect rather than on it.
|
|
214
|
+
|
|
215
|
+
Both were caught only because somebody re-broke the source by hand and re-ran them. A green test
|
|
216
|
+
looks identical whether it is checking something or nothing; the single thing that separates the two
|
|
217
|
+
is having watched it go red — and that observation used to live in terminal scrollback.
|
|
218
|
+
|
|
219
|
+
### The convention
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
/**
|
|
223
|
+
* @regression 11.33.1 — deleteFileByName() re-resolved the file with an EMPTY context, so an
|
|
224
|
+
* overridden checkRights() was asked two different questions about one request.
|
|
225
|
+
* @seen-failing Drop `serviceOptions` from the getFileInfoByName() call in
|
|
226
|
+
* src/core/modules/file/core-file.service.ts — registered as mutation
|
|
227
|
+
* `delete-by-name-drops-context` in tests/regression-mutations.json.
|
|
228
|
+
*/
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
pnpm run check:mutations # apply every registered mutation, require its specs to go RED
|
|
233
|
+
pnpm run check:mutations -- --id=<id> # one mutation
|
|
234
|
+
pnpm run check:mutations -- --list # the registry, without running anything
|
|
235
|
+
pnpm run check:mutations -- --allow-dirty # when the fix and its evidence share a working tree
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Not part of `pnpm run check` — it edits source and re-runs whole e2e suites. It belongs in review
|
|
239
|
+
and on the publish path. Between runs the registry is kept from rotting by
|
|
240
|
+
`tests/unit/regression-evidence.spec.ts`, which asserts every `find` still matches its target
|
|
241
|
+
**exactly once**: a stale mutation would silently become a no-op, and a no-op "confirms" evidence
|
|
242
|
+
that was never checked.
|
|
243
|
+
|
|
244
|
+
`tests/unit/regression-evidence.spec.ts` also enforces the other direction — every registered
|
|
245
|
+
mutation must be referenced by some `@regression` block, and each referenced mutation must actually
|
|
246
|
+
run the file the tag lives in.
|
|
247
|
+
|
|
248
|
+
Free prose ("Regression guard: …") is untouched by any of this. It predates the convention and often
|
|
249
|
+
sits on tests whose defect has no reachable mutation any more; retro-fitting it would produce
|
|
250
|
+
ceremony, not evidence. **The tag is the promise.**
|
|
251
|
+
|
|
252
|
+
### What a reviewer must ask for
|
|
253
|
+
|
|
254
|
+
When a change adds or edits a test that claims to fix or pin a bug:
|
|
255
|
+
|
|
256
|
+
1. **"Show me it red."** Either the `@seen-failing` line with a registered mutation id, or the
|
|
257
|
+
pasted output of `pnpm run check:mutations -- --id=<id>`.
|
|
258
|
+
2. **"Which cases went red, and under which driver/configuration?"** One red case where you expected
|
|
259
|
+
four means the mutation is not the defect, or the coverage is narrower than claimed.
|
|
260
|
+
3. **"Would a permissive fixture also make this pass?"** For anything driving an authorization hook,
|
|
261
|
+
the paired refusal case is mandatory — without it, a rule that has silently gone permissive
|
|
262
|
+
explains the green just as well as the fix does.
|
|
263
|
+
4. **"Is the mutation the defect, or a proxy for it?"** A mutation that breaks everything proves
|
|
264
|
+
nothing about the specific behaviour.
|
|
265
|
+
|
|
266
|
+
## Consumer gate: the starter runs BEFORE publish, not after
|
|
267
|
+
|
|
268
|
+
`pnpm run check:consumer` builds the tarball (`pnpm pack`), installs it into a **throwaway copy** of
|
|
269
|
+
`nest-server-starter`, and runs the consumer's own checks against it.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
pnpm run check:consumer # full: the starter's own `check`
|
|
273
|
+
pnpm run check:consumer -- --fast # typecheck + build + tests (~5 min)
|
|
274
|
+
pnpm run check:consumer -- --starter=<path> # else ../nest-server-starter, or NEST_SERVER_STARTER_PATH
|
|
275
|
+
pnpm run check:consumer -- --keep # keep the workspace for inspection
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
It is not a duplicate of `pnpm run check`. This repo's suite exercises `src/server` — a consumer
|
|
279
|
+
that, by construction, tracks every framework change in the same commit and imports `src/` by
|
|
280
|
+
relative path. The starter does neither: it subclasses the shipped `Core*` classes and consumes
|
|
281
|
+
`dist/` through the package's public entry points. It therefore catches what nothing else can: a
|
|
282
|
+
`files`/`exports` mistake that drops something from the tarball, a signature change only a
|
|
283
|
+
**subclass** notices, a `devDependency` used at runtime by framework code, and behaviour that
|
|
284
|
+
differs under the starter's configuration.
|
|
285
|
+
|
|
286
|
+
Wired into `.github/workflows/publish.yml` before the publish step, with `--fast`. Deliberately not
|
|
287
|
+
on every push (~5 minutes), and deliberately not the starter's full `check` in CI: that also runs
|
|
288
|
+
the starter's own `pnpm audit` / `format:check` / `lint`, none of which say anything about our
|
|
289
|
+
tarball — a fresh advisory in one of the starter's own dependencies would otherwise block an
|
|
290
|
+
unrelated release.
|
|
291
|
+
|
|
292
|
+
## Consumer contracts: exercise the extension points, in executed code
|
|
293
|
+
|
|
294
|
+
**Rule: an overridable seam that only `src/server`'s defaults ever touch is an untested seam.**
|
|
295
|
+
`src/server` IS a consumer of `src/core`, but for a long time it was a consumer that took every
|
|
296
|
+
default — and a `@Restricted`/`checkRights()`/`securityCheck()` override documented only in a JSDoc
|
|
297
|
+
`@example` is never compiled, never type-checked and never run.
|
|
298
|
+
|
|
299
|
+
| Seam | Contract suite |
|
|
300
|
+
|------|----------------|
|
|
301
|
+
| `CoreFileService.checkRights()` | `tests/file-ownership.e2e-spec.ts` (+ the parity matrix, per driver) |
|
|
302
|
+
| `CoreModel.securityCheck()` | `tests/security-check-contract.e2e-spec.ts` |
|
|
303
|
+
|
|
304
|
+
A contract suite tests the SEAM, not one consumer of it. `security-check-contract` is the shape to
|
|
305
|
+
copy: its models' `securityCheck()` **records its own invocation** (`checkedFor`) as well as
|
|
306
|
+
narrowing fields, so "the response looks redacted" — which a `@Restricted` rule, `prepareOutput` or
|
|
307
|
+
a typo in the fixture would produce too — becomes "the hook ran, with this user, on this object".
|
|
308
|
+
|
|
309
|
+
## Structural invariants over `src/`
|
|
310
|
+
|
|
311
|
+
Some properties cannot be observed by running the code, only by reading it — and a runtime guard
|
|
312
|
+
catches the *failure*, never the *disarming* of the safety property.
|
|
313
|
+
|
|
314
|
+
| Invariant | Guard |
|
|
315
|
+
|-----------|-------|
|
|
316
|
+
| DI tokens live in import-free leaves (SWC/TDZ) | `tests/unit/import-cycle-invariants.spec.ts` |
|
|
317
|
+
| Internal calls forward the caller's `ServiceOptions` | `tests/unit/service-options-forwarding.spec.ts` |
|
|
318
|
+
| The parity matrix is complete and honest | `tests/unit/file-storage-parity-matrix.spec.ts` |
|
|
319
|
+
| Regression tests carry re-runnable evidence | `tests/unit/regression-evidence.spec.ts` |
|
|
320
|
+
|
|
321
|
+
`service-options-forwarding` is 11.33.1 generalised: inside `src/core/`, a method that HAS the
|
|
322
|
+
caller's context must pass it to every internal call that accepts one. Passing a local derived from
|
|
323
|
+
it counts (`const config = { ...serviceOptions, … }`). A call that must genuinely run context-free
|
|
324
|
+
says so at the call site — the opt-out is a claim about authorization, so it belongs in the diff:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// serviceOptions-forwarding: <why this call must not carry the caller's context>
|
|
328
|
+
```
|
|
329
|
+
|
|
156
330
|
## Test Best Practices
|
|
157
331
|
|
|
158
332
|
1. **Always run tests before completing changes**: `pnpm test`
|
|
@@ -160,6 +334,10 @@ pnpm run test:cleanup
|
|
|
160
334
|
3. **Use TestHelper** for GraphQL and REST API testing
|
|
161
335
|
4. **Clean up test data** in `afterAll` hooks
|
|
162
336
|
5. **Unique test data** - Use timestamps/random strings to avoid conflicts
|
|
337
|
+
6. **One contract, one matrix** — see "Behaviour matrices" above before writing a second suite for
|
|
338
|
+
the same contract with a different implementation
|
|
339
|
+
7. **A regression test carries `@regression` + `@seen-failing`** — see "Regression tests must carry
|
|
340
|
+
their evidence"
|
|
163
341
|
|
|
164
342
|
## Test File Structure
|
|
165
343
|
|
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-08-
|
|
3
|
+
> Auto-generated from source code on 2026-08-12 (v11.34.0)
|
|
4
4
|
> File: `FRAMEWORK-API.md` — compact, machine-readable API surface for Claude Code
|
|
5
5
|
|
|
6
6
|
## CoreModule.forRoot()
|
|
@@ -29,6 +29,7 @@ export declare class GridFSHelper {
|
|
|
29
29
|
static findFileById(bucket: GridFSBucket, id: string | Types.ObjectId): Promise<GridFSFileInfo | null>;
|
|
30
30
|
static findFileByName(bucket: GridFSBucket, filename: string): Promise<GridFSFileInfo | null>;
|
|
31
31
|
static findFiles(bucket: GridFSBucket, filter?: any, options?: any): Promise<GridFSFileInfo[]>;
|
|
32
|
+
private static mapContentTypeKeys;
|
|
32
33
|
static deleteFile(bucket: GridFSBucket, id: string | Types.ObjectId): Promise<void>;
|
|
33
34
|
static openDownloadStream(bucket: GridFSBucket, id: string | Types.ObjectId): GridFSBucketReadStream;
|
|
34
35
|
static openDownloadStreamByName(bucket: GridFSBucket, filename: string): GridFSBucketReadStream;
|
|
@@ -19,8 +19,30 @@ class GridFSHelper {
|
|
|
19
19
|
const uploadStream = bucket.openUploadStream(options.filename, {
|
|
20
20
|
metadata,
|
|
21
21
|
});
|
|
22
|
-
|
|
22
|
+
let settled = false;
|
|
23
|
+
const fail = (error) => {
|
|
24
|
+
if (settled) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
settled = true;
|
|
23
28
|
reject(error);
|
|
29
|
+
};
|
|
30
|
+
const succeed = (fileInfo) => {
|
|
31
|
+
if (settled) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
settled = true;
|
|
35
|
+
resolve(fileInfo);
|
|
36
|
+
};
|
|
37
|
+
stream.on('error', (error) => {
|
|
38
|
+
Promise.resolve(uploadStream.abort?.()).catch(() => undefined);
|
|
39
|
+
fail(error);
|
|
40
|
+
});
|
|
41
|
+
uploadStream.on('error', (error) => {
|
|
42
|
+
if (!stream.destroyed) {
|
|
43
|
+
stream.destroy();
|
|
44
|
+
}
|
|
45
|
+
fail(error);
|
|
24
46
|
});
|
|
25
47
|
uploadStream.on('finish', () => {
|
|
26
48
|
bucket
|
|
@@ -28,13 +50,13 @@ class GridFSHelper {
|
|
|
28
50
|
.toArray()
|
|
29
51
|
.then((files) => {
|
|
30
52
|
if (files && files.length > 0) {
|
|
31
|
-
|
|
53
|
+
succeed(GridFSHelper.normalizeFileInfo(files[0]));
|
|
32
54
|
}
|
|
33
55
|
else {
|
|
34
|
-
|
|
56
|
+
fail(new Error('File uploaded but metadata not found'));
|
|
35
57
|
}
|
|
36
58
|
})
|
|
37
|
-
.catch(
|
|
59
|
+
.catch(fail);
|
|
38
60
|
});
|
|
39
61
|
stream.pipe(uploadStream);
|
|
40
62
|
});
|
|
@@ -74,9 +96,25 @@ class GridFSHelper {
|
|
|
74
96
|
return files.length > 0 ? GridFSHelper.normalizeFileInfo(files[0]) : null;
|
|
75
97
|
}
|
|
76
98
|
static async findFiles(bucket, filter = {}, options = {}) {
|
|
77
|
-
const
|
|
99
|
+
const query = GridFSHelper.mapContentTypeKeys(filter);
|
|
100
|
+
const findOptions = options && options.sort ? { ...options, sort: GridFSHelper.mapContentTypeKeys(options.sort) } : options;
|
|
101
|
+
const files = await bucket.find(query, findOptions).toArray();
|
|
78
102
|
return files.map((file) => GridFSHelper.normalizeFileInfo(file));
|
|
79
103
|
}
|
|
104
|
+
static mapContentTypeKeys(value) {
|
|
105
|
+
if (Array.isArray(value)) {
|
|
106
|
+
return value.map((entry) => GridFSHelper.mapContentTypeKeys(entry));
|
|
107
|
+
}
|
|
108
|
+
if (!value || typeof value !== 'object' || value instanceof RegExp || value instanceof Date) {
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
const mapped = {};
|
|
112
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
113
|
+
const nested = key === '$and' || key === '$nor' || key === '$or' ? GridFSHelper.mapContentTypeKeys(entry) : entry;
|
|
114
|
+
mapped[key === 'contentType' ? 'metadata.contentType' : key] = nested;
|
|
115
|
+
}
|
|
116
|
+
return mapped;
|
|
117
|
+
}
|
|
80
118
|
static async deleteFile(bucket, id) {
|
|
81
119
|
const objectId = typeof id === 'string' ? new ObjectId(id) : id;
|
|
82
120
|
await bucket.delete(objectId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridfs.helper.js","sourceRoot":"","sources":["../../../../src/core/common/helpers/gridfs.helper.ts"],"names":[],"mappings":";;;AAAA,uCAAwC;AAIxC,MAAM,QAAQ,GAAG,gBAAK,CAAC,QAAQ,CAAC;AAyDhC,MAAa,YAAY;IAKf,MAAM,CAAC,iBAAiB,CAAC,QAAuB;QACtD,OAAO;YACL,GAAG,QAAQ;YACX,WAAW,EAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW;SAC5C,CAAC;IACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"gridfs.helper.js","sourceRoot":"","sources":["../../../../src/core/common/helpers/gridfs.helper.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,10 @@ export declare class CoreS3Service implements OnApplicationShutdown, OnModuleIni
|
|
|
28
28
|
protected bucketExists(bucket: string): Promise<boolean>;
|
|
29
29
|
getClient(): S3Client;
|
|
30
30
|
putObject(key: string, body: Buffer | Readable | string, contentType?: string, contentLength?: number): Promise<void>;
|
|
31
|
+
protected guardBodyStream(stream: Readable): {
|
|
32
|
+
body: Readable;
|
|
33
|
+
sourceError: () => Error | undefined;
|
|
34
|
+
};
|
|
31
35
|
copyObject(sourceKey: string, destinationKey: string, sourceBucket?: string, contentType?: string): Promise<void>;
|
|
32
36
|
static readonly MAX_COPY_OBJECT_BYTES: number;
|
|
33
37
|
protected copySource(bucket: string, key: string): string;
|
|
@@ -12,6 +12,7 @@ var CoreS3Service_1;
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.CoreS3Service = void 0;
|
|
14
14
|
const common_1 = require("@nestjs/common");
|
|
15
|
+
const stream_1 = require("stream");
|
|
15
16
|
const content_disposition_helper_1 = require("../helpers/content-disposition.helper");
|
|
16
17
|
const config_service_1 = require("./config.service");
|
|
17
18
|
const MAX_PRESIGNED_EXPIRY_SECONDS = 604_800;
|
|
@@ -148,13 +149,39 @@ let CoreS3Service = class CoreS3Service {
|
|
|
148
149
|
else if (length === undefined && typeof body !== 'string') {
|
|
149
150
|
length = body.length;
|
|
150
151
|
}
|
|
151
|
-
|
|
152
|
+
const send = () => client.send(new sdk.PutObjectCommand({
|
|
152
153
|
Body: payload,
|
|
153
154
|
Bucket: config.bucket,
|
|
154
155
|
...(contentType ? { ContentType: contentType } : {}),
|
|
155
156
|
...(length === undefined ? {} : { ContentLength: length }),
|
|
156
157
|
Key: key,
|
|
157
158
|
}));
|
|
159
|
+
if (this.isStream(payload)) {
|
|
160
|
+
const guard = this.guardBodyStream(payload);
|
|
161
|
+
payload = guard.body;
|
|
162
|
+
try {
|
|
163
|
+
await send();
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw guard.sourceError() ?? error;
|
|
167
|
+
}
|
|
168
|
+
const failure = guard.sourceError();
|
|
169
|
+
if (failure) {
|
|
170
|
+
throw failure;
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
await send();
|
|
175
|
+
}
|
|
176
|
+
guardBodyStream(stream) {
|
|
177
|
+
const relay = new stream_1.PassThrough();
|
|
178
|
+
let sourceError;
|
|
179
|
+
stream.on('error', (error) => {
|
|
180
|
+
sourceError = error;
|
|
181
|
+
relay.end();
|
|
182
|
+
});
|
|
183
|
+
stream.pipe(relay);
|
|
184
|
+
return { body: relay, sourceError: () => sourceError };
|
|
158
185
|
}
|
|
159
186
|
async copyObject(sourceKey, destinationKey, sourceBucket, contentType) {
|
|
160
187
|
const { client, config, sdk } = this.requireInit();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core-s3.service.js","sourceRoot":"","sources":["../../../../src/core/common/services/core-s3.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAyF;
|
|
1
|
+
{"version":3,"file":"core-s3.service.js","sourceRoot":"","sources":["../../../../src/core/common/services/core-s3.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,10 +34,12 @@ export declare abstract class CoreFileService {
|
|
|
34
34
|
protected findFilesystemFileByName(filename: string): Promise<FilesystemFileInfo | null>;
|
|
35
35
|
createFile(file: MaybePromise<FileUploadSource>, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo>;
|
|
36
36
|
createFiles(files: MaybePromise<FileUploadSource>[], serviceOptions?: FileServiceOptions): Promise<CoreFileInfo[]>;
|
|
37
|
-
duplicateByName(name: string, newName: string): Promise<
|
|
38
|
-
duplicateById(id: string): Promise<string>;
|
|
37
|
+
duplicateByName(name: string, newName: string, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo>;
|
|
38
|
+
duplicateById(id: string | Types.ObjectId, serviceOptions?: FileServiceOptions): Promise<string>;
|
|
39
|
+
protected duplicateFile(source: CoreFileInfo, newName: string, openSourceStream: () => Promise<Readable>, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo>;
|
|
39
40
|
findFileInfo(filterArgs?: FilterArgs, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo[]>;
|
|
40
41
|
protected sortMergedFileInfo<T extends Record<string, any>>(docs: T[], sort?: Record<string, any>): T[];
|
|
42
|
+
protected readSortField(doc: Record<string, any>, field: string): any;
|
|
41
43
|
getFileInfo(id: string | Types.ObjectId, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo>;
|
|
42
44
|
getFileInfoByName(filename: string, serviceOptions?: FileServiceOptions): Promise<CoreFileInfo>;
|
|
43
45
|
getFileStream(id: string | Types.ObjectId, serviceOptions?: FileServiceOptions, knownStore?: FileStorageDriver): Promise<Readable>;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CoreFileService = void 0;
|
|
4
4
|
const common_1 = require("@nestjs/common");
|
|
5
5
|
const mongoose_1 = require("mongoose");
|
|
6
|
+
const access_denied_exception_1 = require("../../common/exceptions/access-denied.exception");
|
|
6
7
|
const db_helper_1 = require("../../common/helpers/db.helper");
|
|
7
8
|
const filter_helper_1 = require("../../common/helpers/filter.helper");
|
|
8
9
|
const gridfs_helper_1 = require("../../common/helpers/gridfs.helper");
|
|
@@ -93,55 +94,37 @@ class CoreFileService {
|
|
|
93
94
|
}
|
|
94
95
|
return await Promise.all(promises);
|
|
95
96
|
}
|
|
96
|
-
async duplicateByName(name, newName) {
|
|
97
|
-
const
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
return this.createFile({
|
|
101
|
-
createReadStream: () => source,
|
|
102
|
-
filename: newName,
|
|
103
|
-
mimetype: nonGridFsSource.contentType || 'application/octet-stream',
|
|
104
|
-
});
|
|
97
|
+
async duplicateByName(name, newName, serviceOptions) {
|
|
98
|
+
const source = await this.getFileInfoByName(name, serviceOptions);
|
|
99
|
+
if (!source) {
|
|
100
|
+
throw new common_1.NotFoundException(`File not found with filename ${name}`);
|
|
105
101
|
}
|
|
106
|
-
return
|
|
107
|
-
const downloadStream = gridfs_helper_1.GridFSHelper.openDownloadStreamByName(this.files, name);
|
|
108
|
-
downloadStream.on('error', reject);
|
|
109
|
-
const uploadStream = gridfs_helper_1.GridFSHelper.openUploadStream(this.files, newName);
|
|
110
|
-
uploadStream.on('error', reject);
|
|
111
|
-
uploadStream.on('finish', () => resolve(uploadStream));
|
|
112
|
-
downloadStream.pipe(uploadStream);
|
|
113
|
-
});
|
|
102
|
+
return this.duplicateFile(source, newName, () => this.getFileStreamByName(name, serviceOptions), serviceOptions);
|
|
114
103
|
}
|
|
115
|
-
async duplicateById(id) {
|
|
104
|
+
async duplicateById(id, serviceOptions) {
|
|
116
105
|
const objectId = (0, db_helper_1.getObjectIds)(id);
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const source = await this.getFileStream(objectId);
|
|
121
|
-
const copy = await this.createFile({
|
|
122
|
-
createReadStream: () => source,
|
|
123
|
-
filename: file.filename,
|
|
124
|
-
mimetype: file.contentType || 'application/octet-stream',
|
|
125
|
-
});
|
|
126
|
-
return copy.id;
|
|
106
|
+
const source = await this.getFileInfo(objectId, serviceOptions);
|
|
107
|
+
if (!source) {
|
|
108
|
+
throw new common_1.NotFoundException(`File not found with id ${(0, db_helper_1.getStringIds)(objectId)}`);
|
|
127
109
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
110
|
+
const copy = await this.duplicateFile(source, source.filename, () => this.getFileStream(objectId, serviceOptions), serviceOptions);
|
|
111
|
+
return copy.id;
|
|
112
|
+
}
|
|
113
|
+
async duplicateFile(source, newName, openSourceStream, serviceOptions) {
|
|
114
|
+
const stream = await openSourceStream();
|
|
115
|
+
if (!stream) {
|
|
116
|
+
throw new common_1.NotFoundException(`File not found with filename ${source.filename}`);
|
|
117
|
+
}
|
|
118
|
+
const copy = await this.createFile({
|
|
119
|
+
createReadStream: () => stream,
|
|
120
|
+
filename: newName,
|
|
121
|
+
mimetype: source.contentType || 'application/octet-stream',
|
|
122
|
+
}, serviceOptions);
|
|
123
|
+
if (!copy) {
|
|
124
|
+
stream.destroy?.();
|
|
125
|
+
throw (0, access_denied_exception_1.accessDeniedException)(serviceOptions?.currentUser);
|
|
126
|
+
}
|
|
127
|
+
return copy;
|
|
145
128
|
}
|
|
146
129
|
async findFileInfo(filterArgs, serviceOptions) {
|
|
147
130
|
if (!(await this.checkRights(filterArgs, { ...serviceOptions, checkInputType: 'filterArgs' }))) {
|
|
@@ -169,8 +152,8 @@ class CoreFileService {
|
|
|
169
152
|
const effective = spec.length ? spec : [['uploadDate', -1]];
|
|
170
153
|
return [...docs].sort((a, b) => {
|
|
171
154
|
for (const [field, direction] of effective) {
|
|
172
|
-
const left = a
|
|
173
|
-
const right = b
|
|
155
|
+
const left = this.readSortField(a, field);
|
|
156
|
+
const right = this.readSortField(b, field);
|
|
174
157
|
if (left === right) {
|
|
175
158
|
continue;
|
|
176
159
|
}
|
|
@@ -185,6 +168,19 @@ class CoreFileService {
|
|
|
185
168
|
return 0;
|
|
186
169
|
});
|
|
187
170
|
}
|
|
171
|
+
readSortField(doc, field) {
|
|
172
|
+
if (!field.includes('.')) {
|
|
173
|
+
return doc?.[field];
|
|
174
|
+
}
|
|
175
|
+
let current = doc;
|
|
176
|
+
for (const segment of field.split('.')) {
|
|
177
|
+
if (current === null || current === undefined || typeof current !== 'object') {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
current = current[segment];
|
|
181
|
+
}
|
|
182
|
+
return current;
|
|
183
|
+
}
|
|
188
184
|
async getFileInfo(id, serviceOptions) {
|
|
189
185
|
if (!(await this.checkRights(id, { ...serviceOptions, checkInputType: 'id' }))) {
|
|
190
186
|
return null;
|
|
@@ -302,6 +298,9 @@ class CoreFileService {
|
|
|
302
298
|
}
|
|
303
299
|
const objectId = (0, db_helper_1.getObjectIds)(id);
|
|
304
300
|
const fileInfo = await this.getFileInfo(objectId, serviceOptions);
|
|
301
|
+
if (!fileInfo) {
|
|
302
|
+
throw new common_1.NotFoundException(`File not found with id ${(0, db_helper_1.getStringIds)(objectId)}`);
|
|
303
|
+
}
|
|
305
304
|
if (await this.findS3FileById(objectId)) {
|
|
306
305
|
await s3_file_helper_1.S3FileHelper.deleteFile(this.options.s3Service, this.s3Files, objectId);
|
|
307
306
|
return fileInfo;
|