checkoff 0.270.0 → 0.272.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 032663b4218d38868008e9e90b82a54e31698a3710fb79e54756371a42883b86
4
- data.tar.gz: 6a736e72e0ef3a7787897222a17e144c985ff458536ffc3f21983a328d3a36ec
3
+ metadata.gz: 1ee9be06d36d312ccf07f7ae6a482d74384b266d2df302c54bc387c32236050e
4
+ data.tar.gz: 8bc105aba595c6f58cf764691cf292da9fbfca7ffbd39d845ac87aa7e159c0d4
5
5
  SHA512:
6
- metadata.gz: 1ff16973c80d26b71e949b6e7678080312d3357e5cb9fdb24c1a9da80bc75d3c40662c4c89908bcf47485fe1ca0f3249f15a767bd2a02fe70becf26a34a6113f
7
- data.tar.gz: 9b8adc4d23bfa6f44f44d1c2ec4a03cc64fb89b749fc9dd53d6fce225a5c0ec36afb3425efa5eac76a4f30b2737666a59f3fed013a5ca08c4cd3332fbd829ce0
6
+ metadata.gz: 6e53fa173069fe709a8fc86463820ed785265b447e29a853992b3622de12e2584f9b62b22560f11e54a50f1df831c96d1aebdcd369b7c24899d515dce2f39b07
7
+ data.tar.gz: c5cc8297668e6c32aea00a7b1b0c6ae427abef6f73c14427e0b3673e88e97e07d37d43037d43f3de96e16c376ff7999fae92446801de7e92de1c1b26d2bc0921
@@ -82,7 +82,10 @@ module Checkoff
82
82
  # @param uri [URI::Generic]
83
83
  # @param verify_mode [Integer] - e.g., OpenSSL::SSL::VERIFY_NONE,OpenSSL::SSL::VERIFY_PEER
84
84
  #
85
- # @return [Object]
85
+ # @yieldparam tempfile [File]
86
+ # @yieldreturn [Asana::Resources::Attachment, nil]
87
+ #
88
+ # @return [Asana::Resources::Attachment, nil]
86
89
  def download_uri(uri, verify_mode: OpenSSL::SSL::VERIFY_PEER, &block)
87
90
  out = nil
88
91
  host = uri.host || raise("URI has no host: #{uri}")
@@ -101,7 +104,7 @@ module Checkoff
101
104
 
102
105
  # @param response [#read_body]
103
106
  #
104
- # @yields [IO]
107
+ # @yieldparam tempfile [File]
105
108
  #
106
109
  # @return [void]
107
110
  def write_tempfile_from_response(response)
@@ -128,7 +131,7 @@ module Checkoff
128
131
  uri = URI(url)
129
132
  # @type [String]
130
133
  resolved_attachment_name = attachment_name || File.basename(uri.path || '')
131
- download_uri(uri, verify_mode:) do |tempfile|
134
+ attachment = download_uri(uri, verify_mode:) do |tempfile|
132
135
  content_type = content_type_from_filename(resolved_attachment_name)
133
136
  content_type ||= content_type_from_filename(uri.path || '')
134
137
  # neither the attachment name nor the URL's path has a MIME-recognizable extension
@@ -137,6 +140,7 @@ module Checkoff
137
140
  resource.attach(filename: resolved_attachment_name, mime: content_type,
138
141
  io: tempfile)
139
142
  end
143
+ attachment || raise("No attachment created from #{url}")
140
144
  end
141
145
 
142
146
  # @param url [String]
@@ -152,8 +156,8 @@ module Checkoff
152
156
  'name' => attachment_name,
153
157
  }
154
158
  options = {}
155
- Asana::Resources::Resource.new(parse(client.post('/attachments', body: with_params, options:)).first,
156
- client:)
159
+ Asana::Resources::Attachment.new(parse(client.post('/attachments', body: with_params, options:)).first,
160
+ client:)
157
161
  end
158
162
 
159
163
  # @param filename [String]
data/lib/checkoff/cli.rb CHANGED
@@ -185,7 +185,7 @@ module Checkoff
185
185
  @tasks = tasks
186
186
  end
187
187
 
188
- # @return [void]
188
+ # @return [String]
189
189
  def run
190
190
  if section_name.nil?
191
191
  run_on_project(workspace_name, project_name)
@@ -88,10 +88,12 @@ module Checkoff
88
88
  # @param gid [String]
89
89
  # @param resource_type [String,nil]
90
90
  #
91
- # @return [Array([String, nil], [String, nil])]
91
+ # @return [Array(String, String), Array(nil, String), Array(nil, nil)]
92
92
  def enrich_gid(gid, resource_type: nil)
93
93
  resource, resource_type = resources.resource_by_gid(gid, resource_type:)
94
- [resource&.name, resource_type]
94
+ return [nil, nil] if resource.nil? || resource_type.nil?
95
+
96
+ [resource.name, resource_type]
95
97
  end
96
98
 
97
99
  # @param filter [Hash{String => String, Array<String>}]
@@ -19,7 +19,7 @@ module Checkoff
19
19
  end
20
20
 
21
21
  # @param key [Symbol]
22
- # @return [Object]
22
+ # @return [Object, nil]
23
23
  def [](key)
24
24
  config_value = @config[key]
25
25
  return config_value unless config_value.nil?
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'checkoff/custom_fields'
@@ -50,6 +50,16 @@ module Checkoff
50
50
  Time.parse(time_str)
51
51
  end
52
52
 
53
+ # @param project [Asana::Resources::Project]
54
+ # @param field_spec [Array] [:custom_field, custom field name]
55
+ #
56
+ # @return [Time, Date, nil]
57
+ def custom_field_by_spec(project, field_spec)
58
+ raise "Teach me how to handle field #{field_spec.inspect}" unless field_spec.length == 2
59
+
60
+ custom_field(project, field_spec.fetch(1))
61
+ end
62
+
53
63
  # @param project [Asana::Resources::Project]
54
64
  # @param field_name [Symbol,Array]
55
65
  #
@@ -64,9 +74,8 @@ module Checkoff
64
74
  if field_name.is_a?(Array)
65
75
  # @type [Symbol]
66
76
  actual_field_name = field_name.first
67
- args = field_name[1..]
68
77
 
69
- return custom_field(project, *args) if actual_field_name == :custom_field
78
+ return custom_field_by_spec(project, field_name) if actual_field_name == :custom_field
70
79
  end
71
80
 
72
81
  raise "Teach me how to handle field #{field_name.inspect}"
@@ -184,7 +184,7 @@ module Checkoff
184
184
 
185
185
  # custom_field_#{gid}.variant = 'is'
186
186
  class Is < CustomFieldVariant
187
- # @return [Array(Hash{String => String}, Array<Array<String>, String, Array>)]
187
+ # @return [Array(Hash{String => String}, Array<Array<String>, String, Array, Symbol>)]
188
188
  def convert
189
189
  selected_options = fetch_solo_param("custom_field_#{gid}.selected_options").split('~')
190
190
 
