{"id":13509534,"url":"https://github.com/jeffweiss/forcex","last_synced_at":"2025-04-09T17:26:51.498Z","repository":{"id":23476872,"uuid":"26841726","full_name":"jeffweiss/forcex","owner":"jeffweiss","description":"Elixir library for the Force.com / Salesforce / SFDC REST API","archived":false,"fork":false,"pushed_at":"2022-10-28T18:37:05.000Z","size":149,"stargazers_count":51,"open_issues_count":12,"forks_count":33,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-02T11:56:29.706Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeffweiss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-19T03:01:35.000Z","updated_at":"2024-04-03T13:33:55.000Z","dependencies_parsed_at":"2022-08-19T07:00:39.049Z","dependency_job_id":null,"html_url":"https://github.com/jeffweiss/forcex","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffweiss%2Fforcex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffweiss%2Fforcex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffweiss%2Fforcex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffweiss%2Fforcex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffweiss","download_url":"https://codeload.github.com/jeffweiss/forcex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248076317,"owners_count":21043748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T02:01:09.178Z","updated_at":"2025-04-09T17:26:51.480Z","avatar_url":"https://github.com/jeffweiss.png","language":"Elixir","funding_links":[],"categories":["Third Party APIs"],"sub_categories":[],"readme":"# Forcex\n\n[![Build Status](https://travis-ci.org/jeffweiss/forcex.svg?branch=master)](https://travis-ci.org/jeffweiss/forcex)\n[![Hex.pm Version](http://img.shields.io/hexpm/v/forcex.svg?style=flat)](https://hex.pm/packages/forcex)\n[![Coverage Status](https://coveralls.io/repos/github/jeffweiss/forcex/badge.svg?branch=master)](https://coveralls.io/github/jeffweiss/forcex?branch=master)\n\nElixir library for interacting with the Force.com REST API.\n\n## Usage\n\nAdd Forcex to your dependency list\n```elixir\n  defp deps do\n    [ {:forcex, \"~\u003e 0.4\"}\n    ]\n  end\n```\n\nAt compile time Forcex will query the Force.com REST API and generate modules for all the\nSObjects you have configured and permission to see.\n\nIf you see a warning like\n```elixir\n23:37:02.057 [warn]  Cannot log into SFDC API. Please ensure you have Forcex properly configured.\nGot error code 400 and message %{\"error\" =\u003e \"invalid_client_id\", \"error_description\" =\u003e \"client identifier invalid\"}\n```\n\nYou will need to configure Forcex, as noted below, and then explicitly recompile Forcex\n\n```shell\n$ mix deps.clean forcex\n$ mix deps.compile forcex\n```\n\nYou can have Forcex generate modules at compile time using the accompanying Mix task.\n\n```shell\n$ mix compile.forcex\n```\n\nThis can also be invoked automatically by adding Forcex to your project's compilers in `mix.exs`\n\n```elixir\ncompilers: [:forcex] ++ Mix.compilers,\n```\n\n## Bulk API Usage\n\nForcex has an example Bulk API query job controller. Here's roughly how that can\nwork.\n\n```elixir\nclient = Forcex.Bulk.Client.login\n[\n  \"Account\",\n  \"Campaign\",\n  \"Contact\",\n  \"Lead\",\n  \"Opportunity\",\n  \"OpportunityLineItem\",\n]\n|\u003e Enum.map(fn sobject -\u003e {sobject, [\"select Id, Name from #{sobject}\"]} end)\n|\u003e Enum.map(fn {sobject, queries} -\u003e\nForcex.Bulk.JobController.start_link({:query, sobject, queries, client}) end)\n```\n\n## Configuration\n\nThe `Forcex.Client` is configured to read login information either from\napplication configuration:\n\n```elixir\n\nconfig :forcex, Forcex.Client,\n  username: \"user@example.com\",\n  password: \"my_super_secret_password\",\n  security_token: \"EMAILED_FROM_SALESFORCE\",\n  client_id: \"CONNECTED_APP_OAUTH_CLIENT_ID\",\n  client_secret: \"CONNECTED_APP_OAUTH_CLIENT_SECRET\"\n```\n\nor these environment variables:\n\n* `SALESFORCE_USERNAME`\n* `SALESFORCE_PASSWORD`\n* `SALESFORCE_SECURITY_TOKEN`\n* `SALESFORCE_CLIENT_ID`\n* `SALESFORCE_CLIENT_SECRET`\n\nHTTPoison request-specific options may also be configured:\n\n```elixir\nconfig :forcex, :request_options,\n  timeout: 20000,\n  recv_timeout: :infinity\n```\n\nFor steps on how to create a Connected App with OAuth keys and secrets,\nplease see the [Force.com REST API section on Connected Apps](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_defining_remote_access_applications.htm).\n\nCurrently, to be fully functional, the `Forcex.Client` must both `login` and\n`locate_services`.\n\nPagination of results is entirely manual at the moment.\n\n```elixir\nclient = Forcex.Client.login |\u003e Forcex.Client.locate_services\n\nfirst_page = Forcex.query(\"select Id, Name from Account order by CreatedDate desc\", client)\n\nsecond_page = first_page |\u003e Map.get(:nextRecordsUrl) |\u003e Forcex.get(client)\n```\n\n## Further Configuration\n\nForcex allows additional configuration of API endpoint and API version via the\n`%Forcex.Client{}` struct. You may also use this mechanism if you have a\n`grant_type` other than password.\n\nThis example shows how to use both an older API version and the SalesForce\nsandbox API.\n```elixir\nForcex.Client.default_config\n|\u003e Forcex.Client.login(%Forcex.Client{endpoint: \"https://test.salesforce.com\", api_version: \"34.0\"})\n```\n\n## Testing\n\nMake sure dependencies are installed\n\n    mix deps.get\n\nTests can be run with\n\n    mix test\n\nTests can be run automatically when files change with\n\n    mix test.watch --stale\n\nTests mock the api calls to the Salesforce API using Mox to set expectations on\n`Forcex.Api.MockHttp.raw_request`.  To know what to put in a mock response just\nrun the client in `iex` and look for the debug logging response from http.ex.\nMake sure to scrub any responses for sensitive data before including them\nin a commit.\n\nExample assuming environment variables are in place with login info\n\n    % iex -S mix\n    iex(1)\u003e client = Forcex.Client.login |\u003e Forcex.Client.locate_services\n    14:40:27.858 file=forcex/lib/forcex/api/http.ex line=19 [debug] Elixir.Forcex.Api.Http.raw_request response=%{access_token: \"redacted\",...\n    14:40:28.222 file=forcex/lib/forcex/api/http.ex line=19 [debug] Elixir.Forcex.Api.Http.raw_request response=%{process: \"/services/data/v43.0/process\", search...\n    iex(2)\u003e Forcex.query(\"select Id, Name from Account order by CreatedDate desc\", client)\n    14:43:05.896 file=forcex/lib/forcex/api/http.ex line=19 [debug] Elixir.Forcex.Api.Http.raw_request response=%{done: false, nextRecordsUrl: \"/services/data/v4\n\nJust take the data after `response=` and throw it in a Mox expectation.  See\nexisting tests for full examples\n\n    response = %{access_token: \"redacted\"}\n    Forcex.Api.MockHttp\n    |\u003e expect(:raw_request, fn(:get, ^expected_url, _, ^auth_header, _) -\u003e response end)\n\n\n## Current State\n\nSee https://www.salesforce.com/us/developer/docs/api_rest/\n\n - [x] List API versions available\n - [x] Login (Username/Password/Client Key/Client Secret)\n - [ ] Login (Web Server OAuth)\n - [ ] Login (User-Agent OAuth)\n - [ ] OAuth Refresh Token\n - [x] Resources by Version\n - [x] Limits\n - [x] Describe Global\n - [x] SObject Basic Information\n - [x] SObject Describe\n - [x] SObject Get Deleted\n - [x] SObject Get Updated\n - [ ] SObject Named Layouts\n - [x] SObject Rows\n - [x] SObject Rows by External ID\n - [ ] SObject ApprovalLayouts\n - [ ] SObject CompactLayouts\n - [ ] SObject Layouts\n - [x] SObject Blob Retrieve\n - [ ] SObject Quick Actions\n - [ ] SObject Suggested Articles for Case\n - [ ] SObject User Password\n - [ ] AppMenu\n - [ ] Compact Layouts\n - [ ] FlexiPage\n - [ ] Process Approvals\n - [ ] Process Rules\n - [x] Query\n - [x] QueryAll\n - [x] Quick Actions\n - [ ] Search\n - [ ] Search Scope and Order\n - [ ] Search Result Layouts\n - [x] Recently Viewed Items\n - [ ] Search Suggested Article Title Matches\n - [x] Tabs\n - [x] Themes\n\n# License\n\nMIT License, see LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffweiss%2Fforcex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffweiss%2Fforcex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffweiss%2Fforcex/lists"}