├── .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 |
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 |
59 |
--------------------------------------------------------------------------------
/logo/logotype_horizontal.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
61 |
--------------------------------------------------------------------------------
/logo/logotype_vertical.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 | [](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)
2 |
3 |

4 |
5 | # Awesome Crystal
6 | [](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 |
--------------------------------------------------------------------------------