Skip to content
Agile Defense

Curriculum / Application Developer & Ontology Engineering

INTERMEDIATEUnit 3unit-03

Reusable Functions: TypeScript v2 functions on objects

not started~300 min
Author and publish a TypeScript-v2 query function (shipmentRiskRollup) that reads objects/links and returns a structured risk summary.

Introduction

Scenario: The supply-chain Command Center app needs reusable risk logic that every page can call: given a disruption, roll up its exposed Shipments and orders into one structured risk summary. You author that logic once as a published TypeScript v2 query function so Workshop, Quiver, and the API gateway can all consume the same numbers.

Unit 3 moves you from shaping the Ontology to writing reusable logic on top of it. Foundry Functions provide first-class, version-controlled support for authoring logic against the Ontology — reading object properties, traversing link types, and (later) making Ontology edits. Functions come in three implementations: TypeScript v1, TypeScript v2, and Python. You will use TypeScript v2, which runs on a Node.js runtime and adds first-class OSDK support over v1, making it the modern default for Functions on Objects. The deliverable is a query function named shipmentRiskRollup that takes a disruptionId, reads the related DisruptionEvent and its exposed Shipment objects, and returns a structured risk summary the whole app can reuse.

The distinction that drives this unit is query versus edit. A query function is the read-only subset of functions exposed through the API gateway: it is annotated as a query, its apiName is lowerCamelCase, and it cannot have side effects such as modifying the Ontology — editing the Ontology is the job of a function-backed Action (Unit 5). Because query functions are read-only and enumerable, they are exactly what the instance checks can confirm: once you publish, shipmentRiskRollup appears in List Query Types, and Execute Query runs it and returns its structured output. You author and test the logic in the Functions helper Live Preview, then publish by tagging a version (semantic versioning, committed in the repository).

Authoring a TypeScript v2 function follows strict repository conventions that the platform enforces but that no read API can see from the outside. You scaffold a repository from the 'TypeScript v2 functions template', place your function in typescript-functions/src/functions, name the file to match the function name, and make the function the default export. To read the Ontology you import the relevant object types from the ontology-api package — for a private ontology, from @foundry/ontology-api/<ontology-api-name> — then read properties and traverse links to Shipments and orders. The two scaffolding-and-authoring steps are therefore self-attested: they are verified in Live Preview, not by an external endpoint. Only after you publish do the read-side endpoints (List Query Types, Execute Query) have anything to bind to.

Capability focus: TypeScript-v2 functions repository; reading objects + traversing links; publishing query functions; Execute Query. · Artifact: A published TypeScript-v2 query function (shipmentRiskRollup) returning a structured risk summary.

Key concepts

  • Foundry Functions: Version-controlled, reusable logic authored against the Ontology, with three implementations — TypeScript v1, TypeScript v2, and Python. Functions provide first-class support for reading object properties, traversing link types, and (via the Ontology edits API) making Ontology edits. Published functions are consumable across the platform: function-backed Workshop variables, function-backed Actions, Quiver, Automate, and the API gateway via query functions.
  • TypeScript v2 functions: Created via + New > Repository using the 'TypeScript v2 functions template'. The function lives in typescript-functions/src/functions, the file name must match the function name, and the function must be the default export. TS v2 adds a Node.js runtime and first-class OSDK support over v1, and is one of the surfaces where Ontology interfaces are fully supported (alongside Ontology Manager and the Ontology SDK).
  • Functions on Objects: A function reads object properties and traverses links by importing the object type from the ontology-api package (for a private ontology, @foundry/ontology-api/<ontology-api-name>). This is how shipmentRiskRollup reaches a DisruptionEvent, walks its links to the exposed Shipments, and aggregates their orders. Logic is tested interactively in the Functions helper Live Preview before publishing.
  • Query functions (read-only): The read-only subset of functions exposed through the API gateway, annotated as a query with a lowerCamelCase apiName. A query function cannot have side effects such as modifying the Ontology — for edits you use a function-backed Action instead. Because they are read-only and enumerable, query functions appear in List Query Types and can be invoked through Execute Query; API-named queries always resolve to the latest tagged version.
  • Query vs edit functions: A query reads and returns a value; an Ontology-edit function mutates objects and is consumed through a function-backed Action (Unit 5). This matters for verification: an edit function will NOT appear in List Query Types and cannot be invoked through Execute Query — it is confirmed indirectly via the Action it backs and the object-state that Action produces. Only a read-only query function is directly enumerable and executable.
  • Publishing and Execute Query: Functions are published by tagging a version (semantic versioning) and committing in the repository; once published they are managed in Ontology Manager's Functions tab, searchable by name, description, apiName, and RID. Execute Query takes the query apiName, an optional version, and parameters, runs the published function (defaulting to the default branch), and returns its structured result — the machine-checkable proof that shipmentRiskRollup returns the expected keys.

