From 76402e6f2fe9eafa61600425bce8b9eeaaa5bc51 Mon Sep 17 00:00:00 2001 From: Overlord Date: Tue, 25 Nov 2025 15:45:35 +0100 Subject: [PATCH] init --- .editorconfig | 9 + .gitattributes | 7 + .gitignore | 9 + app/Dockerfile | 0 app/src/assets/dev/index.html | 276 +++++++++++++++++ app/src/assets/dev/ref.html | 260 ++++++++++++++++ app/src/assets/style/error.css | 101 ++++++ app/src/assets/style/style.css | 476 +++++++++++++++++++++++++++++ app/src/assets/style/style.css.zst | Bin 0 -> 2106 bytes app/src/main.v | 126 ++++++++ app/src/template/dashboard.html | 36 +++ app/src/template/error.html | 18 ++ docker-compose.yml | 32 ++ v.mod | 7 + 14 files changed, 1357 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 app/Dockerfile create mode 100644 app/src/assets/dev/index.html create mode 100644 app/src/assets/dev/ref.html create mode 100644 app/src/assets/style/error.css create mode 100644 app/src/assets/style/style.css create mode 100644 app/src/assets/style/style.css.zst create mode 100644 app/src/main.v create mode 100644 app/src/template/dashboard.html create mode 100644 app/src/template/error.html create mode 100644 docker-compose.yml create mode 100644 v.mod diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..517d63e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.v] +indent_style = tab +indent_size = 4 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..885103d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto eol=lf +*.bat eol=crlf + +**/*.v linguist-language=V +**/*.vv linguist-language=V +**/*.vsh linguist-language=V +**/v.mod linguist-language=V \ No newline at end of file diff --git a/.gitignore b/.gitignore index 552a506..7fcb2f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ # ---> V +main +*.dylib +*.exe~ *.exe *.o *.so @@ -11,3 +14,9 @@ *.bak *.out +bin/ + +.DS_Store +.idea/ +.vscode/ +*.iml diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/app/src/assets/dev/index.html b/app/src/assets/dev/index.html new file mode 100644 index 0000000..454e480 --- /dev/null +++ b/app/src/assets/dev/index.html @@ -0,0 +1,276 @@ + + + + + + File Browser + + + +
+
+ +
+ +
+
+
+
+ 0 directories + 0 files + 0 B total +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+
+ + + + diff --git a/app/src/assets/dev/ref.html b/app/src/assets/dev/ref.html new file mode 100644 index 0000000..fe4f7c4 --- /dev/null +++ b/app/src/assets/dev/ref.html @@ -0,0 +1,260 @@ + + + + + + File Browser + + + + + +
+
+ +
+ +
+
+
+
+ 0 directories + 0 files + 0 B total +
+ +
+
+
+ +
+
+
+ +
+
+
+
+ + + diff --git a/app/src/assets/style/error.css b/app/src/assets/style/error.css new file mode 100644 index 0000000..4e03a8c --- /dev/null +++ b/app/src/assets/style/error.css @@ -0,0 +1,101 @@ + +* { margin:0; padding:0; box-sizing:border-box; } + +:root[data-theme="light"] { + --bg-primary: #ffffff; + --bg-secondary: #f5f7fb; + --bg-tertiary: #eff2f5; + --text-primary: #1a202c; + --text-secondary: #6c757d; + --border-color: #d4d7de; + --accent: #0051ba; + --accent-hover: #003e8f; +} + +:root[data-theme="dark"] { + --bg-primary: #0d1117; + --bg-secondary: #161b22; + --bg-tertiary: #21262d; + --text-primary: #e6edf3; + --text-secondary: #8b949e; + --border-color: #30363d; + --accent: #58a6ff; + --accent-hover: #79c0ff; +} + +:root { + --bg-primary:#0d1117; + --bg-secondary:#161b22; + --bg-tertiary:#21262d; + --text-primary:#e6edf3; + --text-secondary:#8b949e; + --border-color:#30363d; + --accent:#58a6ff; + --accent-hover:#79c0ff; + + @media (prefers-color-scheme: light) { + --bg-primary: #ffffff; + --bg-secondary: #f5f7fb; + --bg-tertiary: #eff2f5; + --text-primary: #1a202c; + --text-secondary: #6c757d; + --border-color: #d4d7de; + --accent: #0051ba; + --accent-hover: #003e8f; + } +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + background-color: var(--bg-primary); + color: var(--text-primary); + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + flex-direction: column; + text-align: center; + transition: background-color 0.3s, color 0.3s; +} + +h1 { + font-size: 6rem; + margin-bottom: 1rem; + color: var(--accent); +} + +p { + font-size: 1.25rem; + margin-bottom: 2rem; + color: var(--text-secondary); +} + +a.btn { + display: inline-block; + padding: 0.75rem 1.5rem; + background-color: var(--bg-tertiary); + color: var(--text-primary); + border: 1px solid var(--border-color); + border-radius: 0.375rem; + text-decoration: none; + transition: all 0.2s ease; +} + +a.btn:hover { + background-color: var(--accent); + border-color: var(--accent); + color: #fff; +} + +@media (prefers-color-scheme: light) { + :root:not([data-theme]) { + --bg-primary: #ffffff; + --bg-secondary: #f5f7fb; + --bg-tertiary: #eff2f5; + --text-primary: #1a202c; + --text-secondary: #6c757d; + --border-color: #d4d7de; + --accent: #0051ba; + --accent-hover: #003e8f; + } +} diff --git a/app/src/assets/style/style.css b/app/src/assets/style/style.css new file mode 100644 index 0000000..7449460 --- /dev/null +++ b/app/src/assets/style/style.css @@ -0,0 +1,476 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +/* Light Mode (Cloudflare Dashboard Style) */ +:root[data-theme="light"] { + --bg-primary: #ffffff; + --bg-secondary: #f5f7fb; + --bg-tertiary: #eff2f5; + --text-primary: #1a202c; + --text-secondary: #6c757d; + --border-color: #d4d7de; + --accent: #0051ba; + --accent-hover: #003e8f; + --file-hover: #f0f2f5; +} + +/* Dark Mode (GitHub Style) */ +:root[data-theme="dark"] { + --bg-primary: #0d1117; + --bg-secondary: #161b22; + --bg-tertiary: #21262d; + --text-primary: #e6edf3; + --text-secondary: #8b949e; + --border-color: #30363d; + --accent: #58a6ff; + --accent-hover: #79c0ff; + --file-hover: #1c2128; +} + +/* Default to dark mode */ +:root { + --bg-primary: #0d1117; + --bg-secondary: #161b22; + --bg-tertiary: #21262d; + --text-primary: #e6edf3; + --text-secondary: #8b949e; + --border-color: #30363d; + --accent: #58a6ff; + --accent-hover: #79c0ff; + --file-hover: #1c2128; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + background-color: var(--bg-primary); + color: var(--text-primary); + line-height: 1.6; + transition: background-color 0.3s ease, color 0.3s ease; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +.header { + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); + padding: 1.5rem; + position: sticky; + top: 0; + z-index: 10; + transition: background-color 0.3s ease, border-color 0.3s ease; +} + +.breadcrumbs { + text-transform: uppercase; + font-size: 10px; + letter-spacing: 1px; + color: var(--text-secondary); + margin-bottom: 0.5rem; + padding-left: 3px; +} + +.path-container { + display: flex; + align-items: center; + gap: 0; + flex-wrap: wrap; + word-break: break-all; + margin-bottom: 1rem; + font-size: 1rem; +} + +.breadcrumb-link { + color: var(--accent); + text-decoration: none; + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + transition: all 0.2s ease; + cursor: pointer; +} + +.breadcrumb-link:hover { + background-color: var(--bg-tertiary); + color: var(--accent-hover); +} + +.breadcrumb-text { + color: var(--text-secondary); + padding: 0.25rem 0.5rem; +} + +.breadcrumb-sep { + color: var(--text-secondary); + margin: 0 0.25rem; +} + +.controls { + display: flex; + gap: 0.75rem; + flex-wrap: wrap; +} + +.btn { + padding: 0.5rem 1rem; + background-color: var(--bg-tertiary); + border: 1px solid var(--border-color); + color: var(--text-primary); + border-radius: 0.375rem; + cursor: pointer; + font-size: 0.875rem; + transition: all 0.2s ease; + white-space: nowrap; +} + +.btn:hover { + background-color: var(--accent); + border-color: var(--accent); + color: #ffffff; +} + +.btn:active { + transform: scale(0.98); +} + +.content { + padding: 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; + border-bottom: 1px solid var(--border-color); + background-color: var(--bg-secondary); +} + +.meta { + display: flex; + gap: 2rem; + font-size: 0.875rem; + flex-wrap: wrap; +} + +#summary { + display: flex; + gap: 2rem; + align-items: center; +} + +.meta-item { + white-space: nowrap; +} + +.meta-item b { + color: var(--text-primary); + font-weight: 600; +} + +.layout-toggle { + display: flex; + gap: 0.5rem; + border: 1px solid var(--border-color); + border-radius: 0.375rem; + padding: 0.25rem; + background-color: var(--bg-tertiary); +} + +.layout-btn { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.375rem 0.75rem; + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + border-radius: 0.25rem; + transition: all 0.2s ease; + font-size: 0.875rem; +} + +.layout-btn:hover { + color: var(--text-primary); + background-color: var(--bg-secondary); +} + +.layout-btn.active { + background-color: var(--accent); + color: white; +} + +.listing { + flex: 1; + padding: 1.5rem; + overflow-x: auto; +} + +/* Table Layout */ +.file-table { + width: 100%; + border-collapse: collapse; +} + +.file-table thead { + position: sticky; + top: 0; + background-color: var(--bg-secondary); + z-index: 5; +} + +.file-table th { + text-align: left; + padding: 0.75rem; + border-bottom: 1px solid var(--border-color); + color: var(--text-secondary); + font-size: 0.875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.file-table tbody tr { + border-bottom: 1px solid var(--border-color); + transition: all 0.2s ease; + cursor: pointer; +} + +.file-table tbody tr:hover { + background-color: var(--file-hover); +} + +.file-table td { + padding: 0.75rem; + color: var(--text-primary); +} + +.file-table td.icon { + width: 2.5rem; + font-size: 1.25rem; + text-align: center; +} + +.file-table td.name { + font-weight: 500; +} + +.file-table tr.directory td.name { + color: var(--accent); + font-weight: 600; +} + +.file-table td.size, +.file-table td.date { + color: var(--text-secondary); + font-size: 0.875rem; + white-space: nowrap; +} + +/* Grid Layout */ +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 1rem; +} + +.grid-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + padding: 1rem; + background-color: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: 0.5rem; + cursor: pointer; + transition: all 0.2s ease; + text-align: center; +} + +.grid-item:hover { + background-color: var(--file-hover); + border-color: var(--accent); + transform: translateY(-2px); +} + +.grid-icon { + font-size: 2.5rem; + margin-bottom: 0.75rem; +} + +.grid-name { + font-weight: 500; + color: var(--text-primary); + word-break: break-word; + overflow-wrap: break-word; + font-size: 0.875rem; + margin-bottom: 0.5rem; +} + +.grid-item:has(.grid-name) .grid-name { + color: var(--accent); + font-weight: 600; +} + +.grid-size { + font-size: 0.75rem; + color: var(--text-secondary); + margin-top: auto; +} + +.empty-state { + text-align: center; + padding: 3rem 1rem; + color: var(--text-secondary); +} + +.empty-state-icon { + font-size: 3rem; + margin-bottom: 1rem; + opacity: 0.5; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .header { + padding: 1rem; + } + + .listing { + padding: 1rem; + } + + .content { + padding: 1rem; + flex-direction: column; + align-items: flex-start; + } + + .file-table td.date { + display: none; + } + + .file-table th:last-child { + display: none; + } + + .grid { + grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + gap: 0.75rem; + } + + .grid-item { + padding: 0.75rem; + } + + .path-container { + font-size: 0.9rem; + margin-bottom: 0.75rem; + } + + .meta { + gap: 1rem; + font-size: 0.8rem; + } +} + +@media (max-width: 480px) { + .container { + min-height: auto; + } + + .header { + padding: 0.75rem; + } + + .listing { + padding: 0.75rem; + } + + .content { + padding: 0.75rem; + gap: 0.5rem; + } + + .path-container { + font-size: 0.8rem; + margin-bottom: 0.5rem; + } + + .breadcrumb-link, + .breadcrumb-text, + .breadcrumb-sep { + padding: 0.125rem 0.25rem; + } + + .controls { + width: 100%; + gap: 0.5rem; + } + + .btn { + flex: 1; + padding: 0.5rem; + font-size: 0.75rem; + } + + .meta { + gap: 1rem; + font-size: 0.75rem; + flex-direction: column; + } + + .file-table th, + .file-table td { + padding: 0.5rem 0.25rem; + } + + .file-table td.size { + display: none; + } + + .grid { + grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); + gap: 0.5rem; + } + + .grid-item { + padding: 0.5rem; + } + + .grid-icon { + font-size: 2rem; + margin-bottom: 0.5rem; + } + + .grid-name { + font-size: 0.7rem; + } +} + +/* Scrollbar Styling */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: var(--bg-secondary); +} + +::-webkit-scrollbar-thumb { + background: var(--border-color); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--text-secondary); +} diff --git a/app/src/assets/style/style.css.zst b/app/src/assets/style/style.css.zst new file mode 100644 index 0000000000000000000000000000000000000000..3fe1c4e0e3f5319667d53c453e7e0ec461edf88a GIT binary patch literal 2106 zcmV-A2*vj(wJ-f-z93~m0JcB4B>;2uY-Z%v9t2 zq5psD4=b_&s{p0|5r!f~w|Ims&;vnG^jMzD^E}aY*pAT!@$#X=c7v0AN=d>v#X0w= zRO{%eI2XY0sYBQvFVP?d@UwMR7%!Czv_Qx~{XFJhkswKO`PM&@E>b1Z3jHET0sJ!C zm9$oyqSiJ5CP0E$PJQd|sPVPh7bzg%iO=jUINGieb-RJx_LSmPCxe7N)(L)Uk`hc% z5Q&6D5U?6G>(SQeL*9nfXreO4wh$aYDks|&Gjjxl2?DX5qSZAkgl=VQJ|%uxPwUD^ zc{oR9RsU*6z%1vWhadG(W*TOl%6?j*)A()YOK}`OTII`2+rGtl_&L>_$~lqP_K5VV zcIto~N$a;=+LxO--S*RF;O2UIMHt*rpE8VsoBB1X72FI&V6fN8Ee5!GS{*E4PjpZ@ z7r3eXZ+4qc%j(82o3d)DJ*`p}Yg94U=bu+gj)5KsK9Yk67fWL*kz%1ZiXRvp1ohir zHS6h|B{PYt>jp$3AyB_p)IIYaHP0mZ_u_b-`UG>}IEl}O*FEIJu9TnqODcnL9L3R( zF3zmh@;iC5TKsIi_JVWvy<}_)IZi8WTcOAH%-M}!M~k**Y^Epc{BGqh8=d6rMtxfp zelPiK?tyLHX8qr%f5>|qTDPo=UuCOwqw2CSw%f=({4kGHwhya*)&b?;YE^D4&J*RV zmoe+%SJnTK5QC_?C>ROB-1f2~@=SZSqdBXE7EDlZaU7+BphcO7j9Jnbd*#7o> zR3v1ASs2Sj!Y!j$3Urd!8!oNZ^@>XNl|sqhs@&m;%-_xr6Tamu@W0n}}o0QB}wDcBFj`}#%Asy?0a*dVCKGBeyJm;@B< zZH=bBvLl~9oB_I{bO8w!BJr5k7K483798*@q4@PQ!0cngMFwG0221dek@B*rEIxu# zY0@z%*8toVPVzGRlhxi(2TCxN3J}>AV8-DbMbknW`#jx=I&_XPE+Ydbq_SGn7G&oP zi9Lz0P!xwqz&$iI&T*P)93EHM0UH<39kMvb2fsr#LRm~UfOY5$$%GjaHYL`Du?0Rs znztW4#bN^&7X?&fnjrqASV-KO1XdEkAe2nDg-}lcK4iwgC+i!mJwYA8ZgfzbJos|S zwmjx?()=vwLx(rtOH0VZyh5WkU&|P%`@0kR#JIrwNHoijSZ#1*?h$(WL^LI7O{xPe)*T8X2Sot z4Vn-MWyN+a1`l%Z1&bJLNSg9-0ZFX-s3QOkPz3~Lq2F9IFf&W5qojkXGZjk4(c2Ny zhyx#h*%z2f`M=eUvYD`RKBSwMi-Dx=wSId)H*BaKJ@gImRv434hg(T`9RgAIB;9(; z_`yTGDsi7B2E$+jDtrS7&Xqh0-qvIhF&%s{I>HA>&K1WyTp4ndw|Cov>8$vTC8PF( z4aTBmGTA?Lz%Slzg5p^*O-c=DiD0CZaSo#m2;IsJ+tQmzLaG4HRhj68V-}K1WNBZN zfVTSKB`8whg7Y9Cz=gBOn(Q~wFL8wfWkW!QcMM~mEuhe+27!s6MCyeQ(Hj7qJYIDb zCpaO!H|KaFxCNw{aj3p6u1;Dz2B#V*fGecsEtV-qWx&P;)$U!NBpcaZTRd{kNQ!1z zv_5|71U08gjFzD?;iS+p^O{Va?ic*GtfNwR-fdB`OgFNQbfHCHqvG;WWwbsJgxr3e zz}4n#LR%88+c7mfL7c#e)5lcrkZ`yM2iN?fF2(R@jF4t@0Lk@GVw_fvE~EvD+-b`G z_(;VR=-x2Z+b(h#Ux(45Mk2r>9k97TLdsodN$-TaJRSGAR(LSQ6U znMauLK{hWKl0FD4z3#a;mj#BF$9=Yv!rH|Xls+#hN^xACS8eBT5*qxMu;l3N5&V>4 zz?Hao@pCzgpP)~yqxy-_EU~!rjKF##)slcI6<3V4t1_UvFfXg@s4&aLXT}XJFd1ab k{8IY$C#xuenRefAfd~s7Jp>47O=ldRBQj9X0$Zim!(96IlmGw# literal 0 HcmV?d00001 diff --git a/app/src/main.v b/app/src/main.v new file mode 100644 index 0000000..878cd33 --- /dev/null +++ b/app/src/main.v @@ -0,0 +1,126 @@ +module main + +import veb +import os +import log + +struct Config { +pub mut: + root string + port int +} + +struct Embedded { +pub mut: + style_css string + error_css string +} + +pub struct User { +pub mut: + name string + id int +} + +pub struct Context { + veb.Context +pub mut: + embed Embedded + user User + session_id string +} + +pub struct App { + veb.Controller + veb.StaticHandler + veb.Middleware[Context] +pub mut: + embed Embedded +} + +pub struct Auth {} + +// endpoints + +@['/:path...'] +pub fn (app &App) root(mut ctx Context, path string) veb.Result { + style := app.embed.style_css + return ctx.html($tmpl('template/dashboard.html')) +} + +@['/error'] +pub fn (app &App) error(mut ctx Context) veb.Result { + return ctx.html(ctx.error_page(500, 'Internal Server Error', 'Oops! Seems like something went wrong here.')) +} + +// auth endpoints + +@[get; post] +pub fn (auth &Auth) login(mut ctx Context) veb.Result { + return ctx.text('') +} + +@[get; post] +pub fn (auth &Auth) logout(mut ctx Context) veb.Result { + return ctx.text('') +} + +@[get; post; put] +pub fn (auth &Auth) register(mut ctx Context) veb.Result { + return ctx.text('') +} + +// utility + +fn (mut ctx Context) error_page(code int, short string, long string) string { + style := ctx.embed.error_css + return $tmpl('template/error.html') +} + +pub fn (mut ctx Context) not_found() veb.Result { + ctx.res.set_status(.not_found) + return ctx.html(ctx.error_page(404, 'Not found', 'Oops! The page you are looking for does not exist.')) +} + +// -- + +fn populate() &Config { + mut cfg := &Config{ + root: $d('root', '.') + port: $d('port', 6767) + } + + if os.getenv('CDN_ROOT') != '' { + cfg.root = os.getenv('CDN_ROOT').str() + } + if os.getenv('CDN_PORT') != '' { + cfg.port = os.getenv('CDN_PORT').int() + } + + return cfg +} + +fn main() { + cfg := populate() + + mut app := &App{} + mut auth := &Auth{} + app.embed = &Embedded{ + style_css: $embed_file('assets/style/style.css', .zlib).to_string() + error_css: $embed_file('assets/style/error.css', .zlib).to_string() + } + + app.register_controller[Auth, Context]('/auth', mut auth)! + + app.enable_static_compression = true + app.use(veb.encode_auto[Context]()) + + app.use(veb.MiddlewareOptions[Context]{ + handler: fn [app] (mut ctx Context) bool { + ctx.embed = &app.embed + return true + } + }) + + veb.run[App, Context](mut app, cfg.port) +} diff --git a/app/src/template/dashboard.html b/app/src/template/dashboard.html new file mode 100644 index 0000000..80704af --- /dev/null +++ b/app/src/template/dashboard.html @@ -0,0 +1,36 @@ + + + + + + File Browser + + + + +
+
+ +
+
+
+
+
+ 0 directories + 0 files + 0 B total +
+ +
+
+
+ +
+
+
+
+
+
+
+ + diff --git a/app/src/template/error.html b/app/src/template/error.html new file mode 100644 index 0000000..df0b2fa --- /dev/null +++ b/app/src/template/error.html @@ -0,0 +1,18 @@ + + + + + + @code - @short + + + +

@code

+

@long

+Go Home + + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f9059ef --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +services: + app: + build: + context: ./app + dockerfile: Dockerfile + container_name: cdn_web + depends_on: + - db + ports: + - "8080:8080" + environment: + # env shee + DB_HOST: db + DB_USER: appuser + DB_PASS: s3cret + DB_NAME: appdb + restart: unless-stopped + + db: + image: postgres:16 + container_name: cdn_db + environment: + POSTGRES_USER: appuser + POSTGRES_PASSWORD: s3cret + POSTGRES_DB: appdb + volumes: + - dbdata:/var/lib/postgresql/data + - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql + restart: unless-stopped + +volumes: + dbdata: diff --git a/v.mod b/v.mod new file mode 100644 index 0000000..38fbabf --- /dev/null +++ b/v.mod @@ -0,0 +1,7 @@ +Module { + name: 'CDN' + description: '' + version: '0.0.1' + license: 'MIT' + dependencies: [] +}