From a135f28fd502ff50e8bfd35e41a949977168767e Mon Sep 17 00:00:00 2001 From: LordMathis Date: Wed, 25 Sep 2024 20:36:09 +0200 Subject: [PATCH] Initial backend api --- backend/cmd/server/main.go | 39 +++++++ backend/go.mod | 5 + backend/go.sum | 2 + backend/internal/api/handlers.go | 36 +++++++ backend/internal/filesystem/filesystem.go | 37 +++++++ frontend/package-lock.json | 98 +++++++++++++++++ frontend/package.json | 2 + package-lock.json | 126 ---------------------- package.json | 6 -- 9 files changed, 219 insertions(+), 132 deletions(-) create mode 100644 backend/cmd/server/main.go create mode 100644 backend/go.mod create mode 100644 backend/go.sum create mode 100644 backend/internal/api/handlers.go create mode 100644 backend/internal/filesystem/filesystem.go delete mode 100644 package-lock.json delete mode 100644 package.json diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go new file mode 100644 index 0000000..51fb945 --- /dev/null +++ b/backend/cmd/server/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "log" + "net/http" + "os" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + + "novamd/internal/api" + "novamd/internal/filesystem" +) + +func main() { + r := chi.NewRouter() + + // Middleware + r.Use(middleware.Logger) + r.Use(middleware.Recoverer) + + // Initialize filesystem + folderPath := os.Getenv("FOLDER_PATH") + fs := filesystem.New(folderPath) + + // API routes + r.Route("/api/v1", func(r chi.Router) { + r.Get("/files", api.ListFiles(fs)) + r.Get("/files/*", api.GetFileContent(fs)) + }) + + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + + log.Printf("Server starting on port %s", port) + log.Fatal(http.ListenAndServe(":"+port, r)) +} diff --git a/backend/go.mod b/backend/go.mod new file mode 100644 index 0000000..5932a29 --- /dev/null +++ b/backend/go.mod @@ -0,0 +1,5 @@ +module novamd + +go 1.23.1 + +require github.com/go-chi/chi/v5 v5.1.0 diff --git a/backend/go.sum b/backend/go.sum new file mode 100644 index 0000000..823cdbb --- /dev/null +++ b/backend/go.sum @@ -0,0 +1,2 @@ +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= diff --git a/backend/internal/api/handlers.go b/backend/internal/api/handlers.go new file mode 100644 index 0000000..d24859f --- /dev/null +++ b/backend/internal/api/handlers.go @@ -0,0 +1,36 @@ +package api + +import ( + "encoding/json" + "net/http" + "strings" + + "novamd/internal/filesystem" +) + +func ListFiles(fs *filesystem.FileSystem) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + files, err := fs.ListFilesRecursively() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(files) + } +} + +func GetFileContent(fs *filesystem.FileSystem) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + filePath := strings.TrimPrefix(r.URL.Path, "/api/v1/files/") + content, err := fs.GetFileContent(filePath) + if err != nil { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + + w.Header().Set("Content-Type", "text/plain") + w.Write(content) + } +} diff --git a/backend/internal/filesystem/filesystem.go b/backend/internal/filesystem/filesystem.go new file mode 100644 index 0000000..ce02617 --- /dev/null +++ b/backend/internal/filesystem/filesystem.go @@ -0,0 +1,37 @@ +package filesystem + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +type FileSystem struct { + RootDir string +} + +func New(rootDir string) *FileSystem { + return &FileSystem{RootDir: rootDir} +} + +func (fs *FileSystem) ListFilesRecursively() ([]string, error) { + var files []string + + err := filepath.Walk(fs.RootDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + relPath, _ := filepath.Rel(fs.RootDir, path) + files = append(files, relPath) + } + return nil + }) + + return files, err +} + +func (fs *FileSystem) GetFileContent(filePath string) ([]byte, error) { + fullPath := filepath.Join(fs.RootDir, filePath) + return ioutil.ReadFile(fullPath) +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 52a9c3c..603294b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,6 +24,8 @@ "babel-loader": "^9.2.1", "css-loader": "^7.1.2", "html-webpack-plugin": "^5.6.0", + "sass": "^1.79.3", + "sass-loader": "^16.0.2", "style-loader": "^4.0.0", "webpack": "^5.94.0", "webpack-cli": "^5.1.4", @@ -4674,6 +4676,13 @@ "postcss": "^8.1.0" } }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true, + "license": "MIT" + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -6118,6 +6127,95 @@ "dev": true, "license": "MIT" }, + "node_modules/sass": { + "version": "1.79.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", + "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.2.tgz", + "integrity": "sha512-Ll6iXZ1EYwYT19SqW4mSBb76vSSi8JgzElmzIerhEGgzB5hRjDQIWsPmuk1UrAXkR16KJHqVY0eH+5/uw9Tmfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", + "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 901cd55..0521433 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -56,6 +56,8 @@ "babel-loader": "^9.2.1", "css-loader": "^7.1.2", "html-webpack-plugin": "^5.6.0", + "sass": "^1.79.3", + "sass-loader": "^16.0.2", "style-loader": "^4.0.0", "webpack": "^5.94.0", "webpack-cli": "^5.1.4", diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 770a862..0000000 --- a/package-lock.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "name": "NovaMD", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "devDependencies": { - "sass": "^1.79.3", - "sass-loader": "^16.0.2" - } - }, - "node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass": { - "version": "1.79.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", - "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-loader": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.2.tgz", - "integrity": "sha512-Ll6iXZ1EYwYT19SqW4mSBb76vSSi8JgzElmzIerhEGgzB5hRjDQIWsPmuk1UrAXkR16KJHqVY0eH+5/uw9Tmfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index f65b9d6..0000000 --- a/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "devDependencies": { - "sass": "^1.79.3", - "sass-loader": "^16.0.2" - } -}