This topic discusses the custom data provider specification.
Registration Object
Every custom data provider has a file named index.js that exports a registration object containing provider information. The object describes how to load and use the provider. The following is the code that is automatically included in the index.js file by the Custom Data Feeds (CDF) command line tool.
const packageInfo = require('../package.json');
const csconfigInfo = require('../cdconfig.json');
const provider = {
type: csconfigInfo.type,
name: csconfigInfo.name,
version: packageInfo.version,
hosts: csconfigInfo.properties.hosts,
disableIdParam: csconfigInfo.properties.disableIdParam,
Model: require('./model')
};
module.exports = provider;
The table below describes each field in detail:
Field | Required? | Type | Description |
---|---|---|---|
type | Yes | string | Set to 'provider' |
name | Yes | string | URL-safe provider name |
version | Yes | string | Provider version number |
hosts | No | Boolean | Add a :host parameter to routes |
disable | No | Boolean | Remove the :id parameter from routes |
Model | Yes | class | require statement for Model class |
routes | No | Object[] | Array of provider-specific route objects |
Controller | No | class | Controller class that supports route handling |
The auto-generated code pulls the provider version from the package.json file and other fields from the cdconfig.json file. To modify these fields, change the corresponding values in the cdconfig.json file instead of the index.js file.
Model Class
Every custom data provider implements a Model
class, which is usually
in the model.js file. The Model
class includes a required get
method
that will contain code for fetching and tranforming remote data into GeoJSON. It may optionally include
edit
for handling feature editing or authorize()
for handling custom user authorization.
The following table describes the arguments that the get
method accepts. The callback
is
optional because the get
method may be an async
function if desired.
Name | Type | Description |
---|---|---|
req | Object | Express.js request object. |
callback | Function | Optional function that either returns a GeoJSON object or an error. Using async syntax is recommended. |
Request Object
The following table shows the properties that are availble on the request object. The example column is not exhaustive.
Property | Details | Example Usage |
---|---|---|
params | The params object will include service parameters and layer index. | const layer const sheet const host = req.params.host; |
query | The query object contains the parameters sent from the requesting client. These query parameters are crucial for creating efficient pass-through providers. Refer to the ArcGIS REST documentation for full details. | const where const result const result |
_user | The _user object is available when the service configuration option forward is true . Refer to the topic on creating custom data providers for more information. | const username = req. const server |
body | The body will be availble in POST requests and will contain the requested edits sent to the apply route. Refer to the topic on creating custom data providers with edit capability for more details. | const add const delete |
GeoJSON Metadata
Custom Data Feeds requires that the GeoJSON be decorated with a property called metadata
.
It should have an object as its value. This object contains information important for
translating the GeoJSON to its feature service equivalent. The table below describes
some of the key metadata properties:
Field | Type | Description | Example |
---|---|---|---|
default | Boolean | Specifies the default visibility of the layer. Default: true | true |
description | string | Description of the layer. | My amazing dataset |
display | string | The name of the layer's primary display field. | FL |
fields | object[] | An arrary of objects that define feature attributes. If you decide to define one attribute, then you must define all of your attributes. If this field is not set, the value is inferred from first feature in the dataset. It is highly recommended to always set this field to avoid a situation in which the fields are not set properly becuase first feature is not representative of the entire set. Every feature in the remote dataset may not have an identical attribute list. | { name |
geometry | string | Geometry type of features. If set to null , it will assume tabular data. Possible values include: Point , Multi , Line , Multi , Polygon , Multi , and null . If this field is not set, the value is inferred from first feature in the dataset. It is highly recommended to always set this field to avoid a situation in which the first feature in the set may lack geometry and leads to null geometryType to be inferred for all features. Every feature in the remote dataset may not have geometry. | Point |
has | Boolean | Indicates whether the features have elevation (z) values. Default: false | false |
id | string | The unique ID assigned to the layer. Default: 0 | 1 |
id | string | Every feature layer must have a field that uniquely identifies each feature. This property will be used as the feature's OBJECTID . To be maximally compatible with ArcGIS clients, a 64-bit integer is the safest value to use. However, some ArcGIS clients can support other types such as 64-bit strings. Become familiar with the clients that will be consuming your service to pick the best data type for your implementation. Click here for more information | id |
input | number | WKID for the remote data source coordinate system. Unless specified in the metadata, custom data feeds defaults to 4326 (WGS84). Specifying the input ensures accurate reprojection. | 3857 |
labeling | object[] | Array of objects that specifies rules for fomatting feature labels. | {"symbol" |
max | number | Maximum number of features the provider can return at once. This value should be set equal to the number of records that can be returned from the remote data source. Default: 2000 | 2000 |
max | number | Defines the maximum scale (most zoomed in) at which the layer is visible in the view. Default: 0 | 99000 |
min | number | Defines the minimum scale (most zoomed out) at which the layer is visible in the view. Default: 0 | 1000 |
name | string | Each feature layer must have a name that differentiates it from all other layers. This is the name of this particular layer. | Test Layer |
renderer | object | Customize how features are visually displayed. | { "type" |
supported | string | Override the default PBF query format. | JSO |
supports | Boolean | Indicates whether the query response supports pagination. This field lets ArcGIS clients know if they can expect to fetch multiple pages of data. Default: true | true |
templates | object[] | Defines which attributes are present in the editing template and the default values for attributes. If no templates are provided in the metadata, then a default template is created. | [ {"name" |
If your data does not contain a field that can be used as the OBJECTID
, you can leave id
undefined.
In such cases Custom Data Feeds will create an OBJECTID
for each feature by default. However, this is
less than ideal as it impacts performance and in very rare cases may lead to OBJECTID
collisions. The
best practice is to have a field on the raw data that meets the requirements of id
. See Setting
the idField Property for more details.
Routes and Controllers
Routes
To use provider-specific routes, ensure that the routes
field in the
index.js file points to a file that exports an array of route
definition objects. The following table describes the fields that each
route definition object must contain.
Field | Type | Description |
---|---|---|
path | string | Express.js-style route that includes optional parameters |
methods | string[] | HTTP methods that this route can handle |
handler | string | Name of the controller function that should handle requests at this route |
Controllers
Set the handler
field of each route definition object to the function
name that handles requests for that route. You can define these
functions in a Controller
class. The Controller
field in the
index.js file must reference the Controller
class. Below is an
example of how to implement a Controller
class.
function Controller (model) {
this.model = model;
}
Controller.prototype.test = function (req, res) {
res.status(200).json({version: '1.0.0'});
};