@@ -17,7 +17,7 @@ module Checkoff
17
17
  end
18
18
 
19
19
  # @param task_selectors [Array<Array<Symbol, Array>>]
20
- # @return [Symbol, Array, Array(Symbol, Array, Array)]
20
+ # @return [Array<Symbol, Array>, Array(Symbol, Array, Array)]
21
21
  def self.merge_task_selectors(*task_selectors)
22
22
  return [] if task_selectors.empty?
23
23
 
@@ -8,7 +8,7 @@ module Checkoff
8
8
  module Common
9
9
  # Base class to evaluate a project selector function given fully evaluated arguments
10
10
  class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
11
- # @param selector [Array<Symbol, Array>, Symbol]
11
+ # @param selector [Array<Symbol, Array>, Symbol, String]
12
12
  # @param custom_fields [Checkoff::CustomFields]
13
13
  # @param _kwargs [Hash]
14
14
  def initialize(selector:, custom_fields:, **_kwargs)
@@ -22,7 +22,7 @@ module Checkoff
22
22
 
23
23
  private
24
24
 
25
- # @return [Array<Symbol, Array>, Symbol]
25
+ # @return [Array<Symbol, Array>, Symbol, String]
26
26
  attr_reader :selector
27
27
  end
28
28
  end
@@ -108,7 +108,12 @@ module Checkoff
108
108
  custom_field = custom_fields.resource_custom_field_by_name(resource, custom_field_name)
109
109
  return nil if custom_field.nil?
110
110
 
111
- custom_field['display_value']
111
+ display_value = custom_field['display_value']
112
+ unless display_value.nil? || display_value.is_a?(String)
113
+ raise "Expected display_value to be a String or nil, got #{display_value.class}"
114
+ end
115
+
116
+ display_value
112
117
  end
113
118
  end
114
119
 
@@ -224,7 +229,7 @@ module Checkoff
224
229
  # @param prefix [String]
225
230
  # @return [boolish]
226
231
  def evaluate(resource, prefix)
227
- resource.name&.start_with?(prefix)
232
+ resource.name.start_with?(prefix)
228
233
  end
229
234
  end
230
235
 
@@ -30,16 +30,16 @@ module Checkoff
30
30
  raise 'Override me!'
31
31
  end
32
32
 
33
- # @param _task [Asana::Resources::Task]
33
+ # @param _resource [Asana::Resources::Resource]
34
34
  # @param _args [Array<Object>]
35
35
  # @return [Object]
36
- def evaluate(_task, *_args)
36
+ def evaluate(_resource, *_args)
37
37
  raise 'Implement me!'
38
38
  end
39
39
 
40
40
  private
41
41
 
42
- # @param object [Array<Symbol, Array>, Symbol]
42
+ # @param object [Array<Symbol, Array>, Symbol, String]
43
43
  # @param fn_name [Symbol]
44
44
  # @return [Boolean]
45
45
  def fn?(object, fn_name)
@@ -8,7 +8,7 @@ module Checkoff
8
8
  module Project
9
9
  # Base class to evaluate a project selector function given fully evaluated arguments
10
10
  class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
11
- # @param selector [Array<Symbol, Array>, Symbol]
11
+ # @param selector [Array<Symbol, Array>, Symbol, String]
12
12
  # @param projects [Checkoff::Projects]
13
13
  # @param portfolios [Checkoff::Portfolios]
14
14
  # @param workspaces [Checkoff::Workspaces]
@@ -36,7 +36,7 @@ module Checkoff
36
36
 
37
37
  private
38
38
 
39
- # @return [Array<Symbol, Array>, Symbol]
39
+ # @return [Array<Symbol, Array>, Symbol, String]
40
40
  attr_reader :selector
41
41
  end
42
42
  end
@@ -8,7 +8,7 @@ module Checkoff
8
8
  module Section
9
9
  # Base class to evaluate a project selector function given fully evaluated arguments
10
10
  class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
11
- # @param selector [Array<Symbol, Array>, Symbol]
11
+ # @param selector [Array<Symbol, Array>, Symbol, String]
12
12
  # @param client [Asana::Client]
13
13
  # @param sections [Checkoff::Sections]
14
14
  # @param kwargs [Hash]
@@ -30,7 +30,7 @@ module Checkoff
30
30
 
31
31
  private
32
32
 
33
- # @return [Array<Symbol, Array>, Symbol]
33
+ # @return [Array<Symbol, Array>, Symbol, String]
34
34
  attr_reader :selector
35
35
  end
36
36
  end
@@ -8,7 +8,7 @@ module Checkoff
8
8
  module Task
9
9
  # Base class to evaluate a task selector function given fully evaluated arguments
10
10
  class FunctionEvaluator < ::Checkoff::SelectorClasses::FunctionEvaluator
11
- # @param selector [Array<Symbol, Array>, Symbol]
11
+ # @param selector [Array<Symbol, Array>, Symbol, String]
12
12
  # @param tasks [Checkoff::Tasks]
13
13
  # @param timelines [Checkoff::Timelines]
14
14
  # @param custom_fields [Checkoff::CustomFields]
@@ -36,7 +36,7 @@ module Checkoff
36
36
 
37
37
  private
38
38
 
39
- # @return [Array<Symbol, Array>, Symbol]
39
+ # @return [Array<Symbol, Array>, Symbol, String]
40
40
  attr_reader :selector
41
41
  end
42
42
  end
@@ -254,10 +254,7 @@ module Checkoff
254
254
  # @param story [Asana::Resources::Story]
255
255
  # @return [Time]
256
256
  def created_time(story)
257
- created_at = story.created_at
258
- raise "Story #{story.gid} has no created_at" if created_at.nil?
259
-
260
- Time.parse(created_at)
257
+ Time.parse(story.created_at)
261
258
  end
262
259
  end
263
260
 
@@ -45,8 +45,8 @@ module Checkoff
45
45
  task_hash['unwrapped']['custom_fields'] = unwrapped_custom_fields
46
46
  end
47
47
 
48
- # @param [Hash{String => String, Hash, Array}] task_hash
49
- # @param [Array<Hash>] memberships
48
+ # @param task_hash [Hash{String => Object}]
49
+ # @param memberships [Array<Hash>]
50
50
  #
51
51
  # @return [void]
52
52
  def add_user_task_list(task_hash, memberships)
@@ -63,7 +63,7 @@ module Checkoff
63
63
  }
64
64
  end
65
65
 
66
- # @param task_hash [Hash{String => String, Hash, Array}]
66
+ # @param task_hash [Hash{String => Object}]
67
67
  # @return [Hash{String => Object}]
68
68
  def assignee_hash(task_hash)
69
69
  assignee = task_hash.fetch('assignee')
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Checkoff
@@ -71,6 +71,16 @@ module Checkoff
71
71
  Time.parse(time_str)
72
72
  end
73
73
 
