sf_cli 0.0.9 → 0.0.10

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: 64f11658c0b90ce494643c625b80f6826ec42597723315fd52690aefc6d97c8c
4
- data.tar.gz: e0318c64547346287a378766a3441249cf2906539693bc982e486d6bca4b7836
3
+ metadata.gz: a3e5833449ce9819bd4c28f92d21d2719cfac0bd9b6a0917f61de212b3b1a485
4
+ data.tar.gz: 34c71983f1f8feae1dec31b965e9ef1102ea1b4340eb0ebaffa376df8c1cc699
5
5
  SHA512:
6
- metadata.gz: 57c9f53f54298b2bcb7e566bceb48704012154c6a160e08402eb48d998cd2dc361d1f021bedb7866fade1beecfddab30affb0dcffa812cdfb20b7b6417c69df5
7
- data.tar.gz: 875b18097589d7f4df8a212a078bbaf98e35de738782a8d4522f2a198861f280457ed23828838a77c645d170305423985edc16ee4e23ef77bd0afaeb8f0986af
6
+ metadata.gz: 62d251ef5a3411ec98a835de03f686e45551eb783d6504772ba56abc8eff986b95d0d70f37257479934a670e279656b047326faf623845879cc7f4e797bdae80
7
+ data.tar.gz: 25b30fd9cc789d55be2d8f15903b72e16d7bcf03447402782be48f738a8d00bf71270972c47a776df0ce2c59d801bea880ffc1c46e557d8837cc67e32b216406
@@ -6,7 +6,16 @@ module SfCli
6
6
  module QueryMethods
7
7
  # @private :nodoc: just for developers
8
8
  class QueryCondition
9
- attr_reader :connection, :object_name, :all_field_names, :fields, :conditions, :limit_num, :row_order
9
+ attr_reader :connection,
10
+ :object_name,
11
+ :all_field_names,
12
+ :fields,
13
+ :conditions,
14
+ :limit_num,
15
+ :row_order,
16
+ :count_select,
17
+ :max_select_field,
18
+ :min_select_field
10
19
 
11
20
  def initialize(connection, object_name, field_names)
12
21
  @object_name = object_name
@@ -16,71 +25,23 @@ module SfCli
16
25
  @conditions = []
17
26
  @limit_num = nil
18
27
  @row_order = nil
28
+ @count_select = false
29
+ @max_select_field = nil
30
+ @min_select_field = nil
19
31
  end
20
32
 
21
33
  def where(*expr)
22
- return self if expr&.empty?
23
- return self if expr.map{|o| (o == '' || o == {} || o == []) ? nil : o}.compact.size.zero?
24
- return self unless [Hash, Symbol, String].any?{|klass| expr.first.instance_of? klass}
34
+ return self unless valid_expr?(expr)
25
35
 
