@into-cps-association/libms 0.4.4 → 0.4.7

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.
Files changed (91) hide show
  1. package/DEVELOPER.md +62 -0
  2. package/DOCKER.md +295 -0
  3. package/HTTP.md +12 -0
  4. package/README.md +1 -7
  5. package/compose.lib.dev.yml +9 -0
  6. package/compose.lib.yml +8 -0
  7. package/dist/src/app.module.js +14 -16
  8. package/dist/src/app.module.js.map +1 -1
  9. package/dist/src/bootstrap.js +10 -13
  10. package/dist/src/bootstrap.js.map +1 -1
  11. package/dist/src/cloudcmd/cloudcmd.js +15 -9
  12. package/dist/src/cloudcmd/cloudcmd.js.map +1 -1
  13. package/dist/src/enums/config-mode.enum.d.ts +4 -0
  14. package/dist/src/enums/config-mode.enum.js +6 -0
  15. package/dist/src/enums/config-mode.enum.js.map +1 -0
  16. package/dist/src/files/files-service.factory.d.ts +5 -0
  17. package/dist/src/files/files-service.factory.js +22 -0
  18. package/dist/src/files/files-service.factory.js.map +1 -0
  19. package/dist/src/files/files.module.js +23 -9
  20. package/dist/src/files/files.module.js.map +1 -1
  21. package/dist/src/files/{resolvers/files.resolver.d.ts → files.resolver.d.ts} +3 -3
  22. package/dist/src/files/{resolvers/files.resolver.js → files.resolver.js} +14 -14
  23. package/dist/src/files/files.resolver.js.map +1 -0
  24. package/dist/src/files/git/git-files.module.d.ts +2 -0
  25. package/dist/src/files/git/git-files.module.js +18 -0
  26. package/dist/src/files/git/git-files.module.js.map +1 -0
  27. package/dist/src/files/git/git-files.service.d.ts +9 -0
  28. package/dist/src/files/git/git-files.service.js +29 -0
  29. package/dist/src/files/git/git-files.service.js.map +1 -0
  30. package/dist/src/files/interfaces/files.service.interface.d.ts +4 -1
  31. package/dist/src/files/interfaces/files.service.interface.js +1 -2
  32. package/dist/src/files/interfaces/files.service.interface.js.map +1 -1
  33. package/dist/src/files/local/local-files.module.d.ts +2 -0
  34. package/dist/src/files/local/local-files.module.js +18 -0
  35. package/dist/src/files/local/local-files.module.js.map +1 -0
  36. package/dist/src/files/{services → local}/local-files.service.d.ts +5 -2
  37. package/dist/src/files/{services → local}/local-files.service.js +17 -15
  38. package/dist/src/files/local/local-files.service.js.map +1 -0
  39. package/dist/src/main.js +4 -6
  40. package/dist/src/main.js.map +1 -1
  41. package/dist/src/types.js +56 -59
  42. package/dist/src/types.js.map +1 -1
  43. package/dist/test/cloudcmd/cloudcmd.spec.js +14 -16
  44. package/dist/test/cloudcmd/cloudcmd.spec.js.map +1 -1
  45. package/dist/test/e2e/app.e2e.spec.js +18 -18
  46. package/dist/test/e2e/app.e2e.spec.js.map +1 -1
  47. package/dist/test/integration/files.service.integration.spec.js +28 -19
  48. package/dist/test/integration/files.service.integration.spec.js.map +1 -1
  49. package/dist/test/testUtil.js +18 -23
  50. package/dist/test/testUtil.js.map +1 -1
  51. package/dist/test/unit/files-service.factory.unit.spec.js +17 -16
  52. package/dist/test/unit/files-service.factory.unit.spec.js.map +1 -1
  53. package/dist/test/unit/files.resolver.unit.spec.js +26 -24
  54. package/dist/test/unit/files.resolver.unit.spec.js.map +1 -1
  55. package/dist/test/unit/local-files.service.unit.spec.js +23 -24
  56. package/dist/test/unit/local-files.service.unit.spec.js.map +1 -1
  57. package/dist/tsconfig.tsbuildinfo +1 -1
  58. package/eslint.config.js +60 -0
  59. package/jest.config.ts +47 -0
  60. package/package.json +54 -48
  61. package/src/app.module.ts +1 -1
  62. package/src/bootstrap.ts +3 -3
  63. package/src/cloudcmd/cloudcmd.ts +11 -3
  64. package/src/enums/config-mode.enum.ts +4 -0
  65. package/src/files/files-service.factory.ts +19 -0
  66. package/src/files/files.module.ts +24 -4
  67. package/src/files/{resolvers/files.resolver.ts → files.resolver.ts} +9 -8
  68. package/src/files/git/git-files.module.ts +8 -0
  69. package/src/files/git/git-files.service.ts +20 -0
  70. package/src/files/interfaces/files.service.interface.ts +4 -1
  71. package/src/files/local/local-files.module.ts +8 -0
  72. package/src/files/{services → local}/local-files.service.ts +15 -10
  73. package/src/main.ts +1 -1
  74. package/test/cloudcmd/cloudcmd.spec.ts +4 -6
  75. package/test/e2e/app.e2e.spec.ts +4 -3
  76. package/test/integration/files.service.integration.spec.ts +19 -4
  77. package/test/unit/files-service.factory.unit.spec.ts +18 -11
  78. package/test/unit/files.resolver.unit.spec.ts +19 -12
  79. package/test/unit/local-files.service.unit.spec.ts +4 -2
  80. package/tsconfig.json +10 -7
  81. package/.env +0 -6
  82. package/.eslintignore +0 -6
  83. package/.eslintrc +0 -53
  84. package/dist/src/files/resolvers/files.resolver.js.map +0 -1
  85. package/dist/src/files/services/files-service.factory.d.ts +0 -9
  86. package/dist/src/files/services/files-service.factory.js +0 -40
  87. package/dist/src/files/services/files-service.factory.js.map +0 -1
  88. package/dist/src/files/services/local-files.service.js.map +0 -1
  89. package/jest.config.json +0 -30
  90. package/src/files/services/files-service.factory.ts +0 -22
  91. /package/{pm2.config.js → pm2.config.cjs} +0 -0