74
+ # @param task [Asana::Resources::Task]
75
+ # @param field_spec [Array] [:custom_field, custom field name]
76
+ #
77
+ # @return [Time, Date, nil]
78
+ def custom_field_by_spec(task, field_spec)
79
+ raise "Teach me how to handle field #{field_spec.inspect}" unless field_spec.length == 2
80
+
81
+ custom_field(task, field_spec.fetch(1))
82
+ end
83
+
74
84
  # @param task [Asana::Resources::Task]
75
85
  # @param field_name [Symbol,Array]
76
86
  #
@@ -87,9 +97,8 @@ module Checkoff
87
97
  if field_name.is_a?(Array)
88
98
  # @type [Symbol]
89
99
  actual_field_name = field_name.first
90
- args = field_name[1..]
91
100
 
92
- return custom_field(task, *args) if actual_field_name == :custom_field
101
+ return custom_field_by_spec(task, field_name) if actual_field_name == :custom_field
93
102
  end
94
103
 
95
104
  raise "Teach me how to handle field #{field_name.inspect}"
@@ -57,7 +57,9 @@ module Checkoff
57
57
  # @param gid [String]
58
58
  # @param resource_type [String,nil]
59
59
  #
60
- # @return [Array([Asana::Resource, nil], [String,nil])]
60
+ # @return [Array(Asana::Resources::Task, String),
61
+ # Array(Asana::Resources::Section, String),
62
+ # Array(Asana::Resources::Project, String), Array(nil, nil)]
61
63
  def resource_by_gid(gid, resource_type: nil)
62
64
  %w[task section project].each do |resource_type_to_try|
63
65
  next unless [resource_type_to_try, nil].include?(resource_type)
@@ -73,7 +75,8 @@ module Checkoff
73
75
  # @param resource_type [String]
74
76
  # @param gid [String]
75
77
  #
76
- # @return [Asana::Resources::Resource, nil]
78
+ # @return [Asana::Resources::Task, Asana::Resources::Section,
79
+ # Asana::Resources::Project, nil]
77
80
  def fetch_gid_by_type(resource_type, gid)
78
81
  case resource_type
79
82
  when 'task' then fetch_task_gid(gid)
@@ -106,7 +106,7 @@ module Checkoff
106
106
  # @param by_section [Hash]
107
107
  # @param task [Asana::Resources::Task]
108
108
  #
109
- # @return [Array(String, Hash)]
109
+ # @return [Array(String, Hash), Array(nil, Hash)]
110
110
  def file_task_by_section(current_section, by_section, task)
111
111
  if subtask_section?(task)
112
112
  current_section = task.name
@@ -93,9 +93,9 @@ module Checkoff
93
93
 
94
94
  next true if last_milestone.gid == task.gid
95
95
 
96
- all_dependent_task_gids ||= @tasks.all_dependent_tasks(task).map(&:gid)
96
+ dependent_task_gids = all_dependent_task_gids ||= @tasks.all_dependent_tasks(task).map(&:gid)
97
97
 
98
- all_dependent_task_gids.include? last_milestone.gid
98
+ dependent_task_gids.include? last_milestone.gid
99
99
  end
100
100
  end
101
101
 
@@ -121,14 +121,14 @@ module Checkoff
121
121
 
122
122
  # do this once, but lazily, so we don't have to do it if all
123
123
  # projects are excluded
124
- all_dependent_milestones ||=
124
+ dependent_milestones = all_dependent_milestones ||=
125
125
  @tasks.all_dependent_tasks(task,
126
126
  extra_task_fields: ['resource_subtype',
127
127
  'memberships.project.gid']).select do |dependent_task|
128
128
  dependent_task.resource_subtype == 'milestone'
129
129
  end
130
130
 
131
- all_dependent_milestones.any? do |milestone|
131
+ dependent_milestones.any? do |milestone|
132
132
  memberships.memberships_or_raise(milestone).any? do |milestone_membership_data|
133
133
  milestone_membership_data.fetch('project').fetch('gid') == project_gid
134
134
  end
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # typed: false
2
+ # typed: true
3
3
 
4
4
  # frozen_string_literal: true
5
5
 
@@ -51,12 +51,7 @@ module Checkoff
51
51
 
52
52
  return now_or_before?(date_or_time) if period == :now_or_before
53
53
 
54
- if period.is_a?(Array)
55
- period_name = T.cast(period.first, Symbol)
56
- args = period[1..]
57
-
58
- return compound_in_period?(date_or_time, period_name, *args)
59
- end
54
+ return compound_in_period?(date_or_time, period) if period.is_a?(Array)
60
55
 
61
56
  raise "Teach me how to handle period #{period.inspect}"
62
57
  end
@@ -204,24 +199,53 @@ module Checkoff
204
199
  end
205
200
 
206
201
  # @param date_or_time [Date,Time,nil]
207
- # @param period_name [Symbol]
208
- # @param args [Array<Object>]
209
- def compound_in_period?(date_or_time, period_name, *args)
210
- return less_than_n_days_ago?(date_or_time, *args) if period_name == :less_than_n_days_ago
202
+ # @param period [Array<Symbol, Integer, nil>] period name, then its arguments
203
+ def compound_in_period?(date_or_time, period)
204
+ period_name = period.first
205
+ args = period.drop(1)
206
+
207
+ num_days = args.first
208
+ if args.length == 1 && num_days.is_a?(Integer)
209
+ return single_num_days_in_period?(date_or_time, period_name, num_days)
210
+ end
211
+
212
+ if period_name == :between_relative_days && args.length == 2
213
+ return between_relative_days?(date_or_time,
214
+ optional_num_days(period, args.fetch(0)),
215
+ optional_num_days(period, args.fetch(1)))
216
+ end
211
217
 
212
- return less_than_n_days_from_now?(date_or_time, *args) if period_name == :less_than_n_days_from_now
218
+ raise "Teach me how to handle period #{period.inspect}"
219
+ end
220
+
221
+ # @param period [Array<Symbol, Integer, nil>] period the argument came from
222
+ # @param arg [Symbol, Integer, nil]
223
+ #
224
+ # @return [Integer, nil]
225
+ def optional_num_days(period, arg)
226
+ return nil if arg.nil?
227
+ return arg if arg.is_a?(Integer)
228
+
229
+ raise "Teach me how to handle period #{period.inspect}"
230
+ end
231
+
232
+ # @param date_or_time [Date,Time,nil]
233
+ # @param period_name [Symbol, Integer, nil]
234
+ # @param num_days [Integer]
235
+ def single_num_days_in_period?(date_or_time, period_name, num_days)
236
+ return less_than_n_days_ago?(date_or_time, num_days) if period_name == :less_than_n_days_ago
237
+
238
+ return less_than_n_days_from_now?(date_or_time, num_days) if period_name == :less_than_n_days_from_now
213
239
 
214
240
  if period_name == :greater_than_or_equal_to_n_days_from_now
215
- return greater_than_or_equal_to_n_days_from_now?(date_or_time, *args)
241
+ return greater_than_or_equal_to_n_days_from_now?(date_or_time, num_days)
216
242
  end
217
243
 
218
244
  if period_name == :greater_than_or_equal_to_n_days_from_today
