├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ └── ci.yml └── CONTRIBUTING.md ├── logo ├── icon.png ├── logotype_vertical.png ├── logotyp_verticalv2.png ├── logotype_horizontal.jpg ├── logotype_horizontal.png ├── icon.svg ├── logotype_verticalv2.svg ├── logotype_horizontal.svg └── logotype_vertical.svg ├── shard.lock ├── shard.yml ├── .gitignore ├── util ├── stats.cr ├── readme.cr └── cli.cr ├── LICENSE ├── spec └── readme_spec.cr ├── CODE_OF_CONDUCT.md └── README.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | README.md @blacksmoke16 @veelenga 2 | -------------------------------------------------------------------------------- /logo/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veelenga/awesome-crystal/HEAD/logo/icon.png -------------------------------------------------------------------------------- /logo/logotype_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veelenga/awesome-crystal/HEAD/logo/logotype_vertical.png -------------------------------------------------------------------------------- /logo/logotyp_verticalv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veelenga/awesome-crystal/HEAD/logo/logotyp_verticalv2.png -------------------------------------------------------------------------------- /logo/logotype_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veelenga/awesome-crystal/HEAD/logo/logotype_horizontal.jpg -------------------------------------------------------------------------------- /logo/logotype_horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veelenga/awesome-crystal/HEAD/logo/logotype_horizontal.png -------------------------------------------------------------------------------- /shard.lock: -------------------------------------------------------------------------------- 1 | version: 2.0 2 | shards: 3 | markd: 4 | git: https://github.com/icyleaf/markd.git 5 | version: 0.4.2 6 | 7 | -------------------------------------------------------------------------------- /shard.yml: -------------------------------------------------------------------------------- 1 | name: 'Awesome Crystal' 2 | version: 0.1.0 3 | 4 | targets: 5 | cli: 6 | main: util/cli.cr 7 | 8 | development_dependencies: 9 | markd: 10 | github: icyleaf/markd 11 | version: ~> 0.4.0 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Link 2 | 3 | 4 | ## Checklist 5 | * [ ] - Shard is at least 30 days old. 6 | * [ ] - Shard has CI implemented. 7 | * [ ] - Shard has daily/weekly periodic builds (ideally with Crystal latest and nightly). 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.deps/ 2 | /lib/ 3 | /.crystal/ 4 | bin/ 5 | 6 | # Don't track the shard report files 7 | shard_list.yml 8 | report.md 9 | 10 | 11 | # Libraries don't need dependency lock 12 | # Dependencies will be locked in application that uses them 13 | /.deps.lock 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'master' 7 | 8 | jobs: 9 | test_latest: 10 | runs-on: ubuntu-latest 11 | container: 12 | image: crystallang/crystal:latest-alpine 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Install Dependencies 16 | run: shards install 17 | - name: Specs 18 | run: crystal spec 19 | -------------------------------------------------------------------------------- /util/stats.cr: -------------------------------------------------------------------------------- 1 | require "uri" 2 | require "./readme" 3 | 4 | puts "== Crystal Awesome Owner Rank == \n\n" 5 | 6 | Readme 7 | .new 8 | .refs(/git(?:hub|lab)\.com/) 9 | .map { |ref| URI.parse(ref).path.as(String?).try &.split(/\//).try &.[1] } 10 | .compact 11 | .reject(&.blank?) 12 | .map(&.downcase) 13 | .group_by(&.itself) 14 | .to_a 15 | .sort_by { |_, entries| -1 * entries.size } 16 | .each_with_index do |heros, i| 17 | puts "#{i + 1}. #{heros.first} (#{heros.last.size} entries)" 18 | end 19 | -------------------------------------------------------------------------------- /util/readme.cr: -------------------------------------------------------------------------------- 1 | require "xml" 2 | require "markd" 3 | 4 | class Readme 5 | getter html : XML::Node 6 | getter path : String 7 | 8 | def initialize(@path : String = "./README.md") 9 | @html = to_html File.read(@path) 10 | end 11 | 12 | def find(xpath) 13 | @html.xpath(xpath) 14 | end 15 | 16 | def awesomeness 17 | find("//ul/li/a").as XML::NodeSet 18 | end 19 | 20 | def refs(selects = nil) 21 | set = find("//ul/li/a[1]/@href").as XML::NodeSet 22 | refs = set.map { |node| node.text.as String } 23 | refs.select! { |x| x =~ selects } if selects 24 | refs 25 | end 26 | 27 | def groups 28 | set = find("//ul[li]").as XML::NodeSet 29 | set.map do |node| 30 | list_items = node.xpath("./li").as XML::NodeSet 31 | list_items.map do |li| 32 | first_link = li.xpath("./a[1]").as XML::NodeSet 33 | first_link.first?.try(&.content) || "" 34 | end.reject(&.empty?) 35 | end 36 | end 37 | 38 | private def to_html(markdown) 39 | XML.parse_html %[ 40 | 41 | #{Markd.to_html(markdown)} 42 | 43 | ] 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2018 veelenga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /logo/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guidelines 2 | 3 | Keep in mind that the list is very mature by now, so the bar of getting something accepted is high. Only submit something unique and generally useful. 4 | 5 | - **If you just created something, wait at least 30 days before submitting** to give it some time to mature and ensure it's not just a publish-and-forget type of project 6 | - Actively maintained: 7 | - Regular, recent commits 8 | - Or, for finished projects, issues and pull requests are responded to 9 | - Ensure your work follows general quality rules 10 | (look at [Writing Shards](https://crystal-lang.org/docs/guides/writing_shards.html) tutorial if this is a Crystal shard) 11 | - Your shard **must** have periodical (e.g. daily or weekly) builds set up on a publicly accessible CI against latest stable Crystal (nightly is optional) 12 | - For Travis CI see https://docs.travis-ci.com/user/cron-jobs. Note that you can also run Crystal nightly builds using [Docker-based approach](https://gist.github.com/vladfaust/9cf8ca03b00a3ab5c0e86ca8381acad7) 13 | 14 | ## List quality rules 15 | 16 | - List items are sorted alphabetically 17 | - Descriptions are clear and concise. For example, excessive information like *"... for Crystal programming language"* is omitted, because it is implied 18 | - No duplicates 19 | - No unnecessary empty lines and trailing spaces 20 | 21 | Most of this rules are guaranteed by automatic specs (`crystal spec`). Be sure specs pass before creating a PR. 22 | -------------------------------------------------------------------------------- /spec/readme_spec.cr: -------------------------------------------------------------------------------- 1 | require "spec" 2 | require "uri" 3 | require "../util/readme" 4 | 5 | readme = Readme.new 6 | 7 | # Enable for debug purpose 8 | # File.write("readme.html", readme.html) 9 | 10 | describe "List of Crystal Awesomeness" do 11 | it "has references to awesomeness" do 12 | readme.refs(/github\.com/).empty?.should be_false 13 | end 14 | 15 | it "has github references ('https://github.com/path')" do 16 | readme.refs(/github\.com/).each do |ref| 17 | uri = URI.parse(ref) 18 | uri.scheme.should eq "https" 19 | uri.host.should eq "github.com" 20 | uri.path.should_not be nil 21 | end 22 | end 23 | 24 | it "has gitlab references ('https://gitlab.com/path')" do 25 | readme.refs(/gitlab\.com/).each do |ref| 26 | uri = URI.parse(ref) 27 | uri.scheme.should eq "https" 28 | uri.host.should eq "gitlab.com" 29 | uri.path.should_not be nil 30 | end 31 | end 32 | 33 | it "does not have duplicates" do 34 | prev = nil 35 | readme.refs(/git(?:hub|lab)\.com/).map do |ref| 36 | uri = URI.parse(ref) 37 | host = uri.host.as String 38 | path = uri.path.as String? 39 | "#{host.downcase}#{path.try &.downcase}" 40 | end.sort.each do |ref| 41 | ref.should_not eq prev 42 | prev = ref 43 | end 44 | end 45 | 46 | it "has alphabetical case insensitive order" do 47 | readme.groups.each do |group| 48 | sorted = group.sort { |x, y| x.downcase <=> y.downcase } 49 | group.each_with_index do |awesome, i| 50 | awesome.should eq sorted[i] 51 | end 52 | end 53 | end 54 | 55 | context "Document" do 56 | it "does not have trailing spaces" do 57 | File.read_lines(readme.path).each_with_index do |line, line_number| 58 | (line =~ /[ \t]+$/ && line_number + 1).should eq nil 59 | end 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at velenhaupt@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /logo/logotype_verticalv2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 18 | 21 | 24 | 28 | 32 | 34 | 37 | 38 | 40 | 42 | 45 | 49 | 51 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /logo/logotype_horizontal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 19 | 23 | 26 | 30 | 34 | 36 | 39 | 40 | 42 | 44 | 47 | 51 | 53 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /logo/logotype_vertical.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 21 | 24 | 28 | 32 | 36 | 38 | 42 | 43 | 44 | 47 | 49 | 52 | 56 | 58 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /util/cli.cr: -------------------------------------------------------------------------------- 1 | require "./readme" 2 | require "yaml" 3 | require "json" 4 | require "http/client" 5 | require "colorize" 6 | require "option_parser" 7 | require "log" 8 | 9 | Log.setup_from_env default_sources: "awesome-crystal.cli" 10 | 11 | private LOGGER = ::Log.for "awesome-crystal.cli" 12 | 13 | # A `Shard` must have been built sometime in this span in order to be considered active. 14 | TIME_WINDOW = 1.year 15 | 16 | # Represents a version control provider. 17 | enum VC 18 | Github 19 | Gitlab 20 | 21 | # Returns the protocol and domain for `self`. 22 | def host : String 23 | case self 24 | when .github? then "https://github.com" 25 | when .gitlab? then "https://gitlab.com" 26 | end.not_nil! 27 | end 28 | end 29 | 30 | # Represents a specific `CIBuildResolver`. 31 | enum CI 32 | None 33 | Travis 34 | Gitlab 35 | Circle 36 | Actions 37 | Drone 38 | TravisPro 39 | Exempt 40 | end 41 | 42 | # Represents the latest build of a shard for a given `CIBuildResolver`. 43 | # 44 | # Exposes what `CI` provider it's related to, when it was last built, and if the shard was transferred. 45 | record CIRun, provider : CI, built_at : Time? = nil, transferred : Bool = false, active_workflow_proc : Proc(Bool)? = nil do 46 | include Comparable(self) 47 | 48 | def <=>(other : self) : Int32 49 | case {other.transferred, @transferred} 50 | when {false, true} then return 1 51 | when {true, false} then return -1 52 | end 53 | 54 | other_last_built = other.built_at 55 | built_at = @built_at 56 | 57 | case {other_last_built, built_at} 58 | when {Nil, Time} then return 1 59 | when {Time, Nil} then return -1 60 | when {Nil, Nil} then return 0 61 | end 62 | 63 | built_at.not_nil! <=> other_last_built.not_nil! 64 | end 65 | 66 | def active_workflow? : Bool 67 | return true unless (callback = @active_workflow_proc) 68 | callback.call 69 | end 70 | end 71 | 72 | # Attempts to resolve the latest `CIRun`, if possible, for a specific `CI` provider. 73 | abstract class CIBuildResolver 74 | private record Build, created_at : Time? do 75 | include JSON::Serializable 76 | end 77 | 78 | # Yields each `CIBuildResolver` implementation. 79 | def self.each_provider(owner : String, name : String, & : self ->) : Nil 80 | {% for provider in CIBuildResolver.all_subclasses.reject &.abstract? %} 81 | yield {{provider.id}}.new owner, name 82 | {% end %} 83 | end 84 | 85 | # Returns the count of unique `CIBuildResolver`s. 86 | def self.provider_count : Int32 87 | {{CIBuildResolver.all_subclasses.reject(&.abstract?).size}} 88 | end 89 | 90 | @latest_run_response : HTTP::Client::Response? = nil 91 | 92 | def initialize(@owner : String, @name : String); end 93 | 94 | # Returns the `CI` member related to `self`. 95 | abstract def member : CI 96 | 97 | # Returns the latest `CIRun` for the related `CI` `#member`. 98 | # 99 | # Returns `nil` if it could not be determined. 100 | def latest_run : CIRun? 101 | response = self.client.exec self.request 102 | 103 | if response.status.redirection? 104 | return CIRun.new self.member, transferred: true 105 | end 106 | 107 | if !response.status.success? 108 | LOGGER.debug { "Request failed: #{response.body.strip}" } 109 | return 110 | end 111 | 112 | if last_built = self.last_built response 113 | LOGGER.debug { "Last built #{(Time.utc - last_built).days} days ago" } 114 | else 115 | LOGGER.debug { "Was never built" } 116 | end 117 | 118 | @latest_run_response = response 119 | 120 | CIRun.new self.member, last_built, active_workflow_proc: ->active_workflow? 121 | rescue ex : Exception 122 | LOGGER.debug { "Failed to determine latest run: #{ex.message.try &.strip}" } 123 | return 124 | end 125 | 126 | # Returns `true` if the related workflow is active. 127 | # Can be overridden if a certain provider has additional logic used to determine this. 128 | protected def active_workflow? : Bool 129 | true 130 | end 131 | 132 | # Returns the API domain for `self`. 133 | protected abstract def api_domain : String 134 | 135 | # Returns an `HTTP::Request` used to fetch the CI builds related to `self`. 136 | protected abstract def request : HTTP::Request 137 | 138 | # Returns the `Time` of that latest build, or `nil` if it was never built. 139 | protected abstract def last_built(response : HTTP::Client::Response) : Time? 140 | 141 | # Returns the `HTTP::Client` used to fetch the CI builds. 142 | protected def client : HTTP::Client 143 | HTTP::Client.new self.api_domain, tls: true 144 | end 145 | end 146 | 147 | # :inherit: 148 | class Actions < CIBuildResolver 149 | # :inherit: 150 | def member : CI 151 | CI::Actions 152 | end 153 | 154 | protected def active_workflow? : Bool 155 | return true unless (response = @latest_run_response) 156 | 157 | workflow_runs = JSON.parse(response.body)["workflow_runs"].as_a 158 | 159 | return true if workflow_runs.empty? 160 | 161 | workflow_id = workflow_runs[0].as_h["workflow_id"].as_i 162 | 163 | LOGGER.debug { "#{@owner}/#{@name} has a workflow_id of #{workflow_id}" } 164 | 165 | response = self.client.exec(self.request "/actions/workflows/#{workflow_id}") 166 | 167 | if !response.status.success? 168 | LOGGER.notice { "Workflow status request failed: #{response.body.strip}" } 169 | return true 170 | end 171 | 172 | "active" == String.from_json response.body, root: "state" 173 | end 174 | 175 | protected def api_domain : String 176 | "api.github.com" 177 | end 178 | 179 | protected def last_built(response : HTTP::Client::Response) : Time? 180 | Array(Build).from_json(response.body, root: "workflow_runs").first?.try &.created_at 181 | end 182 | 183 | protected def request(path = "/actions/runs") : HTTP::Request 184 | HTTP::Request.new "GET", "/repos/#{@owner}/#{@name}#{path}", headers: HTTP::Headers{"Accept" => "application/vnd.github.v3+json"} 185 | end 186 | 187 | protected def client : HTTP::Client 188 | client = super 189 | 190 | if (gh_username = ENV["GH_USERNAME"]?) && (gh_token = ENV["GH_TOKEN"]?) 191 | client.basic_auth(gh_username, gh_token) 192 | else 193 | raise RuntimeError.new "Missing GitHub credentials ENV vars. Define GH_USERNAME and GH_TOKEN in order to authenticate with the GitHub API.\n\nNOTE: The GH token does not need to have any permissions." 194 | end 195 | 196 | client 197 | end 198 | end 199 | 200 | # :inherit: 201 | class Circle < CIBuildResolver 202 | private record Build, start_time : Time? do 203 | include JSON::Serializable 204 | end 205 | 206 | def member : CI 207 | CI::Circle 208 | end 209 | 210 | # :inherit: 211 | protected def api_domain : String 212 | "circleci.com" 213 | end 214 | 215 | protected def last_built(response : HTTP::Client::Response) : Time? 216 | Array(Build).from_json(response.body).find(&.start_time).try &.start_time 217 | end 218 | 219 | protected def request : HTTP::Request 220 | HTTP::Request.new "GET", "/api/v1.1/project/gh/#{@owner}/#{@name}", headers: HTTP::Headers{"Accept" => "application/json"} 221 | end 222 | end 223 | 224 | # :inherit: 225 | class Drone < CIBuildResolver 226 | private struct Build 227 | include JSON::Serializable 228 | 229 | @[JSON::Field(converter: Time::EpochConverter)] 230 | getter started : Time 231 | end 232 | 233 | # :inherit: 234 | def member : CI 235 | CI::Drone 236 | end 237 | 238 | protected def api_domain : String 239 | "cloud.drone.io" 240 | end 241 | 242 | protected def last_built(response : HTTP::Client::Response) : Time? 243 | Array(Build).from_json(response.body).find(&.started).try &.started 244 | end 245 | 246 | protected def request : HTTP::Request 247 | HTTP::Request.new "GET", "/api/repos/#{@owner}/#{@name}/builds" 248 | end 249 | end 250 | 251 | # :inherit: 252 | class Gitlab < CIBuildResolver 253 | # :inherit: 254 | def member : CI 255 | CI::Gitlab 256 | end 257 | 258 | protected def api_domain : String 259 | "gitlab.com" 260 | end 261 | 262 | protected def last_built(response : HTTP::Client::Response) : Time? 263 | Array(Build).from_json(response.body).find(&.created_at).try &.created_at 264 | end 265 | 266 | protected def request : HTTP::Request 267 | HTTP::Request.new "GET", "/api/v4/projects/#{@owner}%2F#{@name}/pipelines" 268 | end 269 | end 270 | 271 | # :inherit: 272 | abstract class AbstractTravis < CIBuildResolver 273 | private record Build, last_build_started_at : Time? do 274 | include JSON::Serializable 275 | end 276 | 277 | protected def last_built(response : HTTP::Client::Response) : Time? 278 | Build.from_json(response.body, root: "repo").last_build_started_at 279 | end 280 | 281 | protected def request : HTTP::Request 282 | HTTP::Request.new "GET", "/repos/#{@owner}/#{@name}", headers: HTTP::Headers{"Accept" => "application/vnd.travis-ci.2.1+json"} 283 | end 284 | end 285 | 286 | # :inherit: 287 | class Travis < AbstractTravis 288 | # :inherit: 289 | def member : CI 290 | CI::Travis 291 | end 292 | 293 | protected def api_domain : String 294 | "api.travis-ci.org" 295 | end 296 | end 297 | 298 | # :inherit: 299 | class TravisPro < AbstractTravis 300 | # :inherit: 301 | def member : CI 302 | CI::TravisPro 303 | end 304 | 305 | protected def api_domain : String 306 | "api.travis-ci.com" 307 | end 308 | end 309 | 310 | # Handles logic related to resolving what `CI` provider a given `Shard` uses. 311 | struct CIResolver 312 | # Shards that are exempt from reporting. 313 | # Mainly for utilities and plugins that 314 | # can't really be tested autonomously. 315 | private EXEMPT_SHARDS = { 316 | "bcardiff/crystal-ast-helper", 317 | "crenv/crenv", 318 | "crystal-community/crystal-patterns", 319 | "crystal-lang-tools/crystal-ide", 320 | "crystal-lang-tools/Crystal.tmbundle", 321 | "crystal-lang-tools/geany-crystal", 322 | "crystal-lang-tools/sublime-crystal", 323 | "crystal-lang-tools/vscode-crystal-lang", 324 | "crystal-lang/clang.cr", 325 | "crystal-lang/crystal-mysql", 326 | "dotmilk/emacs-crystal-mode", 327 | "elorest/cry", 328 | "elorest/vim-slang", 329 | "exercism/crystal", 330 | "g3ortega/vscode-crystal", 331 | "ilanpillemer/acmecrystal", 332 | "ilmanzo/crystal-koans", 333 | "jhass/DeBot", 334 | "juanedi/crystal-spacemacs-layer", 335 | "marciogm/asdf-crystal", 336 | "ruivieira/crystal-base", 337 | "Sija/crystal-dash-docset", 338 | "veelenga/crystal-zsh", 339 | "vscode-crystal-lang", 340 | "will/crystal-pg", 341 | } 342 | 343 | def initialize(@owner : String, @name : String) 344 | end 345 | 346 | # Resolve the latest `CIRun` 347 | def resolve : CIRun 348 | if EXEMPT_SHARDS.includes? "#{@owner}/#{@name}" 349 | return CIRun.new :exempt 350 | end 351 | 352 | build_channel = Channel(CIRun?).new 353 | builds = Array(CIRun).new 354 | 355 | CIBuildResolver.each_provider @owner, @name do |provider| 356 | spawn do 357 | LOGGER.context.set provider: provider.member.to_s 358 | 359 | if build = provider.latest_run 360 | build_channel.send build 361 | else 362 | build_channel.send nil 363 | end 364 | end 365 | end 366 | 367 | CIBuildResolver.provider_count.times do 368 | if build = build_channel.receive 369 | builds << build 370 | end 371 | end 372 | 373 | builds.sort!.last? || CIRun.new :none 374 | end 375 | end 376 | 377 | # Represents a shard within `README.md`. 378 | class Shard 379 | include YAML::Serializable 380 | include Comparable(self) 381 | 382 | # The owner of the shard's repo. 383 | # 384 | # Can either be a user or organization. 385 | getter owner : String 386 | 387 | # The name of the shard's repo. 388 | getter name : String 389 | 390 | # Which `VC` `self` uses. 391 | getter vc : VC 392 | 393 | # Which `CI` `self` uses. 394 | getter ci : CI 395 | 396 | @[YAML::Field(emit_null: true)] 397 | # The last time `self` was built. 398 | # 399 | # TODO: Make this the last time `self` was _successfully_ built; would be more useful in the future. 400 | getter last_built : Time? 401 | 402 | # Returns `true` if the shard has been transferred. 403 | # E.g. because of a `#owner` name change. 404 | getter? transferred : Bool = false 405 | 406 | # Returns `true` if this shard has an actie CI workflow. 407 | # 408 | # Will be `true` for all `CI`, but could be `false` for `CI::Actions` 409 | # if the shard has went >60 days without activity. 410 | getter? active_workflow : Bool 411 | 412 | # Try to resolve the `ci` of `self` by looking each shard up via 413 | # each CI provider's API. 414 | def initialize(@owner : String, @name : String, @vc : VC) 415 | LOGGER.info { "Adding #{@owner}/#{@name}" } 416 | 417 | latest_build = CIResolver.new(@owner, @name).resolve 418 | 419 | @ci = latest_build.provider 420 | @last_built = latest_build.built_at 421 | @transferred = latest_build.transferred 422 | @active_workflow = latest_build.active_workflow? 423 | 424 | if @ci.exempt? 425 | LOGGER.notice { "#{@owner}/#{@name} is exempt\n".colorize(:light_green).to_s } 426 | elsif lb = @last_built 427 | LOGGER.info { "#{@owner}/#{@name} uses #{@ci} and was last built #{(Time.utc - lb).days} days ago#{@active_workflow ? "\n" : ""}" } 428 | LOGGER.warn { "#{@owner}/#{@name} #{@ci}'s workflow is inactive!\n".colorize(Colorize::ColorRGB.new(242, 140, 40)).to_s } unless @active_workflow 429 | elsif !@transferred 430 | LOGGER.warn { "#{@owner}/#{@name} was never built!\n".colorize(:red).to_s } 431 | elsif @transferred 432 | LOGGER.warn { "#{@owner}/#{@name} has been transferred!\n".colorize(:yellow).to_s } 433 | end 434 | end 435 | 436 | # Returns `true` if `self`'s was `#last_built` more the `TIME_WINDOW` ago. 437 | def inactive? : Bool 438 | return false unless last_built = @last_built 439 | last_built <= TIME_WINDOW.ago 440 | end 441 | 442 | # A `String` representation of `self`. 443 | # 444 | # Controls how `self` is formatted within the report. 445 | def to_s(io : IO) : Nil 446 | io.puts "#{@vc.host}/#{@owner}/#{@name} - @#{@owner}" 447 | end 448 | 449 | def <=>(other : self) : Int32 450 | @owner <=> other.owner 451 | end 452 | end 453 | 454 | # Type to wrap the shard list. 455 | # 456 | # Provides methods used in the cli to interact with `README.md` and the shard list. 457 | record ShardList, shards : Array(Shard) = [] of Shard do 458 | include YAML::Serializable 459 | 460 | private OUT_FILE = "./shard_list.yml" 461 | private REPORT_FILE = "./report.md" 462 | 463 | # Parses `README.md` to build out the shard list, resolving the CI/VC of each shard. 464 | def self.initialize : self 465 | rm = Readme.new 466 | shard_list = new 467 | 468 | shards = (rm.refs(/gitlab\.com/) + rm.refs(/github\.com/)) 469 | 470 | shards.each do |ref| 471 | next if ref.starts_with? '#' 472 | uri = URI.parse(ref.chomp('/')) 473 | 474 | slug = uri.path.lchop('/').split('/') 475 | 476 | next if slug.size <= 1 477 | 478 | owner, name = slug 479 | 480 | vc = case uri.host 481 | when "github.com" then VC::Github 482 | when "gitlab.com" then VC::Gitlab 483 | else raise "Unexpected host #{uri.host}" 484 | end 485 | 486 | shard_list.shards << Shard.new owner, name, vc 487 | end 488 | 489 | File.open OUT_FILE, "w" do |file| 490 | shard_list.to_yaml file 491 | end 492 | 493 | generate_report 494 | 495 | shard_list 496 | end 497 | 498 | # Generates the report file based on the current `OUT_FILE` 499 | def self.generate_report : Nil 500 | File.open(REPORT_FILE, "w") do |file| 501 | file.puts "### No CI" 502 | self.no_ci.join(file) { |s, io| s.to_s io } 503 | file << '\n' 504 | 505 | file.puts "### CI Never Built" 506 | self.never_built.join(file) { |s, io| s.to_s io } 507 | file << '\n' 508 | 509 | file.puts "### Not Active" 510 | self.inactive.join(file) { |s, io| s.to_s io } 511 | file << '\n' 512 | 513 | file.puts "### Inactive Workflow" 514 | self.inactive_workflow.join(file) { |s, io| s.to_s io } 515 | file << '\n' 516 | 517 | file.puts "### Transferred" 518 | self.transferred.join(file) { |s, io| s.to_s io } 519 | end 520 | end 521 | 522 | # Returns an array of shards that do not have CI setup. 523 | def self.no_ci : Array(Shard) 524 | self.shards.select { |s| s.ci.none? && !s.transferred? } 525 | end 526 | 527 | # Returns an array of shards that have CI but a built never ran. 528 | def self.never_built : Array(Shard) 529 | self.shards.select { |s| !s.ci.none? && !s.last_built && !s.transferred? }.sort 530 | end 531 | 532 | # Returns an array of shards that has CI but are no longer considered 533 | # active due to last CI build time being over `TIME_WINDOW` ago, 534 | # excluding those with inactive workflows. 535 | def self.inactive : Array(Shard) 536 | self.shards.select { |s| !s.ci.none? && !s.transferred? && (s.inactive? && s.active_workflow?) }.sort 537 | end 538 | 539 | # Returns an array of shards that have been transferred. 540 | def self.transferred : Array(Shard) 541 | self.shards.select { |s| s.transferred? } 542 | end 543 | 544 | # Returns an array of shards that have inactive workflows. 545 | def self.inactive_workflow : Array(Shard) 546 | self.shards.select { |s| !s.active_workflow? } 547 | end 548 | 549 | private def self.shards : Array(Shard) 550 | self.read.shards.reject! &.ci.exempt? 551 | end 552 | 553 | # Serializes *OUT_FILE* into `self`. 554 | private def self.read : self 555 | ShardList.from_yaml File.read OUT_FILE 556 | end 557 | end 558 | 559 | private enum ShardReportClass 560 | NO_CI 561 | NEVER_BUILT 562 | NOT_ACTIVE 563 | TRANSFERRED 564 | INACTIVE_WORKFLOW 565 | 566 | def shards : Array(Shard) 567 | case self 568 | in .no_ci? then ShardList.no_ci 569 | in .never_built? then ShardList.never_built 570 | in .not_active? then ShardList.inactive 571 | in .transferred? then ShardList.transferred 572 | in .inactive_workflow? then ShardList.inactive_workflow 573 | end 574 | end 575 | end 576 | 577 | OptionParser.parse do |parser| 578 | parser.banner = "Usage: cli [arguments]" 579 | parser.on("-h", "--help", "Show this help") { puts parser; exit } 580 | parser.on("-i", "--initialize", "Initializes the shard list") { ShardList.initialize; exit } 581 | parser.on("-g", "--generate", "Generate the report from the current shard list") { ShardList.generate_report; exit } 582 | parser.on("-d TYPE", "--delete TYPE", "Removes shards from the README of the given TYPE") do |type| 583 | shards = ShardReportClass.parse(type).shards 584 | 585 | # Get an array of each line in the README 586 | lines = File.read_lines "./README.md", chomp: false 587 | 588 | # Remove the lines that contain an erroneous shard 589 | lines.reject! do |l| 590 | shards.any? { |s| l.includes? "#{s.owner}/#{s.name}" } 591 | end 592 | 593 | # Write the file contents again with the erroneous shards removed. 594 | File.write "./README.md", lines.join 595 | end 596 | end 597 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) 2 | 3 |

