PSScript Docs / Reference

Entities & queries

Entities are PSScript's first-class data records. PSEntity builds and mutates them; PSEntityQuery reads them back with a fluent, chainable builder.

Creating entities

Construct an entity from its fully-qualified class name. The entity starts empty; you populate it with the methods below and then persist it.

var order = PSEntity("com.domain.commerce.Order");
order.identifier("ORD-2024-001");
PSEntity(typeName)

Create a new, unsaved entity of the given class.

entity.identifier(idn)

Set a stable business identifier — the key you later pass to data$.load.

Load-or-create A very common pattern loads an entity by identifier and constructs a fresh one only when it does not yet exist, so a script is safe to re-run:
var idn = "PROCESS_CATEGORY_BUSINESS";
var model = data$.load(idn);
if (model == null) {
    model = PSEntity("com.paradicshift.platform.automation.process.Category");
    model.identifier(idn);
}
model.text("name", "en", "Business");
data$.persist(model);

Fields & values

entity.val(field, value)

Set a scalar field (string, number, bool, …). value is an alias of val.

entity.val(field)

Read a field back; returns null if unset.

order.val("total", 149.99);
order.val("currency", "USD");
order.val("hidden", false);

context$.log("total = {}", order.val("total"));   // 149.99
entity.removeVal(field)

Removes a field from the entity.

entity.map(name, mapValue)

Store a named map on the entity. The value must be a PSScript map and is persisted in ArcadeDB as a queryable MAP, separately from scalar val fields.

entity.map(name)

Read a named entity map; returns the complete map, or null when the name is unset. Members are read with normal map indexing.

var shipping = {};
shipping["country"] = "TR";
shipping["priority"] = true;
order.map("shipping", shipping);

var savedShipping = order.map("shipping");
context$.log("country = {}", savedShipping["country"]);
entity.secret(name, value)

Store a secret string. Secret values are encrypted at rest and must be used for credentials, tokens and other sensitive scalar data instead of val or map.

entity.secret(name)

Read a secret string inside the running script; returns null when the secret is unset.

Secret values are never exported as plaintext to entity JSON, logs or AI input. Their names remain visible, but their values are rendered as ***.

Multilingual text

Text fields are stored per locale, so a record can carry its name or description in many languages at once.

entity.text(field, locale, text)

Set the localized text of a field. The field name and locale are auto-detected by order, so ("name", "en", …) and ("en", "name", …) both work.

entity.text(field, locale)

Read a localized value back. Reading a locale that was never set is a runtime error, so guard or set it first.

component.text("name", "en", "Execute access");
component.text("name", "fa", "دسترسی اجرا");

GIS geometry

Entities can hold geospatial fields expressed as WKT strings. The geometry is parsed and validated when you set it.

entity.gis(field, wkt)

Attach a geometry to a field from a WKT string. gisWkt is an alias.

Supported WKT geometry types include points, lines, polygons and their multi-variants:

e.gis("location", "POINT(%f %f)".formatted(lon, lat));
e.gis("area_1",   "POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))"
                  .formatted(lon, lat, lon2, lat, lon2, lat2, lon, lat2, lon, lat));
e.gis("path",     "LINESTRING(%f %f, %f %f, %f %f)"
                  .formatted(lon, lat, lon2, lat2, lon3, lat3));
entity.gisWkt(field)

Reads a geometry field back as a WKT string.

entity.gisGeoData(field)

Reads a geometry field back as a GeoData object, ready for the gis$ helpers.

Access control

entity.grantAll()

Grant open access to the entity — useful for shared platform data such as categories and model properties.

entity.openAccess(accessType)

Open a specific kind of access (for example "list") without granting everything.

Persisting & linking

Saving, deleting and relating entities is done through data$ (see System objects). An entity also exposes a convenience delete.

data$.persist(entity)  ·  data$.link(child, parent, relation)  ·  entity.delete()
data$.persist(subCat);
data$.link(subCat, model, "IN_PARENT_CATEGORY");

PSEntityQuery

Build a read query against a base class, chaining select clauses (what to return), filter clauses (which rows) and traversal clauses (follow relations). Pass the finished query to data$.query().

var q = PSEntityQuery("com.domain.commerce.Order")
            .selectId()
            .selectVal("total")
            .selectMapValue("shipping", "country")
            .filterVal("currency", "equals", "USD")
            .filterVal("total", "greater_than", 100)
            .filterMap("shipping", "priority", "equals", true);

var rows = data$.query(q);

Select clauses

.selectId()include the internal id
.selectIdentifier()include the business identifier
.selectVal(field)include a scalar field
.selectMap(name)include an entire named entity map in each result row
.selectMapValue(name, key)include one nested key from a named entity map
.selectText(field, locale)include localized text
.selectCount(field)aggregate count
.selectSumVal(field, alias)aggregate sum of a field

Filter clauses

.filterId(value)match on internal id
.filterIdentifier(value, op)match on business identifier
.filterVal(field, op, value)match on a scalar field
.filterMap(name, key, op, value)match a nested key inside a named entity map without converting the map to text
.filterText(field, locale, op, value)match on localized text
.filter(name, op, value)generic: routes to id / identifier / val automatically
.filterGIS(field, predicate, wkt)spatial match against a WKT geometry (filterGis alias)

Traversal

.forward(relation)follow a relation in its forward direction
.backward(relation)follow a relation in reverse

Filter operators

The comparison operator in a filter is given as a string:

Operator stringMeaning
"equals"equal to
"not_equals"not equal to
"greater_than"greater than
"greater_than_or_equals"greater than or equal
"less_than"less than
"less_than_or_equals"less than or equal
Filter values A filter value must be a scalar (string, number, bool, null) or a map — entities, queries and system objects cannot be used as filter values.

Published queries

A query designed and published in the Designer is run by uid instead of being built in code. Pass its parameters as a map, or add them one at a time; the result is read with data$.query exactly like a PSEntityQuery.

PSEntityQueryModel.(publishedUid, params) query.param(name, value)

Sets one parameter and returns the query, so calls can be chained.

query.addParam(name, value)

Adds a parameter without replacing the ones already set.

query.params(map)

Replaces every parameter with the given map.

var params = {};
params["email"]   = "[email protected]";
params["_locale"] = context$.getLocale();
params["_limit"]  = 100;

var query = PSEntityQueryModel("QUERY_BY_EMAIL", params);
query = query.param("active", true);
var rows = data$.query(query);
Published queries Three parameter names are reserved by the platform: _locale selects the language used for text columns, while _limit and _offset page the result.

Feeding an iteration

Converts query result rows into the map shape workflow$.iterate expects, taking the item id from one column and its label from another.

data$.toIterationMap(rows, idField, labelField)
var rows  = data$.query(PSEntityQueryModel("ACTIVE_CASES", {}));
var items = data$.toIterationMap(rows, "id", "name");
var current = workflow$.iterate(items);

context$.log("processing {}", param$["iterationItem"]);