219
- return greater_than_or_equal_to_n_days_from_today?(date_or_time, *args)
245
+ return greater_than_or_equal_to_n_days_from_today?(date_or_time, num_days)
220
246
  end
221
247
 
222
- return between_relative_days?(date_or_time, *args) if period_name == :between_relative_days
223
-
224
- raise "Teach me how to handle period [#{period_name.inspect}, #{args.map(&:inspect).join(', ')}]"
248
+ raise "Teach me how to handle period [#{period_name.inspect}, #{num_days.inspect}]"
225
249
  end
226
250
 
227
251
  # bundle exec ./time.rb
@@ -4,5 +4,5 @@
4
4
  # Command-line and gem client for Asana (unofficial)
5
5
  module Checkoff
6
6
  # Version of library
7
- VERSION = '0.270.0'
7
+ VERSION = '0.272.0'
8
8
  end
data/rbi/checkoff.rbi CHANGED
@@ -82,7 +82,7 @@ module Overcommit
82
82
  end
83
83
 
84
84
  module Checkoff
85
- VERSION = '0.270.0'
85
+ VERSION = '0.272.0'
86
86
 
87
87
  class Attachments
88
88
  include Logging
@@ -1451,8 +1451,14 @@ module Checkoff
1451
1451
  sig { params(date_or_time: T.untyped, beginning_num_days_from_now: T.untyped, end_num_days_from_now: T.untyped).returns(T.untyped) }
1452
1452
  def between_relative_days?(date_or_time, beginning_num_days_from_now, end_num_days_from_now); end
1453
1453
 
1454
- sig { params(date_or_time: T.untyped, period_name: T.untyped, args: T.untyped).returns(T.untyped) }
1455
- def compound_in_period?(date_or_time, period_name, *args); end
1454
+ sig { params(date_or_time: T.untyped, period: T.untyped).returns(T.untyped) }
1455
+ def compound_in_period?(date_or_time, period); end
1456
+
1457
+ sig { params(period: T.untyped, arg: T.untyped).returns(T.untyped) }
1458
+ def optional_num_days(period, arg); end
1459
+
1460
+ sig { params(date_or_time: T.untyped, period_name: T.untyped, num_days: T.untyped).returns(T.untyped) }
1461
+ def single_num_days_in_period?(date_or_time, period_name, num_days); end
1456
1462
 
1457
1463
  sig { returns(T.untyped) }
1458
1464
  def self.run; end
@@ -1636,6 +1642,9 @@ module Checkoff
1636
1642
  sig { params(project: T.untyped, custom_field_name: T.untyped).returns(T.untyped) }
1637
1643
  def custom_field(project, custom_field_name); end
1638
1644
 
1645
+ sig { params(project: T.untyped, field_spec: T.untyped).returns(T.untyped) }
1646
+ def custom_field_by_spec(project, field_spec); end
1647
+
1639
1648
  sig { params(project: T.untyped, field_name: T.untyped).returns(T.untyped) }
1640
1649
  def date_or_time_field_by_name(project, field_name); end
1641
1650
  end
@@ -1699,6 +1708,9 @@ module Checkoff
1699
1708
  sig { params(task: T.untyped, custom_field_name: T.untyped).returns(T.untyped) }
1700
1709
  def custom_field(task, custom_field_name); end
1701
1710
 
1711
+ sig { params(task: T.untyped, field_spec: T.untyped).returns(T.untyped) }
1712
+ def custom_field_by_spec(task, field_spec); end
1713
+
1702
1714
  sig { params(task: T.untyped, field_name: T.untyped).returns(T.untyped) }
1703
1715
  def date_or_time_field_by_name(task, field_name); end
1704
1716
  end
@@ -2021,8 +2033,8 @@ module Checkoff
2021
2033
  sig { returns(T.untyped) }
2022
2034
  def matches?; end
2023
2035
 
2024
- sig { params(_task: T.untyped, _args: T.untyped).returns(T.untyped) }
2025
- def evaluate(_task, *_args); end
2036
+ sig { params(_resource: T.untyped, _args: T.untyped).returns(T.untyped) }
2037
+ def evaluate(_resource, *_args); end
2026
2038
 
2027
2039
  sig { params(object: T.untyped, fn_name: T.untyped).returns(T.untyped) }
2028
2040
  def fn?(object, fn_name); end
@@ -2505,7 +2517,7 @@ end
2505
2517
  # typed: ignore
2506
2518
  # Command-line and gem client for Asana (unofficial)
2507
2519
  module Checkoff
2508
- VERSION = T.let('0.270.0', T.untyped)
2520
+ VERSION = T.let('0.272.0', T.untyped)
2509
2521
 
2510
2522
  # Move tasks from one place to another
2511
2523
  class MvSubcommand
@@ -2660,7 +2672,7 @@ module Checkoff
2660
2672
  projects:), tasks: Checkoff::Tasks.new(config:,
2661
2673
  sections:), stderr: $stderr); end
2662
2674
 
2663
- sig { void }
2675
+ sig { returns(String) }
2664
2676
  def run; end
2665
2677
 
2666
2678
  # _@param_ `project_name`
@@ -3354,15 +3366,27 @@ module Checkoff
3354
3366
 
3355
3367
  # _@param_ `date_or_time`
3356
3368
  #
3357
- # _@param_ `period_name`
3358
- #
3359
- # _@param_ `args`
3360
- sig { params(date_or_time: T.nilable(T.any(Date, Time)), period_name: Symbol, args: Object).returns(T::Boolean) }
3361
- def compound_in_period?(date_or_time, period_name, *args); end
3369
+ # _@param_ `period` — period name, then its arguments
3370
+ sig { params(date_or_time: T.nilable(T.any(Date, Time)), period: T::Array[T.nilable(T.any(Symbol, Integer))]).returns(T::Boolean) }
3371
+ def compound_in_period?(date_or_time, period); end
3362
3372
 
3363
3373
  sig { void }
3364
3374
  def self.run; end
3365
3375
 
3376
+ # _@param_ `period` — period the argument came from
3377
+ #
3378
+ # _@param_ `arg`
3379
+ sig { params(period: T::Array[T.nilable(T.any(Symbol, Integer))], arg: T.nilable(T.any(Symbol, Integer))).returns(T.nilable(Integer)) }
3380
+ def optional_num_days(period, arg); end
3381
+
3382
+ # _@param_ `date_or_time`
3383
+ #
3384
+ # _@param_ `period_name`
3385
+ #
3386
+ # _@param_ `num_days`
3387
+ sig { params(date_or_time: T.nilable(T.any(Date, Time)), period_name: T.nilable(T.any(Symbol, Integer)), num_days: Integer).returns(T::Boolean) }
3388
+ def single_num_days_in_period?(date_or_time, period_name, num_days); end
3389
+
3366
3390
  sig { returns(::Logger) }
3367
3391
  def logger; end
3368
3392
 
@@ -3968,7 +3992,7 @@ module Checkoff
3968
3992
  # _@param_ `by_section`
3969
3993
  #
3970
3994
  # _@param_ `task`
