diff --git a/README.md b/README.md index 46214ed..c6327e4 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ ๐Ÿš€ Accelerates your development by 2-3x with an API Design First approach. Seamlessly integrates with your Rails application server โ€” no fancy tooling or expenses required. +We believe that API contracts should lead the development process, not be an afterthought derived from code. This framework embraces the [**API Design-First philosophy**](#-api-design-first-philosophy), ensuring that contracts remain independent from implementation. + +With APICraft, contracts are not only clear and consistent, but theyโ€™re also immediately usable, enabling teams to work with automatically generated mocks, behaviours and introspection tools, allowing development to begin in parallel, without waiting for backend implementations. + +It avoids the pitfalls of the code-first methodology, where contracts are auto-generated, often leading to inconsistency and misalignment. + ![APICraft Rails Logo](assets/apicraft_rails.png) - [APICraft Rails (Beta)](#apicraft-rails-beta) @@ -16,7 +22,7 @@ - [๐ŸŽญ API Mocking](#-api-mocking) - [๐ŸŽฎ API Mocking (Behaviours)](#-api-mocking-behaviours) - [๐Ÿง API Introspection](#-api-introspection) - - [๐Ÿ“– API Documentation (Swagger docs and Redoc)](#-api-documentation-swagger-docs-and-redoc) + - [๐Ÿ“– API Documentation (Swagger docs and RapiDoc)](#-api-documentation-swagger-docs-and-rapidoc) - [๐Ÿ”ง Configuration](#-configuration) - [๐Ÿค Contributing](#-contributing) - [๐Ÿ“ License](#-license) @@ -29,7 +35,7 @@ - ๐Ÿ” **API Introspections** - Introspect API schemas without needing to dig into the docs everytime. -- ๐Ÿ“บ **Documentation Out of the Box** - Documentation using `SwaggerDoc` and `Redoc` both. +- ๐Ÿ“บ **Documentation Out of the Box** - Documentation using `SwaggerDoc` and `RapiDoc` both. - ๐Ÿ—‚ **Easy Contracts Management** - Management of `openapi` specifications from within `app/contracts` directory. No new syntax, just plain old `openapi` standard with `.json` or `.yaml` formats @@ -66,7 +72,7 @@ By adopting an API Design First approach with APICraft Rails, you can accelerate Add this line to your application's Gemfile: ```ruby -gem 'apicraft-rails', '~> 0.5.0.beta1' +gem 'apicraft-rails', '~> 0.5.1.beta1' ``` And then execute: @@ -187,7 +193,7 @@ Example: `https://yoursite.com/api/orders` } } ``` -### ๐Ÿ“– API Documentation (Swagger docs and Redoc) +### ๐Ÿ“– API Documentation (Swagger docs and RapiDoc) Mount the documentation views in your route file. @@ -202,7 +208,7 @@ end You can browse API Documentation at - `/apicraft/swaggerdoc` -- `/apicraft/redoc` +- `/apicraft/rapidoc` Enable authentication for the `/apicraft` namespace. diff --git a/lib/apicraft/version.rb b/lib/apicraft/version.rb index fd50084..633cb42 100644 --- a/lib/apicraft/version.rb +++ b/lib/apicraft/version.rb @@ -2,5 +2,5 @@ # Current version of Apicraft. module Apicraft - VERSION = "0.5.0.beta1" + VERSION = "0.5.1.beta1" end diff --git a/lib/apicraft/web/actions.rb b/lib/apicraft/web/actions.rb index 98eb31d..be30cc2 100644 --- a/lib/apicraft/web/actions.rb +++ b/lib/apicraft/web/actions.rb @@ -5,16 +5,11 @@ module Web # Web actions to be handled from # the rack app. module Actions - def self.index(view_path) - [ - File.read(view_path), - "text/html" - ] - end - - def self.swaggerdoc(view_path) + def self.render_erb(view_path) @vars = { - urls: Router.contract_urls + urls: Router.contract_urls, + namespace: Router.namespace, + version: Apicraft::VERSION } [ @@ -25,16 +20,10 @@ def self.swaggerdoc(view_path) ] end - def self.redoc(view_path) - @vars = { - urls: Router.contract_urls - } - + def self.images(view_path) [ - ERB.new( - File.read(view_path) - ).result(binding), - "text/html" + File.read(view_path), + mime_type(view_path) ] end @@ -45,15 +34,9 @@ def self.contract(view_path) ] end - def self.introspect(method, view_path) - [ - Apicraft::Openapi::Contract.find_by_operation( - method, view_path - )&.operation( - method, view_path - )&.raw_schema&.to_json, - "application/json" - ] + def self.mime_type(view_path) + ext = File.extname(view_path) + Rack::Mime.mime_type(ext) end end end diff --git a/lib/apicraft/web/app.rb b/lib/apicraft/web/app.rb index 82ddcc6..37b326f 100644 --- a/lib/apicraft/web/app.rb +++ b/lib/apicraft/web/app.rb @@ -13,10 +13,10 @@ def self.call(env) Router.namespace = env["SCRIPT_NAME"] path = uri.split( Router.namespace - )[-1] + )[-1] || "/" content, content_type = Router.load_response!( - method, path || "/" + method, path ) raise Errors::RouteNotFound if content.nil? diff --git a/lib/apicraft/web/router.rb b/lib/apicraft/web/router.rb index 4ee760d..98e528f 100644 --- a/lib/apicraft/web/router.rb +++ b/lib/apicraft/web/router.rb @@ -7,20 +7,33 @@ module Router WEB_ROOT = File.expand_path( "#{File.dirname(__FILE__)}/../../../web" ) + IMAGES_DIR = "#{WEB_ROOT}/assets/images" def self.routes @routes ||= { "/": { - action: :index, - view_path: "#{WEB_ROOT}/views/index.html" + action: :render_erb, + view_path: "#{WEB_ROOT}/views/index.erb" }, "/swaggerdoc": { - action: :swaggerdoc, + action: :render_erb, view_path: "#{WEB_ROOT}/views/swaggerdoc.erb" }, "/redoc": { - action: :redoc, + action: :render_erb, view_path: "#{WEB_ROOT}/views/redoc.erb" + }, + "/rapidoc": { + action: :render_erb, + view_path: "#{WEB_ROOT}/views/rapidoc.erb" + }, + "/assets/images/thumb.png": { + action: :images, + view_path: "#{IMAGES_DIR}/apicraft_thumb.png" + }, + "/assets/images/logo.png": { + action: :images, + view_path: "#{IMAGES_DIR}/apicraft.png" } }.with_indifferent_access end @@ -32,9 +45,7 @@ def self.add(path, view_path) } end - def self.load_response!(method, path) - return Actions.introspect(method, path) unless routes[path].present? - + def self.load_response!(_method, path) Actions.send( routes[path][:action], routes[path][:view_path] diff --git a/web/assets/images/apicraft.png b/web/assets/images/apicraft.png new file mode 100644 index 0000000..54c9e53 Binary files /dev/null and b/web/assets/images/apicraft.png differ diff --git a/web/assets/images/apicraft_thumb.png b/web/assets/images/apicraft_thumb.png new file mode 100644 index 0000000..de215ff Binary files /dev/null and b/web/assets/images/apicraft_thumb.png differ diff --git a/web/views/index.erb b/web/views/index.erb new file mode 100644 index 0000000..9d51d0e --- /dev/null +++ b/web/views/index.erb @@ -0,0 +1,83 @@ + + + + APICraft + + + + + + +
+ +

Welcome to APICraft.

+

An opinionated framework for an API Design First approach to development.

+
+ RapiDoc + Swagger +
+
+
+ + โญ Star us on GitHub + +
+
+
+ v<%= @vars[:version] %> +
+
+ + diff --git a/web/views/index.html b/web/views/index.html deleted file mode 100644 index 048fdac..0000000 --- a/web/views/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - APICraft - - - - - - - - - diff --git a/web/views/rapidoc.erb b/web/views/rapidoc.erb new file mode 100644 index 0000000..3974d6b --- /dev/null +++ b/web/views/rapidoc.erb @@ -0,0 +1,102 @@ + + + + APICraft - Rapidoc + + + + + + + +
+ + APICraft +
+ +
+ + + + + diff --git a/web/views/redoc.erb b/web/views/redoc.erb index a1d0231..5a86592 100644 --- a/web/views/redoc.erb +++ b/web/views/redoc.erb @@ -60,8 +60,32 @@ end.to_json %> + const customTheme = { + colors: { + primary: { + main: '#4CAF50', // Set the primary color to #4CAF50 + }, + text: { + primary: '#ffffff', + secondary: '#b0b0b0', + }, + background: { + primary: '#1a1a1a', // Set the background color to #1a1a1a + secondary: '#222222', + }, + borders: '#4CAF50', // Border color for primary sections + }, + typography: { + fontSize: '16px', + fontFamily: '"Montserrat", "Roboto", sans-serif', + }, + sidebar: { + backgroundColor: '#2b2b2b', + }, + }; + // Initially render first API - Redoc.init(apis[0].url); + Redoc.init(apis[0].url, { theme: null }); // Function to handle API selection change function onSelectChange() {