npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

salesforce-schema-reader

v1.0.6

Published

A tool to read a salesforce database schema using a visitor pattern which can be extended to a visitor-filter pattern enbling searches based on any schema data like for instance object and field names

Downloads

10

Readme

salesforce-schema-reader

quick example

Upload the file dist/schema-reader.js as a staticresource called schemaReader and this should work:

<apex:page docType="html-5.0" showHeader="false"> 

 <ul id="test"></ul>

 <apex:includeScript value="{!URLFOR($Resource.schemaReader)}" />
 <script src="/soap/ajax/39.0/connection.js"></script>
 <script>
 // setup a connection instance
 sforce.connection.sessionId = "{!$Api.Session_ID}";  
 var connection = sforce.connection;
   
 // callbacks and batch size for loading the schema
 var batchSize = 50;
 function failure() { console.log('An error occured while trying to load the schema'); };
 function success(reader) { 
   console.log('Schema loaded successfully'); 
   // visit the id field of each type and log the metadata
   var list = document.getElementById('test');
   reader.shallowReadFields(function(field, object, path, reader){
     if(field.name === 'Id') {
       var e = document.createElement('li');
       e.innerHTML = object.name;
       list.appendChild(e);
     }
   });
 };
   
 // load the schema into the schema reader
 var reader = new SchemaReader(connection, batchSize, success, failure);
   
 </script>
</apex:page>

Now if you load the page and look at the browser console you should see a load of schema data displayed.

introduction

This tool will help you in reading a salesforce database schema. You can read the entire schema using a visitor. A visitor is a function which takes context information as parameters. Specifically a visitor in this too will be given the current field being visited, the object that the field belongs to, the path that was followed to get to that field and the reader instance itself. Hence a field visitor definition looks like this:

function visitor(field, object, path, reader)

where the path is an array with the object that the read started from as its first element, the relationship objects that the reader used to find it's way to referenced objects as it's intermediate elements and the visited field object as it's last element.

And a child relationship visitor definition looks like this:

function visitor(rel, object, path, reader)

Where the path is an array with the object that the read started from as its first element and the child relationship objects that the reader used to find it's way to referenced objects as it's concecutive elements.

The child relationship read is the opposite of a field read. Crudely in database terms, if an object has a reference to another object, it is the child of that object and that makes the other object the parent object. In salesforce the parent object is specifically given a child relationship definition and you can walk these relationships whith a child relationship visitor in this tool.

The reader takes care of not traversing circular dpendencies i.e. if there is an object called Human with a reference to an object called Pet with a reference back to Human, that would be a circular dependency and if not handled will cause an infinite loop. The reader handles these scenarios simply by keeping track of all the traversed objects and making sure no object gets traversed twice.

Obtaining a salesforce connection instance

To put your visitor into use you need a salesforce connection which you can aquire for example in a visualforce page like so:

<apex:page docType="html-5.0" showHeader="false">
  <script src="/soap/ajax/39.0/connection.js"></script>
  <script>
  var connection = sforce.connection;
  </script>
</apex:page>

Instatiating the reader in a standard html page

If you have saved your schema reader file in ./js/schema-reader.js you can initialise it like so:

<script src="schema-reader.js" ></script>
<script>
function success(reader) { console.log('Schema loaded successfully'); };
function failure() { console.log('An error occured while trying to load the schema'); };
var batchSize = 50; // the higher the number the less requests made, but the larger the payload
new SchemaReader(connection, batchSize, success, failure);
</script>

Instatiating the reader in a visualforce page

Do the same as above but to reference the schema-reader.js file you will need to have a static resource like for instance shemaReader.resource in your salesforce org and you'll need to reference it like so:

<apex:includeScript value="{!URLFOR($Resource.schemaReader)}" /> <!-- the same as<script src="schema-reader.js" ></script>  in a normal html page-->
<script>
function success(reader) { console.log('Schema loaded successfully'); };
function failure() { console.log('An error occured while trying to load the schema'); };
var batchSize = 50; // the higher the number the less requests made, but the larger the payload
new SchemaReader(connection, batchSize, success, failure);
</script>

Instatiating the reader in node

To install the schema reader in a node project do:

$> npm install salesforce-schema-reader

And to instantiate:

var SchemaReader = require('salesforce-schema-reader');
function success() { console.log('Schema loaded successfully'); };
function failure() { console.log('An error occured while trying to load the schema'); };
var batchSize = 50; // the higher the number the less requests made, but the larger the payload
var reader = new SchemaReader(connection, batchSize, success, failure);

Reading the schema

Once the reader is instantiated - To read the schema you can use a variety of methods and techniques and you might find it beneficial to have a look at the tests to see how to use the tool. Here are a few examples:

Shallow read fields

Shallow reading fields means no relationships are followed up, which means each field in each object gets visited exactly once. And it's done like this:

reader.shallowReadFields(visitor);

Deep read fields

Deep reading fields means all relationships are followed up, which means each field in each object gets visited at least once plus as many times as there are paths to that object from other objects. And it's done like this:

reader.deepReadFields(visitor);

Shallow read child relationships

Shallow reading child relationships means no relationships are followed up, which means each child relationship definition in each object gets visited exactly once. And it's done like this:

reader.shallowReadChildRelationships(visitor);

Deep read child relationships

Deep reading child relationships means all relationships are followed up, which means each child relationships in each object gets visited at least once plus as many times as there are paths to that object from other objects. And it's done like this:

reader.deepReadChildRelationships(visitor);

Filters

Just walking all fields or child relationships isn't necessarily vary useful. Most of the time you would probably like to be able to visit specific fields. Maybe you want to find all the objects that have a reference to another object, or all the objects that have a valid path to another object, or just all the fields with a particular name.

For this you would use filters like so:

Reference to another object

function filter(field, object, path, reader) {
	return field.referenceTo === 'someObject__c' ||
	    (Array.isArray(field.referenceTo) && field.referenceTo.indexOf('someObject__c') >= 0); // a field can refer to multiple types of objects
};

reader.deepReadFields(SchemaReader.createFilterVisitor(filter, function(field, object, path, reader) {
  console.log('The object: ' + path[0].name + ' references someObject__c');
}));

All objects with a path to another object

function filter(field, object, path, reader) {
	return field.type === 'reference' && 
	  (field.referenceTo === 'someObject__c' ||
	    (Array.isArray(field.referenceTo) && field.referenceTo.indexOf('someObject__c') >= 0)); // a field can refer to multiple types of objects
};

reader.deepReadFields(SchemaReader.createFilterVisitor(filter, function(field, object, path, reader) {
  console.log('The object: ' + path[0].name + ' has the following path to object: someObject__c');
	console.log(ShemaReader.concatPath(path));
}));

All fields by name

reader.shallowReadFields(SchemaReader.newFieldNameFilter('id', function(field, object, path, reader) {
	console.log('The object: ' + object.name + ' has an id field! What a supprise!');
}));

Thanks for reading!

And let me know if you have issues and/or you want to fix them