@@ -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,87 @@
1
1
  {
2
2
  "name": "@into-cps-association/libms",
3
- "version": "0.4.4",
3
+ "version": "0.4.7",
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": "npx tsc",
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.js",
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": "npx eslint . --fix",
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": "yarn build && yarn start:pm2 && jest test/cloudcmd --coverage --coverageThreshold=\"{}\" && pm2 delete libms",
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.9",
36
- "@apollo/server": "^4.10.0",
37
- "@nestjs/apollo": "^12.0.11",
38
- "@nestjs/common": "^10.3.7",
39
- "@nestjs/config": "^3.2.0",
40
- "@nestjs/core": "^10.3.3",
41
- "@nestjs/graphql": "^12.0.11",
42
- "@nestjs/platform-express": "^10.3.7",
43
- "axios": "^1.5.1",
44
- "cloudcmd": "^16.17.7",
45
- "commander": "^11.1.0",
46
- "dotenv": "^16.3.1",
47
- "graphql": "^16.8.1",
48
- "mock-fs": "^5.2.0",
49
- "reflect-metadata": "^0.2.1",
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.9.0",
51
+ "graphql": "^16.9.0",
52
+ "mock-fs": "^5.3.0",
53
+ "reflect-metadata": "^0.2.2",
50
54
  "rxjs": "^7.8.1",
51
- "socket.io": "^4.7.2",
52
- "type-graphql": "^2.0.0-beta.3"
55
+ "socket.io": "^4.8.0",
56
+ "type-graphql": "^2.0.0-rc.2"
53
57
  },
