Initial commit

This commit is contained in:
tofu
2026-03-03 21:42:51 +05:00
commit b1c3b657c2
43 changed files with 833 additions and 0 deletions

2
.env Normal file
View File

@@ -0,0 +1,2 @@
# This is checked into source control, so put sensitive values into `.env.local`
DATABASE_URL=sqlite: db/clash_deck_generator2.sqlite

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.env*.local
log/*
public/*
!public/404.html
!public/500.html
node_modules/
db/*.sqlite

33
Gemfile Normal file
View File

@@ -0,0 +1,33 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "hanami", "~> 2.3.0"
gem "hanami-assets", "~> 2.3.0"
gem "hanami-controller", "~> 2.3.0"
gem "hanami-db", "~> 2.3.0"
gem "hanami-router", "~> 2.3.0"
gem "hanami-validations", "~> 2.3.0"
gem "hanami-view", "~> 2.3.0"
gem "dry-types", "~> 1.7"
gem "dry-operation", ">= 1.0.1"
gem "puma"
gem "rake"
gem "sqlite3"
group :development do
gem "hanami-webconsole", "~> 2.3.0"
end
group :development, :test do
gem "dotenv"
end
group :cli, :development do
gem "hanami-reloader", "~> 2.3.0"
end
group :cli, :development, :test do
gem "hanami-rspec", "~> 2.3.0"
end

304
Gemfile.lock Normal file
View File

@@ -0,0 +1,304 @@
GEM
remote: https://rubygems.org/
specs:
base64 (0.3.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.3.1)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
coderay (1.1.3)
concurrent-ruby (1.3.6)
csv (3.3.5)
date (3.5.1)
debug_inspector (1.2.0)
diff-lcs (1.6.2)
dotenv (3.2.0)
dry-auto_inject (1.1.0)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-cli (1.4.1)
dry-configurable (1.3.0)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-core (1.2.0)
concurrent-ruby (~> 1.0)
logger
zeitwerk (~> 2.6)
dry-events (1.1.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.1)
dry-files (1.1.0)
dry-inflector (1.3.1)
dry-initializer (3.2.0)
dry-logger (1.2.1)
logger
dry-logic (1.6.0)
bigdecimal
concurrent-ruby (~> 1.0)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-monads (1.9.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.1)
zeitwerk (~> 2.6)
dry-monitor (1.0.1)
dry-configurable (~> 1.0, < 2)
dry-core (~> 1.0, < 2)
dry-events (~> 1.0, < 2)
dry-operation (1.1.0)
dry-monads (~> 1.6)
zeitwerk (~> 2.6)
dry-schema (1.16.0)
concurrent-ruby (~> 1.0)
dry-configurable (~> 1.0, >= 1.0.1)
dry-core (~> 1.1)
dry-initializer (~> 3.2)
dry-logic (~> 1.6)
dry-types (~> 1.9, >= 1.9.1)
zeitwerk (~> 2.6)
dry-struct (1.8.1)
dry-core (~> 1.1)
dry-types (~> 1.8, >= 1.8.2)
ice_nine (~> 0.11)
zeitwerk (~> 2.6)
dry-system (1.2.5)
dry-auto_inject (~> 1.1)
dry-configurable (~> 1.3)
dry-core (~> 1.1)
dry-inflector (~> 1.1)
dry-transformer (1.1.0)
bigdecimal
zeitwerk (~> 2.6)
dry-types (1.9.1)
bigdecimal (>= 3.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
dry-logic (~> 1.4)
zeitwerk (~> 2.6)
dry-validation (1.11.1)
concurrent-ruby (~> 1.0)
dry-core (~> 1.1)
dry-initializer (~> 3.2)
dry-schema (~> 1.14)
zeitwerk (~> 2.6)
erb (6.0.2)
erubi (1.13.1)
ffi (1.17.3-x64-mingw-ucrt)
formatador (1.2.3)
reline
guard (2.20.1)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
logger (~> 1.6)
lumberjack (>= 1.0.12, < 2.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.13.0)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-puma (0.9.2)
guard (~> 2.14)
guard-compat (~> 1.2)
puma (>= 4.0, < 8)
hanami (2.3.2)
bundler (>= 2.0)
dry-configurable (~> 1.0, >= 1.2.0, < 2)
dry-core (~> 1.0, < 2)
dry-inflector (~> 1.0, >= 1.1.0, < 2)
dry-logger (~> 1.2, < 2)
dry-monitor (~> 1.0, >= 1.0.1, < 2)
dry-system (~> 1.1)
hanami-cli (>= 2.3.1)
hanami-utils (>= 2.3.0)
json (>= 2.7.2)
rack-session
zeitwerk (~> 2.6)
hanami-assets (2.3.0)
zeitwerk (~> 2.6)
hanami-cli (2.3.5)
bundler (>= 2.1)
dry-cli (~> 1.0, >= 1.1.0)
dry-files (~> 1.0, >= 1.0.2)
dry-inflector (~> 1.0)
irb
rackup
rake (~> 13.0)
zeitwerk (~> 2.6)
hanami-controller (2.3.1)
dry-configurable (~> 1.0, < 2)
dry-core (~> 1.0)
hanami-utils (~> 2.3.0)
rack (>= 2.1)
zeitwerk (~> 2.6)
hanami-db (2.3.0)
rom (~> 5.4, >= 5.4.1)
rom-sql (~> 3.7)
zeitwerk (~> 2.6)
hanami-reloader (2.3.0)
guard (~> 2.19)
guard-puma (~> 0.8)
hanami-cli (~> 2.3.0)
zeitwerk (~> 2.6)
hanami-router (2.3.1)
csv (~> 3.3)
mustermann (~> 3.0)
mustermann-contrib (~> 3.0)
rack (>= 2.2.16)
hanami-rspec (2.3.1)
hanami-cli (~> 2.3.0)
rake (~> 13.0)
rspec (~> 3.12)
zeitwerk (~> 2.6)
hanami-utils (2.3.0)
bigdecimal (~> 3.1)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0, < 2)
dry-transformer (~> 1.0, < 2)
hanami-validations (2.3.0)
dry-validation (>= 1.10, < 2)
hanami-view (2.3.1)
dry-configurable (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0, < 2)
temple (~> 0.10.0, >= 0.10.2)
tilt (~> 2.3)
zeitwerk (~> 2.6)
hanami-webconsole (2.3.1)
better_errors (~> 2.10, >= 2.10.1)
binding_of_caller (~> 1.0)
hansi (0.2.1)
ice_nine (0.11.2)
io-console (0.8.2)
irb (1.17.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
json (2.18.1)
listen (3.10.0)
logger
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0)
lumberjack (1.4.2)
method_source (1.1.0)
mustermann (3.0.4)
ruby2_keywords (~> 0.0.1)
mustermann-contrib (3.0.4)
hansi (~> 0.2.0)
mustermann (= 3.0.4)
nenv (0.3.0)
nio4r (2.7.5)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
pp (0.6.3)
prettyprint
prettyprint (0.2.0)
prism (1.9.0)
pry (0.16.0)
coderay (~> 1.1)
method_source (~> 1.0)
reline (>= 0.6.0)
psych (5.3.1)
date
stringio
puma (7.2.0)
nio4r (~> 2.0)
rack (3.2.5)
rack-session (2.1.1)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rackup (2.3.1)
rack (>= 3)
rake (13.3.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rdoc (7.2.0)
erb
psych (>= 4.0.0)
tsort
reline (0.6.3)
io-console (~> 0.5)
rom (5.4.3)
rom-changeset (~> 5.4)
rom-core (~> 5.4)
rom-repository (~> 5.4, >= 5.4.3)
rom-changeset (5.4.0)
dry-core (~> 1.0)
rom-core (~> 5.4)
transproc (~> 1.1)
rom-core (5.4.0)
concurrent-ruby (~> 1.1)
dry-configurable (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
dry-initializer (~> 3.2)
dry-struct (~> 1.0)
dry-types (~> 1.6)
transproc (~> 1.1)
rom-repository (5.4.3)
dry-core (~> 1.0)
dry-initializer (~> 3.2)
rom-core (~> 5.4)
rom-sql (3.7.0)
dry-core (~> 1.1)
dry-types (~> 1.8)
rom (~> 5.4)
sequel (>= 4.49)
rouge (4.7.0)
rspec (3.13.2)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.7)
ruby2_keywords (0.0.5)
sequel (5.102.0)
bigdecimal
shellany (0.0.1)
sqlite3 (2.9.1-x64-mingw-ucrt)
stringio (3.2.0)
temple (0.10.4)
thor (1.5.0)
tilt (2.7.0)
transproc (1.1.1)
tsort (0.2.0)
zeitwerk (2.7.5)
PLATFORMS
x64-mingw-ucrt
DEPENDENCIES
dotenv
dry-operation (>= 1.0.1)
dry-types (~> 1.7)
hanami (~> 2.3.0)
hanami-assets (~> 2.3.0)
hanami-controller (~> 2.3.0)
hanami-db (~> 2.3.0)
hanami-reloader (~> 2.3.0)
hanami-router (~> 2.3.0)
hanami-rspec (~> 2.3.0)
hanami-validations (~> 2.3.0)
hanami-view (~> 2.3.0)
hanami-webconsole (~> 2.3.0)
puma
rake
sqlite3
BUNDLED WITH
2.5.22

2
Procfile.dev Normal file
View File

@@ -0,0 +1,2 @@
web: bundle exec hanami server
assets: bundle exec hanami assets watch

15
README.md Normal file
View File

@@ -0,0 +1,15 @@
# ClashDeckGenerator2
🌸 Welcome to your Hanami app!
## Getting started
- Set up the project with `bin/setup`
- Run the server with `bin/dev`
- View the app at [http://localhost:2300](http://localhost:2300)
- Run the tests with `bundle exec rake`
## Useful links
- [Hanami](http://hanamirb.org)
- [Hanami guides](https://guides.hanamirb.org/)

6
Rakefile Normal file
View File

@@ -0,0 +1,6 @@
# frozen_string_literal: true
require "hanami/rake_tasks"
# Add your custom rake tasks to the lib/tasks directory
Rake.add_rakelib "lib/tasks"

12
app/action.rb Normal file
View File

@@ -0,0 +1,12 @@
# auto_register: false
# frozen_string_literal: true
require "hanami/action"
require "dry/monads"
module ClashDeckGenerator2
class Action < Hanami::Action
# Provide `Success` and `Failure` for pattern matching on operation results
include Dry::Monads[:result]
end
end

0
app/actions/.keep Normal file
View File

5
app/assets/css/app.css Normal file
View File

@@ -0,0 +1,5 @@
body {
background-color: #fff;
color: #000;
font-family: sans-serif;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

1
app/assets/js/app.js Normal file
View File

@@ -0,0 +1 @@
import "../css/app.css";

10
app/db/relation.rb Normal file
View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
require "hanami/db/relation"
module ClashDeckGenerator2
module DB
class Relation < Hanami::DB::Relation
end
end
end

10
app/db/repo.rb Normal file
View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
require "hanami/db/repo"
module ClashDeckGenerator2
module DB
class Repo < Hanami::DB::Repo
end
end
end

10
app/db/struct.rb Normal file
View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
require "hanami/db/struct"
module ClashDeckGenerator2
module DB
class Struct < Hanami::DB::Struct
end
end
end

9
app/operation.rb Normal file
View File

@@ -0,0 +1,9 @@
# auto_register: false
# frozen_string_literal: true
require "dry/operation"
module ClashDeckGenerator2
class Operation < Dry::Operation
end
end

0
app/relations/.keep Normal file
View File

11
app/relations/cards.rb Normal file
View File

@@ -0,0 +1,11 @@
module ClashDeckGenerator
module Relations
class Cards < DB::Relation
schema :cards, infer: true
def meta
where(is_meta: 1)
end
end
end
end

0
app/repos/.keep Normal file
View File

9
app/repos/cards_repo.rb Normal file
View File

@@ -0,0 +1,9 @@
module ClashDeckGenerator
module Repos
class CardsRepo < DB::Repo[:cards]
def meta_cards
cards.meta.to_a
end
end
end
end

0
app/structs/.keep Normal file
View File

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clash deck generator2</title>
<%= favicon_tag %>
<%= stylesheet_tag "app" %>
</head>
<body>
<%= yield %>
<%= javascript_tag "app" %>
</body>
</html>

9
app/view.rb Normal file
View File

@@ -0,0 +1,9 @@
# auto_register: false
# frozen_string_literal: true
require "hanami/view"
module ClashDeckGenerator2
class View < Hanami::View
end
end

10
app/views/context.rb Normal file
View File

@@ -0,0 +1,10 @@
# auto_register: false
# frozen_string_literal: true
module ClashDeckGenerator2
module Views
class Context < Hanami::View::Context
# Define your view context here. See https://guides.hanamirb.org/views/context/ for details.
end
end
end

10
app/views/helpers.rb Normal file
View File

@@ -0,0 +1,10 @@
# auto_register: false
# frozen_string_literal: true
module ClashDeckGenerator2
module Views
module Helpers
# Add your view helpers here
end
end
end

8
bin/dev Normal file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env sh
if ! gem list foreman -i --silent; then
echo "Installing foreman..."
gem install foreman
fi
exec foreman start -f Procfile.dev --env=/dev/null "$@"

25
bin/setup Normal file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# This script is a way to set up and keep your development environment updated
# automatically. It is meant to be idempotent so that you can run it at any
# time to get the same result. Add any new necessary setup steps to this file
# as your application evolves.
announce() {
local bold='\033[1m'
local reset='\033[0m'
printf "${bold}${1}${reset}\n"
}
announce "Running bundle install..."
bundle check || bundle install
announce "\nRunning npm install..."
npm install
announce "\nPreparing the database..."
hanami db prepare
announce "\n🌸 Setup complete!"

5
config.ru Normal file
View File

@@ -0,0 +1,5 @@
# frozen_string_literal: true
require "hanami/boot"
run Hanami.app

8
config/app.rb Normal file
View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
require "hanami"
module ClashDeckGenerator2
class App < Hanami::App
end
end

17
config/assets.js Normal file
View File

@@ -0,0 +1,17 @@
import * as assets from "hanami-assets";
// Assets are managed by esbuild (https://esbuild.github.io), and can be
// customized below.
//
// Learn more at https://guides.hanamirb.org/assets/customization/.
await assets.run({
esbuildOptionsFn: (args, esbuildOptions) => {
// Customize your `esbuildOptions` here.
//
// Use the `args.watch` boolean as a condition to apply diffierent options
// when running `hanami assets watch` vs `hanami assets compile`.
return esbuildOptions;
},
});

0
config/db/migrate/.keep Normal file
View File

15
config/db/seeds.rb Normal file
View File

@@ -0,0 +1,15 @@
# This seeds file should create the database records required to run the app.
#
# The code should be idempotent so that it can be executed at any time.
#
# To load the seeds, run `hanami db seed`. Seeds are also loaded as part of `hanami db prepare`.
# For example, if you have appropriate repos available:
#
# category_repo = Hanami.app["repos.category_repo"]
# category_repo.create(title: "General")
#
# Alternatively, you can use relations directly:
#
# categories = Hanami.app["relations.categories"]
# categories.insert(title: "General")

20
config/providers/db.rb Normal file
View File

@@ -0,0 +1,20 @@
warn "DB PROVIDER FILE LOADED"
ClashDeckGenerator2::App.register_provider :db do
warn "DB PROVIDER REGISTERED"
prepare do
warn "DB PROVIDER PREPARE"
require "hanami/db"
end
start do
warn "DB PROVIDER START"
config = target["settings"].database_url
db = Hanami::DB.new(config)
register "db", db
register "db.rom", db.rom
register "db.gateway", db.gateway
end
end

47
config/puma.rb Normal file
View File

@@ -0,0 +1,47 @@
# frozen_string_literal: true
#
# Environment and port
#
port ENV.fetch("HANAMI_PORT", 2300)
environment ENV.fetch("HANAMI_ENV", "development")
#
# Threads within each Puma/Ruby process (aka worker)
#
# Configure the minimum and maximum number of threads to use to answer requests.
max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5)
min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
#
# Workers (aka Puma/Ruby processes)
#
puma_concurrency = Integer(ENV.fetch("HANAMI_WEB_CONCURRENCY", 0))
puma_cluster_mode = puma_concurrency > 1
# How many worker (Puma/Ruby) processes to run.
# Typically this is set to the number of available cores.
workers puma_concurrency
#
# Cluster mode (aka multiple workers)
#
if puma_cluster_mode
# Preload the application before starting the workers. Only in cluster mode.
preload_app!
# Code to run immediately before master process forks workers (once on boot).
#
# These hooks can block if necessary to wait for background operations unknown
# to puma to finish before the process terminates. This can be used to close
# any connections to remote servers (database, redis, …) that were opened when
# preloading the code.
before_fork do
Hanami.shutdown
end
end

7
config/routes.rb Normal file
View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
module ClashDeckGenerator2
class Routes < Hanami::Routes
# Add your routes here. See https://guides.hanamirb.org/routing/overview/ for details.
end
end

9
config/settings.rb Normal file
View File

@@ -0,0 +1,9 @@
# frozen_string_literal: true
module ClashDeckGenerator2
class Settings < Hanami::Settings
# Define your app settings here, for example:
#
# setting :my_flag, default: false, constructor: Types::Params::Bool
end
end

0
db/.keep Normal file
View File

BIN
db/development.sqlite3 Normal file

Binary file not shown.

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
require "dry/types"
module ClashDeckGenerator2
Types = Dry.Types(default: :strict)
module Types
# Define your custom types here
end
end

0
lib/tasks/.keep Normal file
View File

8
package.json Normal file
View File

@@ -0,0 +1,8 @@
{
"name": "clash_deck_generator2",
"private": true,
"type": "module",
"dependencies": {
"hanami-assets": "^2.3.0"
}
}

82
public/404.html Normal file
View File

@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The page you were looking for doesnt exist (404)</title>
<style>
:root {
--foreground-rgb: 0, 0, 0;
--background-rgb: 255, 255, 255;
--font-sans: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-rgb: 0, 0, 0;
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,
html {
max-width: 100vw;
overflow-x: hidden;
font-size: 100%;
}
body {
color: rgb(var(--foreground-rgb));
background: rgb(var(--background-rgb));
font-family: var(--font-sans);
font-style: normal;
}
main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
padding: 0 4vw;
}
.message {
display: flex;
gap: 1rem;
flex-direction: column;
text-align: center;
}
.message h1 {
font-size: 2rem;
font-weight: 500;
}
p {
line-height: 1.6;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<main>
<div class="message">
<h1>404</h1>
<p>The page you were looking for doesnt exist.</p>
</div>
</main>
</body>
</html>

82
public/500.html Normal file
View File

@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Were sorry, but something went wrong (500)</title>
<style>
:root {
--foreground-rgb: 0, 0, 0;
--background-rgb: 255, 255, 255;
--font-sans: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-rgb: 0, 0, 0;
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,
html {
max-width: 100vw;
overflow-x: hidden;
font-size: 100%;
}
body {
color: rgb(var(--foreground-rgb));
background: rgb(var(--background-rgb));
font-family: var(--font-sans);
font-style: normal;
}
main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
padding: 0 4vw;
}
.message {
display: flex;
gap: 1rem;
flex-direction: column;
text-align: center;
}
.message h1 {
font-size: 2rem;
font-weight: 500;
}
p {
line-height: 1.6;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<main>
<div class="message">
<h1>500</h1>
<p>Were sorry, but something went wrong.</p>
</div>
</main>
</body>
</html>