alet 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/alet/app.rb +27 -22
- data/lib/alet/config/locales/en.yml +262 -17
- data/lib/alet/config/locales/ja.yml +262 -14
- data/lib/alet/config.rb +4 -10
- data/lib/alet/irb/command/conn.rb +25 -0
- data/lib/alet/irb/command/deploy.rb +73 -0
- data/lib/alet/irb/command/describe.rb +131 -0
- data/lib/alet/irb/command/export.rb +1 -1
- data/lib/alet/irb/command/gen/apex.rb +36 -0
- data/lib/alet/irb/command/gen/lwc.rb +99 -0
- data/lib/alet/irb/command/gen.rb +58 -0
- data/lib/alet/irb/command/generate_model.rb +26 -4
- data/lib/alet/irb/command/grep.rb +38 -0
- data/lib/alet/irb/command/org.rb +11 -0
- data/lib/alet/irb/command/query.rb +1 -1
- data/lib/alet/irb/helper_methods.rb +4 -21
- data/lib/alet/irb/shared_functions.rb +56 -0
- data/lib/alet/irb.rb +37 -18
- data/lib/alet/project.rb +44 -0
- data/lib/alet/version.rb +1 -1
- data/lib/alet.rb +23 -0
- metadata +32 -8
- data/lib/alet/generate/project.rb +0 -22
@@ -7,41 +7,48 @@ ja:
|
|
7
7
|
example:
|
8
8
|
default: irbセッションを開始.
|
9
9
|
target_org: SF組織の別名またはログインユーザー名を指定してirbを起動
|
10
|
-
|
11
|
-
desc: Salesforce DX
|
12
|
-
|
10
|
+
project:
|
11
|
+
desc: Salesforce DXプロジェクトの生成・更新を行う
|
12
|
+
open_editor: プロジェクト構築/更新完了後、そのプロジェクトをカレントディレクトとしてvs codeを起動する
|
13
|
+
generate:
|
13
14
|
desc: salesforce DX projectを生成する
|
14
15
|
target_org: マニフェストファイルとソースファイルの読み込み先となるSF組織の別名またはその組織のユーザー名
|
15
16
|
manifest: マニフェストファイル(package.xml)を生成する
|
16
17
|
retrieve: マニフェストファイルの内容を元にSF組織からソースファイルを取得する
|
17
|
-
open_editor: プロジェクト構築完了後、そのプロジェクトをカレントディレクトとしてvs codeを起動する
|
18
18
|
example:
|
19
|
-
default:
|
19
|
+
default: Salesfore DXプロジェクトのディレクトリを作成する
|
20
20
|
manifest: プロジェクトディレクトリにマニフェストファイル(package.xml)を含める
|
21
21
|
from_org: 接続組織のメタデータ情報を元にマニフェストファイルの内容を書き込む.
|
22
22
|
retrieve: メタデータのソースファイルをDXプロジェクト内に生成する
|
23
|
-
|
24
|
-
|
23
|
+
update:
|
24
|
+
desc: 現在接続中のSF組織の内容でマニフェストとソースファイルを更新する
|
25
25
|
apex:
|
26
26
|
description: Apexコードを実行する
|
27
|
-
|
28
|
-
description:
|
27
|
+
model:
|
28
|
+
description: 生成済みモデルクラスの表示.またはsobjectクラスの生成
|
29
|
+
list:
|
30
|
+
noclass: 現セッション内で生成済みのSObjectModelクラスはありません
|
31
|
+
title: 【生成済みのSObjectModelクラス】
|
29
32
|
help: |
|
30
33
|
## Name
|
31
|
-
|
34
|
+
model
|
32
35
|
|
33
36
|
## SYNOPSIS
|
34
|
-
|
37
|
+
model [list|load sObjectType...]
|
35
38
|
|
36
39
|
## DESCRIPTION
|
37
|
-
1
|
40
|
+
1. セッション内で既に生成済みのsobjectクラスの一覧表示
|
41
|
+
2. 1つ以上のsobjectクラスを生成する
|
38
42
|
|
39
43
|
## ARGUMENTS
|
40
|
-
**
|
44
|
+
**list** sobjectクラスの一覧表示.何も引数を指定しない場合はこの挙動を実行する.
|
45
|
+
**load sObjectType...** 1つ以上のsObjectクラスを生成する(sObjectTypeはsobjectの型名)
|
41
46
|
|
42
47
|
## EXAMPLES
|
43
48
|
```shell
|
44
|
-
|
49
|
+
model # 生成済みsobjectクラスの一覧表示
|
50
|
+
model list # 同上
|
51
|
+
model load Account Contact User # 取引先、取引先責任者およびユーザーオブジェクトのモデルクラスを生成
|
45
52
|
```
|
46
53
|
query:
|
47
54
|
description: SOQLを使ってレコードを検索する
|
@@ -103,3 +110,244 @@ ja:
|
|
103
110
|
```shell
|
104
111
|
export SELECT Id, Name FROM Account
|
105
112
|
```
|
113
|
+
org:
|
114
|
+
description: 現在のSalesforce組織との接続情報
|
115
|
+
help: |
|
116
|
+
## NAME
|
117
|
+
org
|
118
|
+
|
119
|
+
## SYNOPSIS
|
120
|
+
org
|
121
|
+
|
122
|
+
## DESCRIPTION
|
123
|
+
現在のSalesforce組織との接続情報を表示する
|
124
|
+
grep:
|
125
|
+
description: オブジェクト(sObject)を探す
|
126
|
+
help: |
|
127
|
+
## NAME
|
128
|
+
grep
|
129
|
+
|
130
|
+
## SYNOPSIS
|
131
|
+
grep [-ln] regexp
|
132
|
+
|
133
|
+
## DESCRIPTION
|
134
|
+
ラベルもしくはAPI名のどちらかでオブジェクト(sObject)の存在を探す。
|
135
|
+
sObjectであれば全てが検索対象となる。
|
136
|
+
|
137
|
+
## ARGUMENTS
|
138
|
+
**regexp** オブジェクトのラベルまたはAPI名を示す正規表現
|
139
|
+
|
140
|
+
## OPTIONS
|
141
|
+
**-l, [---label]** ラベル名のみで探す
|
142
|
+
**-n, [---api-name]** API名のみで探す
|
143
|
+
|
144
|
+
## EXAMPLE
|
145
|
+
```shell
|
146
|
+
grep Account
|
147
|
+
grep -n Account*
|
148
|
+
```
|
149
|
+
desc:
|
150
|
+
description: オブジェクトの概要を表示する
|
151
|
+
table:
|
152
|
+
field: 【項目】
|
153
|
+
relation: 【参照関係】
|
154
|
+
record_type: 【レコードタイプ】
|
155
|
+
column:
|
156
|
+
label: ラベル
|
157
|
+
name: API名
|
158
|
+
type: データ型
|
159
|
+
relation_name: リレーション名
|
160
|
+
relation_type: 種別
|
161
|
+
relation_class: クラス名
|
162
|
+
relation_field: 項目名
|
163
|
+
record_type_name: レコードタイプ名
|
164
|
+
record_type_id: レコードタイプID
|
165
|
+
record_type_developer_name: developer name
|
166
|
+
relation_type:
|
167
|
+
parent: 子-親
|
168
|
+
child: 親-子
|
169
|
+
error:
|
170
|
+
notfound: 該当するオブジェクトがありません
|
171
|
+
help: |
|
172
|
+
## NAME
|
173
|
+
desc
|
174
|
+
|
175
|
+
## SYNOPSIS
|
176
|
+
desc [-rta] object-name
|
177
|
+
|
178
|
+
## DESCRIPTION
|
179
|
+
オブジェクトの概要を表示する
|
180
|
+
|
181
|
+
## ARGUMENTS
|
182
|
+
**object-name** オブジェクト名(API名)
|
183
|
+
|
184
|
+
## OPTIONS
|
185
|
+
**-r, [---relation]** リレーションを表示
|
186
|
+
**-t, [---record-type]** レコードタイプを表示
|
187
|
+
**-a, [---all]** 全ての概要を表示
|
188
|
+
|
189
|
+
もし何もオプションが指定されなければ各項目の概要を表示する
|
190
|
+
|
191
|
+
## EXAMPLE
|
192
|
+
```shell
|
193
|
+
desc Account # 取引先の項目を表示する
|
194
|
+
desc -r Account # 取引先のリレーションを表示する
|
195
|
+
```
|
196
|
+
conn:
|
197
|
+
description: SF組織に対する接続設定の表示または設定
|
198
|
+
invalid_subcommand: 指定されたサブコマンドは利用できません
|
199
|
+
help: |
|
200
|
+
## NAME
|
201
|
+
conn
|
202
|
+
|
203
|
+
## SYNOPSIS
|
204
|
+
conn [reset]
|
205
|
+
|
206
|
+
## DESCRIPTION
|
207
|
+
引数なしで呼び出したときは各種接続設定を表示する。
|
208
|
+
resetサブコマンドが指定されたときは、現在接続しているSF組織への接続を更新する。
|
209
|
+
gen:
|
210
|
+
description: Salesforce DXプロジェクトの資材を生成する
|
211
|
+
error:
|
212
|
+
no_subcommand: サブコマンドを指定してください
|
213
|
+
invalid_subcommand: 利用できないサブコマンドです
|
214
|
+
file_duplicated: 同名のコンポーネントがあります。ファイルを作成できません。
|
215
|
+
help: |
|
216
|
+
## NAME
|
217
|
+
gen
|
218
|
+
|
219
|
+
## SYNOPSIS
|
220
|
+
`gen sub-command ...`
|
221
|
+
|
222
|
+
## DESCRIPTION
|
223
|
+
Salesforce DXプロジェクトの資材を生成する
|
224
|
+
|
225
|
+
## ARGUMENTS
|
226
|
+
サブコマンドを指定する。サブコマンドごとに必要な引数は異なる。
|
227
|
+
**apex** ApexクラスまたはApexトリガーのソースファイルを生成する
|
228
|
+
**lwc** LWCのソースファイルを生成する
|
229
|
+
|
230
|
+
### apex サブコマンド
|
231
|
+
|
232
|
+
#### SYNOPSIS
|
233
|
+
`gen apex [-t|-e event1,event2,...|-o object-name] name`
|
234
|
+
|
235
|
+
#### DESCRIPTION
|
236
|
+
ApexクラスまたはApexトリガーのソースファイルを生成する。Salesforce DXプロジェクトのルートディレクトリで実行した場合、所定のディレクトリにファイルを生成する.
|
237
|
+
|
238
|
+
#### ARGUMENTS
|
239
|
+
`name` ApexクラスまたはApexトリガーの名前
|
240
|
+
|
241
|
+
#### OPTIONS
|
242
|
+
`-t`, `--trigger` トリガーのソースファイルを生成する
|
243
|
+
`-o`, `--sobject` トリガーが機能するオブジェクト
|
244
|
+
`-e`, `--event` トリガーが機能するイベント。複数のイベントを指定する場合はカンマでつなぐこと。スペースを入れてはならない(例: bi,bu)。
|
245
|
+
|
246
|
+
##### eventで利用可能な値
|
247
|
+
|
248
|
+
|値|意味|
|
249
|
+
|bi|before insert|
|
250
|
+
|ai|after insert|
|
251
|
+
|bu|before update|
|
252
|
+
|au|after update|
|
253
|
+
|bd|before delete|
|
254
|
+
|ad|after delete|
|
255
|
+
|aud|after undelete|
|
256
|
+
|
257
|
+
#### EXAMPLE
|
258
|
+
```shell
|
259
|
+
gen apex MyClass1 # MyClassという名前のApexクラスのソースファイルを生成
|
260
|
+
gen apex MyTrigger --trigger # MyTriggerという名前のトリガーのソースファイルを生成
|
261
|
+
gen apex -t MyTrigger -o Account # トリガーのオブジェクトにAccount(取引先)オブジェクトを指定
|
262
|
+
gen apex -t MyTrigger --event bi,au # トリガーのイベントに before insertとafter update を指定
|
263
|
+
```
|
264
|
+
|
265
|
+
### lwc サブコマンド
|
266
|
+
|
267
|
+
#### SYNOPSIS
|
268
|
+
`gen lwc [-l label|-d description|-e|-t target1,target2,...|-o object1,object2,...] name`
|
269
|
+
|
270
|
+
#### DESCRIPTION
|
271
|
+
LWC(Lightning Web Component)を構成するファイルをローカルプロジェクト内に生成する。
|
272
|
+
Salesforce DXプロジェクトのルートディレクトリで実行することが前提で、それ以外の場所で実行すると基本的にエラーとなる。
|
273
|
+
|
274
|
+
#### ARGUMENTS
|
275
|
+
`name` LWCの名前
|
276
|
+
|
277
|
+
#### OPTIONS
|
278
|
+
`-l`, `--label` LWC設定ファイルの`masterLabel`セクションの内容を指定する
|
279
|
+
`-d`, `--description` LWC設定ファイルの`description`セクションの内容を指定する
|
280
|
+
`-e`, `--exposed` LWC設定ファイルの`isExposed`セクションの内容を指定する。デフォルトはfalse。
|
281
|
+
`-t`, `--target` LWC設定ファイルの`targets`セクションの内容を指定する。複数設定する場合はカンマ区切りで指定すること。
|
282
|
+
`-o`, `--object` LWC設定ファイルの`object`セクションの内容を指定する。`target`に**record**を指定したときにのみ有効。複数設定する場合はカンマ区切りで指定すること。
|
283
|
+
|
284
|
+
##### targetオプションの値
|
285
|
+
|
286
|
+
|値 |意味 |
|
287
|
+
|app |lightning__AppPage |
|
288
|
+
|flow |lightning__FlowScreen |
|
289
|
+
|home |lightning__HomePage |
|
290
|
+
|action|lightning__RecordAction|
|
291
|
+
|record|lightning__RecordPage |
|
292
|
+
|tab |lightning__Tab |
|
293
|
+
|bar |lightning__UtilityBar |
|
294
|
+
|
295
|
+
#### EXAMPLE
|
296
|
+
```shell
|
297
|
+
gen lwc LWC1 # LWC1という名前のLWCソースファイルを生成
|
298
|
+
gen lwc LWC1 -l "my first LWC"
|
299
|
+
gen lwc LWC1 -d "this is my first LWC"
|
300
|
+
gen lwc LWC1 -t app,home,record # LWCの利用可能範囲をアプリケーションページ、ホームページ、レコードページに指定
|
301
|
+
gen lwc LWC1 -o Account -t record # LWCの利用可能範囲をAccountのレコードページに指定
|
302
|
+
```
|
303
|
+
|
304
|
+
#### SEE ALSO
|
305
|
+
[XML設定ファイルの要素](https://developer.salesforce.com/docs/platform/ja-jp/lwc/guide/reference-configuration-tags.html)
|
306
|
+
deploy:
|
307
|
+
description: プロジェクトの資材をSalesforce組織にアップロードする
|
308
|
+
error:
|
309
|
+
no_arguments: 引数を指定してください
|
310
|
+
help: |
|
311
|
+
## NAME
|
312
|
+
deploy
|
313
|
+
|
314
|
+
## SYNOPSIS
|
315
|
+
`deploy [-d|-t test1,test2...|-l test-level] component-type component-name...`
|
316
|
+
|
317
|
+
## DESCRIPTION
|
318
|
+
ローカルプロジェクトの資材をSF組織にアップロードする
|
319
|
+
|
320
|
+
## ARGUMENTS
|
321
|
+
`component-type` コンポーネントの種類。`file` かそれ以外を指定する。`file`以外で指定できる値は各メタデータタイプ名もしくは短縮名。
|
322
|
+
`component-name` コンポーネントの名前。コンポーネントの種類が`file`の場合、この名前はファイルパスまたはディレクトリパスである必要がある。コンポーネントの種類が`file`以外ならワイルドカード(*)も使用できる。
|
323
|
+
|
324
|
+
### コンポーネント短縮名の一覧
|
325
|
+
|
326
|
+
|短縮名|メタデータタイプ名|
|
327
|
+
|apex|ApexClass|
|
328
|
+
|trigger|ApexTrigger|
|
329
|
+
|lwc|LightningComponentBundle|
|
330
|
+
|
331
|
+
メタデータタイプ名はsfコマンドで確認できる。(`sf org list metadata-type`)
|
332
|
+
|
333
|
+
## OPTIONS
|
334
|
+
`-d`, `--dryrun` 実際にアップロードはせず、アップロードの検証のみ行う
|
335
|
+
`-l`, `--test-level` アップロード時に実行するApexテストの種類を指定する。
|
336
|
+
`-t`, `--tests` アップロード時に実行するテスト。`test-level`が`RunSpecifiedTests`のときにのみ有効。複数指定するときはカンマ区切りでつなぐこと。
|
337
|
+
`-m`, `--manifest` マニフェストファイルの内容に従ってプロジェクトのファイルをアップロードする。`component-type`が`file`のときのみ有効。このオプションが指定されると`component-name`は無視される。
|
338
|
+
|
339
|
+
### test-levelで利用可能な値
|
340
|
+
|
341
|
+
|値|意味|
|
342
|
+
|RunSpecifiedTests|指定された個別のテストのみ実行|
|
343
|
+
|RunLocalTests|managed packageを除く組織内のテストを全て実行|
|
344
|
+
|RunLocalTests|managed packageを含む全ての組織内テストを実行|
|
345
|
+
|
346
|
+
## EXAMPLE
|
347
|
+
```shell
|
348
|
+
deploy apex MyClass1
|
349
|
+
deploy lwc myLWC
|
350
|
+
deploy apex MyClass --test-level RunSpecifiedTests --tests test1,test2
|
351
|
+
deploy file -m manifest/package.xml
|
352
|
+
deploy file force-app/main/default/class/MyClass1.cls
|
353
|
+
```
|
data/lib/alet/config.rb
CHANGED
@@ -1,18 +1,12 @@
|
|
1
1
|
module Alet
|
2
|
-
def self.config
|
3
|
-
@config ||= Config.new
|
4
|
-
end
|
5
|
-
|
6
2
|
class Config
|
7
|
-
def
|
8
|
-
@
|
3
|
+
def org
|
4
|
+
@org
|
9
5
|
end
|
10
|
-
alias conn connection
|
11
6
|
|
12
|
-
def
|
13
|
-
@
|
7
|
+
def org=(org)
|
8
|
+
@org = org
|
14
9
|
end
|
15
|
-
alias conn= connection=
|
16
10
|
|
17
11
|
def cli_options
|
18
12
|
@cli_options ||= {}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../shared_functions'
|
2
|
+
|
3
|
+
class Conn < IRB::Command::Base
|
4
|
+
category "Alet"
|
5
|
+
description t('conn.description')
|
6
|
+
help_message TTY::Markdown.parse t('conn.help')
|
7
|
+
|
8
|
+
def execute(arg)
|
9
|
+
argv = arg.split(' ')
|
10
|
+
if argv.empty?
|
11
|
+
puts '【Current Org settings】'
|
12
|
+
show_org_settings
|
13
|
+
puts '【Rest Client settings】'
|
14
|
+
show_rest_client_settings
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
case argv.first
|
19
|
+
when 'reset'
|
20
|
+
reset_connection
|
21
|
+
else
|
22
|
+
puts t('conn.invalid_subcommand')+ ": #{argv.first}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
class Deploy < IRB::Command::Base
|
5
|
+
category "Alet"
|
6
|
+
description t('deploy.description')
|
7
|
+
help_message TTY::Markdown.parse t('deploy.help')
|
8
|
+
|
9
|
+
def execute(arg)
|
10
|
+
pastel = Pastel.new
|
11
|
+
argv = Shellwords.shellsplit(arg)
|
12
|
+
|
13
|
+
opts = OptionParser.new
|
14
|
+
opts.on('-m manifest-file', '--manifest')
|
15
|
+
opts.on('-d', '--dryrun')
|
16
|
+
opts.on('-l test-level', '--test-level')
|
17
|
+
opts.on('-t test1,test2,...', '--tests')
|
18
|
+
|
19
|
+
if argv.empty?
|
20
|
+
puts pastel.red(t('deploy.error.no_arguments'))
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
params = {}
|
25
|
+
opts.parse!(argv, into: params)
|
26
|
+
component_type = argv.shift
|
27
|
+
|
28
|
+
options = {
|
29
|
+
dry_run: params[:dryrun] || false,
|
30
|
+
tests: params[:tests]&.split(','),
|
31
|
+
test_level: params[:"test-level"]
|
32
|
+
}
|
33
|
+
|
34
|
+
puts component_type # for debug
|
35
|
+
puts argv # for debug
|
36
|
+
puts params # for debug
|
37
|
+
puts options # for debug
|
38
|
+
|
39
|
+
if component_type == 'file'
|
40
|
+
deploy_file(argv, params[:manifest], options)
|
41
|
+
else
|
42
|
+
deploy_component(component_type, argv, options)
|
43
|
+
end
|
44
|
+
rescue => e
|
45
|
+
puts pastel.red(e.message)
|
46
|
+
end
|
47
|
+
|
48
|
+
def deploy_file(argv, manifest, options)
|
49
|
+
if manifest
|
50
|
+
sf.project.deploy_start manifest: manifest, target_org: Alet.config.org.alias, raw_output: true, **options
|
51
|
+
else
|
52
|
+
sf.project.deploy_start source_dir: argv.first, target_org: Alet.config.org.alias, raw_output: true, **options
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def deploy_component(component_type, argv, options)
|
57
|
+
return if argv.empty?
|
58
|
+
|
59
|
+
type_alias = {
|
60
|
+
'apex' => 'ApexClass',
|
61
|
+
'trigger' => 'ApexTrigger',
|
62
|
+
'lwc' => 'LightningComponentBundle',
|
63
|
+
}
|
64
|
+
|
65
|
+
metadata_names =
|
66
|
+
argv.map do |name|
|
67
|
+
metadata_type = type_alias[component_type] || component_type
|
68
|
+
%|"#{metadata_type}:#{name}"|
|
69
|
+
end
|
70
|
+
|
71
|
+
sf.project.deploy_start metadata: metadata_names, target_org: Alet.config.org.alias, raw_output: true, **options
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'stringio'
|
3
|
+
require 'irb/pager'
|
4
|
+
require 'sobject_model/schema'
|
5
|
+
|
6
|
+
class Describe < IRB::Command::Base
|
7
|
+
category "Alet"
|
8
|
+
description t('desc.description')
|
9
|
+
help_message TTY::Markdown.parse t('desc.help')
|
10
|
+
|
11
|
+
def execute(arg)
|
12
|
+
pastel = Pastel.new
|
13
|
+
argv = arg.split(' ')
|
14
|
+
opt = OptionParser.new
|
15
|
+
opt.on '-r', '--relation'
|
16
|
+
opt.on '-t', '--record-type'
|
17
|
+
opt.on '-a', '--all'
|
18
|
+
|
19
|
+
params = {}
|
20
|
+
opt.parse(argv, into: params)
|
21
|
+
|
22
|
+
object_type = argv.first
|
23
|
+
|
24
|
+
schema = SObjectModel::Schema.new(Alet.describe(object_type.to_sym))
|
25
|
+
|
26
|
+
if params.has_key?(:relation)
|
27
|
+
show_relations(schema)
|
28
|
+
elsif params.has_key?(:"record-type")
|
29
|
+
show_record_types(schema)
|
30
|
+
elsif params.has_key?(:all)
|
31
|
+
show_all(schema)
|
32
|
+
else
|
33
|
+
show_fields(schema)
|
34
|
+
end
|
35
|
+
rescue SObjectModel::Rest::RequestError => e
|
36
|
+
puts pastel.red(e.message)
|
37
|
+
rescue SObjectModel::Rest::RecordNotFoundError => e
|
38
|
+
puts pastel.red(t('desc.error.notfound'))
|
39
|
+
end
|
40
|
+
|
41
|
+
def show_fields(schema)
|
42
|
+
table = create_field_table(schema)
|
43
|
+
sio = StringIO.new
|
44
|
+
sio << t('desc.table.field')
|
45
|
+
sio << "\n"
|
46
|
+
sio << table.render(:unicode)
|
47
|
+
IRB::Pager.page_content(sio.string)
|
48
|
+
end
|
49
|
+
|
50
|
+
def show_relations(schema)
|
51
|
+
table = crate_relation_table(schema)
|
52
|
+
sio = StringIO.new
|
53
|
+
sio << t('desc.table.relation')
|
54
|
+
sio << "\n"
|
55
|
+
sio << table.render(:unicode)
|
56
|
+
IRB::Pager.page_content(sio.string)
|
57
|
+
end
|
58
|
+
|
59
|
+
def show_record_types(schema)
|
60
|
+
table = create_record_type_table(schema)
|
61
|
+
sio = StringIO.new
|
62
|
+
sio << t('desc.table.record_type')
|
63
|
+
sio << "\n"
|
64
|
+
sio << table.render(:unicode)
|
65
|
+
IRB::Pager.page_content(sio.string)
|
66
|
+
end
|
67
|
+
|
68
|
+
def show_all(schema)
|
69
|
+
field_table = create_field_table(schema)
|
70
|
+
relation_table = crate_relation_table(schema)
|
71
|
+
record_type_table = create_record_type_table(schema)
|
72
|
+
|
73
|
+
sio = StringIO.new
|
74
|
+
sio << t('desc.table.field')
|
75
|
+
sio << "\n"
|
76
|
+
sio << field_table.render(:unicode)
|
77
|
+
sio << "\n"
|
78
|
+
sio << "\n"
|
79
|
+
sio << t('desc.table.relation')
|
80
|
+
sio << "\n"
|
81
|
+
sio << relation_table.render(:unicode)
|
82
|
+
sio << "\n"
|
83
|
+
sio << "\n"
|
84
|
+
sio << t('desc.table.record_type')
|
85
|
+
sio << "\n"
|
86
|
+
sio << record_type_table.render(:unicode)
|
87
|
+
IRB::Pager.page_content(sio.string)
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_field_table(schema)
|
91
|
+
rows = []
|
92
|
+
schema.fields.each do |f|
|
93
|
+
if f.picklist_values.empty?
|
94
|
+
rows << [f.label, f.name, f.type, '']
|
95
|
+
else
|
96
|
+
f.picklist_values.each_with_index do |pv, i|
|
97
|
+
next unless pv.active
|
98
|
+
if i == 0
|
99
|
+
rows << [f.label, f.name, f.type, %|#{f.label}/#{pv.value}|]
|
100
|
+
else
|
101
|
+
rows << ['', '', '', %|#{f.label}/#{pv.value}|]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
TTY::Table.new(
|
108
|
+
[t('desc.column.label'), t('desc.column.name'), t('desc.column.type'), ''],
|
109
|
+
rows)
|
110
|
+
end
|
111
|
+
|
112
|
+
def crate_relation_table(schema)
|
113
|
+
rows =
|
114
|
+
schema.parent_relations.map{|r| [r[:name], t('desc.relation_type.parent'), r[:class_name], r[:field]]} +
|
115
|
+
schema.child_relations.map{|r| [r[:name], t('desc.relation_type.child'), r[:class_name], r[:field]]}
|
116
|
+
|
117
|
+
TTY::Table.new(
|
118
|
+
[t('desc.column.relation_name'), t('desc.column.relation_type'), t('desc.column.relation_class'), t('desc.column.relation_field')],
|
119
|
+
rows)
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_record_type_table(schema)
|
123
|
+
rows = schema.record_types
|
124
|
+
.select{|rt| rt.active && rt.available}
|
125
|
+
.map{|rt| [rt.name, rt.recordTypeId, rt.developerName]}
|
126
|
+
|
127
|
+
TTY::Table.new(
|
128
|
+
[t('desc.column.record_type_name'), t('desc.column.record_type_id'), t('desc.column.record_type_developer_name')],
|
129
|
+
rows)
|
130
|
+
end
|
131
|
+
end
|
@@ -14,7 +14,7 @@ class Export < IRB::Command::Base
|
|
14
14
|
|
15
15
|
return if soql.nil?
|
16
16
|
|
17
|
-
csv = sf.data.query(soql, format: :csv, target_org: ::Alet.config.
|
17
|
+
csv = sf.data.query(soql, format: :csv, target_org: ::Alet.config.org.alias)
|
18
18
|
|
19
19
|
filename = "#{Time.now.strftime('%Y%m%d%H%M%S')}_export.csv"
|
20
20
|
File.open(filename, 'w'){|f| f.write(csv) }
|
@@ -0,0 +1,36 @@
|
|
1
|
+
def gen_apex(argv, params)
|
2
|
+
return if argv.empty?
|
3
|
+
|
4
|
+
name = argv.first
|
5
|
+
|
6
|
+
base_dir = Dir.pwd
|
7
|
+
dx_dir = 'force-app/main/default'
|
8
|
+
dir = if FileTest.exist?(%|#{base_dir}/#{dx_dir}|)
|
9
|
+
%|#{base_dir}/#{dx_dir}/#{params[:trigger] ? 'triggers' : 'classes'}|
|
10
|
+
else
|
11
|
+
base_dir
|
12
|
+
end
|
13
|
+
|
14
|
+
if FileTest.exist?(%|#{dir}/#{name}#{params[:trigger] ? '.trigger' : '.cls'}|)
|
15
|
+
pastel = Pastel.new
|
16
|
+
puts pastel.red(t('gen.error.file_duplicated'))
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
if params[:trigger]
|
21
|
+
event_map = {
|
22
|
+
'bi' => 'before insert',
|
23
|
+
'bu' => 'before update',
|
24
|
+
'bd' => 'before delete',
|
25
|
+
'ai' => 'after insert',
|
26
|
+
'au' => 'after update',
|
27
|
+
'ad' => 'after delete',
|
28
|
+
'aud' => 'after undelete',
|
29
|
+
}
|
30
|
+
events = params[:event]&.split(',')&.map{|e| event_map[e]}&.compact
|
31
|
+
sf.apex.generate_trigger name, output_dir: dir, sobject: params[:sobject], event: events
|
32
|
+
else
|
33
|
+
sf.apex.generate_class name, output_dir: dir
|
34
|
+
sf.apex.generate_class %|#{name}Test|, output_dir: dir, template: :ApexUnitTest
|
35
|
+
end
|
36
|
+
end
|