3971
- sig { params(current_section: T.nilable(String), by_section: T::Hash[T.untyped, T.untyped], task: Asana::Resources::Task).returns([String, T::Hash[T.untyped, T.untyped]]) }
3995
+ sig { params(current_section: T.nilable(String), by_section: T::Hash[T.untyped, T.untyped], task: Asana::Resources::Task).returns(T.any([String, T::Hash[T.untyped, T.untyped]], [NilClass, T::Hash[T.untyped, T.untyped]])) }
3972
3996
  def file_task_by_section(current_section, by_section, task); end
3973
3997
 
3974
3998
  sig { returns(Checkoff::Projects) }
@@ -4014,23 +4038,19 @@ module Checkoff
4014
4038
  end
4015
4039
  def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), workspaces: Checkoff::Workspaces.new(config:), tasks: Checkoff::Tasks.new(config:), sections: Checkoff::Sections.new(config:), projects: Checkoff::Projects.new(config:), clients: Checkoff::Clients.new(config:), client: clients.client); end
4016
4040
 
4017
- # sord warn - "[Asana::Resource" does not appear to be a type
4018
- # sord warn - "nil]" does not appear to be a type
4019
- # sord warn - "[String" does not appear to be a type
4020
- # sord warn - "nil]" does not appear to be a type
4021
4041
  # Attempt to look up a GID, even in situations where we don't
4022
4042
  # have a resource type provided.
4023
4043
  #
4024
4044
  # _@param_ `gid`
4025
4045
  #
4026
4046
  # _@param_ `resource_type`
4027
- sig { params(gid: String, resource_type: T.nilable(String)).returns([T.untyped, T.untyped, T.untyped, T.untyped]) }
4047
+ sig { params(gid: String, resource_type: T.nilable(String)).returns(T.any([Asana::Resources::Task, String], [Asana::Resources::Section, String], [Asana::Resources::Project, String], [NilClass, NilClass])) }
4028
4048
  def resource_by_gid(gid, resource_type: nil); end
4029
4049
 
4030
4050
  # _@param_ `resource_type`
4031
4051
  #
4032
4052
  # _@param_ `gid`
4033
- sig { params(resource_type: String, gid: String).returns(T.nilable(Asana::Resources::Resource)) }
4053
+ sig { params(resource_type: String, gid: String).returns(T.nilable(T.any(Asana::Resources::Task, Asana::Resources::Section, Asana::Resources::Project))) }
4034
4054
  def fetch_gid_by_type(resource_type, gid); end
4035
4055
 
4036
4056
  # _@param_ `gid`
@@ -4311,13 +4331,13 @@ module Checkoff
4311
4331
  # _@param_ `uri`
4312
4332
  #
4313
4333
  # _@param_ `verify_mode` — - e.g., OpenSSL::SSL::VERIFY_NONE,OpenSSL::SSL::VERIFY_PEER
4314
- sig { params(uri: URI::Generic, verify_mode: Integer, block: T.untyped).returns(Object) }
4334
+ sig { params(uri: URI::Generic, verify_mode: Integer, block: T.proc.params(tempfile: File).returns(T.nilable(Asana::Resources::Attachment))).returns(T.nilable(Asana::Resources::Attachment)) }
4315
4335
  def download_uri(uri, verify_mode: OpenSSL::SSL::VERIFY_PEER, &block); end
4316
4336
 
4317
4337
  # sord duck - #read_body looks like a duck type, replacing with untyped
4318
4338
  # _@param_ `response`
4319
- sig { params(response: T.untyped).void }
4320
- def write_tempfile_from_response(response); end
4339
+ sig { params(response: T.untyped, blk: T.proc.params(tempfile: File).void).void }
4340
+ def write_tempfile_from_response(response, &blk); end
4321
4341
 
4322
4342
  # _@param_ `url`
4323
4343
  #
@@ -4859,11 +4879,11 @@ module Checkoff
4859
4879
  # _@param_ `task_hash`
4860
4880
  #
4861
4881
  # _@param_ `memberships`
4862
- sig { params(task_hash: T::Hash[String, T.any(String, T::Hash[T.untyped, T.untyped], T::Array[T.untyped])], memberships: T::Array[T::Hash[T.untyped, T.untyped]]).void }
4882
+ sig { params(task_hash: T::Hash[String, Object], memberships: T::Array[T::Hash[T.untyped, T.untyped]]).void }
4863
4883
  def add_user_task_list(task_hash, memberships); end
4864
4884
 
4865
4885
  # _@param_ `task_hash`
4866
- sig { params(task_hash: T::Hash[String, T.any(String, T::Hash[T.untyped, T.untyped], T::Array[T.untyped])]).returns(T::Hash[String, Object]) }
4886
+ sig { params(task_hash: T::Hash[String, Object]).returns(T::Hash[String, Object]) }
4867
4887
  def assignee_hash(task_hash); end
4868
4888
 
4869
4889
  # _@param_ `task_hash`
@@ -4938,6 +4958,12 @@ module Checkoff
4938
4958
  # _@param_ `field_name`
4939
4959
  sig { params(task: Asana::Resources::Task, field_name: T.any(Symbol, T::Array[T.untyped])).returns(T.nilable(T.any(Date, Time))) }
4940
4960
  def date_or_time_field_by_name(task, field_name); end
4961
+
4962
+ # _@param_ `task`
4963
+ #
4964
+ # _@param_ `field_spec` — [:custom_field, custom field name]
4965
+ sig { params(task: Asana::Resources::Task, field_spec: T::Array[T.untyped]).returns(T.nilable(T.any(Time, Date))) }
4966
+ def custom_field_by_spec(task, field_spec); end
4941
4967
  end
4942
4968
 
4943
4969
  # Manage thread lock variables in a block
@@ -4961,7 +4987,7 @@ module Checkoff
4961
4987
  def initialize(config, sym, yaml_filename); end
4962
4988
 
4963
4989
  # _@param_ `key`
4964
- sig { params(key: Symbol).returns(Object) }
4990
+ sig { params(key: Symbol).returns(T.nilable(Object)) }
4965
4991
  def [](key); end
4966
4992
 
4967
4993
  # _@param_ `key`
@@ -5049,6 +5075,12 @@ module Checkoff
5049
5075
  # _@param_ `field_name`
5050
5076
  sig { params(project: Asana::Resources::Project, field_name: T.any(Symbol, T::Array[T.untyped])).returns(T.nilable(T.any(Date, Time))) }
5051
5077
  def date_or_time_field_by_name(project, field_name); end
5078
+
5079
+ # _@param_ `project`
5080
+ #
5081
+ # _@param_ `field_spec` — [:custom_field, custom field name]
5082
+ sig { params(project: Asana::Resources::Project, field_spec: T::Array[T.untyped]).returns(T.nilable(T.any(Time, Date))) }
5083
+ def custom_field_by_spec(project, field_spec); end
5052
5084
  end
5053
5085
 
5054
5086
  module SearchUrl
@@ -5087,7 +5119,7 @@ module Checkoff
5087
5119
  def self.merge_args(*args); end