54
58
  "devDependencies": {
55
- "@nestjs/cli": "^10.3.2",
56
- "@nestjs/schematics": "^10.1.1",
57
- "@nestjs/testing": "^10.3.3",
58
- "@types/express": "^4.17.21",
59
- "@types/jest": "^29.5.12",
60
- "@types/node": "20.12.5",
59
+ "@eslint/compat": "^1.1.1",
60
+ "@eslint/eslintrc": "^3.1.0",
61
+ "@nestjs/cli": "^10.4.5",
62
+ "@nestjs/schematics": "^10.1.4",
63
+ "@nestjs/testing": "^10.4.4",
64
+ "@types/express": "^5.0.0",
65
+ "@types/jest": "^29.5.13",
66
+ "@types/node": "22.7.0",
61
67
  "@types/supertest": "^6.0.2",
62
- "@typescript-eslint/eslint-plugin": "^6.19.0",
63
- "@typescript-eslint/parser": "^6.19.0",
68
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
69
+ "@typescript-eslint/parser": "^8.8.0",
64
70
  "cross-fetch": "^4.0.0",
65
- "eslint": "^8.56.0",
71
+ "eslint": "^9.11.1",
66
72
  "eslint-config-airbnb-base": "^15.0.0",
67
73
  "eslint-config-prettier": "^9.1.0",
68
- "eslint-plugin-import": "^2.29.1",
69
- "eslint-plugin-jest": "^28.2.0",
70
- "eslint-plugin-prettier": "^5.1.3",
71
- "graphql-scalars": "^1.22.2",
72
- "jest": "29.7.0",
73
- "prettier": "^3.2.2",
74
- "react": "^18.2.0",
75
- "supertest": "^6.3.4",
76
- "ts-jest": "^29.1.1",
77
- "ts-node": "^10.9.1",
74
+ "eslint-plugin-import": "^2.31.0",
75
+ "eslint-plugin-jest": "^28.8.3",
76
+ "eslint-plugin-prettier": "^5.2.1",
77
+ "graphql-scalars": "^1.23.0",
78
+ "jest": "^29.7.0",
79
+ "prettier": "^3.3.3",
80
+ "react": "^18.3.1",
81
+ "supertest": "^7.0.0",
82
+ "ts-jest": "^29.2.5",
83
+ "ts-node": "^10.9.2",
78
84
  "tsconfig-paths": "4.2.0",
79
- "typescript": "^5.2.2"
85
+ "typescript": "^5.6.2"
80
86
  }
