fake-salesforce-remote-objects

Library that auto-fakes the Salesforce Remote Object API based on apex:remoteObject DOM elements in the page. For use in local development ONLY.

Usage no npm install needed!

<script type="module">
  import fakeSalesforceRemoteObjects from 'https://cdn.skypack.dev/fake-salesforce-remote-objects';
</script>

README

fake-salesforce-remote-objects

If you are using @RemoteActions, this package will not help you at all!

The purpose of this package is to make it easier possible to locally develop Visualforce pages that make use of Salesforce Remote Objects. It is somewhat opinionated in how it expects apex DOM elements to be declared.

  • Only one jsNamespace is allowed for all apex:remoteObject elements
    • More than one namespace will result in an error
    • If you do not define a namespace, it is set to the Salesforce default of SObjectModel
      • For simplicity and brevity, it is easiest to not define any namespaces and use the default
  • apex:remoteObjectModel should have their fields declared in the fields attribute, not in individual apex:remoteObjectField
    • Objects must have at least one field declared, otherwise an error will occur
    • Functions are automatically generated based on the Name. This is inline with the offical API
    • If a jsShortname is declared, functions will be generated for that as well
  • apex:remoteObjectField are totally ignored, so if you use these you will need to refactor to us the field attribute of apex:remoteObjectModel
    • This was an intentional omission, I see no point in renaming fields in your frontend (unless you really enjoy confusion)

This library in no way keeps track of the state of created/updated/deleted objects. Creating a record then doing a retrieval will not return that object. In fact, it will return an entirely different object. This library only serves to give you something it bounce your remote object requests off of during local development. If your application requires advanced logic such as creating an object then immediately retrieving that object, keep in mind this will not work exactly right during local development, since the returned object will have different data than expected.

Since this library is a fake of the offical remote object API, promises are not supported OOTB(just like the real API). Unless you like callbacks, I suggest writing your own helpers to wrap these functions in promises.

installation

npm install fake-salesforce-remote-objects

usage

To use this package, simply make a reference to the index.js script in the HEAD of your page:

<script src="../../node_modules/fake-salesforce-remote-objects/index.js"></script>

or if you are using Webpack or some other bundler, just reference the package in your entrypoint:

import 'fake-salesforce-remote-objects';

Upon page load, the script will run and attach a remote object manager to the window under the namespace you defined. Declaring the following object:

  <apex:remoteObjects>
    <apex:remoteObjectModel name="Contact" jsShorthand="jsContact" fields="Id, Name"></apex:remoteObjectModel>
  </apex:remoteObjects>

Fake contacts can be be accessed locally in exactly the same way that they are accessed on a deployed Visualforce page:

    getContacts() {
      const contact = SObjectModel.jsContact();
      new contact.retrieve({ limit: 10 }, (err, contacts) => {
      console.log(contacts);
        for (let i = 0; i < contacts.length; i++) {
          console.log(contacts[i].get("Id"));
        }
        return;
      });
    }
    createContact() {
      const contact = SObjectModel.jsContact();
      new contact.create({ LastName: 'some_dude' }, (err) => {
        if(err){
          console.log(err);
          return;
        }
        console.log('Good job, you inserted a contact!');
        return;
      });
    }

This library should not be used in a page deployed to Salesforce. It will detect that the page is in a deployed environment, and print a message in the console. Your page will still work properly, but don't force your users to download things they don't need.

Object Names

Object names are derived in the following ways:

  • The root remote manager is determined by what you set your jsNamespace attribute to in your root apex:remoteObjects DOM elements
    • If you omit the jsNamespace attribute, it will be set to SObjectModel
    • Currently, only one namespace is allowed, more than one will intentionally throw an error
  • The jsShorthand name for apex:remoteObjectModel can be explicitly defined in the DOM element
    • This is not required, but can be used if you choose
    • If not defined, call the object by the Name attribute

Fake fields

These fields are not part of the Salesforce spec, and they should not be referenced directly in your code.

RemoteObject

These fields are added to the window level Remote Object

  • _jsNamespace
    • The namespace that the Remote Object was assigned to via jsNamespace
  • _remoteObjectModels
    • The available models as defined on the page through apex:remoteobjectmodel DOM elements

RemoteObjectModel

