commit 83a8bbd940d22fd6a5f0028023f4545f6a1a20c5 Author: Brooke Kuhlmann Date: Mon Apr 21 18:00:12 2025 -0600 Added project skeleton This includes the following dependencies necessary for this implementation: * link:https://alchemists.io/projects/cogger[Cogger]. * link:https://alchemists.io/projects/containable[Containable]. * link:https://github.com/httprb/http[HTTP]. * link:https://alchemists.io/projects/http-fake[HTTP Fake]. * link:https://alchemists.io/projects/infusible[Infusible]. * link:https://alchemists.io/projects/pipeable[Pipeable]. * link:https://alchemists.io/projects/refinements[Refinements]. Generated with link:https://alchemists.io/projects/gemsmith[Gemsmith] 23.3.0. diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..5ff1a12 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,36 @@ +version: 2.1 +jobs: + build: + working_directory: ~/project + docker: + - image: bkuhlmann/alpine-ruby:latest + steps: + - checkout + + - restore_cache: + name: Gems Restore + keys: + - gem-cache-{{.Branch}}-{{checksum "Gemfile"}}-{{checksum "trmnl-api.gemspec"}} + - gem-cache- + + - run: + name: Gems Install + command: | + gem update --system + bundle config set path "vendor/bundle" + bundle install + + - save_cache: + name: Gems Store + key: gem-cache-{{.Branch}}-{{checksum "Gemfile"}}-{{checksum "trmnl-api.gemspec"}} + paths: + - vendor/bundle + + - run: + name: Rake + command: bundle exec rake + + - store_artifacts: + name: SimpleCov Report + path: ~/project/coverage + destination: coverage diff --git a/.config/rubocop/config.yml b/.config/rubocop/config.yml new file mode 100644 index 0000000..bb2750e --- /dev/null +++ b/.config/rubocop/config.yml @@ -0,0 +1,2 @@ +inherit_gem: + caliber: config/all.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..b614951 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,8 @@ +## Why + + +## How + + +## Notes + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5bb52a2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +## Overview + + +## Screenshots/Screencasts + + +## Details + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b944ccc --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.gem +.bundle +Gemfile.lock +pkg +tmp diff --git a/.reek.yml b/.reek.yml new file mode 100644 index 0000000..a2736e3 --- /dev/null +++ b/.reek.yml @@ -0,0 +1,7 @@ +exclude_paths: + - tmp + - vendor + +detectors: + LongParameterList: + enabled: false diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..6cb9d3d --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.4.3 diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..0571ea6 --- /dev/null +++ b/Gemfile @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +ruby file: ".ruby-version" + +source "https://rubygems.org" + +gemspec + +group :quality do + gem "caliber", "~> 0.79" + gem "git-lint", "~> 9.0" + gem "reek", "~> 6.5", require: false + gem "simplecov", "~> 0.22", require: false +end + +group :development do + gem "rake", "~> 13.2" +end + +group :test do + gem "http-fake", "~> 4.2" + gem "refinements", "~> 13.0" + gem "rspec", "~> 3.13" +end + +group :tools do + gem "amazing_print", "~> 1.7" + gem "debug", "~> 1.10" + gem "irb-kit", "~> 1.1" + gem "repl_type_completor", "~> 0.1" +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..403c538 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 TRMNL + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..6de1a1e --- /dev/null +++ b/README.adoc @@ -0,0 +1,93 @@ +:toc: macro +:toclevels: 5 +:figure-caption!: + += Trmnl Api + +toc::[] + +== Features + +== Requirements + +. link:https://www.ruby-lang.org[Ruby]. + +== Setup + +To install _with_ security, run: + +[source,bash] +---- +# 💡 Skip this line if you already have the public certificate installed. +gem cert --add <(curl --compressed --location https://alchemists.io/gems.pem) +gem install trmnl-api --trust-policy HighSecurity +---- + +To install _without_ security, run: + +[source,bash] +---- +gem install trmnl-api +---- + +You can also add the gem directly to your project: + +[source,bash] +---- +bundle add trmnl-api +---- + +Once the gem is installed, you only need to require it: + +[source,ruby] +---- +require "trmnl/api" +---- + +== Usage + +== Development + +To contribute, run: + +[source,bash] +---- +git clone https://github.com/bkuhlmann/trmnl-api +cd trmnl-api +bin/setup +---- + +You can also use the IRB console for direct access to all objects: + +[source,bash] +---- +bin/console +---- + +== Tests + +To test, run: + +[source,bash] +---- +bin/rake +---- + +== link:https://alchemists.io/policies/license[License] + +== link:https://alchemists.io/policies/security[Security] + +== link:https://alchemists.io/policies/code_of_conduct[Code of Conduct] + +== link:https://alchemists.io/policies/contributions[Contributions] + +== link:https://alchemists.io/policies/developer_certificate_of_origin[Developer Certificate of Origin] + +== link:https://alchemists.io/projects/trmnl-api/versions[Versions] + +== link:https://alchemists.io/community[Community] + +== Credits + +* Built with link:https://alchemists.io/projects/gemsmith[Gemsmith]. +* Engineered by link:https://alchemists.io/team/brooke_kuhlmann[Brooke Kuhlmann]. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..7d50342 --- /dev/null +++ b/Rakefile @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "bundler/setup" +require "git/lint/rake/register" +require "reek/rake/task" +require "rspec/core/rake_task" +require "rubocop/rake_task" + +Git::Lint::Rake::Register.call +Reek::Rake::Task.new +RSpec::Core::RakeTask.new { |task| task.verbose = false } +RuboCop::RakeTask.new + +desc "Run code quality checks" +task quality: %i[git_lint reek rubocop] + +task default: %i[quality spec] diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..64391f1 --- /dev/null +++ b/bin/console @@ -0,0 +1,10 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" +Bundler.require :tools + +require "irb" +require "trmnl/api" + +IRB.start __FILE__ diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..9bef742 --- /dev/null +++ b/bin/rake @@ -0,0 +1,6 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" + +load Gem.bin_path "rake", "rake" diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 0000000..328edde --- /dev/null +++ b/bin/rspec @@ -0,0 +1,6 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" + +load Gem.bin_path "rspec-core", "rspec" diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000..fcc59f5 --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,6 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" + +load Gem.bin_path "rubocop", "rubocop" diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..988e359 --- /dev/null +++ b/bin/setup @@ -0,0 +1,17 @@ +#! /usr/bin/env ruby +# frozen_string_literal: true + +require "debug" +require "fileutils" +require "pathname" + +APP_ROOT = Pathname(__dir__).join("..").expand_path + +Runner = lambda do |*arguments, kernel: Kernel| + kernel.system(*arguments) || kernel.abort("\nERROR: Command #{arguments.inspect} failed.") +end + +FileUtils.chdir APP_ROOT do + puts "Installing dependencies..." + Runner.call "bundle install" +end diff --git a/lib/trmnl/api.rb b/lib/trmnl/api.rb new file mode 100644 index 0000000..28ef011 --- /dev/null +++ b/lib/trmnl/api.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "zeitwerk" + +Zeitwerk::Loader.new.then do |loader| + loader.inflector.inflect "api" => "API", "trmnl" => "TRMNL" + loader.tag = "trmnl-api" + loader.push_dir "#{__dir__}/.." + loader.setup +end + +module TRMNL + # Main namespace. + module API + def self.loader registry = Zeitwerk::Registry + @loader ||= registry.loaders.find { |loader| loader.tag == "trmnl-api" } + end + end +end diff --git a/spec/lib/trmnl/api_spec.rb b/spec/lib/trmnl/api_spec.rb new file mode 100644 index 0000000..2d54205 --- /dev/null +++ b/spec/lib/trmnl/api_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe TRMNL::API do + describe ".loader" do + it "eager loads" do + expectation = proc { described_class.loader.eager_load force: true } + expect(&expectation).not_to raise_error + end + + it "answers unique tag" do + expect(described_class.loader.tag).to eq("trmnl-api") + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..cefd38f --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require "simplecov" + +unless ENV["NO_COVERAGE"] + SimpleCov.start do + add_filter %r(^/spec/) + enable_coverage :branch + enable_coverage_for_eval + minimum_coverage_by_file line: 95, branch: 95 + end +end + +Bundler.require :tools + +require "dry/monads" +require "refinements" +require "trmnl/api" + +SPEC_ROOT = Pathname(__dir__).realpath.freeze + +using Refinements::Pathname + +Pathname.require_tree SPEC_ROOT.join("support/shared_contexts") + +RSpec.configure do |config| + config.color = true + config.disable_monkey_patching! + config.example_status_persistence_file_path = "./tmp/rspec-examples.txt" + config.filter_run_when_matching :focus + config.formatter = ENV.fetch("CI", false) == "true" ? :progress : :documentation + config.order = :random + config.pending_failure_output = :no_backtrace + config.shared_context_metadata_behavior = :apply_to_host_groups + config.warnings = true + + config.expect_with :rspec do |expectations| + expectations.syntax = :expect + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_doubled_constant_names = true + mocks.verify_partial_doubles = true + end + + config.before(:suite) { Dry::Monads.load_extensions :rspec } +end diff --git a/trmnl-api.gemspec b/trmnl-api.gemspec new file mode 100644 index 0000000..5dd76ad --- /dev/null +++ b/trmnl-api.gemspec @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = "trmnl-api" + spec.version = "0.0.0" + spec.authors = ["TRMNL"] + spec.email = ["support@usetrmnl.com"] + spec.homepage = "https://github.com/usetrmnl/trmnl-api" + spec.summary = "A monadic TRMNL API client." + spec.license = "MIT" + + spec.metadata = { + "bug_tracker_uri" => "https://github.com/usetrmnl/trmnl-api/issues", + "changelog_uri" => "https://github.com/usetrmnl/trmnl-api/tags", + "homepage_uri" => "https://github.com/usetrmnl/trmnl-api", + "label" => "TRMNL API", + "rubygems_mfa_required" => "true", + "source_code_uri" => "https://github.com/usetrmnl/trmnl-api" + } + + spec.signing_key = Gem.default_key_path + spec.cert_chain = [Gem.default_cert_path] + + spec.required_ruby_version = "~> 3.4" + + spec.add_dependency "cogger", "~> 1.2" + spec.add_dependency "containable", "~> 1.2" + spec.add_dependency "dry-monads", "~> 1.8" + spec.add_dependency "dry-schema", "~> 1.14" + spec.add_dependency "http", "~> 5.2" + spec.add_dependency "infusible", "~> 4.3" + spec.add_dependency "pipeable", "~> 1.3" + spec.add_dependency "zeitwerk", "~> 2.7" + + spec.extra_rdoc_files = Dir["README*", "LICENSE*"] + spec.files = Dir["*.gemspec", "lib/**/*"] +end