sf_cli 1.2.5 → 1.3.0

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: 9eaa5b952281b6d65ee9985c4627ed2e28cdca208bc8a9de215bfe933ae71d2a
4
- data.tar.gz: 7ee7b1020b429e05edc68fed332267e24a3d3806ff2fffd2dfaf7279a3e00759
3
+ metadata.gz: a644e819d71225a7ac587cd46e40d47d2c1d766a4cc7ff237c9d90ffd9b3ab2c
4
+ data.tar.gz: 806e3a803d8a7fdbafab63930c7c4cbe0438819804a8a37e71fdcac2d565378b
5
5
  SHA512:
6
- metadata.gz: 27ad97ba8c8478f9e75b50c446101ebf7a1045772d4734ac8b89a4ef0a4f0195ff849be5694dce36e5bc9033906f5754a4936355d5181910db55a5fec02ec546
7
- data.tar.gz: a986236aa5b63bfb86202148df5a2fc5251d9f125a3bc9fb795578137a6d180af2f8f4edcbd61cd2065d1c7f532b7b21e5807b35b268368007016f83a04e7d03
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
@@ -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.5'
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.5
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-17 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