These fields are added to any fake objects created. They simply exist to make local development easier and help you keep track of objects.

  • _sfObjectType
    • The Salesforce Object Type declared in the apex:remoteObjectModel
  • _shorthandName
    • The jsShorthand name
    • Field won't exist if jsShorthand wasn't used
  • _fakeCount
    • When doing a query or retrieval, this field keeps count of the returned objects
  • _predefinedObject
    • If you initalized the object with values, the original values will be stored here
    • Field won't exist if initialized without values
  • _values
    • When initializing objects, values are stored here
    • This is to accurately reflect the Salesforce API, which doesn't attach properties directly to the object
      • Use the get method to retrieve values from this store
      • Values should never be directly accessed through this property

Fake Object functions

This list contains the fuctions that have been faked from the Salesforce Remote Object API. It probably won't ever contain all of the possible functions, just the most frequently used ones. Console messages are used extensively so you can follow your API calls during development.

  • constructor({ field: 'value', field2: 'value'})
    • Any fields passed in to the constructor will be assigned to the created object
    • Any retrievals from this object will return an array of n objects of the same type, but with different data
  • get(FieldName)
    • If the value was initialized during construction
      • The value will be returned
    • If the value was set in code
      • The value will be returned
    • If the value was not initalized
      • It will consistently return the same random string
    • If the field was not defined in the apex:remoteObjectModel DOM element
      • an error message will be printed in the console but your code will still be allowed to run
      • The return value will also make note of this error.
    • Values are stored in the _values property on the object, but you should only access them through this method
  • set(fieldName, value)
    • Set the internal _values field to the value provided
  • retrieve({ limit: 100, where: {} }, callback(err, results))
    • Only the callback format of this function is supported
    • Each returned object is automatically assigned an Id field that is populated with a random string to simulate a Salesforce Id
    • A number of objects equal to the limit passed in are returned
      • These objects are direct copies of the initalized object
      • object have a _fakeCount field attached to them for identification
      • limits > 100 will display an error message, but your code will run normally
        • Salesforce doesn't allow more than 100 results at a time
      • The where clause object will be echo'd back at you in console
        • Where clause arguments are not validated nor are results filtered based on the query
  • create() | create(callback) | create(recordValues, callback)
    • The callback methods are the preferred way to use this function
    • An Id field will be created and populated on execution
    • An array of created Ids will be turned if using callback
    • Nothing is returned if callback omitted (per API spec)
  • update() | update(callback) | update(recordValues, callback)
    • Currently only one record can be updated at a time
    • The callback methods are the preferred way to use this function
    • An array of updated Ids will be turned if using callback
    • Nothing is returned if callback omitted (per API spec)

Fake Data

The fake data generated by this library is not representative of the fields or their data types. It is simply filler data so you have something to look at while you develop.

  • Any created Fake object will be assigned a unique faux Id field

    • This field in no way represents an actual Salesforce object Id, and its value should not be depended upon in your code
    • The value is not even in the Salesforce format to discourage any sort of filtering by Id
  • Any fields defined in the apex:remoteobjectmodel will be assigned random values upon fake object creation

  • If you pass in a predefined object, any fields supplied will not be overwritten

    • If you have fields you wish to remain blank, then pass them in with empty strings
  • If you attempt to get a field that was not predefined, and is not defined in the apex:remoteobjectmodel, an error is displayed in the console

    • This isn't a fatal error, just a warning that you should add that field to your apex:remoteobjectmodel definition
  • UUID Generation Library

  • RandomWords Library

Configuration

Basic configuration can be made by assigning a Configuration object to the window.fakeRemoteConfig object.

  • debugLevel
    • 1 - Will show all DEBUG message
    • 2 - Only shows INFO messages
  • requestDelay
    • Default 1000ms
    • Will delay all commands for Create/Update/Retrieve by the specified amount
    • Use to simulate a real deployment
  • errors
    • create
      • Set True to cause all create operations to fail via callback
    • update
      • Set True to cause all update operations to fail via callback
    • retrieve
      • Set True to cause all retrieve operations to fail via callback

Wish list

  • Predefined data sets
    • An external file that could be used to model Salesforce objects, their fields, and potential field values
  • Global configuration
    • Pass in an object to set behavior
      • Fake time delay for CRUD
      • Fake server errors
      • Set logging level
  • Keep track of objects
  • Parse retrieval queries and return objects based on them

More functions will be added as necessary, pull requests are welcome!