sf_cli 1.2.4 → 1.3.0

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: e22af218b203252c97bf0021671105be00d1af29161b2a087e23256cc81d8505
4
- data.tar.gz: a8a84e90555ebd665651137ea7d339768f68cb211ab9d1c10df328bbb2f28842
3
+ metadata.gz: a644e819d71225a7ac587cd46e40d47d2c1d766a4cc7ff237c9d90ffd9b3ab2c
4
+ data.tar.gz: 806e3a803d8a7fdbafab63930c7c4cbe0438819804a8a37e71fdcac2d565378b
5
5
  SHA512:
6
- metadata.gz: 64e83911a17efb2b59760c52e5722e9437c83888dea7a05c4a56477c24f919b6c35b43a96fb19e20dfec15cdea0ade7c501d8f40b214971b6da2263dc393ee20
7
- data.tar.gz: f1b8fc98e0c1f3f429b9cc6af47a50bdb32b71014dc530c430225591d8ea08ae238347fe293d141870c51fa5608c06113bc52f9a8c953728317ff456fa119cc5
6
+ metadata.gz: 0c61efe52e48624aa6948ec16df153b15a813207096bbdc72239d25a43b9b9105d7d5e8d2f5d1e165b9ad03d779cf65fcec9978f4b1ef47afb923a327805eea6
7
+ data.tar.gz: cb0d416817d9e4d698b87db6353083aee9a14aa860c86b166396bb3ce66f640c4c74d89906bbfd203a53b63c27ee90d69f62b67ecb9f529e3bea81115d7507eb
@@ -1,8 +1,5 @@
1
1
  require 'sf_cli'
2
2
  require 'byebug'
3
- require 'sf_cli/sf/model'
4
- require 'sf_cli/sf/model/query_condition'
5
- require 'sf_cli/sf/model/sf_command_connection'
6
3
  require 'stringio'
7
4
 
8
5
  module SfCli
@@ -12,36 +9,8 @@ module SfCli
12
9
  # Developer Console commands
13
10
  #
14
11
  module Commands
15
- def use(target_org)
16
- org_info = sf.org.display target_org: target_org
17
- conn = SfCli::Sf::Model::SfCommandConnection.new target_org: target_org, instance_url: org_info.instance_url
18
- conn.open unless org_info.connected?
19
-
20
- SfCli::Sf::Model.set_connection conn
21
-
22
- available_models.each do |model|
23
- Object.const_get(model).connection = conn
24
- end
25
-
26
- true
27
- end
28
-
29
- def available_models
30
- @available_models ||= []
31
- end
32
-
33
- def generate(*object_types)
34
- SfCli::Sf::Model.generate object_types
35
- available_models.append(*object_types).flatten
36
- object_types
37
- end
38
-
39
- def connection
40
- SfCli::Sf::Model.connection
41
- end
42
-
43
12
  def target_org
44
- connection.target_org
13
+ @target_org
45
14
  end
46
15
 
47
16
  def apex(apex_code = nil)
@@ -62,68 +31,6 @@ module SfCli
62
31
  system 'sf org list'
63
32
  conf.inspect_mode = true
64
33
  end
65
-
66
- alias :gen :generate
67
- alias :conn :connection
68
-
69
- def help
70
- conf.inspect_mode = false
71
- puts <<~HELP
72
- Available commands:
73
- use --- set current org.
74
- gen --- generate Object model classes
75
- query --- Query by SOQL with human readable format
76
- apex --- run Apex code
77
- conn --- show current connection setting
78
- orgs --- show the list of org
79
-
80
- Syntax:
81
- [use]
82
- use target-org
83
-
84
- parameters:
85
- targat-org --- Username or alias of the org you are going to use. If you are not sure about them, check by `sf org list`.
86
-
87
- example:
88
- use :your_org_alias
89
-
90
- [gen]
91
- gen object-name, object-name, ...
92
- generate object-name, object-name, ...
93
-
94
- parameters:
95
- object-name --- Comma separated Names. Symbol or String can be OK. At least 1 object name is required.
96
-
97
- example:
98
- gen :Account, :Contact, :User
99
-
100
- [query]
101
- query SOQL
102
-
103
- parameters:
104
- SOQL --- soql.You must quote it like "SELECT ...."
105
-
106
- example:
107
- query "SELECT Id, Name FROM Account LIMIT 3"
108
-
109
- [apex]
110
- apex apex_code
111
-
112
- parameters:
113
- apex code --- Apex code you want to execute.You must quote the code.
114
-
115
- example:
116
- apex "System.debug('abc');"
117
-
118
- [conn]
119
- conn
120
- connection
121
-
122
- [orgs]
123
- orgs
124
- HELP
125
- conf.inspect_mode = true
126
- end
127
34
  end