26
- if expr.size > 1
27
- return self if expr.size < 3
28
-
29
- value = case expr[2].class.name.to_sym
30
- when :String
31
- %|'#{expr[2]}'|
32
- when :Time
33
- expr[2].to_datetime
34
- when :Array
35
- candidates = expr[2].map do |o|
36
- case o.class.name.to_sym
37
- when :String
38
- %|'#{o}'|
39
- when :Time
40
- o.to_datetime
41
- else
42
- o
43
- end
44
- end
45
- %|IN (#{candidates.join(', ')})|
46
- else
47
- expr[2]
48
- end
49
- conditions << %|#{expr[0]} #{expr[1]} #{value}|
50
-
51
- return self
52
- end
36
+ conditions.append to_string_expr(expr)
37
+ self
38
+ end
53
39
 
54
- if expr[0].instance_of? String
55
- conditions << expr[0]
56
- return self
57
- end
40
+ def not(*expr)
41
+ return self unless valid_expr?(expr)
58
42
 
59
- new_conditions =
60
- expr[0].map do |k,v|
61
- case v.class.name.to_sym
62
- when :String
63
- %|#{k} = '#{v}'|
64
- when :Time
65
- %|#{k} = #{v.to_datetime}|
66
- when :Array
67
- candidates = v.map do |o|
68
- case o.class.name.to_sym
69
- when :String
70
- %|'#{o}'|
71
- when :Time
72
- %|#{o.to_datetime}|
73
- else
74
- o
75
- end
76
- end
77
- %|#{k} IN (#{candidates.join(', ')})|
78
- else
79
- "#{k} = #{v}"
80
- end
81
- end
82
- conditions.append new_conditions
83
- return self
43
+ conditions.append %|NOT(#{to_string_expr(expr)})|
44
+ self
84
45
  end
85
46
 
86
47
  def select(*expr)
@@ -115,21 +76,113 @@ module SfCli
115
76
  [base, where, _order, limit].compact.join(' ')
116
77
  end
117
78
 
79
+ def to_csv
80
+ connection.query(to_soql, Object.const_get(object_name.to_sym), :csv)
81
+ end
82
+
118
83
  def all
119
84
  connection.query(to_soql, Object.const_get(object_name.to_sym))
120
85
  end
121
86
 
122
87
  def pluck(field_name)
123
- all.map{|record| record.__send__(field_name.to_sym)}
88
+ connection.query(to_soql, nil).map{|record| record[field_name.to_s]}
124
89
  end
125
90
 
126
91
  def take
127
92
  limit(1).all.first
128
93
  end
129
94
 
95
+ def count
96
+ @count_select = true
97
+ connection.query(to_soql, nil).first['expr0']
98
+ end
99
+
100
+ def max(field_name)
101
+ @max_select_field = field_name
102
+ connection.query(to_soql, nil).first['expr0']
103
+ end
104
+
105
+ def min(field_name)
106
+ @min_select_field = field_name
107
+ connection.query(to_soql, nil).first['expr0']
108
+ end
109
+
110
+ private
111
+
130
112
  def select_fields
113
+ return 'COUNT(Id)' if count_select
114
+ return "MAX(#{max_select_field})" if max_select_field
115
+ return "MIN(#{min_select_field})" if min_select_field
116
+
131
117
  (fields.empty? ? all_field_names : fields).join(', ')
132
118
  end
119
+
120
+ def to_string_expr(expr)
121
+ return str_by_ternary_expr(expr) if expr.size > 1
122
+ return expr[0] if expr[0].instance_of? String
123
+
124
+ strs_by_hash_expr(expr)
125
+ end
126
+
127
+ def str_by_ternary_expr(expr)
128
+ return self if expr.size < 3
129
+
130
+ value = case expr[2].class.name.to_sym
131
+ when :String
132
+ %|'#{expr[2]}'|
133
+ when :Time
134
+ expr[2].to_datetime
135
+ when :Array
136
+ candidates = expr[2].map do |o|
137
+ case o.class.name.to_sym
138
+ when :String
139
+ %|'#{o}'|
140
+ when :Time
141
+ o.to_datetime
142
+ else
143
+ o
144
+ end
145
+ end
146
+ %|IN (#{candidates.join(', ')})|
147
+ else
148
+ expr[2]
149
+ end
150
+ %|#{expr[0]} #{expr[1]} #{value}|
151
+ end
152
+
153
+ def valid_expr?(expr)
154
+ return false if expr&.empty?
155
+ return false if expr.map{|o| (o == '' || o == {} || o == []) ? nil : o}.compact.size.zero?
156
+ return false unless [Hash, Symbol, String].any?{|klass| expr.first.instance_of? klass}
157
+
158
+ true
159
+ end
160
+
161
+ def strs_by_hash_expr(expr)
162
+ expr[0].map do |k,v|
163
+ case v.class.name.to_sym
164
+ when :String
165
+ %|#{k} = '#{v}'|
166
+ when :Time
167
+ %|#{k} = #{v.to_datetime}|
168
+ when :Array
169
+ candidates = v.map do |o|
170
+ case o.class.name.to_sym
171
+ when :String
172
+ %|'#{o}'|
173
+ when :Time
174
+ %|#{o.to_datetime}|
175
+ else
176
+ o
177
+ end
178
+ end
179
+ %|#{k} IN (#{candidates.join(', ')})|
180
+ else
181
+ "#{k} = #{v}"
182
+ end
183
+ end
184
+ .join(' AND ')
185
+ end
133
186
  end
134
187
  end
135
188
  end
@@ -22,15 +22,6 @@ module SfCli
22
22
  return qc
23
23
  end
24
24
 
25
- def find(id)
26
- connection.find(name.to_sym, id, Object.const_get(name.to_sym))
27
- end
28
-
29
- def find_by(*find_condition)
30
- qc = QueryCondition.new(connection, self.name, self.field_names)
31
- qc.where(*find_condition).take
32
- end
33
-
34
25
  def limit(num)
35
26
  qc = QueryCondition.new(connection, self.name, self.field_names)
36
27
  qc.limit(num)
@@ -43,11 +34,25 @@ module SfCli
43
34
  qc
44
35
  end
45
36
 
37
+ def find(id)
38
+ connection.find(name.to_sym, id, Object.const_get(name.to_sym))
39
+ end
40
+
41
+ def find_by(*find_condition)
42
+ qc = QueryCondition.new(connection, self.name, self.field_names)
43
+ qc.where(*find_condition).take
44
+ end
45
+
46
46
  def all
47
47
  qc = QueryCondition.new(connection, self.name, self.field_names)
48
48
  qc.all
49
49
  end
50
50
 
51
+ def to_csv
52
+ qc = QueryCondition.new(connection, self.name, self.field_names)
53
+ qc.to_csv
54
+ end
55
+
51
56
  def pluck(field_name)
52
57
  qc = QueryCondition.new(connection, self.name, self.field_names)
53
58
  qc.pluck(field_name)
@@ -57,6 +62,21 @@ module SfCli
57
62
  qc = QueryCondition.new(connection, self.name, self.field_names)
58
63
  qc.take
59
64
  end
65
+
66
+ def count
67
+ qc = QueryCondition.new(connection, self.name, self.field_names)
68
+ qc.count
69
+ end
70
+
71
+ def max(field_name)
72
+ qc = QueryCondition.new(connection, self.name, self.field_names)
73
+ qc.max(field_name)
74
+ end
75
+
76
+ def min(field_name)
77
+ qc = QueryCondition.new(connection, self.name, self.field_names)
78
+ qc.min(field_name)
79
+ end
60
80
  end
61
81
  end
62
82
  end
@@ -65,8 +65,8 @@ module SfCli
65
65
  end
66
66
 
67
67
  # @private :nodoc: just for developers
68
- def query(soql, klass)
69
- sf_data.query soql, target_org: target_org, model_class: klass
68
+ def query(soql, klass, format = nil)
69
+ sf_data.query soql, target_org: target_org, format: format, model_class: klass
70
70
  end
71
71
 
72
72
  # @private :nodoc: just for developers
@@ -13,8 +13,8 @@ module SfCli::Sf::Sobject
13
13
  # schema = sf.sobject.describe :Account
14
14
  # schema.name # Account
15
15
  # schema.label # Account
16
- # schema.field_names # [:Id, :Name, ....]
17
- # schema.fields[:Name] # => {"aggregatable"=>true, "aiPredictionField"=>false, "autoNumber"=>false,...}
16
+ # schema.field_names # [:Id, :Name, ....]
17
+ # schema.fields.name_and_labels # [['Id', 'Account Id'], ['Name', 'Account Name'], ...]
18
18
  #
19
19
  # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_sobject_commands_unified.htm#cli_reference_sobject_describe_unified command reference
20
20
  #
@@ -2,32 +2,28 @@ module SfCli
2
2
  module Sf
3
3
  module Sobject
4
4
  class Schema
5
- attr_reader :schema
6
-
7
5
  def initialize(schema)
8
6
  @schema = schema
9
7
  end
10
8
 
11
- def all
12
- schema
13
- end
14
-
15
9
  def name
16
- @name ||= schema['name']
10
+ schema['name']
17
11
  end
18
12
 
19
13
  def label
20
- @label ||= schema['label']
14
+ schema['label']
15
+ end
16
+
17
+ def fields
18
+ @fields ||= Fields.new(schema)
21
19
  end
22
20
 
23
21
  def field_names
24
- @field_names ||= schema['fields'].map{|f| f['name'].to_sym}
22
+ @field_names ||= fields.map{|f| f.name.to_sym}
25
23
  end
26
24
 
27
- def fields
28
- @field_map ||= schema['fields'].each_with_object({}) do |f, h|
29
- h[f['name'].to_sym] = f
30
- end
25
+ def field_labels
26
+ @field_labels ||= fields.map{|f| f.label}
31
27
  end
32
28
 
33
29
  def children_relations
@@ -37,9 +33,449 @@ module SfCli
37
33
  end
38
34
 
39
35
  def parent_relations
40
- schema['fields']
41
- .select{|f| f['relationshipName'].nil? == false && f['referenceTo']&.size > 0}
42
- .map{|f| {name: f['relationshipName'].to_sym, field: f['name'].to_sym, class_name: f['referenceTo'].first.to_sym}}
36
+ fields
37
+ .select{|f| !(f.relationship_name.nil? || f.reference_to.nil?) && f.reference_to.size > 0}
38
+ .map{|f| {name: f.relationship_name.to_sym, field: f.name.to_sym, class_name: f.reference_to.first.to_sym} }
39
+ end
40
+
41
+ def to_h
42
+ schema
43
+ end
44
+
45
+ def compact_layoutable?
46
+ schema["compactLayoutable"]
47
+ end
48
+
49
+ def createable?
50
+ schema["createable"]
51
+ end
52
+
53
+ def custom?
54
+ schema["custom"]
55
+ end
56
+
57
+ def custom_setting?
58
+ schema["customSetting"]
59
+ end
60
+
61
+ def deep_cloneable?
62
+ schema["deepCloneable"]
63
+ end
64
+
65
+ def default_implementation
66
+ schema["defaultImplementation"]
67
+ end
68
+
69
+ def deletable?
70
+ schema["deletable"]
71
+ end
72
+
73
+ def deprecated_and_hidden?
74
+ schema["deprecatedAndHidden"]
75
+ end
76
+
77
+ def extended_by
78
+ schema["extendedBy"]
79
+ end
80
+
81
+ def extends_interfaces
82
+ schema["extendsInterfaces"]
83
+ end
84
+
85
+ def feed_enabled?
86
+ schema["feedEnabled"]
87
+ end
88
+
89
+ def has_subtypes?
90
+ schema["hasSubtypes"]
91
+ end
92
+
93
+ def implemented_by
94
+ schema["implementedBy"]
95
+ end
96
+
97
+ def implements_interfaces
98
+ schema["implementsInterfaces"]
99
+ end
100
+
101
+ def interface?
102
+ schema["isInterface"]
103
+ end
104
+
105
+ def subtype?
106
+ schema["isSubtype"]
107
+ end
108
+
109
+ def key_prefix
110
+ schema["keyPrefix"]
111
+ end
112
+
113
+ def label_plural
114
+ schema["labelPlural"]
115
+ end
116
+
117
+ def layoutable?
118
+ schema["layoutable"]
119
+ end
120
+
121
+ def listviewable?
122
+ schema["listviewable"]
123
+ end
124
+
125
+ def lookup_layoutable
126
+ schema["lookupLayoutable"]
127
+ end
128
+
129
+ def mergeable?
130
+ schema["mergeable"]
131
+ end
132
+
133
+ def mruEnabled
134
+ schema["mruEnabled"]
135
+ end
136
+
137
+ def named_layouts
138
+ schema["namedLayoutInfos"]
139
+ end
140
+
141
+ def network_scope_field_name
142
+ schema["networkScopeFieldName"]
143
+ end
144
+
145
+ def queryable?
146
+ schema["queryable"]
147
+ end
148
+
149
+ def record_types
150
+ schema["recordTypeInfos"]
151
+ end
152
+
153
+ def replicateable?
154
+ schema["replicateable"]
155
+ end
156
+
157
+ def retrieveable?
158
+ schema["retrieveable"]
159
+ end
160
+
161
+ def search_layoutable?
162
+ schema["searchLayoutable"]
163
+ end
164
+
165
+ def searchable?
166
+ schema["searchable"]
167
+ end
168
+
169
+ def sobject_describe_option
170
+ schema["sobjectDescribeOption"]
171
+ end
172
+
173
+ def supported_scopes
174
+ schema["supportedScopes"]
175
+ end
176
+
177
+ def triggerable?
178
+ schema["triggerable"]
179
+ end
180
+
181
+ def undeletable?
182
+ schema["undeletable"]
183
+ end
184
+
185
+ def updateable?
186
+ schema["updateable"]
187
+ end
188
+
189
+ def urls
190
+ schema["urls"]
191
+ end
192
+
193
+ private
194
+
195
+ def schema
196
+ @schema
197
+ end
198
+
199
+ class Fields
200
+ include Enumerable
201
+
202
+ def initialize(schema)
203
+ @fields = schema['fields'].map{|h| Field.new(**h)}
204
+ end
205
+
206
+ def each(&block)
207
+ fields.each &block
208
+ end
209
+
210
+ def to_a
211
+ fields
212
+ end
213
+
214
+ def find_by(name: nil, label: nil)
215
+ return nil if name.nil? && label.nil?
216
+
217
+ attr_name = name.nil? ? :label : :name
218
+ val = name || label
219
+
220
+ find do |field|
221
+ attr_val = field.__send__(attr_name.to_sym)
222
+ attr_val == val
223
+ end
224
+ end
225
+
226
+ def name_and_labels
227
+ map{|field| [field.name, field.label]}
228
+ end
229
+
230
+ private
231
+
232
+ def fields
233
+ @fields
234
+ end
235
+ end
236
+
237
+ class Field
238
+ def initialize(field)
239
+ @field = field
240
+ end
241
+
242
+ def aggregatable?
243
+ field["aggregatable"]
244
+ end
245
+
246
+ def ai_prediction_field?
247
+ field["aiPredictionField"]
248
+ end
249
+
250
+ def autoNumber?
251
+ field["autoNumber"]
252
+ end
253
+
254
+ def byteLength
255
+ field["byteLength"]
256
+ end
257
+
258
+ def calculated?
259
+ field["calculated"]
260
+ end
261
+
262
+ def calculated_formula
263
+ field["calculatedFormula"]
264
+ end
265
+
266
+ def cascade_delete?
267
+ field["cascadeDelete"]
268
+ end
269
+
270
+ def case_sensitive
271
+ field["caseSensitive"]
272
+ end
273
+
274
+ def compound_field_name
275
+ field["compoundFieldName"]
276
+ end
277
+
278
+ def controller_name
279
+ field["controllerName"]
280
+ end
281
+
282
+ def createable?
283
+ field["createable"]
284
+ end
285
+
286
+ def custom?
287
+ field["custom"]
288
+ end
289
+
290
+ def default_value
291
+ field["defaultValue"]
292
+ end
293
+
294
+ def default_value_formula
295
+ field["defaultValueFormula"]
296
+ end
297
+
298
+ def defaulted_on_create?
299
+ field["defaultedOnCreate"]
300
+ end
301
+
302
+ def dependent_picklist?
303
+ field["dependentPicklist"]
304
+ end
305
+
306
+ def deprecated_and_hidden?
307
+ field["deprecatedAndHidden"]
308
+ end
309
+
310
+ def digits
311
+ field["digits"]
312
+ end
313
+
314
+ def display_location_in_decimal?
315
+ field["displayLocationInDecimal"]
316
+ end
317
+
318
+ def encrypted?
319
+ field["encrypted"]
320
+ end
321
+
322
+ def external_id?
323
+ field["externalId"]
324
+ end
325
+
326
+ def extra_type_info
327
+ field["extraTypeInfo"]
328
+ end
329
+
330
+ def filterable?
331
+ field["filterable"]
332
+ end
333
+
334
+ def filtered_lookup_info
335
+ field["filteredLookupInfo"]
336
+ end
337
+
338
+ def formula_treat_null_number_as_zero?
339
+ field["formulaTreatNullNumberAsZero"]
340
+ end
341
+
342
+ def groupable?
343
+ field["groupable"]
344
+ end
345
+
346
+ def high_scale_number?
347
+ field["highScaleNumber"]
348
+ end
349
+
350
+ def html_formatted?
351
+ field["htmlFormatted"]
352
+ end
353
+
354
+ def id_lookup?
355
+ field["idLookup"]
356
+ end
357
+
358
+ def inline_help_text
359
+ field["inlineHelpText"]
360
+ end
361
+
362
+ def label
363
+ field["label"]
364
+ end
365
+
366
+ def length
367
+ field["length"]
368
+ end
369
+
370
+ def mask
371
+ field["mask"]
372
+ end
373
+
374
+ def mask_type
375
+ field["maskType"]
376
+ end
377
+
378
+ def name
379
+ field["name"]
380
+ end
381
+
382
+ def name_field?
383
+ field["nameField"]
384
+ end
385
+
386
+ def name_pointing?
387
+ field["namePointing"]
388
+ end
389
+
390
+ def nillable?
391
+ field["nillable"]
392
+ end
393
+
394
+ def permissionable?
395
+ field["permissionable"]
396
+ end
397
+
398
+ def picklist_values
399
+ field["picklistValues"]
400
+ end
401
+
402
+ def polymorphic_foreign_key?
403
+ field["polymorphicForeignKey"]
404
+ end
405
+
406
+ def precision
407
+ field["precision"]
408
+ end
409
+
410
+ def query_by_distance?
411
+ field["queryByDistance"]
412
+ end
413
+
414
+ def reference_target_field
415
+ field["referenceTargetField"]
416
+ end
417
+
418
+ def reference_to
419
+ field["referenceTo"]
420
+ end
421
+
422
+ def relationship_name
423
+ field["relationshipName"]
424
+ end
425
+
426
+ def relationship_order
427
+ field["relationshipOrder"]
428
+ end
429
+
430
+ def restricted_delete
431
+ field["restrictedDelete"]
432
+ end
433
+
434
+ def restricted_picklist?
435
+ field["restrictedPicklist"]
436
+ end
437
+
438
+ def scale
439
+ field["scale"]
440
+ end
441
+
442
+ def search_prefilterable?
443
+ field["searchPrefilterable"]
444
+ end
445
+
446
+ def soapType
447
+ field["soapType"]
448
+ end
449
+
450
+ def sortable?
451
+ field["sortable"]
452
+ end
453
+
454
+ def type
455
+ field["type"]
456
+ end
457
+
458
+ def unique?
459
+ field["unique"]
460
+ end
461
+
462
+ def updateable?
463
+ field["updateable"]
464
+ end
465
+
466
+ def write_Requires_Master_Read?
467
+ field["writeRequiresMasterRead"]
468
+ end
469
+
470
+ def to_h
471
+ field
472
+ end
473
+
474
+ private
475
+
476
+ def field
477
+ @field
478
+ end
43
479
  end
44
480
  end
45
481
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sf_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takanobu Maekawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-23 00:00:00.000000000 Z
11
+ date: 2024-09-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A class library for introducing Salesforce CLI to Ruby scripting. Currenty
14
14
  only sf command is the target of development.