sf_cli 1.2.0 → 1.2.2

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: e9e80b705227bf6cc0a20eb798294a8179ac417b70ee1720626c34ede61c57f9
4
- data.tar.gz: a47fae091fde1fa337f11a3265dc27703a14642ad3dc287dfb400f41f3e0fcdb
3
+ metadata.gz: f20d5801d3a2c887f01fa3fb3ab8775153d78b27d760ac2c6b148dac749a4945
4
+ data.tar.gz: 9295c01a6eab70749c2a0367a99d29f90ac3e7dafd65c49315ac521820362506
5
5
  SHA512:
6
- metadata.gz: c4f31ede06a4efd8e9bf8e257712ffa2f5be05e0b7a06e79d7d5a056671480d06eaaaace79c5b2896ae4037ae53de46620a5337841b8e9c415397c70fffc9f59
7
- data.tar.gz: 24a8d99be40d9f0df743dbe0839dd25c31c6d3870123f50f2b806d580c588e37578a7d2341c2eb8a73f3003748e8ddc0ef44f7315467a2e8c67841e0b65189c3
6
+ metadata.gz: 31b95e54526b884b83e19e6b870b99b148114b99692b92e4c01ea092a9068d4e779d708beba850fd60471bf44821ffcf859a00e094573e7ea8e2b70b46a341f9
7
+ data.tar.gz: 68637d5bd35140a9dc851176e9e22ae341c8c1029d451f63dfc0d076d5ea103f50b6f743d2c98743d121277b59cbb335933e6f98f74484509c1fe74bd02ed33b
data/bin/sf_cli CHANGED
@@ -8,13 +8,15 @@ def generate_project(project_name, params)
8
8
  base_dir = Dir.pwd
9
9
  target_org = params[:"target-org"]
10
10
  retrieve_source = params[:retrieve]
11
+ editor = params[:editor]
11
12
 
12
13
  sf.project.generate project_name, manifest: true
13
14
 
14
15
  Dir.chdir project_name
15
16
 
16
- sf.project.generate_manifest from_org: target_org, output_dir: 'manifest' if target_org
17
+ sf.project.generate_manifest from_org: target_org, output_dir: 'manifest' if target_org
17
18
  sf.project.retrieve_start manifest: 'manifest/package.xml', target_org: target_org if retrieve_source
19
+ system 'code .' if editor
18
20
  ensure
19
21
  Dir.chdir base_dir
20
22
  end
@@ -25,11 +27,14 @@ Version = SfCli::VERSION
25
27
 
26
28
  opt.on('-i', '--irb', 'Start irb session that integrates sf_cli and object model library.') { system 'irb -r sf_cli/console' }
27
29
  opt.on('-g OBJECT', '--generate', 'Generate OBJECT. As of now, only project is available as OBJECT.')
28
- opt.on('-o TARGET_ORG', '--target-org', 'Username or alias of the target org. When specified with "-g model", the manifest file is created based on the org')
29
- opt.on('-r', '--retrieve', 'Retrieve source files.When specified with "-g model", source files is loaded according to the manifest file.')
30
+ opt.on('-o TARGET_ORG', '--target-org', 'Username or alias of the target org. When specified with "-g project", the manifest file is created based on the org')
31
+ opt.on('-r', '--retrieve', 'Retrieve source files.When specified with "-g project", source files is loaded according to the manifest file.')
32
+ opt.on('-e', '--editor', 'Open VS Code for current directory. When specified with "-g project", it opens the project directory')
30
33
 
31
34
  opt.parse!(ARGV, into: params)
32
35
 
33
36
  if params[:generate] == 'project'
34
37
  generate_project(ARGV[0], params)
38
+ elsif params[:editor]
39
+ system 'code .'
35
40
  end
@@ -1,5 +1,6 @@
1
1
  require 'sf_cli'
2
2
  require 'sf_cli/sf/model'
3
+ require 'sf_cli/sf/model/query_condition'
3
4
  require 'sf_cli/sf/model/sf_command_connection'
4
5
  require 'stringio'
5
6
 
@@ -48,7 +49,8 @@ module SfCli
48
49
  sf.apex.run target_org: target_org, file: StringIO.new(apex_code)
