diff --git a/gems/asana/.rubocop.yml b/gems/asana/.rubocop.yml new file mode 100644 index 00000000..7d0be8ff --- /dev/null +++ b/gems/asana/.rubocop.yml @@ -0,0 +1,19 @@ +# This configuration inherits from /.rubocop.yml. +# You can configure RBS style of this gem. +# This file is used on CI. It is configured to automatically +# make rubocop suggestions on pull requests for this gem. +# If you do not like the style enforcement, you should remove this file. +inherit_from: ../../.rubocop.yml + +## +# If you want to customize the style, please consult with the gem reviewers. +# You can see the list of cops at https://github.com/ksss/rubocop-on-rbs/blob/main/docs/modules/ROOT/pages/cops.adoc + +RBS/Layout: + Enabled: true + +RBS/Lint: + Enabled: true + +RBS/Style: + Enabled: true diff --git a/gems/asana/0.10/_test/metadata.yaml b/gems/asana/0.10/_test/metadata.yaml new file mode 100644 index 00000000..29015bc0 --- /dev/null +++ b/gems/asana/0.10/_test/metadata.yaml @@ -0,0 +1,4 @@ +# If the test needs gem's RBS files, declare them here. +# +# additional_gems: +# - GEM_NAME diff --git a/gems/asana/0.10/_test/test.rb b/gems/asana/0.10/_test/test.rb new file mode 100644 index 00000000..ce3944e4 --- /dev/null +++ b/gems/asana/0.10/_test/test.rb @@ -0,0 +1,79 @@ +require "asana" + +client = Asana::Client.new do |c| + c.authentication :access_token, "personal-access-token" + c.default_headers "asana-enable" => "new_user_task_lists" +end + +workspace = client.workspaces.find_all.first +workspace_gid = workspace&.gid || "1" +workspace&.name&.upcase + +me = client.users.me +me.gid.length + +project = client.projects.find_by_id("2", options: { fields: ["name", "due_date"] }) +project.due_date&.length +client.projects.find_all(workspace: workspace_gid, archived: false).map(&:gid) + +sections = client.sections.get_sections_for_project(project_gid: project.gid) +sections.each do |section| + section.name&.strip + client.tasks.get_tasks(section: section.gid, per_page: 100, options: { fields: ["name", "completed"] }).each do |task| + task.completed + end +end + +task = client.tasks.find_by_id("3") +task.name&.strip +task.assignee&.fetch("gid") +task.memberships&.each { |membership| membership["section"] } +task.custom_fields&.size +task.subtasks(per_page: 50).each { |subtask| subtask.gid } +task.dependencies.to_a.size +task.stories.each { |story| story.created_at } +task.tags.map(&:name) +task.projects(per_page: 10).first&.gid +task.dependents.size +task.start_at&.length +task.assignee_section&.gid +task.assignee_section&.name&.upcase +task.permalink_url.length +task.add_project(project: project.gid, section: sections.first&.gid) +project.completed_by&.gid +project.tasks(per_page: 50, options: { fields: ["name"] }).first&.name +Asana::Resources::Task.find_by_tag(client, tag: "6").to_a +client.portfolios.find_by_id("5").custom_field_settings.map(&:is_important) +task.update(completed: true).completed +task.attach(filename: "notes.txt", mime: "text/plain", io: StringIO.new("hello")).name + +new_task = Asana::Resources::Task.create(client, workspace: workspace_gid, name: "Write RBS") +client.tasks.update_task(task_gid: new_task.gid, name: "Write more RBS") +client.tasks.add_project_for_task(task_gid: new_task.gid, project: project.gid) +client.sections.add_task_for_section(section_gid: "4", task: new_task.gid) +client.tasks.get_subtasks_for_task(task_gid: new_task.gid).first&.gid +client.tasks.search_tasks_for_workspace(workspace_gid: workspace_gid, text: "RBS", completed: false).to_a + +tags = client.tags.get_tags_for_workspace(workspace_gid: workspace_gid) +tags.select { |tag| tag.name == "urgent" }.each { |tag| tag.get_tasks_with_tag.size } + +list = client.user_task_lists.get_user_task_list_for_user(user_gid: "me", workspace: workspace_gid) +client.tasks.find_all(user_task_list: list.gid, completed_since: "now").next_page + +portfolio = client.portfolios.find_by_id("5") +client.portfolios.get_items_for_portfolio(portfolio_gid: portfolio.gid).map(&:name) + +client.custom_fields.get_custom_fields_for_workspace(workspace_gid: workspace_gid).map(&:type) +client.attachments.find_by_task(task: new_task.gid).each { |attachment| attachment.view_url } +client.webhooks.get_all(workspace: workspace_gid).each { |webhook| webhook.active } + +response = client.get("/users/me") +response.body["data"] + +begin + client.tasks.find_by_id("missing") +rescue Asana::Errors::NotFound => e + e.response&.status +rescue Asana::Errors::RateLimitEnforced => e + e.retry_after_seconds + 1 +end diff --git a/gems/asana/0.10/asana.rbs b/gems/asana/0.10/asana.rbs new file mode 100644 index 00000000..723df580 --- /dev/null +++ b/gems/asana/0.10/asana.rbs @@ -0,0 +1,708 @@ +module Asana + VERSION: String + + # Asana::Client#tasks, #projects, etc. are defined with define_method over + # Resources::Registry and return a ResourceProxy, which forwards every call + # to the resource class's singleton method with the HTTP client prepended. + # Each interface below is that resource's singleton API minus the leading + # client argument. + class Client + class Configuration + def initialize: () -> void + def authentication: (:access_token, String value) -> void + | (:oauth2, untyped value) -> void + def faraday_adapter: (Symbol adapter) -> void + def configure_faraday: () { (untyped conn) -> void } -> void + def debug_mode: () -> void + def log_asana_change_warnings: (boolish value) -> void + def default_headers: (Hash[String, String] value) -> void + def to_h: () -> Hash[Symbol, untyped] + end + + class ResourceProxy + def initialize: (client: HttpClient, resource: singleton(Resources::Resource)) -> void + end + + interface _Attachments + def find_by_id: (String id, ?options: Resources::options) -> Resources::Attachment + def find_by_task: (task: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Attachment] + end + + interface _CustomFields + def find_by_id: (String id, ?options: Resources::options) -> Resources::CustomField + def find_by_workspace: (workspace: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Resource] + def get_custom_fields_for_workspace: (workspace_gid: String, ?options: Resources::options) -> Resources::Collection[Resources::CustomField] + end + + interface _Portfolios + def find_by_id: (String id, ?options: Resources::options) -> Resources::Portfolio + def find_all: (workspace: String, owner: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Portfolio] + def get_items_for_portfolio: (portfolio_gid: String, ?options: Resources::options) -> Resources::Collection[Resources::Project] + end + + interface _Projects + def create: (workspace: String, ?team: String?, ?options: Resources::options, **untyped data) -> Resources::Project + def find_by_id: (String id, ?options: Resources::options) -> Resources::Project + def find_all: (?workspace: String?, ?team: String?, ?is_template: bool?, ?archived: bool?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Project] + def find_by_workspace: (workspace: String, ?is_template: bool?, ?archived: bool?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Project] + end + + interface _Sections + def find_by_id: (String id, ?options: Resources::options) -> Resources::Section + def get_sections_for_project: (project_gid: String, ?options: Resources::options) -> Resources::Collection[Resources::Section] + def add_task_for_section: (section_gid: String, ?options: Resources::options, **untyped data) -> untyped + end + + interface _Stories + def find_by_id: (String id, ?options: Resources::options) -> Resources::Story + def find_by_task: (task: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Story] + end + + interface _Tags + def create: (workspace: String, ?options: Resources::options, **untyped data) -> Resources::Tag + def find_by_id: (String id, ?options: Resources::options) -> Resources::Tag + def find_all: (?workspace: String?, ?team: String?, ?archived: bool?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Tag] + def find_by_workspace: (workspace: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Tag] + def get_tags_for_workspace: (workspace_gid: String, ?options: Resources::options) -> Resources::Collection[Resources::Tag] + end + + interface _Tasks + def create: (?workspace: String?, ?options: Resources::options, **untyped data) -> Resources::Task + def find_by_id: (String id, ?options: Resources::options) -> Resources::Task + def find_all: (?assignee: String?, ?workspace: String?, ?project: String?, ?section: String?, ?tag: String?, ?user_task_list: String?, ?completed_since: String?, ?modified_since: String?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Task] + def get_task: (task_gid: String, ?options: Resources::options) -> Resources::Task + def get_tasks: (?assignee: String?, ?project: String?, ?section: String?, ?workspace: String?, ?completed_since: String?, ?per_page: Integer, ?modified_since: String?, ?options: Resources::options) -> Resources::Collection[Resources::Task] + def get_subtasks_for_task: (task_gid: String, ?options: Resources::options) -> Resources::Collection[Resources::Task] + def update_task: (task_gid: String, ?options: Resources::options, **untyped data) -> Resources::Task + def add_project_for_task: (task_gid: String, ?options: Resources::options, **untyped data) -> untyped + def search_tasks_for_workspace: (workspace_gid: String, ?options: Resources::options, **untyped filters) -> Resources::Collection[Resources::Task] + end + + interface _UserTaskLists + def find_by_id: (String id, ?options: Resources::options) -> Resources::UserTaskList + def get_user_task_list_for_user: (user_gid: String, ?workspace: String?, ?options: Resources::options) -> Resources::UserTaskList + end + + interface _Users + def me: (?options: Resources::options) -> Resources::Resource + def find_by_id: (String id, ?options: Resources::options) -> Resources::User + def find_all: (?workspace: String?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::User] + def find_by_workspace: (workspace: String, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::User] + end + + interface _Webhooks + def create: (resource: String, target: String, ?options: Resources::options, **untyped data) -> Resources::Webhook + def create_webhook: (?options: Resources::options, **untyped data) -> Resources::Webhook + def get_all: (workspace: String, ?resource: String?, ?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Webhook] + end + + interface _Workspaces + def find_by_id: (String id, ?options: Resources::options) -> Resources::Workspace + def find_all: (?per_page: Integer, ?options: Resources::options) -> Resources::Collection[Resources::Workspace] + end + + def initialize: () { (Configuration config) -> void } -> void + + def get: (String url, **untyped args) -> HttpClient::Response + def post: (String url, **untyped args) -> HttpClient::Response + def put: (String url, **untyped args) -> HttpClient::Response + def delete: (String url, **untyped args) -> HttpClient::Response + + def attachments: () -> _Attachments + def custom_fields: () -> _CustomFields + def portfolios: () -> _Portfolios + def projects: () -> _Projects + def sections: () -> _Sections + def stories: () -> _Stories + def tags: () -> _Tags + def tasks: () -> _Tasks + def user_task_lists: () -> _UserTaskLists + def users: () -> _Users + def webhooks: () -> _Webhooks + def workspaces: () -> _Workspaces + end + + class HttpClient + class Response + attr_reader faraday_env: untyped + attr_reader status: Integer + attr_reader body: Hash[String, untyped] + attr_reader headers: Hash[String, String] + end + + def get: (String resource_uri, ?params: Hash[Symbol, untyped], ?options: Resources::options) -> Response + def put: (String resource_uri, ?body: Hash[Symbol, untyped], ?options: Resources::options) -> Response + def post: (String resource_uri, ?body: Hash[Symbol, untyped], ?upload: untyped, ?options: Resources::options) -> Response + def delete: (String resource_uri, ?params: Hash[Symbol, untyped], ?options: Resources::options) -> Response + end + + module Errors + class APIError < StandardError + attr_accessor response: HttpClient::Response? + end + + class NotAuthorized < APIError + end + + class PremiumOnly < APIError + end + + class Forbidden < APIError + end + + class NotFound < APIError + end + + class ServerError < APIError + attr_accessor phrase: String + def initialize: (String phrase) -> void + end + + class InvalidRequest < APIError + attr_accessor errors: Array[String] + def initialize: (Array[String] errors) -> void + end + + class RateLimitEnforced < APIError + attr_accessor retry_after_seconds: Integer + def initialize: (Integer retry_after_seconds) -> void + end + end + + module Resources + # The request I/O options every endpoint accepts, e.g. + # { fields: ['name'], expand: ['projects'], pretty: true }. + type options = Hash[Symbol, untyped] + + # Resource class methods take the client they send requests through: + # an Asana::HttpClient when reached through Asana::Client's proxies, or an + # Asana::Client when called directly (it answers the same verbs). + type client = Asana::Client | Asana::HttpClient + + # A nested object in compact form that Resource#method_missing wraps in + # a plain Resource, which answers each of its fields by method_missing. + interface _CompactResource + def gid: () -> String + def name: () -> String + def resource_type: () -> String + end + + # Resource attributes are nil when the request's `fields` option leaves + # them out. Those are declared `implicitly-returns-nil`; attributes the + # API itself can return as null (e.g. Task#due_on) are optional types. + # References to other objects arrive in compact form ({ "gid" =>, + # "name" =>, "resource_type" => }), so they are Hash[String, String]. + + module ResponseHelper + def parse: (HttpClient::Response response) -> [untyped, Hash[String, untyped]] + end + + class Resource + include ResponseHelper + extend ResponseHelper + + def initialize: (Hash[String, untyped] data, client: client) -> void + # Every Asana object carries a gid, including the plain Resources that + # nested objects and some endpoints (e.g. Users.me) are wrapped in. + def gid: () -> String + def refresh: () -> self + def to_h: () -> Hash[String, untyped] + + private + + def client: () -> client + def refresh_with: (Hash[String, untyped] data) -> self + end + + class Collection[T] + include Enumerable[T] + include ResponseHelper + + attr_reader elements: Array[T] + + def initialize: ([Array[Hash[String, untyped]], Hash[String, untyped]] response, ?type: singleton(Resource), client: client) -> void + def each: () { (T) -> void } -> void + | () -> Enumerator[T, void] + def last: () -> T? + def size: () -> Integer + alias length size + def next_page: () -> Collection[T]? + end + + module AttachmentUploading + # Anything Faraday::FilePart can read the upload from, e.g. a StringIO. + interface _Readable + def read: () -> String? + end + + def attach: (filename: String, mime: String, ?io: _Readable?, ?options: options, **untyped data) -> Attachment + end + + module EventSubscription + def events: (?wait: Integer, ?options: options) -> untyped + end + + # Generated endpoint classes. Each concrete resource below inherits its + # generated API endpoints from one of these. + + class AttachmentsBase < Resource + end + + class CustomFieldSettingsBase < Resource + end + + class CustomFieldsBase < Resource + def self.get_custom_fields_for_workspace: (client client, workspace_gid: String, ?options: options) -> Collection[CustomField] + end + + class PortfoliosBase < Resource + def self.get_items_for_portfolio: (client client, portfolio_gid: String, ?options: options) -> Collection[Project] + end + + class ProjectsBase < Resource + end + + class SectionsBase < Resource + def self.get_sections_for_project: (client client, project_gid: String, ?options: options) -> Collection[Section] + def self.add_task_for_section: (client client, section_gid: String, ?options: options, **untyped data) -> untyped + end + + class StoriesBase < Resource + end + + class TagsBase < Resource + def self.get_tags_for_workspace: (client client, workspace_gid: String, ?options: options) -> Collection[Tag] + end + + class TasksBase < Resource + def self.get_task: (client client, task_gid: String, ?options: options) -> Task + def self.get_tasks: (client client, ?assignee: String?, ?project: String?, ?section: String?, ?workspace: String?, ?completed_since: String?, ?per_page: Integer, ?modified_since: String?, ?options: options) -> Collection[Task] + def self.get_subtasks_for_task: (client client, task_gid: String, ?options: options) -> Collection[Task] + def self.update_task: (client client, task_gid: String, ?options: options, **untyped data) -> Task + def self.add_project_for_task: (client client, task_gid: String, ?options: options, **untyped data) -> untyped + def self.search_tasks_for_workspace: (client client, workspace_gid: String, ?options: options, **untyped filters) -> Collection[Task] + end + + class UsersBase < Resource + end + + class UserTaskListsBase < Resource + def self.get_user_task_list_for_user: (client client, user_gid: String, ?workspace: String?, ?options: options) -> UserTaskList + end + + class WebhooksBase < Resource + def self.create_webhook: (client client, ?options: options, **untyped data) -> Webhook + end + + class WorkspacesBase < Resource + end + + class Attachment < AttachmentsBase + attr_reader gid: String + attr_reader resource_type: String + def created_at: %a{implicitly-returns-nil} () -> String + attr_reader download_url: String? + attr_reader host: String? + def name: %a{implicitly-returns-nil} () -> String + attr_reader parent: Hash[String, String]? + attr_reader view_url: String? + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def permanent_url: () -> String? + def size: () -> Integer + def connected_to_app: () -> bool + + def self.find_by_id: (client client, String id, ?options: options) -> Attachment + def self.find_by_task: (client client, task: String, ?per_page: Integer, ?options: options) -> Collection[Attachment] + end + + class CustomFieldSetting < CustomFieldSettingsBase + attr_reader gid: String + def resource_type: %a{implicitly-returns-nil} () -> String + def created_at: %a{implicitly-returns-nil} () -> String + def is_important: %a{implicitly-returns-nil} () -> bool + def parent: %a{implicitly-returns-nil} () -> Hash[String, String] + def project: %a{implicitly-returns-nil} () -> Hash[String, String] + def custom_field: %a{implicitly-returns-nil} () -> Hash[String, untyped] + end + + class CustomField < CustomFieldsBase + attr_reader gid: String + attr_reader resource_type: String + def resource_subtype: %a{implicitly-returns-nil} () -> String + def name: %a{implicitly-returns-nil} () -> String + attr_reader description: String? + def type: %a{implicitly-returns-nil} () -> String + attr_reader enum_options: Array[Hash[String, untyped]]? + attr_reader precision: Integer? + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def enabled: () -> bool + def representation_type: () -> String + def id_prefix: () -> String? + def input_restrictions: () -> Array[String] + def is_formula_field: () -> bool + def is_lookup_field: () -> bool + def date_value: () -> Resource? + def enum_value: () -> Resource? + def multi_enum_values: () -> Array[Resource] + def number_value: () -> Numeric? + def text_value: () -> String? + def display_value: () -> String? + def format: () -> String + def currency_code: () -> String? + def custom_label: () -> String? + def custom_label_position: () -> String? + def is_global_to_workspace: () -> bool + def has_notifications_enabled: () -> bool + def asana_created_field: () -> String? + def is_value_read_only: () -> bool + def created_by: () -> Resource? + def people_value: () -> Array[Resource] + def reference_value: () -> Array[Resource] + def html_text_value: () -> String? + def privacy_setting: () -> String + def default_access_level: () -> String + + def self.find_by_id: (client client, String id, ?options: options) -> CustomField + # Wraps its elements as plain Resources, not CustomFields. + def self.find_by_workspace: (client client, workspace: String, ?per_page: Integer, ?options: options) -> Collection[Resource] + def update: (?options: options, **untyped data) -> CustomField + end + + class Portfolio < PortfoliosBase + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + def owner: %a{implicitly-returns-nil} () -> Hash[String, String] + def created_at: %a{implicitly-returns-nil} () -> String + attr_reader created_by: Hash[String, String]? + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def resource_subtype: () -> String + def archived: () -> bool + def start_on: () -> String? + def due_on: () -> String? + def default_access_level: () -> String + def public: () -> bool + def current_status_update: () -> Resource? + def custom_fields: () -> Array[Resource] + def permalink_url: () -> String + def privacy_setting: () -> String + def project_templates: () -> Array[Resource] + def custom_type: () -> Resource? + + def custom_field_settings: (?options: options) -> Collection[CustomFieldSetting] + def color: %a{implicitly-returns-nil} () -> String + def workspace: %a{implicitly-returns-nil} () -> Hash[String, String] + def members: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + + def self.find_by_id: (client client, String id, ?options: options) -> Portfolio + def self.find_all: (client client, workspace: String, owner: String, ?per_page: Integer, ?options: options) -> Collection[Portfolio] + def update: (?options: options, **untyped data) -> Portfolio + def get_items: (?options: options) -> Collection[Resource] + end + + class Project < ProjectsBase + include EventSubscription + + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + attr_reader owner: Hash[String, String]? + attr_reader current_status: Hash[String, untyped]? + attr_reader due_date: String? + attr_reader due_on: String? + attr_reader start_on: String? + def created_at: %a{implicitly-returns-nil} () -> String + def modified_at: %a{implicitly-returns-nil} () -> String + def archived: %a{implicitly-returns-nil} () -> bool + def public: %a{implicitly-returns-nil} () -> bool + def members: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + def followers: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + def custom_fields: %a{implicitly-returns-nil} () -> Array[Hash[String, untyped]] + def custom_field_settings: %a{implicitly-returns-nil} () -> Array[Hash[String, untyped]] + attr_reader color: String? + def notes: %a{implicitly-returns-nil} () -> String + def html_notes: %a{implicitly-returns-nil} () -> String + def workspace: %a{implicitly-returns-nil} () -> Hash[String, String] + attr_reader team: Hash[String, String]? + def layout: %a{implicitly-returns-nil} () -> String + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def resource_subtype: () -> String + def icon: () -> String? + def current_status_update: () -> Resource? + def default_view: () -> String + def privacy_setting: () -> String + def default_access_level: () -> String + def minimum_access_level_for_customization: () -> String + def minimum_access_level_for_sharing: () -> String + def completed: () -> bool + def completed_at: () -> String? + def completed_by: () -> Resource? + def permalink_url: () -> String + def project_brief: () -> Resource? + def created_from_template: () -> Resource? + def custom_type: () -> Resource? + + def self.create: (client client, workspace: String, ?team: String?, ?options: options, **untyped data) -> Project + def self.find_by_id: (client client, String id, ?options: options) -> Project + def self.find_all: (client client, ?workspace: String?, ?team: String?, ?is_template: bool?, ?archived: bool?, ?per_page: Integer, ?options: options) -> Collection[Project] + def self.find_by_workspace: (client client, workspace: String, ?is_template: bool?, ?archived: bool?, ?per_page: Integer, ?options: options) -> Collection[Project] + def update: (?options: options, **untyped data) -> Project + def tasks: (?per_page: Integer, ?options: options) -> Collection[Task] + end + + class Section < SectionsBase + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + def project: %a{implicitly-returns-nil} () -> Hash[String, String] + def created_at: %a{implicitly-returns-nil} () -> String + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def projects: () -> Array[Resource] + + def self.find_by_id: (client client, String id, ?options: options) -> Section + def update: (?options: options, **untyped data) -> Section + end + + class Story < StoriesBase + attr_reader gid: String + attr_reader resource_type: String + def resource_subtype: %a{implicitly-returns-nil} () -> String + def created_at: %a{implicitly-returns-nil} () -> String + attr_reader created_by: Hash[String, String]? + def liked: %a{implicitly-returns-nil} () -> bool + def likes: %a{implicitly-returns-nil} () -> Array[Hash[String, untyped]] + def num_likes: %a{implicitly-returns-nil} () -> Integer + def text: %a{implicitly-returns-nil} () -> String + def html_text: %a{implicitly-returns-nil} () -> String + def target: %a{implicitly-returns-nil} () -> Hash[String, String] + def is_pinned: %a{implicitly-returns-nil} () -> bool + def is_edited: %a{implicitly-returns-nil} () -> bool + def source: %a{implicitly-returns-nil} () -> String + def type: %a{implicitly-returns-nil} () -> String + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def sticker_name: () -> String + def is_editable: () -> bool + def hearted: () -> bool + def hearts: () -> Array[Resource] + def num_hearts: () -> Integer + def reaction_summary: () -> Array[Resource] + def previews: () -> Array[Resource] + def old_name: () -> String + def new_name: () -> String? + def old_dates: () -> Resource + def new_dates: () -> Resource + def old_resource_subtype: () -> String + def new_resource_subtype: () -> String + def story: () -> Resource + def assignee: () -> Resource + def follower: () -> Resource + def old_section: () -> Resource + def new_section: () -> Resource + def task: () -> Resource + def project: () -> Resource + def tag: () -> Resource + def custom_field: () -> Resource + def old_text_value: () -> String + def new_text_value: () -> String + def old_number_value: () -> Integer? + def new_number_value: () -> Integer + def old_enum_value: () -> Resource + def new_enum_value: () -> Resource + def old_date_value: () -> Resource + def new_date_value: () -> Resource + def old_people_value: () -> Array[Resource] + def new_people_value: () -> Array[Resource] + def old_multi_enum_values: () -> Array[Resource] + def new_multi_enum_values: () -> Array[Resource] + def new_approval_status: () -> String + def old_approval_status: () -> String + def duplicate_of: () -> Resource + def duplicated_from: () -> Resource + def dependency: () -> Resource + + def self.find_by_id: (client client, String id, ?options: options) -> Story + def self.find_by_task: (client client, task: String, ?per_page: Integer, ?options: options) -> Collection[Story] + def update: (?text: String?, ?html_text: String?, ?is_pinned: bool?, ?options: options, **untyped data) -> Story + end + + class Tag < TagsBase + attr_reader gid: String + attr_reader resource_type: String + def created_at: %a{implicitly-returns-nil} () -> String + def followers: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + def name: %a{implicitly-returns-nil} () -> String + attr_reader color: String? + def workspace: %a{implicitly-returns-nil} () -> Hash[String, String] + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def notes: () -> String + def permalink_url: () -> String + + def self.create: (client client, workspace: String, ?options: options, **untyped data) -> Tag + def self.find_by_id: (client client, String id, ?options: options) -> Tag + def self.find_all: (client client, ?workspace: String?, ?team: String?, ?archived: bool?, ?per_page: Integer, ?options: options) -> Collection[Tag] + def self.find_by_workspace: (client client, workspace: String, ?per_page: Integer, ?options: options) -> Collection[Tag] + def update: (?options: options, **untyped data) -> Tag + def get_tasks_with_tag: (?per_page: Integer, ?options: options) -> Collection[Task] + end + + class Task < TasksBase + include AttachmentUploading + include EventSubscription + + attr_reader gid: String + attr_reader resource_type: String + def resource_subtype: %a{implicitly-returns-nil} () -> String + attr_reader assignee: Hash[String, String]? + attr_reader assignee_status: String? + def created_at: %a{implicitly-returns-nil} () -> String + def completed: %a{implicitly-returns-nil} () -> bool + attr_reader completed_at: String? + def custom_fields: %a{implicitly-returns-nil} () -> Array[Hash[String, untyped]] + attr_reader due_on: String? + attr_reader due_at: String? + attr_reader external: Hash[String, String]? + def followers: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + def is_rendered_as_separator: %a{implicitly-returns-nil} () -> bool + def liked: %a{implicitly-returns-nil} () -> bool + def likes: %a{implicitly-returns-nil} () -> Array[Hash[String, untyped]] + def memberships: %a{implicitly-returns-nil} () -> Array[Hash[String, Hash[String, String]]] + def modified_at: %a{implicitly-returns-nil} () -> String + def name: %a{implicitly-returns-nil} () -> String + def notes: %a{implicitly-returns-nil} () -> String + def html_notes: %a{implicitly-returns-nil} () -> String + def num_likes: %a{implicitly-returns-nil} () -> Integer + def num_subtasks: %a{implicitly-returns-nil} () -> Integer + attr_reader parent: Hash[String, String]? + attr_reader start_on: String? + def workspace: %a{implicitly-returns-nil} () -> Hash[String, String] + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def created_by: () -> Resource + def approval_status: () -> String + def assigned_by: () -> Resource? + def completed_by: () -> Resource? + def hearted: () -> bool + def hearts: () -> Array[Resource] + def has_subtasks_date_mismatch: () -> bool + def num_hearts: () -> Integer + def start_at: () -> String? + def actual_time_minutes: () -> Numeric? + def assignee_section: () -> (Resource & _CompactResource)? + def custom_type: () -> Resource? + def custom_type_status_option: () -> Resource? + def effective_memberships: () -> Array[Resource] + def permalink_url: () -> String + + def self.create: (client client, ?workspace: String?, ?options: options, **untyped data) -> Task + def self.find_by_id: (client client, String id, ?options: options) -> Task + def self.find_all: (client client, ?assignee: String?, ?workspace: String?, ?project: String?, ?section: String?, ?tag: String?, ?user_task_list: String?, ?completed_since: String?, ?modified_since: String?, ?per_page: Integer, ?options: options) -> Collection[Task] + def self.find_by_project: (client client, ?project: String?, ?projectId: String?, ?per_page: Integer, ?options: options) -> Collection[Task] + def self.find_by_tag: (client client, tag: String, ?per_page: Integer, ?options: options) -> Collection[Task] + def self.find_by_section: (client client, section: String, ?per_page: Integer, ?options: options) -> Collection[Task] + + def update: (?options: options, **untyped data) -> Task + # The gem also declares `attr_reader :dependencies`; this method, + # defined later, replaces it and fetches the dependencies from the API. + def dependencies: (?options: options) -> Collection[Task] + def subtasks: (?per_page: Integer, ?options: options) -> Collection[Task] + def stories: (?per_page: Integer, ?options: options) -> Collection[Story] + def dependents: (?options: options) -> Collection[Task] + def projects: (?per_page: Integer, ?options: options) -> Collection[Project] + def tags: (?per_page: Integer, ?options: options) -> Collection[Tag] + def add_project: (project: String, ?insert_after: String?, ?insert_before: String?, ?section: String?, ?options: options, **untyped data) -> bool + end + + class User < UsersBase + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + attr_reader email: String? + attr_reader photo: Hash[String, String]? + def workspaces: %a{implicitly-returns-nil} () -> Array[Hash[String, String]] + + # Wraps the response as a plain Resource, not a User. + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def custom_fields: () -> Array[Resource] + + def self.me: (client client, ?options: options) -> Resource + def self.find_by_id: (client client, String id, ?options: options) -> User + def self.find_all: (client client, ?workspace: String?, ?per_page: Integer, ?options: options) -> Collection[User] + def self.find_by_workspace: (client client, workspace: String, ?per_page: Integer, ?options: options) -> Collection[User] + end + + class UserTaskList < UserTaskListsBase + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + def owner: %a{implicitly-returns-nil} () -> Hash[String, String] + def workspace: %a{implicitly-returns-nil} () -> Hash[String, String] + + def self.find_by_id: (client client, String id, ?options: options) -> UserTaskList + end + + class Webhook < WebhooksBase + attr_reader gid: String + attr_reader resource_type: String + def resource: %a{implicitly-returns-nil} () -> Hash[String, String] + def target: %a{implicitly-returns-nil} () -> String + def active: %a{implicitly-returns-nil} () -> bool + def created_at: %a{implicitly-returns-nil} () -> String + attr_reader last_success_at: String? + attr_reader last_failure_at: String? + attr_reader last_failure_content: String? + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def delivery_retry_count: () -> Integer + def next_attempt_after: () -> String + def failure_deletion_timestamp: () -> String + def filters: () -> Array[Resource] + + def self.create: (client client, resource: String, target: String, ?options: options, **untyped data) -> Webhook + def self.get_all: (client client, workspace: String, ?resource: String?, ?per_page: Integer, ?options: options) -> Collection[Webhook] + end + + class Workspace < WorkspacesBase + attr_reader gid: String + attr_reader resource_type: String + def name: %a{implicitly-returns-nil} () -> String + def is_organization: %a{implicitly-returns-nil} () -> bool + + # Fields the gem answers only through Resource#method_missing, which + # wraps nested objects in a plain Resource and raises NoMethodError + # unless the request's fields option included the field. + def email_domains: () -> Array[String] + + def self.find_by_id: (client client, String id, ?options: options) -> Workspace + def self.find_all: (client client, ?per_page: Integer, ?options: options) -> Collection[Workspace] + def update: (?options: options, **untyped data) -> Workspace + end + end +end diff --git a/gems/asana/_reviewers.yaml b/gems/asana/_reviewers.yaml new file mode 100644 index 00000000..8d710c45 --- /dev/null +++ b/gems/asana/_reviewers.yaml @@ -0,0 +1,2 @@ +reviewers: + - apiology