5088
5120
 
5089
5121
  # _@param_ `task_selectors`
5090
- sig { params(task_selectors: T::Array[T.any(Symbol, T::Array[T.untyped])]).returns(T.any(Symbol, T::Array[T.untyped], [Symbol, T::Array[T.untyped], T::Array[T.untyped]])) }
5122
+ sig { params(task_selectors: T::Array[T.any(Symbol, T::Array[T.untyped])]).returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], [Symbol, T::Array[T.untyped], T::Array[T.untyped]])) }
5091
5123
  def self.merge_task_selectors(*task_selectors); end
5092
5124
  end
5093
5125
 
@@ -5185,7 +5217,7 @@ module Checkoff
5185
5217
 
5186
5218
  # custom_field_#{gid}.variant = 'is'
5187
5219
  class Is < Checkoff::Internal::SearchUrl::CustomFieldVariant::CustomFieldVariant
5188
- sig { returns([T::Hash[String, String], T::Array[T.any(T::Array[String], String, T::Array[T.untyped])]]) }
5220
+ sig { returns([T::Hash[String, String], T::Array[T.any(T::Array[String], String, T::Array[T.untyped], Symbol)]]) }
5189
5221
  def convert; end
5190
5222
  end
5191
5223
  end
@@ -5589,17 +5621,13 @@ module Checkoff
5589
5621
  sig { params(webhook_subscription: T.nilable(T::Hash[T.untyped, T.untyped])).void }
5590
5622
  def enrich_webhook_subscription!(webhook_subscription); end
5591
5623
 
5592
- # sord warn - "[String" does not appear to be a type
5593
- # sord warn - "nil]" does not appear to be a type
5594
- # sord warn - "[String" does not appear to be a type
5595
- # sord warn - "nil]" does not appear to be a type
5596
5624
  # Attempt to look up a GID in situations where we don't have a
5597
5625
  # resource type provided, and returns the name of the resource.
5598
5626
  #
5599
5627
  # _@param_ `gid`
5600
5628
  #
5601
5629
  # _@param_ `resource_type`
5602
- sig { params(gid: String, resource_type: T.nilable(String)).returns([T.untyped, T.untyped, T.untyped, T.untyped]) }
5630
+ sig { params(gid: String, resource_type: T.nilable(String)).returns(T.any([String, String], [NilClass, String], [NilClass, NilClass])) }
5603
5631
  def enrich_gid(gid, resource_type: nil); end
5604
5632
 
5605
5633
  # _@param_ `filter`
@@ -5983,7 +6011,7 @@ module Checkoff
5983
6011
  # _@param_ `_kwargs`
5984
6012
  sig do
5985
6013
  params(
5986
- selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol),
6014
+ selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String),
5987
6015
  tasks: Checkoff::Tasks,
5988
6016
  timelines: Checkoff::Timelines,
5989
6017
  custom_fields: Checkoff::CustomFields,
@@ -6001,7 +6029,7 @@ module Checkoff
6001
6029
  sig { returns(Checkoff::CustomFields) }
6002
6030
  attr_reader :custom_fields
6003
6031
 
6004
- sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol)) }
6032
+ sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String)) }
6005
6033
  attr_reader :selector
6006
6034
  end
6007
6035
  end
@@ -6206,13 +6234,13 @@ module Checkoff
6206
6234
  # _@param_ `custom_fields`
6207
6235
  #
6208
6236
  # _@param_ `_kwargs`
6209
- sig { params(selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol), custom_fields: Checkoff::CustomFields, _kwargs: T.untyped).void }
6237
+ sig { params(selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String), custom_fields: Checkoff::CustomFields, _kwargs: T.untyped).void }
6210
6238
  def initialize(selector:, custom_fields:, **_kwargs); end
6211
6239
 
6212
6240
  sig { returns(Checkoff::CustomFields) }
6213
6241
  attr_reader :custom_fields
6214
6242
 
6215
- sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol)) }
6243
+ sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String)) }
6216
6244
  attr_reader :selector
6217
6245
  end
6218
6246
  end
@@ -6283,7 +6311,7 @@ module Checkoff
6283
6311
  # _@param_ `_kwargs`
6284
6312
  sig do
6285
6313
  params(
6286
- selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol),
6314
+ selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String),
6287
6315
  projects: Checkoff::Projects,
6288
6316
  portfolios: Checkoff::Portfolios,
6289
6317
  workspaces: Checkoff::Workspaces,
@@ -6301,7 +6329,7 @@ module Checkoff
6301
6329
  sig { returns(Checkoff::Workspaces) }
6302
6330
  attr_reader :workspaces
6303
6331
 
6304
- sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol)) }
6332
+ sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String)) }
6305
6333
  attr_reader :selector
6306
6334
  end
6307
6335
  end
@@ -6343,7 +6371,7 @@ module Checkoff
6343
6371
  # _@param_ `kwargs`
6344
6372
  sig do
6345
6373
  params(
6346
- selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol),
6374
+ selector: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String),
6347
6375
  sections: Checkoff::Sections,
6348
6376
  client: Asana::Client,
6349
6377
  kwargs: T.untyped
@@ -6357,7 +6385,7 @@ module Checkoff
6357
6385
  sig { returns(Asana::Client) }
6358
6386
  attr_reader :client
6359
6387
 
6360
- sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol)) }
6388
+ sig { returns(T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String)) }
6361
6389
  attr_reader :selector
6362
6390
  end
6363
6391
  end
@@ -6387,16 +6415,16 @@ module Checkoff
6387
6415
  sig { returns(T::Boolean) }
6388
6416
  def matches?; end
6389
6417
 
6390
- # _@param_ `_task`
6418
+ # _@param_ `_resource`
6391
6419
  #
6392
6420
  # _@param_ `_args`
6393
- sig { params(_task: Asana::Resources::Task, _args: Object).returns(Object) }
6394
- def evaluate(_task, *_args); end
6421
+ sig { params(_resource: Asana::Resources::Resource, _args: Object).returns(Object) }
6422
+ def evaluate(_resource, *_args); end
6395
6423
 
6396
6424
  # _@param_ `object`
6397
6425
  #
6398
6426
  # _@param_ `fn_name`
6399
- sig { params(object: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol), fn_name: Symbol).returns(T::Boolean) }
6427
+ sig { params(object: T.any(T::Array[T.any(Symbol, T::Array[T.untyped])], Symbol, String), fn_name: Symbol).returns(T::Boolean) }
6400
6428
  def fn?(object, fn_name); end
6401
6429
 
6402
6430
  sig { returns(::Logger) }
data/sig/checkoff.rbs CHANGED
@@ -131,7 +131,7 @@ module Checkoff
131
131
  ?stderr: IO
132
132
  ) -> void
133
133
 
134
- def run: () -> void
134
+ def run: () -> String
135
135
 
136
136
  # _@param_ `project_name`
137
137
  def validate_and_assign_project_name: ((String | Symbol) project_name) -> (String | Symbol)
@@ -700,13 +700,23 @@ module Checkoff
700
700
 
