In order to be published to the registry, a TypeScript function must have explicit type annotations on all input parameters and specify an explicit return type. Below is the full list of currently supported function registry types and their corresponding language types.
Function registry type | TypeScript v1 type | TypeScript v2 type | Python type | |
---|---|---|---|---|
Attachment | Attachment | Attachment | Attachment | Example |
Boolean | boolean | boolean | bool | Example |
Binary | Not supported | Not supported | bytes | Example |
Byte | Not supported | Not supported | int* | Example |
Date | LocalDate | DateISOString | datetime.date | Example |
Decimal | Not supported | Not supported | decimal.Decimal | Example |
Double | Double | Double | float* | Example |
Float | Float | Float | float | Example |
Group | Group | Not supported | Not supported | Example |
Integer | Integer | Integer | int | Example |
List | T[] or Array<T> | T[] or Array<T> | list[T] | Example |
Long | Long | Long | int* | Example |
Map | FunctionsMap<K, V> | Record<K, V> | dict[K, V] | Example |
Media reference | MediaItem | Not supported | Not supported | Example |
Notification | Notification | Not supported | Not supported | Example |
Object | MyObjectType | Osdk.Instance<MyObjectType> | MyObjectType | Example |
Object set | ObjectSet<MyObjectType> | ObjectSet<MyObjectType> | MyObjectTypeObjectSet | Example |
Ontology edit | void | Edits | OntologyEdit | Example |
Optional | T | undefined | T | undefined | typing.Optional or T | None | Example |
Principal | Principal | Not supported | Not supported | Example |
Range | IRange<T> | Range<T> | Range[T] | Example |
Set | Set<T> | Not supported | set[T] | Example |
Short | Not supported | Not supported | int* | Example |
String | string | string | str | Example |
Struct/custom type | interface | interface | dataclasses.dataclass | Example |
Timestamp | Timestamp | TimestampISOString | datetime.datetime | Example |
Two-dimensional aggregation | TwoDimensionalAggregation<K, V> | TwoDimensionalAggregation<K, V> | TwoDimensionalAggregation[K, V] | Example |
Three-dimensional aggregation | ThreeDimensionalAggregation<K, S, V> | ThreeDimensionalAggregation<K, S, V> | ThreeDimensionalAggregation[K, S, V] | Example |
User | User | Not supported | Not supported | Example |
Although both Integer
and Long
correspond to the Python type int
, any fields marked as int
directly in your function signature will be registered with type Integer
. Therefore, we instead recommend using either the Integer
or Long
types from the API to register numerical data types. Similar guidelines apply to Float
and Double
; if the Python type float
is directly in your function signature, it will be registered as Float
by default.
Scalar types represent a single value and are commonly used to hold textual, numeric, or temporal data.
In JavaScript and TypeScript, there is one number
type that is commonly used to represent both integer and floating-point values. In order to provide further type validation and structure, we only support the numeric aliases exported from the @foundry/functions-api
package for TypeScript v1 functions and the @osdk/functions
package for TypeScript v2 functions. Similarly, when working with numeric types in Python functions we recommend using the type aliases exported from the functions.api
module.
Copied!1 2 3 4 5 6 7 8
import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public isEven(num: Integer): boolean { return num % 2 === 0; } }
Copied!1 2 3 4 5 6 7 8
import { Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public greet(name: string): string { return `Hello, ${name}!`; } }
Represents integer values from -32,768 to 32,767.
In Python functions, the Short
type is an alias for the built-in int
type.
Copied!1 2 3 4 5
from functions.api import function, Short @function def increment(num: Short) -> Short: return num + 1
Represents integer values from (-231) to (231 - 1).
Integer
type is an alias for the built-in number
type.Integer
type is an alias for the built-in int
type.Copied!1 2 3 4 5 6 7 8
import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public sum(a: Integer, b: Integer): Integer { return a + b; } }
Represents integer values from -(253 - 1) to (253 - 1). These bounds are equivalent to Number.MIN_SAFE_INTEGER
and Number.MAX_SAFE_INTEGER
in JavaScript to prevent precision loss when functions are called from browser contexts.
Long
type is an alias for the built-in number
type. In TypeScript v2 functions, the Long
type is an alias for the built-in string
type.Long
type is an alias for the built-in int
type.Copied!1 2 3 4 5 6 7 8
import { Function, Long } from "@foundry/functions-api"; export class MyFunctions { @Function() public subtract(a: Long, b: Long): string { return (BigInt(a) - BigInt(b)).toString(); } }
Represents a 32-bit floating-point number.
Float
type is an alias for the built-in number
type.Float
type is an alias for the built-in float
type.Copied!1 2 3 4 5 6 7 8
import { Float, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public multiply(a: Float, b: Float): Float { return a * b; } }
Represents a 64-bit floating-point number.
Double
type is an alias for the built-in number
type.Double
type is an alias for the built-in float
type.Copied!1 2 3 4 5 6 7 8
import { Double, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public divide(a: Double, b: Double): Double { return a / b; } }
Copied!1 2 3 4 5 6
from decimal import Decimal from functions.api import function @function def return_pi() -> Decimal: return Decimal('3.1415926535')
Represents a calendar date.
Copied!1 2 3 4 5 6 7 8
import { Function, LocalDate } from "@foundry/functions-api"; export class MyFunctions { @Function() public returnDate(): LocalDate { return LocalDate.fromISOString("1999-10-17"); } }
Represents an instant in time.
Copied!1 2 3 4 5 6 7 8
import { Function, Timestamp } from "@foundry/functions-api"; export class MyFunctions { @Function() public getCurrentTimestamp(): Timestamp { return Timestamp.now(); } }
In Python functions, the Binary
type is an alias for the built-in bytes
type.
Copied!1 2 3 4 5
from functions.api import function @function def encode_utf8(param: str) -> bytes: return param.encode('utf-8')
In Python functions, the Byte
type is an alias for the built-in int
type.
Copied!1 2 3 4 5 6 7
from functions.api import function, Byte @function def get_first_byte(param: str) -> Byte: if len(param) == 0: raise Exception("String length cannot be zero.") return param.encode('utf-8')[0]
Collection types are parameterized by other types. For example, Array[String] is a list of strings and Map[String, Integer] is a dictionary with string keys and integer values. The parameterized types must be specified, and the type must be another supported type. Map keys can only be scalar types or an Ontology object type.
Copied!1 2 3 4 5 6 7 8
import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public filterForEvenIntegers(nums: Integer[]): Integer[] { return nums.filter(num => num % 2 === 0); } }
Maps are commonly used to key by a scalar type and access an associated value that can be of any other function registry type.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13
import { Function, FunctionsMap } from "@foundry/functions-api"; export class MyFunctions { @Function() public getMap(): FunctionsMap<string, string> { const myMap = new FunctionsMap<string, string>(); myMap.set("Name", "Phil"); myMap.set("Favorite Color", "Blue"); return myMap; } }
Additionally, maps support Ontology objects as keys.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import { Function, FunctionsMap } from "@foundry/functions-api"; import { Airplane } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getObjectMap(aircraft: Airplane[]): FunctionsMap<Airplane, Integer | undefined> { const myMap = new FunctionsMap<Airplane, Integer | undefined>(); aircraft.forEach(obj => { myMap.set(obj, obj.capacity); }); return myMap; } }
Copied!1 2 3 4 5 6 7 8
import { Function, Integer } from "@foundry/functions-api"; export class MyFunctions { @Function() public getSizeOfSet(mySet: Set<Integer>): Integer { return mySet.size; } }
varName?: T
or varName: T | undefined
. For example, a function that has an optional integer parameter named value
could be declared as either value?: Integer
or value: Integer | undefined
. TypeScript functions can also declare an optional return type by specifying a type of T | undefined
. For example, a function that may return either an Integer
or no value would have a return type of Integer | undefined
.typing.Optional[T]
or T | None
. The T | None
syntax requires Python 3.10 or greater.T
must be specified, and it must be another supported type.Copied!1 2 3 4 5 6 7 8 9 10 11
import { Function } from "@foundry/functions-api"; export class MyFunction { @Function() public greet(name?: string): string | undefined { if (name === undefined) { return undefined; } return `Hello, ${name}!`; } }
Functions also support default values in the function signature.
Copied!1 2 3 4 5 6 7 8 9
import { Double, Function } from "@foundry/functions-api"; import { Customer } from "@foundry/ontology-api"; export class MyFunctions { @Function() public computeRiskFactor(customer: Customer, weight: Double = 0.75): Double { // ... } }
Custom types are composed of other supported types (including other custom types) and can be used in function signatures.
In TypeScript functions, custom types are user-defined TypeScript interfaces using the interface
keyword.
?
optional token or a union with undefined
.In Python functions, custom types are user-defined Python classes.
__init__
method must accept only named arguments with the same names and type annotations as the fields.dataclasses.dataclass
↗ decorator can be used to automatically generate an __init__
method that conforms with these requirements.Copied!1 2 3 4 5 6 7 8 9 10 11 12
import { Function, Integer } from "@foundry/functions-api"; import { Passenger } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getPassengerInfo(passenger: Passenger): PassengerInfo { return { name: passenger.name, age: passenger.age, }; } }
Aggregation types can be returned from functions for use in other parts of the platform, such as Charts in Workshop.
There are two supported aggregation types:
Aggregations can be keyed by several types:
true
or false
.Copied!1 2 3 4 5 6 7 8 9 10 11
import { Function, Integer, IRange } from "@foundry/functions-api"; export class MyFunctions { @Function() public getRange(min: Integer, max: Integer): IRange<Integer> { return { min, max, }; } }
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13
import { Double, Function, TwoDimensionalAggregation } from "@foundry/functions-api"; export class MyFunctions { @Function() public myTwoDimensionalAggregation(): TwoDimensionalAggregation<string, Double> { return { buckets: [ { key: "bucket1", value: 5.0 }, { key: "bucket2", value: 6.0 }, ], }; } }
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
import { Double, Function, ThreeDimensionalAggregation } from "@foundry/functions-api"; export class MyFunctions { @Function() public myThreeDimensionalAggregation(): ThreeDimensionalAggregation<string, string, Double> { return { buckets: [ { key: "group-by-1", groups: [ { key: "partition-by-1", value: 5.0 }, { key: "partition-by-2", value: 6.0 }, ], }, { key: "group-by-2", groups: [ { key: "partition-by-1", value: 7.0 }, { key: "partition-by-2", value: 8.0 }, ], }, ] }; } }
Object types must be imported into your repository to use them in function signatures. Learn more about Ontology imports.
Object types from your ontology can be used as both inputs and outputs in your function signature. To either accept or return a single instance of an object type, import the object type from your Ontology SDK and use that type to annotate your function.
Copied!1 2 3 4 5 6 7 8 9
import { Function, Integer } from "@foundry/functions-api"; import { Airplane } from "@foundry/ontology-api"; export class MyFunctions { @Function() public getCapacity(airplane: Airplane): Integer { return airplane.capacity; } }
There are two ways to pass a collection of objects into and out of a function: concrete collections of objects (such as arrays), or object sets.
Passing an array of objects to a function enables executing logic over a concrete list of objects at the expense of loading the objects into the function execution environment up front. An object set, however, allows you to perform filtering, search-around, and aggregation operations and only load the final result when you request it.
We recommend using an object set instead of an array because an object set often achieves better performance and allows more than 10,000 objects to be passed into the function.
The below example shows how to filter an object set without loading the objects into memory, allowing you to return the filtered object set to a different part of the application.
Copied!1 2 3 4 5 6 7 8 9
import { Function } from "@foundry/functions-api"; import { Airplane, ObjectSet } from "@foundry/ontology-api"; export class MyFunctions { @Function() public filterAircraft(aircraft: ObjectSet<Airplane>): ObjectSet<Airplane> { return aircraft.filter(a => a.capacity.range().gt(200)); } }
In addition to writing functions that read data from the Ontology, you can also write functions that create objects and edit the properties and links between objects. For more details about how edit functions work, refer to the overview page.
To be registered as edit functions, TypeScript v1 functions require a void
return type in the signature. TypeScript v2 and Python functions, however, require explicitly returning a list of Ontology edits.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import { Edits, OntologyEditFunction } from "@foundry/functions-api"; import { Employee, LaptopRequest, Objects } from "@foundry/ontology-api"; export class MyFunctions { @Edits(Employee, LaptopRequest) @OntologyEditFunction() public assignEmployee(newEmployee: Employee, leadEmployee: Employee): void { const newLaptopRequest = Objects.create().laptopRequest(Date.now().toString()); newLaptopRequest.employeeName = newEmployee.name; newEmployee.lead.set(leadEmployee); } }
Copied!1 2 3 4 5 6 7 8
import { Attachment, Function } from "@foundry/functions-api"; export class MyFunctions { @Function() public loadAttachmentContents(attachment: Attachment): Promise<string> { return attachment.readAsync().then(blob => blob.text()); } }
Notification types can be returned from a function to flexibly configure notifications that should be sent in the platform. For example, you can author a function that takes in parameters such as a User
and an object type and returns a Notification with a configured message.
Notification
consists of two fields: a ShortNotification
and EmailNotificationContent
.ShortNotification
represents a summarized version of the notification, which will be shown within the Foundry platform. It includes a short heading
, content
, and a collection of Link
s.EmailNotificationContent
represents a rich version of the notification which can be sent externally via email. It includes a subject
, a body
consisting of headless HTML, and a collection of Link
s.Link
has a user-facing label
and a linkTarget
. The LinkTarget
can be a URL, an OntologyObject
, or a rid
of any resource within Foundry.For an example of how to use the Notifications API, review our guide.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
import { EmailNotificationContent, Function, Notification, ShortNotification, } from "@foundry/functions-api"; export class MyFunctions { @Function() public buildNotification(): Notification { return Notification.builder() .shortNotification(ShortNotification.builder() .heading("Issue reminder") .content("Investigate this issue.") .build()) .emailNotificationContent(EmailNotificationContent.builder() .subject("New issue") .body("hello") .build()) .build(); } }
Functions can accept and return media items. For more information, review the guide on media.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import { Function, MediaItem } from "@foundry/functions-api"; export class MyFunctions { @Function() public transcribeAudioFile(file: MediaItem): Promise<string | undefined> { if (MediaItem.isAudio(file.mediaReference)) { return await file.mediaReference.transcribeAsync({ language: TranscriptionLanguage.ENGLISH, performanceMode: TranscriptionPerformanceMode.MORE_ECONOMICAL, outputFormat: {type: "plainTextNoSegmentData", addTimestamps: true} }); } return undefined; } }
A Principal represents either a Foundry user account or group. These types can be passed into a function to allow accessing information associated with a user or group, such as a group's name or a user's first and last name or email address. All Principal types are exported from the @foundry/functions-api
package.
User
always has a username, and may have a firstName
, lastName
, or email
. It also includes all fields associated with a Principal
.Group
has a name. It also includes all fields associated with a Principal
.Principal
can be either a User
or a Group
. You can inspect the type
field to determine whether a given Principal
is a User
or a Group
. In addition to User
and Group
-specific fields, a Principal
has an id
, realm
, and dictionary of attributes
.Copied!1 2 3 4 5 6 7 8
import { Function, User } from "@foundry/functions-api"; export class MyFunctions { @Function() public getUserEmail(user: User): string { return user.email; } }
Copied!1 2 3 4 5 6 7 8
import { Function, Group } from "@foundry/functions-api"; export class MyFunctions { @Function() public getGroupName(group: Group): string { return group.name; } }
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import { Function, Principal } from "@foundry/functions-api"; export class MyFunctions { @Function() public getPrincipalType(principal: Principal): string { switch (principal.type) { case "user": return "User"; case "group": return "Group"; default: return "Unknown"; } } }