49
50
  end
50
51
 
51
- def query(soql)
52
+ def query(_soql)
53
+ soql = _soql.is_a?(SfCli::Sf::Model::QueryMethods::QueryCondition) ? _soql.to_soql : _soql
52
54
  conf.inspect_mode = false
53
55
  puts sf.data.query(soql, format: :human, target_org: target_org)
54
56
  conf.inspect_mode = true
@@ -17,6 +17,10 @@ module SfCli::Sf::Data
17
17
  # @example
18
18
  # sf.data.query 'SELECT Id, Name FROM Account LIMIT 1' # => [{Id: "abc", Name: "account name"}]
19
19
  #
20
+ # accounts = sf.data.query('SELECT Id, Name From Account') do |record|
21
+ # record['Name'] += " Changed!" # can manipulate the record in block
22
+ # end
23
+ #
20
24
  # Account = Struct.new(:Id, :Name)
21
25
  # sf.data.query('SELECT Id, Name From Account Limit 3', model_class: Account) # returns an array of Account struct object
22
26
  #
@@ -39,7 +43,7 @@ module SfCli::Sf::Data
39
43
  #
40
44
  # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_query_unified command reference
41
45
  #
42
- def query(soql, target_org: nil, format: nil, bulk: false, wait: nil, api_version: nil, model_class: nil)
46
+ def query(soql, target_org: nil, format: nil, bulk: false, wait: nil, api_version: nil, model_class: nil, &block)
43
47
  flags = {
44
48
  :"query" => %("#{soql}"),
45
49
  :"target-org" => target_org,
@@ -53,9 +57,15 @@ module SfCli::Sf::Data
53
57
  raw_output = format ? true : false
54
58
  format = format&.to_sym || :json
55
59
 
56
- result = exec(__method__, flags: flags, switches: switches, redirection: :null_stderr, raw_output: raw_output, format: format)
60
+ exec_result = exec(__method__, flags: flags, switches: switches, redirection: :null_stderr, raw_output: raw_output, format: format)
61
+
62
+ results = return_result(exec_result, raw_output, bulk, model_class)
63
+
64
+ return results if raw_output
65
+
66
+ results.each(&block) if block_given?
57
67
 
58
- return_result(result, raw_output, bulk, model_class)
68
+ results
59
69
  end
60
70
 
61
71
  # Resume a bulk query job, which you previously started, and get records
@@ -12,17 +12,28 @@ module SfCli
12
12
  end
13
13
 
14
14
  def generate(object_name)
15
+ return false if generated? object_name
16
+
15
17
  schema = describe(object_name)
16
18
  class_definition = ClassDefinition.new(schema)
17
19
 
18
20
  instance_eval "::#{object_name} = #{class_definition}"
19
21
  klass = Object.const_get object_name.to_sym
20
22
  klass.connection = connection
23
+
24
+ true
21
25
  end
22
26
 
23
27
  def describe(object_name)
24
28
  connection.describe object_name
25
29
  end
30
+
31
+ def generated?(object_name)
32
+ Object.const_get object_name.to_sym
33
+ true
34
+ rescue NameError
35
+ false
36
+ end
26
37
  end
27
38
  end
28
39
  end
@@ -40,7 +40,7 @@ module SfCli
40
40
  def not(*expr)
41
41
  return self unless valid_expr?(expr)
42
42
 
43
- conditions.append %|NOT(#{to_string_expr(expr)})|
43
+ conditions.append %|(NOT(#{to_string_expr(expr)}))|
44
44
  self
45
45
  end
46
46
 
@@ -132,6 +132,8 @@ module SfCli
132
132
  %|'#{expr[2]}'|
133
133
  when :Time
134
134
  expr[2].to_datetime
135
+ when :NilClass
136
+ :null
135
137
  when :Array
136
138
  candidates = expr[2].map do |o|
137
139
  case o.class.name.to_sym
@@ -139,11 +141,13 @@ module SfCli
139
141
  %|'#{o}'|
140
142
  when :Time
141
143
  o.to_datetime
144
+ when :NilClass
145
+ :null
142
146
  else
143
147
  o
144
148
  end
145
149
  end
146
- %|IN (#{candidates.join(', ')})|
150
+ %|(#{candidates.join(', ')})|
147
151
  else
148
152
  expr[2]
149
153
  end
@@ -165,6 +169,8 @@ module SfCli
165
169
  %|#{k} = '#{v}'|
166
170
  when :Time
167
171
  %|#{k} = #{v.to_datetime}|
172
+ when :NilClass
173
+ %|#{k} = null|
168
174
  when :Array
169
175
  candidates = v.map do |o|
170
176
  case o.class.name.to_sym
@@ -172,6 +178,8 @@ module SfCli
172
178
  %|'#{o}'|
173
179
  when :Time
174
180
  %|#{o.to_datetime}|
181
+ when :NilClass
182
+ :null
175
183
  else
176
184
  o
177
185
  end
@@ -1,7 +1,7 @@
1
1
  module SfCli::Sf::Org
2
2
  module ListLimits
3
3
  #
4
- # Returns the metadata types that are enabled for your org.
4
+ # List the limits in your org
5
5
  # @param target_org [Symbol,String] an alias of paticular org, or username can be used
6
6
  # @param api_version [Numeric] override the api version used for api requests made by this command
7
7
  #
@@ -1,7 +1,7 @@
1
1
  module SfCli::Sf::Org
2
2
  module ListMetadata
3
3
  #
4
- # Returns the metadata types that are enabled for your org.
4
+ # List the metadata components and properties of a specified type
5
5
  # @param metadata [Symbol,String] name of metadata type
6
6
  # @param folder [Symbol,String] folder associated with the component such as Report, EmailTemplate, Dashboard and Document
7
7
  # @param target_org [Symbol,String] an alias of paticular org, or username can be used
@@ -1,6 +1,6 @@
1
1
  module SfCli::Sf::Org
2
2
  module Login
3
- # Login to the org by the browser.
3
+ # Log in to a Salesforce org using the web server flow
4
4
  # @param target_org [Symbol,String] an alias of paticular org, or username can be used
5
5
  # @param instance_url [String] URL of the instance that the org lives on.
6
6
  # @param browser [Symbol,String] browser in which to open the org.
@@ -3,7 +3,7 @@ module SfCli::Sf::Project
3
3
  Result = Struct.new(:output_dir, :files, :raw_output, :warnings)
4
4
 
5
5
  #
6
- # Generate a Salesforce project
6
+ # Generate a Salesforce DX project
7
7
  # @param name [Symbol,String] project name
8
8
  # @param template [Symbol,String] project template name
9
9
  # @param output_dir [String] output directory
@@ -1,6 +1,6 @@
1
1
  module SfCli::Sf::Project
2
2
  module GenerateManifest
3
- # Generate the manifest file of a Salesforce DX project
3
+ # Create a project manifest that lists the metadata components you want to deploy or retrieve
4
4
  # @param metadata [Array] an array that consists of metadata type like CustomObject, Layout and so on. (default: [])
5
5
  # @param api_version [Integer] API version (default: nil)
6
6
  # @param output_dir [String] manifest's output directory in the project directory. You can use relative path from the project root (default: nil)
@@ -2,7 +2,7 @@ require_relative './schema'
2
2
 
3
3
  module SfCli::Sf::Sobject
4
4
  module Describe
5
- # Returns a schema object containing the Salesforce object schema
5
+ # Get a Salesforce object schema
6
6
  # @param object_type [Symbol,String] object type(ex: Account)
7
7
  # @param target_org [Symbol,String] an alias of paticular org, or username can be used
8
8
  # @param api_version [Numeric] override the api version used for api requests made by this command
@@ -1,6 +1,6 @@
1
1
  module SfCli::Sf::Sobject
2
2
  module List
3
- # Returns a list of Salesforce object name
3
+ # List all Salesforce objects of a specified category.
4
4
  # @param object_type [Symbol,String] 'all' or 'custom'
5
5
  # @param target_org [Symbol,String] an alias of paticular org, or username can be used
6
6
  # @param api_version [Numeric] override the api version used for api requests made by this command
@@ -19,29 +19,51 @@ module SfCli
19
19
  end
20
20
 
21
21
  def field_names
22
- @field_names ||= fields.map{|f| f.name.to_sym}
22
+ @field_names ||= fields.map{|f| f.name.to_sym}.sort
23
23
  end
24
24
 
25
25
  def field_labels
26
- @field_labels ||= fields.map{|f| f.label}
26
+ @field_labels ||= fields.map{|f| f.label}.sort
27
27
  end
28
28
 
29
29
  def children_relations
30
- schema['childRelationships']
31
- .select{|r| r['relationshipName'].nil? == false}
32
- .map{|r| {name: r['relationshipName'].to_sym, field: r['field'].to_sym, class_name: r['childSObject'].to_sym}}
30
+ @children_relations ||=
31
+ schema['childRelationships']
32
+ .select{|r| r['relationshipName'].nil? == false}
33
+ .map{|r| {name: r['relationshipName'].to_sym, field: r['field'].to_sym, class_name: r['childSObject'].to_sym}}
33
34
  end
34
35
 
35
36
  def parent_relations
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} }
37
+ @parent_relations ||=
38
+ fields
39
+ .select{|f| !(f.relationship_name.nil? || f.reference_to.nil?) && f.reference_to.size > 0}
40
+ .map{|f| {name: f.relationship_name.to_sym, field: f.name.to_sym, class_name: f.reference_to.first.to_sym} }
41
+ end
42
+
43
+ def relations
44
+ @relations ||= Relations.new(children_relations + parent_relations)
39
45
  end
40
46
 
41
47
  def to_h
42
48
  schema
43
49
  end
44
50
 
51
+ def action_overrides
52
+ schema["actionOverrides"]
53
+ end
54
+
55
+ def activateable?
56
+ schema["activateable"]
57
+ end
58
+
59
+ def associateEntityType
60
+ schema["associateEntityType"]
61
+ end
62
+
63
+ def associateParentEntity
64
+ schema["associateParentEntity"]
65
+ end
66
+
45
67
  def compact_layoutable?
46
68
  schema["compactLayoutable"]
47
69
  end
@@ -196,6 +218,35 @@ module SfCli
196
218
  @schema
197
219
  end
198
220
 
221
+ Relation = Struct.new(:name, :field, :class_name)
222
+
223
+ class Relations
224
+ include Enumerable
225
+
226
+ def initialize(relations)
227
+ @relations = relations.map{|r| Relation.new(name: r[:name], field: r[:field], class_name: r[:class_name])}
228
+ end
229
+
230
+ def each(&block)
231
+ relations.each(&block)
232
+ end
233
+
234
+ def names
235
+ map(&:name).sort
236
+ end
237
+
238
+ def find(name)
239
+ relations.find{|r| r.name == name.to_sym}
240
+ end
241
+
242
+ private
243
+
244
+ def relations
245
+ @relations
246
+ end
247
+ end
248
+
249
+
199
250
  class Fields
200
251
  include Enumerable
201
252
 
@@ -219,7 +270,7 @@ module SfCli
219
270
 
220
271
  find do |field|
221
272
  attr_val = field.__send__(attr_name.to_sym)
222
- attr_val == val
273
+ attr_val == val.to_s
223
274
  end
224
275
  end
225
276
 
@@ -1,3 +1,3 @@
1
1
  module SfCli
2
- VERSION = '1.2.0'
2
+ VERSION = '1.2.2'
3
3
  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: 1.2.0
4
+ version: 1.2.2
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-10-01 00:00:00.000000000 Z
11
+ date: 2024-10-15 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.
@@ -16,10 +16,8 @@ email:
16
16
  executables:
17
17
  - sf_cli
18
18
  extensions: []
19
- extra_rdoc_files:
20
- - README.rdoc
19
+ extra_rdoc_files: []
21
20
  files:
22
- - README.rdoc
23
21
  - bin/sf_cli
24
22
  - lib/sf_cli.rb
25
23
  - lib/sf_cli/console.rb
data/README.rdoc DELETED
@@ -1,94 +0,0 @@
1
- = Salesforce CLI library for Ruby
2
- https://badge.fury.io/rb/sf_cli.png
3
-
4
- This is a class library for introducing {Salesforce CLI}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_top.htm] to Ruby scripting.<br>
5
- It is designed to be similar usability to the original command.<br>
6
- Currently only *sf* command is the target of development.
7
-
8
- [rubygems] https://rubygems.org/gems/sf_cli
9
- [official document] https://tmkw.github.io/sf_cli/
10
-
11
- == prerequisite
12
- {Salesforce CLI}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_top.htm] must be installed.<br>
13
- As of as of September in 2024, ver.2.56.7 is the development target.
14
-
15
- == install
16
- Rubygem::
17
- the simplest way:
18
- $ gem install sf_cli
19
- Bundler::
20
- in Gemfile:
21
- gem 'sf_cli'
22
- then,
23
- $ bundle install
24
- == Usage
25
- Load module
26
- require 'sf_cli'
27
-
28
- Login to org
29
- sf.org.login_web
30
-
31
- Get Salesforce Object schema
32
- sf.sobject.describe :Account
33
-
34
- Get a record
35
- sf.data.get_record :Account, record_id: 'xxxxxxx'
36
- sf.data.get_record :Account, where: {Name: 'Jonny B.Good', Country: 'USA'}
37
-
38
- Execute SOQL
39
- sf.data.query "SELECT Id, Name FROM Account LIMIT 1" # => [{Id: "abc", Name: "account name"}]
40
-
41
- Create a record
42
- sf.data.create_record :TheCustomObject__c, values: {Name: "John Smith", Age: 33}
43
-
44
- Update a record
45
- sf.data.update_record :Account, record_id: 'xxxxxxx', values: {Name: 'New Account Name'}
46
- sf.data.update_record :Hoge__c, where: {Name: 'Jonny B.Good', Country: 'USA'}, values: {Phone: 'xxxxx', bar: 2000}
47
-
48
- Delete a record
49
- sf.data.delete_record :Hoge__c, record_id: 'xxxxxxx'
50
- sf.data.delete_record :Hoge__c, where: {Name: 'Jonny B.Good', Country: 'USA'}
51
-
52
- Using Bulk API 2.0
53
- sf.data.upsert_bulk sobject: :TestCustomObject__c, file: 'upsert.csv', wait: 5 # waiting for 5 minutes at maximum
54
-
55
- Run Apex
56
- sf.apex.run file: 'path/to/file'
57
- sf.apex.run file: StringIO.new("System.debug('Hello World')")
58
- == Object Model Support
59
- With sf command:
60
- rows = sf.data.query "SELECT Id, Name FROM Contact WHERE Name = 'Akin Kristen'", model_class: Contact
61
- rows.first # <Contact: @Id="0035j00001RW3xbAAD", @Name="Akin Kristen">
62
- rows.first.Name # Akin Kristen
63
- Doing the same thing independently:
64
- contact = Contact.select(:Id, :Name).where(Name: 'Akin Kristen').take
65
- contact.Name # Akin Kristen
66
- == Developer Console
67
- Developer console integrates both sf_cli's command methods and object model librry into IRB to make scripting easier in REPL.
68
-
69
- You can directly use sf_cli's command methods:
70
- $ sf_cli -i
71
- > sf.query "SELECT Id, Name FROM Case", target_org: :your_org
72
-
73
- Object Model is also available:
74
- > use :your_org_name
75
- > gen :Account, :Contact, :User #=> generate 3 Object model classes
76
- > acc = Account.find_by Name: 'Hoge Fuga'
77
-
78
- There are some other console commands:
79
- > query "SELECT Id, Name, ... FROM BazBar__c" # just same as `sf data query` with human readable format
80
- > apex "System.debug('abc');" # execute Apex code instantly
81
-
82
- Type *help* to know all console commands
83
-
84
- == Utility
85
- sf_cli command also have other functions. As of 1.2.0, it can generate Salesforce DX project.
86
-
87
- Create a project directory and files including manifest file
88
- $ sf_cli -g project YOUR_PROJECT_NAME
89
-
90
- Same as above, but the manifest file is built based on the org
91
- $ sf_cli -g project YOUR_PROJECT_NAME -o YOUR_TARGET_ORG
92
-
93
- Build project and manifest then retreave metadata such as Apex code at once
94
- $ sf_cli -g project YOUR_PROJECT_NAME -o YOUR_TARGET_ORG -r