awesome-crystal

4 | 5 | # Awesome Crystal 6 | [![Awesome](https://awesome.re/badge.svg)](https://awesome.re) 7 | 8 | A curated list of awesome Crystal code and resources. Inspired by [awesome](https://github.com/sindresorhus/awesome) and [awesome-awesomeness](https://github.com/bayandin/awesome-awesomeness). 9 | The goal is to have projects mostly stable and useful for the community. 10 | 11 | Search shards at [shards.info](https://shards.info) for more. 12 | 13 | Contributions are welcome. Please take a quick look at the [contribution guidelines](https://github.com/veelenga/awesome-crystal/blob/master/.github/CONTRIBUTING.md) first. 14 | 15 | * [Awesome Crystal](#awesome-crystal) 16 | * [Algorithms and Data structures](#algorithms-and-data-structures) 17 | * [Blockchain](#blockchain) 18 | * [C Bindings](#c-bindings) 19 | * [Caching](#caching) 20 | * [CLI Builders](#cli-builders) 21 | * [CLI Utils](#cli-utils) 22 | * [Code Analysis and Metrics](#code-analysis-and-metrics) 23 | * [Compression](#compression) 24 | * [Configuration](#configuration) 25 | * [Converters](#converters) 26 | * [Cryptography](#cryptography) 27 | * [Data Formats](#data-formats) 28 | * [Data Generators](#data-generators) 29 | * [Database Drivers/Clients](#database-driversclients) 30 | * [Database Tools](#database-tools) 31 | * [Debugging](#debugging) 32 | * [Dependency Injection](#dependency-injection) 33 | * [Email](#email) 34 | * [Environment Management](#environment-management) 35 | * [Examples and funny stuff](#examples-and-funny-stuff) 36 | * [Framework Components](#framework-components) 37 | * [Game Development](#game-development) 38 | * [GUI Development](#gui-development) 39 | * [HTML Builders](#html-builders) 40 | * [HTML/XML parsing](#htmlxml-parsing) 41 | * [HTTP](#http) 42 | * [Image Processing](#image-processing) 43 | * [Implementations/Compilers](#implementationscompilers) 44 | * [Internationalization](#internationalization) 45 | * [Logging and monitoring](#logging-and-monitoring) 46 | * [Machine Learning](#machine-learning) 47 | * [Markdown/Text Processors](#markdowntext-processors) 48 | * [Misc](#misc) 49 | * [Network Protocols](#network-protocols) 50 | * [Networking](#networking) 51 | * [ORM/ODM Extensions](#ormodm-extensions) 52 | * [Package Management](#package-management) 53 | * [Processes and Threads](#processes-and-threads) 54 | * [Project Generators](#project-generators) 55 | * [Queues and Messaging](#queues-and-messaging) 56 | * [Routing](#routing) 57 | * [Scheduling](#scheduling) 58 | * [Science and Data analysis](#science-and-data-analysis) 59 | * [Search](#search) 60 | * [Security](#security) 61 | * [Serverless Computing](#serverless-computing) 62 | * [System](#system) 63 | * [Task management](#task-management) 64 | * [Template Engine](#template-engine) 65 | * [Testing](#testing) 66 | * [Third-party APIs](#third-party-apis) 67 | * [Validation](#validation) 68 | * [Web Frameworks](#web-frameworks) 69 | * [Community](#community) 70 | * [Unofficial](#unofficial) 71 | * [Resources](#resources) 72 | * [Official Documentation Translations](#official-documentation-translations) 73 | * [Services and Apps](#services-and-apps) 74 | * [Tools](#tools) 75 | * [DevOps](#devops) 76 | * [Editor Plugins](#editor-plugins) 77 | * [LSP Language Server Protocol Implementations](#lsp-language-server-protocol-implementations) 78 | * [Shell Plugins](#shell-plugins) 79 | 80 | ## Algorithms and Data structures 81 | * [bisect](https://github.com/spider-gazelle/bisect) - Inserting values into a sorted array 82 | * [blurhash.cr](https://github.com/Sija/blurhash.cr) - [BlurHash](https://github.com/woltapp/blurhash) implementation 83 | * [crie](https://github.com/c910335/crie) - Compile-time Trie 84 | * [CrOTP](https://github.com/philnash/crotp) - HOTP and TOTP implementation for two factor authentication 85 | * [crystal-linked-list](https://github.com/abvdasker/crystal-linked-list) - Implementation of Linked List 86 | * [crystaledge](https://github.com/unn4m3d/crystaledge) - A pure Vector Math library 87 | * [crystalg](https://github.com/tobyapi/crystalg) - A Generic Algorithm Library 88 | * [crystalline](https://github.com/jtomschroeder/crystalline) - A collection of containers and algorithms 89 | * [csuuid](https://github.com/wyhaines/csuuid.cr) - A Chronologically Sortable UUID 90 | * [edits.cr](https://github.com/tcrouch/edits.cr) - Collection of edit distance algorithms 91 | * [fzy](https://github.com/hugopl/fzy) - A Crystal port of awesome Fzy project fuzzy finder algorithm 92 | * [Goban](https://github.com/soya-daizu/goban) - A fast and efficient QR Code implementation 93 | * [graphlb](https://github.com/mettuaditya/graphlb) - Collection of graph datastructure and algorithms 94 | * [haversine](https://github.com/geocrystal/haversine) - An Implementation of the Haversine formula 95 | * [HKDF](https://github.com/spider-gazelle/HKDF) - HMAC-based Extract-and-Expand Key Derivation Function [rfc5869](https://www.rfc-editor.org/rfc/rfc5869) 96 | * [kd_tree](https://github.com/geocrystal/kd_tree) - An implementation of "K-Dimensional Tree" and "N-Nearest Neighbors" 97 | * [ksuid.cr](https://github.com/Sija/ksuid.cr) - K-Sortable Globally Unique IDs 98 | * [markov](https://github.com/mccallofthewild/markov) - Build Markov Chains and run Markov Processes 99 | * [multiset.cr](https://github.com/tcrouch/multiset.cr) - Implementation of a multiset 100 | * [named_information](https://github.com/spider-gazelle/named_information) - Naming Things with Hashes [rfc6920](https://datatracker.ietf.org/doc/html/rfc6920) 101 | * [qr-code](https://github.com/spider-gazelle/qr-code) - QR Code generator 102 | * [radix](https://github.com/luislavena/radix) - Radix Tree implementation 103 | * [s2_cells](https://github.com/spider-gazelle/s2_cells) - [S2 Geometry](https://s2geometry.io/devguide/s2cell_hierarchy.html) for spatial indexing 104 | * [secure-remote-password](https://github.com/spider-gazelle/secure-remote-password) - SRP-6a protocol for authentication over an insecure network 105 | * [SPAKE2+](https://github.com/spider-gazelle/SPAKE2_plus) - Password Authenticated Key Exchange (PAKE) protocol, comparable to SRP-6a 106 | * [splay_tree_map](https://github.com/wyhaines/splay_tree_map.cr) - Splay Tree implementation that conforms to the Hash ducktype 107 | * [verhoeff](https://github.com/spider-gazelle/verhoeff) - Implementation of the Verhoeff checksum algorithm 108 | 109 | ## Blockchain 110 | * [Axentro](https://github.com/Axentro/Axentro) - A custom blockchain platform 111 | * [Cocol](https://github.com/cocol-project/cocol) - A minimal blockchain testbed 112 | * [secp256k1.cr](https://github.com/q9f/secp256k1.cr) - Elliptic curve used in the public-private-key cryptography 113 | 114 | ## C bindings 115 | * [augeas.cr](https://github.com/fernandes/augeas.cr) - Bindings for [Augeas](https://augeas.net/) 116 | * [clang.cr](https://github.com/crystal-lang/clang.cr) - Libclang bindings 117 | * [crt.cr](https://github.com/maiha/crt.cr) - Bindings for libncursesw and crt 118 | * [crystal-gsl](https://github.com/konovod/crystal-gsl) - Bindings for [GNU Scientific Library](https://www.gnu.org/software/gsl/) 119 | * [crystal-hunspell](https://github.com/mamantoha/crystal-hunspell) - Bindings for [Hunspell](https://hunspell.github.io/) 120 | * [duktape.cr](https://github.com/jessedoyle/duktape.cr) - Bindings for the [Duktape](https://github.com/svaarala/duktape) javascript engine 121 | * [fftw.cr](https://github.com/firejox/fftw.cr) - Bindings for [FFTW](https://fftw.org/) library 122 | * [gphoto2.cr](https://github.com/Sija/gphoto2.cr) - Bindings for the [libgphoto2](http://www.gphoto.org/) library 123 | * [gpio.cr](https://github.com/spider-gazelle/gpio.cr) - Bindings for the gpiod library (general purpose IO control and feedback) 124 | * [icu.cr](https://github.com/olbat/icu.cr) - Bindings for the [ICU](http://site.icu-project.org/) library 125 | * [libnotify.cr](https://github.com/splattael/libnotify.cr) - Bindings for Libnotify 126 | * [nlopt.cr](https://github.com/konovod/nlopt.cr) - Bindings for [NLOpt](https://nlopt.readthedocs.io/en/latest/) 127 | * [pcap.cr](https://github.com/maiha/pcap.cr) - Bindings for libpcap 128 | * [pledge.cr](https://github.com/chris-huxtable/pledge.cr) - Bindings for OpenBSD's `pledge(2)` 129 | * [ssh2.cr](https://github.com/spider-gazelle/ssh2.cr) - Bindings for libssh2 library 130 | * [syslog.cr](https://github.com/chris-huxtable/syslog.cr) - Bindings for `syslog` 131 | * [v4l2.cr](https://github.com/spider-gazelle/v4l2.cr) - Bindings for [Video4Linux2](https://en.wikipedia.org/wiki/Video4Linux) 132 | * [wasmer-crystal](https://github.com/naqvis/wasmer-crystal) - Bindings for the `wasmer` WebAssembly runtime 133 | * [win32cr](https://github.com/mjblack/win32cr) - Bindings for Win32 API 134 | * [x_do.cr](https://github.com/woodruffw/x_do.cr) - Bindings for libxdo ([`xdotool`](https://github.com/jordansissel/xdotool)) 135 | 136 | ## Caching 137 | * [crystal-memcached](https://github.com/comandeo/crystal-memcached) - Implementation of a memcached client 138 | 139 | ## CLI Builders 140 | * [admiral](https://github.com/jwaldrip/admiral.cr) - A robust DSL for writing command line interfaces 141 | * [Athena Console](https://github.com/athena-framework/console) - Allows for the creation of CLI based commands 142 | * [clicr](https://github.com/j8r/clicr) - A simple declarative command line interface builder 143 | * [clim](https://github.com/at-grandpa/clim) - Slim command line interface builder 144 | * [Cling](https://github.com/devnote-dev/cling) - A modular, non-macro-based command line interface library 145 | * [commander](https://github.com/mrrooijen/commander) - Command-line interface builder 146 | * [Keimeno](https://github.com/robacarp/keimeno) - A lightweight text user interface library in Crystal 147 | * [OptionParser](https://crystal-lang.org/api/OptionParser.html) - command-line options processing (Crystal stdlib) 148 | * [Phreak](https://github.com/shinzlet/phreak) - A highly flexible Crystal CLI builder in the style of OptionParser 149 | 150 | ## CLI Utils 151 | * [climate](https://github.com/Sija/climate.cr) - Tiny tool to make your CLI output 🌈 coloured 152 | * [coin](https://github.com/caian-org/coin) - Command-line application that performs currency conversion via the [Fixer API](https://fixer.io) 153 | * [cride](https://github.com/j8r/cride) - A light CLI text editor/IDE 154 | * [git-repository](https://github.com/place-labs/git-repository) - A git cli wrapper querying and cloning remote repositories with minimal data transfer 155 | * [hetzner-k3s](https://github.com/vitobotta/hetzner-k3s) - A CLI tool to quickly create and manage Kubernetes clusters in Hetzner Cloud 156 | * [lff](https://github.com/mkdika/lff-cr) - Simple and straightforward large files finder utility in command line 157 | * [meet](https://github.com/ryanprior/meet) - Start a jitsi meeting quickly from the comfort of your command line 158 | * [oq](https://github.com/Blacksmoke16/oq) - A performant, and portable jq wrapper to facilitate the consumption and output of formats other than JSON; using [jq](https://github.com/stedolan/jq) filters to transform the data 159 | * [progress_bar.cr](https://github.com/TPei/progress_bar.cr) - A simple and customizable progress bar 160 | * [tablo](https://github.com/hutou/tablo) - A flexible terminal table generator 161 | * [tallboy](https://github.com/epoch/tallboy) - Generate ASCII character tables with support for spanning cells over multiple columns 162 | 163 | ## Code Analysis and Metrics 164 | * [ameba](https://github.com/crystal-ameba/ameba) - A static code analysis tool 165 | * [cruml](https://github.com/tamdaz/cruml) - A tool that provides an UML class diagram generator for any Crystal projects 166 | * [linguist.cr](https://github.com/microgit-com/linguist.cr) - Using multiple ways to find programming language used in files, based on Github's Linguist 167 | 168 | ## Compression 169 | * [Crystar](https://github.com/naqvis/crystar) - Readers and writers of Tar archive format 170 | * [Gzip](https://crystal-lang.org/api/Compress/Gzip.html) - readers and writers of gzip format (Crystal stdlib) 171 | * [polylines.cr](https://github.com/BuonOmo/polylines.cr) — compression of series of coordinates 172 | * [snappy](https://github.com/naqvis/snappy) - Snappy compression format reader/writer for Crystal 173 | * [Zip](https://crystal-lang.org/api/Compress/Zip.html) - readers and writers of zip format (Crystal stdlib) 174 | * [Zlib](https://crystal-lang.org/api/Compress/Zlib.html) - readers and writers of zlib format (Crystal stdlib) 175 | * [zstd.cr](https://github.com/didactic-drunk/zstd.cr) - Bindings for [Zstandard](https://github.com/facebook/zstd) compression library 176 | 177 | ## Configuration 178 | * [cr-dotenv](https://github.com/gdotdesign/cr-dotenv) - Loads .env file 179 | * [Envy](https://github.com/grottopress/envy) - Load environment variables from YAML 180 | * [envyable](https://github.com/philnash/envyable.cr) - A simple YAML to ENV config loader 181 | * [habitat](https://github.com/luckyframework/habitat) - Type safe configuration for your classes and modules 182 | * [totem](https://github.com/icyleaf/totem) - Load and parse a configuration in JSON, YAML, dotenv formats 183 | 184 | ## Converters 185 | * [base62.cr](https://github.com/Sija/base62.cr) - Base62 encoder/decoder, well suited for url-shortening 186 | * [crunits](https://github.com/spider-gazelle/crunits) - Tool for converting units of measure (miles to kilometers, celsius to fahrenheit etc) 187 | * [money](https://github.com/crystal-money/money) - Handling money and currency conversion with ease (almost complete port of [RubyMoney](https://github.com/RubyMoney/money)) 188 | * [sass.cr](https://github.com/straight-shoota/sass.cr) - Compile SASS/SCSS to CSS ([libsass](https://github.com/sass/libsass/) binding) 189 | * [tssc.cr](https://github.com/Sija/tssc.cr) - `Time::Span` String Converter (incl. JSON & YAML support) 190 | 191 | ## Cryptography 192 | * [cmac](https://github.com/spider-gazelle/cmac) - Crystal implementation of Cipher-based Message Authentication Code (CMAC) 193 | * [ed25519](https://github.com/spider-gazelle/ed25519) - the Ed25519 elliptic curve public-key signature system 194 | described in [RFC 8032] 195 | * [monocypher.cr](https://github.com/konovod/monocypher.cr) - Crystal wrapper for the Monocypher crypto library 196 | * [sodium.cr](https://github.com/didactic-drunk/sodium.cr) - Crystal wrapper for the libsodium crypto API 197 | 198 | ## Data Formats 199 | * [BinData](https://github.com/spider-gazelle/bindata) - Binary data parser helper with an [ASN.1](https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) parser 200 | * [config.cr](https://github.com/chris-huxtable/config.cr) - Easy to use configuration format parser 201 | * [crinder](https://github.com/c910335/crinder) - Class based json renderer 202 | * [Crystalizer](https://github.com/j8r/crystalizer) - (De)serialize any Crystal object; supporting JSON, YAML, and Byte formats out of the box 203 | * [CSV](https://crystal-lang.org/api/CSV.html) - parsing and generating for comma-separated values (Crystal stdlib) 204 | * [front_matter.cr](https://github.com/chris-huxtable/front_matter.cr) - Separates a files front matter from its content 205 | * [geoip2.cr](https://github.com/delef/geoip2.cr) - GeoIP2 reader 206 | * [HAR](https://github.com/NeuraLegion/har) - HAR (HTTP Archive) parser 207 | * [INI](https://crystal-lang.org/api/INI.html) - INI file parser (Crystal stdlib) 208 | * [jmespath.cr](https://github.com/qequ/jmespath.cr) - Crystal implementation of JMESPath, a query language for JSON 209 | * [JSON](https://crystal-lang.org/api/JSON.html) - parsing and generating JSON documents (Crystal stdlib) 210 | * [json-schema](https://github.com/spider-gazelle/json-schema) - convert JSON serializable classes into a [JSON Schema](https://json-schema.org/) representation 211 | * [JSON::OnSteroids](https://github.com/anykeyh/json_on_steroids) - handle and mutate JSON document easily 212 | * [maxminddb.cr](https://github.com/delef/maxminddb.cr) - MaxMindDB reader 213 | * [toml.cr](https://github.com/crystal-community/toml.cr) - TOML parser 214 | * [XML](https://crystal-lang.org/api/XML.html) - parsing and generating XML documents (Crystal stdlib) 215 | * [YAML](https://crystal-lang.org/api/YAML.html) - parsing and generating YAML documents (Crystal stdlib) 216 | 217 | ## Data Generators 218 | * [faker](https://github.com/askn/faker) - A library for generating fake data 219 | * [hashids.cr](https://github.com/splattael/hashids.cr) - A library to generate YouTube-like ids from one or many numbers 220 | * [prime](https://github.com/wontruefree/prime) - A prime number generator 221 | 222 | ## Database Drivers/Clients 223 | * [couchdb.cr](https://github.com/TechMagister/couchdb.cr) - CouchDB client 224 | * [cryomongo](https://github.com/elbywan/cryomongo) - MongoDB driver 225 | * [crystal-db](https://github.com/crystal-lang/crystal-db) - Common db api 226 | * [crystal-ldap](https://github.com/spider-gazelle/crystal-ldap) - LDAP client 227 | * [crystal-mysql](https://github.com/crystal-lang/crystal-mysql) - MySQL connector for Crystal 228 | * [crystal-pg](https://github.com/will/crystal-pg) - A Postgres driver 229 | * [crystal-redis](https://github.com/stefanwille/crystal-redis) - Full featured Redis client 230 | * [crystal-rethinkdb](https://github.com/kingsleyh/crystal-rethinkdb) - Driver for RethinkDB / RebirthDB 231 | * [crystal-sqlite3](https://github.com/crystal-lang/crystal-sqlite3) - SQLite3 bindings 232 | * [leveldb](https://github.com/crystal-community/leveldb) - Crystal bindings for LevelDB 233 | * [rocksdb.cr](https://github.com/maiha/rocksdb.cr) - RocksDB client 234 | * [surrealdb.cr](https://github.com/yorci/surrealdb.cr) - Unoffical SurrealDB HTTP & Websocket Client 235 | 236 | ## Database Tools 237 | * [migrate](https://github.com/vladfaust/migrate.cr) - A simpler database migration tool with transactions 238 | 239 | ## Debugging 240 | * [backtracer.cr](https://github.com/Sija/backtracer.cr) - Shard aiming to assist with parsing backtraces into a structured form 241 | * [debug.cr](https://github.com/Sija/debug.cr) - `debug!(…)` macro for `pp`-style debugging 242 | 243 | ## Dependency Injection 244 | * [Athena Dependency Injection](https://github.com/athena-framework/dependency-injection) - Robust dependency injection service container framework 245 | * [Crystal-DI](https://github.com/funk-yourself/crystal-di) - Lightweight DI Container 246 | * [HardWire](https://github.com/jerometwell/hardwire) - A compile-time non-intrusive dependency injection system 247 | * [syringe](https://github.com/Bonemind/syringe) - A simple and basic dependency injection shard for crystal 248 | 249 | ## Email 250 | * [carbon](https://github.com/luckyframework/carbon) - Fun, testable, and adapter-based email library 251 | * [crystal-email](https://github.com/arcage/crystal-email) - Simple e-mail sending library 252 | * [CrystalEmail](https://git.sceptique.eu/Sceptique/CrystalEmail) - A RFC compliant Email validator 253 | * [sendgrid.cr](https://github.com/dlanileonardo/sendgrid.cr) - Simple Sendgrid Client 254 | 255 | ## Environment Management 256 | * [asdf-crystal](https://github.com/marciogm/asdf-crystal) - Plugin for asdf version manager 257 | * [crenv](https://github.com/crenv/crenv) - Crystal version manager 258 | * [rcm.cr](https://github.com/maiha/rcm.cr) - Redis Cluster Manager 259 | * [vfox-crystal](https://github.com/yanecc/vfox-crystal) - Plugin for vfox version manager 260 | 261 | ## Examples and funny stuff 262 | * [blackjack-cr](https://github.com/gdonald/blackjack-cr) - Console Blackjack 263 | * [crystal-patterns](https://github.com/crystal-community/crystal-patterns) - Examples of GOF patters 264 | * [crystalworld](https://github.com/vladfaust/crystalworld) - [realworld.io](https://realworld.io) back-end API implementation 265 | * [exercism-crystal](https://github.com/exercism/crystal) - Exercism exercises 266 | * [try.cr](https://github.com/maiha/try.cr) - Try monad 267 | 268 | ## Framework Components 269 | * [Athena Event Dispatcher](https://github.com/athena-framework/event-dispatcher) - A Mediator and Observer pattern event library 270 | * [Athena Negotiation](https://github.com/athena-framework/negotiation) - Framework agnostic content negotiation library 271 | * [device_detector](https://github.com/creadone/device_detector) - Shard for detect device by user agent string 272 | * [Exception Page](https://github.com/crystal-loot/exception_page) - An exceptional exception page for Crystal web libraries and frameworks 273 | * [graphql](https://github.com/graphql-crystal/graphql) - Type-safe [GraphQL](http://graphql.org) server implementation 274 | * [graphql-crystal](https://github.com/ziprandom/graphql-crystal) - [GraphQL](http://graphql.org) implementation 275 | * [kemal-session](https://github.com/kemalcr/kemal-session) - Session handler for Kemal 276 | * [mochi](https://github.com/awcrotwell/mochi) - Authentication shard inspired by Devise supporting: Authenticable, Confirmable, Invitable & more 277 | * [motion.cr](https://github.com/awcrotwell/motion.cr) - Object oriented frontend library for Amber 278 | * [multi-auth](https://github.com/msa7/multi_auth) - Standardized multi-provider OAuth2 authentication (inspired by omniauth) 279 | * [praetorian](https://github.com/ilanusse/praetorian) - Minimalist authorization library inspired by Pundit 280 | * [Shield](https://github.com/grottopress/shield) - Comprehensive security for *Lucky* framework 281 | * [shrine.cr](https://github.com/jetrockets/shrine.cr) - File Attachment toolkit for Crystal applications. Heavily inspired by Shrine for Ruby 282 | * [tourmaline](https://github.com/protoncr/tourmaline) - Telegram bot framework with an API loosely based on [telegraf.js](https://telegraf.js.org/) 283 | 284 | ## Game Development 285 | * [CrSFML](https://github.com/oprypin/crsfml) - Bindings to [SFML](https://www.sfml-dev.org/) multimedia/game library 286 | * [crystal-chipmunk](https://github.com/oprypin/crystal-chipmunk) - Bindings to [Chipmunk](http://chipmunk-physics.net/), a fast and lightweight 2D game physics library 287 | * [crystal-imgui-sfml](https://github.com/oprypin/crystal-imgui-sfml) - Bindings to integrate [Dear ImGui](https://github.com/ocornut/imgui) into an [SFML](https://www.sfml-dev.org/) project 288 | * [entitas.cr](https://github.com/spoved/entitas.cr) - A Entity Component System Framework for Crystal 289 | * [MyECS](https://github.com/konovod/myecs) - A Sparse Entity Component System Framework for Crystal 290 | * [Raylib-cr](https://github.com/sol-vin/raylib-cr) - Direct bindings to [Raylib](https://raylib.com), which supports Linux, Windows, and Mac 291 | * [SDL-Crystal-Bindings](https://github.com/Hadeweka/SDL-Crystal-Bindings) - Direct (unsafe) bindings to [SDL2](https://www.libsdl.org/), intended for writing own game libraries 292 | 293 | ## GUI Development 294 | * [crystal-imgui](https://github.com/oprypin/crystal-imgui) - Bindings to [Dear ImGui](https://github.com/ocornut/imgui), an immediate-mode graphical UI library 295 | * [GTK4.cr](https://github.com/hugopl/gtk4.cr) - Bindings for [GTK4](https://docs.gtk.org/gtk4/overview.html) with Crystalized API 296 | * [Iu](https://github.com/grkek/iu) - UI framework based on the [Fusion/libui.cr](https://github.com/Fusion/libui.cr) library, with custom elements and modified bindings from [hedron-crystal/hedron](https://github.com/hedron-crystal/hedron) 297 | * [Ultimate GTK4 Crystal Guide](https://ultimate-gtk4-crystal-guide.geopjr.dev/) - Learn how to create premium GTK4 apps in Crystal 298 | 299 | ## HTML Builders 300 | * [blueprint](https://github.com/gunbolt/blueprint) - Write reusable and testable HTML templates in plain Crystal 301 | * [form_builder.cr](https://github.com/westonganger/form_builder.cr) - Dead simple HTML form builder for Crystal with built-in support for many popular UI libraries such as Bootstrap 302 | * [to_html](https://github.com/sbsoftware/to_html.cr) - The fastest HTML builder engine for Crystal 303 | * [Water](https://github.com/shootingfly/water) - A library for writing HTML in plain Crystal 304 | 305 | ## HTML/XML Parsing 306 | * [docx_cr_converter](https://github.com/aristotelesbr/docx_cr_converter) - parse DOCX Word 307 | * [lexbor](https://github.com/kostya/lexbor) - Fast HTML5 Parser that includes CSS selectors 308 | 309 | ## HTTP 310 | * [Cable](https://github.com/cable-cr/cable) - An ActionCable "port" to Crystal, framework agnostic, 100% compatible with the ActionCable JS Client 311 | * [cossack](https://github.com/crystal-community/cossack) - Simple flexible HTTP client 312 | * [crest](https://github.com/mamantoha/crest) - Simple HTTP and REST client, inspired by the Ruby's RestClient gem 313 | * [crul](https://github.com/porras/crul) - Command line HTTP client 314 | * [digest-auth](https://github.com/spider-gazelle/digest-auth) - Digest authentication 315 | * [halite](https://github.com/icyleaf/halite) - Crystal HTTP Requests with a chainable REST API, built-in sessions and loggers 316 | * [http-multiserver.cr](https://github.com/vladfaust/http-multiserver.cr) - Mounting multiple servers via routes (a.k.a. URL mapping) 317 | * [http-params-serializable](https://github.com/vladfaust/http-params-serializable) - HTTP params (de)serialization, applicable to URL queries and URL-encoded forms 318 | * [http-protection](https://github.com/rogeriozambon/http-protection) - Protection against typical web attacks 319 | * [http2](https://github.com/ysbaddaden/http2) - HTTP/2 Protocol Implementation 320 | * [HTTP::Client](https://crystal-lang.org/api/HTTP/Client.html) - HTTP client (Crystal stdlib) 321 | * [HTTP::Server](https://crystal-lang.org/api/HTTP/Server.html) - HTTP server (Crystal stdlib) 322 | * [HTTP::WebSocket](https://crystal-lang.org/api/HTTP/WebSocket.html) - HTTP WebSocket client (Crystal stdlib) 323 | * [link-header](https://github.com/spider-gazelle/link-header) - HTTP Link Header Parser 324 | * [ntlm](https://github.com/spider-gazelle/ntlm) - NTLM authentication 325 | * [proxy-fetcher.cr](https://github.com/nbulaj/proxy-fetcher.cr) - Proxy lists fetching & validating library 326 | * [sse.cr](https://github.com/y2k2mt/sse.cr) - [Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html) client 327 | 328 | ## Image processing 329 | * [celestine](https://github.com/celestinecr/celestine) - Create SVG images using a DSL 330 | * [ffmpeg](https://github.com/spider-gazelle/ffmpeg) - FFmpeg bindings that works with StumpyPNG to extract frames 331 | * [Pluto](https://github.com/phenopolis/pluto) - A fast and convenient image processing library 332 | * [stumpy_png](https://github.com/stumpycr/stumpy_png) - Read and write PNG images 333 | 334 | ## Implementations/Compilers 335 | * [charly](https://github.com/charly-lang) - Charly Programming Language 336 | * [cltk](https://github.com/ziprandom/cltk) - A crystal port of the Ruby Language Toolkit 337 | * [crisp](https://github.com/rhysd/Crisp) - Lisp dialect implemented with Crystal 338 | * [LinCAS-lang](https://github.com/LinCAS-lang) - A programming language for scientific computation 339 | * [mint-lang](https://github.com/mint-lang/mint) - A refreshing programming language for the front-end web 340 | * [myst-lang](https://github.com/myst-lang/) - A practical, dynamic language designed to be written and understood as easily and efficiently as possible 341 | * [novika](https://github.com/novika-lang/novika) - A free-form, moldable, interpreted programming language 342 | * [runic-lang](https://github.com/runic-lang) - In-design toy language 343 | 344 | ## Internationalization 345 | 346 | * [crystal-i18n](https://github.com/crystal-i18n/i18n) - An internationalization library inspired by Ruby-I18n 347 | * [i18n.cr](https://github.com/vladfaust/i18n.cr) - Internationalization shard 348 | * [Lens](https://github.com/syeopite/lens) - A multiformat internationalization (i18n) shard for Crystal. Supports Gettext, Ruby YAML, etc. 349 | * [Rosetta](https://github.com/wout/rosetta) - A blazing fast internationalization (i18n) library with compile-time key lookup supporting YAML and JSON formats 350 | 351 | ## Logging and monitoring 352 | * [crafana](https://github.com/spoved/crafana.cr) - A [Grafana](https://grafana.com/) library to help autogenerate dashboards 353 | * [fiber_metrics.cr](https://github.com/didactic-drunk/fiber_metrics.cr) - Track run time, wait time, or memory allocations per `Fiber`, method or block 354 | * [Log](https://crystal-lang.org/api/Log.html) - logging utility (Crystal stdlib) 355 | * [statsd.cr](https://github.com/miketheman/statsd.cr) - [Statsd](https://github.com/etsy/statsd) client library 356 | 357 | ## Machine Learning 358 | * [ai4cr](https://github.com/drhuffman12/ai4cr) - Artificial Intelligence (based on https://github.com/SergioFierens/ai4r) 359 | * [Cadmium](https://github.com/cadmiumcr/cadmium) - NLP library based heavily on [natural](https://github.com/NaturalNode/natural) 360 | * [crystal-fann](https://github.com/NeuraLegion/crystal-fann) - FANN (Fast Artifical Neural Network) binding 361 | * [mxnet.cr](https://github.com/toddsundsted/mxnet.cr) - Bindings for [MXNet](https://mxnet.incubator.apache.org/) 362 | * [shainet](https://github.com/NeuraLegion/shainet) - SHAInet (Neural Network in pure crystal) 363 | 364 | ## Markdown/Text Processors 365 | * [cr-cmark-gfm](https://github.com/amauryt/cr-cmark-gfm) - Crystal C bindings for cmark-gfm to work with Commonmark and Github Flavored Markdown 366 | * [markd](https://github.com/icyleaf/markd) - Yet another markdown parser built for speed, Compliant to CommonMark specification 367 | 368 | ## Misc 369 | * [aasm.cr](https://github.com/veelenga/aasm.cr) - Easy to use finite state machine for Crystal classes 370 | * [any_hash.cr](https://github.com/Sija/any_hash.cr) - Recursive Hash with better JSON::Any included 371 | * [anyolite](https://github.com/Anyolite/anyolite) - Full mruby interpreter with simple bindings, allowing for easy scripting support in projects 372 | * [burocracia.cr](https://github.com/vinibrsl/burocracia.cr) - burocracia.cr the dependecyless shard to validate, generate and format Brazilian burocracias such as CPF, CNPJ and CEP 373 | * [callbacks](https://github.com/vladfaust/callbacks.cr) - Expressive callbacks module 374 | * [circuit_breaker](https://github.com/TPei/circuit_breaker) - Implementation of the circuit breaker pattern 375 | * [CrSignals](https://github.com/firejox/CrSignals) - Signals/slots notification library 376 | * [crystal-binary_parser](https://github.com/DanSnow/crystal-binary_parser) - Binary parser 377 | * [crystal-web-framework-stars](https://github.com/isaced/crystal-web-framework-stars) - Web frameworks for Crystal, most starred on Github 378 | * [crz](https://github.com/dhruvrajvanshi/crz) - Functional programming library 379 | * [defined](https://github.com/wyhaines/defined.cr) - macros for conditional compilation based on constant definitions, version requirements, or environment variable settings 380 | * [emoji.cr](https://github.com/veelenga/emoji.cr) - Emoji library 381 | * [gphoto2-web.cr](https://github.com/Sija/gphoto2-web.cr) - Web API for libgphoto2 382 | * [immutable](https://github.com/lucaong/immutable) - Implementation of thread-safe, persistent, immutable collections 383 | * [iterm2](https://github.com/toddsundsted/iterm2) - Display images within the terminal using the ITerm2 Inline Images Protocol 384 | * [monads](https://github.com/alex-lairan/monads) - Monad implementation 385 | * [observable](https://github.com/TPei/observable) - Implementation of the observer pattern 386 | * [pinger](https://github.com/spider-gazelle/pinger) - Ping IP addresses and DNS entries without requiring sudo 387 | * [port_midi](https://github.com/jimm/crystal_port_midi) - Crystal C bindings for the PortMIDI cross-platform MIDI I/O library 388 | * [retriable.cr](https://github.com/Sija/retriable.cr) - Simple DSL to retry failed code blocks 389 | * [sentry](https://github.com/crystal-china/sentry) - Build/Runs your crystal application, watches files, and rebuilds/restarts app on file changes. 390 | * [serf-handler.cr](https://github.com/wyhaines/serf-handler.cr) - Framework for building Serf handlers, with a suite of useful builtin capabilities 391 | * [simple_retry](https://github.com/spider-gazelle/simple_retry) - Simple tool for retrying failed code blocks 392 | * [sslscan.cr](https://github.com/NeuraLegion/sslscan.cr) - Crystal shard wrapping the rbsec/sslscan utility 393 | * [version_tools](https://github.com/anicholson/crystal-version-tools) - Version-dependent behaviour, specified at compile-time 394 | * [wafalyzer](https://github.com/NeuraLegion/wafalyzer) - Web Application Firewall (WAF) Detector - shard + cli 395 | * [zaru_crystal](https://github.com/szTheory/zaru_crystal) - Filename sanitization 396 | 397 | ## Network Protocols 398 | * [amqp-client.cr](https://github.com/cloudamqp/amqp-client.cr) - AMQP 0-9.1, a messaging protocol, implemented by eg. RabbitMQ 399 | * [connect-proxy](https://github.com/spider-gazelle/connect-proxy) - Connect method style of HTTP tunnelling / HTTP proxy 400 | * [cr-xmpp](https://github.com/naqvis/cr-xmpp) - XMPP/Jabber Library 401 | * [Crirc](https://github.com/Meoowww/Crirc) - IRC protocol implementation (Client, Server, Bots) 402 | * [crystal-bacnet](https://github.com/spider-gazelle/crystal-bacnet) - BACnet protocol implementation with BACnet/IP client 403 | * [crystal-json-socket](https://github.com/foi/crystal-json-socket) - JSON-socket client & server implementation. Inspired by and compatible with [node-json-socket](https://github.com/sebastianseilund/node-json-socket/) and [ruby-json-socket](https://github.com/foi/ruby-json-socket) 404 | * [crystal-mqtt](https://github.com/spider-gazelle/crystal-mqtt) - A MQTT client 405 | * [crystal-snmp](https://github.com/spider-gazelle/crystal-snmp) - An SNMP implementation with version 1, 2c and 3 support 406 | * [dns](https://github.com/spider-gazelle/dns) - DNS protocol implementation and resolver 407 | * [fast_irc.cr](https://github.com/RX14/fast_irc.cr) - Fast IRC parser/generator 408 | * [jwt](https://github.com/crystal-community/jwt) - Implementation of JWT (JSON Web Token) 409 | * [knx](https://github.com/spider-gazelle/knx) - KNX protocol implementation supporting multicast, unicast and TCP/IP tunnelling 410 | * [mDNS](https://github.com/spider-gazelle/mdns) - DNS Service Discovery and multicast DNS 411 | * [mqtt-client.cr](https://github.com/84codes/mqtt-client.cr) - A fast and lightweight MQTT client 412 | * [msgpack-crystal](https://github.com/crystal-community/msgpack-crystal) - MessagePack library 413 | * [OAuth](https://crystal-lang.org/api/OAuth.html) - OAuth consumer (Crystal stdlib) 414 | * [OAuth2](https://crystal-lang.org/api/OAuth2.html) - OAuth2 client (Crystal stdlib) 415 | * [OpenSSL](https://crystal-lang.org/api/OpenSSL.html) - bindings to libssl (Crystal stdlib) 416 | * [simple_rpc](https://github.com/kostya/simple_rpc) - RPC Server and Client for Crystal. Implements msgpack-rpc protocol 417 | * [stomp](https://github.com/spider-gazelle/stomp) - STOMP protocol 418 | * [telnet.cr](https://github.com/spider-gazelle/telnet.cr) - Telnet protocol 419 | * [transfer_more](https://git.sceptique.eu/Sceptique/transfer_more) - Clone of transfer.sh to uploads files 420 | 421 | ## Networking 422 | * [ipaddress.cr](https://github.com/Sija/ipaddress.cr) - Library to handle IPv4 and IPv6 addresses 423 | * [mac-address](https://github.com/automatico/mac-address) - Library for working with MAC addresses 424 | 425 | ## ORM/ODM Extensions 426 | * [avram](https://github.com/luckyframework/avram) - A database wrapper for reading, writing, and migrating Postgres databases 427 | * [clear](https://github.com/anykeyh/clear) - ORM specialized to PostgreSQL only but with advanced features 428 | * [crecto](https://github.com/Crecto/crecto) - Database wrapper, based on Ecto 429 | * [granite](https://github.com/amberframework/granite) - ORM for Postgres, Mysql, Sqlite 430 | * [jennifer.cr](https://github.com/imdrasil/jennifer.cr) - Active Record pattern implementation with flexible query chainable builder and migration system 431 | * [rethinkdb-orm](https://github.com/spider-gazelle/rethinkdb-orm) - ORM for RethinkDB / RebirthDB 432 | 433 | ## Package Management 434 | * [shards](https://github.com/crystal-lang/shards) - Dependency manager for the Crystal 435 | 436 | ## Processes and Threads 437 | * [await_async](https://github.com/anykeyh/await_async) - Add keywords await & async in Crystal Lang 438 | * [concurrent.cr](https://github.com/didactic-drunk/concurrent.cr) - Simplified concurrency using streams/pipelines, waitgroups, semaphores, smores and more 439 | * [neph](https://github.com/tbrand/neph) - A modern command line job processor that can execute jobs concurrently 440 | * [promise](https://github.com/spider-gazelle/promise) - A Promise implementation with type inference 441 | * [werk](https://github.com/marghidanu/werk) - Dead simple task runner with concurrent support, ideal for local CI 442 | 443 | ## Project Generators 444 | * [crygen](https://github.com/tamdaz/crygen) - A library that allows to generate the Crystal code 445 | * [crystal_lib](https://github.com/crystal-lang/crystal_lib) - Automatic binding generator for native libraries 446 | * [fez](https://github.com/jwoertink/fez) - A Kemal application generator 447 | * [libgen](https://github.com/olbat/libgen) - Automatic bindings generator configured using JSON/YAML files 448 | 449 | ## Queues and Messaging 450 | * [crafka](https://github.com/BT-OpenSource/crafka) - Apache Kafka library utilizing `librdkafka` 451 | * [mosquito](https://github.com/mosquito-cr/mosquito/) - Redis backed periodic and ad hoc job processing 452 | * [NATS.io](https://github.com/nats-io/nats.cr) - NATS client 453 | * [sidekiq.cr](https://github.com/mperham/sidekiq.cr) - Simple, efficient job processing 454 | 455 | ## Routing 456 | * [orion](https://github.com/obsidian/orion) - A minimal, rails-esque routing library 457 | * [router.cr](https://github.com/tbrand/router.cr) - Minimum but powerful http router for HTTP::Server 458 | 459 | ## Scheduling 460 | * [crystime](https://gitlab.com/crystallabs/crystime) - Advanced time, calendar, schedule, and remind library 461 | * [schedule.cr](https://github.com/hugoabonizio/schedule.cr) - Run periodic tasks 462 | * [tasker](https://github.com/spider-gazelle/tasker) - A high precision scheduler including timezone aware cron jobs 463 | 464 | ## Science and Data analysis 465 | * [alea](https://github.com/nin93/alea) - Repeatable sampling, CDF and other utilities to work with probability distributions 466 | * [ishi](https://github.com/toddsundsted/ishi) - Graph plotting package with a small API and sensible defaults powered by gnuplot 467 | * [linalg](https://github.com/konovod/linalg) - Linear algebra library inspired by MATLAB and SciPy.linalg 468 | * [num.cr](https://github.com/crystal-data/num.cr) - Numerical computing library supporting N-Dimensional data 469 | * [predict.cr](https://github.com/RX14/predict.cr) - Satellite prediction library using the sgp4 model 470 | * [quartz](https://github.com/RomainFranceschini/quartz) - Modeling and simulation framework 471 | 472 | ## Search 473 | * [hermes](https://github.com/imdrasil/hermes.cr) - Data Mapper pattern implementation for ElastiSearch 474 | 475 | ## Security 476 | * [cyclonedx-cr](https://github.com/hahwul/cyclonedx-cr) - CycloneDX SBOM(Software Bill of Materials) generator for Crystal projects 477 | * [OWASP Noir](https://github.com/owasp-noir/noir) - Attack surface detector that identifies endpoints by static analysis 478 | * [XSSMaze](https://github.com/hahwul/xssmaze) - XSSMaze is a web service that tests security tools using diverse XSS cases 479 | 480 | ## Serverless Computing 481 | * [crystal_openfaas](https://github.com/TPei/crystal_openfaas/) - Template to enable crystal as first class citizens in OpenFaaS 482 | * [secrets-env](https://github.com/spider-gazelle/secrets-env) - Extends ENV module to read values injected by docker / kubernetes secrets and other orchestration tools 483 | 484 | ## System 485 | * [baked_file_system](https://github.com/schovi/baked_file_system) - Virtual file system implementation 486 | * [hardware](https://github.com/crystal-community/hardware) - Get CPU, Memory and Network informations of the running OS and its processes 487 | 488 | ## Task management 489 | * [cake](https://github.com/axvm/cake) - Production-ready Make-like utility tool 490 | * [sam](https://github.com/imdrasil/sam.cr) - Another one Rake-like task manager with namespacing and arguments system 491 | 492 | ## Template Engine 493 | * [crinja](https://github.com/straight-shoota/crinja) - An implementation of the [Jinja2 template engine](http://jinja.pocoo.org/) 494 | * [crustache](https://github.com/MakeNowJust/crustache) - [{{Mustache}}](https://mustache.github.io) for Crystal 495 | * [ECR (Embedded Crystal)](https://crystal-lang.org/api/ECR.html) - compile time template language which uses plain crystal expressions (Crystal stdlib) 496 | * [Jbuilder](https://github.com/shootingfly/jbuilder) - Generate JSON objects with a Builder-style DSL, inspired by jbuilder 497 | * [Kilt](https://github.com/jeromegn/kilt) - Abstraction layer for template engines 498 | * [Slang](https://github.com/jeromegn/slang) - Lightweight, terse, templating language inspired by Ruby's Slim 499 | * [teeplate](https://github.com/mosop/teeplate) - A library for rendering multiple template files 500 | 501 | ## Testing 502 | * [Athena Spec](https://github.com/athena-framework/spec) - Common/helpful [Spec](https://crystal-lang.org/api/Spec.html) compliant testing utilities 503 | * [crotest](https://github.com/emancu/crotest) - A tiny and simple test framework 504 | * [crytic](https://github.com/hanneskaeufler/crytic) - Mutation testing framework 505 | * [hashr](https://github.com/crystal-china/hashr) - A tiny class makes test on JSON response easier 506 | * [LuckyFlow](https://github.com/luckyframework/lucky_flow) - Automated browser tests similar to Capybara 507 | * [mass-spec](https://github.com/c910335/mass-spec) - Web API testing library 508 | * [microtest](https://github.com/Ragmaanir/microtest) - Small opinionated testing library focusing on power asserts 509 | * [minitest.cr](https://github.com/ysbaddaden/minitest.cr) - Library for unit tests and assertions 510 | * [mocks.cr](https://github.com/waterlink/mocks.cr) - Mocking library for Crystal 511 | * [selenium.cr](https://github.com/crystal-loot/selenium.cr) - Selenium client for interacting with web pages for browser automation 512 | * [Spec](https://crystal-lang.org/api/Spec.html) - spec framework (Crystal stdlib) 513 | * [spectator](https://gitlab.com/arctic-fox/spectator) - Feature rich spec framework that uses the modern expect syntax 514 | * [timecop.cr](https://github.com/crystal-community/timecop.cr) - Library for mocking with `Time.now`. Inspired by the [timecop ruby gem](https://github.com/travisjeffery/timecop) 515 | * [vcr](https://github.com/spoved/vcr.cr) - A HTTP capture and replay implementation for crystal 516 | * [webdriver_pump](https://github.com/bwilczek/webdriver_pump) - Page Object library. Inspired by Ruby's [WatirPump](https://github.com/bwilczek/watir_pump) 517 | * [webmock.cr](https://github.com/manastech/webmock.cr) - Library for stubbing `HTTP::Client` requests 518 | 519 | ## Third-party APIs 520 | * [amazonite](https://github.com/rjnienaber/amazonite) - An unofficial SDK supporting popular AWS APIs 521 | * [aws-signer.cr](https://github.com/beanieboi/aws-signer.cr) - This library signs your HTTP requests using AWS v4 522 | * [awscr-s3](https://github.com/taylorfinnell/awscr-s3) - AWS S3 interface 523 | * [awscr-signer](https://github.com/taylorfinnell/awscr-signer) - Sign HTTP::Request objects and generate presigned post forms 524 | * [crystal-consul](https://github.com/rogerwelin/crystal-consul) - Consul API client 525 | * [crystal-darksky](https://github.com/sb89/crystal-darksky) - Wrapper for the [Dark Sky](https://darksky.net) API 526 | * [crystal-swapi](https://github.com/sb89/crystal-swapi) - Star Wars API (SWAPI) wrapper 527 | * [crystal_slack](https://github.com/manastech/crystal_slack) - A tool that parses Slack slash commands or send incoming web hooks 528 | * [GDAX](https://github.com/mccallofthewild/gdax) - GDAX REST and WebSocket API Wrapper with request signing 529 | * [gitlab.cr](https://github.com/icyleaf/gitlab.cr) - GitLab API wrapper 530 | * [google](https://github.com/PlaceOS/google) - Google API wrapper 531 | * [host_meta](https://github.com/toddsundsted/host_meta) - A Web Host Metadata (https://tools.ietf.org/html/rfc6415) client 532 | * [kube-client.cr](https://github.com/spoved/kube-client.cr) - Kubernetes API Client 533 | * [mixpanel-crystal](https://github.com/petoem/mixpanel-crystal) - A library for sending events to Mixpanel 534 | * [mollie.cr](https://github.com/wout/mollie.cr) - [Mollie](https://www.mollie.com/en/) Payments API wrapper (Creditcard, PayPal, Apple Pay, Sofort, Klarna, ...) 535 | * [office365](https://github.com/PlaceOS/office365) - Microsoft Graph API wrapper 536 | * [pinboard.cr](https://github.com/oz/pinboard.cr) - [Pinboard](https://pinboard.in) API 537 | * [raven.cr](https://github.com/sija/raven.cr) - Raven is a client for [Sentry](https://github.com/getsentry/sentry) 538 | * [stripe.cr](https://github.com/confact/stripe.cr) - Stripe api wrapper 539 | * [tmdb.cr](https://github.com/mmacia/tmdb.cr) - The Movie DB (TMDb) api wrapper 540 | * [twitter-crystal](https://github.com/sferik/twitter-crystal) - A library to access the Twitter API 541 | * [web_finger](https://github.com/toddsundsted/web_finger) - A WebFinger (https://tools.ietf.org/html/rfc7033) client 542 | * [ynab.cr](https://github.com/jaredsmithse/ynab.cr) - A library to interact with your YNAB data 543 | 544 | ## Validation 545 | * [accord](https://github.com/neovintage/accord) - Shareable validation library for Crystal Objects 546 | * [Athena Validator](https://github.com/athena-framework/validator) - Robust & flexible validation framework 547 | * [validations](https://github.com/vladfaust/validations.cr) - Validations mixin 548 | * [validator](https://github.com/Nicolab/crystal-validator) - Data check and validation 549 | 550 | ## Web Frameworks 551 | * [amber](https://github.com/amberframework/amber) - Open source efficient and cohesive web application framework 552 | * [Athena](https://github.com/athena-framework/athena) - A web framework comprised of reusable, independent components 553 | * [grip](https://github.com/grip-framework/grip) - The microframework for writing powerful web applications 554 | * [kemal](https://github.com/kemalcr/kemal) - Lightning Fast, Super Simple web framework. Inspired by Sinatra 555 | * [lucky](https://github.com/luckyframework/lucky) - Catch bugs early, forget about most performance issues, and spend more time on code instead of debugging and writing tests 556 | * [marten](https://github.com/martenframework/marten) - A web framework that makes building web applications easy, productive, and fun 557 | * [runcobo](https://github.com/runcobo/runcobo) - An api framework with simple, intuitive and consistent DSL, using jbuilder to render json 558 | * [Shivneri](https://github.com/ujjwalguptaofficial/shivneri) - Component based MVC web framework for crystal targeting good code structures, modularity & performance 559 | * [spider-gazelle](https://github.com/spider-gazelle/spider-gazelle) - A Rails esque web framework with a focus on speed and extensibility 560 | 561 | # Community 562 | * [Crystal Forum](https://forum.crystal-lang.org/) 563 | * [Crystal newsletter](https://crystal-lang.org/#newsletter) 564 | * [Gitter](https://gitter.im/crystal-lang/crystal) 565 | * [IRC](ircs://irc.libera.chat:6697#crystal-lang) - #crystal-lang on Libera 566 | * [Reddit](https://www.reddit.com/r/crystal_programming/) 567 | * [Stackoverflow](https://stackoverflow.com/tags/crystal-lang/info) 568 | 569 | ## Unofficial 570 | * [Crystal Programming Discord Server](https://discord.gg/YS7YvQy) - Unofficial Discord server dedicated to the Crystal Programming Language 571 | * [Portuguese-speaking Telegram Group](https://t.me/crystalbrasil) - Bem vindos ao Crystal Brasil! 572 | * [Russian-speaking Telegram Group](https://t.me/crystal_ru) - Добро пожаловать, товарищ! 573 | 574 | # Resources 575 | * [Crystal for Rubyists](http://www.crystalforrubyists.com/) - Free book to bootstrap your Crystal journey 576 | * [Crystal Shards for Ruby Gems](https://github.com/crystal-lang/crystal/wiki/Crystal-Shards-for-Ruby-Gems) - A list of Ruby Gems and their Crystal Shards equivalents 577 | * [crystal-koans](https://github.com/ilmanzo/crystal-koans) - Learn Crystal by writing unit tests 578 | * [crystal-lang.org](https://crystal-lang.org) - Official language site 579 | * [devdocs.io](https://devdocs.io/crystal/) - API Documentation Browser with Crystal support 580 | * [Learn X in Y minutes](https://learnxinyminutes.com/docs/crystal/) - Quick tutorial on Crystal 581 | * [Programming Crystal](https://pragprog.com/book/crystal/programming-crystal) - PragProg book to start your Crystal journey 582 | * [Usability of Programming Languages](https://gergelyk.github.io/prog-lang-usability/) - Comparison of Python, Rust, Crystal 583 | 584 | ## Official Documentation Translations 585 | * [br.crystal-lang.org](http://br.crystal-lang.org/) - Brazilian 586 | * [ja.crystal-lang.org](http://ja.crystal-lang.org/) - Japanese 587 | * [kr.crystal-lang.org](https://kr.crystal-lang.org/) - Korean 588 | * [ru.crystal-lang.org](http://ru.crystal-lang.org/) - Russian 589 | * [tw.crystal-lang.org](http://tw.crystal-lang.org/) - Chinese Traditional 590 | 591 | # Services and Apps 592 | * [carc.in](https://carc.in/) - A web service that runs your code and displays the result 593 | * [Crank](https://github.com/arktisklada/crank) - A Procfile-based application manager (like Foreman) 594 | * [cry](https://github.com/elorest/cry) - Ability to execute crystal code in a fashion similar to Ruby's pry edit 595 | * [DeBot](https://github.com/jhass/DeBot) - IRC bot written in Crystal 596 | * [icr](https://github.com/crystal-community/icr) - Interactive console for Crystal (like IRB for Ruby) 597 | * [Invidious](https://github.com/iv-org/invidious) - Invidious is an alternative front-end to YouTube 598 | * [mpngin](https://github.com/thewalkingtoast/mpngin) - A URL shortener with simple stats 599 | * [procodile](https://github.com/crystal-china/procodile) - Run processes in the background (and foreground) on Mac & Linux from a Procfile (for production and/or development environments) 600 | * [quicktype](https://quicktype.io/) - Generate models and serializers from JSON, JSON Schema, GraphQL, and TypeScript 601 | * [shards.info](http://shards.info/) - Web service that lists all repositories on GitHub that have Crystal code in them. The sources are available on [GitHub](https://github.com/mamantoha/shards-info) 602 | 603 | # Tools 604 | * [ast_helper](https://github.com/bcardiff/crystal-ast-helper) - Helper tool to debug parser and formatter 605 | * [crystal-base](https://github.com/ruivieira/crystal-base) - CentOS base docker image for Crystal development 606 | * [crystal-dash-docset](https://github.com/Sija/crystal-dash-docset) - [Dash](https://kapeli.com/dash) docset generator 607 | * [port_ruby_to_crystal](https://github.com/crystal-china/port_ruby_to_crystal) - A regex replace ruby script for port ruby code to crystal easier, reduce friction 608 | * [public_suffix](https://github.com/toddsundsted/public_suffix) - A small library designed to make the Public Suffix List (https://publicsuffix.org/) easier to use 609 | 610 | ## DevOps 611 | * [ansible-crystal](https://github.com/CorbanR/ansible-crystal) - Ansible playbook for installing crystal 612 | * [DPPM](https://github.com/DFabric/dppm) - An easy, universal way to install and manage applications as packages (mostly Linux) 613 | 614 | ## Editor Plugins 615 | * Acme: 616 | * [acmecrystal](https://github.com/ilanpillemer/acmecrystal) - Reformats crystal code in acme 617 | * Atom 618 | * [crystal-tools](https://atom.io/packages/crystal-tools) - Enables built in tools in Crystal compiler 619 | * [language-crystal-actual](https://atom.io/packages/language-crystal-actual) - Crystal language support in Atom 620 | * Emacs 621 | * [crystal-mode](https://melpa.org/#/crystal-mode) - Crystal language support for Emacs ([crystal-lang-tools/emacs-crystal-mode](https://github.com/crystal-lang-tools/emacs-crystal-mode)) 622 | * Geany 623 | * [geany-crystal](https://github.com/crystal-lang-tools/geany-crystal) - Crystal support for the [Geany editor](https://www.geany.org/) 624 | * IntelliJ IDEA 625 | * [intellij-crystal-lang](https://github.com/asedunov/intellij-crystal-lang) - Crystal support for the JetBrains IDEs 626 | * Lite-XL 627 | * [lite-plugin-crystal](https://github.com/Tamnac/lite-plugin-crystal) - Crystal support for the [Lite-XL](https://lite-xl.com/en/) editor 628 | * Spacemacs 629 | * [crystal-spacemacs-layer](https://github.com/juanedi/crystal-spacemacs-layer) - Spacemacs contribution layer for Crystal 630 | * Sublime 631 | * [sublime-crystal](https://github.com/crystal-lang-tools/sublime-crystal) - Crystal syntax highlighting for sublime Text 632 | * TextMate 633 | * [Crystal.tmbundle](https://github.com/crystal-lang-tools/Crystal.tmbundle) - Crystal syntax highlighting, compile, format command, snippets 634 | * Vim 635 | * [vim-crystal](https://github.com/vim-crystal/vim-crystal) - Vim filetype support for Crystal 636 | * [vim-slang](https://github.com/elorest/vim-slang) - Vim filetype support for Slang Templating Engine 637 | * Visual Studio Code 638 | * [vscode-crystal-lang](https://github.com/crystal-lang-tools/vscode-crystal-lang) - Formatter, linter and syntax highlighting for `cr` and `ecr` files 639 | 640 | ## LSP Language Server Protocol Implementations 641 | * [crystalline](https://github.com/elbywan/crystalline) - Crystalline is an implementation of the Language Server Protocol written in and for the Crystal Language 642 | * [scry](https://github.com/crystal-lang-tools/scry) - Code analysis server for Crystal implementing the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) 643 | 644 | ## Shell plugins 645 | * [crun](https://github.com/Val/crun) - Crystal Run : shebang wrapper for Crystal 646 | * [crystal-zsh](https://github.com/veelenga/crystal-zsh) - .oh-my-zsh plugin 647 | --------------------------------------------------------------------------------