701
701
  # _@param_ `date_or_time`
702
702
  #
703
- # _@param_ `period_name`
704
- #
705
- # _@param_ `args`
706
- def compound_in_period?: ((Date | Time)? date_or_time, Symbol period_name, *Object args) -> bool
703
+ # _@param_ `period` — period name, then its arguments
704
+ def compound_in_period?: ((Date | Time)? date_or_time, ::Array[(Symbol | Integer)?] period) -> bool
707
705
 
708
706
  def self.run: () -> void
709
707
 
708
+ # _@param_ `period` — period the argument came from
709
+ #
710
+ # _@param_ `arg`
711
+ def optional_num_days: (::Array[(Symbol | Integer)?] period, (Symbol | Integer)? arg) -> Integer?
712
+
713
+ # _@param_ `date_or_time`
714
+ #
715
+ # _@param_ `period_name`
716
+ #
717
+ # _@param_ `num_days`
718
+ def single_num_days_in_period?: ((Date | Time)? date_or_time, (Symbol | Integer)? period_name, Integer num_days) -> bool
719
+
710
720
  def logger: () -> ::Logger
711
721
 
712
722
  # _@param_ `message`
@@ -1213,7 +1223,7 @@ module Checkoff
1213
1223
  # _@param_ `by_section`
1214
1224
  #
1215
1225
  # _@param_ `task`
1216
- def file_task_by_section: (String? current_section, ::Hash[untyped, untyped] by_section, Asana::Resources::Task task) -> [String, ::Hash[untyped, untyped]]
1226
+ def file_task_by_section: (String? current_section, ::Hash[untyped, untyped] by_section, Asana::Resources::Task task) -> ([String, ::Hash[untyped, untyped]] | [NilClass, ::Hash[untyped, untyped]])
1217
1227
 
1218
1228
  attr_reader projects: Checkoff::Projects
1219
1229
 
@@ -1253,22 +1263,18 @@ module Checkoff
1253
1263
  ?client: Asana::Client
1254
1264
  ) -> void
1255
1265
 
1256
- # sord warn - "[Asana::Resource" does not appear to be a type
1257
- # sord warn - "nil]" does not appear to be a type
1258
- # sord warn - "[String" does not appear to be a type
1259
- # sord warn - "nil]" does not appear to be a type
1260
1266
  # Attempt to look up a GID, even in situations where we don't
1261
1267
  # have a resource type provided.
1262
1268
  #
1263
1269
  # _@param_ `gid`
1264
1270
  #
1265
1271
  # _@param_ `resource_type`
1266
- def resource_by_gid: (String gid, ?resource_type: String?) -> [untyped, untyped, untyped, untyped]
1272
+ def resource_by_gid: (String gid, ?resource_type: String?) -> ([Asana::Resources::Task, String] | [Asana::Resources::Section, String] | [Asana::Resources::Project, String] | [NilClass, NilClass])
1267
1273
 
1268
1274
  # _@param_ `resource_type`
1269
1275
  #
1270
1276
  # _@param_ `gid`
1271
- def fetch_gid_by_type: (String resource_type, String gid) -> Asana::Resources::Resource?
1277
+ def fetch_gid_by_type: (String resource_type, String gid) -> (Asana::Resources::Task | Asana::Resources::Section | Asana::Resources::Project)?
1272
1278
 
1273
1279
  # _@param_ `gid`
1274
1280
  def fetch_task_gid: (String gid) -> Asana::Resources::Task?
@@ -1503,11 +1509,11 @@ module Checkoff
1503
1509
  # _@param_ `uri`
1504
1510
  #
1505
1511
  # _@param_ `verify_mode` — - e.g., OpenSSL::SSL::VERIFY_NONE,OpenSSL::SSL::VERIFY_PEER
1506
- def download_uri: (URI::Generic uri, ?verify_mode: Integer) ?{ (*untyped args) -> untyped } -> Object
1512
+ def download_uri: (URI::Generic uri, ?verify_mode: Integer) { (File tempfile) -> Asana::Resources::Attachment? } -> Asana::Resources::Attachment?
1507
1513
 
1508
1514
  # sord duck - #read_body looks like a duck type, replacing with untyped
1509
1515
  # _@param_ `response`
1510
- def write_tempfile_from_response: (untyped response) -> void
1516
+ def write_tempfile_from_response: (untyped response) { (File tempfile) -> void } -> void
1511
1517
 
1512
1518
  # _@param_ `url`
1513
1519
  #
@@ -1956,10 +1962,10 @@ module Checkoff
1956
1962
  # _@param_ `task_hash`
1957
1963
  #
1958
1964
  # _@param_ `memberships`
1959
- def add_user_task_list: (::Hash[String, (String | ::Hash[untyped, untyped] | ::Array[untyped])] task_hash, ::Array[::Hash[untyped, untyped]] memberships) -> void
1965
+ def add_user_task_list: (::Hash[String, Object] task_hash, ::Array[::Hash[untyped, untyped]] memberships) -> void
1960
1966
 
1961
1967
  # _@param_ `task_hash`
1962
- def assignee_hash: (::Hash[String, (String | ::Hash[untyped, untyped] | ::Array[untyped])] task_hash) -> ::Hash[String, Object]
1968
+ def assignee_hash: (::Hash[String, Object] task_hash) -> ::Hash[String, Object]
1963
1969
 
1964
1970
  # _@param_ `task_hash`
1965
1971
  #
@@ -2019,6 +2025,11 @@ module Checkoff
2019
2025
  #
2020
2026
  # _@param_ `field_name`
2021
2027
  def date_or_time_field_by_name: (Asana::Resources::Task task, (Symbol | ::Array[untyped]) field_name) -> (Date | Time)?
2028
+
2029
+ # _@param_ `task`
2030
+ #
2031
+ # _@param_ `field_spec` — [:custom_field, custom field name]
2032
+ def custom_field_by_spec: (Asana::Resources::Task task, ::Array[untyped] field_spec) -> (Time | Date)?
2022
2033
  end
2023
2034
 
2024
2035
  # Manage thread lock variables in a block
@@ -2040,7 +2051,7 @@ module Checkoff
2040
2051
  def initialize: (::Hash[Symbol, untyped] config, Symbol sym, String yaml_filename) -> void
2041
2052
 
2042
2053
  # _@param_ `key`
2043
- def []: (Symbol key) -> Object
2054
+ def []: (Symbol key) -> Object?
2044
2055
 
2045
2056
  # _@param_ `key`
2046
2057
  def fetch: (Symbol key) -> Object
@@ -2112,6 +2123,11 @@ module Checkoff
2112
2123
  #
2113
2124
  # _@param_ `field_name`
2114
2125
  def date_or_time_field_by_name: (Asana::Resources::Project project, (Symbol | ::Array[untyped]) field_name) -> (Date | Time)?
2126
+
2127
+ # _@param_ `project`
2128
+ #
2129
+ # _@param_ `field_spec` — [:custom_field, custom field name]
2130
+ def custom_field_by_spec: (Asana::Resources::Project project, ::Array[untyped] field_spec) -> (Time | Date)?
2115
2131
  end
