sf_cli 0.0.9 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64f11658c0b90ce494643c625b80f6826ec42597723315fd52690aefc6d97c8c
4
- data.tar.gz: e0318c64547346287a378766a3441249cf2906539693bc982e486d6bca4b7836
3
+ metadata.gz: afdf126ac27d743486c73a2113ce6456ba3577d705d8791cef1744685ab4799f
4
+ data.tar.gz: f504f4b26b64ceeae348c3d5b21bf386f028e4a5a31e841e659b18a5732681e9
5
5
  SHA512:
6
- metadata.gz: 57c9f53f54298b2bcb7e566bceb48704012154c6a160e08402eb48d998cd2dc361d1f021bedb7866fade1beecfddab30affb0dcffa812cdfb20b7b6417c69df5
7
- data.tar.gz: 875b18097589d7f4df8a212a078bbaf98e35de738782a8d4522f2a198861f280457ed23828838a77c645d170305423985edc16ee4e23ef77bd0afaeb8f0986af
6
+ metadata.gz: c7d2f747adec0dbabf6e68c8a9eb92eec2f3b9c5cc22640576d44582056e3379c633f2876334b2e0eabfb1e552457ebf0bbb67bf7af440a49190df13b89ff469
7
+ data.tar.gz: a1c4d13892f2e9a9223dffbf7084b5d982fadeaaf3b1c4d55a604781410529a8d64a5735df9a4065749d4cd464c2939d97b7ee8cc4b77671736a405a75d02436
data/bin/sfdc ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rake'
4
+
5
+ Rake.application.init
6
+ Rake.application.define_task(Rake::Task, :default) { system('irb -r sf_cli/sf/console') }
7
+ Rake.application.top_level
@@ -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,24 +1,26 @@
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: 1.0.0.beta1
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-26 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.
15
15
  email:
16
- executables: []
16
+ executables:
17
+ - sfdc
17
18
  extensions: []
18
19
  extra_rdoc_files:
19
20
  - README.rdoc
20
21
  files:
21
22
  - README.rdoc
23
+ - bin/sfdc
22
24
  - lib/sf_cli.rb
23
25
  - lib/sf_cli/console.rb
24
26
  - lib/sf_cli/console/commands.rb