sf_cli 1.2.0 → 1.2.2

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: 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