81
87
  }
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) {
@@ -1,7 +1,9 @@
1
1
  import { INestApplication } from '@nestjs/common';
2
2
  import { Server } from 'socket.io';
3
- import * as cloudcmd from 'cloudcmd';
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
- configManager('root', filesPath);
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,4 @@
1
+ export enum CONFIG_MODE {
2
+ GIT = 'git',
3
+ LOCAL = 'local',
4
+ }
@@ -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 './resolvers/files.resolver';
3
- import FilesServiceFactory from './services/files-service.factory';
4
- import LocalFilesService from './services/local-files.service';
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
- providers: [FilesResolver, LocalFilesService, FilesServiceFactory],
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 { IFilesService } from '../interfaces/files.service.interface';
3
- import FilesServiceFactory from '../services/files-service.factory';
4
- import { Project } from '../../types';
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
- private readonly filesService: IFilesService;
9
-
10
- constructor(filesServiceFactory: FilesServiceFactory) {
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,8 @@
1
+ import { Module } from '@nestjs/common';
2
+ import GitFilesService from './git-files.service.js';
3
+
4
+ @Module({
5
+ providers: [GitFilesService],
6
+ exports: [GitFilesService],
7
+ })
8
+ export class GitFilesModule {}
@@ -0,0 +1,20 @@
1
+ import { 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
+
6
+ @Injectable()
7
+ export default class GitFilesService implements IFilesService {
8
+ // eslint-disable-next-line no-useless-constructor, no-empty-function
9
+ constructor() {}
10
+ getMode(): CONFIG_MODE {
11
+ return CONFIG_MODE.GIT;
12
+ }
13
+
14
+ listDirectory(): Promise<Project> {
15
+ throw new Error('Method not implemented.');
16
+ }
17
+ readFile(): Promise<Project> {
18
+ throw new Error('Method not implemented.');
19
+ }
20
+ }
@@ -1,7 +1,10 @@
1
- import { Project } from 'src/types';
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
  }
@@ -0,0 +1,8 @@
1
+ import { Module } from '@nestjs/common';
2
+ import LocalFilesService from './local-files.service.js';
3
+
4
+ @Module({
5
+ providers: [LocalFilesService],
6
+ exports: [LocalFilesService],
7
+ })
8
+ export class LocalFilesModule {}
@@ -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
- // eslint-disable-next-line no-useless-constructor, no-empty-function
11
- constructor(private configService: ConfigService) {}
11
+ private readonly dataPath: string;
12
12
 
13
- async listDirectory(path: string): Promise<Project> {
14
- const dataPath = this.configService.get('LOCAL_PATH');
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 dataPath = this.configService.get('LOCAL_PATH');
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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import bootstrap from './bootstrap';
3
+ import bootstrap from './bootstrap.js';
4
4
 
5
5
  type ProgramOptions = {
6
6
  config?: string;
@@ -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
- expect(response.data.files[0].name).toEqual('common');
31
- expect(response.data.files[1].name).toEqual('user1');
32
- expect(response.data.files[2].name).toEqual('user2');
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 () => {
@@ -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 * as request from 'supertest';
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/resolvers/files.resolver';
4
- import FilesServiceFactory from '../../src/files/services/files-service.factory';
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
- FilesServiceFactory,
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();
@@ -1,37 +1,44 @@
1
1
  // files-service.factory.spec.ts
2
+ import { describe, it, expect, jest } from '@jest/globals';
2
3
  import { Test, TestingModule } from '@nestjs/testing';
3
4
  import { ConfigService } from '@nestjs/config';
4
- import FilesServiceFactory from '../../src/files/services/files-service.factory';
5
- import LocalFilesService from '../../src/files/services/local-files.service';
5
+ import FilesServiceFactory from '../../src/files/files-service.factory';
6
+ import LocalFilesService from '../../src/files/local/local-files.service';
6
7
  import { IFilesService } from '../../src/files/interfaces/files.service.interface';
8
+ import GitFilesService from '../../src/files/git/git-files.service';
7
9
 
8
10
  describe('FilesServiceFactory', () => {
9
- let serviceFactory: FilesServiceFactory;
10
11
  let configService: ConfigService;
11
12
  let localFilesService: IFilesService;
13
+ let gitFilesService: IFilesService;
14
+ let fileServices: IFilesService[];
12
15
 
13
16
  beforeEach(async () => {
14
- localFilesService = new LocalFilesService(configService as ConfigService);
15
-
17
+
16
18
  const module: TestingModule = await Test.createTestingModule({
17
19
  providers: [
18
- FilesServiceFactory,
20
+ GitFilesService,
19
21
  { provide: ConfigService, useValue: { get: jest.fn() } },
20
- { provide: LocalFilesService, useValue: localFilesService },
21
22
  ],
22
23
  }).compile();
23
-
24
- serviceFactory = module.get<FilesServiceFactory>(FilesServiceFactory);
24
+
25
25
  configService = module.get<ConfigService>(ConfigService);
26
+ localFilesService = new LocalFilesService(configService);
27
+ gitFilesService = module.get<GitFilesService>(GitFilesService);
28
+ fileServices = [gitFilesService, localFilesService];
26
29
  });
27
30
 
28
31
  it('should create a local files service when MODE is local', () => {
29
32
  jest.spyOn(configService, 'get').mockReturnValue('local');
30
- expect(serviceFactory.create()).toBe(localFilesService);
33
+ expect(FilesServiceFactory.create(configService, fileServices)).toBe(
34
+ localFilesService,
35
+ );
31
36
  });
32
37
 
33
38
  it('should throw an error when MODE is invalid', () => {
34
39
  jest.spyOn(configService, 'get').mockReturnValue('invalid');
35
- expect(() => serviceFactory.create()).toThrowError(`Invalid MODE: invalid`);
40
+ expect(() =>
41
+ FilesServiceFactory.create(configService, fileServices),
42
+ ).toThrow(`Invalid MODE: invalid`);
36
43
  });
37
44
  });