├── .circleci └── config.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── bubbles ├── common.go ├── deploy.go └── job.go ├── command ├── active.go ├── apex.go ├── apiversion.go ├── bigobject.go ├── bulk.go ├── bulk_test.go ├── command_suite_test.go ├── create.go ├── datapipe.go ├── deploy.go ├── deploys.go ├── describe.go ├── eventlogfile.go ├── export.go ├── export_test.go ├── fetch.go ├── field.go ├── import.go ├── limits.go ├── log.go ├── login.go ├── logins.go ├── logins_test.go ├── logout.go ├── notify.go ├── oauth.go ├── open.go ├── package.go ├── password.go ├── pubsub.go ├── push.go ├── query.go ├── quickdeploy.go ├── record.go ├── rest.go ├── root.go ├── search.go ├── security.go ├── smart_flow.go ├── smart_flow_test.go ├── sobject.go ├── test.go ├── test_test.go ├── trace.go ├── usedxauth.go ├── version.go └── whoami.go ├── config └── config.go ├── desktop ├── notify.go └── open.go ├── docs ├── force.md ├── force_active.md ├── force_apex.md ├── force_apiversion.md ├── force_apiversion_list.md ├── force_bigobject.md ├── force_bigobject_create.md ├── force_bigobject_list.md ├── force_bulk.md ├── force_bulk_batch.md ├── force_bulk_batches.md ├── force_bulk_delete.md ├── force_bulk_hardDelete.md ├── force_bulk_insert.md ├── force_bulk_job.md ├── force_bulk_query.md ├── force_bulk_request.md ├── force_bulk_result.md ├── force_bulk_retrieve.md ├── force_bulk_update.md ├── force_bulk_upsert.md ├── force_bulk_watch.md ├── force_create.md ├── force_create_apexclass.md ├── force_create_apexcomponent.md ├── force_create_apexpage.md ├── force_create_apextrigger.md ├── force_datapipe.md ├── force_datapipe_create.md ├── force_datapipe_createjob.md ├── force_datapipe_delete.md ├── force_datapipe_list.md ├── force_datapipe_listjobs.md ├── force_datapipe_queryjob.md ├── force_datapipe_update.md ├── force_deploys.md ├── force_deploys_cancel.md ├── force_deploys_errors.md ├── force_deploys_list.md ├── force_deploys_watch.md ├── force_describe.md ├── force_describe_metadata.md ├── force_describe_sobject.md ├── force_eventlogfile.md ├── force_export.md ├── force_fetch.md ├── force_field.md ├── force_field_create.md ├── force_field_delete.md ├── force_field_list.md ├── force_field_type.md ├── force_import.md ├── force_limits.md ├── force_log.md ├── force_log_delete.md ├── force_log_tail.md ├── force_login.md ├── force_login_scratch.md ├── force_logins.md ├── force_logout.md ├── force_notify.md ├── force_oauth.md ├── force_oauth_create.md ├── force_open.md ├── force_package.md ├── force_package_install.md ├── force_password.md ├── force_password_change.md ├── force_password_reset.md ├── force_password_status.md ├── force_pubsub.md ├── force_pubsub_publish.md ├── force_pubsub_subscribe.md ├── force_push.md ├── force_query.md ├── force_quickdeploy.md ├── force_record.md ├── force_record_create.md ├── force_record_delete.md ├── force_record_get.md ├── force_record_merge.md ├── force_record_undelete.md ├── force_record_update.md ├── force_rest.md ├── force_rest_get.md ├── force_rest_patch.md ├── force_rest_post.md ├── force_rest_put.md ├── force_search.md ├── force_security.md ├── force_sobject.md ├── force_sobject_create.md ├── force_sobject_delete.md ├── force_sobject_import.md ├── force_sobject_list.md ├── force_test.md ├── force_trace.md ├── force_trace_delete.md ├── force_trace_list.md ├── force_trace_start.md ├── force_usedxauth.md ├── force_version.md ├── force_whoami.md └── mkdocs.go ├── error └── error.go ├── go.mod ├── go.sum ├── lib ├── apiversion.go ├── auth.go ├── bayeux │ └── client.go ├── bulk.go ├── bulk_test.go ├── display.go ├── folder.go ├── force.go ├── force_test.go ├── httpaux.go ├── httpaux_test.go ├── internal │ ├── internal.go │ └── internal_test.go ├── junit │ └── junit.go ├── jwt.go ├── lib_suite_test.go ├── log.go ├── merge.go ├── metadata.go ├── packagebuilder.go ├── packagebuilder_test.go ├── partner.go ├── pubsub │ ├── bitmap.go │ ├── grpcclient.go │ ├── proto │ │ ├── pubsub_api.pb.go │ │ ├── pubsub_api.proto │ │ └── pubsub_api_grpc.pb.go │ ├── publish.go │ └── subscribe.go ├── query │ └── query.go ├── record_reader │ ├── csv_record_reader.go │ ├── json_record_reader.go │ ├── record_reader.go │ └── record_reader_test.go ├── request.go ├── scratch.go ├── session.go ├── sfdx.go ├── soap.go ├── soap │ └── types.go ├── sort.go ├── test.go ├── test_test.go ├── undelete.go └── version.go └── main.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: cimg/go:1.20 6 | steps: 7 | - checkout 8 | - run: go install github.com/mitchellh/gox@v1.0.1 9 | - run: go install github.com/tcnksm/ghr@v0.16.0 10 | - run: sudo apt-get update && sudo apt-get install p7zip-full 11 | - restore_cache: # restores saved cache if no changes are detected since last run 12 | keys: 13 | - go-mod-v4-{{ checksum "go.sum" }} 14 | - run: make dist 15 | - save_cache: 16 | key: go-mod-v4-{{ checksum "go.sum" }} 17 | paths: 18 | - "/go/pkg/mod" 19 | - run: 20 | name: create release 21 | command: | 22 | if [ "$CIRCLE_TAG" ]; then 23 | mkdir -p dist 24 | mv force*.zip dist 25 | ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME --replace $CIRCLE_TAG dist/ 26 | else 27 | echo "No tag" 28 | fi 29 | workflows: 30 | version: 2 31 | build-workflow: # the name of our workflow 32 | jobs: # the jobs that we are sequencing. 33 | - build: 34 | filters: 35 | tags: 36 | only: /^v.*/ 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | metadata/ 3 | 4 | # Force CLI specific things 5 | force 6 | metadata 7 | test 8 | 9 | *.json 10 | 11 | *.xml 12 | *.exe 13 | *.sh 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Submitting a Pull Request 2 | 3 | 0. Check out [Hacking on Force][hacking] in the README guide for 4 | bootstrapping the project for local development 5 | 1. [Fork the repository.][fork] 6 | 2. [Create a topic branch.][branch] 7 | 3. Implement your feature and make sure it is covered by appropriate tests 8 | 4. Run `go test` and make sure all of the tests pass 9 | 5. Add documentation for your feature or bug fix 10 | 6. Run `go fmt` from the root of the project, to enforce style. 11 | 7. Add, commit, and push your changes. Following [this guide for commits and commit messages][commits] is very appreciated 12 | 8. [Submit a pull request.][pr] Please be specific with your message, detailing what the why/how of your contribution. 13 | 9. Please expect and facilitate feedback and discussion :) 14 | 15 | [hacking]: https://github.com/ForceCLI/force#hacking 16 | [fork]: https://help.github.com/articles/fork-a-repo 17 | [branch]: http://learn.github.com/p/branching.html 18 | [pr]: https://help.github.com/articles/using-pull-requests 19 | [commits]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 salesforce.com, inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION=$(shell git describe --abbrev=0 --always) 2 | LDFLAGS = -ldflags "-X github.com/ForceCLI/force/lib.Version=${VERSION}" 3 | GCFLAGS = -gcflags="all=-N -l" 4 | EXECUTABLE=force 5 | WINDOWS=$(EXECUTABLE)_windows_amd64.exe 6 | LINUX=$(EXECUTABLE)_linux_amd64 7 | OSX_AMD64=$(EXECUTABLE)_osx_amd64 8 | OSX_ARM64=$(EXECUTABLE)_osx_arm64 9 | ALL=$(WINDOWS) $(LINUX) $(OSX_AMD64) $(OSX_ARM64) 10 | 11 | default: 12 | go build ${LDFLAGS} 13 | 14 | install: 15 | go install ${LDFLAGS} 16 | 17 | install-debug: 18 | go install ${LDFLAGS} ${GCFLAGS} 19 | 20 | $(WINDOWS): 21 | env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -v -o $(WINDOWS) ${LDFLAGS} 22 | 23 | $(LINUX): 24 | env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -o $(LINUX) ${LDFLAGS} 25 | 26 | $(OSX_AMD64): 27 | env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -o $(OSX_AMD64) ${LDFLAGS} 28 | 29 | $(OSX_ARM64): 30 | env CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -v -o $(OSX_ARM64) ${LDFLAGS} 31 | 32 | $(basename $(WINDOWS)).zip: $(WINDOWS) 33 | zip $@ $< 34 | 7za rn $@ $< $(EXECUTABLE)$(suffix $<) 35 | 36 | %.zip: % 37 | zip $@ $< 38 | 7za rn $@ $< $(EXECUTABLE) 39 | 40 | docs: 41 | go run docs/mkdocs.go 42 | 43 | dist: test $(addsuffix .zip,$(basename $(ALL))) 44 | 45 | fmt: 46 | go fmt ./... 47 | 48 | test: 49 | test -z "$(go fmt)" 50 | go vet 51 | go test ./... 52 | go test -race ./... 53 | 54 | clean: 55 | -rm -f $(EXECUTABLE) $(EXECUTABLE)_* 56 | 57 | .PHONY: default dist clean docs 58 | -------------------------------------------------------------------------------- /bubbles/common.go: -------------------------------------------------------------------------------- 1 | package bubbles 2 | 3 | import "github.com/charmbracelet/lipgloss" 4 | 5 | var ( 6 | headerStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#FFDD57")) 7 | subHeaderStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#4E4E4E")) 8 | infoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#4E4E4E")) 9 | testResultStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#89D5C9")) 10 | detailStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#89D5C9")) 11 | failureStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#E88388")) 12 | ) 13 | 14 | const ( 15 | padding = 2 16 | maxWidth = 80 17 | ) 18 | -------------------------------------------------------------------------------- /bubbles/job.go: -------------------------------------------------------------------------------- 1 | package bubbles 2 | 3 | import ( 4 | "fmt" 5 | 6 | force "github.com/ForceCLI/force/lib" 7 | "github.com/charmbracelet/bubbles/progress" 8 | tea "github.com/charmbracelet/bubbletea" 9 | "github.com/charmbracelet/lipgloss" 10 | ) 11 | 12 | var ( 13 | jobInfoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#4E4E4E")).TabWidth(lipgloss.NoTabConversion) 14 | jobStatusStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#89D5C9")).TabWidth(lipgloss.NoTabConversion) 15 | ) 16 | 17 | type JobModel struct { 18 | force.JobInfo 19 | progress progress.Model 20 | } 21 | 22 | type NewJobStatusMsg struct { 23 | force.JobInfo 24 | } 25 | 26 | type QuitMsg struct{} 27 | 28 | func NewJobModel() JobModel { 29 | return JobModel{ 30 | progress: progress.New(progress.WithDefaultGradient()), 31 | } 32 | } 33 | 34 | func (m JobModel) Init() tea.Cmd { 35 | return nil 36 | } 37 | 38 | func (m JobModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 39 | switch msg := msg.(type) { 40 | case tea.WindowSizeMsg: 41 | m.progress.Width = msg.Width - padding*2 - 4 42 | if m.progress.Width > maxWidth { 43 | m.progress.Width = maxWidth 44 | } 45 | return m, nil 46 | 47 | case NewJobStatusMsg: 48 | m.JobInfo = msg.JobInfo 49 | // cmd := m.progress.SetPercent(float64(m.NumberComponentsDeployed) / float64(m.NumberComponentsTotal)) 50 | cmd := m.progress.SetPercent(0.5) 51 | return m, cmd 52 | case tea.KeyMsg: 53 | switch msg.String() { 54 | case "q", "ctrl+c": 55 | return m, tea.Quit 56 | } 57 | case progress.FrameMsg: 58 | progressModel, cmd := m.progress.Update(msg) 59 | m.progress = progressModel.(progress.Model) 60 | return m, cmd 61 | case QuitMsg: 62 | return m, tea.Quit 63 | } 64 | return m, nil 65 | } 66 | 67 | func (m JobModel) View() string { 68 | header := headerStyle.Render("Bulk Job Status") 69 | var infoMsg = ` 70 | Id %s 71 | State %s 72 | Operation %s 73 | Object %s 74 | Api Version %s 75 | 76 | Created By Id %s 77 | Created Date %s 78 | System Mod Stamp %s 79 | Content Type %s 80 | Concurrency Mode %s 81 | ` 82 | 83 | var statusMsg = ` 84 | Number Batches Queued %d 85 | Number Batches In Progress %d 86 | Number Batches Completed %d 87 | Number Batches Failed %d 88 | Number Batches Total %d 89 | Number Records Processed %d 90 | Number Retries %d 91 | 92 | Number Records Failed %d 93 | Total Processing Time %d 94 | Api Active Processing Time %d 95 | Apex Processing Time %d 96 | ` 97 | return lipgloss.JoinVertical(lipgloss.Top, header, 98 | jobInfoStyle.Render(fmt.Sprintf(infoMsg, m.Id, m.State, m.Operation, m.Object, m.ApiVersion, 99 | m.CreatedById, m.CreatedDate, m.SystemModStamp, 100 | m.ContentType, m.ConcurrencyMode)), 101 | jobStatusStyle.Render(fmt.Sprintf(statusMsg, 102 | m.NumberBatchesQueued, m.NumberBatchesInProgress, 103 | m.NumberBatchesCompleted, m.NumberBatchesFailed, 104 | m.NumberBatchesTotal, m.NumberRecordsProcessed, 105 | m.NumberRetries, 106 | m.NumberRecordsFailed, m.TotalProcessingTime, 107 | m.ApiActiveProcessingTime, m.ApexProcessingTime))) 108 | } 109 | -------------------------------------------------------------------------------- /command/active.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | "runtime" 7 | "sort" 8 | 9 | . "github.com/ForceCLI/force/config" 10 | . "github.com/ForceCLI/force/error" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func init() { 15 | activeCmd.Flags().BoolP("json", "j", false, "output in JSON format") 16 | activeCmd.Flags().BoolP("local", "l", false, "set active account locally, for current directory") 17 | activeCmd.Flags().BoolP("session", "s", false, "output session id") 18 | RootCmd.AddCommand(activeCmd) 19 | } 20 | 21 | var activeCmd = &cobra.Command{ 22 | Use: "active [account]", 23 | Short: "Show or set the active force.com account", 24 | Long: "Get or set the active force.com account", 25 | Example: ` 26 | force active 27 | force active user@example.org 28 | `, 29 | Args: cobra.MaximumNArgs(1), 30 | Run: func(cmd *cobra.Command, args []string) { 31 | if len(args) == 0 { 32 | printCurrentAccount(cmd) 33 | return 34 | } 35 | local, _ := cmd.Flags().GetBool("local") 36 | setAccount(args[0], local) 37 | }, 38 | } 39 | 40 | func printCurrentAccount(cmd *cobra.Command) { 41 | if force == nil { 42 | ErrorAndExit("No active session") 43 | } 44 | creds := force.Credentials 45 | if creds == nil || creds.UserInfo == nil { 46 | ErrorAndExit("No active session") 47 | } 48 | sessionId, _ := cmd.Flags().GetBool("session") 49 | tojson, _ := cmd.Flags().GetBool("json") 50 | if sessionId { 51 | fmt.Println(creds.AccessToken) 52 | } else if tojson { 53 | fmt.Printf(fmt.Sprintf(`{ "login": "%s", "instanceUrl": "%s", "namespace": "%s", "orgId": "%s" }`, creds.SessionName(), creds.InstanceUrl, creds.UserInfo.OrgNamespace, creds.UserInfo.OrgId)) 54 | } else { 55 | fmt.Println(fmt.Sprintf("%s - %s - Org: %s - ns:%s", creds.SessionName(), creds.InstanceUrl, creds.UserInfo.OrgId, creds.UserInfo.OrgNamespace)) 56 | } 57 | } 58 | 59 | func setAccount(account string, local bool) { 60 | accounts, _ := Config.List("accounts") 61 | i := sort.SearchStrings(accounts, account) 62 | if i < len(accounts) && accounts[i] == account { 63 | if runtime.GOOS == "windows" { 64 | cmd := exec.Command("title", account) 65 | cmd.Run() 66 | } else { 67 | title := fmt.Sprintf("\033];%s\007", account) 68 | fmt.Printf(title) 69 | } 70 | fmt.Printf("%s now active\n", account) 71 | if local { 72 | Config.SaveLocal("current", "account", account) 73 | } else { 74 | Config.SaveGlobal("current", "account", account) 75 | } 76 | } else { 77 | ErrorAndExit(fmt.Sprintf("no such account %s\n", account)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /command/apex.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | 8 | . "github.com/ForceCLI/force/error" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | func init() { 13 | apexCmd.Flags().BoolP("test", "t", false, "run in test context") 14 | RootCmd.AddCommand(apexCmd) 15 | } 16 | 17 | var apexCmd = &cobra.Command{ 18 | Use: "apex [file]", 19 | Short: "Execute anonymous Apex code", 20 | Example: ` 21 | force apex ~/test.apex 22 | 23 | force apex 24 | >> Start typing Apex code; press CTRL-D(for Mac/Linux) / Ctrl-Z (for Windows) when finished 25 | `, 26 | Run: func(cmd *cobra.Command, args []string) { 27 | testContext, _ := cmd.Flags().GetBool("test") 28 | switch len(args) { 29 | case 1: 30 | runApexInFile(args[0], testContext) 31 | case 0: 32 | runApexFromStdin(testContext) 33 | default: 34 | fmt.Println("Got test indication. DEPRECATED.") 35 | getTestCoverage(args[1]) 36 | } 37 | }, 38 | } 39 | 40 | func runApexFromStdin(testContext bool) { 41 | fmt.Println(">> Start typing Apex code; press CTRL-D(for Mac/Linux) / Ctrl-Z (for Windows) when finished") 42 | code, err := ioutil.ReadAll(os.Stdin) 43 | fmt.Println("\n\n>> Executing code...") 44 | var output string 45 | if testContext { 46 | output, err = executeAsTest(code) 47 | } else { 48 | output, err = execute(code) 49 | } 50 | fmt.Println(output) 51 | if err != nil { 52 | ErrorAndExit(err.Error()) 53 | } 54 | } 55 | 56 | func runApexInFile(filename string, testContext bool) { 57 | code, err := ioutil.ReadFile(filename) 58 | if err != nil { 59 | ErrorAndExit(err.Error()) 60 | } 61 | var output string 62 | if testContext { 63 | output, err = executeAsTest(code) 64 | } else { 65 | output, err = execute(code) 66 | } 67 | fmt.Println(output) 68 | if err != nil { 69 | ErrorAndExit(err.Error()) 70 | } 71 | } 72 | 73 | func executeAsTest(code []byte) (string, error) { 74 | return force.Partner.ExecuteAnonymousTest(string(code)) 75 | } 76 | 77 | func execute(code []byte) (string, error) { 78 | return force.Partner.ExecuteAnonymous(string(code)) 79 | } 80 | 81 | func getTestCoverage(apexclass string) { 82 | fmt.Println(apexclass) 83 | err := force.GetCodeCoverage("", apexclass) 84 | if err != nil { 85 | ErrorAndExit(err.Error()) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /command/apiversion.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "regexp" 7 | 8 | . "github.com/ForceCLI/force/error" 9 | . "github.com/ForceCLI/force/lib" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | func init() { 14 | apiVersionListCmd.Flags().BoolP("json", "j", false, "json output") 15 | apiVersionCmd.AddCommand(apiVersionListCmd) 16 | 17 | apiVersionCmd.Flags().BoolP("release", "r", false, "include release version") 18 | 19 | RootCmd.AddCommand(apiVersionCmd) 20 | } 21 | 22 | var apiVersionCmd = &cobra.Command{ 23 | Use: "apiversion", 24 | Short: "Display/Set current API version", 25 | Example: ` 26 | force apiversion 27 | force apiversion 40.0 28 | force apiversion list 29 | `, 30 | Args: cobra.MaximumNArgs(1), 31 | DisableFlagsInUseLine: false, 32 | Run: func(cmd *cobra.Command, args []string) { 33 | if len(args) == 1 { 34 | setApiVersion(args[0]) 35 | return 36 | } 37 | v := ApiVersion() 38 | r, _ := cmd.Flags().GetBool("release") 39 | if r { 40 | releaseVersion, err := getReleaseVersion() 41 | if err != nil { 42 | ErrorAndExit(err.Error()) 43 | } 44 | v = fmt.Sprintf("%s (%s)", v, releaseVersion) 45 | } 46 | fmt.Println(v) 47 | }, 48 | } 49 | 50 | var apiVersionListCmd = &cobra.Command{ 51 | Use: "list", 52 | Short: "List API versions supported by org", 53 | Example: ` 54 | force apiversion list 55 | `, 56 | Args: cobra.MaximumNArgs(0), 57 | DisableFlagsInUseLine: true, 58 | Run: func(cmd *cobra.Command, args []string) { 59 | json, _ := cmd.Flags().GetBool("json") 60 | listApiVersions(json) 61 | }, 62 | } 63 | 64 | func setApiVersion(apiVersionNumber string) { 65 | err := force.UpdateApiVersion(apiVersionNumber) 66 | if err != nil { 67 | ErrorAndExit("%v", err) 68 | } 69 | } 70 | 71 | func listApiVersions(jsonOutput bool) { 72 | data, err := force.GetAbsolute("/services/data") 73 | if err != nil { 74 | ErrorAndExit(err.Error()) 75 | } 76 | if jsonOutput { 77 | fmt.Println(data) 78 | return 79 | } 80 | var versions []map[string]string 81 | err = json.Unmarshal([]byte(data), &versions) 82 | if err != nil { 83 | ErrorAndExit(err.Error()) 84 | } 85 | for _, v := range versions { 86 | fmt.Printf("%s (%s)\n", v["version"], v["label"]) 87 | } 88 | } 89 | 90 | func getReleaseVersion() (string, error) { 91 | data, err := force.GetAbsolute("/releaseVersion.jsp") 92 | if err != nil { 93 | return "", fmt.Errorf("failed to get /releaseVersion.jsp: %w", err) 94 | } 95 | 96 | re := regexp.MustCompile(`(?m)^ReleaseName=([\d\.]+)$`) 97 | matches := re.FindStringSubmatch(string(data)) 98 | if len(matches) < 2 { 99 | return "", fmt.Errorf("release version not found") 100 | } 101 | return matches[1], nil 102 | } 103 | -------------------------------------------------------------------------------- /command/bulk_test.go: -------------------------------------------------------------------------------- 1 | package command_test 2 | 3 | import ( 4 | . "github.com/ForceCLI/force/command" 5 | "io/ioutil" 6 | "os" 7 | 8 | . "github.com/onsi/ginkgo" 9 | . "github.com/onsi/gomega" 10 | ) 11 | 12 | var _ = Describe("Bulk", func() { 13 | Describe("SplitCSV", func() { 14 | var ( 15 | tempDir string 16 | ) 17 | 18 | BeforeEach(func() { 19 | tempDir, _ = ioutil.TempDir("", "bulk-test") 20 | }) 21 | 22 | AfterEach(func() { 23 | os.RemoveAll(tempDir) 24 | }) 25 | 26 | It("should handle mulit-line field values", func() { 27 | csvFilePath := tempDir + "/bulk.csv" 28 | csvContents := `Id,Description 29 | 001000000000000000,single-line value 30 | 001000000000000001,single-line value 31 | 001000000000000002,"multi-line 32 | value"` 33 | ioutil.WriteFile(csvFilePath, []byte(csvContents), 0644) 34 | 35 | batches, err := SplitCSV(csvFilePath, 2) 36 | Expect(err).To(BeNil()) 37 | 38 | Expect(len(batches)).To(Equal(2)) 39 | Expect(batches[0]).To(HavePrefix("Id,Description")) 40 | Expect(batches[1]).To(HavePrefix("Id,Description")) 41 | Expect(batches[0]).To(HaveSuffix("single-line value\n")) 42 | Expect(batches[1]).To(HaveSuffix("multi-line\nvalue\"\n")) 43 | }) 44 | 45 | It("should handle single-row files", func() { 46 | csvFilePath := tempDir + "/bulk.csv" 47 | csvContents := `Id,Description 48 | 001000000000000000,single value` 49 | ioutil.WriteFile(csvFilePath, []byte(csvContents), 0644) 50 | 51 | batches, err := SplitCSV(csvFilePath, 2) 52 | Expect(err).To(BeNil()) 53 | 54 | Expect(len(batches)).To(Equal(1)) 55 | Expect(batches[0]).To(HavePrefix("Id,Description")) 56 | Expect(batches[0]).To(HaveSuffix("single value\n")) 57 | }) 58 | 59 | It("should return an error for an invalid file", func() { 60 | csvFilePath := tempDir + "/bulk.csv" 61 | csvContents := `Column 1 62 | 001000000000000000,single value` 63 | ioutil.WriteFile(csvFilePath, []byte(csvContents), 0644) 64 | 65 | _, err := SplitCSV(csvFilePath, 2) 66 | Expect(err).To(MatchError(MatchRegexp("wrong number of fields"))) 67 | }) 68 | 69 | It("should return an error for a missing file", func() { 70 | csvFilePath := tempDir + "/no-such-file.csv" 71 | 72 | _, err := SplitCSV(csvFilePath, 2) 73 | Expect(err).To(MatchError(MatchRegexp("no such file or directory"))) 74 | }) 75 | }) 76 | }) 77 | -------------------------------------------------------------------------------- /command/command_suite_test.go: -------------------------------------------------------------------------------- 1 | package command_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestCommand(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Command Suite") 13 | } 14 | -------------------------------------------------------------------------------- /command/describe.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "encoding/xml" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | . "github.com/ForceCLI/force/lib" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | describeMetadataCmd.Flags().StringP("type", "t", "", "type of metadata") 13 | describeMetadataCmd.Flags().BoolP("json", "j", false, "json output") 14 | describeSobjectCmd.Flags().StringP("name", "n", "", "name of sobject") 15 | describeSobjectCmd.Flags().BoolP("json", "j", false, "json output") 16 | 17 | describeCmd.AddCommand(describeMetadataCmd) 18 | describeCmd.AddCommand(describeSobjectCmd) 19 | RootCmd.AddCommand(describeCmd) 20 | } 21 | 22 | var describeMetadataCmd = &cobra.Command{ 23 | Use: "metadata", 24 | Short: "Describe metadata", 25 | Long: `List the metadata in the org. With no type specified, lists all 26 | metadata types supported. Specifying a type will list the individual metadata 27 | components of that type. 28 | `, 29 | Example: ` 30 | force describe metadata 31 | force describe metadata -t MatchingRule -j 32 | `, 33 | Args: cobra.ExactArgs(0), 34 | Run: func(cmd *cobra.Command, args []string) { 35 | metadataType, _ := cmd.Flags().GetString("type") 36 | json, _ := cmd.Flags().GetBool("json") 37 | describeMetadata(metadataType, json) 38 | }, 39 | } 40 | 41 | var describeSobjectCmd = &cobra.Command{ 42 | Use: "sobject", 43 | Short: "List sobjects", 44 | Long: `With no name specified, list all SObjects in the org. Specifying an 45 | object name will retrieve all of the details about the object. 46 | `, 47 | Args: cobra.ExactArgs(0), 48 | Run: func(cmd *cobra.Command, args []string) { 49 | item, _ := cmd.Flags().GetString("name") 50 | json, _ := cmd.Flags().GetBool("json") 51 | describeSObject(item, json) 52 | }, 53 | } 54 | 55 | var describeCmd = &cobra.Command{ 56 | Use: "describe (metadata|sobject) [flags]", 57 | Short: "Describe the types of metadata available in the org", 58 | Example: ` 59 | force describe metadata 60 | force describe metadata -t MatchingRule -j 61 | force describe sobject -n Account 62 | `, 63 | Args: cobra.ExactArgs(0), 64 | } 65 | 66 | func describeMetadata(item string, json bool) { 67 | if len(item) == 0 { 68 | // List all metadata 69 | describe, err := force.Metadata.DescribeMetadata() 70 | if err != nil { 71 | ErrorAndExit(err.Error()) 72 | } 73 | if json { 74 | DisplayMetadataListJson(describe.MetadataObjects) 75 | } else { 76 | DisplayMetadataList(describe.MetadataObjects) 77 | } 78 | } else { 79 | // List all metdata object of metaItem type 80 | body, err := force.Metadata.ListMetadata(item) 81 | if err != nil { 82 | ErrorAndExit(err.Error()) 83 | } 84 | var res struct { 85 | Response ListMetadataResponse `xml:"Body>listMetadataResponse"` 86 | } 87 | if err = xml.Unmarshal(body, &res); err != nil { 88 | ErrorAndExit(err.Error()) 89 | } 90 | if json { 91 | DisplayListMetadataResponseJson(res.Response) 92 | } else { 93 | DisplayListMetadataResponse(res.Response) 94 | } 95 | } 96 | } 97 | 98 | func describeSObject(item string, json bool) { 99 | if len(item) == 0 { 100 | // list all sobject 101 | if json { 102 | l := getSobjectList("") 103 | DisplayForceSobjectsJson(l) 104 | } else { 105 | runSobjectList("") 106 | } 107 | } else { 108 | // describe sobject 109 | desc, err := force.DescribeSObject(item) 110 | if err != nil { 111 | ErrorAndExit(err.Error()) 112 | } 113 | DisplayForceSobjectDescribe(desc) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /command/eventlogfile.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | . "github.com/ForceCLI/force/lib" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | RootCmd.AddCommand(eventLogFileCmd) 13 | } 14 | 15 | var eventLogFileCmd = &cobra.Command{ 16 | Use: "eventlogfile [eventlogfileId]", 17 | Short: "List and fetch event log file", 18 | Example: ` 19 | force eventlogfile 20 | force eventlogfile 0AT300000000XQ7GAM 21 | `, 22 | Args: cobra.MaximumNArgs(1), 23 | Run: func(cmd *cobra.Command, args []string) { 24 | if len(args) == 0 { 25 | listEventLogFiles() 26 | return 27 | } 28 | getEventLogFile(args[0]) 29 | }, 30 | } 31 | 32 | func listEventLogFiles() { 33 | records, err := force.QueryEventLogFiles() 34 | if err != nil { 35 | ErrorAndExit(err.Error()) 36 | } 37 | DisplayForceRecords(records) 38 | } 39 | 40 | func getEventLogFile(logId string) { 41 | log, err := force.RetrieveEventLogFile(logId) 42 | if err != nil { 43 | ErrorAndExit(err.Error()) 44 | } 45 | fmt.Println(log) 46 | } 47 | -------------------------------------------------------------------------------- /command/export_test.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestIsExcluded(t *testing.T) { 8 | excluded := []string{"ApexClass", "CustomThing"} 9 | 10 | testCases := []struct { 11 | input string 12 | expected bool 13 | }{ 14 | {"custom", false}, 15 | {"CustomThing", true}, 16 | } 17 | 18 | for _, test := range testCases { 19 | t.Run(test.input, func(t *testing.T) { 20 | got := isExcluded(excluded, test.input) 21 | 22 | if got != test.expected { 23 | t.Errorf("Expected %v got %v for %s entry", test.expected, got, test.input) 24 | } 25 | }) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /command/limits.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "os" 5 | "sort" 6 | "strconv" 7 | 8 | . "github.com/ForceCLI/force/error" 9 | . "github.com/ForceCLI/force/lib" 10 | "github.com/olekukonko/tablewriter" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var limitsCmd = &cobra.Command{ 15 | Use: "limits", 16 | Short: "Display current limits", 17 | Long: ` 18 | Use the limits command to display limits information for your organization. 19 | 20 | -- Max is the limit total for the organization. 21 | 22 | -- Remaining is the total number of calls or events left for the organization.`, 23 | Args: cobra.MaximumNArgs(0), 24 | Run: func(cmd *cobra.Command, args []string) { 25 | warn, _ := cmd.Flags().GetFloat64("warn") 26 | runLimits(warn) 27 | }, 28 | } 29 | 30 | func init() { 31 | limitsCmd.Flags().Float64P("warn", "w", 10, "warning percentange. highlight if remaining is less.") 32 | RootCmd.AddCommand(limitsCmd) 33 | } 34 | 35 | func runLimits(warn float64) { 36 | var result ForceLimits 37 | result, err := force.GetLimits() 38 | 39 | if err != nil { 40 | ErrorAndExit(err.Error()) 41 | } else { 42 | printLimits(result, warn) 43 | } 44 | } 45 | 46 | func printLimits(result map[string]ForceLimit, warnPercent float64) { 47 | table := tablewriter.NewWriter(os.Stdout) 48 | table.SetHeader([]string{"Limit", "Maximum", "Remaining"}) 49 | table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT}) 50 | //sort keys 51 | var keys []string 52 | for k := range result { 53 | keys = append(keys, k) 54 | } 55 | sort.Strings(keys) 56 | 57 | for _, k := range keys { 58 | remaining := result[k].Remaining 59 | max := result[k].Max 60 | row := []string{k, strconv.FormatInt(max, 10), strconv.FormatInt(remaining, 10)} 61 | if max > 0 && float64(remaining)/float64(max) < warnPercent/100 { 62 | table.Rich(row, []tablewriter.Colors{tablewriter.Colors{}, tablewriter.Colors{}, tablewriter.Colors{tablewriter.BgRedColor}}) 63 | } 64 | 65 | table.Append(row) 66 | } 67 | if table.NumLines() > 0 { 68 | table.Render() 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /command/log.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | . "github.com/ForceCLI/force/error" 8 | . "github.com/ForceCLI/force/lib" 9 | "github.com/ForceCLI/force/lib/bayeux" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | func init() { 14 | logCmd.AddCommand(deleteLogCmd) 15 | logCmd.AddCommand(tailLogCmd) 16 | RootCmd.AddCommand(logCmd) 17 | } 18 | 19 | var logCmd = &cobra.Command{ 20 | Use: "log", 21 | Short: "Fetch debug logs", 22 | Example: ` 23 | force log [list] 24 | force log 25 | force log delete 26 | force log tail 27 | `, 28 | Run: func(cmd *cobra.Command, args []string) { 29 | if len(args) == 0 || args[0] == "list" { 30 | getAllLogs() 31 | return 32 | } 33 | getLog(args[0]) 34 | }, 35 | Args: cobra.MaximumNArgs(1), 36 | DisableFlagsInUseLine: true, 37 | } 38 | 39 | var deleteLogCmd = &cobra.Command{ 40 | Use: "delete [logId]", 41 | Short: "Delete debug logs", 42 | Example: ` 43 | force log delete 44 | `, 45 | Run: func(cmd *cobra.Command, args []string) { 46 | deleteLog(args[0]) 47 | }, 48 | Args: cobra.ExactArgs(1), 49 | DisableFlagsInUseLine: true, 50 | } 51 | 52 | var tailLogCmd = &cobra.Command{ 53 | Use: "tail", 54 | Short: "Stream debug logs", 55 | Example: ` 56 | force log tail 57 | `, 58 | Run: func(cmd *cobra.Command, args []string) { 59 | tailLogs() 60 | }, 61 | Args: cobra.ExactArgs(0), 62 | DisableFlagsInUseLine: true, 63 | } 64 | 65 | func getAllLogs() { 66 | records, err := force.QueryLogs() 67 | if err != nil { 68 | ErrorAndExit(err.Error()) 69 | } 70 | force.DisplayAllForceRecords(records) 71 | } 72 | 73 | func deleteLog(logId string) { 74 | err := force.DeleteToolingRecord("ApexLog", logId) 75 | if err != nil { 76 | ErrorAndExit(err.Error()) 77 | } 78 | fmt.Println("Debug log deleted") 79 | } 80 | 81 | func getLog(logId string) { 82 | log, err := force.RetrieveLog(logId) 83 | if err != nil { 84 | ErrorAndExit(err.Error()) 85 | } 86 | fmt.Println(log) 87 | } 88 | 89 | type logEvent struct { 90 | Event struct { 91 | CreatedDate string `json:"createdDate"` 92 | Type string `json:"type"` 93 | } `json:"event"` 94 | Sobject struct { 95 | Id string `json:"id"` 96 | } `json:"sobject"` 97 | } 98 | 99 | func tailLogs() { 100 | client := bayeux.NewClient(force) 101 | msgs := make(chan *bayeux.Message) 102 | if err := client.Subscribe("/systemTopic/Logging", msgs); err != nil { 103 | ErrorAndExit(err.Error()) 104 | } 105 | // Disconnect from server and stop background loop. 106 | defer client.Close() 107 | 108 | for msg := range msgs { 109 | var newLog logEvent 110 | if err := json.Unmarshal(msg.Data, &newLog); err == nil { 111 | getLog(newLog.Sobject.Id) 112 | } else { 113 | Log.Info(fmt.Sprintf("Received unexpected message on channel %s: %s\n", msg.Channel, string(msg.Data))) 114 | } 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /command/logins.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | "strings" 8 | "text/tabwriter" 9 | 10 | . "github.com/ForceCLI/force/config" 11 | . "github.com/ForceCLI/force/lib" 12 | "github.com/spf13/cobra" 13 | ) 14 | 15 | func init() { 16 | loginsCmd.Flags().StringP("org-id", "o", "", "filter by org id") 17 | loginsCmd.Flags().StringP("user-id", "i", "", "filter by user id") 18 | RootCmd.AddCommand(loginsCmd) 19 | } 20 | 21 | type accountFilter func(ForceSession) bool 22 | 23 | var loginsCmd = &cobra.Command{ 24 | Use: "logins", 25 | Short: "List force.com logins used", 26 | Example: ` 27 | force logins 28 | `, 29 | Run: func(cmd *cobra.Command, args []string) { 30 | runLogins(filters(cmd)) 31 | }, 32 | } 33 | 34 | func filters(cmd *cobra.Command) []accountFilter { 35 | var filters []accountFilter 36 | orgId, _ := cmd.Flags().GetString("org-id") 37 | if orgId != "" { 38 | filters = append(filters, func(s ForceSession) bool { 39 | if s.UserInfo == nil { 40 | return false 41 | } 42 | if len(orgId) == 15 { 43 | return s.UserInfo.OrgId[0:15] == orgId 44 | } 45 | return strings.ToLower(s.UserInfo.OrgId) == strings.ToLower(orgId) 46 | }) 47 | } 48 | 49 | userId, _ := cmd.Flags().GetString("user-id") 50 | if userId != "" { 51 | filters = append(filters, func(s ForceSession) bool { 52 | if s.UserInfo == nil { 53 | return false 54 | } 55 | if len(userId) == 15 { 56 | return s.UserInfo.UserId[0:15] == userId 57 | } 58 | return strings.ToLower(s.UserInfo.UserId) == strings.ToLower(userId) 59 | }) 60 | } 61 | return filters 62 | } 63 | 64 | func runLogins(filters []accountFilter) { 65 | active, _ := ActiveLogin() 66 | accounts, _ := Config.List("accounts") 67 | if len(accounts) == 0 { 68 | fmt.Println("no logins") 69 | return 70 | } 71 | w := new(tabwriter.Writer) 72 | w.Init(os.Stdout, 1, 0, 1, ' ', 0) 73 | 74 | ACCOUNTS: 75 | for _, account := range accounts { 76 | if !strings.HasPrefix(account, ".") { 77 | var creds ForceSession 78 | data, err := Config.Load("accounts", account) 79 | json.Unmarshal([]byte(data), &creds) 80 | if err != nil { 81 | return 82 | } 83 | for _, f := range filters { 84 | if !f(creds) { 85 | continue ACCOUNTS 86 | } 87 | } 88 | 89 | var banner = fmt.Sprintf("\t%s", creds.InstanceUrl) 90 | if account == active { 91 | account = fmt.Sprintf("\x1b[31;1m%s (active)\x1b[0m", account) 92 | } else { 93 | account = fmt.Sprintf("%s \x1b[31;1m\x1b[0m", account) 94 | } 95 | fmt.Fprintln(w, fmt.Sprintf("%s%s", account, banner)) 96 | } 97 | } 98 | fmt.Fprintln(w) 99 | w.Flush() 100 | } 101 | -------------------------------------------------------------------------------- /command/logins_test.go: -------------------------------------------------------------------------------- 1 | package command_test 2 | 3 | import ( 4 | . "github.com/ForceCLI/force/lib" 5 | "github.com/bmizerany/assert" 6 | "github.com/devangel/config" 7 | "os" 8 | "os/exec" 9 | "testing" 10 | ) 11 | 12 | var TestConfig = config.NewConfig("force") 13 | 14 | // test that SetActiveLogin in turn sets the "current account" 15 | func TestSetActiveLogin(t *testing.T) { 16 | prevAcct, err := TestConfig.Load("current", "account") 17 | if err != nil { 18 | prevAcct = "" 19 | } 20 | SetActiveLogin("clint") 21 | account, _ := TestConfig.Load("current", "account") 22 | SetActiveLogin(prevAcct) 23 | assert.Equal(t, account, "clint") 24 | } 25 | 26 | /* test that ActiveCredentials exits with a status code of 1 if there is no matching 27 | * credential file for the active login. 28 | */ 29 | func TestActiveCredentialsMissingFile(t *testing.T) { 30 | if os.Getenv("TEST_MISSING_CREDS") == "1" { 31 | SetActiveLogin("no_matching_credentials_file") 32 | ActiveCredentials(true) 33 | return 34 | } 35 | prevAcct, err := TestConfig.Load("current", "account") 36 | if err != nil { 37 | prevAcct = "" 38 | } 39 | cmd := exec.Command(os.Args[0], "-test.run=TestActiveCredentialsMissingFile") 40 | cmd.Env = append(os.Environ(), "TEST_MISSING_CREDS=1") 41 | err = cmd.Run() 42 | SetActiveLogin(prevAcct) 43 | if e, ok := err.(*exec.ExitError); ok && !e.Success() { 44 | return 45 | } 46 | t.Fatalf("process ran with err %v, expect exit status 1", err) 47 | } 48 | -------------------------------------------------------------------------------- /command/logout.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "os/exec" 6 | "runtime" 7 | 8 | . "github.com/ForceCLI/force/config" 9 | . "github.com/ForceCLI/force/error" 10 | . "github.com/ForceCLI/force/lib" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func init() { 15 | RootCmd.AddCommand(logoutCmd) 16 | } 17 | 18 | var logoutCmd = &cobra.Command{ 19 | Use: "logout", 20 | Short: "Log out from Force.com", 21 | Args: cobra.MaximumNArgs(0), 22 | DisableFlagsInUseLine: true, 23 | Run: func(cmd *cobra.Command, args []string) { 24 | runLogout() 25 | }, 26 | } 27 | 28 | func runLogout() { 29 | accounts, _ := Config.List("accounts") 30 | if len(accounts) == 0 { 31 | ErrorAndExit("No logins, so a username cannot be assumed.") 32 | } 33 | username := force.Credentials.UserInfo.UserName 34 | Config.Delete("accounts", username) 35 | if active, _ := Config.Load("current", "account"); active == username { 36 | Config.Delete("current", "account") 37 | SetActiveLoginDefault() 38 | } 39 | if runtime.GOOS == "windows" { 40 | cmd := exec.Command("title", account) 41 | cmd.Run() 42 | } else { 43 | title := fmt.Sprintf("\033];%s\007", "") 44 | fmt.Printf(title) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /command/notify.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/ForceCLI/force/desktop" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | RootCmd.AddCommand(notifyCmd) 13 | } 14 | 15 | var notifyCmd = &cobra.Command{ 16 | Use: "notify (true | false)", 17 | Short: "Should notifications be used", 18 | Long: ` 19 | Determines if notifications should be used 20 | `, 21 | Args: cobra.MaximumNArgs(1), 22 | DisableFlagsInUseLine: true, 23 | Run: func(cmd *cobra.Command, args []string) { 24 | var err error 25 | shouldNotify := true 26 | if len(args) == 0 { 27 | shouldNotify = desktop.GetShouldNotify() 28 | fmt.Println("Show notifications: " + strconv.FormatBool(shouldNotify)) 29 | return 30 | } 31 | 32 | shouldNotify, err = strconv.ParseBool(args[0]) 33 | if err != nil { 34 | fmt.Println("Expecting a boolean parameter.") 35 | } 36 | 37 | desktop.SetShouldNotify(shouldNotify) 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /command/oauth.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func init() { 11 | oauthCmd.AddCommand(oauthCreateCmd) 12 | 13 | RootCmd.AddCommand(oauthCmd) 14 | } 15 | 16 | var oauthCmd = &cobra.Command{ 17 | Use: "oauth []", 18 | Short: "Manage ConnectedApp credentials", 19 | Long: ` 20 | Manage ConnectedApp credentials 21 | 22 | Usage: 23 | 24 | force oauth create 25 | `, 26 | 27 | Example: ` 28 | force oauth create MyApp http://localhost:3835/oauth/callback 29 | `, 30 | } 31 | 32 | var oauthCreateCmd = &cobra.Command{ 33 | Use: "create ", 34 | Short: "Create ConnectedApp", 35 | Long: ` 36 | Create ConnectedApp 37 | 38 | Usage: 39 | 40 | force oauth create 41 | `, 42 | Example: ` 43 | force oauth create MyApp http://localhost:3835/oauth/callback 44 | `, 45 | Args: cobra.ExactArgs(2), 46 | Run: func(cmd *cobra.Command, args []string) { 47 | runOauthCreate(args[0], args[1]) 48 | }, 49 | } 50 | 51 | func runOauthCreate(name, callback string) { 52 | err := force.Metadata.CreateConnectedApp(name, callback) 53 | if err != nil { 54 | ErrorAndExit(err.Error()) 55 | } 56 | fmt.Println("Connected App created") 57 | } 58 | -------------------------------------------------------------------------------- /command/open.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | "os" 7 | 8 | desktop "github.com/ForceCLI/force/desktop" 9 | . "github.com/ForceCLI/force/error" 10 | . "github.com/ForceCLI/force/lib" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var debug bool 15 | 16 | func init() { 17 | openCmd.Flags().StringP("start", "s", "", "relative URL to open") 18 | openCmd.Flags().BoolVarP(&debug, "debug", "d", false, "show link") 19 | RootCmd.AddCommand(openCmd) 20 | } 21 | 22 | var openCmd = &cobra.Command{ 23 | Use: "open [account]", 24 | Short: "Open a browser window, logged into an authenticated Salesforce org", 25 | Long: ` 26 | Open a browser window, logged into an authenticated Salesforce org. 27 | By default, the active account is used. 28 | `, 29 | Example: ` 30 | force open user@example.com 31 | `, 32 | Args: cobra.MaximumNArgs(1), 33 | Run: func(cmd *cobra.Command, args []string) { 34 | var err error 35 | if len(args) != 0 { 36 | force, err = GetForce(args[0]) 37 | if err != nil { 38 | ErrorAndExit(err.Error()) 39 | } 40 | } 41 | startUrl, _ := cmd.Flags().GetString("start") 42 | runOpen(startUrl) 43 | }, 44 | } 45 | 46 | func runOpen(startUrl string) { 47 | _, err := force.Whoami() 48 | if err != nil { 49 | ErrorAndExit(err.Error()) 50 | } 51 | openUrl := fmt.Sprintf("%s/secur/frontdoor.jsp?sid=%s", force.Credentials.InstanceUrl, force.Credentials.AccessToken) 52 | if startUrl != "" { 53 | openUrl = fmt.Sprintf("%s&retURL=%s", openUrl, url.QueryEscape(startUrl)) 54 | } 55 | if debug { 56 | fmt.Fprintln(os.Stderr, openUrl) 57 | } 58 | err = desktop.Open(openUrl) 59 | if err != nil { 60 | ErrorAndExit(err.Error()) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /command/package.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func init() { 11 | packageInstallCmd.Flags().BoolP("activate", "A", false, "keep the isActive state of any Remote Site Settings (RSS) and Content Security Policies (CSP) in package") 12 | packageInstallCmd.Flags().StringP("password", "p", "", "password for package") 13 | 14 | packageCmd.AddCommand(packageInstallCmd) 15 | RootCmd.AddCommand(packageCmd) 16 | } 17 | 18 | var packageCmd = &cobra.Command{ 19 | Use: "package", 20 | Short: "Manage installed packages", 21 | } 22 | 23 | var packageInstallCmd = &cobra.Command{ 24 | Use: "install [flags] ", 25 | Short: "Installed packages", 26 | Args: cobra.RangeArgs(2, 3), 27 | Run: func(cmd *cobra.Command, args []string) { 28 | activateRSS, _ := cmd.Flags().GetBool("activate") 29 | password, _ := cmd.Flags().GetString("password") 30 | packageNamespace := args[0] 31 | version := args[1] 32 | if len(args) > 2 { 33 | fmt.Println("Warning: Deprecated use of [password] argument. Use --password flag.") 34 | password = args[2] 35 | } 36 | runInstallPackage(packageNamespace, version, password, activateRSS) 37 | }, 38 | } 39 | 40 | func runInstallPackage(packageNamespace string, version string, password string, activateRSS bool) { 41 | if err := force.Metadata.InstallPackageWithRSS(packageNamespace, version, password, activateRSS); err != nil { 42 | ErrorAndExit(err.Error()) 43 | } 44 | fmt.Println("Package installed") 45 | } 46 | -------------------------------------------------------------------------------- /command/password.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var passwordCmd = &cobra.Command{ 11 | Use: "password [user name] [new password]", 12 | Short: "See password status or reset password", 13 | Long: ` 14 | See password status or reset/change password 15 | `, 16 | Example: ` 17 | force password status joe@org.com 18 | force password reset joe@org.com 19 | force password change joe@org.com '$uP3r$3cure' 20 | `, 21 | DisableFlagsInUseLine: true, 22 | } 23 | 24 | var passwordStatusCmd = &cobra.Command{ 25 | Use: "status [user name]", 26 | Short: "See password status", 27 | Example: ` 28 | force password status joe@org.com 29 | 30 | `, 31 | Args: cobra.ExactArgs(1), 32 | Run: func(cmd *cobra.Command, args []string) { 33 | runPasswordStatus(args[0]) 34 | }, 35 | DisableFlagsInUseLine: true, 36 | } 37 | 38 | var passwordResetCmd = &cobra.Command{ 39 | Use: "reset [user name]", 40 | Short: "Reset password", 41 | Example: ` 42 | force password reset joe@org.com 43 | `, 44 | Args: cobra.ExactArgs(1), 45 | Run: func(cmd *cobra.Command, args []string) { 46 | runPasswordReset(args[0]) 47 | }, 48 | DisableFlagsInUseLine: true, 49 | } 50 | 51 | var passwordChangeCmd = &cobra.Command{ 52 | Use: "change [user name] [new password]", 53 | Short: "Set new password", 54 | Example: ` 55 | force password change joe@org.com '$uP3r$3cure' 56 | 57 | `, 58 | Args: cobra.ExactArgs(2), 59 | Run: func(cmd *cobra.Command, args []string) { 60 | runPasswordChange(args[0], args[1]) 61 | }, 62 | DisableFlagsInUseLine: true, 63 | } 64 | 65 | func init() { 66 | passwordCmd.AddCommand(passwordStatusCmd) 67 | passwordCmd.AddCommand(passwordResetCmd) 68 | passwordCmd.AddCommand(passwordChangeCmd) 69 | RootCmd.AddCommand(passwordCmd) 70 | } 71 | 72 | func runPasswordStatus(username string) { 73 | id := getUserId(username) 74 | object, err := force.GetPasswordStatus(id) 75 | if err != nil { 76 | ErrorAndExit(err.Error()) 77 | } else { 78 | fmt.Printf("\nPassword is expired: %t\n\n", object.IsExpired) 79 | } 80 | } 81 | 82 | func runPasswordReset(username string) { 83 | id := getUserId(username) 84 | object, err := force.ResetPassword(id) 85 | if err != nil { 86 | ErrorAndExit(err.Error()) 87 | } else { 88 | fmt.Printf("\nNew password is: %s\n\n", object.NewPassword) 89 | } 90 | } 91 | 92 | func runPasswordChange(username, pass string) { 93 | id := getUserId(username) 94 | newPass := make(map[string]string) 95 | newPass["NewPassword"] = pass 96 | _, err, emessages := force.ChangePassword(id, newPass) 97 | if err != nil { 98 | ErrorAndExit(err.Error(), emessages[0].ErrorCode) 99 | } else { 100 | fmt.Println("\nPassword changed\n ") 101 | } 102 | } 103 | 104 | func getUserId(username string) string { 105 | records, err := force.Query(fmt.Sprintf("SELECT Id FROM User WHERE UserName = '%s'", username)) 106 | if err != nil { 107 | ErrorAndExit(err.Error()) 108 | } 109 | if len(records.Records) > 0 { 110 | return records.Records[0]["Id"].(string) 111 | } 112 | ErrorAndExit("user not found") 113 | return "" 114 | } 115 | -------------------------------------------------------------------------------- /command/quickdeploy.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | . "github.com/ForceCLI/force/error" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | quickDeployCmd.Flags().BoolP("verbose", "v", false, "give more verbose output") 13 | RootCmd.AddCommand(quickDeployCmd) 14 | } 15 | 16 | var quickDeployCmd = &cobra.Command{ 17 | Use: "quickdeploy ", 18 | Short: "Quick deploy validation id", 19 | Example: ` 20 | force quickdeploy 0Af1200000FFbBzCAL 21 | force quickdeploy -v 0Af0b000000ZvXH 22 | `, 23 | Args: cobra.ExactValidArgs(1), 24 | DisableFlagsInUseLine: false, 25 | Run: func(cmd *cobra.Command, args []string) { 26 | verbose, _ := cmd.Flags().GetBool("verbose") 27 | runQuickDeploy(args[0], verbose) 28 | }, 29 | } 30 | 31 | func runQuickDeploy(quickDeployId string, verbose bool) { 32 | result, err := force.Metadata.DeployRecentValidation(quickDeployId) 33 | problems := result.Details.ComponentFailures 34 | successes := result.Details.ComponentSuccesses 35 | if err != nil { 36 | ErrorAndExit(err.Error()) 37 | } 38 | 39 | fmt.Printf("\nFailures - %d\n", len(problems)) 40 | if verbose { 41 | for _, problem := range problems { 42 | if problem.FullName == "" { 43 | fmt.Println(problem.Problem) 44 | } else { 45 | fmt.Printf("%s: %s\n", problem.FullName, problem.Problem) 46 | } 47 | } 48 | } 49 | 50 | fmt.Printf("\nSuccesses - %d\n", len(successes)) 51 | if verbose { 52 | for _, success := range successes { 53 | if success.FullName != "package.xml" { 54 | verb := "unchanged" 55 | if success.Changed { 56 | verb = "changed" 57 | } else if success.Deleted { 58 | verb = "deleted" 59 | } else if success.Created { 60 | verb = "created" 61 | } 62 | fmt.Printf("%s\n\tstatus: %s\n\tid=%s\n", success.FullName, verb, success.Id) 63 | } 64 | } 65 | } 66 | if len(problems) > 0 { 67 | err = errors.New("Some components failed deployment") 68 | } else if !result.Success { 69 | err = errors.New(fmt.Sprintf("Status: %s", result.Status)) 70 | } 71 | if err != nil { 72 | ErrorAndExit(err.Error()) 73 | } 74 | fmt.Printf("Deploy Id %s\n", result.Id) 75 | } 76 | -------------------------------------------------------------------------------- /command/rest.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strings" 8 | 9 | . "github.com/ForceCLI/force/error" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | func init() { 14 | restCmd.AddCommand(restGetCmd) 15 | restCmd.AddCommand(restPostCmd) 16 | restCmd.AddCommand(restPatchCmd) 17 | restCmd.AddCommand(restPutCmd) 18 | restCmd.PersistentFlags().BoolP("absolute", "A", false, "use URL as-is (do not prepend /services/data/vXX.0)") 19 | RootCmd.AddCommand(restCmd) 20 | } 21 | 22 | var restCmd = &cobra.Command{ 23 | Use: "rest ", 24 | Short: "Execute a REST request", 25 | Example: ` 26 | force rest get "/tooling/query?q=Select id From Account" 27 | force rest get /appMenu/AppSwitcher 28 | force rest get -a /services/data/ 29 | force rest post "/tooling/sobjects/CustomField/00D9A0000000TgcUAE" path/to/definition.json 30 | force rest put "/tooling/sobjects/CustomField/00D9A0000000TgcUAE" path/to/definition.json 31 | `, 32 | } 33 | 34 | var restGetCmd = &cobra.Command{ 35 | Use: "get ", 36 | Short: "Execute a REST GET request", 37 | Args: cobra.ExactArgs(1), 38 | Example: ` 39 | force rest get "/tooling/query?q=Select id From Account" 40 | force rest get /appMenu/AppSwitcher 41 | force rest get -a /services/data/ 42 | `, 43 | Run: func(cmd *cobra.Command, args []string) { 44 | absolute, _ := cmd.Flags().GetBool("absolute") 45 | runGet(args[0], absolute) 46 | }, 47 | } 48 | 49 | var restPostCmd = &cobra.Command{ 50 | Use: "post [file]", 51 | Short: "Execute a REST POST request", 52 | Args: cobra.RangeArgs(1, 2), 53 | Run: func(cmd *cobra.Command, args []string) { 54 | fn := makePostPatchPut("post") 55 | runPostPatchPut(fn, cmd, args) 56 | }, 57 | } 58 | 59 | var restPatchCmd = &cobra.Command{ 60 | Use: "patch [file]", 61 | Short: "Execute a REST PATCH request", 62 | Args: cobra.RangeArgs(1, 2), 63 | Run: func(cmd *cobra.Command, args []string) { 64 | fn := makePostPatchPut("patch") 65 | runPostPatchPut(fn, cmd, args) 66 | }, 67 | } 68 | 69 | var restPutCmd = &cobra.Command{ 70 | Use: "put [file]", 71 | Short: "Execute a REST PUT request", 72 | Args: cobra.RangeArgs(1, 2), 73 | Run: func(cmd *cobra.Command, args []string) { 74 | fn := makePostPatchPut("put") 75 | runPostPatchPut(fn, cmd, args) 76 | }, 77 | } 78 | 79 | type postPatchPutFn func(url string, input []byte, absolute bool) 80 | 81 | func runPostPatchPut(fn postPatchPutFn, cmd *cobra.Command, args []string) { 82 | var data []byte 83 | var err error 84 | absolute, _ := cmd.Flags().GetBool("absolute") 85 | if len(args) == 2 { 86 | data, err = os.ReadFile(args[1]) 87 | } else { 88 | data, err = io.ReadAll(os.Stdin) 89 | } 90 | if err != nil { 91 | ErrorAndExit(err.Error()) 92 | } 93 | fn(args[0], data, absolute) 94 | } 95 | 96 | func runGet(url string, absolute bool) { 97 | var err error 98 | var data string 99 | if absolute { 100 | data, err = force.GetAbsolute(url) 101 | } else { 102 | data, err = force.GetREST(url) 103 | } 104 | if err != nil { 105 | ErrorAndExit(err.Error()) 106 | } 107 | fmt.Println(data) 108 | } 109 | 110 | func makePostPatchPut(action string) postPatchPutFn { 111 | action = strings.ToUpper(action) 112 | return func(url string, input []byte, absolute bool) { 113 | var ( 114 | data string 115 | err error 116 | ) 117 | if absolute { 118 | data, err = force.PostPatchAbsolute(url, string(input), action) 119 | } else { 120 | data, err = force.PostPatchREST(url, string(input), action) 121 | } 122 | if err != nil { 123 | ErrorAndExit(err.Error()) 124 | } 125 | msg := fmt.Sprintf("%s %s\n%s", action, url, data) 126 | fmt.Println(msg) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /command/root.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/ForceCLI/config" 11 | forceConfig "github.com/ForceCLI/force/config" 12 | . "github.com/ForceCLI/force/error" 13 | . "github.com/ForceCLI/force/lib" 14 | ) 15 | 16 | var ( 17 | account string 18 | configName string 19 | _apiVersion string 20 | 21 | force *Force 22 | ) 23 | 24 | func init() { 25 | // Provide backwards compatibility for single-dash flags 26 | args := os.Args[1:] 27 | for i, arg := range args { 28 | if len(arg) > 2 && strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") { 29 | args[i] = fmt.Sprintf("-%s", arg) 30 | } 31 | } 32 | RootCmd.SetArgs(args) 33 | RootCmd.PersistentFlags().StringVarP(&account, "account", "a", "", "account `username` to use") 34 | RootCmd.PersistentFlags().StringVar(&configName, "config", "", "config directory to use (default: .force)") 35 | RootCmd.PersistentFlags().StringVarP(&_apiVersion, "apiversion", "V", "", "API version to use") 36 | 37 | RootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { 38 | initializeConfig() 39 | current := cmd 40 | for current.Parent() != nil && current.Parent() != RootCmd { 41 | current = current.Parent() 42 | } 43 | switch current.Name() { 44 | case "force", "login", "completion": 45 | default: 46 | initializeSession() 47 | } 48 | } 49 | } 50 | 51 | var RootCmd = &cobra.Command{ 52 | Use: "force", 53 | Short: "force CLI", 54 | Run: func(cmd *cobra.Command, args []string) { 55 | cmd.Help() 56 | os.Exit(1) 57 | }, 58 | DisableFlagsInUseLine: true, 59 | } 60 | 61 | func initializeConfig() { 62 | if configName != "" { 63 | forceConfig.Config = config.NewConfig(strings.TrimPrefix(configName, ".")) 64 | fmt.Println("Setting config to", forceConfig.Config.Base) 65 | } 66 | } 67 | 68 | func envSession() *Force { 69 | token := os.Getenv("SF_ACCESS_TOKEN") 70 | instance := os.Getenv("SF_INSTANCE_URL") 71 | if token == "" || instance == "" { 72 | return nil 73 | } 74 | creds := &ForceSession{ 75 | AccessToken: token, 76 | InstanceUrl: instance, 77 | } 78 | f := NewForce(creds) 79 | return f 80 | } 81 | 82 | func initializeSession() { 83 | var err error 84 | if account != "" { 85 | force, err = GetForce(account) 86 | } else if force = envSession(); force == nil { 87 | force, err = ActiveForce() 88 | } 89 | if err != nil { 90 | ErrorAndExit(err.Error()) 91 | } 92 | if _apiVersion != "" { 93 | err := SetApiVersion(_apiVersion) 94 | if err != nil { 95 | ErrorAndExit(err.Error()) 96 | } 97 | } 98 | } 99 | 100 | func Execute() { 101 | if err := RootCmd.Execute(); err != nil { 102 | fmt.Println(err) 103 | os.Exit(1) 104 | } 105 | } 106 | 107 | type quietLogger struct{} 108 | 109 | func (l quietLogger) Info(args ...interface{}) { 110 | } 111 | -------------------------------------------------------------------------------- /command/search.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | . "github.com/ForceCLI/force/error" 8 | . "github.com/ForceCLI/force/lib" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | func init() { 13 | RootCmd.AddCommand(searchCmd) 14 | } 15 | 16 | var searchCmd = &cobra.Command{ 17 | Use: "search [flags] ", 18 | Short: "Execute a SOSL statement", 19 | Example: ` 20 | force search "FIND {Jane Doe} IN ALL FIELDS RETURNING Account (Id, Name)" 21 | `, 22 | Args: cobra.MinimumNArgs(1), 23 | Run: func(cmd *cobra.Command, args []string) { 24 | format, _ := cmd.Flags().GetString("format") 25 | query := strings.Join(args, " ") 26 | runSearch(query, format) 27 | }, 28 | } 29 | 30 | func runSearch(query string, format string) { 31 | records, err := force.Search(query) 32 | if err != nil { 33 | ErrorAndExit(err.Error()) 34 | } 35 | fmt.Print(RenderForceRecords(records)) 36 | } 37 | -------------------------------------------------------------------------------- /command/test_test.go: -------------------------------------------------------------------------------- 1 | package command_test 2 | 3 | import ( 4 | . "github.com/ForceCLI/force/command" 5 | . "github.com/ForceCLI/force/lib" 6 | 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | ) 10 | 11 | type stubTestRunner struct { 12 | } 13 | 14 | func (testRunner stubTestRunner) RunTests(tests []string, namespace string) (output TestCoverage, err error) { 15 | if tests[0] == "NoSuchTest" { 16 | output = TestCoverage{NumberRun: 0, NumberFailures: 0} 17 | } else if tests[0] == "Success" { 18 | output = TestCoverage{NumberRun: 1, NumberFailures: 0} 19 | } else { 20 | output = TestCoverage{NumberRun: 1, NumberFailures: 1} 21 | } 22 | return 23 | } 24 | 25 | var _ = Describe("Test", func() { 26 | var ( 27 | stub stubTestRunner 28 | ) 29 | 30 | BeforeEach(func() { 31 | stub = stubTestRunner{} 32 | }) 33 | 34 | Describe("RunTests", func() { 35 | It("should return an error if no tests can be run", func() { 36 | _, err := RunTests(stub, []string{"NoSuchTest"}, "") 37 | Expect(err).To(HaveOccurred()) 38 | }) 39 | It("should not return an error if tests pass", func() { 40 | _, err := RunTests(stub, []string{"Success"}, "") 41 | Expect(err).ToNot(HaveOccurred()) 42 | }) 43 | It("should not return an error if tests fail", func() { 44 | _, err := RunTests(stub, []string{"Fail"}, "") 45 | Expect(err).ToNot(HaveOccurred()) 46 | }) 47 | }) 48 | 49 | Describe("QualifyMethods", func() { 50 | It("should prepend class to method names", func() { 51 | methods := QualifyMethods("MyClass", []string{"method1", "method2"}) 52 | Expect(methods).To(Equal([]string{"MyClass.method1", "MyClass.method2"})) 53 | }) 54 | It("should return class if no methods", func() { 55 | methods := QualifyMethods("MyClass", make([]string, 0, 0)) 56 | Expect(methods).To(Equal([]string{"MyClass"})) 57 | }) 58 | }) 59 | 60 | Describe("GenerateResults", func() { 61 | var ( 62 | results = TestCoverage{ 63 | NumberRun: 5, 64 | NumberFailures: 2, 65 | NumberLocations: []int{1, 1, 1, 1, 1}, 66 | NumberLocationsNotCovered: []int{0, 0, 1, 0, 1}, 67 | Name: []string{"Test1", "Test2", "Test3", "Test4", "Test5"}} 68 | ) 69 | 70 | It("should ignore test classes with 0% coverage", func() { 71 | output := GenerateResults(results) 72 | Expect(output).ToNot(MatchRegexp(`\D0%`)) 73 | }) 74 | }) 75 | }) 76 | -------------------------------------------------------------------------------- /command/trace.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func init() { 11 | traceCmd.AddCommand(traceStartCmd) 12 | traceCmd.AddCommand(traceListCmd) 13 | traceCmd.AddCommand(traceDeleteCmd) 14 | RootCmd.AddCommand(traceCmd) 15 | } 16 | 17 | var traceStartCmd = &cobra.Command{ 18 | Use: "start [user id]", 19 | Short: "Set trace flag", 20 | Args: cobra.MaximumNArgs(1), 21 | Run: func(cmd *cobra.Command, args []string) { 22 | runStartTrace(args...) 23 | }, 24 | } 25 | 26 | var traceListCmd = &cobra.Command{ 27 | Use: "list", 28 | Short: "List trace flags", 29 | Args: cobra.MaximumNArgs(0), 30 | Run: func(cmd *cobra.Command, args []string) { 31 | runQueryTrace() 32 | }, 33 | } 34 | 35 | var traceDeleteCmd = &cobra.Command{ 36 | Use: "delete ", 37 | Short: "Delete trace flag", 38 | Args: cobra.ExactValidArgs(1), 39 | Run: func(cmd *cobra.Command, args []string) { 40 | runDeleteTrace(args[0]) 41 | }, 42 | } 43 | 44 | var traceCmd = &cobra.Command{ 45 | Use: "trace ", 46 | Short: "Manage trace flags", 47 | Example: ` 48 | force trace start [user id] 49 | force trace list 50 | force trace delete 51 | `, 52 | } 53 | 54 | func runQueryTrace() { 55 | result, err := force.QueryTraceFlags() 56 | if err != nil { 57 | ErrorAndExit(err.Error()) 58 | } 59 | force.DisplayAllForceRecordsf(result, "json-pretty") 60 | } 61 | 62 | func runStartTrace(userId ...string) { 63 | _, err, _ := force.StartTrace(userId...) 64 | if err != nil { 65 | ErrorAndExit(err.Error()) 66 | } 67 | fmt.Printf("Tracing Enabled\n") 68 | } 69 | 70 | func runDeleteTrace(id string) { 71 | err := force.DeleteToolingRecord("TraceFlag", id) 72 | if err != nil { 73 | ErrorAndExit(err.Error()) 74 | } 75 | fmt.Printf("Trace Flag deleted\n") 76 | } 77 | -------------------------------------------------------------------------------- /command/version.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/lib" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func init() { 11 | RootCmd.AddCommand(versionCmd) 12 | } 13 | 14 | var versionCmd = &cobra.Command{ 15 | Use: "version", 16 | Short: "Display current version", 17 | Example: ` 18 | force version 19 | `, 20 | Args: cobra.MaximumNArgs(0), 21 | Run: func(cmd *cobra.Command, args []string) { 22 | fmt.Println(Version) 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /command/whoami.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import ( 4 | "fmt" 5 | 6 | . "github.com/ForceCLI/force/error" 7 | . "github.com/ForceCLI/force/lib" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func init() { 12 | whoamiCmd.Flags().BoolP("username", "u", false, "Get username of the active account") 13 | whoamiCmd.Flags().BoolP("id", "i", false, "Get user id of the active account") 14 | whoamiCmd.MarkFlagsMutuallyExclusive("username", "id") 15 | RootCmd.AddCommand(whoamiCmd) 16 | } 17 | 18 | var whoamiCmd = &cobra.Command{ 19 | Use: "whoami", 20 | Short: "Show information about the active account", 21 | Example: ` 22 | force whoami 23 | `, 24 | Args: cobra.MaximumNArgs(0), 25 | Run: func(cmd *cobra.Command, args []string) { 26 | displayUsername, _ := cmd.Flags().GetBool("username") 27 | displayUserId, _ := cmd.Flags().GetBool("id") 28 | me, err := force.Whoami() 29 | if err != nil { 30 | ErrorAndExit(err.Error()) 31 | } 32 | if displayUsername { 33 | fmt.Println(me["Username"]) 34 | } else if displayUserId { 35 | fmt.Println(me["Id"]) 36 | } else { 37 | DisplayForceRecord(me) 38 | } 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/ForceCLI/config" 8 | ) 9 | 10 | var Config = config.NewConfig("force") 11 | 12 | var sourceDirs = []string{ 13 | "src", 14 | "metadata", 15 | } 16 | 17 | // IsSourceDir returns a boolean indicating that dir is actually a Salesforce 18 | // source directory. 19 | func IsSourceDir(dir string) bool { 20 | if _, err := os.Stat(dir); err == nil { 21 | return true 22 | } 23 | return false 24 | } 25 | 26 | // GetSourceDir returns a rooted path name of the Salesforce source directory, 27 | // relative to the current directory. GetSourceDir will look for a source 28 | // directory in the nearest subdirectory. If no such directory exists, it will 29 | // look at its parents, assuming that it is within a source directory already. 30 | func GetSourceDir() (dir string, err error) { 31 | base, err := os.Getwd() 32 | if err != nil { 33 | return 34 | } 35 | 36 | // Look down to our nearest subdirectories 37 | for _, src := range sourceDirs { 38 | if len(src) > 0 { 39 | dir = filepath.Join(base, src) 40 | if IsSourceDir(dir) { 41 | return 42 | } 43 | } 44 | } 45 | 46 | // Check the current directory and then start looking up at our parents. 47 | // When dir's parent is identical, it means we're at the root. If we blow 48 | // past the actual root, we should drop to the next section of code 49 | for dir != filepath.Dir(dir) { 50 | dir = filepath.Dir(dir) 51 | for _, src := range sourceDirs { 52 | adir := filepath.Join(dir, src) 53 | if IsSourceDir(adir) { 54 | dir = adir 55 | return 56 | } 57 | } 58 | } 59 | 60 | // No source directory found, create a src directory and a symlinked "metadata" 61 | // directory for backward compatibility and return that. 62 | dir = filepath.Join(base, "src") 63 | err = os.Mkdir(dir, 0777) 64 | symlink := filepath.Join(base, "metadata") 65 | os.Symlink(dir, symlink) 66 | dir = symlink 67 | return 68 | } 69 | -------------------------------------------------------------------------------- /desktop/notify.go: -------------------------------------------------------------------------------- 1 | package desktop 2 | 3 | import ( 4 | "strconv" 5 | 6 | . "github.com/ForceCLI/force/config" 7 | "github.com/ViViDboarder/gotifier" 8 | ) 9 | 10 | func Notify(method string, message string) { 11 | shouldNotify := GetShouldNotify() 12 | if shouldNotify { 13 | gotifier.Notification{Title: "Force Cli", Subtitle: method, Message: message}.Push() 14 | } 15 | } 16 | 17 | func GetShouldNotify() bool { 18 | shouldNotify := false 19 | notifStr, err := Config.Load("notifications", "shouldNotify") 20 | if err == nil { 21 | shouldNotify, err = strconv.ParseBool(notifStr) 22 | } 23 | 24 | return shouldNotify 25 | } 26 | 27 | func SetShouldNotify(shouldNotify bool) { 28 | // Set config 29 | Config.Save("notifications", "shouldNotify", strconv.FormatBool(shouldNotify)) 30 | } 31 | 32 | func NotifySuccess(method string, success bool) { 33 | if success { 34 | Notify(method, "SUCCESS") 35 | } else { 36 | Notify(method, "FAILURE") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /desktop/open.go: -------------------------------------------------------------------------------- 1 | package desktop 2 | 3 | // taken from https://bitbucket.org/tebeka/go-wise/src/tip/desktop.go 4 | 5 | import ( 6 | "fmt" 7 | "os/exec" 8 | "runtime" 9 | "strings" 10 | ) 11 | 12 | var openCommands = map[string][]string{ 13 | "windows": []string{"cmd", "/c", "start"}, 14 | "darwin": []string{"open"}, 15 | "linux": []string{"xdg-open"}, 16 | } 17 | 18 | func Open(uri string) error { 19 | run, ok := openCommands[runtime.GOOS] 20 | if !ok { 21 | return fmt.Errorf("don't know how to open things on %s platform", runtime.GOOS) 22 | } 23 | if runtime.GOOS == "windows" { 24 | uri = strings.Replace(uri, "&", "^&", -1) 25 | } 26 | run = append(run, uri) 27 | cmd := exec.Command(run[0], run[1:]...) 28 | return cmd.Start() 29 | } 30 | -------------------------------------------------------------------------------- /docs/force.md: -------------------------------------------------------------------------------- 1 | ## force 2 | 3 | force CLI 4 | 5 | ``` 6 | force 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -a, --account username account username to use 13 | -V, --apiversion string API version to use 14 | --config string config directory to use (default: .force) 15 | -h, --help help for force 16 | ``` 17 | 18 | ### SEE ALSO 19 | 20 | * [force active](force_active.md) - Show or set the active force.com account 21 | * [force apex](force_apex.md) - Execute anonymous Apex code 22 | * [force apiversion](force_apiversion.md) - Display/Set current API version 23 | * [force bigobject](force_bigobject.md) - Manage big objects 24 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 25 | * [force create](force_create.md) - Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 26 | * [force datapipe](force_datapipe.md) - Manage DataPipes 27 | * [force deploys](force_deploys.md) - Manage metadata deployments 28 | * [force describe](force_describe.md) - Describe the types of metadata available in the org 29 | * [force eventlogfile](force_eventlogfile.md) - List and fetch event log file 30 | * [force export](force_export.md) - Export metadata to a local directory 31 | * [force fetch](force_fetch.md) - Export specified artifact(s) to a local directory 32 | * [force field](force_field.md) - Manage SObject fields 33 | * [force import](force_import.md) - Import metadata from a local directory 34 | * [force limits](force_limits.md) - Display current limits 35 | * [force log](force_log.md) - Fetch debug logs 36 | * [force login](force_login.md) - Log into Salesforce and store a session token 37 | * [force logins](force_logins.md) - List force.com logins used 38 | * [force logout](force_logout.md) - Log out from Force.com 39 | * [force notify](force_notify.md) - Should notifications be used 40 | * [force oauth](force_oauth.md) - Manage ConnectedApp credentials 41 | * [force open](force_open.md) - Open a browser window, logged into an authenticated Salesforce org 42 | * [force package](force_package.md) - Manage installed packages 43 | * [force password](force_password.md) - See password status or reset password 44 | * [force pubsub](force_pubsub.md) - Subscribe to a pub/sub channel 45 | * [force push](force_push.md) - Deploy metadata from a local directory 46 | * [force query](force_query.md) - Execute a SOQL statement 47 | * [force quickdeploy](force_quickdeploy.md) - Quick deploy validation id 48 | * [force record](force_record.md) - Create, modify, or view records 49 | * [force rest](force_rest.md) - Execute a REST request 50 | * [force search](force_search.md) - Execute a SOSL statement 51 | * [force security](force_security.md) - Displays the OLS and FLS for a given SObject 52 | * [force sobject](force_sobject.md) - Manage standard & custom objects 53 | * [force test](force_test.md) - Run apex tests 54 | * [force trace](force_trace.md) - Manage trace flags 55 | * [force usedxauth](force_usedxauth.md) - Authenticate with SFDX Scratch Org User 56 | * [force version](force_version.md) - Display current version 57 | * [force whoami](force_whoami.md) - Show information about the active account 58 | 59 | -------------------------------------------------------------------------------- /docs/force_active.md: -------------------------------------------------------------------------------- 1 | ## force active 2 | 3 | Show or set the active force.com account 4 | 5 | ### Synopsis 6 | 7 | Get or set the active force.com account 8 | 9 | ``` 10 | force active [account] [flags] 11 | ``` 12 | 13 | ### Examples 14 | 15 | ``` 16 | 17 | force active 18 | force active user@example.org 19 | 20 | ``` 21 | 22 | ### Options 23 | 24 | ``` 25 | -h, --help help for active 26 | -j, --json output in JSON format 27 | -l, --local set active account locally, for current directory 28 | -s, --session output session id 29 | ``` 30 | 31 | ### Options inherited from parent commands 32 | 33 | ``` 34 | -a, --account username account username to use 35 | -V, --apiversion string API version to use 36 | --config string config directory to use (default: .force) 37 | ``` 38 | 39 | ### SEE ALSO 40 | 41 | * [force](force.md) - force CLI 42 | 43 | -------------------------------------------------------------------------------- /docs/force_apex.md: -------------------------------------------------------------------------------- 1 | ## force apex 2 | 3 | Execute anonymous Apex code 4 | 5 | ``` 6 | force apex [file] [flags] 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force apex ~/test.apex 14 | 15 | force apex 16 | >> Start typing Apex code; press CTRL-D(for Mac/Linux) / Ctrl-Z (for Windows) when finished 17 | 18 | ``` 19 | 20 | ### Options 21 | 22 | ``` 23 | -h, --help help for apex 24 | -t, --test run in test context 25 | ``` 26 | 27 | ### Options inherited from parent commands 28 | 29 | ``` 30 | -a, --account username account username to use 31 | -V, --apiversion string API version to use 32 | --config string config directory to use (default: .force) 33 | ``` 34 | 35 | ### SEE ALSO 36 | 37 | * [force](force.md) - force CLI 38 | 39 | -------------------------------------------------------------------------------- /docs/force_apiversion.md: -------------------------------------------------------------------------------- 1 | ## force apiversion 2 | 3 | Display/Set current API version 4 | 5 | ``` 6 | force apiversion [flags] 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force apiversion 14 | force apiversion 40.0 15 | force apiversion list 16 | 17 | ``` 18 | 19 | ### Options 20 | 21 | ``` 22 | -h, --help help for apiversion 23 | -r, --release include release version 24 | ``` 25 | 26 | ### Options inherited from parent commands 27 | 28 | ``` 29 | -a, --account username account username to use 30 | -V, --apiversion string API version to use 31 | --config string config directory to use (default: .force) 32 | ``` 33 | 34 | ### SEE ALSO 35 | 36 | * [force](force.md) - force CLI 37 | * [force apiversion list](force_apiversion_list.md) - List API versions supported by org 38 | 39 | -------------------------------------------------------------------------------- /docs/force_apiversion_list.md: -------------------------------------------------------------------------------- 1 | ## force apiversion list 2 | 3 | List API versions supported by org 4 | 5 | ``` 6 | force apiversion list 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force apiversion list 14 | 15 | ``` 16 | 17 | ### Options 18 | 19 | ``` 20 | -h, --help help for list 21 | -j, --json json output 22 | ``` 23 | 24 | ### Options inherited from parent commands 25 | 26 | ``` 27 | -a, --account username account username to use 28 | -V, --apiversion string API version to use 29 | --config string config directory to use (default: .force) 30 | ``` 31 | 32 | ### SEE ALSO 33 | 34 | * [force apiversion](force_apiversion.md) - Display/Set current API version 35 | 36 | -------------------------------------------------------------------------------- /docs/force_bigobject.md: -------------------------------------------------------------------------------- 1 | ## force bigobject 2 | 3 | Manage big objects 4 | 5 | ### Synopsis 6 | 7 | 8 | Manage big objects 9 | 10 | Usage: 11 | 12 | force bigobject list 13 | 14 | force bigobject create -n= [-f= ...] 15 | A field is defined as a "+" separated list of attributes 16 | Attributes depend on the type of the field. 17 | 18 | Type = text: name, label, length 19 | Type = datetime: name, label 20 | Type = lookup: name, label, referenceTo, relationshipName 21 | 22 | 23 | ### Examples 24 | 25 | ``` 26 | 27 | force bigobject list 28 | 29 | force bigobject create -n=MyObject -l="My Object" -p="My Objects" \ 30 | -f=name:Field1+label:"Field 1"+type:Text+length:120 \ 31 | -f=name:MyDate+type=dateTime 32 | 33 | 34 | ``` 35 | 36 | ### Options 37 | 38 | ``` 39 | -h, --help help for bigobject 40 | ``` 41 | 42 | ### Options inherited from parent commands 43 | 44 | ``` 45 | -a, --account username account username to use 46 | -V, --apiversion string API version to use 47 | --config string config directory to use (default: .force) 48 | ``` 49 | 50 | ### SEE ALSO 51 | 52 | * [force](force.md) - force CLI 53 | * [force bigobject create](force_bigobject_create.md) - Create big object 54 | * [force bigobject list](force_bigobject_list.md) - List big objects 55 | 56 | -------------------------------------------------------------------------------- /docs/force_bigobject_create.md: -------------------------------------------------------------------------------- 1 | ## force bigobject create 2 | 3 | Create big object 4 | 5 | ``` 6 | force bigobject create [flags] 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force bigobject create -n=MyObject -l="My Object" -p="My Objects" \ 14 | -f=name:Field1+label:"Field 1"+type:Text+length:120 \ 15 | -f=name:MyDate+type=dateTime 16 | 17 | ``` 18 | 19 | ### Options 20 | 21 | ``` 22 | -f, --field strings field definition 23 | -h, --help help for create 24 | -l, --label string big object label 25 | -p, --plural string big object plural label 26 | ``` 27 | 28 | ### Options inherited from parent commands 29 | 30 | ``` 31 | -a, --account username account username to use 32 | -V, --apiversion string API version to use 33 | --config string config directory to use (default: .force) 34 | ``` 35 | 36 | ### SEE ALSO 37 | 38 | * [force bigobject](force_bigobject.md) - Manage big objects 39 | 40 | -------------------------------------------------------------------------------- /docs/force_bigobject_list.md: -------------------------------------------------------------------------------- 1 | ## force bigobject list 2 | 3 | List big objects 4 | 5 | ``` 6 | force bigobject list [object] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for list 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bigobject](force_bigobject.md) - Manage big objects 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk.md: -------------------------------------------------------------------------------- 1 | ## force bulk 2 | 3 | Load csv file or query data using Bulk API 4 | 5 | ### Examples 6 | 7 | ``` 8 | 9 | force bulk insert Account [csv file] 10 | force bulk update Account [csv file] 11 | force bulk delete Account [csv file] 12 | force bulk upsert -e ExternalIdField__c Account [csv file] 13 | force bulk job [job id] 14 | force bulk batches [job id] 15 | force bulk batch [job id] [batch id] 16 | force bulk query [-wait | -w] Account [SOQL] 17 | force bulk query [-chunk | -p]=50000 Account [SOQL] 18 | force bulk retrieve [job id] [batch id] 19 | 20 | ``` 21 | 22 | ### Options 23 | 24 | ``` 25 | -h, --help help for bulk 26 | ``` 27 | 28 | ### Options inherited from parent commands 29 | 30 | ``` 31 | -a, --account username account username to use 32 | -V, --apiversion string API version to use 33 | --config string config directory to use (default: .force) 34 | ``` 35 | 36 | ### SEE ALSO 37 | 38 | * [force](force.md) - force CLI 39 | * [force bulk batch](force_bulk_batch.md) - Show bulk job batch details 40 | * [force bulk batches](force_bulk_batches.md) - List bulk job batches 41 | * [force bulk delete](force_bulk_delete.md) - Delete records using Bulk API 42 | * [force bulk hardDelete](force_bulk_hardDelete.md) - Hard delete records using Bulk API 43 | * [force bulk insert](force_bulk_insert.md) - Create records from csv file using Bulk API 44 | * [force bulk job](force_bulk_job.md) - Show bulk job details 45 | * [force bulk query](force_bulk_query.md) - Query records using Bulk API 46 | * [force bulk request](force_bulk_request.md) - Retrieve job request using Bulk API 47 | * [force bulk result](force_bulk_result.md) - Retrieve job results using Bulk API 48 | * [force bulk retrieve](force_bulk_retrieve.md) - Retrieve query results using Bulk API 49 | * [force bulk update](force_bulk_update.md) - Update records from csv file using Bulk API 50 | * [force bulk upsert](force_bulk_upsert.md) - Upsert records from csv file using Bulk API 51 | * [force bulk watch](force_bulk_watch.md) - Show bulk job details 52 | 53 | -------------------------------------------------------------------------------- /docs/force_bulk_batch.md: -------------------------------------------------------------------------------- 1 | ## force bulk batch 2 | 3 | Show bulk job batch details 4 | 5 | ``` 6 | force bulk batch [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for batch 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_batches.md: -------------------------------------------------------------------------------- 1 | ## force bulk batches 2 | 3 | List bulk job batches 4 | 5 | ``` 6 | force bulk batches [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for batches 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_delete.md: -------------------------------------------------------------------------------- 1 | ## force bulk delete 2 | 3 | Delete records using Bulk API 4 | 5 | ``` 6 | force bulk delete [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -b, --batchsize int Batch size (default 10000) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -f, --format format file format (default "CSV") 15 | -h, --help help for delete 16 | -i, --interactive interactive mode. implies --wait 17 | -w, --wait Wait for job to complete 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | -V, --apiversion string API version to use 25 | --config string config directory to use (default: .force) 26 | ``` 27 | 28 | ### SEE ALSO 29 | 30 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 31 | 32 | -------------------------------------------------------------------------------- /docs/force_bulk_hardDelete.md: -------------------------------------------------------------------------------- 1 | ## force bulk hardDelete 2 | 3 | Hard delete records using Bulk API 4 | 5 | ``` 6 | force bulk hardDelete [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -b, --batchsize int Batch size (default 10000) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -f, --format format file format (default "CSV") 15 | -h, --help help for hardDelete 16 | -i, --interactive interactive mode. implies --wait 17 | -w, --wait Wait for job to complete 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | -V, --apiversion string API version to use 25 | --config string config directory to use (default: .force) 26 | ``` 27 | 28 | ### SEE ALSO 29 | 30 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 31 | 32 | -------------------------------------------------------------------------------- /docs/force_bulk_insert.md: -------------------------------------------------------------------------------- 1 | ## force bulk insert 2 | 3 | Create records from csv file using Bulk API 4 | 5 | ``` 6 | force bulk insert [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -b, --batchsize int Batch size (default 10000) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -f, --format format file format (default "CSV") 15 | -h, --help help for insert 16 | -i, --interactive interactive mode. implies --wait 17 | -w, --wait Wait for job to complete 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | -V, --apiversion string API version to use 25 | --config string config directory to use (default: .force) 26 | ``` 27 | 28 | ### SEE ALSO 29 | 30 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 31 | 32 | -------------------------------------------------------------------------------- /docs/force_bulk_job.md: -------------------------------------------------------------------------------- 1 | ## force bulk job 2 | 3 | Show bulk job details 4 | 5 | ``` 6 | force bulk job [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for job 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_query.md: -------------------------------------------------------------------------------- 1 | ## force bulk query 2 | 3 | Query records using Bulk API 4 | 5 | ``` 6 | force bulk query [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -p, --chunk records PK chunking size (number of records) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -f, --format format file format (default "CSV") 15 | -h, --help help for query 16 | -i, --interactive interactive mode. implies --wait 17 | --parent object Parent object to use for PK chunking 18 | -A, --query-all query all records including deleted and archived 19 | -w, --wait Wait for job to complete 20 | ``` 21 | 22 | ### Options inherited from parent commands 23 | 24 | ``` 25 | -a, --account username account username to use 26 | -V, --apiversion string API version to use 27 | --config string config directory to use (default: .force) 28 | ``` 29 | 30 | ### SEE ALSO 31 | 32 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 33 | 34 | -------------------------------------------------------------------------------- /docs/force_bulk_request.md: -------------------------------------------------------------------------------- 1 | ## force bulk request 2 | 3 | Retrieve job request using Bulk API 4 | 5 | ``` 6 | force bulk request [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for request 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_result.md: -------------------------------------------------------------------------------- 1 | ## force bulk result 2 | 3 | Retrieve job results using Bulk API 4 | 5 | ``` 6 | force bulk result [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for result 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_retrieve.md: -------------------------------------------------------------------------------- 1 | ## force bulk retrieve 2 | 3 | Retrieve query results using Bulk API 4 | 5 | ``` 6 | force bulk retrieve [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for retrieve 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_bulk_update.md: -------------------------------------------------------------------------------- 1 | ## force bulk update 2 | 3 | Update records from csv file using Bulk API 4 | 5 | ``` 6 | force bulk update [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -b, --batchsize int Batch size (default 10000) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -f, --format format file format (default "CSV") 15 | -h, --help help for update 16 | -i, --interactive interactive mode. implies --wait 17 | -w, --wait Wait for job to complete 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | -V, --apiversion string API version to use 25 | --config string config directory to use (default: .force) 26 | ``` 27 | 28 | ### SEE ALSO 29 | 30 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 31 | 32 | -------------------------------------------------------------------------------- /docs/force_bulk_upsert.md: -------------------------------------------------------------------------------- 1 | ## force bulk upsert 2 | 3 | Upsert records from csv file using Bulk API 4 | 5 | ``` 6 | force bulk upsert -e [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -b, --batchsize int Batch size (default 10000) 13 | -m, --concurrencymode mode Concurrency mode. Valid options are Serial and Parallel. (default "Parallel") 14 | -e, --externalid string The external Id field for upserting data 15 | -f, --format format file format (default "CSV") 16 | -h, --help help for upsert 17 | -i, --interactive interactive mode. implies --wait 18 | -w, --wait Wait for job to complete 19 | ``` 20 | 21 | ### Options inherited from parent commands 22 | 23 | ``` 24 | -a, --account username account username to use 25 | -V, --apiversion string API version to use 26 | --config string config directory to use (default: .force) 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 32 | 33 | -------------------------------------------------------------------------------- /docs/force_bulk_watch.md: -------------------------------------------------------------------------------- 1 | ## force bulk watch 2 | 3 | Show bulk job details 4 | 5 | ``` 6 | force bulk watch [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for watch 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force bulk](force_bulk.md) - Load csv file or query data using Bulk API 26 | 27 | -------------------------------------------------------------------------------- /docs/force_create.md: -------------------------------------------------------------------------------- 1 | ## force create 2 | 3 | Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 4 | 5 | ### Options 6 | 7 | ``` 8 | -h, --help help for create 9 | ``` 10 | 11 | ### Options inherited from parent commands 12 | 13 | ``` 14 | -a, --account username account username to use 15 | -V, --apiversion string API version to use 16 | --config string config directory to use (default: .force) 17 | ``` 18 | 19 | ### SEE ALSO 20 | 21 | * [force](force.md) - force CLI 22 | * [force create apexclass](force_create_apexclass.md) - Create an Apex Class 23 | * [force create apexcomponent](force_create_apexcomponent.md) - Create a Visualforce Component 24 | * [force create apexpage](force_create_apexpage.md) - Create a Visualforce Page 25 | * [force create apextrigger](force_create_apextrigger.md) - Create an Apex Trigger 26 | 27 | -------------------------------------------------------------------------------- /docs/force_create_apexclass.md: -------------------------------------------------------------------------------- 1 | ## force create apexclass 2 | 3 | Create an Apex Class 4 | 5 | ``` 6 | force create apexclass [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for apexclass 13 | -n, --name string Name of Apex Class 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force create](force_create.md) - Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 27 | 28 | -------------------------------------------------------------------------------- /docs/force_create_apexcomponent.md: -------------------------------------------------------------------------------- 1 | ## force create apexcomponent 2 | 3 | Create a Visualforce Component 4 | 5 | ``` 6 | force create apexcomponent [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for apexcomponent 13 | -n, --name string Name of Visualforce Component 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force create](force_create.md) - Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 27 | 28 | -------------------------------------------------------------------------------- /docs/force_create_apexpage.md: -------------------------------------------------------------------------------- 1 | ## force create apexpage 2 | 3 | Create a Visualforce Page 4 | 5 | ``` 6 | force create apexpage [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for apexpage 13 | -n, --name string Name of Visualforce Page 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force create](force_create.md) - Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 27 | 28 | -------------------------------------------------------------------------------- /docs/force_create_apextrigger.md: -------------------------------------------------------------------------------- 1 | ## force create apextrigger 2 | 3 | Create an Apex Trigger 4 | 5 | ``` 6 | force create apextrigger [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for apextrigger 13 | -n, --name string Name of Apex Trigger 14 | -s, --sobject string For which sobject should the trigger be created 15 | ``` 16 | 17 | ### Options inherited from parent commands 18 | 19 | ``` 20 | -a, --account username account username to use 21 | -V, --apiversion string API version to use 22 | --config string config directory to use (default: .force) 23 | ``` 24 | 25 | ### SEE ALSO 26 | 27 | * [force create](force_create.md) - Creates a new, empty Apex Class, Trigger, Visualforce page, or Component. 28 | 29 | -------------------------------------------------------------------------------- /docs/force_datapipe.md: -------------------------------------------------------------------------------- 1 | ## force datapipe 2 | 3 | Manage DataPipes 4 | 5 | ### Examples 6 | 7 | ``` 8 | 9 | force datapipe create -n=MyPipe -l="My Pipe" -t=Pig -v=34.0 \ 10 | -c="A = load 'force://soql/Select Id, Name From Contact' using \ 11 | gridforce.hadoop.pig.loadstore.func.ForceStorage();" 12 | 13 | ``` 14 | 15 | ### Options 16 | 17 | ``` 18 | -h, --help help for datapipe 19 | ``` 20 | 21 | ### Options inherited from parent commands 22 | 23 | ``` 24 | -a, --account username account username to use 25 | -V, --apiversion string API version to use 26 | --config string config directory to use (default: .force) 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [force](force.md) - force CLI 32 | * [force datapipe create](force_datapipe_create.md) - Create Data Pipeline 33 | * [force datapipe createjob](force_datapipe_createjob.md) - Create Data Pipeline Job 34 | * [force datapipe delete](force_datapipe_delete.md) - Delete Data Pipeline 35 | * [force datapipe list](force_datapipe_list.md) - List Data Pipelines 36 | * [force datapipe listjobs](force_datapipe_listjobs.md) - List Data Pipeline Jobs 37 | * [force datapipe queryjob](force_datapipe_queryjob.md) - Query Data Pipeline Job 38 | * [force datapipe update](force_datapipe_update.md) - Update Data Pipeline 39 | 40 | -------------------------------------------------------------------------------- /docs/force_datapipe_create.md: -------------------------------------------------------------------------------- 1 | ## force datapipe create 2 | 3 | Create Data Pipeline 4 | 5 | ``` 6 | force datapipe create [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -v, --apiversion string script content (default "55.0") 13 | -h, --help help for create 14 | -l, --masterlabel string master label 15 | -n, --name string data pipeline name 16 | -c, --scriptcontent string script content (default "\n-- Sample script for a data pipeline\nA = load 'ffx://REPLACE_ME' using gridforce.hadoop.pig.loadstore.func.ForceStorage();\nStore A into 'ffx://REPLACE_ME_TOO' using gridforce.hadoop.pig.loadstore.func.ForceStorage();\n") 17 | -t, --scripttype string script type (default "Pig") 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | --config string config directory to use (default: .force) 25 | ``` 26 | 27 | ### SEE ALSO 28 | 29 | * [force datapipe](force_datapipe.md) - Manage DataPipes 30 | 31 | -------------------------------------------------------------------------------- /docs/force_datapipe_createjob.md: -------------------------------------------------------------------------------- 1 | ## force datapipe createjob 2 | 3 | Create Data Pipeline Job 4 | 5 | ``` 6 | force datapipe createjob [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for createjob 13 | -n, --name string data pipeline name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force datapipe](force_datapipe.md) - Manage DataPipes 27 | 28 | -------------------------------------------------------------------------------- /docs/force_datapipe_delete.md: -------------------------------------------------------------------------------- 1 | ## force datapipe delete 2 | 3 | Delete Data Pipeline 4 | 5 | ``` 6 | force datapipe delete [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for delete 13 | -n, --name string data pipeline name 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force datapipe](force_datapipe.md) - Manage DataPipes 27 | 28 | -------------------------------------------------------------------------------- /docs/force_datapipe_list.md: -------------------------------------------------------------------------------- 1 | ## force datapipe list 2 | 3 | List Data Pipelines 4 | 5 | ``` 6 | force datapipe list [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -f, --format string format (csv or json) (default "json") 13 | -h, --help help for list 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force datapipe](force_datapipe.md) - Manage DataPipes 27 | 28 | -------------------------------------------------------------------------------- /docs/force_datapipe_listjobs.md: -------------------------------------------------------------------------------- 1 | ## force datapipe listjobs 2 | 3 | List Data Pipeline Jobs 4 | 5 | ``` 6 | force datapipe listjobs [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for listjobs 13 | ``` 14 | 15 | ### Options inherited from parent commands 16 | 17 | ``` 18 | -a, --account username account username to use 19 | -V, --apiversion string API version to use 20 | --config string config directory to use (default: .force) 21 | ``` 22 | 23 | ### SEE ALSO 24 | 25 | * [force datapipe](force_datapipe.md) - Manage DataPipes 26 | 27 | -------------------------------------------------------------------------------- /docs/force_datapipe_queryjob.md: -------------------------------------------------------------------------------- 1 | ## force datapipe queryjob 2 | 3 | Query Data Pipeline Job 4 | 5 | ``` 6 | force datapipe queryjob [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -h, --help help for queryjob 13 | -j, --jobid string id of data pipeline job 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force datapipe](force_datapipe.md) - Manage DataPipes 27 | 28 | -------------------------------------------------------------------------------- /docs/force_datapipe_update.md: -------------------------------------------------------------------------------- 1 | ## force datapipe update 2 | 3 | Update Data Pipeline 4 | 5 | ``` 6 | force datapipe update [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -v, --apiversion string script content (default "55.0") 13 | -h, --help help for update 14 | -l, --masterlabel string master label 15 | -n, --name string data pipeline name 16 | -c, --scriptcontent string script content (default "\n-- Sample script for a data pipeline\nA = load 'ffx://REPLACE_ME' using gridforce.hadoop.pig.loadstore.func.ForceStorage();\nStore A into 'ffx://REPLACE_ME_TOO' using gridforce.hadoop.pig.loadstore.func.ForceStorage();\n") 17 | -t, --scripttype string script type (default "Pig") 18 | ``` 19 | 20 | ### Options inherited from parent commands 21 | 22 | ``` 23 | -a, --account username account username to use 24 | --config string config directory to use (default: .force) 25 | ``` 26 | 27 | ### SEE ALSO 28 | 29 | * [force datapipe](force_datapipe.md) - Manage DataPipes 30 | 31 | -------------------------------------------------------------------------------- /docs/force_deploys.md: -------------------------------------------------------------------------------- 1 | ## force deploys 2 | 3 | Manage metadata deployments 4 | 5 | ### Synopsis 6 | 7 | 8 | List and cancel metadata deployments. 9 | 10 | 11 | ### Examples 12 | 13 | ``` 14 | 15 | force deploys list 16 | force deploys cancel --all 17 | force deploys cancel -d 0Af000000000000000 18 | 19 | ``` 20 | 21 | ### Options 22 | 23 | ``` 24 | -h, --help help for deploys 25 | ``` 26 | 27 | ### Options inherited from parent commands 28 | 29 | ``` 30 | -a, --account username account username to use 31 | -V, --apiversion string API version to use 32 | --config string config directory to use (default: .force) 33 | ``` 34 | 35 | ### SEE ALSO 36 | 37 | * [force](force.md) - force CLI 38 | * [force deploys cancel](force_deploys_cancel.md) - Cancel deploy 39 | * [force deploys errors](force_deploys_errors.md) - List metadata deploy errors 40 | * [force deploys list](force_deploys_list.md) - List metadata deploys 41 | * [force deploys watch](force_deploys_watch.md) - Monitor metadata deploy 42 | 43 | -------------------------------------------------------------------------------- /docs/force_deploys_cancel.md: -------------------------------------------------------------------------------- 1 | ## force deploys cancel 2 | 3 | Cancel deploy 4 | 5 | ``` 6 | force deploys cancel -d 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -A, --all Cancel all pending and in-progress deploys 13 | -d, --deploy-id string Deploy Id to cancel 14 | -h, --help help for cancel 15 | ``` 16 | 17 | ### Options inherited from parent commands 18 | 19 | ``` 20 | -a, --account username account username to use 21 | -V, --apiversion string API version to use 22 | --config string config directory to use (default: .force) 23 | ``` 24 | 25 | ### SEE ALSO 26 | 27 | * [force deploys](force_deploys.md) - Manage metadata deployments 28 | 29 | -------------------------------------------------------------------------------- /docs/force_deploys_errors.md: -------------------------------------------------------------------------------- 1 | ## force deploys errors 2 | 3 | List metadata deploy errors 4 | 5 | ``` 6 | force deploys errors [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -d, --deploy-id string Deploy Id to cancel 13 | -h, --help help for errors 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force deploys](force_deploys.md) - Manage metadata deployments 27 | 28 | -------------------------------------------------------------------------------- /docs/force_deploys_list.md: -------------------------------------------------------------------------------- 1 | ## force deploys list 2 | 3 | List metadata deploys 4 | 5 | ``` 6 | force deploys list [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -f, --format string output format: csv, json, json-pretty, console (default "console") 13 | -h, --help help for list 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force deploys](force_deploys.md) - Manage metadata deployments 27 | 28 | -------------------------------------------------------------------------------- /docs/force_deploys_watch.md: -------------------------------------------------------------------------------- 1 | ## force deploys watch 2 | 3 | Monitor metadata deploy 4 | 5 | ``` 6 | force deploys watch [flags] 7 | ``` 8 | 9 | ### Options 10 | 11 | ``` 12 | -d, --deploy-id string Deploy Id to cancel 13 | -h, --help help for watch 14 | ``` 15 | 16 | ### Options inherited from parent commands 17 | 18 | ``` 19 | -a, --account username account username to use 20 | -V, --apiversion string API version to use 21 | --config string config directory to use (default: .force) 22 | ``` 23 | 24 | ### SEE ALSO 25 | 26 | * [force deploys](force_deploys.md) - Manage metadata deployments 27 | 28 | -------------------------------------------------------------------------------- /docs/force_describe.md: -------------------------------------------------------------------------------- 1 | ## force describe 2 | 3 | Describe the types of metadata available in the org 4 | 5 | ### Examples 6 | 7 | ``` 8 | 9 | force describe metadata 10 | force describe metadata -t MatchingRule -j 11 | force describe sobject -n Account 12 | 13 | ``` 14 | 15 | ### Options 16 | 17 | ``` 18 | -h, --help help for describe 19 | ``` 20 | 21 | ### Options inherited from parent commands 22 | 23 | ``` 24 | -a, --account username account username to use 25 | -V, --apiversion string API version to use 26 | --config string config directory to use (default: .force) 27 | ``` 28 | 29 | ### SEE ALSO 30 | 31 | * [force](force.md) - force CLI 32 | * [force describe metadata](force_describe_metadata.md) - Describe metadata 33 | * [force describe sobject](force_describe_sobject.md) - List sobjects 34 | 35 | -------------------------------------------------------------------------------- /docs/force_describe_metadata.md: -------------------------------------------------------------------------------- 1 | ## force describe metadata 2 | 3 | Describe metadata 4 | 5 | ### Synopsis 6 | 7 | List the metadata in the org. With no type specified, lists all 8 | metadata types supported. Specifying a type will list the individual metadata 9 | components of that type. 10 | 11 | 12 | ``` 13 | force describe metadata [flags] 14 | ``` 15 | 16 | ### Examples 17 | 18 | ``` 19 | 20 | force describe metadata 21 | force describe metadata -t MatchingRule -j 22 | 23 | ``` 24 | 25 | ### Options 26 | 27 | ``` 28 | -h, --help help for metadata 29 | -j, --json json output 30 | -t, --type string type of metadata 31 | ``` 32 | 33 | ### Options inherited from parent commands 34 | 35 | ``` 36 | -a, --account username account username to use 37 | -V, --apiversion string API version to use 38 | --config string config directory to use (default: .force) 39 | ``` 40 | 41 | ### SEE ALSO 42 | 43 | * [force describe](force_describe.md) - Describe the types of metadata available in the org 44 | 45 | -------------------------------------------------------------------------------- /docs/force_describe_sobject.md: -------------------------------------------------------------------------------- 1 | ## force describe sobject 2 | 3 | List sobjects 4 | 5 | ### Synopsis 6 | 7 | With no name specified, list all SObjects in the org. Specifying an 8 | object name will retrieve all of the details about the object. 9 | 10 | 11 | ``` 12 | force describe sobject [flags] 13 | ``` 14 | 15 | ### Options 16 | 17 | ``` 18 | -h, --help help for sobject 19 | -j, --json json output 20 | -n, --name string name of sobject 21 | ``` 22 | 23 | ### Options inherited from parent commands 24 | 25 | ``` 26 | -a, --account username account username to use 27 | -V, --apiversion string API version to use 28 | --config string config directory to use (default: .force) 29 | ``` 30 | 31 | ### SEE ALSO 32 | 33 | * [force describe](force_describe.md) - Describe the types of metadata available in the org 34 | 35 | -------------------------------------------------------------------------------- /docs/force_eventlogfile.md: -------------------------------------------------------------------------------- 1 | ## force eventlogfile 2 | 3 | List and fetch event log file 4 | 5 | ``` 6 | force eventlogfile [eventlogfileId] [flags] 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force eventlogfile 14 | force eventlogfile 0AT300000000XQ7GAM 15 | 16 | ``` 17 | 18 | ### Options 19 | 20 | ``` 21 | -h, --help help for eventlogfile 22 | ``` 23 | 24 | ### Options inherited from parent commands 25 | 26 | ``` 27 | -a, --account username account username to use 28 | -V, --apiversion string API version to use 29 | --config string config directory to use (default: .force) 30 | ``` 31 | 32 | ### SEE ALSO 33 | 34 | * [force](force.md) - force CLI 35 | 36 | -------------------------------------------------------------------------------- /docs/force_export.md: -------------------------------------------------------------------------------- 1 | ## force export 2 | 3 | Export metadata to a local directory 4 | 5 | ``` 6 | force export [dir] [flags] 7 | ``` 8 | 9 | ### Examples 10 | 11 | ``` 12 | 13 | force export 14 | force export [directory] 15 | force export -x ApexClass -x CustomObject 16 | 17 | ``` 18 | 19 | ### Options 20 | 21 | ``` 22 | -x, --exclude strings exclude metadata type 23 | -h, --help help for export 24 | -w, --warnings display warnings about metadata that cannot be retrieved 25 | ``` 26 | 27 | ### Options inherited from parent commands 28 | 29 | ``` 30 | -a, --account username account username to use 31 | -V, --apiversion string API version to use 32 | --config string config directory to use (default: .force) 33 | ``` 34 | 35 | ### SEE ALSO 36 | 37 | * [force](force.md) - force CLI 38 | 39 | -------------------------------------------------------------------------------- /docs/force_fetch.md: -------------------------------------------------------------------------------- 1 | ## force fetch 2 | 3 | Export specified artifact(s) to a local directory 4 | 5 | ### Synopsis 6 | 7 | 8 | Export specified artifact(s) to a local directory. Use "package" type to retrieve an unmanaged package. 9 | 10 | 11 | ``` 12 | force fetch -t ApexClass [flags] 13 | ``` 14 | 15 | ### Examples 16 | 17 | ``` 18 | 19 | force fetch -t=CustomObject -n=Book__c -n=Author__c 20 | force fetch -t Aura -n MyComponent -d /Users/me/Documents/Project/home 21 | force fetch -t AuraDefinitionBundle -t ApexClass 22 | force fetch -x myproj/metadata/package.xml 23 | 24 | ``` 25 | 26 | ### Options 27 | 28 | ``` 29 | -d, --directory string Use to specify the root directory of your project 30 | -h, --help help for fetch 31 | -n, --name strings names of metadata 32 | -p, --preserve keep zip file on disk 33 | -t, --type strings Type of metadata to fetch 34 | -u, --unpack Unpack any static resources 35 | -x, --xml string Package.xml file to use for fetch. 36 | ``` 37 | 38 | ### Options inherited from parent commands 39 | 40 | ``` 41 | -a, --account username account username to use 42 | -V, --apiversion string API version to use 43 | --config string config directory to use (default: .force) 44 | ``` 45 | 46 | ### SEE ALSO 47 | 48 | * [force](force.md) - force CLI 49 | 50 | -------------------------------------------------------------------------------- /docs/force_field.md: -------------------------------------------------------------------------------- 1 | ## force field 2 | 3 | Manage SObject fields 4 | 5 | ### Synopsis 6 | 7 | 8 | Manage SObject fields 9 | 10 | Usage: 11 | 12 | force field list 13 | force field create : [