From 25e7da24e6d3a15f7c0a8f7a362a96b4aa7c6904 Mon Sep 17 00:00:00 2001 From: creations Date: Sun, 18 May 2025 19:12:34 -0400 Subject: [PATCH] first commit --- LICENSE | 28 ++++++++++++++++++++++ README.md | 3 +++ biome.json | 44 ++++++++++++++++++++++++++++++++++ config/index.ts | 36 ++++++++++++++++++++++++++++ package.json | 28 ++++++++++++++++++++++ src/index.html | 19 +++++++++++++++ src/index.ts | 28 ++++++++++++++++++++++ src/lib/char.ts | 5 ++++ src/public/assets/favicon.ico | Bin 0 -> 15086 bytes src/public/assets/logo.svg | 1 + src/views/App.tsx | 14 +++++++++++ src/views/css/App.module.css | 33 +++++++++++++++++++++++++ src/views/css/index.css | 13 ++++++++++ src/views/index.tsx | 13 ++++++++++ tsconfig.json | 25 +++++++++++++++++++ types/config.d.ts | 6 +++++ types/css.d.ts | 4 ++++ 17 files changed, 300 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 biome.json create mode 100644 config/index.ts create mode 100644 package.json create mode 100644 src/index.html create mode 100644 src/index.ts create mode 100644 src/lib/char.ts create mode 100644 src/public/assets/favicon.ico create mode 100644 src/public/assets/logo.svg create mode 100644 src/views/App.tsx create mode 100644 src/views/css/App.module.css create mode 100644 src/views/css/index.css create mode 100644 src/views/index.tsx create mode 100644 tsconfig.json create mode 100644 types/config.d.ts create mode 100644 types/css.d.ts diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d93a942 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2025, creations.works + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..144fff6 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +## License + +[BSD 3](LICENSE) diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..46ee8c9 --- /dev/null +++ b/biome.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": true, + "ignore": [] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab", + "lineEnding": "lf" + }, + "organizeImports": { + "enabled": true + }, + "css": { + "formatter": { + "indentStyle": "tab", + "lineEnding": "lf" + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "correctness": { + "noUnusedImports": "error" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "indentStyle": "tab", + "lineEnding": "lf", + "jsxQuoteStyle": "double", + "semicolons": "always" + } + } +} diff --git a/config/index.ts b/config/index.ts new file mode 100644 index 0000000..8eb0582 --- /dev/null +++ b/config/index.ts @@ -0,0 +1,36 @@ +import { logger } from "@creations.works/logger"; +import { normalizeFqdn } from "@lib/char"; + +const environment: Environment = { + port: Number.parseInt(process.env.PORT || "8080", 10), + host: process.env.HOST || "0.0.0.0", + development: + process.env.NODE_ENV === "development" || process.argv.includes("--dev"), + fqdn: normalizeFqdn(process.env.FQDN) || "http://localhost:8080", +}; + +function verifyRequiredVariables(): void { + const requiredVariables = [ + "HOST", + "PORT", + + "FQDN", + "BACKEND_URL", + ]; + + let hasError = false; + + for (const key of requiredVariables) { + const value = process.env[key]; + if (value === undefined || value.trim() === "") { + logger.error(`Missing or empty environment variable: ${key}`); + hasError = true; + } + } + + if (hasError) { + process.exit(1); + } +} + +export { environment, verifyRequiredVariables }; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ed17f65 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "atums.world.frontend", + "version": "0.0.0", + "description": "", + "private": true, + "type": "module", + "scripts": { + "start": "bun src/index.ts", + "dev": "bun src/index.ts --dev", + "build": "vite build", + "serve": "vite preview", + "lint": "bunx biome check", + "lint:fix": "bunx biome check --fix", + "cleanup": "rm -rf logs node_modules bun.lock" + }, + "license": "BSD-3-Clause", + "devDependencies": { + "@biomejs/biome": "^1.9.4", + "@types/bun": "^1.2.13", + "vite": "^6.3.5", + "vite-plugin-solid": "^2.11.6", + "vite-tsconfig-paths": "^5.1.4" + }, + "dependencies": { + "@creations.works/logger": "^1.0.3", + "solid-js": "^1.9.5" + } +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..d62bd90 --- /dev/null +++ b/src/index.html @@ -0,0 +1,19 @@ + + + + + + + + + Solid App + + + + +
+ + + + + \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..d1695a2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,28 @@ +import { resolve } from "node:path"; +import { environment, verifyRequiredVariables } from "@config"; +import { logger } from "@creations.works/logger"; +import { createServer } from "vite"; +import solidPlugin from "vite-plugin-solid"; +import tsconfigPaths from "vite-tsconfig-paths"; + +verifyRequiredVariables(); + +const server = await createServer({ + root: resolve("src"), + publicDir: resolve("src/public"), + plugins: [solidPlugin(), tsconfigPaths()], + server: { + port: environment.port, + host: environment.host, + strictPort: true, + }, + build: { + target: "esnext", + }, +}); + +await server.listen(); + +logger.info( + `Server is running at http://${environment.host}:${environment.port}`, +); diff --git a/src/lib/char.ts b/src/lib/char.ts new file mode 100644 index 0000000..3d90743 --- /dev/null +++ b/src/lib/char.ts @@ -0,0 +1,5 @@ +export function normalizeFqdn(value?: string): string | null { + if (!value) return null; + if (!/^https?:\/\//.test(value)) return `https://${value}`; + return value; +} diff --git a/src/public/assets/favicon.ico b/src/public/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b836b2bccac650e0e7d90514083add91d2c027ff GIT binary patch literal 15086 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 WLaxim%Fn{v*G \ No newline at end of file diff --git a/src/views/App.tsx b/src/views/App.tsx new file mode 100644 index 0000000..8743f23 --- /dev/null +++ b/src/views/App.tsx @@ -0,0 +1,14 @@ +import type { Component } from "solid-js"; + +import styles from "@views/css/App.module.css"; + +const App: Component = () => { + return ( +
+
+
+
+ ); +}; + +export default App; diff --git a/src/views/css/App.module.css b/src/views/css/App.module.css new file mode 100644 index 0000000..d5c3782 --- /dev/null +++ b/src/views/css/App.module.css @@ -0,0 +1,33 @@ +.App { + text-align: center; +} + +.logo { + animation: logo-spin infinite 20s linear; + height: 40vmin; + pointer-events: none; +} + +.header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; +} + +.link { + color: #b318f0; +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/views/css/index.css b/src/views/css/index.css new file mode 100644 index 0000000..e068437 --- /dev/null +++ b/src/views/css/index.css @@ -0,0 +1,13 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; +} diff --git a/src/views/index.tsx b/src/views/index.tsx new file mode 100644 index 0000000..71637cf --- /dev/null +++ b/src/views/index.tsx @@ -0,0 +1,13 @@ +import { render } from "solid-js/web"; + +import "@views/css/index.css"; +import App from "@views/App"; + +const root = document.getElementById("root"); + +if (!(root instanceof HTMLElement)) { + throw new Error("Root element not found"); +} + +render(() => , root); + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7a08f4e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": ["src/*"], + "@views/*": ["src/views/*"], + "@config": ["config/index.ts"], + "@config/*": ["config/*"], + "@types/*": ["types/*"], + "@lib/*": ["src/lib/*"] + }, + "typeRoots": ["./src/types", "./node_modules/@types"], + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "noEmit": true, + "isolatedModules": true + }, + "include": ["src", "types", "config"] +} diff --git a/types/config.d.ts b/types/config.d.ts new file mode 100644 index 0000000..1b60b8e --- /dev/null +++ b/types/config.d.ts @@ -0,0 +1,6 @@ +type Environment = { + port: number; + host: string; + development: boolean; + fqdn: string; +}; diff --git a/types/css.d.ts b/types/css.d.ts new file mode 100644 index 0000000..3f39e9d --- /dev/null +++ b/types/css.d.ts @@ -0,0 +1,4 @@ +declare module "*.module.css" { + const classes: { [key: string]: string }; + export default classes; +}