@into-cps-association/libms 0.4.5 → 0.5.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/DEVELOPER.md +80 -0
- package/DOCKER.md +295 -0
- package/README.md +8 -0
- package/compose.lib.dev.yml +9 -0
- package/compose.lib.yml +8 -0
- package/dist/src/app.module.d.ts +2 -1
- package/dist/src/app.module.js +14 -16
- package/dist/src/app.module.js.map +1 -1
- package/dist/src/bootstrap.d.ts +3 -3
- package/dist/src/bootstrap.js +13 -13
- package/dist/src/bootstrap.js.map +1 -1
- package/dist/src/cloudcmd/cloudcmd.d.ts +1 -5
- package/dist/src/cloudcmd/cloudcmd.js +15 -9
- package/dist/src/cloudcmd/cloudcmd.js.map +1 -1
- package/dist/src/enums/config-mode.enum.d.ts +4 -0
- package/dist/src/enums/config-mode.enum.js +6 -0
- package/dist/src/enums/config-mode.enum.js.map +1 -0
- package/dist/src/files/files-service.factory.d.ts +5 -0
- package/dist/src/files/files-service.factory.js +22 -0
- package/dist/src/files/files-service.factory.js.map +1 -0
- package/dist/src/files/files.module.d.ts +2 -1
- package/dist/src/files/files.module.js +23 -9
- package/dist/src/files/files.module.js.map +1 -1
- package/dist/src/files/files.resolver.d.ts +8 -0
- package/dist/src/files/{resolvers/files.resolver.js → files.resolver.js} +14 -14
- package/dist/src/files/files.resolver.js.map +1 -0
- package/dist/src/files/git/git-files.module.d.ts +2 -0
- package/dist/src/files/git/git-files.module.js +19 -0
- package/dist/src/files/git/git-files.module.js.map +1 -0
- package/dist/src/files/git/git-files.service.d.ts +14 -0
- package/dist/src/files/git/git-files.service.js +67 -0
- package/dist/src/files/git/git-files.service.js.map +1 -0
- package/dist/src/files/interfaces/files.service.interface.d.ts +6 -3
- package/dist/src/files/interfaces/files.service.interface.js +1 -2
- package/dist/src/files/interfaces/files.service.interface.js.map +1 -1
- package/dist/src/files/local/local-files.module.d.ts +2 -0
- package/dist/src/files/local/local-files.module.js +18 -0
- package/dist/src/files/local/local-files.module.js.map +1 -0
- package/dist/src/files/local/local-files.service.d.ts +14 -0
- package/dist/src/files/{services → local}/local-files.service.js +17 -15
- package/dist/src/files/local/local-files.service.js.map +1 -0
- package/dist/src/main.js +4 -6
- package/dist/src/main.js.map +1 -1
- package/dist/src/types.d.ts +19 -19
- package/dist/src/types.js +56 -59
- package/dist/src/types.js.map +1 -1
- package/dist/test/cloudcmd/cloudcmd.spec.js +14 -16
- package/dist/test/cloudcmd/cloudcmd.spec.js.map +1 -1
- package/dist/test/e2e/app.e2e.spec.js +18 -18
- package/dist/test/e2e/app.e2e.spec.js.map +1 -1
- package/dist/test/integration/files.service.integration.spec.js +28 -19
- package/dist/test/integration/files.service.integration.spec.js.map +1 -1
- package/dist/test/testUtil.d.ts +66 -68
- package/dist/test/testUtil.js +21 -23
- package/dist/test/testUtil.js.map +1 -1
- package/dist/test/unit/files-service.factory.unit.spec.js +22 -16
- package/dist/test/unit/files-service.factory.unit.spec.js.map +1 -1
- package/dist/test/unit/files.resolver.unit.spec.js +26 -24
- package/dist/test/unit/files.resolver.unit.spec.js.map +1 -1
- package/dist/test/unit/git-files.service.unit.spec.d.ts +1 -0
- package/dist/test/unit/git-files.service.unit.spec.js +55 -0
- package/dist/test/unit/git-files.service.unit.spec.js.map +1 -0
- package/dist/test/unit/local-files.service.unit.spec.js +23 -24
- package/dist/test/unit/local-files.service.unit.spec.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/eslint.config.js +60 -0
- package/jest.config.ts +47 -0
- package/package.json +55 -48
- package/src/app.module.ts +1 -1
- package/src/bootstrap.ts +7 -3
- package/src/cloudcmd/cloudcmd.ts +11 -3
- package/src/enums/config-mode.enum.ts +4 -0
- package/src/files/files-service.factory.ts +19 -0
- package/src/files/files.module.ts +24 -4
- package/src/files/{resolvers/files.resolver.ts → files.resolver.ts} +9 -8
- package/src/files/git/git-files.module.ts +9 -0
- package/src/files/git/git-files.service.ts +58 -0
- package/src/files/interfaces/files.service.interface.ts +4 -1
- package/src/files/local/local-files.module.ts +8 -0
- package/src/files/{services → local}/local-files.service.ts +15 -10
- package/src/main.ts +1 -1
- package/test/cloudcmd/cloudcmd.spec.ts +4 -6
- package/test/e2e/app.e2e.spec.ts +4 -3
- package/test/integration/files.service.integration.spec.ts +19 -4
- package/test/testUtil.ts +3 -0
- package/test/unit/files-service.factory.unit.spec.ts +24 -10
- package/test/unit/files.resolver.unit.spec.ts +19 -12
- package/test/unit/git-files.service.unit.spec.ts +81 -0
- package/test/unit/local-files.service.unit.spec.ts +4 -2
- package/tsconfig.json +10 -7
- package/.env +0 -6
- package/.eslintignore +0 -6
- package/.eslintrc +0 -53
- package/coverage/clover.xml +0 -162
- package/coverage/cobertura-coverage.xml +0 -306
- package/coverage/coverage-final.json +0 -8
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -176
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/bootstrap.ts.html +0 -196
- package/coverage/lcov-report/src/cloudcmd/cloudcmd.ts.html +0 -181
- package/coverage/lcov-report/src/cloudcmd/index.html +0 -116
- package/coverage/lcov-report/src/files/files.module.ts.html +0 -112
- package/coverage/lcov-report/src/files/index.html +0 -116
- package/coverage/lcov-report/src/files/resolvers/files.resolver.ts.html +0 -154
- package/coverage/lcov-report/src/files/resolvers/index.html +0 -116
- package/coverage/lcov-report/src/files/services/files-service.factory.ts.html +0 -151
- package/coverage/lcov-report/src/files/services/index.html +0 -131
- package/coverage/lcov-report/src/files/services/local-files.service.ts.html +0 -313
- package/coverage/lcov-report/src/index.html +0 -131
- package/coverage/lcov-report/src/types.ts.html +0 -361
- package/coverage/lcov.info +0 -237
- package/dist/src/files/resolvers/files.resolver.d.ts +0 -8
- package/dist/src/files/resolvers/files.resolver.js.map +0 -1
- package/dist/src/files/services/files-service.factory.d.ts +0 -12
- package/dist/src/files/services/files-service.factory.js +0 -40
- package/dist/src/files/services/files-service.factory.js.map +0 -1
- package/dist/src/files/services/local-files.service.d.ts +0 -11
- package/dist/src/files/services/local-files.service.js.map +0 -1
- package/jest.config.json +0 -30
- package/src/files/services/files-service.factory.ts +0 -22
- /package/{pm2.config.js → pm2.config.cjs} +0 -0
package/eslint.config.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { fixupConfigRules } from '@eslint/compat';
|
|
2
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
import jest from 'eslint-plugin-jest';
|
|
5
|
+
import js from '@eslint/js';
|
|
6
|
+
import prettier from 'eslint-config-prettier';
|
|
7
|
+
import ts from '@typescript-eslint/eslint-plugin';
|
|
8
|
+
import tsParser from '@typescript-eslint/parser';
|
|
9
|
+
import imprt from 'eslint-plugin-import'; // 'import' is ambiguous & prettier has trouble
|
|
10
|
+
|
|
11
|
+
const flatCompat = new FlatCompat();
|
|
12
|
+
|
|
13
|
+
export default [
|
|
14
|
+
{
|
|
15
|
+
...js.configs.recommended,
|
|
16
|
+
files: ['src/**', 'test/**'],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
...fixupConfigRules(flatCompat.extends('airbnb-base')),
|
|
20
|
+
files: ['src/**', 'test/**'],
|
|
21
|
+
},
|
|
22
|
+
prettier,
|
|
23
|
+
{
|
|
24
|
+
languageOptions: {
|
|
25
|
+
globals: {
|
|
26
|
+
...globals.jest,
|
|
27
|
+
...globals.node,
|
|
28
|
+
Atomics: 'readonly',
|
|
29
|
+
SharedArrayBuffer: 'readonly',
|
|
30
|
+
},
|
|
31
|
+
parser: tsParser,
|
|
32
|
+
parserOptions: {
|
|
33
|
+
project: './tsconfig.json',
|
|
34
|
+
requireConfigFile: false,
|
|
35
|
+
ecmaVersion: 2022,
|
|
36
|
+
ecmaFeatures: { modules: true },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
files: ['src/**', 'test/**'],
|
|
40
|
+
plugins: { jest, '@typescript-eslint': ts, import: imprt, ts },
|
|
41
|
+
rules: {
|
|
42
|
+
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
|
|
43
|
+
'no-console': 'error',
|
|
44
|
+
'import/first': 'error',
|
|
45
|
+
'linebreak-style': 0, // disable linter linebreak rule, to allow for both unix and windows developement
|
|
46
|
+
'import/no-unresolved': 'off', // Whatever IDE will pass an error if if the module is not found, so no reason for this..
|
|
47
|
+
'import/extensions': 'off', // That includes the production build.. We use linter for code checking / clean code optimization..
|
|
48
|
+
'no-use-before-define': 'off',
|
|
49
|
+
},
|
|
50
|
+
ignores: [
|
|
51
|
+
'api/*',
|
|
52
|
+
'build/*',
|
|
53
|
+
'coverage/*',
|
|
54
|
+
'dist/*',
|
|
55
|
+
'node_modules/*',
|
|
56
|
+
'script/*',
|
|
57
|
+
'src/types.ts',
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
];
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createDefaultEsmPreset, type JestConfigWithTsJest } from 'ts-jest';
|
|
2
|
+
|
|
3
|
+
const jestConfig: JestConfigWithTsJest = {
|
|
4
|
+
testEnvironment: 'node',
|
|
5
|
+
transform: {
|
|
6
|
+
...createDefaultEsmPreset().transform,
|
|
7
|
+
'\\.[jt]sx?$": "ts-jest': [
|
|
8
|
+
'ts-jest',
|
|
9
|
+
{
|
|
10
|
+
useESM: true,
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
collectCoverage: true,
|
|
15
|
+
coverageReporters: ['text', 'cobertura', 'clover', 'lcov', 'json'],
|
|
16
|
+
collectCoverageFrom: ['src/**/*.{ts,js}'],
|
|
17
|
+
coveragePathIgnorePatterns: [
|
|
18
|
+
'node_modules',
|
|
19
|
+
'./dist',
|
|
20
|
+
'./src/app.module.ts',
|
|
21
|
+
'./src/main.ts',
|
|
22
|
+
'./src/bootstrap.ts',
|
|
23
|
+
],
|
|
24
|
+
extensionsToTreatAsEsm: ['.ts'],
|
|
25
|
+
moduleFileExtensions: ['js', 'json', 'ts'],
|
|
26
|
+
modulePathIgnorePatterns: [],
|
|
27
|
+
coverageDirectory: '<rootDir>/coverage/',
|
|
28
|
+
coverageThreshold: {
|
|
29
|
+
global: {
|
|
30
|
+
branches: 20,
|
|
31
|
+
functions: 30,
|
|
32
|
+
lines: 50,
|
|
33
|
+
statements: 50,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
verbose: true,
|
|
37
|
+
testRegex: './test/.*\\.spec.tsx?$',
|
|
38
|
+
modulePaths: ['<rootDir>', '<rootDir>/src/', '<rootDir>/test/'],
|
|
39
|
+
moduleDirectories: ['node_modules', 'src', 'test'],
|
|
40
|
+
rootDir: './',
|
|
41
|
+
roots: ['<rootDir>', 'src/', 'test/'],
|
|
42
|
+
moduleNameMapper: {
|
|
43
|
+
'^(\\.\\.?\\/.+)\\.jsx?$': '$1',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default jestConfig;
|
package/package.json
CHANGED
|
@@ -1,81 +1,88 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@into-cps-association/libms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "microservices that handles request by fetching and returning the file-names and folders of given directory",
|
|
5
5
|
"author": "phillip.boe.jensen@gmail.com",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Prasad Talasila",
|
|
8
8
|
"Mads Kelberg",
|
|
9
|
-
"Linda Nguyen"
|
|
9
|
+
"Linda Nguyen",
|
|
10
|
+
"Nichlaes H. Sørensen"
|
|
10
11
|
],
|
|
11
12
|
"private": false,
|
|
12
13
|
"license": "SEE LICENSE IN <LICENSE.md>",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/src/main.js",
|
|
13
16
|
"scripts": {
|
|
14
|
-
"build": "
|
|
17
|
+
"build": "tsc",
|
|
15
18
|
"clean": "npx rimraf build node_modules coverage dist src.svg test.svg",
|
|
16
19
|
"format": "prettier --ignore-path ../.gitignore --write \"**/*.{ts,tsx,css,scss}\"",
|
|
17
20
|
"graph": "npx madge --image src.svg src && npx madge --image test.svg test",
|
|
18
|
-
"start": "node dist/src/main.js",
|
|
19
|
-
"start:pm2": "pm2 start pm2.config.
|
|
21
|
+
"start": "tsc & node dist/src/main.js",
|
|
22
|
+
"start:pm2": "pm2 start pm2.config.cjs",
|
|
20
23
|
"stop:pm2": "pm2 delete libms",
|
|
21
|
-
"syntax": "
|
|
24
|
+
"syntax": "eslint . --fix",
|
|
22
25
|
"pretest": "npx shx cp test/data/user2/tools/README.md ../../files/user2/tools/README.md",
|
|
23
26
|
"posttest": "npx rimraf ../../files/user2/tools/README.md",
|
|
24
|
-
"test:all": "npx cross-env LOCAL_PATH=test/data jest --testPathIgnorePatterns=cloudcmd --coverage",
|
|
25
|
-
"test:e2e": "npx cross-env LOCAL_PATH=test/data jest --config ./test/jest-e2e.json --coverage",
|
|
27
|
+
"test:all": "npx cross-env NODE_OPTIONS=--experimental-vm-modules LOCAL_PATH=test/data jest --testPathIgnorePatterns=cloudcmd --coverage",
|
|
28
|
+
"test:e2e": "npx cross-env NODE_OPTIONS=--experimental-vm-modules LOCAL_PATH=test/data jest --config ./test/jest-e2e.json --coverage",
|
|
26
29
|
"test:http": "yarn build && pm2 start -f --name libms-test dist/src/main.js -- -c .env -H ./config/http.json && jest test/cloudcmd --coverage --coverageThreshold=\"{}\" && pm2 delete libms-test",
|
|
27
30
|
"test:http-nocov": "yarn build && pm2 start -f --name libms-test dist/src/main.js -- -c .env -H ./config/http.json && jest test/cloudcmd --coverage=false && pm2 delete libms-test",
|
|
28
|
-
"test:http-github": "
|
|
29
|
-
"test:int": "npx cross-env LOCAL_PATH=test/data jest ../test/integration --coverage",
|
|
31
|
+
"test:http-github": "jest test/cloudcmd --coverage --coverageThreshold=\"{}\"",
|
|
32
|
+
"test:int": "npx cross-env NODE_OPTIONS=--experimental-vm-modules LOCAL_PATH=test/data jest ../test/integration --coverage",
|
|
30
33
|
"test:nocov": "yarn test:http-nocov && npx cross-env LOCAL_PATH=test/data jest --testPathIgnorePatterns=cloudcmd --coverage=false",
|
|
31
|
-
"test:unit": "npx cross-env LOCAL_PATH=test/data jest ../test/unit --coverage"
|
|
34
|
+
"test:unit": "npx cross-env NODE_OPTIONS=--experimental-vm-modules LOCAL_PATH=test/data jest ../test/unit --coverage"
|
|
32
35
|
},
|
|
33
36
|
"bin": "./dist/src/main.js",
|
|
34
37
|
"dependencies": {
|
|
35
|
-
"@apollo/client": "^3.8
|
|
36
|
-
"@apollo/server": "^4.
|
|
37
|
-
"@nestjs/apollo": "^12.0
|
|
38
|
-
"@nestjs/common": "^10.
|
|
39
|
-
"@nestjs/config": "^3.2.
|
|
40
|
-
"@nestjs/core": "^10.
|
|
41
|
-
"@nestjs/graphql": "^12.0
|
|
42
|
-
"@nestjs/platform-express": "^10.
|
|
43
|
-
"axios": "^1.
|
|
44
|
-
"cloudcmd": "^
|
|
45
|
-
"commander": "^
|
|
46
|
-
"dotenv": "^16.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
38
|
+
"@apollo/client": "^3.11.8",
|
|
39
|
+
"@apollo/server": "^4.11.0",
|
|
40
|
+
"@nestjs/apollo": "^12.2.0",
|
|
41
|
+
"@nestjs/common": "^10.4.4",
|
|
42
|
+
"@nestjs/config": "^3.2.3",
|
|
43
|
+
"@nestjs/core": "^10.4.4",
|
|
44
|
+
"@nestjs/graphql": "^12.2.0",
|
|
45
|
+
"@nestjs/platform-express": "^10.4.4",
|
|
46
|
+
"axios": "^1.7.7",
|
|
47
|
+
"cloudcmd": "^18.1.0",
|
|
48
|
+
"commander": "^12.1.0",
|
|
49
|
+
"dotenv": "^16.4.5",
|
|
50
|
+
"globals": "^15.11.0",
|
|
51
|
+
"graphql": "^16.9.0",
|
|
52
|
+
"isomorphic-git": "^1.27.1",
|
|
53
|
+
"mock-fs": "^5.3.0",
|
|
54
|
+
"reflect-metadata": "^0.2.2",
|
|
50
55
|
"rxjs": "^7.8.1",
|
|
51
|
-
"socket.io": "^4.
|
|
52
|
-
"type-graphql": "^2.0.0-
|
|
56
|
+
"socket.io": "^4.8.0",
|
|
57
|
+
"type-graphql": "^2.0.0-rc.2"
|
|
53
58
|
},
|
|
54
59
|
"devDependencies": {
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"@nestjs/
|
|
58
|
-
"@
|
|
59
|
-
"@
|
|
60
|
-
"@types/
|
|
60
|
+
"@eslint/compat": "^1.2.2",
|
|
61
|
+
"@eslint/eslintrc": "^3.1.0",
|
|
62
|
+
"@nestjs/cli": "^10.4.5",
|
|
63
|
+
"@nestjs/schematics": "^10.1.4",
|
|
64
|
+
"@nestjs/testing": "^10.4.4",
|
|
65
|
+
"@types/express": "^5.0.0",
|
|
66
|
+
"@types/jest": "^29.5.13",
|
|
67
|
+
"@types/node": "22.7.0",
|
|
61
68
|
"@types/supertest": "^6.0.2",
|
|
62
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
63
|
-
"@typescript-eslint/parser": "^
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^8.12.2",
|
|
70
|
+
"@typescript-eslint/parser": "^8.12.2",
|
|
64
71
|
"cross-fetch": "^4.0.0",
|
|
65
|
-
"eslint": "^
|
|
72
|
+
"eslint": "^9.11.1",
|
|
66
73
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
67
74
|
"eslint-config-prettier": "^9.1.0",
|
|
68
|
-
"eslint-plugin-import": "^2.
|
|
69
|
-
"eslint-plugin-jest": "^28.
|
|
70
|
-
"eslint-plugin-prettier": "^5.1
|
|
71
|
-
"graphql-scalars": "^1.
|
|
72
|
-
"jest": "29.7.0",
|
|
73
|
-
"prettier": "^3.
|
|
74
|
-
"react": "^18.
|
|
75
|
-
"supertest": "^
|
|
76
|
-
"ts-jest": "^29.
|
|
77
|
-
"ts-node": "^10.9.
|
|
75
|
+
"eslint-plugin-import": "^2.31.0",
|
|
76
|
+
"eslint-plugin-jest": "^28.8.3",
|
|
77
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
78
|
+
"graphql-scalars": "^1.23.0",
|
|
79
|
+
"jest": "^29.7.0",
|
|
80
|
+
"prettier": "^3.3.3",
|
|
81
|
+
"react": "^18.3.1",
|
|
82
|
+
"supertest": "^7.0.0",
|
|
83
|
+
"ts-jest": "^29.2.5",
|
|
84
|
+
"ts-node": "^10.9.2",
|
|
78
85
|
"tsconfig-paths": "4.2.0",
|
|
79
|
-
"typescript": "^5.
|
|
86
|
+
"typescript": "^5.6.3"
|
|
80
87
|
}
|
|
81
88
|
}
|
package/src/app.module.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Module } from '@nestjs/common';
|
|
|
3
3
|
import { GraphQLModule } from '@nestjs/graphql';
|
|
4
4
|
import { ApolloDriver } from '@nestjs/apollo';
|
|
5
5
|
import { join } from 'path';
|
|
6
|
-
import FilesModule from './files/files.module';
|
|
6
|
+
import FilesModule from './files/files.module.js';
|
|
7
7
|
|
|
8
8
|
@Module({
|
|
9
9
|
imports: [
|
package/src/bootstrap.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { NestFactory } from '@nestjs/core';
|
|
2
2
|
import { ConfigService } from '@nestjs/config';
|
|
3
3
|
import * as dotenv from 'dotenv';
|
|
4
|
-
import AppModule from './app.module';
|
|
5
|
-
import cloudCMD from './cloudcmd/cloudcmd';
|
|
4
|
+
import AppModule from './app.module.js';
|
|
5
|
+
import cloudCMD from './cloudcmd/cloudcmd.js';
|
|
6
6
|
|
|
7
7
|
type BootstrapOptions = {
|
|
8
8
|
config?: string;
|
|
@@ -15,7 +15,7 @@ export default async function bootstrap(options?: BootstrapOptions) {
|
|
|
15
15
|
path: options?.config ?? '.env',
|
|
16
16
|
override: true,
|
|
17
17
|
});
|
|
18
|
-
if (configFile.error) {
|
|
18
|
+
if (configFile.error && process.env.LOCAL_PATH === undefined) {
|
|
19
19
|
// eslint-disable-next-line no-console
|
|
20
20
|
console.error(configFile.error);
|
|
21
21
|
if (options.runHelp) {
|
|
@@ -28,6 +28,10 @@ export default async function bootstrap(options?: BootstrapOptions) {
|
|
|
28
28
|
const app = await NestFactory.create(AppModule);
|
|
29
29
|
const configService = app.get(ConfigService);
|
|
30
30
|
const port = configService.get<number>('PORT');
|
|
31
|
+
const localPath = configService.get<string>('LOCAL_PATH');
|
|
32
|
+
const mode = configService.get<string>('MODE');
|
|
33
|
+
|
|
34
|
+
console.log(`\x1b[32mStarting libms in \x1b[33m${mode} \x1b[32mmode, serving files from \x1b[34m${localPath} \x1b[32mon port \x1b[35m${port}\x1b[0m`);
|
|
31
35
|
|
|
32
36
|
if (options.httpServer) {
|
|
33
37
|
cloudCMD(app, options.httpServer, configService.get<string>('LOCAL_PATH'));
|
package/src/cloudcmd/cloudcmd.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { INestApplication } from '@nestjs/common';
|
|
2
2
|
import { Server } from 'socket.io';
|
|
3
|
-
import
|
|
4
|
-
import { join } from 'path';
|
|
3
|
+
import cloudcmd from 'cloudcmd';
|
|
4
|
+
import { join, relative } from 'path';
|
|
5
|
+
|
|
6
|
+
const isWindowsAbsolutePath = (filesPath: string) => filesPath.includes(':');
|
|
5
7
|
|
|
6
8
|
const runCloudCMD = (
|
|
7
9
|
app: INestApplication,
|
|
@@ -13,7 +15,13 @@ const runCloudCMD = (
|
|
|
13
15
|
configPath: join(process.cwd(), optionsPath),
|
|
14
16
|
});
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
if (isWindowsAbsolutePath(filesPath)) {
|
|
19
|
+
const workDir = process.cwd();
|
|
20
|
+
const relativePath = relative(workDir, filesPath);
|
|
21
|
+
configManager('root', relativePath);
|
|
22
|
+
} else {
|
|
23
|
+
configManager('root', filesPath);
|
|
24
|
+
}
|
|
17
25
|
|
|
18
26
|
const server = app.getHttpServer();
|
|
19
27
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ConfigService } from '@nestjs/config';
|
|
3
|
+
import { IFilesService } from './interfaces/files.service.interface.js';
|
|
4
|
+
|
|
5
|
+
@Injectable()
|
|
6
|
+
export default class FilesServiceFactory {
|
|
7
|
+
static create(
|
|
8
|
+
configService: ConfigService,
|
|
9
|
+
fileServices: IFilesService[],
|
|
10
|
+
): IFilesService {
|
|
11
|
+
const mode = configService.get<string>('MODE');
|
|
12
|
+
const service = fileServices.find((s) => s.getMode() == mode);
|
|
13
|
+
|
|
14
|
+
if (service == undefined) {
|
|
15
|
+
throw new Error(`Invalid MODE: ${mode}`);
|
|
16
|
+
}
|
|
17
|
+
return service;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
import { Module } from '@nestjs/common';
|
|
2
|
-
import FilesResolver from './
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import FilesResolver from './files.resolver.js';
|
|
3
|
+
import { GitFilesModule } from './git/git-files.module.js';
|
|
4
|
+
import { LocalFilesModule } from './local/local-files.module.js';
|
|
5
|
+
import LocalFilesService from './local/local-files.service.js';
|
|
6
|
+
import GitFilesService from './git/git-files.service.js';
|
|
7
|
+
import { FILE_SERVICE } from './interfaces/files.service.interface.js';
|
|
8
|
+
import FilesServiceFactory from './files-service.factory.js';
|
|
9
|
+
import { ConfigService } from '@nestjs/config';
|
|
5
10
|
|
|
6
11
|
@Module({
|
|
7
|
-
|
|
12
|
+
imports: [LocalFilesModule, GitFilesModule],
|
|
13
|
+
providers: [
|
|
14
|
+
FilesResolver,
|
|
15
|
+
{
|
|
16
|
+
provide: FILE_SERVICE,
|
|
17
|
+
useFactory: (
|
|
18
|
+
configService: ConfigService,
|
|
19
|
+
localFilesService: LocalFilesService,
|
|
20
|
+
gitFilesService: GitFilesService,
|
|
21
|
+
) => {
|
|
22
|
+
const fileServices = [localFilesService, gitFilesService];
|
|
23
|
+
return FilesServiceFactory.create(configService, fileServices);
|
|
24
|
+
},
|
|
25
|
+
inject: [ConfigService, LocalFilesService, GitFilesService],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
8
28
|
})
|
|
9
29
|
export default class FilesModule {}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Resolver, Query, Args } from '@nestjs/graphql';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
FILE_SERVICE,
|
|
4
|
+
IFilesService,
|
|
5
|
+
} from './interfaces/files.service.interface.js';
|
|
6
|
+
import { Project } from '../types.js';
|
|
7
|
+
import { Inject } from '@nestjs/common';
|
|
5
8
|
|
|
6
9
|
@Resolver()
|
|
7
10
|
export default class FilesResolver {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.filesService = filesServiceFactory.create();
|
|
12
|
-
}
|
|
11
|
+
constructor(
|
|
12
|
+
@Inject(FILE_SERVICE) private readonly filesService: IFilesService,
|
|
13
|
+
) {}
|
|
13
14
|
|
|
14
15
|
@Query(() => Project)
|
|
15
16
|
async listDirectory(@Args('path') path: string): Promise<Project> {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import GitFilesService from './git-files.service.js';
|
|
3
|
+
import LocalFilesService from '../local/local-files.service.js';
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
providers: [GitFilesService, LocalFilesService],
|
|
7
|
+
exports: [GitFilesService],
|
|
8
|
+
})
|
|
9
|
+
export class GitFilesModule {}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
2
|
+
import { Project } from 'src/types.js';
|
|
3
|
+
import { IFilesService } from '../interfaces/files.service.interface.js';
|
|
4
|
+
import { CONFIG_MODE } from '../../enums/config-mode.enum.js';
|
|
5
|
+
import { ConfigService } from '@nestjs/config';
|
|
6
|
+
import * as git from 'isomorphic-git';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as http from 'isomorphic-git/http/node/index.cjs';
|
|
9
|
+
import LocalFilesService from '../local/local-files.service.js';
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export default class GitFilesService implements IFilesService {
|
|
13
|
+
private readonly dataPath: string;
|
|
14
|
+
@Inject(LocalFilesService) private localFilesService: LocalFilesService;
|
|
15
|
+
|
|
16
|
+
constructor(private configService: ConfigService) {
|
|
17
|
+
this.dataPath = this.configService.get('LOCAL_PATH');
|
|
18
|
+
this.cloneRepositories();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private cloneRepositories() {
|
|
22
|
+
let userRepoUrl = '';
|
|
23
|
+
let userRepoUrls = [];
|
|
24
|
+
let userCounter = 1;
|
|
25
|
+
while ((userRepoUrl = this.configService.get(
|
|
26
|
+
`GIT_USER${userCounter}_REPO_URL`
|
|
27
|
+
)) !== undefined) {
|
|
28
|
+
userRepoUrls.push(userRepoUrl);
|
|
29
|
+
++userCounter;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
userRepoUrls.forEach((userRepoUrl, i) => {
|
|
33
|
+
git
|
|
34
|
+
.clone({
|
|
35
|
+
fs,
|
|
36
|
+
http,
|
|
37
|
+
dir: this.dataPath + `/user${i + 1}`,
|
|
38
|
+
url: userRepoUrl,
|
|
39
|
+
ref: 'main',
|
|
40
|
+
singleBranch: true,
|
|
41
|
+
})
|
|
42
|
+
.then(() => console.log('done cloning ' + userRepoUrl));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getMode(): CONFIG_MODE {
|
|
47
|
+
return CONFIG_MODE.GIT;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
listDirectory(path: string): Promise<Project> {
|
|
51
|
+
console.log('listDirectory', path);
|
|
52
|
+
return this.localFilesService.listDirectory(path);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
readFile(path: string): Promise<Project> {
|
|
56
|
+
return this.localFilesService.readFile(path);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CONFIG_MODE } from '../../enums/config-mode.enum.js';
|
|
2
|
+
import { Project } from 'src/types.js';
|
|
2
3
|
|
|
4
|
+
export const FILE_SERVICE = 'FILE_SERVICE';
|
|
3
5
|
// FileService interface
|
|
4
6
|
export interface IFilesService {
|
|
5
7
|
listDirectory(path: string): Promise<Project>;
|
|
6
8
|
readFile(path: string): Promise<Project>;
|
|
9
|
+
getMode(): CONFIG_MODE;
|
|
7
10
|
}
|
|
@@ -2,18 +2,24 @@ import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { ConfigService } from '@nestjs/config';
|
|
5
|
-
import { Project } from 'src/types';
|
|
6
|
-
import { IFilesService } from '../interfaces/files.service.interface';
|
|
5
|
+
import { Project } from 'src/types.js';
|
|
6
|
+
import { IFilesService } from '../interfaces/files.service.interface.js';
|
|
7
|
+
import { CONFIG_MODE } from '../../enums/config-mode.enum.js';
|
|
7
8
|
|
|
8
9
|
@Injectable()
|
|
9
10
|
export default class LocalFilesService implements IFilesService {
|
|
10
|
-
|
|
11
|
-
constructor(private configService: ConfigService) {}
|
|
11
|
+
private readonly dataPath: string;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const fullPath = join(dataPath, path);
|
|
13
|
+
constructor(private configService: ConfigService) {
|
|
14
|
+
this.dataPath = this.configService.get('LOCAL_PATH');
|
|
16
15
|
|
|
16
|
+
}
|
|
17
|
+
getMode(): CONFIG_MODE {
|
|
18
|
+
return CONFIG_MODE.LOCAL;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async listDirectory(path: string): Promise<Project> {
|
|
22
|
+
const fullPath = join(this.dataPath, path);
|
|
17
23
|
const files = await fs.promises.readdir(fullPath);
|
|
18
24
|
|
|
19
25
|
const edges = await Promise.all(
|
|
@@ -33,8 +39,7 @@ export default class LocalFilesService implements IFilesService {
|
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
async readFile(path: string): Promise<Project> {
|
|
36
|
-
const
|
|
37
|
-
const fullPath = join(dataPath, path);
|
|
42
|
+
const fullPath = join(this.dataPath, path);
|
|
38
43
|
|
|
39
44
|
try {
|
|
40
45
|
const content = await (
|
|
@@ -45,7 +50,7 @@ export default class LocalFilesService implements IFilesService {
|
|
|
45
50
|
|
|
46
51
|
return LocalFilesService.formatResponse(name, content);
|
|
47
52
|
} catch (error) {
|
|
48
|
-
throw new InternalServerErrorException('Error reading file');
|
|
53
|
+
throw new InternalServerErrorException('Error reading file', error);
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
|
package/src/main.ts
CHANGED
|
@@ -23,13 +23,11 @@ describe('cloudcmd test for the application', () => {
|
|
|
23
23
|
responseType: 'json',
|
|
24
24
|
},
|
|
25
25
|
);
|
|
26
|
-
/* eslint-disable no-console */
|
|
27
|
-
console.log(response.data);
|
|
28
|
-
/* eslint-enable no-console */
|
|
29
26
|
expect(response.data.path).toEqual('/');
|
|
30
|
-
|
|
31
|
-
expect(
|
|
32
|
-
expect(
|
|
27
|
+
const fileNames = response.data.files.map((file) => file.name);
|
|
28
|
+
expect(fileNames).toContain('common');
|
|
29
|
+
expect(fileNames).toContain('user1');
|
|
30
|
+
expect(fileNames).toContain('user2');
|
|
33
31
|
}, 10000);
|
|
34
32
|
|
|
35
33
|
it('should return the content of a file that is uplaoded to cloudcmd ', async () => {
|
package/test/e2e/app.e2e.spec.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
1
2
|
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
3
|
import { INestApplication } from '@nestjs/common';
|
|
3
|
-
import
|
|
4
|
+
import request from 'supertest';
|
|
4
5
|
import fetch from 'cross-fetch';
|
|
5
6
|
import {
|
|
6
7
|
ApolloClient,
|
|
7
8
|
DocumentNode,
|
|
8
|
-
HttpLink,
|
|
9
9
|
InMemoryCache,
|
|
10
10
|
gql,
|
|
11
|
-
} from '@apollo/client';
|
|
11
|
+
} from '@apollo/client/core/core.cjs';
|
|
12
|
+
import { HttpLink } from '@apollo/client/link/http/http.cjs';
|
|
12
13
|
import AppModule from '../../src/app.module';
|
|
13
14
|
import {
|
|
14
15
|
e2eReadFile,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { describe, it, expect, jest } from '@jest/globals';
|
|
1
2
|
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
3
|
import { ConfigService } from '@nestjs/config';
|
|
3
|
-
import FilesResolver from '../../src/files/
|
|
4
|
-
import
|
|
5
|
-
import LocalFilesService from '../../src/files/services/local-files.service';
|
|
4
|
+
import FilesResolver from '../../src/files/files.resolver';
|
|
5
|
+
import LocalFilesService from '../../src/files/local/local-files.service';
|
|
6
6
|
import {
|
|
7
7
|
pathToTestDirectory,
|
|
8
8
|
pathToTestFileContent,
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
testFileContent,
|
|
11
11
|
MockConfigService,
|
|
12
12
|
} from '../testUtil';
|
|
13
|
+
import GitFilesService from '../../src/files/git/git-files.service';
|
|
14
|
+
import { FILE_SERVICE } from '../../src/files/interfaces/files.service.interface';
|
|
15
|
+
import FilesServiceFactory from '../../src/files/files-service.factory';
|
|
13
16
|
|
|
14
17
|
describe('Integration tests for FilesResolver', () => {
|
|
15
18
|
let filesResolver: FilesResolver;
|
|
@@ -20,8 +23,20 @@ describe('Integration tests for FilesResolver', () => {
|
|
|
20
23
|
const module: TestingModule = await Test.createTestingModule({
|
|
21
24
|
providers: [
|
|
22
25
|
FilesResolver,
|
|
23
|
-
|
|
26
|
+
{
|
|
27
|
+
provide: FILE_SERVICE,
|
|
28
|
+
useFactory: (
|
|
29
|
+
configService: ConfigService,
|
|
30
|
+
localFilesService: LocalFilesService,
|
|
31
|
+
gitFilesService: GitFilesService,
|
|
32
|
+
) => {
|
|
33
|
+
const fileServices = [localFilesService, gitFilesService];
|
|
34
|
+
return FilesServiceFactory.create(configService, fileServices);
|
|
35
|
+
},
|
|
36
|
+
inject: [ConfigService, LocalFilesService, GitFilesService],
|
|
37
|
+
},
|
|
24
38
|
LocalFilesService,
|
|
39
|
+
GitFilesService,
|
|
25
40
|
{ provide: ConfigService, useClass: MockConfigService },
|
|
26
41
|
],
|
|
27
42
|
}).compile();
|