Companion video

TypeScript v2 functions walkthrough (placeholder) · open on YouTube

Hands-on activity

each step validates · the unit completes when all steps pass
  1. 1

    Scaffold a TypeScript v2 functions repository

    Scaffold the function's home: create a new repository via + New > Repository using the 'TypeScript v2 functions template'. By convention the function lives in typescript-functions/src/functions, the file name must match the function name (shipmentRiskRollup), and the function must be the default export — these conventions are enforced by the build, not by any external API, so this step is self-attested. Choose TypeScript v2 specifically because it runs on a Node.js runtime with first-class OSDK support and is the modern default for Functions on Objects. There is no read endpoint that can introspect repository contents or the template you started from, so verification here is that the repository exists and builds in the authoring environment, confirmed in the next steps via Live Preview and, after publishing, via the read-side endpoints.

    not startedself-attested

    Self-attested: a TS-v2 functions repository is created (repo contents are not API-introspectable).

  2. 2

    Read objects and traverse links in the function

    Author the read logic: import the object types you need from the ontology-api package — for a private ontology this is @foundry/ontology-api/<ontology-api-name> — then have shipmentRiskRollup accept a disruptionId, load the matching DisruptionEvent, traverse its link types to the exposed Shipment objects, and aggregate their orders into a single risk summary. Return a structured object whose keys include riskScore, exposedOrders, and summary so downstream consumers (and the Execute Query check) get a stable shape. Test the logic interactively in the Functions helper Live Preview against a seeded case rather than guessing — Live Preview is the only way to confirm property reads and link traversal at this stage, because a function's internal logic is not API-introspectable from the outside. This step is therefore self-attested: there is no read API that can confirm which properties you read or which links you walked.

    not startedself-attested

    Self-attested: the function reads object properties/links (verified in Live Preview; internal logic is not API-introspectable).

  3. 3

    Publish the query function (tag a version)

    Publish shipmentRiskRollup by tagging a version (semantic versioning) and committing in the repository; published functions are then managed in Ontology Manager's Functions tab and registered as a query type. Because a query function is the read-only, API-gateway-exposed subset of functions, publishing makes it enumerable: the check calls List Query Types and confirms that the apiName shipmentRiskRollup appears in the returned list of published query types. This is exactly why the function must be a read-only query and not an edit function — an Ontology-edit function would mutate objects and would NOT show up in List Query Types at all (it is reachable only through the Action it backs). If the apiName is missing from the list, the function was not published, was committed without a tagged version, or was authored as something other than a query; confirm the lowerCamelCase apiName matches shipmentRiskRollup exactly.

    not startedinstance check

    Confirms shipmentRiskRollup is published and enumerable after tagging a version.

  4. 4

    Execute the published function on a seeded case

    Prove the function actually returns useful structure by running it on a seeded case. The check invokes Execute Query with the query apiName shipmentRiskRollup and the parameter disruptionId set to the seeded value DISR-CAP-1 (API-named queries resolve to the latest tagged version on the default branch) and confirms the result is a non-empty object containing the required keys riskScore, exposedOrders, and summary. Execute Query is the read-side execute endpoint and only works because shipmentRiskRollup is a read-only query — an edit function cannot be invoked this way, since it has side effects and is verified instead through its Action and the resulting object-state. If the call errors or returns an empty/partial result, re-check in Live Preview that the seeded DisruptionEvent links to Shipments and that your return object names all three keys precisely as expected.

    not startedinstance check

    Executes shipmentRiskRollup and confirms a non-empty result with the required keys.