proteum 1.0.0-1
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/.dockerignore +10 -0
- package/Rte.zip +0 -0
- package/cli/app/config.ts +54 -0
- package/cli/app/index.ts +195 -0
- package/cli/bin.js +11 -0
- package/cli/commands/build.ts +34 -0
- package/cli/commands/deploy/app.ts +29 -0
- package/cli/commands/deploy/web.ts +60 -0
- package/cli/commands/dev.ts +109 -0
- package/cli/commands/init.ts +85 -0
- package/cli/compiler/client/identite.ts +72 -0
- package/cli/compiler/client/index.ts +334 -0
- package/cli/compiler/common/babel/index.ts +170 -0
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +579 -0
- package/cli/compiler/common/babel/routes/imports.ts +127 -0
- package/cli/compiler/common/babel/routes/routes.ts +1130 -0
- package/cli/compiler/common/files/autres.ts +39 -0
- package/cli/compiler/common/files/images.ts +35 -0
- package/cli/compiler/common/files/style.ts +78 -0
- package/cli/compiler/common/index.ts +154 -0
- package/cli/compiler/index.ts +532 -0
- package/cli/compiler/server/index.ts +211 -0
- package/cli/index.ts +189 -0
- package/cli/paths.ts +165 -0
- package/cli/print.ts +12 -0
- package/cli/tsconfig.json +38 -0
- package/cli/utils/index.ts +22 -0
- package/cli/utils/keyboard.ts +78 -0
- package/client/app/component.tsx +54 -0
- package/client/app/index.ts +142 -0
- package/client/app/service.ts +34 -0
- package/client/app.tsconfig.json +28 -0
- package/client/components/Button.tsx +298 -0
- package/client/components/Dialog/Manager.tsx +309 -0
- package/client/components/Dialog/card.tsx +208 -0
- package/client/components/Dialog/index.less +151 -0
- package/client/components/Dialog/status.less +176 -0
- package/client/components/Dialog/status.tsx +48 -0
- package/client/components/index.ts +2 -0
- package/client/components/types.d.ts +3 -0
- package/client/data/input.ts +32 -0
- package/client/global.d.ts +5 -0
- package/client/hooks.ts +22 -0
- package/client/index.ts +6 -0
- package/client/pages/_layout/index.less +6 -0
- package/client/pages/_layout/index.tsx +43 -0
- package/client/pages/bug.tsx.old +60 -0
- package/client/pages/useHeader.tsx +50 -0
- package/client/services/captcha/index.ts +67 -0
- package/client/services/router/components/Link.tsx +46 -0
- package/client/services/router/components/Page.tsx +55 -0
- package/client/services/router/components/router.tsx +218 -0
- package/client/services/router/index.tsx +521 -0
- package/client/services/router/request/api.ts +267 -0
- package/client/services/router/request/history.ts +5 -0
- package/client/services/router/request/index.ts +53 -0
- package/client/services/router/request/multipart.ts +147 -0
- package/client/services/router/response/index.tsx +128 -0
- package/client/services/router/response/page.ts +86 -0
- package/client/services/socket/index.ts +147 -0
- package/client/utils/dom.ts +77 -0
- package/common/app/index.ts +9 -0
- package/common/data/chaines/index.ts +54 -0
- package/common/data/dates.ts +179 -0
- package/common/data/markdown.ts +73 -0
- package/common/data/rte/nodes.ts +83 -0
- package/common/data/stats.ts +90 -0
- package/common/errors/index.tsx +326 -0
- package/common/router/index.ts +213 -0
- package/common/router/layouts.ts +93 -0
- package/common/router/register.ts +55 -0
- package/common/router/request/api.ts +77 -0
- package/common/router/request/index.ts +35 -0
- package/common/router/response/index.ts +45 -0
- package/common/router/response/page.ts +128 -0
- package/common/utils/rte.ts +183 -0
- package/common/utils.ts +7 -0
- package/doc/TODO.md +71 -0
- package/doc/front/router.md +27 -0
- package/doc/workspace/workspace.png +0 -0
- package/doc/workspace/workspace2.png +0 -0
- package/doc/workspace/workspace_26.01.22.png +0 -0
- package/package.json +171 -0
- package/server/app/commands.ts +141 -0
- package/server/app/container/config.ts +203 -0
- package/server/app/container/console/index.ts +550 -0
- package/server/app/container/index.ts +137 -0
- package/server/app/index.ts +273 -0
- package/server/app/service/container.ts +88 -0
- package/server/app/service/index.ts +235 -0
- package/server/app.tsconfig.json +28 -0
- package/server/context.ts +4 -0
- package/server/index.ts +4 -0
- package/server/services/auth/index.ts +250 -0
- package/server/services/auth/old.ts +277 -0
- package/server/services/auth/router/index.ts +95 -0
- package/server/services/auth/router/request.ts +54 -0
- package/server/services/auth/router/service.json +6 -0
- package/server/services/auth/service.json +6 -0
- package/server/services/cache/commands.ts +41 -0
- package/server/services/cache/index.ts +297 -0
- package/server/services/cache/service.json +6 -0
- package/server/services/cron/CronTask.ts +86 -0
- package/server/services/cron/index.ts +112 -0
- package/server/services/cron/service.json +6 -0
- package/server/services/disks/driver.ts +103 -0
- package/server/services/disks/drivers/local/index.ts +188 -0
- package/server/services/disks/drivers/local/service.json +6 -0
- package/server/services/disks/drivers/s3/index.ts +301 -0
- package/server/services/disks/drivers/s3/service.json +6 -0
- package/server/services/disks/index.ts +90 -0
- package/server/services/disks/service.json +6 -0
- package/server/services/email/index.ts +188 -0
- package/server/services/email/utils.ts +53 -0
- package/server/services/fetch/index.ts +201 -0
- package/server/services/fetch/service.json +7 -0
- package/server/services/models.7z +0 -0
- package/server/services/prisma/Facet.ts +142 -0
- package/server/services/prisma/index.ts +201 -0
- package/server/services/prisma/service.json +6 -0
- package/server/services/router/http/index.ts +217 -0
- package/server/services/router/http/multipart.ts +102 -0
- package/server/services/router/http/session.ts.old +40 -0
- package/server/services/router/index.ts +801 -0
- package/server/services/router/request/api.ts +87 -0
- package/server/services/router/request/index.ts +184 -0
- package/server/services/router/request/service.ts +21 -0
- package/server/services/router/request/validation/zod.ts +180 -0
- package/server/services/router/response/index.ts +338 -0
- package/server/services/router/response/mask/Filter.ts +323 -0
- package/server/services/router/response/mask/index.ts +60 -0
- package/server/services/router/response/mask/selecteurs.ts +92 -0
- package/server/services/router/response/page/document.tsx +160 -0
- package/server/services/router/response/page/index.tsx +196 -0
- package/server/services/router/service.json +6 -0
- package/server/services/router/service.ts +36 -0
- package/server/services/schema/index.ts +44 -0
- package/server/services/schema/request.ts +49 -0
- package/server/services/schema/router/index.ts +28 -0
- package/server/services/schema/router/service.json +6 -0
- package/server/services/schema/service.json +6 -0
- package/server/services/security/encrypt/aes/index.ts +85 -0
- package/server/services/security/encrypt/aes/service.json +6 -0
- package/server/services/socket/index.ts +162 -0
- package/server/services/socket/scope.ts +226 -0
- package/server/services/socket/service.json +6 -0
- package/server/services_old/SocketClient.ts +92 -0
- package/server/services_old/Token.old.ts +97 -0
- package/server/utils/slug.ts +79 -0
- package/tsconfig.common.json +45 -0
- package/tsconfig.json +3 -0
- package/types/aliases.d.ts +54 -0
- package/types/global/modules.d.ts +49 -0
- package/types/global/utils.d.ts +103 -0
- package/types/icons.d.ts +1 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPS
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
/*
|
|
5
|
+
A simple adapter to use fs-extra functions with AWS S3 buckets
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Node
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import dayjs from 'dayjs';
|
|
11
|
+
|
|
12
|
+
// Npm
|
|
13
|
+
import fs from 'fs-extra';
|
|
14
|
+
|
|
15
|
+
// Core
|
|
16
|
+
import AppContainer from '@server/app/container';
|
|
17
|
+
|
|
18
|
+
// Specific
|
|
19
|
+
import DiskDriver, { TDrivercnfig, SourceFile, TOutputFileOptions } from '../../driver';
|
|
20
|
+
|
|
21
|
+
/*----------------------------------
|
|
22
|
+
- CONFIG
|
|
23
|
+
----------------------------------*/
|
|
24
|
+
|
|
25
|
+
/*----------------------------------
|
|
26
|
+
- TYPES
|
|
27
|
+
----------------------------------*/
|
|
28
|
+
|
|
29
|
+
export type TConfig = TDrivercnfig & {
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*----------------------------------
|
|
34
|
+
- SERVICE
|
|
35
|
+
----------------------------------*/
|
|
36
|
+
export default class LocalFS<
|
|
37
|
+
Config extends TConfig = TConfig,
|
|
38
|
+
TBucketName = keyof Config["buckets"]
|
|
39
|
+
> extends DiskDriver<TConfig> {
|
|
40
|
+
|
|
41
|
+
public rootDir = AppContainer.path.var;
|
|
42
|
+
|
|
43
|
+
public async mount() {
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async unmount() {
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*----------------------------------
|
|
52
|
+
- ACTIONS
|
|
53
|
+
----------------------------------*/
|
|
54
|
+
|
|
55
|
+
public getFileUrl(
|
|
56
|
+
bucketName: TBucketName,
|
|
57
|
+
filename: string
|
|
58
|
+
) {
|
|
59
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
60
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename || '.' );
|
|
61
|
+
return fullPath;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public async readDir( bucketName: TBucketName, dirname?: string ) {
|
|
65
|
+
|
|
66
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
67
|
+
|
|
68
|
+
const fullPath = path.join( this.rootDir, bucketDir, dirname || '.' );
|
|
69
|
+
|
|
70
|
+
// Combine the files list of all source directory
|
|
71
|
+
const files: SourceFile[] = [];
|
|
72
|
+
const sources = fs.readdirSync( fullPath, { withFileTypes: true });
|
|
73
|
+
for (const source of sources) {
|
|
74
|
+
|
|
75
|
+
if (!source.isDirectory())
|
|
76
|
+
continue;
|
|
77
|
+
|
|
78
|
+
const parentFolder = source.name;
|
|
79
|
+
const csvFiles = fs.readdirSync(
|
|
80
|
+
path.join( fullPath, parentFolder ),
|
|
81
|
+
{ withFileTypes: true }
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
for (const file of csvFiles) {
|
|
85
|
+
|
|
86
|
+
if (!file.isFile() || !file.name.endsWith('.csv'))
|
|
87
|
+
continue;
|
|
88
|
+
|
|
89
|
+
const relPath = path.join( source.name, file.name );
|
|
90
|
+
const fullpath = path.join( fullPath, relPath );
|
|
91
|
+
const stats = fs.statSync(fullpath);
|
|
92
|
+
|
|
93
|
+
const rowsCount = fs.readFileSync( fullpath, 'utf-8').split('\n').length - 1;
|
|
94
|
+
|
|
95
|
+
const name = dayjs(stats.mtime).format('DD/MM HH:mm:ss')
|
|
96
|
+
+ ' : ' + path.join( source.name, file.name )
|
|
97
|
+
+ ' : ' + rowsCount + ' contacts'
|
|
98
|
+
|
|
99
|
+
files.push({
|
|
100
|
+
name,
|
|
101
|
+
path: relPath,
|
|
102
|
+
parentFolder,
|
|
103
|
+
source: source.name,
|
|
104
|
+
modified: stats.mtimeMs
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.config.debug && console.log(`readDir ${fullPath}: ${files.length} objects`);
|
|
111
|
+
return files;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public async readFile( bucketName: TBucketName, filename: string ) {
|
|
115
|
+
|
|
116
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
117
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
118
|
+
|
|
119
|
+
this.config.debug && console.log(`readFile ${fullPath}`);
|
|
120
|
+
return fs.readFileSync( fullPath );
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public createReadStream( bucketName: TBucketName, filename: string ) {
|
|
124
|
+
|
|
125
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
126
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
127
|
+
|
|
128
|
+
this.config.debug && console.log(`createReadStream ${fullPath}`);
|
|
129
|
+
return fs.createReadStream( fullPath );
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public async exists( bucketName: TBucketName, filename: string ) {
|
|
133
|
+
|
|
134
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
135
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
136
|
+
|
|
137
|
+
this.config.debug && console.log(`exists ${fullPath}`);
|
|
138
|
+
return fs.existsSync( fullPath );
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public async move( bucketName: TBucketName, source: string, destination: string, options: { overwrite?: boolean } = {}) {
|
|
142
|
+
|
|
143
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
144
|
+
const fullPathSource = path.join( this.rootDir, bucketDir, source );
|
|
145
|
+
const fullPathDestination = path.join( this.rootDir, bucketDir, destination );
|
|
146
|
+
|
|
147
|
+
this.config.debug && console.log(`move ${fullPathSource} to ${fullPathDestination}`);
|
|
148
|
+
return fs.moveSync(fullPathSource, fullPathDestination, options);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public async outputFile(
|
|
152
|
+
bucketName: TBucketName,
|
|
153
|
+
filename: string,
|
|
154
|
+
content: string | Buffer,
|
|
155
|
+
options?: TOutputFileOptions
|
|
156
|
+
) {
|
|
157
|
+
|
|
158
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
159
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
160
|
+
this.config.debug && console.log(`outputFile`, fullPath);
|
|
161
|
+
|
|
162
|
+
fs.outputFileSync( fullPath, content, options );
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
path: fullPath
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public async readJSON( bucketName: TBucketName, filename: string ) {
|
|
170
|
+
|
|
171
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
172
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
173
|
+
|
|
174
|
+
this.config.debug && console.log(`readJSON ${fullPath}`);
|
|
175
|
+
return fs.readJsonSync( fullPath );
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public async delete( bucketName: TBucketName, filename: string ) {
|
|
179
|
+
|
|
180
|
+
const bucketDir = this.config.buckets[bucketName];
|
|
181
|
+
const fullPath = path.join( this.rootDir, bucketDir, filename );
|
|
182
|
+
|
|
183
|
+
this.config.debug && console.log(`delete ${fullPath}`);
|
|
184
|
+
fs.removeSync( fullPath );
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPS
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
/*
|
|
5
|
+
A simple adapter to use fs-extra functions with AWS S3 buckets
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Node
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// Npm
|
|
12
|
+
import AWS from 'aws-sdk';
|
|
13
|
+
import dayjs from 'dayjs';
|
|
14
|
+
|
|
15
|
+
// Core
|
|
16
|
+
import type { Application } from '@server/app';
|
|
17
|
+
import type { TServiceArgs } from '@server/app/service';
|
|
18
|
+
|
|
19
|
+
// Specific
|
|
20
|
+
import DiskDriver, {
|
|
21
|
+
TDrivercnfig,
|
|
22
|
+
SourceFile,
|
|
23
|
+
TOutputFileOptions,
|
|
24
|
+
TReadFileOptions
|
|
25
|
+
} from '@server/services/disks/driver';
|
|
26
|
+
|
|
27
|
+
/*----------------------------------
|
|
28
|
+
- CONFIG
|
|
29
|
+
----------------------------------*/
|
|
30
|
+
|
|
31
|
+
const debug = false;
|
|
32
|
+
|
|
33
|
+
/*----------------------------------
|
|
34
|
+
- TYPES
|
|
35
|
+
----------------------------------*/
|
|
36
|
+
|
|
37
|
+
export type TConfig = TDrivercnfig & {
|
|
38
|
+
accessKeyId: string,
|
|
39
|
+
secretAccessKey: string,
|
|
40
|
+
region: string,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/*----------------------------------
|
|
44
|
+
- SERVICE
|
|
45
|
+
----------------------------------*/
|
|
46
|
+
export default class S3Driver<
|
|
47
|
+
Config extends TConfig = TConfig,
|
|
48
|
+
TBucketName = keyof Config["buckets"]
|
|
49
|
+
> extends DiskDriver<TConfig> {
|
|
50
|
+
|
|
51
|
+
public s3: AWS.S3;
|
|
52
|
+
|
|
53
|
+
public constructor( config: TConfig, app: Application ) {
|
|
54
|
+
|
|
55
|
+
super(config, app);
|
|
56
|
+
|
|
57
|
+
AWS.config.update({
|
|
58
|
+
accessKeyId: this.config.accessKeyId,
|
|
59
|
+
secretAccessKey: this.config.secretAccessKey,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
this.s3 = new AWS.S3();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/*----------------------------------
|
|
66
|
+
- DISK LIFECYCLE
|
|
67
|
+
----------------------------------*/
|
|
68
|
+
|
|
69
|
+
public async mount() {
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async unmount() {
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/*----------------------------------
|
|
78
|
+
- ACTIONS
|
|
79
|
+
----------------------------------*/
|
|
80
|
+
|
|
81
|
+
public getFileUrl(
|
|
82
|
+
bucketName: TBucketName,
|
|
83
|
+
filename: string
|
|
84
|
+
) {
|
|
85
|
+
|
|
86
|
+
const bucket = this.config.buckets[bucketName];
|
|
87
|
+
if (bucket === undefined)
|
|
88
|
+
throw new Error(`Bucket "${bucketName}" not found in configuration`);
|
|
89
|
+
return `https://${bucket}.s3.${this.config.region}.amazonaws.com/${filename}`
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public readDir( bucketName: TBucketName, dirname?: string ) {
|
|
93
|
+
const bucket = this.config.buckets[bucketName];
|
|
94
|
+
return new Promise<SourceFile[]>((resolve, reject) => {
|
|
95
|
+
debug && console.log(`readDir ` + (dirname === undefined ? bucket : path.join( bucket, dirname )));
|
|
96
|
+
this.s3.listObjectsV2({ Bucket: bucket }, async (err, data) => {
|
|
97
|
+
|
|
98
|
+
if (err) return reject(err);
|
|
99
|
+
|
|
100
|
+
const files: SourceFile[] = [];
|
|
101
|
+
for (const file of data.Contents) {
|
|
102
|
+
|
|
103
|
+
const [source, ...hierarchy] = file.Key.split('/');
|
|
104
|
+
if (hierarchy.length > 1) // Take only direct childs
|
|
105
|
+
continue;
|
|
106
|
+
|
|
107
|
+
const filename = hierarchy.join('/');
|
|
108
|
+
if (!filename.endsWith('.csv'))
|
|
109
|
+
continue;
|
|
110
|
+
|
|
111
|
+
debug && console.log('-', file.Key);
|
|
112
|
+
|
|
113
|
+
const fileContent = await this.readFile( bucketName, file.Key );
|
|
114
|
+
const rowsCount = (fileContent as unknown as string).split('\n').length - 1;
|
|
115
|
+
|
|
116
|
+
const name = dayjs(file.LastModified).format('DD/MM HH:mm:ss')
|
|
117
|
+
+ ' : ' + path.join( source, filename )
|
|
118
|
+
+ ' : ' + rowsCount + ' contacts'
|
|
119
|
+
|
|
120
|
+
files.push({
|
|
121
|
+
name,
|
|
122
|
+
path: file.Key,
|
|
123
|
+
source: source,
|
|
124
|
+
modified: file.LastModified,
|
|
125
|
+
parentFolder: source
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
debug && console.log(`readDir ${bucket}/${dirname || ''}: ${files.length} objects`);
|
|
131
|
+
resolve(files);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public readFile(
|
|
137
|
+
bucketName: TBucketName,
|
|
138
|
+
filename: string,
|
|
139
|
+
options: TReadFileOptions = {}
|
|
140
|
+
) {
|
|
141
|
+
const bucket = this.config.buckets[bucketName];
|
|
142
|
+
debug && console.log(`readFile ${bucket}/${filename}`);
|
|
143
|
+
return new Promise<string>(( resolve, reject ) => {
|
|
144
|
+
this.s3.getObject({
|
|
145
|
+
Bucket: bucket,
|
|
146
|
+
Key: filename
|
|
147
|
+
}, (err, data) => {
|
|
148
|
+
|
|
149
|
+
if (err) return reject(err);
|
|
150
|
+
|
|
151
|
+
let body: any;
|
|
152
|
+
switch (options.encoding) {
|
|
153
|
+
case 'string':
|
|
154
|
+
body = data.Body?.toString()
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
body = data.Body;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
resolve( body );
|
|
162
|
+
});
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public createReadStream( bucketName: TBucketName, filename: string ) {
|
|
167
|
+
const bucket = this.config.buckets[bucketName];
|
|
168
|
+
debug && console.log(`createReadStream ${bucket}/${filename}`);
|
|
169
|
+
return this.s3.getObject({
|
|
170
|
+
Bucket: bucket,
|
|
171
|
+
Key: filename
|
|
172
|
+
}).createReadStream();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public exists( bucketName: TBucketName, filename: string ) {
|
|
176
|
+
const bucket = this.config.buckets[bucketName];
|
|
177
|
+
debug && console.log(`exists`, path.join(bucket, filename));
|
|
178
|
+
return new Promise<boolean>(( resolve, reject ) => {
|
|
179
|
+
this.s3.headObject({
|
|
180
|
+
Bucket: bucket,
|
|
181
|
+
Key: filename
|
|
182
|
+
}, (err, metadata) => {
|
|
183
|
+
|
|
184
|
+
if (!err)
|
|
185
|
+
resolve(true);
|
|
186
|
+
else if (err.name === 'NotFound')
|
|
187
|
+
resolve(false);
|
|
188
|
+
else
|
|
189
|
+
reject(err);
|
|
190
|
+
});
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public async move( bucketName: TBucketName, source: string, destination: string, options: { overwrite?: boolean } = {}) {
|
|
195
|
+
const bucket = this.config.buckets[bucketName];
|
|
196
|
+
debug && console.log(`move ${bucket}/${source} to ${bucket}/${destination}`);
|
|
197
|
+
|
|
198
|
+
if (options.overwrite)
|
|
199
|
+
await this.s3.deleteObject({
|
|
200
|
+
Bucket: bucket,
|
|
201
|
+
Key: destination,
|
|
202
|
+
}).promise();
|
|
203
|
+
|
|
204
|
+
await this.s3.copyObject({
|
|
205
|
+
Bucket: bucket,
|
|
206
|
+
CopySource: source,
|
|
207
|
+
Key: destination
|
|
208
|
+
}).promise();
|
|
209
|
+
|
|
210
|
+
debug && console.log(`Move ${bucket}/${source} to ${bucket}/${destination}: OK`);
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
public outputFile(
|
|
215
|
+
bucketName: TBucketName,
|
|
216
|
+
filename: string,
|
|
217
|
+
content: string | Buffer,
|
|
218
|
+
options?: TOutputFileOptions
|
|
219
|
+
) {
|
|
220
|
+
const bucket = this.config.buckets[bucketName];
|
|
221
|
+
debug && console.log(`outputFile ${bucket}/${filename}`);
|
|
222
|
+
return new Promise(( resolve, reject ) => {
|
|
223
|
+
this.s3.upload({
|
|
224
|
+
Bucket: bucket,
|
|
225
|
+
Key: filename,
|
|
226
|
+
Body: content,
|
|
227
|
+
}, (err, data) => {
|
|
228
|
+
|
|
229
|
+
if (err) return reject(err);
|
|
230
|
+
debug && console.log(`outputFile ${bucket}/${filename}: OK (${data.Location})`);
|
|
231
|
+
|
|
232
|
+
resolve({
|
|
233
|
+
path: data.Location
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public async readJSON( bucketName: TBucketName, filename: string ) {
|
|
240
|
+
const bucket = this.config.buckets[bucketName];
|
|
241
|
+
debug && console.log(`readJSON ${bucket}/${filename}`);
|
|
242
|
+
const filecontent = await this.readFile(bucketName, filename);
|
|
243
|
+
try {
|
|
244
|
+
debug && console.log(`readJSON: ${bucket}/${filename} : PARSE JSON`);
|
|
245
|
+
return JSON.parse(filecontent);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error(`Failed to parse file "${filename}" as JSON: `, error);
|
|
248
|
+
throw new Error(`Failed to parse file "${filename}" as JSON: ` + error);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public delete( bucketName: TBucketName, filename: string ) {
|
|
253
|
+
const bucket = this.config.buckets[bucketName];
|
|
254
|
+
debug && console.log(`delete ${bucket}/${filename}`);
|
|
255
|
+
return new Promise<boolean>(( resolve, reject ) => {
|
|
256
|
+
this.s3.deleteObject({
|
|
257
|
+
Bucket: bucket,
|
|
258
|
+
Key: filename
|
|
259
|
+
}, (err, metadata) => {
|
|
260
|
+
|
|
261
|
+
if (!err)
|
|
262
|
+
resolve(true);
|
|
263
|
+
else if (err.name === 'NotFound')
|
|
264
|
+
resolve(false);
|
|
265
|
+
else
|
|
266
|
+
reject(err);
|
|
267
|
+
});
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
public async deleteDir( bucketName: TBucketName, directoryPath: string ) {
|
|
272
|
+
const bucket = this.config.buckets[bucketName];
|
|
273
|
+
debug && console.log(`delete ${bucket}/${directoryPath}`);
|
|
274
|
+
try {
|
|
275
|
+
// Liste des objets dans le répertoire
|
|
276
|
+
const listedObjects = await this.s3.listObjectsV2({
|
|
277
|
+
Bucket: bucket,
|
|
278
|
+
Prefix: directoryPath
|
|
279
|
+
}).promise();
|
|
280
|
+
|
|
281
|
+
if (!listedObjects.Contents?.length) return;
|
|
282
|
+
|
|
283
|
+
// Supprimer les objets
|
|
284
|
+
await this.s3.deleteObjects({
|
|
285
|
+
Bucket: bucket,
|
|
286
|
+
Delete: {
|
|
287
|
+
Objects: listedObjects.Contents.map(({ Key }) => ({ Key }))
|
|
288
|
+
}
|
|
289
|
+
}).promise();
|
|
290
|
+
|
|
291
|
+
// Récursivement, traiter d'autres pages d'objets si elles existent
|
|
292
|
+
//if (listedObjects.IsTruncated) await deleteDirectory();
|
|
293
|
+
|
|
294
|
+
console.log(`Le répertoire ${directoryPath} a été supprimé.`);
|
|
295
|
+
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.error("Erreur lors de la suppression :", error);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPS
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Core
|
|
6
|
+
import type { Application } from '@server/app';
|
|
7
|
+
import Service, { AnyService, TRegisteredServicesIndex, TServiceArgs } from '@server/app/service';
|
|
8
|
+
|
|
9
|
+
// Specific
|
|
10
|
+
import type Driver from './driver';
|
|
11
|
+
export type { default as Driver } from './driver';
|
|
12
|
+
|
|
13
|
+
/*----------------------------------
|
|
14
|
+
- TYPES
|
|
15
|
+
----------------------------------*/
|
|
16
|
+
|
|
17
|
+
type Config = {
|
|
18
|
+
debug: boolean,
|
|
19
|
+
default: string,//keyof MountpointList,
|
|
20
|
+
drivers: {
|
|
21
|
+
[driverId: string]: Driver
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type Hooks = {
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type Services = {
|
|
30
|
+
[diskId: string]: Driver
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*----------------------------------
|
|
34
|
+
- SERVICE
|
|
35
|
+
----------------------------------*/
|
|
36
|
+
export default class DisksManager<
|
|
37
|
+
MountpointList extends Services,
|
|
38
|
+
TConfig extends Config,
|
|
39
|
+
TApplication extends Application
|
|
40
|
+
> extends Service<TConfig, Hooks, TApplication, TApplication> {
|
|
41
|
+
|
|
42
|
+
public default!: Driver;
|
|
43
|
+
|
|
44
|
+
/*----------------------------------
|
|
45
|
+
- LIFECYCLE
|
|
46
|
+
----------------------------------*/
|
|
47
|
+
|
|
48
|
+
public constructor( ...args: TServiceArgs<DisksManager<MountpointList, TConfig, TApplication>>) {
|
|
49
|
+
|
|
50
|
+
super(...args);
|
|
51
|
+
|
|
52
|
+
const drivers = this.config.drivers;
|
|
53
|
+
|
|
54
|
+
if (Object.keys( drivers ).length === 0)
|
|
55
|
+
throw new Error("At least one disk driver should be mounted.");
|
|
56
|
+
|
|
57
|
+
// Bind current instance of the service as parent
|
|
58
|
+
/*for (const driverId in drivers) {
|
|
59
|
+
drivers[driverId].parent = this;
|
|
60
|
+
}*/
|
|
61
|
+
|
|
62
|
+
const defaultDisk = drivers[ this.config.default ];
|
|
63
|
+
if (defaultDisk === undefined)
|
|
64
|
+
console.log(`Default disk "${this.config.default as string}" not mounted.`);
|
|
65
|
+
|
|
66
|
+
this.default = defaultDisk;
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public async shutdown() {
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/*----------------------------------
|
|
75
|
+
- LIFECYCLE
|
|
76
|
+
----------------------------------*/
|
|
77
|
+
|
|
78
|
+
public get( diskName?: 'default' | keyof MountpointList ): Driver {
|
|
79
|
+
|
|
80
|
+
const disk = diskName == 'default' || diskName === undefined
|
|
81
|
+
? this.default
|
|
82
|
+
: this.config.drivers[diskName];
|
|
83
|
+
|
|
84
|
+
if (disk === undefined)
|
|
85
|
+
throw new Error(`Disk "${diskName as string}" not found.`);
|
|
86
|
+
|
|
87
|
+
return disk;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
}
|