128
35
  end
129
36
  end
@@ -2,4 +2,4 @@ require 'sf_cli/console/commands'
2
2
 
3
3
  include SfCli::Console::Commands
4
4
 
5
- use ARGV[0] if ARGV[0]
5
+ @target_org = ARGV[0]
@@ -1,5 +1,6 @@
1
1
  require_relative '../core/base'
2
2
  require_relative './run'
3
+ require_relative './generate'
3
4
 
4
5
  module SfCli
5
6
  module Sf
@@ -12,6 +13,7 @@ module SfCli
12
13
  class Core
13
14
  include ::SfCli::Sf::Core::Base
14
15
  include Run
16
+ include Generate
15
17
  end
16
18
  end
17
19
  end
@@ -0,0 +1,63 @@
1
+ module SfCli::Sf::Apex
2
+ module Generate
3
+ # Generate an Apex class
4
+ # @param name [String,Symbol] Apex class name
5
+ # @param output_dir [String] directory for saving the created files
6
+ # @param template [String,Symbol] template to use for file creation.Permissible values are: ApexException, ApexUnitTest, BasicUnitTest, DefaultApexClass, InboundEmailService
7
+ # @param api_version [Numeric] override the api version used for api requests made by this command
8
+ # @param raw_output [Boolian] output what original command shows
9
+ #
10
+ # @return [Array] the list of files that is created
11
+ #
12
+ # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_apex_commands_unified.htm#cli_reference_apex_generate_class_unified command reference
13
+ #
14
+ def generate_class(name, output_dir: nil, template: nil, api_version: nil, raw_output: false)
15
+ flags = {
16
+ :"name" => name,
17
+ :"output-dir" => output_dir,
18
+ :"template" => template,
19
+ :"api-version" => api_version,
20
+ }
21
+ switches = {
22
+ }
23
+ command_output_format = raw_output ? :human : :json
24
+ redirect_type = raw_output ? nil : :null_stderr
25
+ action = __method__.to_s.tr('_', ' ')
26
+ output = exec(action, flags: flags, switches: switches, redirection: redirect_type, raw_output: raw_output, format: command_output_format)
27
+ return output if raw_output
28
+
29
+ output['result']['created']
30
+ end
31
+
32
+ # Generate an Apex trigger
33
+ # @param name [String,Symbol] Name of the generated Apex trigger
34
+ # @param output_dir [String] directory for saving the created files
35
+ # @param sobject [String,Symbol] Salesforce object to generate a trigger on
36
+ # @param event [Array] Events that fire the trigger.Permissible values are: "before insert", "before update", "before delete", "after insert", "after update", "after delete", "after undelete"
37
+ # @param api_version [Numeric] override the api version used for api requests made by this command
38
+ # @param raw_output [Boolian] output what original command shows
39
+ #
40
+ # @return [Array] the list of files that is created
41
+ #
42
+ # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_apex_commands_unified.htm#cli_reference_apex_generate_trigger_unified command reference
43
+ #
44
+ def generate_trigger(name, output_dir: nil, sobject: nil, event: nil, api_version: nil, raw_output: false)
45
+ flags = {
46
+ :"name" => name,
47
+ :"output-dir" => output_dir,
48
+ :"sobject" => sobject,
49
+ :"event" => event&.map{|ev| %|"#{ev}"|}&.join(' '),
50
+ :"api-version" => api_version,
51
+ }
52
+ switches = {
53
+ }
54
+ command_output_format = raw_output ? :human : :json
55
+ redirect_type = raw_output ? nil : :null_stderr
56
+ action = __method__.to_s.tr('_', ' ')
57
+ output = exec(action, flags: flags, switches: switches, redirection: redirect_type, raw_output: raw_output, format: command_output_format)
58
+ return output if raw_output
59
+
60
+ output['result']['created']
61
+ end
62
+ end
63
+ end
@@ -47,8 +47,11 @@ module SfCli
47
47
  if format.to_sym == :json
