-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GlobalStorage API support #4
base: master
Are you sure you want to change the base?
Changes from 10 commits
2a978a7
b829c31
b43203c
1af7c1d
9c8e1cb
7b14e53
9b315cd
84ae039
17a6f91
bf7249e
b85148b
85a66cc
4c4a162
d0ea621
ea9a8a2
6312eac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,22 @@ | ||
example_id | status | run_time | | ||
----------------------- | ------ | --------------- | | ||
./spec/sdk_spec.rb[1:1] | passed | 0.00092 seconds | | ||
./spec/sdk_spec.rb[1:2] | passed | 0.06699 seconds | | ||
./spec/sdk_spec.rb[1:3] | passed | 0.00039 seconds | | ||
./spec/sdk_spec.rb[1:4] | passed | 0.00052 seconds | | ||
./spec/sdk_spec.rb[1:5] | passed | 0.0032 seconds | | ||
./spec/sdk_spec.rb[1:6] | passed | 0.00035 seconds | | ||
./spec/sdk_spec.rb[1:7] | passed | 0.0003 seconds | | ||
./spec/sdk_spec.rb[1:8] | passed | 0.00154 seconds | | ||
example_id | status | run_time | | ||
------------------------------------------------------- | ------ | --------------- | | ||
./spec/monday/client_spec.rb[1:1:1] | passed | 0.00003 seconds | | ||
./spec/monday/client_spec.rb[1:1:2] | passed | 0.00003 seconds | | ||
./spec/monday/client_spec.rb[1:1:3] | passed | 0.00002 seconds | | ||
./spec/monday/client_spec.rb[1:2] | passed | 0.00047 seconds | | ||
./spec/monday/client_spec.rb[1:3] | passed | 0.00093 seconds | | ||
./spec/monday/client_spec.rb[1:4] | passed | 0.00017 seconds | | ||
./spec/monday/client_spec.rb[1:5:1] | passed | 0.0006 seconds | | ||
./spec/monday/monday_api/monday_api_client_spec.rb[1:1] | passed | 0.00009 seconds | | ||
./spec/monday/storage_spec.rb[1:1:1] | passed | 0.00003 seconds | | ||
./spec/monday/storage_spec.rb[1:1:2] | passed | 0.00003 seconds | | ||
./spec/monday/storage_spec.rb[1:1:3] | passed | 0.00002 seconds | | ||
./spec/monday/storage_spec.rb[1:2:1] | passed | 0.00016 seconds | | ||
./spec/monday/storage_spec.rb[1:2:2] | passed | 0.00014 seconds | | ||
./spec/monday/storage_spec.rb[1:2:3] | passed | 0.00014 seconds | | ||
./spec/monday/storage_spec.rb[1:2:4] | passed | 0.0003 seconds | | ||
./spec/monday/storage_spec.rb[1:3:1] | passed | 0.00016 seconds | | ||
./spec/monday/storage_spec.rb[1:3:2] | passed | 0.00017 seconds | | ||
./spec/monday/storage_spec.rb[1:4:1] | passed | 0.00076 seconds | | ||
./spec/monday/storage_spec.rb[1:4:2] | passed | 0.00017 seconds | | ||
./spec/sdk_spec.rb[1:1] | passed | 0.00021 seconds | |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
AllCops: | ||
TargetRubyVersion: 2.3 | ||
|
||
Style/FrozenStringLiteralComment: | ||
Enabled: true | ||
SafeAutoCorrect: true | ||
|
||
Style/Documentation: | ||
Enabled: false | ||
|
||
Metrics/BlockLength: | ||
Exclude: | ||
- '**/spec/**/*.rb' | ||
|
||
Metrics/MethodLength: | ||
Exclude: | ||
- '**/spec/**/*.rb' | ||
|
||
Metrics/AbcSize: | ||
Exclude: | ||
- '**/spec/**/*.rb' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
source "https://rubygems.org" | ||
source 'https://rubygems.org' | ||
|
||
# Specify your gem's dependencies in monday-sdk-ruby.gemspec | ||
gemspec |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should resolve the documentation issue |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,169 @@ | ||
# monday-sdk-ruby | ||
|
||
Ruby SDK for developing over the monday.com platform | ||
|
||
--- | ||
|
||
In order to use the APIs you need to have valid access token. | ||
It could be short lived token received from JWT payload from Authorization header (valid for 60 seconds), or you could ask users for permanent [access token with OAuth](https://developer.monday.com/apps/docs/oauth). | ||
|
||
## GraphQL API | ||
|
||
All the future examples requires client instance with valid access token. | ||
|
||
```ruby | ||
token = "short lived access token or OAuth access token" | ||
client = Monday::Client.new(token: token) | ||
|
||
# you can pass a custom API endpoint | ||
client = Monday::Client.new(token: token, api: 'https://custom.api.monday.com') | ||
|
||
# or you can pass a custom Faraday client | ||
connection = Faraday.new do |client| | ||
client.request :json | ||
client.response :raise_error | ||
client.response :json | ||
end | ||
client = Monday::Client.new(token: token, conn: connection) | ||
``` | ||
|
||
For all available queries & mutations please see the documentation in the [Public API playground](https://monday.com/developers/v2/try-it-yourself) | ||
For more references you can look at the [JavaScript SDK docs](https://developer.monday.com/apps/docs/mondayapi) | ||
|
||
Simple query sample: | ||
|
||
```ruby | ||
client.api(%( | ||
query { | ||
me { | ||
name | ||
} | ||
} | ||
)) | ||
``` | ||
|
||
Query with passed variables | ||
|
||
```ruby | ||
client.api(%( | ||
query ($boardId: Int) { | ||
boards(ids: [$boardId]) { | ||
id | ||
name | ||
} | ||
} | ||
), variables: { boardId: 123_456 }) | ||
``` | ||
|
||
Mutation example | ||
|
||
```ruby | ||
client.api(%( | ||
mutation ($boardId: Int!, $title: String!) { | ||
create_column( | ||
board_id: $boardId | ||
title: $title | ||
column_type: text | ||
) { id } | ||
} | ||
), variables: { boardId: 123_456, title: 'Sample column' }) | ||
``` | ||
|
||
## GlobalStorage API | ||
|
||
The most of the [JavaScript SDK documentation](https://developer.monday.com/apps/docs/mondaystorage#global-level) is relevant for Ruby. | ||
|
||
The monday apps infrastructure includes a persistent, key-value storage that developers can leverage to store data without creating their own backend and maintaining their own database. | ||
Storage doesn't reset between major versions since it is shared across the entire app, not just an instance. | ||
|
||
The following limits apply to both the instance and global-level methods: | ||
|
||
- Key length limit: 256 | ||
- Storage limit per key: 6MB | ||
|
||
### Initializing global storage | ||
|
||
The initializing process is the same as for the GraphQL API. | ||
|
||
```ruby | ||
storage = Monday::Storage.new(token: token) | ||
``` | ||
|
||
### Set a new value | ||
|
||
```ruby | ||
storage.set('foo', 'test') | ||
# => {'version' => '098f6'} | ||
|
||
storage.set('foo', 'bar') | ||
# => {'version' => '37b51'} | ||
``` | ||
|
||
### Get a value: | ||
|
||
```ruby | ||
storage.get('foo') | ||
# => {'value' => 'bar', 'version' => '37b51'} | ||
|
||
storage.get('not-existed-key') | ||
# => {'value' => nil} | ||
``` | ||
|
||
### Delete an item: | ||
|
||
```ruby | ||
storage.get('foo') | ||
# => {'value' => 'bar', 'version' => '37b51'} | ||
|
||
storage.delete('foo') | ||
|
||
storage.get('foo') | ||
# => {'value' => nil} | ||
``` | ||
|
||
### Versioning | ||
|
||
`get` and `set` each return a version identifier you can use to identify the value currently stored in a key. Whenever a write that changes the value occurs, the version identifier in the database changes. The identifier signifies whether or not a value changed from another location and prevents it from being overwritten. | ||
|
||
```ruby | ||
storage.get('foo') | ||
# => {'value' => 'bar', 'version' => '37b51'} | ||
begin | ||
storage.set('foo', {value: 'updated', previous_version: 'wrong'}) | ||
rescue Faraday::ConflictError => exception | ||
# the value is not changed due to the version conflict | ||
end | ||
``` | ||
|
||
If you want to not raise an exception, just pass your own instance of Faraday without the `raise_error` middleware: | ||
|
||
```ruby | ||
connection = Faraday.new do |client| | ||
client.request :json | ||
client.response :json | ||
end | ||
storage = Monday::Storage.new(token: token, conn: connection) | ||
``` | ||
|
||
### Access data created from the frontend | ||
|
||
All the methods allow passing shared flag to access values scope accessible for current App's frontend instance. | ||
Values created without this flag available only for the backend. | ||
**Values saved with and without the flag are completely separated!** | ||
|
||
```ruby | ||
storage.get('foo') | ||
# => {'value' => 'bar', 'version' => '1234a'} | ||
|
||
storage.get('foo', shared: true) | ||
# => {'value' => nil} | ||
|
||
storage.set('foo', 'frontend', shared: true) | ||
# => {'version' => 'aca33'} | ||
|
||
storage.get('foo') | ||
# => {'value' => 'bar', 'version' => '1234a'} | ||
|
||
storage.get('foo', shared: true) | ||
# => {'value' => 'frontend', 'version' => 'aca33'} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
require "bundler/gem_tasks" | ||
require "rspec/core/rake_task" | ||
require 'bundler/gem_tasks' | ||
require 'rspec/core/rake_task' | ||
|
||
RSpec::Core::RakeTask.new(:spec) | ||
|
||
task :default => :spec | ||
task default: :spec |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
# Monday SDK is a client to use monday REST api | ||
module Monday | ||
end | ||
|
||
require 'sdk/client' | ||
require 'sdk/constants/constants' | ||
require 'sdk/monday_api/monday-api-client' | ||
require 'sdk/version' | ||
require 'faraday' | ||
require 'json' | ||
|
||
|
||
require 'sdk/client' | ||
require 'sdk/storage' | ||
require 'sdk/constants/constants' | ||
require 'sdk/monday_api/monday_api_client' | ||
require 'sdk/version' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,46 @@ | ||
# frozen_string_literal: true | ||
|
||
# Monday Client implementation | ||
module Monday | ||
|
||
class MondayClientError < StandardError; end | ||
|
||
class Client | ||
|
||
TOKEN_MISSING_ERROR = "Should send 'token' as an option or call mondaySdk.setToken(TOKEN)".freeze | ||
TOKEN_MISSING_ERROR = "Should send 'token' as an option or call mondaySdk.setToken(TOKEN)" | ||
|
||
def initialize(options = {}) | ||
@token = options[:token] # @type string , Client token provided by monday.com | ||
@api_domain = options[:api] # @type string (optional) monday api domain cna be changed, default defined in constants | ||
@faraday_client = options[:conn] || Faraday.new # dependency injection for testing | ||
@api_domain = options[:api] # @type string (optional) monday api domain can be changed, default defined in constants | ||
@connection = options[:conn] # dependency injection for testing | ||
end | ||
|
||
# Main entry point to the client | ||
def api(query, options = {}) | ||
token = options[:token] || @token | ||
|
||
if token.nil? || token.empty? | ||
raise MondayClientError.new TOKEN_MISSING_ERROR.to_s | ||
end | ||
raise(MondayClientError, TOKEN_MISSING_ERROR) if token.nil? || token.empty? | ||
|
||
params = {} | ||
params[:query] = query | ||
params[:variables] = options[:variables] || {} | ||
|
||
options[:api_domain] = @api_domain || MONDAY_API_URL | ||
options[:api_domain] = api_domain | ||
|
||
|
||
MondayApiClient.execute(params, token, @faraday_client, options) | ||
MondayApiClient.execute(params, token, connection, options) | ||
end | ||
|
||
end | ||
private | ||
|
||
end | ||
def api_domain | ||
@api_domain ||= MONDAY_API_URL | ||
end | ||
|
||
def connection | ||
@connection ||= Faraday.new do |client| | ||
client.request :json | ||
|
||
client.response :raise_error | ||
client.response :json | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should parse JSON in the middleware, to avoid doing this by ourselves |
||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
# frozen_string_literal: true | ||
|
||
# Constants | ||
module Monday | ||
MONDAY_PROTOCOL = "https".freeze | ||
MONDAY_DOMAIN = "monday.com".freeze | ||
MONDAY_API_URL = MONDAY_PROTOCOL+"://api."+MONDAY_DOMAIN+"/v2".freeze | ||
MONDAY_OAUTH_URL = MONDAY_PROTOCOL+"://auth."+MONDAY_DOMAIN+"/oauth2/authorize".freeze | ||
MONDAY_OAUTH_TOKEN_URL = MONDAY_PROTOCOL+"://auth."+MONDAY_DOMAIN+"/oauth2/token".freeze | ||
MONDAY_PROTOCOL = 'https' | ||
MONDAY_DOMAIN = 'monday.com' | ||
MONDAY_API_URL = "#{MONDAY_PROTOCOL}://api.#{MONDAY_DOMAIN}/v2".freeze | ||
MONDAY_OAUTH_URL = "#{MONDAY_PROTOCOL}://auth.#{MONDAY_DOMAIN}/oauth2/authorize".freeze | ||
MONDAY_OAUTH_TOKEN_URL = "#{MONDAY_PROTOCOL}://auth.#{MONDAY_DOMAIN}/oauth2/token".freeze | ||
MONDAY_STORAGE_URL = "#{MONDAY_PROTOCOL}://apps-storage.#{MONDAY_DOMAIN}/app_storage_api/v2".freeze | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is the new API endpoint |
||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need the file in repo?