@ruiapp/rapid-core 0.1.2 → 0.1.4
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/dist/bootstrapApplicationConfig.d.ts +289 -2
- package/dist/core/http/formDataParser.d.ts +22 -0
- package/dist/core/providers/runtimeProvider.d.ts +4 -0
- package/dist/core/routeContext.d.ts +0 -1
- package/dist/deno-std/encoding/base64.d.ts +11 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +492 -147
- package/dist/plugins/authManager/routes/getMyProfile.d.ts +11 -2
- package/dist/plugins/authManager/routes/index.d.ts +21 -1
- package/dist/plugins/authManager/routes/signin.d.ts +11 -2
- package/dist/plugins/authManager/routes/signout.d.ts +11 -2
- package/dist/plugins/fileManager/httpHandlers/downloadDocument.d.ts +4 -0
- package/dist/plugins/fileManager/httpHandlers/downloadFile.d.ts +4 -0
- package/dist/plugins/fileManager/httpHandlers/uploadFile.d.ts +4 -0
- package/dist/plugins/fileManager/mod.d.ts +15 -0
- package/dist/types.d.ts +2 -2
- package/dist/utilities/fsUtility.d.ts +6 -0
- package/dist/utilities/jwtUtility.d.ts +5 -8
- package/package.json +5 -3
- package/src/bootstrapApplicationConfig.ts +5 -5
- package/src/core/http/formDataParser.ts +101 -0
- package/src/core/pluginManager.ts +2 -0
- package/src/core/providers/runtimeProvider.ts +5 -0
- package/src/core/request.ts +2 -1
- package/src/core/routeContext.ts +0 -1
- package/src/core/routesBuilder.ts +3 -15
- package/src/deno-std/encoding/base64.ts +145 -0
- package/src/index.ts +2 -0
- package/src/plugins/authManager/httpHandlers/createSession.ts +4 -3
- package/src/plugins/authManager/routes/getMyProfile.ts +2 -2
- package/src/plugins/authManager/routes/signin.ts +2 -2
- package/src/plugins/authManager/routes/signout.ts +2 -2
- package/src/plugins/dataManager/httpHandlers/addEntityRelations.ts +0 -2
- package/src/plugins/dataManager/mod.ts +9 -9
- package/src/plugins/fileManager/httpHandlers/downloadDocument.ts +40 -0
- package/src/plugins/fileManager/httpHandlers/downloadFile.ts +32 -0
- package/src/plugins/fileManager/httpHandlers/uploadFile.ts +37 -0
- package/src/plugins/fileManager/mod.ts +48 -0
- package/src/server.ts +0 -1
- package/src/types.ts +2 -2
- package/src/utilities/fsUtility.ts +62 -0
- package/src/utilities/jwtUtility.ts +22 -8
|
@@ -39,55 +39,55 @@ const routeConfigs: {
|
|
|
39
39
|
}[] = [
|
|
40
40
|
{
|
|
41
41
|
code: "createBatch",
|
|
42
|
-
method: "
|
|
42
|
+
method: "POST",
|
|
43
43
|
endpoint: "/operations/create_batch",
|
|
44
44
|
handlerCode: "createCollectionEntitiesBatch",
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
code: "find",
|
|
48
|
-
method: "
|
|
48
|
+
method: "POST",
|
|
49
49
|
endpoint: "/operations/find",
|
|
50
50
|
handlerCode: "findCollectionEntities",
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
code: "count",
|
|
54
|
-
method: "
|
|
54
|
+
method: "POST",
|
|
55
55
|
endpoint: "/operations/count",
|
|
56
56
|
handlerCode: "countCollectionEntities",
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
code: "addRelations",
|
|
60
|
-
method: "
|
|
60
|
+
method: "POST",
|
|
61
61
|
endpoint: "/operations/add_relations",
|
|
62
62
|
handlerCode: "addEntityRelations",
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
code: "removeRelations",
|
|
66
|
-
method: "
|
|
66
|
+
method: "POST",
|
|
67
67
|
endpoint: "/operations/remove_relations",
|
|
68
68
|
handlerCode: "removeEntityRelations",
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
code: "getById",
|
|
72
|
-
method: "
|
|
72
|
+
method: "GET",
|
|
73
73
|
endpoint: "/:id",
|
|
74
74
|
handlerCode: "findCollectionEntityById",
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
code: "create",
|
|
78
|
-
method: "
|
|
78
|
+
method: "POST",
|
|
79
79
|
endpoint: "",
|
|
80
80
|
handlerCode: "createCollectionEntity",
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
code: "updateById",
|
|
84
|
-
method: "
|
|
84
|
+
method: "PATCH",
|
|
85
85
|
endpoint: "/:id",
|
|
86
86
|
handlerCode: "updateCollectionEntityById",
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
code: "deleteById",
|
|
90
|
-
method: "
|
|
90
|
+
method: "DELETE",
|
|
91
91
|
endpoint: "/:id",
|
|
92
92
|
handlerCode: "deleteCollectionEntityById",
|
|
93
93
|
},
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { IPluginInstance } from "~/types";
|
|
3
|
+
import { HttpHandlerContext } from "~/core/httpHandler";
|
|
4
|
+
import { readFile } from "~/utilities/fsUtility";
|
|
5
|
+
|
|
6
|
+
export const code = "downloadDocument";
|
|
7
|
+
|
|
8
|
+
export async function handler(
|
|
9
|
+
plugin: IPluginInstance,
|
|
10
|
+
ctx: HttpHandlerContext,
|
|
11
|
+
options: any,
|
|
12
|
+
) {
|
|
13
|
+
const { server, applicationConfig, routerContext, input } = ctx;
|
|
14
|
+
const { request, response } = routerContext;
|
|
15
|
+
|
|
16
|
+
const documentDataAccessor = ctx.server.getDataAccessor({
|
|
17
|
+
singularCode: "ecm_document",
|
|
18
|
+
});
|
|
19
|
+
const storageDataAccessor = ctx.server.getDataAccessor({
|
|
20
|
+
singularCode: "ecm_storage_object",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const document = await documentDataAccessor.findById(input.documentId);
|
|
24
|
+
if (!document) {
|
|
25
|
+
ctx.output = { error: new Error("Document not found.") };
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const storageObject = await storageDataAccessor.findById(document.storage_object_id);
|
|
29
|
+
if (!storageObject) {
|
|
30
|
+
ctx.output = { error: new Error("Storage object not found.") };
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const fileKey = storageObject.key;
|
|
35
|
+
const filePathName = path.join(server.config.localFileStoragePath, fileKey);
|
|
36
|
+
const attachmentFileName = document.name;
|
|
37
|
+
|
|
38
|
+
response.body = await readFile(filePathName);
|
|
39
|
+
response.headers.set("Content-Disposition", `attachment; filename="${encodeURIComponent(attachmentFileName)}"`)
|
|
40
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { IPluginInstance } from "~/types";
|
|
3
|
+
import { readFile } from "~/utilities/fsUtility";
|
|
4
|
+
import { HttpHandlerContext } from "~/core/httpHandler";
|
|
5
|
+
|
|
6
|
+
export const code = "downloadFile";
|
|
7
|
+
|
|
8
|
+
export async function handler(
|
|
9
|
+
plugin: IPluginInstance,
|
|
10
|
+
ctx: HttpHandlerContext,
|
|
11
|
+
options: any,
|
|
12
|
+
) {
|
|
13
|
+
const { server, applicationConfig, routerContext, input } = ctx;
|
|
14
|
+
const { request, response } = routerContext;
|
|
15
|
+
|
|
16
|
+
const dataAccessor = ctx.server.getDataAccessor({
|
|
17
|
+
singularCode: "ecm_storage_object",
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const storageObject = await dataAccessor.findById(input.fileId);
|
|
21
|
+
if (!storageObject) {
|
|
22
|
+
ctx.output = { error: new Error("Storage object not found.") };
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const fileKey = storageObject.key;
|
|
27
|
+
const filePathName = path.join(server.config.localFileStoragePath, fileKey);
|
|
28
|
+
const attachmentFileName = input.fileName || path.basename(fileKey);
|
|
29
|
+
|
|
30
|
+
response.body = await readFile(filePathName);
|
|
31
|
+
response.headers.set("Content-Disposition", `attachment; filename="${encodeURIComponent(attachmentFileName)}"`)
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { v1 as uuidv1 } from "uuid";
|
|
2
|
+
import { IPluginInstance } from "~/types";
|
|
3
|
+
import { appendFile } from "~/utilities/fsUtility";
|
|
4
|
+
import { HttpHandlerContext } from "~/core/httpHandler";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { isArray } from "lodash";
|
|
7
|
+
|
|
8
|
+
export const code = "uploadFile";
|
|
9
|
+
|
|
10
|
+
export async function handler(
|
|
11
|
+
plugin: IPluginInstance,
|
|
12
|
+
ctx: HttpHandlerContext,
|
|
13
|
+
options: any,
|
|
14
|
+
) {
|
|
15
|
+
const { server, applicationConfig, routerContext, input } = ctx;
|
|
16
|
+
const { request, response } = routerContext;
|
|
17
|
+
|
|
18
|
+
let file: File | File[] | null = input.files;
|
|
19
|
+
if (isArray(file)) {
|
|
20
|
+
file = file[0];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!file) {
|
|
24
|
+
ctx.status = 400;
|
|
25
|
+
ctx.output = { error: "File not found in request body."};
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const extName = path.extname(file.name);
|
|
30
|
+
const fileKey = `${uuidv1()}${extName}`
|
|
31
|
+
const filePathName = path.join(server.config.localFileStoragePath, fileKey);
|
|
32
|
+
|
|
33
|
+
const fileBuffer = await file.arrayBuffer();
|
|
34
|
+
await appendFile(filePathName, fileBuffer);
|
|
35
|
+
|
|
36
|
+
ctx.output = { ok: true, fileKey };
|
|
37
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File manager plugin
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as _ from "lodash";
|
|
6
|
+
import {
|
|
7
|
+
IPluginInstance,
|
|
8
|
+
RpdApplicationConfig,
|
|
9
|
+
} from "~/types";
|
|
10
|
+
|
|
11
|
+
import * as downloadDocumentHttpHandler from "./httpHandlers/downloadDocument";
|
|
12
|
+
import * as downloadFileHttpHandler from "./httpHandlers/downloadFile";
|
|
13
|
+
import * as uploadFileHttpHandler from "./httpHandlers/uploadFile";
|
|
14
|
+
import { IRpdServer, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "~/core/server";
|
|
15
|
+
|
|
16
|
+
export const code = "fileManager";
|
|
17
|
+
export const description = "fileManager";
|
|
18
|
+
export const extendingAbilities: RpdServerPluginExtendingAbilities[] = [];
|
|
19
|
+
export const configurableTargets: RpdServerPluginConfigurableTargetOptions[] = [];
|
|
20
|
+
export const configurations: RpdConfigurationItemOptions[] = [];
|
|
21
|
+
|
|
22
|
+
let _plugin: IPluginInstance;
|
|
23
|
+
|
|
24
|
+
export async function initPlugin(plugin: IPluginInstance, server: IRpdServer) {
|
|
25
|
+
_plugin = plugin;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function registerHttpHandlers(server: IRpdServer) {
|
|
29
|
+
server.registerHttpHandler(_plugin, downloadDocumentHttpHandler);
|
|
30
|
+
server.registerHttpHandler(_plugin, downloadFileHttpHandler);
|
|
31
|
+
server.registerHttpHandler(_plugin, uploadFileHttpHandler);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function registerEventHandlers(server: IRpdServer) {
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function configureModels(
|
|
38
|
+
server: IRpdServer,
|
|
39
|
+
applicationConfig: RpdApplicationConfig,
|
|
40
|
+
) {
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function onApplicationLoaded(
|
|
44
|
+
server: IRpdServer,
|
|
45
|
+
applicationConfig: RpdApplicationConfig,
|
|
46
|
+
) {
|
|
47
|
+
console.log("fileManager.onApplicationLoaded");
|
|
48
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -223,7 +223,6 @@ export class RapidServer implements IRpdServer {
|
|
|
223
223
|
const rapidRequest = new RapidRequest(request);
|
|
224
224
|
await rapidRequest.parseBody();
|
|
225
225
|
const routeContext = new RouteContext(rapidRequest);
|
|
226
|
-
console.log('routeContext', routeContext)
|
|
227
226
|
await this.#buildedRoutes(routeContext, next);
|
|
228
227
|
return routeContext.response.getResponse();
|
|
229
228
|
}
|
package/src/types.ts
CHANGED
|
@@ -304,11 +304,11 @@ export interface RpdRoute {
|
|
|
304
304
|
handlers: RpdHttpHandler[];
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
export type RpdHttpMethod = "
|
|
307
|
+
export type RpdHttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
308
308
|
|
|
309
309
|
export interface RpdHttpHandler {
|
|
310
310
|
code: string;
|
|
311
|
-
config
|
|
311
|
+
config?: any;
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
export interface IRpdDataAccessor<T = any> {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
|
|
3
|
+
export async function readFile(path: string): Promise<Buffer> {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
fs.readFile(path, null, (err, data) => {
|
|
6
|
+
if (err) {
|
|
7
|
+
reject(err);
|
|
8
|
+
} else {
|
|
9
|
+
resolve(data);
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function copyFile(fromPath: string, toPath: string): Promise<void> {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
fs.copyFile(fromPath, toPath, (err) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
reject(err);
|
|
20
|
+
} else {
|
|
21
|
+
resolve();
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function removeFile(path: string): Promise<void> {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
fs.rm(path, (err) => {
|
|
30
|
+
if (err) {
|
|
31
|
+
reject(err);
|
|
32
|
+
} else {
|
|
33
|
+
resolve();
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function moveFile(fromPath: string, toPath: string): Promise<void> {
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
fs.rename(fromPath, toPath, (err) => {
|
|
42
|
+
if (err) {
|
|
43
|
+
reject(err);
|
|
44
|
+
} else {
|
|
45
|
+
resolve();
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function appendFile(path: string, data: ArrayBuffer): Promise<void> {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
fs.appendFile(path, Buffer.from(data), (err) => {
|
|
54
|
+
if (err) {
|
|
55
|
+
reject(err);
|
|
56
|
+
} else {
|
|
57
|
+
resolve();
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
}
|
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
import { sign, verify, decode, Secret } from "jsonwebtoken";
|
|
2
|
+
import { encode as base64Encode } from "~/deno-std/encoding/base64";
|
|
3
|
+
import crypto from "crypto";
|
|
1
4
|
|
|
2
|
-
export function
|
|
3
|
-
return
|
|
5
|
+
export function createJwt(payload: Record<string, any>, secret: Secret) {
|
|
6
|
+
return sign(payload, secret, {
|
|
7
|
+
algorithm: 'HS512',
|
|
8
|
+
});
|
|
4
9
|
}
|
|
5
10
|
|
|
6
|
-
export
|
|
7
|
-
return
|
|
11
|
+
export function verifyJwt(token: string, secret: Secret) {
|
|
12
|
+
return verify(token, secret, {
|
|
13
|
+
algorithms: ['HS512'],
|
|
14
|
+
});
|
|
8
15
|
}
|
|
9
16
|
|
|
10
|
-
export
|
|
11
|
-
return {};
|
|
17
|
+
export function decodeJwt(token: string) {
|
|
18
|
+
return decode(token, { complete: true});
|
|
12
19
|
}
|
|
13
20
|
|
|
14
|
-
export async function
|
|
15
|
-
|
|
21
|
+
export async function generateJwtSecretKey() {
|
|
22
|
+
const key = await crypto.subtle.generateKey(
|
|
23
|
+
{ name: "HMAC", hash: "SHA-512" },
|
|
24
|
+
true,
|
|
25
|
+
["sign", "verify"],
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const exportedKey = await crypto.subtle.exportKey("raw", key);
|
|
29
|
+
return base64Encode(exportedKey);
|
|
16
30
|
}
|