2116
2132
 
2117
2133
  module SearchUrl
@@ -2143,7 +2159,7 @@ module Checkoff
2143
2159
  def self.merge_args: (*::Hash[String, String] args) -> ::Hash[String, String]
2144
2160
 
2145
2161
  # _@param_ `task_selectors`
2146
- def self.merge_task_selectors: (*::Array[(Symbol | ::Array[untyped])] task_selectors) -> (Symbol | ::Array[untyped] | [Symbol, ::Array[untyped], ::Array[untyped]])
2162
+ def self.merge_task_selectors: (*::Array[(Symbol | ::Array[untyped])] task_selectors) -> (::Array[(Symbol | ::Array[untyped])] | [Symbol, ::Array[untyped], ::Array[untyped]])
2147
2163
  end
2148
2164
 
2149
2165
  # https://developers.asana.com/docs/search-tasks-in-a-workspace
@@ -2225,7 +2241,7 @@ module Checkoff
2225
2241
 
2226
2242
  # custom_field_#{gid}.variant = 'is'
2227
2243
  class Is < Checkoff::Internal::SearchUrl::CustomFieldVariant::CustomFieldVariant
2228
- def convert: () -> [::Hash[String, String], ::Array[(::Array[String] | String | ::Array[untyped])]]
2244
+ def convert: () -> [::Hash[String, String], ::Array[(::Array[String] | String | ::Array[untyped] | Symbol)]]
2229
2245
  end
2230
2246
  end
2231
2247
 
@@ -2537,17 +2553,13 @@ module Checkoff
2537
2553
  # _@param_ `webhook_subscription` — Hash of the request made to webhook POST endpoint - https://app.asana.com/api/1.0/webhooks https://developers.asana.com/reference/createwebhook
2538
2554
  def enrich_webhook_subscription!: (::Hash[untyped, untyped]? webhook_subscription) -> void
2539
2555
 
2540
- # sord warn - "[String" does not appear to be a type
2541
- # sord warn - "nil]" does not appear to be a type
2542
- # sord warn - "[String" does not appear to be a type
2543
- # sord warn - "nil]" does not appear to be a type
2544
2556
  # Attempt to look up a GID in situations where we don't have a
2545
2557
  # resource type provided, and returns the name of the resource.
2546
2558
  #
2547
2559
  # _@param_ `gid`
2548
2560
  #
2549
2561
  # _@param_ `resource_type`
2550
- def enrich_gid: (String gid, ?resource_type: String?) -> [untyped, untyped, untyped, untyped]
2562
+ def enrich_gid: (String gid, ?resource_type: String?) -> ([String, String] | [NilClass, String] | [NilClass, NilClass])
2551
2563
 
2552
2564
  # _@param_ `filter`
2553
2565
  def enrich_filter_parent_gid!: (::Hash[String, (String | ::Array[String])] filter) -> void
@@ -2857,7 +2869,7 @@ module Checkoff
2857
2869
  #
2858
2870
  # _@param_ `_kwargs`
2859
2871
  def initialize: (
2860
- selector: (::Array[(Symbol | ::Array[untyped])] | Symbol),
2872
+ selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String),
2861
2873
  tasks: Checkoff::Tasks,
2862
2874
  timelines: Checkoff::Timelines,
2863
2875
  custom_fields: Checkoff::CustomFields,
@@ -2870,7 +2882,7 @@ module Checkoff
2870
2882
 
2871
2883
  attr_reader custom_fields: Checkoff::CustomFields
2872
2884
 
2873
- attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol)
2885
+ attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String)
2874
2886
  end
2875
2887
  end
2876
2888
 
@@ -3044,11 +3056,11 @@ module Checkoff
3044
3056
  # _@param_ `custom_fields`
3045
3057
  #
3046
3058
  # _@param_ `_kwargs`
3047
- def initialize: (selector: (::Array[(Symbol | ::Array[untyped])] | Symbol), custom_fields: Checkoff::CustomFields, **untyped _kwargs) -> void
3059
+ def initialize: (selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String), custom_fields: Checkoff::CustomFields, **untyped _kwargs) -> void
3048
3060
 
3049
3061
  attr_reader custom_fields: Checkoff::CustomFields
3050
3062
 
3051
- attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol)
3063
+ attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String)
3052
3064
  end
3053
3065
  end
3054
3066
 
@@ -3109,7 +3121,7 @@ module Checkoff
3109
3121
  #
3110
3122
  # _@param_ `_kwargs`
3111
3123
  def initialize: (
3112
- selector: (::Array[(Symbol | ::Array[untyped])] | Symbol),
3124
+ selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String),
3113
3125
  projects: Checkoff::Projects,
3114
3126
  portfolios: Checkoff::Portfolios,
3115
3127
  workspaces: Checkoff::Workspaces,
@@ -3122,7 +3134,7 @@ module Checkoff
3122
3134
 
3123
3135
  attr_reader workspaces: Checkoff::Workspaces
3124
3136
 
3125
- attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol)
3137
+ attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String)
3126
3138
  end
3127
3139
  end
3128
3140
 
@@ -3158,7 +3170,7 @@ module Checkoff
3158
3170
  #
3159
3171
  # _@param_ `kwargs`
3160
3172
  def initialize: (
3161
- selector: (::Array[(Symbol | ::Array[untyped])] | Symbol),
3173
+ selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String),
3162
3174
  sections: Checkoff::Sections,
3163
3175
  client: Asana::Client,
3164
3176
  **untyped kwargs
@@ -3168,7 +3180,7 @@ module Checkoff
3168
3180
 
3169
3181
  attr_reader client: Asana::Client
3170
3182
 
3171
- attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol)
3183
+ attr_reader selector: (::Array[(Symbol | ::Array[untyped])] | Symbol | String)
3172
3184
  end
3173
3185
  end
3174
3186
 
@@ -3194,15 +3206,15 @@ module Checkoff
3194
3206
 
3195
3207
  def matches?: () -> bool
3196
3208
 
3197
- # _@param_ `_task`
3209
+ # _@param_ `_resource`
3198
3210
  #
3199
3211
  # _@param_ `_args`
3200
- def evaluate: (Asana::Resources::Task _task, *Object _args) -> Object
3212
+ def evaluate: (Asana::Resources::Resource _resource, *Object _args) -> Object
3201
3213
 
3202
3214
  # _@param_ `object`
3203
3215
  #
3204
3216
  # _@param_ `fn_name`
3205
- def fn?: ((::Array[(Symbol | ::Array[untyped])] | Symbol) object, Symbol fn_name) -> bool
3217
+ def fn?: ((::Array[(Symbol | ::Array[untyped])] | Symbol | String) object, Symbol fn_name) -> bool
3206
3218
 
3207
3219
  def logger: () -> ::Logger
3208
3220
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checkoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.270.0
4
+ version: 0.272.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vince Broz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-30 00:00:00.000000000 Z
11
+ date: 2026-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport