forma-embedded-view-sdk
Version:
The Forma Embedded View SDK is a JavaScript library for creating custom extensions in Autodesk Forma (previously Spacemaker).
633 lines (632 loc) • 21.2 kB
TypeScript
import type { Child, EmbeddedJsonRepresentation, LinkedRepresentation, Metadata, Properties, Urn } from "forma-elements";
import type { IframeMessenger } from "./iframe-messenger.js";
type PartialNullish<T> = {
[P in keyof T]?: T[P] | null;
};
export declare namespace CreateElementHierarchy {
/**
* Column-major 4x4 matrix. Translation values use metres as unit.
*/
type Transform = [
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number
];
/**
* Relationship to another element that will be a child of an element.
*/
type Child = {
/**
* Either an ID to another element in the request or a full URN to an external element.
*
* External elements must be in the integrate element system and for the same authcontext.
*/
id: string;
/**
* Transform to apply to the child element.
*/
transform?: Transform | undefined;
/**
* Unique id under parent. Used to build up paths. Prefer short values for space efficiency.
*
* Either all children must have keys specified or none of them.
*
* @min 1
* @max 40
*/
key?: string | undefined;
};
/**
* Geometry of the element.
*/
namespace Geometry {
/**
* Geometry in binary glTF (GLB) format.
*
* Currently we only keep basic geometry details from the GLB, so
* the stored GLB might not look exactly as the one you wrote.
*/
type Glb = {
type: "File";
format: "glb";
/**
* Reference to a file uploaded with {@link IntegrateApi.uploadFile}.
*/
s3Id: string;
/**
* ID of the node in the GLB file to use as geometry.
*
* This is useful if the same GLB file is used for multiple elements,
* where each element should use a specific part of the GLB.
*/
nodeId?: string | undefined;
/**
* Enabling this flag makes the default rendering material double sided.
* Double sided materials makes surfaces visible on from both sides
* as opposed to the default behaviour of only being visible from the front.
* Set this property if your geometry is a surface that should be visible from every
* angle or if you have an open-ended volume.
*
* Note that enabling this comes at a cost to rendering performance.
*/
doubleSided?: boolean | undefined;
};
/**
* Geometry in a mesh (verts and faces) format. The unit is meter.
*
* The `verts` list consists of a flattened list of
* x, y and z coordinates of a vertex. The `faces` list
* consists of zero-indexed references to a vertex in the `verts`
* list and is a flattened list of three vertices forming a triangle.
* For example if there are two vertices, meaning 6 items in
* the `verts` list, vertex 0 and 1 can be referenced from `faces`.
*
* @example Example geometry value representing a cube
* ```json
* {
* "type": "Inline",
* "format": "Mesh",
* "verts": [
* // x, y, z
* 0, 0, 0, // vertex 0
* 0, 1, 0, // vertex 1
* 1, 1, 0, // vertex 2
* 1, 0, 0, // vertex 3
* 0, 0, 1, // vertex 4
* 0, 1, 1, // vertex 5
* 1, 1, 1, // vertex 6
* 1, 0, 1 // vertex 7
* ],
* "faces": [
* 0, 1, 3, // half bottom
* 2, 1, 3, // other half bottom
* 0, 3, 7, // half side 1
* 4, 3, 7, // other half side 1
* // and so on...
* ]
* }
* ```
*/
type Mesh = {
type: "Inline";
format: "Mesh";
doubleSided?: boolean | undefined;
/**
* Verts item count must be multiple of 3.
*/
verts: number[];
/**
* Only triangle faces supported.
* Item count must be multiple of 3.
*/
faces: number[];
};
/**
* Geometry in GeoJSON format (inline).
*
* Only `Polygon` and `LineString` can be specified as geometry types.
*/
type GeoJsonInline = {
type: "Inline";
format: "GeoJSON";
geoJson: {
type: "FeatureCollection";
features: unknown[];
};
nodeId?: string | undefined;
};
/**
* Geometry in GeoJSON format (uploaded file).
*
* Only `Polygon` and `LineString` can be specified as geometry types.
*/
type GeoJsonFile = {
type: "File";
format: "GeoJSON";
/**
* Reference to a file uploaded with {@link IntegrateApi.uploadFile}.
*
* The file must contain a valid GeoJSON FeatureCollection.
*/
s3Id: string;
/**
* ID of the GeoJSON feature the element with this geometry should use.
*/
nodeId: string;
};
}
/**
* Metadata of the element to be created.
*/
type Metadata = {
/**
* Pointer to the previous version of this element.
* Must be the full URN to the previous version.
*/
predecessor?: string | undefined;
/**
* Information related to the licensing governing the use and transfer of this element.
*/
licensing?: {
/**
* Whether or not data can be transferred out of Forma, for example
* by downloading a data file or sending a project to Revit.
*/
exportable: boolean | undefined;
/**
* Attribution requirements that must be followed.
* Empty if there are no requirements.
*/
attributions: {
/**
* We support two types of attribution actions, depending on what happens to the data:
* - display: A watermark (clickable text) to be shown whenever data is displayed.
* - transfer: Text to be shown to users (or put in LICENCE files or similar) whenever data is imported or exported.
*/
action: "display" | "transfer";
content: string;
url: string;
}[];
/**
* Link to the original license for the data.
*/
licenseUrl: string;
/**
* Link to the providers description on how the license should be interpreted.
* For auditing purposes.
*/
providerDescriptionUrl: string;
} | undefined;
};
/**
* Properties of the element to be created.
*
* @see https://aps.autodesk.com/en/docs/forma/v1/http-specification/integrate-api/
*/
type Properties = {
/**
* Specifies the type of element.
*
* @example
* building
*
* @example
* vegetation
*/
category?: string | undefined;
/**
* Value displayed to the user in the list of elements.
*/
name?: string | undefined;
/**
* Reference to the original model so if you receive this
* element at a later time. You can use this reference to get information
* about the model that is not stored in the element.
*/
internalRepresentationReference?: string | undefined;
/**
* The root element can be georeferenced by specifying this `geoReference`
* property.
*
* The coordinates in the geometry will be relative to this ref point.
*/
geoReference?: {
/**
* Coordinate system identifier.
*
* This must be the same coordinate system as used for the
* project where the element is stored.
*
* See {@link auto.Forma | Forma}.{@link index.EmbeddedViewSdk.project | project}.
*/
srid: number;
/**
* Reference point within the given coordinate system.
*/
refPoint: [number, number];
} | undefined;
/**
* Specify who created the element, so you can know that the
* element was created by you and that it makes sense to look for
* the `internalRepresentationReference` property.
*/
elementProvider?: string | undefined;
geometry?: Geometry.Glb | Geometry.Mesh | Geometry.GeoJsonInline | Geometry.GeoJsonFile | undefined;
[key: string]: unknown;
};
/**
* Element to create.
*/
type Element = {
id: string;
properties?: Properties | undefined;
/**
* Specify representations for the element.
*
* Representations can be given by specifying either a LinkedRepresentation,
* with a blobId from the upload response of {@link IntegrateApi.uploadFile},
* or for JSON data, an EmbeddedJsonRepresentation.
*
* There is a limit of approximately 100 KiB of JSON data to use
* EmbeddedJsonRepresentation, so if you risk exceeding this consider using
* LinkedRepresentation instead by serializing the JSON to a string.
*
* @see https://aps.autodesk.com/en/docs/forma/v1/working-with-forma/element-system/forma-element-specification/#representations
*/
representations?: Record<string, LinkedRepresentation | EmbeddedJsonRepresentation> | undefined;
/**
* List of children elements.
*/
children?: Child[] | undefined;
};
}
/**
* Hierarchy of elements to create.
*
* There must be at least one element that is the root element.
*
* The values used for IDs of elements are local to the request
* to reference between elements, and can be any string.
*
* @see https://aps.autodesk.com/en/docs/forma/v1/http-specification/integrate-api/
*/
export type CreateElementHierarchy = {
/**
* ID of the root element.
*
* @example
* root
*/
rootElement: string;
/**
* Map of elements to create.
*
* The key must be the same value as the ID of the element.
*/
elements: Record<string, CreateElementHierarchy.Element>;
};
export interface CreateElementV2 {
/**
* Desired URN (optional) for the new element.
*
* You can use {@link IntegrateApi.createUrn} to generate an URN.
*/
urn?: Urn | undefined;
metadata?: Pick<Metadata, "licensing" | "predecessor"> | undefined;
properties?: Properties | undefined;
/**
* Specify representations for the element.
*
* Representations can be given by specifying either a LinkedRepresentation,
* with a blobId from the upload response of {@link IntegrateApi.uploadFile},
* or for JSON data, an EmbeddedJsonRepresentation.
*
* There is a limit of approximately 100 KiB of JSON data to use
* EmbeddedJsonRepresentation, so if you risk exceeding this consider using
* LinkedRepresentation instead by serializing the JSON to a string.
*
* @see https://aps.autodesk.com/en/docs/forma/v1/working-with-forma/element-system/forma-element-specification/#representations
*/
representations?: Record<string, LinkedRepresentation | EmbeddedJsonRepresentation> | undefined;
children?: (Pick<Child, "urn" | "transform"> & {
/**
* Unique id under parent. Used to build up paths. Prefer short values for space efficiency.
*
* Either all children must have keys specified or none of them.
*
* @min 1
* @max 40
*/
key?: string | undefined;
})[] | undefined;
}
export interface UpdateElementV2 {
/**
* The existing element to update.
*/
urn: Urn;
/**
* Desired URN (optional) for the new element.
*
* You can use {@link IntegrateApi.createUrn} to generate an URN.
*/
nextUrn?: Urn | undefined;
metadata?: PartialNullish<Pick<Metadata, "licensing" | "predecessor">> | undefined;
properties?: PartialNullish<Properties> | undefined;
/**
* Specify representations for the element.
*
* Representations can be given by specifying either a LinkedRepresentation,
* with a blobId from the upload response of {@link IntegrateApi.uploadFile},
* or for JSON data, an EmbeddedJsonRepresentation.
*
* There is a limit of approximately 100 KiB of JSON data to use
* EmbeddedJsonRepresentation, so if you risk exceeding this consider using
* LinkedRepresentation instead by serializing the JSON to a string.
*
* @see https://aps.autodesk.com/en/docs/forma/v1/working-with-forma/element-system/forma-element-specification/#representations
*/
representations?: Record<string, LinkedRepresentation | EmbeddedJsonRepresentation | null> | undefined;
children?: (Pick<Child, "urn" | "transform"> & {
/**
* Unique id under parent. Used to build up paths. Prefer short values for space efficiency.
*
* Either all children must have keys specified or none of them.
*
* @min 1
* @max 40
*/
key?: string | undefined;
})[] | undefined;
}
/**
* See {@link IntegrateApi.batchIngestElementsV2}.
*/
export declare namespace BatchIngestElementsV2 {
/**
* Create a new element.
*
* See description of {@link IntegrateApi.createElementV2} for more information.
*/
interface CreateElement extends CreateElementV2 {
operation: "create";
}
/**
* Create a new element based on the existing element.
*
* See description of {@link IntegrateApi.updateElementV2} for more information.
*/
interface UpdateElement extends UpdateElementV2 {
operation: "update";
}
/**
* Result for a successful operation.
*/
interface ResultOk {
status: "ok";
urn: Urn;
}
/**
* Result for a failed operation.
*/
interface ResultFailed {
status: "failed";
error: {
title: string;
detail: string;
errors?: {
field: string | null;
path: (string | number)[] | null;
title: string;
detail: string;
}[] | undefined;
};
}
}
/**
* Create and upload elements to the integrate element system.
*
* @remarks
* Available via {@link auto.Forma | Forma}.{@link index.EmbeddedViewSdk.integrateElements | integrateElements}.
*/
export declare class IntegrateApi {
#private;
/** @hidden */
constructor(iframeMessenger: IframeMessenger);
/**
* Create a hierarchy of elements in the integrate element system.
*
* More information about the integrate element system can be seen
* at https://aps.autodesk.com/en/docs/forma/v1/http-specification/integrate-api/
*
* Requires edit access. See {@link EmbeddedViewSdk.getCanEdit | getCanEdit} for more info.
*
* @deprecated Prefer using {@link IntegrateApi.createElementV2} or {@link IntegrateApi.batchIngestElementsV2} instead.
*
* @returns ID, URN, and revision of the root element created.
*
* @example
* const upload = await Forma.integrateElements.uploadFile({
* data: "glb data here...",
* })
*
* const { urn } = await Forma.integrateElements.createElementHierarchy({
* data: {
* rootElement: "root",
* elements: {
* root: {
* id: "root",
* properties: {
* geometry: {
* type: "File",
* format: "glb",
* s3Id: upload.fileId,
* },
* },
* },
* },
* },
* })
*
* console.log(`Created element: ${urn}`)
*/
createElementHierarchy(request: {
/**
* Authcontext to use with the request.
*
* As of now, the currently open project id is both default
* and only allowed value.
*/
authcontext?: string | undefined;
/**
* Element hierarchy to add, consisting of a
* root element and its children.
*/
data: CreateElementHierarchy;
}): Promise<{
id: string;
urn: string;
revision: string;
}>;
/**
* Create a new element.
*
* Requires edit access. See {@link EmbeddedViewSdk.getCanEdit | getCanEdit} for more info.
*
* @example
* const upload = await Forma.integrateElements.uploadFile({
* data: "glb data here...",
* })
*
* const { urn } = await Forma.integrateElements.createElementV2({
* representations: {
* volumeMesh: {
* blobId: upload.blobId,
* },
* },
* })
*
* @returns URN of the created element.
*/
createElementV2(request: CreateElementV2): Promise<{
urn: Urn;
}>;
/**
* Create a new element based on the existing element. The element must
* belong to integrate system.
*
* The update will be merged onto the existing element. The merge happens
* for each individual property and representation, but not deeper.
* If you want to remove a field you must set it to \`null\`.
*
* Requires edit access. See {@link EmbeddedViewSdk.getCanEdit | getCanEdit} for more info.
*
* @example
* const { urn } = await Forma.integrateElements.updateElementV2({
* urn: existingUrn,
* properties: {
* foo: "bar",
* },
* })
*
* @returns URN of the created element.
*/
updateElementV2(request: UpdateElementV2): Promise<{
urn: Urn;
}>;
/**
* Create and/or update multiple elements in a batch.
*
* As part of the same batch elements can reference each other to form
* a hierarchy in a single request. You need to specify the element URN
* that should be used to store the new element for this.
*
* The response can be partial including failed items.
*
* Requires edit access. See {@link EmbeddedViewSdk.getCanEdit | getCanEdit} for more info.
*
* @example
* const upload = await Forma.integrateElements.uploadFile({
* data: "glb data here...",
* })
*
* const { items } = await Forma.integrateElements.batchIngestElementsV2({
* items: [
* {
* operation: "create",
* representations: {
* volumeMesh: {
* blobId: upload.blobId,
* },
* },
* },
* {
* operation: "update",
* urn: existingUrn,
* properties: {
* foo: "bar",
* },
* },
* ],
* })
* // Handle failures.
*/
batchIngestElementsV2(request: {
/**
* A list of operations to create or update elements. A maximum of 1000 items can be specified.
*/
items: (BatchIngestElementsV2.CreateElement | BatchIngestElementsV2.UpdateElement)[];
}): Promise<{
/**
* Each item in the response corresponds to the item with the same index
* in the request.
*/
items: (BatchIngestElementsV2.ResultOk | BatchIngestElementsV2.ResultFailed)[];
}>;
/**
* Upload a file to the integrate file storage. Files stored here are can only
* be retrieved in relation to an element. An example of this is uploading a
* geometric file - e.g. GLB or GeoJSON files.
*
* Requires edit access. See {@link EmbeddedViewSdk.getCanEdit | getCanEdit} for more info.
*
* @returns Unique identifier for the uploaded file.
*/
uploadFile(request: {
/**
* Authcontext to use with the request.
*
* As of now, the currently open project id is both default
* and only allowed value.
*/
authcontext?: string | undefined;
/**
* File data to upload.
*/
data: string | ArrayBuffer;
}): Promise<{
fileId: string;
blobId: string;
}>;
/**
* Create a new URN to be used for an element in Integrate API.
*
* @example
* const urn = createUrn("pro_japoqu38nx")
*/
createUrn(authcontext: string): Urn;
}
export {};