create-weave-backend-app 0.1.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/README.md +11 -0
- package/dist/chunk-HIPWNEQ7.js +366 -0
- package/dist/create-app.d.ts +14 -0
- package/dist/create-app.js +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +120 -0
- package/package.json +66 -0
- package/template/+express+azure-web-pubsub/README.md +38 -0
- package/template/+express+azure-web-pubsub/eslint.config.js +11 -0
- package/template/+express+azure-web-pubsub/example.env +10 -0
- package/template/+express+azure-web-pubsub/example.gitignore +37 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/delImage.ts +22 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/getHealth.ts +5 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/getImage.ts +35 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/getImages.ts +19 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/getRoomConnect.ts +17 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/postRemoveBackground.ts +60 -0
- package/template/+express+azure-web-pubsub/src/api/v1/controllers/postUploadImage.ts +35 -0
- package/template/+express+azure-web-pubsub/src/api/v1/router.ts +46 -0
- package/template/+express+azure-web-pubsub/src/app.ts +32 -0
- package/template/+express+azure-web-pubsub/src/config/config.ts +38 -0
- package/template/+express+azure-web-pubsub/src/constants.ts +1 -0
- package/template/+express+azure-web-pubsub/src/images/persistence.ts +240 -0
- package/template/+express+azure-web-pubsub/src/logger/logger.ts +24 -0
- package/template/+express+azure-web-pubsub/src/middlewares/body-parser.ts +11 -0
- package/template/+express+azure-web-pubsub/src/middlewares/cors.ts +16 -0
- package/template/+express+azure-web-pubsub/src/middlewares/http-logger.ts +13 -0
- package/template/+express+azure-web-pubsub/src/middlewares/http-response-headers.ts +14 -0
- package/template/+express+azure-web-pubsub/src/server.ts +28 -0
- package/template/+express+azure-web-pubsub/src/store.ts +77 -0
- package/template/+express+azure-web-pubsub/src/types.ts +6 -0
- package/template/+express+azure-web-pubsub/src/utils.ts +33 -0
- package/template/+express+azure-web-pubsub/src/validate.ts +22 -0
- package/template/+express+azure-web-pubsub/tsconfig.json +16 -0
- package/template/+express+websockets/README.md +38 -0
- package/template/+express+websockets/eslint.config.js +11 -0
- package/template/+express+websockets/example.env +3 -0
- package/template/+express+websockets/example.gitignore +37 -0
- package/template/+express+websockets/src/api/v1/controllers/delImage.ts +22 -0
- package/template/+express+websockets/src/api/v1/controllers/getHealth.ts +5 -0
- package/template/+express+websockets/src/api/v1/controllers/getImage.ts +35 -0
- package/template/+express+websockets/src/api/v1/controllers/getImages.ts +19 -0
- package/template/+express+websockets/src/api/v1/controllers/getRoomConnect.ts +9 -0
- package/template/+express+websockets/src/api/v1/controllers/postRemoveBackground.ts +60 -0
- package/template/+express+websockets/src/api/v1/controllers/postUploadImage.ts +35 -0
- package/template/+express+websockets/src/api/v1/router.ts +44 -0
- package/template/+express+websockets/src/app.ts +32 -0
- package/template/+express+websockets/src/config/config.ts +38 -0
- package/template/+express+websockets/src/constants.ts +1 -0
- package/template/+express+websockets/src/images/persistence.ts +240 -0
- package/template/+express+websockets/src/logger/logger.ts +24 -0
- package/template/+express+websockets/src/middlewares/body-parser.ts +11 -0
- package/template/+express+websockets/src/middlewares/cors.ts +16 -0
- package/template/+express+websockets/src/middlewares/http-logger.ts +13 -0
- package/template/+express+websockets/src/middlewares/http-response-headers.ts +14 -0
- package/template/+express+websockets/src/server.ts +28 -0
- package/template/+express+websockets/src/store.ts +69 -0
- package/template/+express+websockets/src/types.ts +6 -0
- package/template/+express+websockets/src/utils.ts +33 -0
- package/template/+express+websockets/src/validate.ts +22 -0
- package/template/+express+websockets/tsconfig.json +16 -0
- package/template/package.json +55 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import { WeaveAzureWebPubsubServer } from '@inditextech/weave-store-azure-web-pubsub/server';
|
|
4
|
+
import { createFolder, existsFolder } from '@/utils';
|
|
5
|
+
|
|
6
|
+
const endpoint = process.env.WEAVE_AZURE_WEB_PUBSUB_ENDPOINT;
|
|
7
|
+
const key = process.env.WEAVE_AZURE_WEB_PUBSUB_KEY;
|
|
8
|
+
const hubName = process.env.WEAVE_AZURE_WEB_PUBSUB_HUB_NAME;
|
|
9
|
+
|
|
10
|
+
if (!endpoint || !key || !hubName) {
|
|
11
|
+
throw new Error('Missing required environment variables');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let azureWebPubsubServer: WeaveAzureWebPubsubServer | null = null;
|
|
15
|
+
|
|
16
|
+
export const getAzureWebPubsubServer = () => {
|
|
17
|
+
if (!azureWebPubsubServer) {
|
|
18
|
+
throw new Error('Azure Web Pubsub server not initialized');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return azureWebPubsubServer;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const setupStore = () => {
|
|
25
|
+
azureWebPubsubServer = new WeaveAzureWebPubsubServer({
|
|
26
|
+
pubsubConfig: {
|
|
27
|
+
endpoint,
|
|
28
|
+
key,
|
|
29
|
+
hubName,
|
|
30
|
+
},
|
|
31
|
+
fetchRoom: async (docName: string) => {
|
|
32
|
+
try {
|
|
33
|
+
const roomsFolder = path.join(__dirname, 'rooms');
|
|
34
|
+
|
|
35
|
+
if (!(await existsFolder(roomsFolder))) {
|
|
36
|
+
await createFolder(roomsFolder);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const roomsFile = path.join(roomsFolder, docName);
|
|
40
|
+
return await fs.readFile(roomsFile);
|
|
41
|
+
} catch (ex) {
|
|
42
|
+
console.error(ex);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
persistRoom: async (
|
|
47
|
+
docName: string,
|
|
48
|
+
actualState: Uint8Array<ArrayBufferLike>
|
|
49
|
+
) => {
|
|
50
|
+
try {
|
|
51
|
+
const roomsFolder = path.join(__dirname, 'rooms');
|
|
52
|
+
|
|
53
|
+
if (!(await existsFolder(roomsFolder))) {
|
|
54
|
+
await createFolder(roomsFolder);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let folderExists = false;
|
|
58
|
+
try {
|
|
59
|
+
await fs.access(roomsFolder);
|
|
60
|
+
folderExists = true;
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
62
|
+
} catch (e) {
|
|
63
|
+
folderExists = false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!folderExists) {
|
|
67
|
+
await fs.mkdir(roomsFolder, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const roomsFile = path.join(roomsFolder, docName);
|
|
71
|
+
await fs.writeFile(roomsFile, actualState);
|
|
72
|
+
} catch (ex) {
|
|
73
|
+
console.error(ex);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
export const getFileContents = async (
|
|
4
|
+
filePath: string,
|
|
5
|
+
encoding: BufferEncoding = 'utf-8',
|
|
6
|
+
): Promise<string> => {
|
|
7
|
+
try {
|
|
8
|
+
const content = await fs.readFile(filePath, { encoding });
|
|
9
|
+
return content;
|
|
10
|
+
} catch (err) {
|
|
11
|
+
console.error(
|
|
12
|
+
`Error reading file ${filePath}: ${err instanceof Error ? err.message : err}`,
|
|
13
|
+
);
|
|
14
|
+
throw err;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const existsFolder = async (folderPath: string) => {
|
|
19
|
+
try {
|
|
20
|
+
const stats = await fs.stat(folderPath);
|
|
21
|
+
return stats.isDirectory();
|
|
22
|
+
} catch (err) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const createFolder = async (folderPath: string): Promise<void> => {
|
|
28
|
+
try {
|
|
29
|
+
await fs.mkdir(folderPath, { recursive: true });
|
|
30
|
+
} catch (err) {
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ZodError } from "zod";
|
|
2
|
+
import { getServiceConfig } from "./config/config.js";
|
|
3
|
+
import { ServiceConfig } from "./types.js";
|
|
4
|
+
import { getLogger } from "./logger/logger.js";
|
|
5
|
+
|
|
6
|
+
export function validateServiceConfig() {
|
|
7
|
+
let config: ServiceConfig | null = null;
|
|
8
|
+
const logger = getLogger().child({ module: "validate" });
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
config = getServiceConfig();
|
|
12
|
+
} catch (ex) {
|
|
13
|
+
// console.log(ex);
|
|
14
|
+
if (ex instanceof ZodError) {
|
|
15
|
+
for (const issue of ex.issues) {
|
|
16
|
+
logger.error(issue.message);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2020",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"moduleResolution": "nodenext",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"paths": {
|
|
13
|
+
"@/*": ["./src/*"]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Weave.js Backend start template
|
|
2
|
+
|
|
3
|
+
This is an Express.js application that was generated with **Create Weave.js Backend**
|
|
4
|
+
|
|
5
|
+
This server setup the Weave.js
|
|
6
|
+
[Azure WebSockets](https://inditextech.github.io/weavejs/docs/main/build/stores/websockets-store) store. No extra setup needed.
|
|
7
|
+
|
|
8
|
+
## Quickstart
|
|
9
|
+
|
|
10
|
+
If you skipped the automatic installation of the dependencies, run first this
|
|
11
|
+
command:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install
|
|
15
|
+
# or
|
|
16
|
+
pnpm install
|
|
17
|
+
# or
|
|
18
|
+
yarn install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Now, lets run the development server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run dev
|
|
25
|
+
# or
|
|
26
|
+
pnpm dev
|
|
27
|
+
# or
|
|
28
|
+
yarn dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Learn more
|
|
32
|
+
|
|
33
|
+
To learn more about Express.js and Weave.js, take a look at the following
|
|
34
|
+
resources:
|
|
35
|
+
|
|
36
|
+
- [Express.js](https://expressjs.com/) - learn about Express.js
|
|
37
|
+
- [Weave.js](https://inditextech.github.io/weavejs) - learn about Weave.js
|
|
38
|
+
- [Weave.js repository](https://github.com/InditexTech/weavejs) - check out out code.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import globals from "globals";
|
|
2
|
+
import pluginJs from "@eslint/js";
|
|
3
|
+
import tseslint from "typescript-eslint";
|
|
4
|
+
|
|
5
|
+
/** @type {import('eslint').Linter.Config[]} */
|
|
6
|
+
export default [
|
|
7
|
+
{files: ["**/*.{js,mjs,cjs,ts}"], ignores: ["dist/**/*"],},
|
|
8
|
+
{languageOptions: { globals: globals.node }},
|
|
9
|
+
pluginJs.configs.recommended,
|
|
10
|
+
...tseslint.configs.recommended,
|
|
11
|
+
];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
pnpm-debug.log*
|
|
8
|
+
lerna-debug.log*
|
|
9
|
+
reports
|
|
10
|
+
|
|
11
|
+
node_modules
|
|
12
|
+
dist
|
|
13
|
+
dist-ssr
|
|
14
|
+
*.local
|
|
15
|
+
vite.config.ts*
|
|
16
|
+
!vite.config.ts
|
|
17
|
+
|
|
18
|
+
# Editor directories and files
|
|
19
|
+
.vscode/*
|
|
20
|
+
!.vscode/extensions.json
|
|
21
|
+
.idea
|
|
22
|
+
.DS_Store
|
|
23
|
+
*.suo
|
|
24
|
+
*.ntvs*
|
|
25
|
+
*.njsproj
|
|
26
|
+
*.sln
|
|
27
|
+
*.sw?
|
|
28
|
+
|
|
29
|
+
*.pem
|
|
30
|
+
.env*
|
|
31
|
+
.npmrc
|
|
32
|
+
|
|
33
|
+
images
|
|
34
|
+
images-mimetype
|
|
35
|
+
rooms
|
|
36
|
+
temp
|
|
37
|
+
public
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { ImagesPersistenceHandler } from "../../../images/persistence.js";
|
|
3
|
+
|
|
4
|
+
export const delImageController = () => {
|
|
5
|
+
const persistenceHandler = new ImagesPersistenceHandler()
|
|
6
|
+
|
|
7
|
+
return async (req: Request, res: Response): Promise<void> => {
|
|
8
|
+
const roomId = req.params.roomId;
|
|
9
|
+
const imageId = req.params.imageId;
|
|
10
|
+
|
|
11
|
+
const fileName = `${roomId}/${imageId}`;
|
|
12
|
+
|
|
13
|
+
const result = await persistenceHandler.delete(fileName);
|
|
14
|
+
|
|
15
|
+
if (result) {
|
|
16
|
+
res.status(200).json({ status: "KO", message: "Image deleted" });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
res.status(404).json({ status: "KO", message: "Image not found" });
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { ImagesPersistenceHandler } from '../../../images/persistence.js';
|
|
3
|
+
|
|
4
|
+
export const getImageController = () => {
|
|
5
|
+
const persistenceHandler = new ImagesPersistenceHandler();
|
|
6
|
+
|
|
7
|
+
return async (req: Request, res: Response): Promise<void> => {
|
|
8
|
+
const roomId = req.params.roomId;
|
|
9
|
+
const imageId = req.params.imageId;
|
|
10
|
+
|
|
11
|
+
const fileName = `${roomId}/${imageId}`;
|
|
12
|
+
|
|
13
|
+
if (!(await persistenceHandler.exists(fileName))) {
|
|
14
|
+
res.status(404).json({ status: 'KO', message: "Image doesn't exists" });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const filePath = await persistenceHandler.getFilePath(fileName);
|
|
19
|
+
|
|
20
|
+
if (filePath) {
|
|
21
|
+
const mimeType = await persistenceHandler.getMimeType(fileName);
|
|
22
|
+
res.setHeader('Content-Type', mimeType);
|
|
23
|
+
res.sendFile(filePath, (err) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
console.error('File not found or error sending file:', err.message);
|
|
26
|
+
res.status(404).send('Image not found');
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
res
|
|
31
|
+
.status(500)
|
|
32
|
+
.json({ status: 'KO', message: 'Error downloading image' });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { ImagesPersistenceHandler } from '../../../images/persistence.js';
|
|
3
|
+
|
|
4
|
+
export const getImagesController = () => {
|
|
5
|
+
const persistenceHandler = new ImagesPersistenceHandler();
|
|
6
|
+
|
|
7
|
+
return async (req: Request, res: Response): Promise<void> => {
|
|
8
|
+
const roomId = req.params.roomId;
|
|
9
|
+
|
|
10
|
+
const pageSize = parseInt(
|
|
11
|
+
(req.query.pageSize as string | undefined) ?? '20',
|
|
12
|
+
);
|
|
13
|
+
const page = parseInt((req.query.page as string | undefined) ?? '1');
|
|
14
|
+
|
|
15
|
+
const images = await persistenceHandler.list(roomId, pageSize, page);
|
|
16
|
+
|
|
17
|
+
res.status(200).json(images);
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { Request, Response } from 'express';
|
|
4
|
+
import { removeBackground } from '@imgly/background-removal-node';
|
|
5
|
+
import { ImagesPersistenceHandler } from '../../../images/persistence.js';
|
|
6
|
+
|
|
7
|
+
async function myBlobToUIntDemo(blob: Blob) {
|
|
8
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
9
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
10
|
+
return new Uint8Array(buffer);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const postRemoveBackgroundController = () => {
|
|
14
|
+
const persistenceHandler = new ImagesPersistenceHandler();
|
|
15
|
+
|
|
16
|
+
return async (req: Request, res: Response): Promise<void> => {
|
|
17
|
+
const roomId = req.params.roomId;
|
|
18
|
+
const imageId = req.params.imageId;
|
|
19
|
+
|
|
20
|
+
const fileName = `${roomId}/${imageId}`;
|
|
21
|
+
|
|
22
|
+
if (!(await persistenceHandler.exists(fileName))) {
|
|
23
|
+
res.status(404).json({ status: 'KO', message: "Image doesn't exists" });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const filePathDownload = await persistenceHandler.getFilePath(fileName);
|
|
29
|
+
|
|
30
|
+
removeBackground(filePathDownload, {
|
|
31
|
+
publicPath: `file://${path.join(process.cwd(), 'public')}/`,
|
|
32
|
+
output: { format: 'image/png', quality: 1 },
|
|
33
|
+
})
|
|
34
|
+
.then(async (blob: Blob) => {
|
|
35
|
+
// The result is a blob encoded as PNG. It can be converted to an URL to be used as HTMLImage.src
|
|
36
|
+
const data = await myBlobToUIntDemo(blob);
|
|
37
|
+
const fileNameRemoved = `${fileName}-removed`;
|
|
38
|
+
await persistenceHandler.persist(fileNameRemoved, 'image/png', data);
|
|
39
|
+
fs.rmSync(filePathDownload);
|
|
40
|
+
|
|
41
|
+
res.status(201).json({
|
|
42
|
+
status: 'Image created OK',
|
|
43
|
+
fileName: fileNameRemoved,
|
|
44
|
+
mimeType: 'image/png',
|
|
45
|
+
});
|
|
46
|
+
})
|
|
47
|
+
.catch((err) => {
|
|
48
|
+
console.error(err);
|
|
49
|
+
res
|
|
50
|
+
.status(500)
|
|
51
|
+
.json({ status: 'KO', message: 'Error transforming the image' });
|
|
52
|
+
});
|
|
53
|
+
} catch (ex) {
|
|
54
|
+
console.error(ex);
|
|
55
|
+
res
|
|
56
|
+
.status(500)
|
|
57
|
+
.json({ status: 'KO', message: 'Error downloading the image' });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { ImagesPersistenceHandler } from '../../../images/persistence.js';
|
|
4
|
+
|
|
5
|
+
export const postUploadImageController = () => {
|
|
6
|
+
const persistenceHandler = new ImagesPersistenceHandler();
|
|
7
|
+
|
|
8
|
+
return async (req: Request, res: Response): Promise<void> => {
|
|
9
|
+
const file = req.file;
|
|
10
|
+
|
|
11
|
+
const roomId = req.params.roomId;
|
|
12
|
+
const mimeType = file?.mimetype ?? 'application/octet-stream';
|
|
13
|
+
const data = file?.buffer ?? new Uint8Array();
|
|
14
|
+
|
|
15
|
+
const fileName = `${roomId}/${uuidv4()}`;
|
|
16
|
+
|
|
17
|
+
if (await persistenceHandler.exists(fileName)) {
|
|
18
|
+
res.status(500).json({ status: 'KO', message: 'Image already exists' });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (file) {
|
|
23
|
+
await persistenceHandler.persist(fileName, mimeType, data);
|
|
24
|
+
res
|
|
25
|
+
.status(201)
|
|
26
|
+
.json({ status: 'Image created OK', fileName, mimeType });
|
|
27
|
+
} else {
|
|
28
|
+
res.status(500).json({ status: 'KO', message: 'Error creating image' });
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
31
|
+
} catch (error) {
|
|
32
|
+
res.status(500).json({ status: 'KO', message: 'Error creating image' });
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Express, Router } from 'express';
|
|
2
|
+
import multer from 'multer';
|
|
3
|
+
import { getHealthController } from './controllers/getHealth.js';
|
|
4
|
+
import { getRoomConnectController } from './controllers/getRoomConnect.js';
|
|
5
|
+
import { getImageController } from './controllers/getImage.js';
|
|
6
|
+
import { postUploadImageController } from './controllers/postUploadImage.js';
|
|
7
|
+
import { delImageController } from './controllers/delImage.js';
|
|
8
|
+
import { getImagesController } from './controllers/getImages.js';
|
|
9
|
+
import { postRemoveBackgroundController } from './controllers/postRemoveBackground.js';
|
|
10
|
+
|
|
11
|
+
const router: Router = Router();
|
|
12
|
+
|
|
13
|
+
export function getApiV1Router() {
|
|
14
|
+
return router;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function setupApiV1Router(app: Express) {
|
|
18
|
+
const router: Router = Router();
|
|
19
|
+
|
|
20
|
+
// Setup multer to upload files
|
|
21
|
+
const upload = multer();
|
|
22
|
+
|
|
23
|
+
// Setup router routes
|
|
24
|
+
router.get(`/health`, getHealthController());
|
|
25
|
+
|
|
26
|
+
// Room handling API
|
|
27
|
+
router.get(`/sync/rooms/:roomId`, getRoomConnectController());
|
|
28
|
+
|
|
29
|
+
// Images handling API
|
|
30
|
+
router.get(`/rooms/:roomId/images`, getImagesController());
|
|
31
|
+
router.get(`/rooms/:roomId/images/:imageId`, getImageController());
|
|
32
|
+
router.post(
|
|
33
|
+
`/rooms/:roomId/images/:imageId/remove-background`,
|
|
34
|
+
postRemoveBackgroundController(),
|
|
35
|
+
);
|
|
36
|
+
router.post(
|
|
37
|
+
`/rooms/:roomId/images`,
|
|
38
|
+
upload.single('file'),
|
|
39
|
+
postUploadImageController(),
|
|
40
|
+
);
|
|
41
|
+
router.delete(`/rooms/:roomId/images/:imageId`, delImageController());
|
|
42
|
+
|
|
43
|
+
app.use('/api/v1', router);
|
|
44
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import express, { type Express } from "express";
|
|
2
|
+
import { setupHttpLoggerMiddleware } from "./middlewares/http-logger.js";
|
|
3
|
+
import { setupCorsMiddleware } from "./middlewares/cors.js";
|
|
4
|
+
import { setupHttpResponseHeadersMiddleware } from "./middlewares/http-response-headers.js";
|
|
5
|
+
import { setupBodyParserMiddleware } from "./middlewares/body-parser.js";
|
|
6
|
+
import { setupApiV1Router } from "./api/v1/router.js";
|
|
7
|
+
|
|
8
|
+
let app: Express | null = null;
|
|
9
|
+
|
|
10
|
+
export function getApp() {
|
|
11
|
+
if (!app) {
|
|
12
|
+
throw new Error("App not initialized");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return app;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function setupApp() {
|
|
19
|
+
// Setup the service
|
|
20
|
+
app = express();
|
|
21
|
+
|
|
22
|
+
// Setup Middlewares
|
|
23
|
+
setupHttpLoggerMiddleware(app);
|
|
24
|
+
setupCorsMiddleware(app);
|
|
25
|
+
setupHttpResponseHeadersMiddleware(app);
|
|
26
|
+
setupBodyParserMiddleware(app);
|
|
27
|
+
|
|
28
|
+
// Setup Routers
|
|
29
|
+
setupApiV1Router(app);
|
|
30
|
+
|
|
31
|
+
return app;
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ServiceConfig } from '../types.js';
|
|
3
|
+
import { DEFAULT_PORT } from '../constants.js';
|
|
4
|
+
|
|
5
|
+
const serviceConfigSchema = z.object({
|
|
6
|
+
service: z.object({
|
|
7
|
+
hostname: z
|
|
8
|
+
.string({
|
|
9
|
+
required_error:
|
|
10
|
+
'Define the service hostname on the environment variable HOSTNAME',
|
|
11
|
+
})
|
|
12
|
+
.trim()
|
|
13
|
+
.optional()
|
|
14
|
+
.default('0.0.0.0'),
|
|
15
|
+
port: z
|
|
16
|
+
.number({
|
|
17
|
+
required_error:
|
|
18
|
+
'Define the service port on the environment variable PORT',
|
|
19
|
+
})
|
|
20
|
+
.int({ message: 'The post must be an integer' })
|
|
21
|
+
.optional()
|
|
22
|
+
.default(DEFAULT_PORT),
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export function getServiceConfig(): ServiceConfig {
|
|
27
|
+
const hostname = process.env.HOSTNAME;
|
|
28
|
+
const port = parseInt(process.env.PORT || `${DEFAULT_PORT}`);
|
|
29
|
+
|
|
30
|
+
const service = {
|
|
31
|
+
hostname,
|
|
32
|
+
port,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const serviceConfig = { service };
|
|
36
|
+
|
|
37
|
+
return serviceConfigSchema.parse(serviceConfig);
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_PORT = 3000;
|