create-forgeon 0.3.22 → 0.3.23
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/package.json +1 -1
- package/src/modules/executor.test.mjs +55 -29
- package/src/modules/files-access.mjs +25 -1
- package/templates/module-presets/files-quotas/packages/files-quotas/package.json +21 -20
- package/templates/module-presets/files-quotas/packages/files-quotas/src/files-quotas.service.ts +118 -118
- package/templates/module-presets/files-quotas/packages/files-quotas/src/forgeon-files-quotas.module.ts +21 -19
package/package.json
CHANGED
|
@@ -506,6 +506,16 @@ function assertFilesAccessWiring(projectRoot) {
|
|
|
506
506
|
assert.match(filesController, /@Req\(\) req: any/);
|
|
507
507
|
assert.match(filesController, /openDownload\(publicId,\s*variant\)/);
|
|
508
508
|
|
|
509
|
+
const filesModule = fs.readFileSync(
|
|
510
|
+
path.join(projectRoot, 'packages', 'files', 'src', 'forgeon-files.module.ts'),
|
|
511
|
+
'utf8',
|
|
512
|
+
);
|
|
513
|
+
assert.match(filesModule, /import \{ ForgeonFilesAccessModule \} from '@forgeon\/files-access';/);
|
|
514
|
+
assert.match(
|
|
515
|
+
filesModule,
|
|
516
|
+
/imports: \[FilesConfigModule, ForgeonFilesAccessModule, (?:ForgeonFilesImageModule, )?DbPrismaModule, \.\.\.\(options\.imports \?\? \[\]\)\],/,
|
|
517
|
+
);
|
|
518
|
+
|
|
509
519
|
const healthController = fs.readFileSync(
|
|
510
520
|
path.join(projectRoot, 'apps', 'api', 'src', 'health', 'health.controller.ts'),
|
|
511
521
|
'utf8',
|
|
@@ -532,14 +542,14 @@ function assertFilesQuotasWiring(projectRoot) {
|
|
|
532
542
|
assert.match(appModule, /filesQuotasEnvSchema/);
|
|
533
543
|
assert.match(appModule, /ForgeonFilesQuotasModule/);
|
|
534
544
|
|
|
535
|
-
const apiPackage = fs.readFileSync(path.join(projectRoot, 'apps', 'api', 'package.json'), 'utf8');
|
|
536
|
-
assert.match(apiPackage, /@forgeon\/files-quotas/);
|
|
537
|
-
assert.match(apiPackage, /pnpm --filter @forgeon\/files-quotas build/);
|
|
538
|
-
assert.equal(
|
|
539
|
-
apiPackage.indexOf('pnpm --filter @forgeon/files-quotas build') >
|
|
540
|
-
apiPackage.indexOf('pnpm --filter @forgeon/files build'),
|
|
541
|
-
true,
|
|
542
|
-
);
|
|
545
|
+
const apiPackage = fs.readFileSync(path.join(projectRoot, 'apps', 'api', 'package.json'), 'utf8');
|
|
546
|
+
assert.match(apiPackage, /@forgeon\/files-quotas/);
|
|
547
|
+
assert.match(apiPackage, /pnpm --filter @forgeon\/files-quotas build/);
|
|
548
|
+
assert.equal(
|
|
549
|
+
apiPackage.indexOf('pnpm --filter @forgeon/files-quotas build') >
|
|
550
|
+
apiPackage.indexOf('pnpm --filter @forgeon/files build'),
|
|
551
|
+
true,
|
|
552
|
+
);
|
|
543
553
|
|
|
544
554
|
const filesPackage = fs.readFileSync(path.join(projectRoot, 'packages', 'files', 'package.json'), 'utf8');
|
|
545
555
|
assert.doesNotMatch(filesPackage, /@forgeon\/files-quotas/);
|
|
@@ -550,13 +560,13 @@ function assertFilesQuotasWiring(projectRoot) {
|
|
|
550
560
|
apiDockerfile,
|
|
551
561
|
/COPY packages\/files-quotas\/package\.json packages\/files-quotas\/package\.json/,
|
|
552
562
|
);
|
|
553
|
-
assert.match(apiDockerfile, /COPY packages\/files-quotas packages\/files-quotas/);
|
|
554
|
-
assert.match(apiDockerfile, /RUN pnpm --filter @forgeon\/files-quotas build/);
|
|
555
|
-
assert.equal(
|
|
556
|
-
apiDockerfile.indexOf('RUN pnpm --filter @forgeon/files-quotas build') >
|
|
557
|
-
apiDockerfile.indexOf('RUN pnpm --filter @forgeon/files build'),
|
|
558
|
-
true,
|
|
559
|
-
);
|
|
563
|
+
assert.match(apiDockerfile, /COPY packages\/files-quotas packages\/files-quotas/);
|
|
564
|
+
assert.match(apiDockerfile, /RUN pnpm --filter @forgeon\/files-quotas build/);
|
|
565
|
+
assert.equal(
|
|
566
|
+
apiDockerfile.indexOf('RUN pnpm --filter @forgeon/files-quotas build') >
|
|
567
|
+
apiDockerfile.indexOf('RUN pnpm --filter @forgeon/files build'),
|
|
568
|
+
true,
|
|
569
|
+
);
|
|
560
570
|
|
|
561
571
|
const filesController = fs.readFileSync(
|
|
562
572
|
path.join(projectRoot, 'packages', 'files', 'src', 'files.controller.ts'),
|
|
@@ -591,6 +601,22 @@ function assertFilesQuotasWiring(projectRoot) {
|
|
|
591
601
|
const readme = fs.readFileSync(path.join(projectRoot, 'README.md'), 'utf8');
|
|
592
602
|
assert.match(readme, /## Files Quotas Module/);
|
|
593
603
|
assert.match(readme, /owner-based limits/i);
|
|
604
|
+
|
|
605
|
+
const filesQuotasService = fs.readFileSync(
|
|
606
|
+
path.join(projectRoot, 'packages', 'files-quotas', 'src', 'files-quotas.service.ts'),
|
|
607
|
+
'utf8',
|
|
608
|
+
);
|
|
609
|
+
assert.match(filesQuotasService, /FilesStore/);
|
|
610
|
+
assert.match(filesQuotasService, /filesStore\.countOwnerUsage/);
|
|
611
|
+
assert.doesNotMatch(filesQuotasService, /FilesService/);
|
|
612
|
+
|
|
613
|
+
const filesQuotasModule = fs.readFileSync(
|
|
614
|
+
path.join(projectRoot, 'packages', 'files-quotas', 'src', 'forgeon-files-quotas.module.ts'),
|
|
615
|
+
'utf8',
|
|
616
|
+
);
|
|
617
|
+
assert.match(filesQuotasModule, /DbPrismaModule/);
|
|
618
|
+
assert.match(filesQuotasModule, /FilesStore/);
|
|
619
|
+
assert.doesNotMatch(filesQuotasModule, /ForgeonFilesModule/);
|
|
594
620
|
}
|
|
595
621
|
|
|
596
622
|
function assertFilesImageWiring(projectRoot) {
|
|
@@ -611,20 +637,20 @@ function assertFilesImageWiring(projectRoot) {
|
|
|
611
637
|
const filesPackage = fs.readFileSync(path.join(projectRoot, 'packages', 'files', 'package.json'), 'utf8');
|
|
612
638
|
assert.match(filesPackage, /@forgeon\/files-image/);
|
|
613
639
|
|
|
614
|
-
const filesModule = fs.readFileSync(
|
|
615
|
-
path.join(projectRoot, 'packages', 'files', 'src', 'forgeon-files.module.ts'),
|
|
616
|
-
'utf8',
|
|
617
|
-
);
|
|
618
|
-
assert.match(filesModule, /ForgeonFilesImageModule/);
|
|
619
|
-
assert.match(
|
|
620
|
-
filesModule,
|
|
621
|
-
/imports: \[FilesConfigModule, (?:ForgeonFilesAccessModule, )?ForgeonFilesImageModule, DbPrismaModule, \.\.\.\(options\.imports \?\? \[\]\)\],/,
|
|
622
|
-
);
|
|
623
|
-
|
|
624
|
-
const filesService = fs.readFileSync(
|
|
625
|
-
path.join(projectRoot, 'packages', 'files', 'src', 'files.service.ts'),
|
|
626
|
-
'utf8',
|
|
627
|
-
);
|
|
640
|
+
const filesModule = fs.readFileSync(
|
|
641
|
+
path.join(projectRoot, 'packages', 'files', 'src', 'forgeon-files.module.ts'),
|
|
642
|
+
'utf8',
|
|
643
|
+
);
|
|
644
|
+
assert.match(filesModule, /ForgeonFilesImageModule/);
|
|
645
|
+
assert.match(
|
|
646
|
+
filesModule,
|
|
647
|
+
/imports: \[FilesConfigModule, (?:ForgeonFilesAccessModule, )?ForgeonFilesImageModule, DbPrismaModule, \.\.\.\(options\.imports \?\? \[\]\)\],/,
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
const filesService = fs.readFileSync(
|
|
651
|
+
path.join(projectRoot, 'packages', 'files', 'src', 'files.service.ts'),
|
|
652
|
+
'utf8',
|
|
653
|
+
);
|
|
628
654
|
assert.match(filesService, /FilesImageService/);
|
|
629
655
|
assert.match(filesService, /filesImageService\.sanitizeForStorage/);
|
|
630
656
|
assert.match(filesService, /sanitizeForStorage\({/);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { copyRecursive, writeJson } from '../utils/fs.mjs';
|
|
4
4
|
import {
|
|
@@ -51,6 +51,29 @@ function patchFilesPackage(targetRoot) {
|
|
|
51
51
|
writeJson(packagePath, packageJson);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function patchFilesModule(targetRoot) {
|
|
55
|
+
const filePath = path.join(targetRoot, 'packages', 'files', 'src', 'forgeon-files.module.ts');
|
|
56
|
+
if (!fs.existsSync(filePath)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
61
|
+
content = ensureImportLine(content, "import { ForgeonFilesAccessModule } from '@forgeon/files-access';");
|
|
62
|
+
|
|
63
|
+
if (!content.includes('imports: [FilesConfigModule, ForgeonFilesAccessModule,')) {
|
|
64
|
+
content = content.replace(
|
|
65
|
+
'imports: [FilesConfigModule, ForgeonFilesImageModule, DbPrismaModule, ...(options.imports ?? [])],',
|
|
66
|
+
'imports: [FilesConfigModule, ForgeonFilesAccessModule, ForgeonFilesImageModule, DbPrismaModule, ...(options.imports ?? [])],',
|
|
67
|
+
);
|
|
68
|
+
content = content.replace(
|
|
69
|
+
'imports: [FilesConfigModule, DbPrismaModule, ...(options.imports ?? [])],',
|
|
70
|
+
'imports: [FilesConfigModule, ForgeonFilesAccessModule, DbPrismaModule, ...(options.imports ?? [])],',
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
|
|
75
|
+
}
|
|
76
|
+
|
|
54
77
|
function patchAppModule(targetRoot) {
|
|
55
78
|
const filePath = path.join(targetRoot, 'apps', 'api', 'src', 'app.module.ts');
|
|
56
79
|
if (!fs.existsSync(filePath)) {
|
|
@@ -366,6 +389,7 @@ export function applyFilesAccessModule({ packageRoot, targetRoot }) {
|
|
|
366
389
|
|
|
367
390
|
patchApiPackage(targetRoot);
|
|
368
391
|
patchFilesPackage(targetRoot);
|
|
392
|
+
patchFilesModule(targetRoot);
|
|
369
393
|
patchAppModule(targetRoot);
|
|
370
394
|
patchFilesController(targetRoot);
|
|
371
395
|
patchHealthController(targetRoot, probeTargets);
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@forgeon/files-quotas",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc -p tsconfig.json"
|
|
9
|
-
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"@forgeon/
|
|
12
|
-
"@
|
|
13
|
-
"@nestjs/
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgeon/files-quotas",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.json"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@forgeon/db-prisma": "workspace:*",
|
|
12
|
+
"@forgeon/files": "workspace:*",
|
|
13
|
+
"@nestjs/common": "^11.0.1",
|
|
14
|
+
"@nestjs/config": "^4.0.0",
|
|
15
|
+
"zod": "^3.24.2"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^22.10.7",
|
|
19
|
+
"typescript": "^5.7.3"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/templates/module-presets/files-quotas/packages/files-quotas/src/files-quotas.service.ts
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import { ConflictException, Injectable } from '@nestjs/common';
|
|
2
|
-
import {
|
|
3
|
-
import { FilesQuotasConfigService } from './files-quotas-config.service';
|
|
4
|
-
import type { FilesQuotaCheckInput, FilesQuotaCheckResult } from './files-quotas.types';
|
|
5
|
-
|
|
6
|
-
@Injectable()
|
|
7
|
-
export class FilesQuotasService {
|
|
8
|
-
constructor(
|
|
9
|
-
private readonly
|
|
10
|
-
private readonly configService: FilesQuotasConfigService,
|
|
11
|
-
) {}
|
|
12
|
-
|
|
13
|
-
get enabled(): boolean {
|
|
14
|
-
return this.configService.enabled;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get limits() {
|
|
18
|
-
return {
|
|
19
|
-
maxFilesPerOwner: this.configService.maxFilesPerOwner,
|
|
20
|
-
maxBytesPerOwner: this.configService.maxBytesPerOwner,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async evaluateUpload(input: FilesQuotaCheckInput): Promise<FilesQuotaCheckResult> {
|
|
25
|
-
const limits = this.limits;
|
|
26
|
-
const emptyUsage = {
|
|
27
|
-
filesCount: 0,
|
|
28
|
-
totalBytes: 0,
|
|
29
|
-
};
|
|
30
|
-
const baseResult = {
|
|
31
|
-
limits,
|
|
32
|
-
current: emptyUsage,
|
|
33
|
-
next: {
|
|
34
|
-
filesCount: emptyUsage.filesCount + 1,
|
|
35
|
-
totalBytes: emptyUsage.totalBytes + input.fileSize,
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
if (!this.enabled) {
|
|
40
|
-
return {
|
|
41
|
-
allowed: true,
|
|
42
|
-
reason: 'disabled',
|
|
43
|
-
...baseResult,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!input.ownerId) {
|
|
48
|
-
return {
|
|
49
|
-
allowed: true,
|
|
50
|
-
reason: 'owner-missing',
|
|
51
|
-
...baseResult,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const usage = await this.
|
|
56
|
-
const next = {
|
|
57
|
-
filesCount: usage.filesCount + 1,
|
|
58
|
-
totalBytes: usage.totalBytes + input.fileSize,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
if (next.filesCount > limits.maxFilesPerOwner) {
|
|
62
|
-
return {
|
|
63
|
-
allowed: false,
|
|
64
|
-
reason: 'max-files',
|
|
65
|
-
limits,
|
|
66
|
-
current: usage,
|
|
67
|
-
next,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
if (next.totalBytes > limits.maxBytesPerOwner) {
|
|
71
|
-
return {
|
|
72
|
-
allowed: false,
|
|
73
|
-
reason: 'max-bytes',
|
|
74
|
-
limits,
|
|
75
|
-
current: usage,
|
|
76
|
-
next,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
allowed: true,
|
|
82
|
-
reason: 'ok',
|
|
83
|
-
limits,
|
|
84
|
-
current: usage,
|
|
85
|
-
next,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async assertUploadAllowed(input: FilesQuotaCheckInput): Promise<void> {
|
|
90
|
-
const result = await this.evaluateUpload(input);
|
|
91
|
-
if (result.allowed) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
throw new ConflictException({
|
|
96
|
-
message: 'File quota exceeded for owner',
|
|
97
|
-
details: {
|
|
98
|
-
reason: result.reason,
|
|
99
|
-
limits: result.limits,
|
|
100
|
-
current: result.current,
|
|
101
|
-
next: result.next,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async getProbeStatus(input: FilesQuotaCheckInput): Promise<{
|
|
107
|
-
status: 'ok';
|
|
108
|
-
feature: 'files-quotas';
|
|
109
|
-
result: FilesQuotaCheckResult;
|
|
110
|
-
}> {
|
|
111
|
-
const result = await this.evaluateUpload(input);
|
|
112
|
-
return {
|
|
113
|
-
status: 'ok',
|
|
114
|
-
feature: 'files-quotas',
|
|
115
|
-
result,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
}
|
|
1
|
+
import { ConflictException, Injectable } from '@nestjs/common';
|
|
2
|
+
import { FilesStore } from '@forgeon/files';
|
|
3
|
+
import { FilesQuotasConfigService } from './files-quotas-config.service';
|
|
4
|
+
import type { FilesQuotaCheckInput, FilesQuotaCheckResult } from './files-quotas.types';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class FilesQuotasService {
|
|
8
|
+
constructor(
|
|
9
|
+
private readonly filesStore: FilesStore,
|
|
10
|
+
private readonly configService: FilesQuotasConfigService,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
get enabled(): boolean {
|
|
14
|
+
return this.configService.enabled;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get limits() {
|
|
18
|
+
return {
|
|
19
|
+
maxFilesPerOwner: this.configService.maxFilesPerOwner,
|
|
20
|
+
maxBytesPerOwner: this.configService.maxBytesPerOwner,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async evaluateUpload(input: FilesQuotaCheckInput): Promise<FilesQuotaCheckResult> {
|
|
25
|
+
const limits = this.limits;
|
|
26
|
+
const emptyUsage = {
|
|
27
|
+
filesCount: 0,
|
|
28
|
+
totalBytes: 0,
|
|
29
|
+
};
|
|
30
|
+
const baseResult = {
|
|
31
|
+
limits,
|
|
32
|
+
current: emptyUsage,
|
|
33
|
+
next: {
|
|
34
|
+
filesCount: emptyUsage.filesCount + 1,
|
|
35
|
+
totalBytes: emptyUsage.totalBytes + input.fileSize,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (!this.enabled) {
|
|
40
|
+
return {
|
|
41
|
+
allowed: true,
|
|
42
|
+
reason: 'disabled',
|
|
43
|
+
...baseResult,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!input.ownerId) {
|
|
48
|
+
return {
|
|
49
|
+
allowed: true,
|
|
50
|
+
reason: 'owner-missing',
|
|
51
|
+
...baseResult,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const usage = await this.filesStore.countOwnerUsage(input.ownerType, input.ownerId);
|
|
56
|
+
const next = {
|
|
57
|
+
filesCount: usage.filesCount + 1,
|
|
58
|
+
totalBytes: usage.totalBytes + input.fileSize,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
if (next.filesCount > limits.maxFilesPerOwner) {
|
|
62
|
+
return {
|
|
63
|
+
allowed: false,
|
|
64
|
+
reason: 'max-files',
|
|
65
|
+
limits,
|
|
66
|
+
current: usage,
|
|
67
|
+
next,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (next.totalBytes > limits.maxBytesPerOwner) {
|
|
71
|
+
return {
|
|
72
|
+
allowed: false,
|
|
73
|
+
reason: 'max-bytes',
|
|
74
|
+
limits,
|
|
75
|
+
current: usage,
|
|
76
|
+
next,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
allowed: true,
|
|
82
|
+
reason: 'ok',
|
|
83
|
+
limits,
|
|
84
|
+
current: usage,
|
|
85
|
+
next,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async assertUploadAllowed(input: FilesQuotaCheckInput): Promise<void> {
|
|
90
|
+
const result = await this.evaluateUpload(input);
|
|
91
|
+
if (result.allowed) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
throw new ConflictException({
|
|
96
|
+
message: 'File quota exceeded for owner',
|
|
97
|
+
details: {
|
|
98
|
+
reason: result.reason,
|
|
99
|
+
limits: result.limits,
|
|
100
|
+
current: result.current,
|
|
101
|
+
next: result.next,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async getProbeStatus(input: FilesQuotaCheckInput): Promise<{
|
|
107
|
+
status: 'ok';
|
|
108
|
+
feature: 'files-quotas';
|
|
109
|
+
result: FilesQuotaCheckResult;
|
|
110
|
+
}> {
|
|
111
|
+
const result = await this.evaluateUpload(input);
|
|
112
|
+
return {
|
|
113
|
+
status: 'ok',
|
|
114
|
+
feature: 'files-quotas',
|
|
115
|
+
result,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { DbPrismaModule } from '@forgeon/db-prisma';
|
|
3
|
+
import { FilesStore } from '@forgeon/files';
|
|
4
|
+
import { FilesQuotasConfigModule } from './files-quotas-config.module';
|
|
5
|
+
import { FilesQuotasService } from './files-quotas.service';
|
|
6
|
+
|
|
7
|
+
const FORGEON_FILES_UPLOAD_QUOTA_SERVICE = 'FORGEON_FILES_UPLOAD_QUOTA_SERVICE';
|
|
8
|
+
|
|
9
|
+
@Module({
|
|
10
|
+
imports: [DbPrismaModule, FilesQuotasConfigModule],
|
|
11
|
+
providers: [
|
|
12
|
+
FilesStore,
|
|
13
|
+
FilesQuotasService,
|
|
14
|
+
{
|
|
15
|
+
provide: FORGEON_FILES_UPLOAD_QUOTA_SERVICE,
|
|
16
|
+
useExisting: FilesQuotasService,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
exports: [FilesQuotasConfigModule, FilesQuotasService, FORGEON_FILES_UPLOAD_QUOTA_SERVICE],
|
|
20
|
+
})
|
|
21
|
+
export class ForgeonFilesQuotasModule {}
|