From d6bd4a8d0f857c9f5a850d8812c7ea8bd5b85ac5 Mon Sep 17 00:00:00 2001 From: Jonathan Siegel <248302+usiegj00@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:05:26 +0900 Subject: [PATCH 1/3] Add documents:delete command; bump to 0.3.6 Wraps the new DELETE /api/v1/documents/:id endpoint shipped in SDK v0.1.8. Useful for removing a document that was imported by mistake (e.g. a wrong Cert of Formation) before re-importing the correct one. --- shard.yml | 2 +- src/right/cli.cr | 29 +++++++++++++++++++++++++++++ src/right/version.cr | 2 +- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/shard.yml b/shard.yml index 6d76220..2378f22 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: right -version: 0.3.5 +version: 0.3.6 authors: - usiegj00 <248302+usiegj00@users.noreply.github.com> diff --git a/src/right/cli.cr b/src/right/cli.cr index 063ba25..a05acdf 100644 --- a/src/right/cli.cr +++ b/src/right/cli.cr @@ -80,6 +80,7 @@ module Right app.add EntitiesCreateCommand.new app.add EntitiesInfoCommand.new app.add DocumentsCommand.new + app.add DocumentsDeleteCommand.new app.add ImportCommand.new app.add CatalogCommand.new app.add SkillsCommand.new @@ -378,6 +379,34 @@ module Right end end + @[ACONA::AsCommand("documents:delete", description: "Delete a document by ID")] + class DocumentsDeleteCommand < ACON::Command + protected def configure : Nil + self.argument("id", :required, "document ID to delete") + end + + protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status + id = input.argument("id").to_s + if id.empty? + output.puts "error: document ID is required" + return ACON::Command::Status::FAILURE + end + + Right.sdk_config + _, status, _ = RightDocuments::DocumentsApi.new.api_v1_documents_id_delete_with_http_info(id) + if status == 204 + output.puts "deleted #{id}" + ACON::Command::Status::SUCCESS + else + output.puts "documents:delete failed: HTTP #{status}" + ACON::Command::Status::FAILURE + end + rescue ex + output.puts "documents:delete failed: #{ex.message}" + ACON::Command::Status::FAILURE + end + end + @[ACONA::AsCommand("import", description: "Import a PDF as an executed document")] class ImportCommand < ACON::Command include JSONOption diff --git a/src/right/version.cr b/src/right/version.cr index 3f9d9a4..a2aafe6 100644 --- a/src/right/version.cr +++ b/src/right/version.cr @@ -1,3 +1,3 @@ module Right - VERSION = "0.3.5" + VERSION = "0.3.6" end From 689107a1b01cde3092c932b1bb07b4803ab3180f Mon Sep 17 00:00:00 2001 From: Jonathan Siegel <248302+usiegj00@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:10:00 +0900 Subject: [PATCH 2/3] Rename shard from "right" to "rightdocuments" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shard package and Crystal module were named "right" / "Right", which doesn't match the user-facing brand or the binary name. Renames: - shard.yml name: right → rightdocuments - src/right.cr → src/rightdocuments.cr - src/right/ → src/rightdocuments/ - module Right → module RightDocuments (merges with the SDK's namespace, no class-name collisions; Right.* helpers become RightDocuments.*) - VERSION → CLI_VERSION (SDK already defines RightDocuments::VERSION) --- shard.yml | 4 ++-- src/right.cr | 3 --- src/right/version.cr | 3 --- src/rightdocuments.cr | 3 +++ src/{right => rightdocuments}/cli.cr | 32 +++++++++++++------------- src/{right => rightdocuments}/skill.md | 0 src/rightdocuments/version.cr | 3 +++ 7 files changed, 24 insertions(+), 24 deletions(-) delete mode 100644 src/right.cr delete mode 100644 src/right/version.cr create mode 100644 src/rightdocuments.cr rename src/{right => rightdocuments}/cli.cr (95%) rename src/{right => rightdocuments}/skill.md (100%) create mode 100644 src/rightdocuments/version.cr diff --git a/shard.yml b/shard.yml index 2378f22..711d451 100644 --- a/shard.yml +++ b/shard.yml @@ -1,4 +1,4 @@ -name: right +name: rightdocuments version: 0.3.6 authors: @@ -6,7 +6,7 @@ authors: targets: rightdocuments: - main: src/right.cr + main: src/rightdocuments.cr crystal: ">= 1.10" diff --git a/src/right.cr b/src/right.cr deleted file mode 100644 index 1f12fd5..0000000 --- a/src/right.cr +++ /dev/null @@ -1,3 +0,0 @@ -require "./right/cli" - -Right::CLI.run(ARGV) diff --git a/src/right/version.cr b/src/right/version.cr deleted file mode 100644 index a2aafe6..0000000 --- a/src/right/version.cr +++ /dev/null @@ -1,3 +0,0 @@ -module Right - VERSION = "0.3.6" -end diff --git a/src/rightdocuments.cr b/src/rightdocuments.cr new file mode 100644 index 0000000..e4c3920 --- /dev/null +++ b/src/rightdocuments.cr @@ -0,0 +1,3 @@ +require "./rightdocuments/cli" + +RightDocuments::CLI.run(ARGV) diff --git a/src/right/cli.cr b/src/rightdocuments/cli.cr similarity index 95% rename from src/right/cli.cr rename to src/rightdocuments/cli.cr index a05acdf..f2f7916 100644 --- a/src/right/cli.cr +++ b/src/rightdocuments/cli.cr @@ -3,7 +3,7 @@ require "oauth-device-flow" require "rightdocuments-client" require "./version" -module Right +module RightDocuments CLIENT_ID = ENV["RIGHTDOCUMENTS_CLIENT_ID"]? || "d4803e11ec443f87854a6caec69ab50b" BASE_URL = ENV["RIGHTDOCUMENTS_URL"]? || "https://app.rightdocuments.com" @@ -72,7 +72,7 @@ module Right module CLI def self.run(argv : Array(String)) : Nil - app = ACON::Application.new("rightdocuments", VERSION) + app = ACON::Application.new("rightdocuments", CLI_VERSION) app.add WhoamiCommand.new app.add LoginCommand.new app.add LogoutCommand.new @@ -101,7 +101,7 @@ module Right @[ACONA::AsCommand("login", description: "Authenticate via OAuth device flow")] class LoginCommand < ACON::Command protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.oauth.authenticate(scope: "documents:read documents:write") + RightDocuments.oauth.authenticate(scope: "documents:read documents:write") output.puts "Logged in." ACON::Command::Status::SUCCESS rescue ex @@ -113,7 +113,7 @@ module Right @[ACONA::AsCommand("logout", description: "Clear stored credentials")] class LogoutCommand < ACON::Command protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.oauth.logout + RightDocuments.oauth.logout output.puts "Logged out." ACON::Command::Status::SUCCESS end @@ -128,7 +128,7 @@ module Right end protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.sdk_config + RightDocuments.sdk_config result = RightDocuments::MeApi.new.api_v1_me_get if json?(input) output.puts result.to_pretty_json @@ -154,7 +154,7 @@ module Right end protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.sdk_config + RightDocuments.sdk_config result = RightDocuments::EntitiesApi.new.api_v1_entities_get if json?(input) output.puts result.to_pretty_json @@ -180,7 +180,7 @@ module Right end protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.sdk_config + RightDocuments.sdk_config result = RightDocuments::EntitiesApi.new.api_v1_entities_id_get(input.argument("entity_id").to_s) if json?(input) output.puts result.to_pretty_json @@ -245,7 +245,7 @@ module Right end protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status - Right.sdk_config + RightDocuments.sdk_config result = RightDocuments::CatalogApi.new.api_v1_catalog_get if json?(input) output.puts result.to_pretty_json @@ -311,15 +311,15 @@ module Right ) body = RightDocuments::ApiV1EntitiesPostRequest.new(entity: entity).to_json - uri = URI.parse("#{Right::BASE_URL}/api/v1/entities") + uri = URI.parse("#{RightDocuments::BASE_URL}/api/v1/entities") headers = HTTP::Headers{ - "Authorization" => "Bearer #{Right.oauth.access_token}", + "Authorization" => "Bearer #{RightDocuments.oauth.access_token}", "Content-Type" => "application/json", } response = HTTP::Client.post(uri, headers: headers, body: body) unless response.status.success? output.puts "entities:create failed: HTTP #{response.status.code} — #{response.body}" - if hint = Right.enum_error_hint(response.body) + if hint = RightDocuments.enum_error_hint(response.body) output.puts hint end return ACON::Command::Status::FAILURE @@ -355,8 +355,8 @@ module Right protected def execute(input : ACON::Input::Interface, output : ACON::Output::Interface) : ACON::Command::Status entity_id = input.argument("entity_id").to_s # Swagger doesn't describe the response schema, so call HTTP directly. - uri = URI.parse("#{Right::BASE_URL}/api/v1/entities/#{URI.encode_path(entity_id)}/documents") - headers = HTTP::Headers{"Authorization" => "Bearer #{Right.oauth.access_token}"} + uri = URI.parse("#{RightDocuments::BASE_URL}/api/v1/entities/#{URI.encode_path(entity_id)}/documents") + headers = HTTP::Headers{"Authorization" => "Bearer #{RightDocuments.oauth.access_token}"} response = HTTP::Client.get(uri, headers: headers) unless response.status.success? output.puts "documents failed: HTTP #{response.status.code} — #{response.body}" @@ -392,7 +392,7 @@ module Right return ACON::Command::Status::FAILURE end - Right.sdk_config + RightDocuments.sdk_config _, status, _ = RightDocuments::DocumentsApi.new.api_v1_documents_id_delete_with_http_info(id) if status == 204 output.puts "deleted #{id}" @@ -434,7 +434,7 @@ module Right # The swagger doesn't yet describe the multipart body for import, so the # SDK's import method takes only entity_id. Drop to direct HTTP until # the swagger is fleshed out. - uri = URI.parse("#{Right::BASE_URL}/api/v1/entities/#{URI.encode_path(entity_id)}/documents/import") + uri = URI.parse("#{RightDocuments::BASE_URL}/api/v1/entities/#{URI.encode_path(entity_id)}/documents/import") io = IO::Memory.new builder = HTTP::FormData::Builder.new(io) File.open(path) do |file| @@ -442,7 +442,7 @@ module Right end builder.finish headers = HTTP::Headers{ - "Authorization" => "Bearer #{Right.oauth.access_token}", + "Authorization" => "Bearer #{RightDocuments.oauth.access_token}", "Content-Type" => builder.content_type, } response = HTTP::Client.post(uri, headers: headers, body: io.to_s) diff --git a/src/right/skill.md b/src/rightdocuments/skill.md similarity index 100% rename from src/right/skill.md rename to src/rightdocuments/skill.md diff --git a/src/rightdocuments/version.cr b/src/rightdocuments/version.cr new file mode 100644 index 0000000..cd5f6fa --- /dev/null +++ b/src/rightdocuments/version.cr @@ -0,0 +1,3 @@ +module RightDocuments + CLI_VERSION = "0.3.6" +end From 020cc5ea40e34fc21559993d2d80e51835d634c6 Mon Sep 17 00:00:00 2001 From: Jonathan Siegel <248302+usiegj00@users.noreply.github.com> Date: Mon, 27 Apr 2026 08:11:58 +0900 Subject: [PATCH 3/3] Update workflows to src/rightdocuments.cr after rename --- .github/workflows/ci.yml | 2 +- .github/workflows/sdk-updated.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c687db2..499857e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - name: Install dependencies run: shards install - name: Type-check - run: crystal build src/right.cr -o bin/rightdocuments --no-codegen --error-on-warnings + run: crystal build src/rightdocuments.cr -o bin/rightdocuments --no-codegen --error-on-warnings - name: Run specs run: crystal spec --error-on-warnings if: hashFiles('spec/**/*_spec.cr') != '' diff --git a/.github/workflows/sdk-updated.yml b/.github/workflows/sdk-updated.yml index 853810c..29fc814 100644 --- a/.github/workflows/sdk-updated.yml +++ b/.github/workflows/sdk-updated.yml @@ -25,7 +25,7 @@ jobs: run: shards update rightdocuments-client - name: Build + test run: | - crystal build src/right.cr -o bin/rightdocuments --no-codegen --error-on-warnings + crystal build src/rightdocuments.cr -o bin/rightdocuments --no-codegen --error-on-warnings if compgen -G "spec/**/*_spec.cr" > /dev/null; then crystal spec --error-on-warnings fi