48
48
  ' ' + {json: true}.merge(hash).each_with_object([]){|(k,v), arr| arr << %(--#{k}) if v}.join(' ')
49
49
  else
50
- return '' if hash.empty?
51
- hash.each_with_object([]){|(k,v), arr| arr << %(--#{k}) if v}.join(' ')
50
+ options = hash.each_with_object([]){|(k,v), arr| arr << %(--#{k}) if v}.join(' ')
51
+ return '' if options.empty?
52
+
53
+ options = ' ' + options unless options.start_with?(' ')
54
+ return options
52
55
  end
53
56
  end
54
57
 
@@ -0,0 +1,19 @@
1
+ require_relative '../core/base'
2
+ require_relative './generate'
3
+
4
+ module SfCli
5
+ module Sf
6
+ #
7
+ # Lightning Commands
8
+ #
9
+ # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_lightning_commands_unified.htm command reference
10
+ #
11
+ module Lightning
12
+ # @private :nodoc: just for developers
13
+ class Core
14
+ include ::SfCli::Sf::Core::Base
15
+ include Generate
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module SfCli::Sf::Lightning
2
+ module Generate
3
+ # Generate an Apex class
4
+ # @param name [String,Symbol] component name
5
+ # @param type [String,Symbol] component type.Only aura or lwc is permissible.
6
+ # @param output_dir [String] directory for saving the created files
7
+ # @param template [String,Symbol] Template to use for file creation.Permissible values are: default, analyticsDashboard, analyticsDashboardWithStep
8
+ # @param api_version [Numeric] override the api version used for api requests made by this command
9
+ # @param raw_output [Boolian] output what original command shows
10
+ #
11
+ # @return [Array] the list of files that is created
12
+ #
13
+ # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_lightning_commands_unified.htm#cli_reference_lightning_generate_component_unified command reference
14
+ #
15
+ def generate_component(name, type: nil, output_dir: nil, template: nil, api_version: nil, raw_output: false)
16
+ flags = {
17
+ :"name" => name,
18
+ :"output-dir" => output_dir,
19
+ :"type" => type,
20
+ :"template" => template,
21
+ :"api-version" => api_version,
22
+ }
23
+ switches = {
24
+ }
25
+ command_output_format = raw_output ? :human : :json
26
+ redirect_type = raw_output ? nil : :null_stderr
27
+ action = __method__.to_s.tr('_', ' ')
28
+ output = exec(action, flags: flags, switches: switches, redirection: redirect_type, raw_output: raw_output, format: command_output_format)
29
+ return output if raw_output
30
+
31
+ output['result']['created']
32
+ end
33
+ end
34
+ end
@@ -15,7 +15,7 @@ module SfCli
15
15
  class Main
16
16
  include Singleton
17
17
 
18
- OPERATION_CATEGORIES = %w[Org Sobject Data Project Apex]
18
+ OPERATION_CATEGORIES = %w[Org Sobject Data Project Apex Lightning]
19
19
 
20
20
  OPERATION_CATEGORIES.each do |category|
21
21
  require_relative %(#{category.downcase}/core)
@@ -2,6 +2,7 @@ require_relative '../core/base'
2
2
  require_relative './generate'
3
3
  require_relative './generate_manifest'
4
4
  require_relative './retrieve_start'
5
+ require_relative './deploy_start'
5
6
 
6
7
  module SfCli
7
8
  module Sf
@@ -17,6 +18,7 @@ module SfCli
17
18
  include Generate
18
19
  include GenerateManifest
19
20
  include RetrieveStart
21
+ include DeployStart
20
22
  end
21
23
  end
22
24
  end
@@ -0,0 +1,80 @@
1
+ module SfCli::Sf::Project
2
+ module DeployStart
3
+ Result = Struct.new(:done, :details, :id, :status, :success, :files) do
4
+ def success?
5
+ success
6
+ end
7
+ end
8
+
9
+ DeployedFile = Data.define(:full_name, :type, :state, :file_path)
10
+
11
+ # Deploy metadata to an org from your local project.
12
+ # @param manifest [String] path of the manifest file(package.xml) that specifies the components to retrieve
13
+ # @param metadata [Array] metadata names that specifies the components to retrieve
14
+ # @param source_dir [String] file or directory path to retrieve from the org.
15
+ # @param target_org [Symbol,String] an alias of paticular org, or username can be used
16
+ # @param api_version [Numeric] override the api version used for api requests made by this command
17
+ # @param wait [Integer] number of minutes to wait for command to complete
18
+ # @param raw_output [Boolian] output what original command shows
19
+ # @param dry_run [Boolian] validate deploy and run Apex tests but don’t save to the org.
20
+ # @param ignore_conflicts [Boolian] ignore conflicts and deploy local files, even if they overwrite changes in the org.
21
+ # @param ignore_errors [Boolian] ignore any errors and don’t roll back deployment. Never use this flag when deploying to a production org.
22
+ # @param ignore_warnings [Boolian] ignore warnings and allow a deployment to complete successfully.
23
+ # @param metadata_dir [Symbol,String] root of directory or zip file of metadata formatted files to deploy.
24
+ # @param single_package [Boolian] indicates that the metadata zip file points to a directory structure for a single package.
25
+ # @param tests [Array] Apex tests to run when --test-level is RunSpecifiedTests.
26
+ # @param test_level [Symbol,String] deployment Apex testing level. Available values are NoTestRun, RunSpecifiedTests, RunLocalTests, RunAllTestsInOrg.
27
+ #
28
+ # @return [Result] the retsult of the command
29
+ #
30
+ # @see https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_project_commands_unified.htm#cli_reference_project_deploy_start_unified command reference
31
+ #
32
+ def deploy_start(metadata: nil, manifest: nil, source_dir: nil, target_org: nil, raw_output: false, metadata_dir: nil, tests: nil, test_level: nil,
33
+ api_version: nil, wait: nil, dry_run: false, ignore_conflicts: false, ignore_errors: false, ignore_warnings: false, single_package: false)
34
+
35
+ flags = {
36
+ :manifest => manifest,
37
+ :metadata => metadata&.join(' '),
38
+ :"source-dir" => source_dir,
39
+ :"target-org" => target_org,
40
+ :"api-version" => api_version,
41
+ :"metadata-dir" => metadata_dir,
42
+ :tests => tests&.join(' '),
43
+ :"test-level" => test_level,
44
+ :"wait" => wait,
45
+ }
46
+ switches = {
47
+ :"dry-run" => dry_run,
48
+ :"ignore-conflicts" => ignore_conflicts,
49
+ :"ignore-errors" => ignore_errors,
50
+ :"ignore-warnings" => ignore_warnings,
51
+ :"single-package" => single_package,
52
+ }
53
+ action = __method__.to_s.tr('_', ' ')
54
+ command_output_format = raw_output ? :human : :json
55
+ redirect_type = raw_output ? nil : :null_stderr
56
+ output = exec(action, flags: flags, switches: switches, redirection: redirect_type, raw_output: raw_output, format: command_output_format)
57
+ return output if raw_output
58
+
59
+ Result.new(
60
+ done: output['result']['done'],
61
+ id: output['result']['id'],
62
+ details: output['result']['details'],
63
+ status: output['result']['status'],
64
+ success: output['result']['success'],
65
+ files: output['result']['files'].map{|f| create_deployed_file(f)}
66
+ )
67
+ end
68
+
69
+ private
70
+
71
+ def create_deployed_file(hash)
72
+ DeployedFile.new(
73
+ full_name: hash['fullName'],
74
+ type: hash['type'],
75
+ state: hash['state'],
76
+ file_path: hash['filePath']
77
+ )
78
+ end
79
+ end
80
+ end
@@ -1,3 +1,3 @@
1
1
  module SfCli
2
- VERSION = '1.2.4'
2
+ VERSION = '1.3.0'
3
3
  end
metadata CHANGED
@@ -1,28 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sf_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.0
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-11-04 00:00:00.000000000 Z
11
+ date: 2024-11-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A library for introducing Salesforce CLI to Ruby scripting.
14
14
  email:
15
- executables:
16
- - sf_cli
15
+ executables: []
17
16
  extensions: []
18
17
  extra_rdoc_files: []
19
18
  files:
20
- - bin/sf_cli
21
19
  - lib/sf_cli.rb
22
20
  - lib/sf_cli/command_exec_error.rb
23
21
  - lib/sf_cli/console.rb
24
22
  - lib/sf_cli/console/commands.rb
25
23
  - lib/sf_cli/sf/apex/core.rb
24
+ - lib/sf_cli/sf/apex/generate.rb
26
25
  - lib/sf_cli/sf/apex/run.rb
27
26
  - lib/sf_cli/sf/core/base.rb
28
27
  - lib/sf_cli/sf/core/org_base.rb
@@ -41,15 +40,9 @@ files:
41
40
  - lib/sf_cli/sf/data/update_record.rb
42
41
  - lib/sf_cli/sf/data/upsert_bulk.rb
43
42
  - lib/sf_cli/sf/data/upsert_resume.rb
43
+ - lib/sf_cli/sf/lightning/core.rb
44
+ - lib/sf_cli/sf/lightning/generate.rb
44
45
  - lib/sf_cli/sf/main.rb
45
- - lib/sf_cli/sf/model.rb
46
- - lib/sf_cli/sf/model/base_methods.rb
47
- - lib/sf_cli/sf/model/class_definition.rb
48
- - lib/sf_cli/sf/model/dml_methods.rb
49
- - lib/sf_cli/sf/model/generator.rb
50
- - lib/sf_cli/sf/model/query_condition.rb
51
- - lib/sf_cli/sf/model/query_methods.rb
52
- - lib/sf_cli/sf/model/sf_command_connection.rb
53
46
  - lib/sf_cli/sf/org/core.rb
54
47
  - lib/sf_cli/sf/org/display.rb
55
48
  - lib/sf_cli/sf/org/list.rb
@@ -58,6 +51,7 @@ files:
58
51
  - lib/sf_cli/sf/org/list_metadata_types.rb
59
52
  - lib/sf_cli/sf/org/login.rb
60
53
  - lib/sf_cli/sf/project/core.rb
54
+ - lib/sf_cli/sf/project/deploy_start.rb
61
55
  - lib/sf_cli/sf/project/generate.rb
62
56
  - lib/sf_cli/sf/project/generate_manifest.rb
63
57
  - lib/sf_cli/sf/project/retrieve_start.rb
data/bin/sf_cli DELETED
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'optparse'
4
- require 'sf_cli'
5
- require 'sf_cli/version'
6
-
7
- def generate_project(project_name, params)
8
- base_dir = Dir.pwd
9
- target_org = params[:"target-org"]
10
- retrieve_source = params[:retrieve]
11
- editor = params[:editor]
12
-
13
- sf.project.generate project_name, manifest: true
14
-
15
- Dir.chdir project_name
16
-
17
- sf.project.generate_manifest from_org: target_org, output_dir: 'manifest' if target_org
18
- sf.project.retrieve_start manifest: 'manifest/package.xml', target_org: target_org if retrieve_source
19
- system 'code .' if editor
20
- ensure
21
- Dir.chdir base_dir
22
- end
23
-
24
- params = {}
25
- opt = OptionParser.new
26
- Version = SfCli::VERSION
27
-
28
- opt.on('-i', '--irb', 'Start irb session that integrates sf_cli and object model library.') { system 'irb -r sf_cli/console' }
29
- opt.on('-g OBJECT', '--generate', 'Generate OBJECT. As of now, only project is available as OBJECT.')
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')
33
-
34
- opt.parse!(ARGV, into: params)
35
-
36
- if params[:generate] == 'project'
37
- generate_project(ARGV[0], params)
38
- elsif params[:editor]
39
- system 'code .'
40
- end
@@ -1,63 +0,0 @@
1
- module SfCli
2
- module Sf
3
- module Model
4
- # @private :nodoc: just for developers
5
- module BaseMethods
6
- def self.included(c)
7
- c.extend ClassMethods
8
- end
9
-
10
- module ClassMethods
11
- def connection
12
- @connection
13
- end
14
-
15
- def connection=(conn)
16
- @connection = conn
17
- end
18
-
19
- def describe
20
- connection.describe(name.to_sym)
21
- end
22
- end
23
-
24
- def initialize(attributes = {})
25
- @original_attributes = {}
26
- @current_attributes = {}
27
- @updated_attributes = {}
28
-
29
- attributes.each do |k, v|
30
- field_name = k.to_sym
31
- if self.class.field_names.include?(field_name)
32
- @original_attributes[field_name] = v
33
- __send__ (field_name.to_s + '='), v
34
- elsif self.class.parent_relations.find{|r| r[:name] == field_name}
35
- __send__ (field_name.to_s + '='), v
36
- elsif self.class.children_relations.find{|r| r[:name] == field_name}
37
- __send__ (field_name.to_s + '='), (v.nil? ? [] : v)
38
- end
39
- end
40
- end
41
-
42
- def to_h(keys: nil)
43
- self.class.field_names.each_with_object({}) do |name, hash|
44
- if keys&.instance_of?(Array)
45
- hash[name] = __send__(name) if keys.include?(name)
46
- else
47
- hash[name] = __send__(name)
48
- end
49
- end
50
- end
51
-
52
- def new_record?
53
- self.Id.nil?
54
- end
55
-
56
- def persisted?
57
- new_record? == false
58
- end
59
- end
60
- end
61
- end
62
- end
63
-
@@ -1,104 +0,0 @@
1
- require_relative './base_methods'
2
- require_relative './dml_methods'
3
- require_relative './query_methods'
4
-
5
- module SfCli
6
- module Sf
7
- module Model
8
- # @private :nodoc: just for developers
9
- class ClassDefinition
10
- attr_reader :schema
11
-
12
- def initialize(schema)
13
- @schema = schema
14
- end
15
-
16
- def to_s
17
- <<~Klass
18
- Class.new do
19
- include ::SfCli::Sf::Model::BaseMethods
20
- include ::SfCli::Sf::Model::DmlMethods
21
- include ::SfCli::Sf::Model::QueryMethods
22
-
23
- attr_reader :original_attributes, :current_attributes, :updated_attributes
24
-
25
- #{ class_methods }
26
-
27
- #{ field_attribute_methods }
28
- #{ parent_relation_methods }
29
- #{ children_relation_methods }
30
- end
31
- Klass
32
- end
33
-
34
- def class_methods
35
- <<~EOS
36
- class << self
37
- def field_names
38
- @field_names ||= #{ schema.field_names }
39
- end
40
-
41
- def parent_relations
42
- @parent_relations ||= #{ schema.parent_relations }
43
- end
44
-
45
- def children_relations
46
- @children_relations ||= #{ schema.children_relations }
47
- end
48
- end
49
- EOS
50
- end
51
-
52
- def field_attribute_methods
53
- schema.field_names.each_with_object('') do |name, s|
54
- s << <<~EOS
55
- def #{name}
56
- @#{name}
57
- end
58
-
59
- def #{name}=(value)
60
- @#{name} = value
61
- return if %i[Id LastModifiedDate IsDeleted SystemModstamp CreatedById CreatedDate LastModifiedById].include?(:#{name})
62
-
63
- current_attributes[:#{name}] = value
64
- if current_attributes[:#{name}] == original_attributes[:#{name}]
65
- updated_attributes[:#{name}] = nil
66
- else
67
- updated_attributes[:#{name}] = value
68
- end
69
- end
70
- EOS
71
- end
72
- end
73
-
74
- def parent_relation_methods
75
- schema.parent_relations.each_with_object('') do |r, s|
76
- s << <<~EOS
77
- def #{r[:name]}
78
- @#{r[:name]}
79
- end
80
-
81
- def #{r[:name]}=(attributes)
82
- @#{r[:name]} = attributes.nil? ? nil : #{r[:class_name]}.new(attributes)
83
- end
84
- EOS
85
- end
86
- end
87
-
88
- def children_relation_methods
89
- schema.children_relations.each_with_object('') do |r, s|
90
- s << <<~EOS
91
- def #{r[:name]}
92
- @#{r[:name]}
93
- end
94
-
95
- def #{r[:name]}=(records)
96
- @#{r[:name]} = records.map{|attributes| #{r[:class_name]}.new(attributes)}
97
- end
98
- EOS
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,37 +0,0 @@
1
- module SfCli
2
- module Sf
3
- module Model
4
- # @private :nodoc: just for developers
5
- module DmlMethods
6
- def self.included(c)
7
- c.extend ClassMethods
8
- end
9
-
10
- def save
11
- if new_record?
12
- self.Id = self.class.connection.create(self.class.name.to_sym, current_attributes.reject{|_,v| v.nil?})
13
- else
14
- self.class.connection.update(self.class.name.to_sym, self.Id, updated_attributes.reject{|_,v| v.nil?})
15
- end
16
-
17
- @original_attributes = current_attributes.dup
18
- @updated_attributes = {}
19
-
20
- self.Id
21
- end
22
-
23
- def delete
24
- return if self.Id.nil?
25
-
26
- self.class.connection.delete(self.class.name.to_sym, self.Id)
27
- end
28
-
29
- module ClassMethods
30
- def create(values = {})
31
- connection.create(name.to_sym, values, Object.const_get(name.to_sym))
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,40 +0,0 @@
1
- require_relative './class_definition'
2
-
3
- module SfCli
4
- module Sf
5
- module Model
6
- # @private :nodoc: just for developers
7
- class Generator
8
- attr_reader :connection
9
-
10
- def initialize(connection)
11
- @connection = connection
12
- end
13
-
14
- def generate(object_name)
15
- return false if generated? object_name
16
-
17
- schema = describe(object_name)
18
- class_definition = ClassDefinition.new(schema)
19
-
20
- instance_eval "::#{object_name} = #{class_definition}"
21
- klass = Object.const_get object_name.to_sym
22
- klass.connection = connection
23
-
24
- true
25
- end
26
-
27
- def describe(object_name)
28
- connection.describe object_name
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
37
- end
38
- end
39
- end
40
- end
@@ -1,198 +0,0 @@
1
- require 'date'
2
-
3
- module SfCli
4
- module Sf
5
- module Model
6
- module QueryMethods
7
- # @private :nodoc: just for developers
8
- class QueryCondition
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
19
-
20
- def initialize(connection, object_name, field_names)
21
- @object_name = object_name
22
- @all_field_names = field_names
23
- @connection = connection
24
- @fields = []
25
- @conditions = []
26
- @limit_num = nil
27
- @row_order = nil
28
- @count_select = false
29
- @max_select_field = nil
30
- @min_select_field = nil
31
- end
32
-
33
- def where(*expr)
34
- return self unless valid_expr?(expr)
35
-
36
- conditions.append to_string_expr(expr)
37
- self
38
- end
39
-
40
- def not(*expr)
41
- return self unless valid_expr?(expr)
42
-
43
- conditions.append %|(NOT(#{to_string_expr(expr)}))|
44
- self
45
- end
46
-
47
- def select(*expr)
48
- return self if expr&.empty?
49
-
50
- if expr.size > 1
51
- @fields = self.fields + expr
52
- else
53
- self.fields << expr.first
54
- end
55
- return self
56
- end
57
-
58
- def limit(num)
59
- @limit_num = num
60
- return self
61
- end
62
-
63
- def order(*fields)
64
- return self if fields&.empty?
65
-
66
- @row_order = fields
67
- return self
68
- end
69
-
70
- def to_soql
71
- base = 'SELECT %{select} FROM %{object}' % {select: select_fields, object: object_name}
72
- where = conditions.size.zero? ? nil : 'WHERE %{where}' % {where: conditions.flatten.join(' AND ')}
73
- _order = row_order.nil? ? nil : 'ORDER BY %{order}' % {order: row_order.join(', ')}
74
- limit = limit_num.nil? ? nil : 'LIMIT %{limit}' % {limit: limit_num}
75
-
76
- [base, where, _order, limit].compact.join(' ')
77
- end
78
-
79
- def to_csv
80
- connection.query(to_soql, Object.const_get(object_name.to_sym), :csv)
81
- end
82
-
83
- def all
84
- connection.query(to_soql, Object.const_get(object_name.to_sym))
85
- end
86
-
87
- def pluck(field_name)
88
- connection.query(to_soql, nil).map{|record| record[field_name.to_s]}
89
- end
90
-
91
- def take
92
- limit(1).all.first
93
- end
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
-
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
-
117
- (fields.empty? ? all_field_names : fields).join(', ')
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 :NilClass
136
- :null
137
- when :Array
138
- candidates = expr[2].map do |o|
139
- case o.class.name.to_sym
140
- when :String
141
- %|'#{o}'|
142
- when :Time
143
- o.to_datetime
144
- when :NilClass
145
- :null
146
- else
147
- o
148
- end
149
- end
150
- %|(#{candidates.join(', ')})|
151
- else
152
- expr[2]
153
- end
154
- %|#{expr[0]} #{expr[1]} #{value}|
155
- end
156
-
157
- def valid_expr?(expr)
158
- return false if expr&.empty?
159
- return false if expr.map{|o| (o == '' || o == {} || o == []) ? nil : o}.compact.size.zero?
160
- return false unless [Hash, Symbol, String].any?{|klass| expr.first.instance_of? klass}
161
-
162
- true
163
- end
164
-
165
- def strs_by_hash_expr(expr)
166
- expr[0].map do |k,v|
167
- case v.class.name.to_sym
168
- when :String
169
- %|#{k} = '#{v}'|
170
- when :Time
171
- %|#{k} = #{v.to_datetime}|
172
- when :NilClass
173
- %|#{k} = null|
174
- when :Array
175
- candidates = v.map do |o|
176
- case o.class.name.to_sym
177
- when :String
178
- %|'#{o}'|
179
- when :Time
180
- %|#{o.to_datetime}|
181
- when :NilClass
182
- :null
183
- else
184
- o
185
- end
186
- end
187
- %|#{k} IN (#{candidates.join(', ')})|
188
- else
189
- "#{k} = #{v}"
190
- end
191
- end
192
- .join(' AND ')
193
- end
194
- end
195
- end
196
- end
197
- end
198
- end
@@ -1,84 +0,0 @@
1
- require_relative './query_condition'
2
-
3
- module SfCli
4
- module Sf
5
- module Model
6
- # @private :nodoc: just for developers
7
- module QueryMethods
8
- def self.included(c)
9
- c.extend ClassMethods
10
- end
11
-
12
- module ClassMethods
13
- def where(*expr)
14
- qc = QueryCondition.new(connection, self.name, self.field_names)
15
- qc.where(*expr)
16
- return qc
17
- end
18
-
19
- def select(*fields)
20
- qc = QueryCondition.new(connection, self.name, self.field_names)
21
- qc.select(*fields)
22
- return qc
23
- end
24
-
25
- def limit(num)
26
- qc = QueryCondition.new(connection, self.name, self.field_names)
27
- qc.limit(num)
28
- qc
29
- end
30
-
31
- def order(*field_names)
32
- qc = QueryCondition.new(connection, self.name, self.field_names)
33
- qc.order(*field_names)
34
- qc
35
- end
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
- def all
47
- qc = QueryCondition.new(connection, self.name, self.field_names)
48
- qc.all
49
- end
50
-
51
- def to_csv
52
- qc = QueryCondition.new(connection, self.name, self.field_names)
53
- qc.to_csv
54
- end
55
-
56
- def pluck(field_name)
57
- qc = QueryCondition.new(connection, self.name, self.field_names)
58
- qc.pluck(field_name)
59
- end
60
-
61
- def take
62
- qc = QueryCondition.new(connection, self.name, self.field_names)
63
- qc.take
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
80
- end
81
- end
82
- end
83
- end
84
- end
@@ -1,79 +0,0 @@
1
- require_relative '../sobject/core'
2
- require_relative '../data/core'
3
- require_relative '../org/core'
4
-
5
- module SfCli
6
- module Sf
7
- module Model
8
- #
9
- # Connection object to access Salesforce based on Sf command
10
- #
11
- class SfCommandConnection
12
- attr_reader :target_org, :instance_url
13
-
14
- # @private :nodoc: just for developers
15
- attr_reader :sf_data, :sf_org, :sf_sobject
16
-
17
- # @param target_org [Symbol,String] an alias of paticular org, or username can be used
18
- # @param instance_url [String] URL of the instance that the org lives on.
19
- #
20
- def initialize(target_org: nil, instance_url: nil)
21
- @sf_org = ::SfCli::Sf::Org::Core.new
22
- @sf_data = ::SfCli::Sf::Data::Core.new
23
- @sf_sobject = ::SfCli::Sf::Sobject::Core.new
24
- @target_org = target_org
25
- @instance_url = instance_url
26
- end
27
-
28
- def open
29
- if ENV['SF_ACCESS_TOKEN']
30
- sf_org.login_access_token target_org: target_org, instance_url: instance_url
31
- else
32
- sf_org.login_web target_org: target_org, instance_url: instance_url
33
- end
34
- end
35
-
36
- # Sf command style query interface for Model module
37
- #
38
- # For query details, see {SfCli::Sf::Data::Query sf data query}
39
- #
40
- def exec_query(soql, format: nil, bulk: false, wait: nil, model_class: nil)
41
- sf_data.query(soql, target_org: target_org, format: format, bulk: bulk, wait: wait, model_class: model_class)
42
- end
43
-
44
- # @private :nodoc: just for developers
45
- def find(object_type, id, klass)
46
- sf_data.get_record object_type, record_id: id, target_org: target_org, model_class: klass
47
- end
48
-
49
- # @private :nodoc: just for developers
50
- def create(object_type, values, klass = nil)
51
- id = sf_data.create_record object_type, values: values, target_org: target_org
52
- return id if klass.nil?
53
-
54
- find(object_type, id, klass)
55
- end
56
-
57
- # @private :nodoc: just for developers
58
- def update(object_type, id, values)
59
- sf_data.update_record object_type, record_id: id, where: nil, values: values, target_org: target_org
60
- end
61
-
62
- # @private :nodoc: just for developers
63
- def delete(object_type, id)
64
- sf_data.delete_record object_type, record_id: id, where: nil, target_org: target_org
65
- end
66
-
67
- # @private :nodoc: just for developers
68
- def query(soql, klass, format = nil)
69
- sf_data.query soql, target_org: target_org, format: format, model_class: klass
70
- end
71
-
72
- # @private :nodoc: just for developers
73
- def describe(object_type)
74
- sf_sobject.describe(object_type, target_org: target_org)
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,31 +0,0 @@
1
- require_relative 'model/generator'
2
-
3
- module SfCli
4
- module Sf
5
- #
6
- # The module for object model definition and generation
7
- #
8
- module Model
9
- # The connection object to access Salesforce
10
- def self.connection
11
- @@connection
12
- end
13
-
14
- # set the connection
15
- def self.set_connection(conn)
16
- @@connection = conn
17
- end
18
-
19
- # generate object models
20
- # @param object_names [Array] a list of object name
21
- #
22
- def self.generate(object_names)
23
- generator = Generator.new(connection)
24
-
25
- object_names.each do |object_name|
26
- generator.generate(object_name)
27
- end
28
- end
29
- end
30
- end
31
- end