@figmarine/rest
Version:
TypeScript client for the Figma REST API with built-in cache and auto-retry. Always up-to-date.
1,259 lines (1,252 loc) • 55.7 kB
JavaScript
// src/__generated__/figmaRestApi.ts
import axios from "axios";
var BlendMode = /* @__PURE__ */ ((BlendMode2) => {
BlendMode2["PASS_THROUGH"] = "PASS_THROUGH";
BlendMode2["NORMAL"] = "NORMAL";
BlendMode2["DARKEN"] = "DARKEN";
BlendMode2["MULTIPLY"] = "MULTIPLY";
BlendMode2["LINEAR_BURN"] = "LINEAR_BURN";
BlendMode2["COLOR_BURN"] = "COLOR_BURN";
BlendMode2["LIGHTEN"] = "LIGHTEN";
BlendMode2["SCREEN"] = "SCREEN";
BlendMode2["LINEAR_DODGE"] = "LINEAR_DODGE";
BlendMode2["COLOR_DODGE"] = "COLOR_DODGE";
BlendMode2["OVERLAY"] = "OVERLAY";
BlendMode2["SOFT_LIGHT"] = "SOFT_LIGHT";
BlendMode2["HARD_LIGHT"] = "HARD_LIGHT";
BlendMode2["DIFFERENCE"] = "DIFFERENCE";
BlendMode2["EXCLUSION"] = "EXCLUSION";
BlendMode2["HUE"] = "HUE";
BlendMode2["SATURATION"] = "SATURATION";
BlendMode2["COLOR"] = "COLOR";
BlendMode2["LUMINOSITY"] = "LUMINOSITY";
return BlendMode2;
})(BlendMode || {});
var EasingType = /* @__PURE__ */ ((EasingType2) => {
EasingType2["EASE_IN"] = "EASE_IN";
EasingType2["EASE_OUT"] = "EASE_OUT";
EasingType2["EASE_IN_AND_OUT"] = "EASE_IN_AND_OUT";
EasingType2["LINEAR"] = "LINEAR";
EasingType2["EASE_IN_BACK"] = "EASE_IN_BACK";
EasingType2["EASE_OUT_BACK"] = "EASE_OUT_BACK";
EasingType2["EASE_IN_AND_OUT_BACK"] = "EASE_IN_AND_OUT_BACK";
EasingType2["CUSTOM_CUBIC_BEZIER"] = "CUSTOM_CUBIC_BEZIER";
EasingType2["GENTLE"] = "GENTLE";
EasingType2["QUICK"] = "QUICK";
EasingType2["BOUNCY"] = "BOUNCY";
EasingType2["SLOW"] = "SLOW";
EasingType2["CUSTOM_SPRING"] = "CUSTOM_SPRING";
return EasingType2;
})(EasingType || {});
var ComponentPropertyType = /* @__PURE__ */ ((ComponentPropertyType2) => {
ComponentPropertyType2["BOOLEAN"] = "BOOLEAN";
ComponentPropertyType2["INSTANCE_SWAP"] = "INSTANCE_SWAP";
ComponentPropertyType2["TEXT"] = "TEXT";
ComponentPropertyType2["VARIANT"] = "VARIANT";
return ComponentPropertyType2;
})(ComponentPropertyType || {});
var ShapeType = /* @__PURE__ */ ((ShapeType2) => {
ShapeType2["SQUARE"] = "SQUARE";
ShapeType2["ELLIPSE"] = "ELLIPSE";
ShapeType2["ROUNDED_RECTANGLE"] = "ROUNDED_RECTANGLE";
ShapeType2["DIAMOND"] = "DIAMOND";
ShapeType2["TRIANGLE_UP"] = "TRIANGLE_UP";
ShapeType2["TRIANGLE_DOWN"] = "TRIANGLE_DOWN";
ShapeType2["PARALLELOGRAM_RIGHT"] = "PARALLELOGRAM_RIGHT";
ShapeType2["PARALLELOGRAM_LEFT"] = "PARALLELOGRAM_LEFT";
ShapeType2["ENG_DATABASE"] = "ENG_DATABASE";
ShapeType2["ENG_QUEUE"] = "ENG_QUEUE";
ShapeType2["ENG_FILE"] = "ENG_FILE";
ShapeType2["ENG_FOLDER"] = "ENG_FOLDER";
ShapeType2["TRAPEZOID"] = "TRAPEZOID";
ShapeType2["PREDEFINED_PROCESS"] = "PREDEFINED_PROCESS";
ShapeType2["SHIELD"] = "SHIELD";
ShapeType2["DOCUMENT_SINGLE"] = "DOCUMENT_SINGLE";
ShapeType2["DOCUMENT_MULTIPLE"] = "DOCUMENT_MULTIPLE";
ShapeType2["MANUAL_INPUT"] = "MANUAL_INPUT";
ShapeType2["HEXAGON"] = "HEXAGON";
ShapeType2["CHEVRON"] = "CHEVRON";
ShapeType2["PENTAGON"] = "PENTAGON";
ShapeType2["OCTAGON"] = "OCTAGON";
ShapeType2["STAR"] = "STAR";
ShapeType2["PLUS"] = "PLUS";
ShapeType2["ARROW_LEFT"] = "ARROW_LEFT";
ShapeType2["ARROW_RIGHT"] = "ARROW_RIGHT";
ShapeType2["SUMMING_JUNCTION"] = "SUMMING_JUNCTION";
ShapeType2["OR"] = "OR";
ShapeType2["SPEECH_BUBBLE"] = "SPEECH_BUBBLE";
ShapeType2["INTERNAL_STORAGE"] = "INTERNAL_STORAGE";
return ShapeType2;
})(ShapeType || {});
var ConnectorLineType = /* @__PURE__ */ ((ConnectorLineType2) => {
ConnectorLineType2["STRAIGHT"] = "STRAIGHT";
ConnectorLineType2["ELBOWED"] = "ELBOWED";
return ConnectorLineType2;
})(ConnectorLineType || {});
var Navigation = /* @__PURE__ */ ((Navigation2) => {
Navigation2["NAVIGATE"] = "NAVIGATE";
Navigation2["SWAP"] = "SWAP";
Navigation2["OVERLAY"] = "OVERLAY";
Navigation2["SCROLL_TO"] = "SCROLL_TO";
Navigation2["CHANGE_TO"] = "CHANGE_TO";
return Navigation2;
})(Navigation || {});
var VariableDataType = /* @__PURE__ */ ((VariableDataType2) => {
VariableDataType2["BOOLEAN"] = "BOOLEAN";
VariableDataType2["FLOAT"] = "FLOAT";
VariableDataType2["STRING"] = "STRING";
VariableDataType2["COLOR"] = "COLOR";
VariableDataType2["VARIABLE_ALIAS"] = "VARIABLE_ALIAS";
VariableDataType2["EXPRESSION"] = "EXPRESSION";
return VariableDataType2;
})(VariableDataType || {});
var VariableResolvedDataType = /* @__PURE__ */ ((VariableResolvedDataType2) => {
VariableResolvedDataType2["BOOLEAN"] = "BOOLEAN";
VariableResolvedDataType2["FLOAT"] = "FLOAT";
VariableResolvedDataType2["STRING"] = "STRING";
VariableResolvedDataType2["COLOR"] = "COLOR";
return VariableResolvedDataType2;
})(VariableResolvedDataType || {});
var ExpressionFunction = /* @__PURE__ */ ((ExpressionFunction2) => {
ExpressionFunction2["ADDITION"] = "ADDITION";
ExpressionFunction2["SUBTRACTION"] = "SUBTRACTION";
ExpressionFunction2["MULTIPLICATION"] = "MULTIPLICATION";
ExpressionFunction2["DIVISION"] = "DIVISION";
ExpressionFunction2["EQUALS"] = "EQUALS";
ExpressionFunction2["NOT_EQUAL"] = "NOT_EQUAL";
ExpressionFunction2["LESS_THAN"] = "LESS_THAN";
ExpressionFunction2["LESS_THAN_OR_EQUAL"] = "LESS_THAN_OR_EQUAL";
ExpressionFunction2["GREATER_THAN"] = "GREATER_THAN";
ExpressionFunction2["GREATER_THAN_OR_EQUAL"] = "GREATER_THAN_OR_EQUAL";
ExpressionFunction2["AND"] = "AND";
ExpressionFunction2["OR"] = "OR";
ExpressionFunction2["VAR_MODE_LOOKUP"] = "VAR_MODE_LOOKUP";
ExpressionFunction2["NEGATE"] = "NEGATE";
ExpressionFunction2["NOT"] = "NOT";
return ExpressionFunction2;
})(ExpressionFunction || {});
var StyleType = /* @__PURE__ */ ((StyleType2) => {
StyleType2["FILL"] = "FILL";
StyleType2["TEXT"] = "TEXT";
StyleType2["EFFECT"] = "EFFECT";
StyleType2["GRID"] = "GRID";
return StyleType2;
})(StyleType || {});
var WebhookV2Event = /* @__PURE__ */ ((WebhookV2Event2) => {
WebhookV2Event2["PING"] = "PING";
WebhookV2Event2["FILE_UPDATE"] = "FILE_UPDATE";
WebhookV2Event2["FILE_VERSION_UPDATE"] = "FILE_VERSION_UPDATE";
WebhookV2Event2["FILE_DELETE"] = "FILE_DELETE";
WebhookV2Event2["LIBRARY_PUBLISH"] = "LIBRARY_PUBLISH";
WebhookV2Event2["FILE_COMMENT"] = "FILE_COMMENT";
return WebhookV2Event2;
})(WebhookV2Event || {});
var WebhookV2Status = /* @__PURE__ */ ((WebhookV2Status2) => {
WebhookV2Status2["ACTIVE"] = "ACTIVE";
WebhookV2Status2["PAUSED"] = "PAUSED";
return WebhookV2Status2;
})(WebhookV2Status || {});
var VariableScope = /* @__PURE__ */ ((VariableScope2) => {
VariableScope2["ALL_SCOPES"] = "ALL_SCOPES";
VariableScope2["TEXT_CONTENT"] = "TEXT_CONTENT";
VariableScope2["CORNER_RADIUS"] = "CORNER_RADIUS";
VariableScope2["WIDTH_HEIGHT"] = "WIDTH_HEIGHT";
VariableScope2["GAP"] = "GAP";
VariableScope2["ALL_FILLS"] = "ALL_FILLS";
VariableScope2["FRAME_FILL"] = "FRAME_FILL";
VariableScope2["SHAPE_FILL"] = "SHAPE_FILL";
VariableScope2["TEXT_FILL"] = "TEXT_FILL";
VariableScope2["STROKE_COLOR"] = "STROKE_COLOR";
VariableScope2["STROKE_FLOAT"] = "STROKE_FLOAT";
VariableScope2["EFFECT_FLOAT"] = "EFFECT_FLOAT";
VariableScope2["EFFECT_COLOR"] = "EFFECT_COLOR";
VariableScope2["OPACITY"] = "OPACITY";
VariableScope2["FONT_FAMILY"] = "FONT_FAMILY";
VariableScope2["FONT_STYLE"] = "FONT_STYLE";
VariableScope2["FONT_WEIGHT"] = "FONT_WEIGHT";
VariableScope2["FONT_SIZE"] = "FONT_SIZE";
VariableScope2["LINE_HEIGHT"] = "LINE_HEIGHT";
VariableScope2["LETTER_SPACING"] = "LETTER_SPACING";
VariableScope2["PARAGRAPH_SPACING"] = "PARAGRAPH_SPACING";
VariableScope2["PARAGRAPH_INDENT"] = "PARAGRAPH_INDENT";
return VariableScope2;
})(VariableScope || {});
var ContentType = /* @__PURE__ */ ((ContentType2) => {
ContentType2["Json"] = "application/json";
ContentType2["FormData"] = "multipart/form-data";
ContentType2["UrlEncoded"] = "application/x-www-form-urlencoded";
ContentType2["Text"] = "text/plain";
return ContentType2;
})(ContentType || {});
var HttpClient = class {
instance;
securityData = null;
securityWorker;
secure;
format;
constructor({
securityWorker: securityWorker2,
secure,
format,
...axiosConfig
} = {}) {
this.instance = axios.create({
...axiosConfig,
baseURL: axiosConfig.baseURL || "https://api.figma.com"
});
this.secure = secure;
this.format = format;
this.securityWorker = securityWorker2;
}
setSecurityData = (data) => {
this.securityData = data;
};
mergeRequestParams(params1, params2) {
const method = params1.method || params2 && params2.method;
return {
...this.instance.defaults,
...params1,
...params2 || {},
headers: {
...method && this.instance.defaults.headers[method.toLowerCase()] || {},
...params1.headers || {},
...params2 && params2.headers || {}
}
};
}
stringifyFormItem(formItem) {
if (typeof formItem === "object" && formItem !== null) {
return JSON.stringify(formItem);
} else {
return `${formItem}`;
}
}
createFormData(input) {
if (input instanceof FormData) {
return input;
}
return Object.keys(input || {}).reduce((formData, key) => {
const property = input[key];
const propertyContent = property instanceof Array ? property : [property];
for (const formItem of propertyContent) {
const isFileType = formItem instanceof Blob || formItem instanceof File;
formData.append(key, isFileType ? formItem : this.stringifyFormItem(formItem));
}
return formData;
}, new FormData());
}
request = async ({
secure,
path,
type,
query,
format,
body,
...params
}) => {
const secureParams = (typeof secure === "boolean" ? secure : this.secure) && this.securityWorker && await this.securityWorker(this.securityData) || {};
const requestParams = this.mergeRequestParams(params, secureParams);
const responseFormat = format || this.format || void 0;
if (type === "multipart/form-data" /* FormData */ && body && body !== null && typeof body === "object") {
body = this.createFormData(body);
}
if (type === "text/plain" /* Text */ && body && body !== null && typeof body !== "string") {
body = JSON.stringify(body);
}
return this.instance.request({
...requestParams,
headers: {
...requestParams.headers || {},
...type ? { "Content-Type": type } : {}
},
params: query,
responseType: responseFormat,
data: body,
url: path
});
};
};
var Api = class extends HttpClient {
v1 = {
/**
* @description Returns the document identified by `file_key` as a JSON object. The file key can be parsed from any Figma file url: `https://www.figma.com/file/{file_key}/{title}`. The `document` property contains a node of type `DOCUMENT`. The `components` property contains a mapping from node IDs to component metadata. This is to help you determine which components each instance comes from.
*
* @tags Files
* @name GetFile
* @summary Get file JSON
* @request GET:/v1/files/{file_key}
* @secure
*/
getFile: (fileKey, query, params = {}) => this.request({
path: `/v1/files/${fileKey}`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns the nodes referenced to by `ids` as a JSON object. The nodes are retrieved from the Figma file referenced to by `file_key`. The node ID and file key can be parsed from any Figma node url: `https://www.figma.com/file/{file_key}/{title}?node-id={id}` The `name`, `lastModified`, `thumbnailUrl`, `editorType`, and `version` attributes are all metadata of the specified file. The `linkAccess` field describes the file link share permission level. There are 5 types of permissions a shared link can have: `"inherit"`, `"view"`, `"edit"`, `"org_view"`, and `"org_edit"`. `"inherit"` is the default permission applied to files created in a team project, and will inherit the project's permissions. `"org_view"` and `"org_edit"` restrict the link to org users. The `document` attribute contains a Node of type `DOCUMENT`. The `components` key contains a mapping from node IDs to component metadata. This is to help you determine which components each instance comes from. By default, no vector data is returned. To return vector data, pass the geometry=paths parameter to the endpoint. Each node can also inherit properties from applicable styles. The styles key contains a mapping from style IDs to style metadata. Important: the nodes map may contain values that are `null`. This may be due to the node id not existing within the specified file.
*
* @tags Files
* @name GetFileNodes
* @summary Get file JSON for specific nodes
* @request GET:/v1/files/{file_key}/nodes
* @secure
*/
getFileNodes: (fileKey, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/nodes`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Renders images from a file. If no error occurs, `"images"` will be populated with a map from node IDs to URLs of the rendered images, and `"status"` will be omitted. The image assets will expire after 30 days. Images up to 32 megapixels can be exported. Any images that are larger will be scaled down. Important: the image map may contain values that are `null`. This indicates that rendering of that specific node has failed. This may be due to the node id not existing, or other reasons such has the node having no renderable components. It is guaranteed that any node that was requested for rendering will be represented in this map whether or not the render succeeded. To render multiple images from the same file, use the `ids` query parameter to specify multiple node ids. ``` GET /v1/images/:key?ids=1:2,1:3,1:4 ```
*
* @tags Files
* @name GetImages
* @summary Render images of file nodes
* @request GET:/v1/images/{file_key}
* @secure
*/
getImages: (fileKey, query, params = {}) => this.request({
path: `/v1/images/${fileKey}`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns download links for all images present in image fills in a document. Image fills are how Figma represents any user supplied images. When you drag an image into Figma, we create a rectangle with a single fill that represents the image, and the user is able to transform the rectangle (and properties on the fill) as they wish. This endpoint returns a mapping from image references to the URLs at which the images may be download. Image URLs will expire after no more than 14 days. Image references are located in the output of the GET files endpoint under the `imageRef` attribute in a `Paint`.
*
* @tags Files
* @name GetImageFills
* @summary Get image fills
* @request GET:/v1/files/{file_key}/images
* @secure
*/
getImageFills: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/images`,
method: "GET",
secure: true,
...params
}),
/**
* @description You can use this endpoint to get a list of all the Projects within the specified team. This will only return projects visible to the authenticated user or owner of the developer token. Note: it is not currently possible to programmatically obtain the team id of a user just from a token. To obtain a team id, navigate to a team page of a team you are a part of. The team id will be present in the URL after the word team and before your team name.
*
* @tags Projects
* @name GetTeamProjects
* @summary Get projects in a team
* @request GET:/v1/teams/{team_id}/projects
* @secure
*/
getTeamProjects: (teamId, params = {}) => this.request({
path: `/v1/teams/${teamId}/projects`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get a list of all the Files within the specified project.
*
* @tags Projects
* @name GetProjectFiles
* @summary Get files in a project
* @request GET:/v1/projects/{project_id}/files
* @secure
*/
getProjectFiles: (projectId, query, params = {}) => this.request({
path: `/v1/projects/${projectId}/files`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description This endpoint fetches the version history of a file, allowing you to see the progression of a file over time. You can then use this information to render a specific version of the file, via another endpoint.
*
* @tags Files
* @name GetFileVersions
* @summary Get versions of a file
* @request GET:/v1/files/{file_key}/versions
* @secure
*/
getFileVersions: (fileKey, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/versions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Gets a list of comments left on the file.
*
* @tags Comments
* @name GetComments
* @summary Get comments in a file
* @request GET:/v1/files/{file_key}/comments
* @secure
*/
getComments: (fileKey, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Posts a new comment on the file.
*
* @tags Comments
* @name PostComment
* @summary Add a comment to a file
* @request POST:/v1/files/{file_key}/comments
* @secure
*/
postComment: (fileKey, data, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments`,
method: "POST",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Deletes a specific comment. Only the person who made the comment is allowed to delete it.
*
* @tags Comments
* @name DeleteComment
* @summary Delete a comment
* @request DELETE:/v1/files/{file_key}/comments/{comment_id}
* @secure
*/
deleteComment: (fileKey, commentId, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments/${commentId}`,
method: "DELETE",
secure: true,
...params
}),
/**
* @description Gets a paginated list of reactions left on the comment.
*
* @tags Comment Reactions
* @name GetCommentReactions
* @summary Get reactions for a comment
* @request GET:/v1/files/{file_key}/comments/{comment_id}/reactions
* @secure
*/
getCommentReactions: (fileKey, commentId, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments/${commentId}/reactions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Posts a new comment reaction on a file comment.
*
* @tags Comment Reactions
* @name PostCommentReaction
* @summary Add a reaction to a comment
* @request POST:/v1/files/{file_key}/comments/{comment_id}/reactions
* @secure
*/
postCommentReaction: (fileKey, commentId, data, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments/${commentId}/reactions`,
method: "POST",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Deletes a specific comment reaction. Only the person who made the reaction is allowed to delete it.
*
* @tags Comment Reactions
* @name DeleteCommentReaction
* @summary Delete a reaction
* @request DELETE:/v1/files/{file_key}/comments/{comment_id}/reactions
* @secure
*/
deleteCommentReaction: (fileKey, commentId, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/comments/${commentId}/reactions`,
method: "DELETE",
query,
secure: true,
...params
}),
/**
* @description Returns the user information for the currently authenticated user.
*
* @tags Users
* @name GetMe
* @summary Get current user
* @request GET:/v1/me
* @secure
*/
getMe: (params = {}) => this.request({
path: `/v1/me`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get a paginated list of published components within a team library.
*
* @tags Components
* @name GetTeamComponents
* @summary Get team components
* @request GET:/v1/teams/{team_id}/components
* @secure
*/
getTeamComponents: (teamId, query, params = {}) => this.request({
path: `/v1/teams/${teamId}/components`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Get a list of published components within a file library.
*
* @tags Components
* @name GetFileComponents
* @summary Get file components
* @request GET:/v1/files/{file_key}/components
* @secure
*/
getFileComponents: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/components`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get metadata on a component by key.
*
* @tags Components
* @name GetComponent
* @summary Get component
* @request GET:/v1/components/{key}
* @secure
*/
getComponent: (key, params = {}) => this.request({
path: `/v1/components/${key}`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get a paginated list of published component sets within a team library.
*
* @tags Component Sets
* @name GetTeamComponentSets
* @summary Get team component sets
* @request GET:/v1/teams/{team_id}/component_sets
* @secure
*/
getTeamComponentSets: (teamId, query, params = {}) => this.request({
path: `/v1/teams/${teamId}/component_sets`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Get a list of published component sets within a file library.
*
* @tags Component Sets
* @name GetFileComponentSets
* @summary Get file component sets
* @request GET:/v1/files/{file_key}/component_sets
* @secure
*/
getFileComponentSets: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/component_sets`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get metadata on a component set by key.
*
* @tags Component Sets
* @name GetComponentSet
* @summary Get component set
* @request GET:/v1/component_sets/{key}
* @secure
*/
getComponentSet: (key, params = {}) => this.request({
path: `/v1/component_sets/${key}`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get a paginated list of published styles within a team library.
*
* @tags Styles
* @name GetTeamStyles
* @summary Get team styles
* @request GET:/v1/teams/{team_id}/styles
* @secure
*/
getTeamStyles: (teamId, query, params = {}) => this.request({
path: `/v1/teams/${teamId}/styles`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Get a list of published styles within a file library.
*
* @tags Styles
* @name GetFileStyles
* @summary Get file styles
* @request GET:/v1/files/{file_key}/styles
* @secure
*/
getFileStyles: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/styles`,
method: "GET",
secure: true,
...params
}),
/**
* @description Get metadata on a style by key.
*
* @tags Styles
* @name GetStyle
* @summary Get style
* @request GET:/v1/styles/{key}
* @secure
*/
getStyle: (key, params = {}) => this.request({
path: `/v1/styles/${key}`,
method: "GET",
secure: true,
...params
}),
/**
* @description Returns a list of activity log events
*
* @tags Activity Logs
* @name GetActivityLogs
* @summary Get activity logs
* @request GET:/v1/activity_logs
* @secure
*/
getActivityLogs: (query, params = {}) => this.request({
path: `/v1/activity_logs`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description There are two methods to query for a user's payment information on a plugin, widget, or Community file. The first method, using plugin payment tokens, is typically used when making queries from a plugin's or widget's code. The second method, providing a user ID and resource ID, is typically used when making queries from anywhere else. Note that you can only query for resources that you own. In most cases, this means that you can only query resources that you originally created.
*
* @tags Payments
* @name GetPayments
* @summary Get payments
* @request GET:/v1/payments
* @secure
*/
getPayments: (query, params = {}) => this.request({
path: `/v1/payments`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description **This API is available to full members of Enterprise orgs.** The `GET /v1/files/:file_key/variables/local` endpoint lets you enumerate local variables created in the file and remote variables used in the file. Remote variables are referenced by their `subscribed_id`. As a part of the Variables related API additions, the `GET /v1/files/:file_key` endpoint now returns a `boundVariables` property, containing the `variableId` of the bound variable. The `GET /v1/files/:file_key/variables/local` endpoint can be used to get the full variable or variable collection object. Note that `GET /v1/files/:file_key/variables/published` does not return modes. Instead, you will need to use the `GET /v1/files/:file_key/variables/local` endpoint, in the same file, to examine the mode values.
*
* @tags Variables
* @name GetLocalVariables
* @summary Get local variables
* @request GET:/v1/files/{file_key}/variables/local
* @secure
*/
getLocalVariables: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/variables/local`,
method: "GET",
secure: true,
...params
}),
/**
* @description **This API is available to full members of Enterprise orgs.** The `GET /v1/files/:file_key/variables/published` endpoint returns the variables that are published from the given file. The response for this endpoint contains some key differences compared to the `GET /v1/files/:file_key/variables/local` endpoint: - Each variable and variable collection contains a `subscribed_id`. - Modes are omitted for published variable collections Published variables have two ids: an id that is assigned in the file where it is created (`id`), and an id that is used by subscribing files (`subscribed_id`). The `id` and `key` are stable over the lifetime of the variable. The `subscribed_id` changes every time the variable is modified and published. The same is true for variable collections. The `updatedAt` fields are ISO 8601 timestamps that indicate the last time that a change to a variable was published. For variable collections, this timestamp will change any time a variable in the collection is changed.
*
* @tags Variables
* @name GetPublishedVariables
* @summary Get published variables
* @request GET:/v1/files/{file_key}/variables/published
* @secure
*/
getPublishedVariables: (fileKey, params = {}) => this.request({
path: `/v1/files/${fileKey}/variables/published`,
method: "GET",
secure: true,
...params
}),
/**
* @description **This API is available to full members of Enterprise orgs with Editor seats.** The `POST /v1/files/:file_key/variables` endpoint lets you bulk create, update, and delete variables and variable collections. The request body supports the following 4 top-level arrays. Changes from these arrays will be applied in the below order, and within each array, by array order. - **variableCollections**: For creating, updating, and deleting variable collections - **variableModes**: For creating, updating, and deleting modes within variable collections - Each collection can have a maximum of 40 modes - Mode names cannot be longer than 40 characters - **variables**: For creating, updating, and deleting variables - Each collection can have a maximum of 5000 variables - Variable names must be unique within a collection and cannot contain certain special characters such as `.{}` - **variableModeValues**: For setting a variable value under a specific mode. - When setting aliases, a variable cannot be aliased to itself or form an alias cycle Temporary ids can be used to reference an object later in the same POST request body. They can be used at create time in the `id` property of variable collections, modes, variables, and in the `initialModeId` property of variable collections. They are scoped to a single request body, and must be unique within the body. The mapping of temporary ids to real ids is returned in the response. This endpoint has the following key behaviors: - The request body must be 4MB or less. - Must include an `action` property for collections, modes, and variables to tell the API whether to create, update, or delete the object. - When creating a collection, mode, or variable, you can include a temporary `id` that can be referenced in dependent objects in the same request. For example, you can create a new collection with the id `"my_new_collection"`. You can then set `variableCollectionId` to `"my_new_collection"` in new modes or variables. Temporary ids must be unique in the request body. - New collections always come with one mode. You can reference this mode by setting `initialModeId` to a temporary id in the request body. This is useful if you want to set values for variables in the mode in the `variableModeValues` array. - The `tempIdToRealId` array returns a mapping of the temporary ids in the request, to the real ids of the newly created objects. - When adding new modes or variables, default variable values will be applied, consistent with what happens in the UI. - Everything to be created, updated, and deleted in the request body is treated as one atomic operation. If there is any validation failure, you will get a 400 status code response, and no changes will be persisted. - You will not be able to update remote variables or variable collections. You can only update variables in the file where they were originally created.
*
* @tags Variables
* @name PostVariables
* @summary Create/modify/delete variables
* @request POST:/v1/files/{file_key}/variables
* @secure
*/
postVariables: (fileKey, data, params = {}) => this.request({
path: `/v1/files/${fileKey}/variables`,
method: "POST",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Get dev resources in a file
*
* @tags Dev Resources
* @name GetDevResources
* @summary Get dev resources
* @request GET:/v1/files/{file_key}/dev_resources
* @secure
*/
getDevResources: (fileKey, query, params = {}) => this.request({
path: `/v1/files/${fileKey}/dev_resources`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Bulk create dev resources across multiple files. Dev resources that are successfully created will show up in the links_created array in the response. If there are any dev resources that cannot be created, you may still get a 200 response. These resources will show up in the errors array. Some reasons a dev resource cannot be created include: - Resource points to a `file_key` that cannot be found. - The node already has the maximum of 10 dev resources. - Another dev resource for the node has the same url.
*
* @tags Dev Resources
* @name PostDevResources
* @summary Create dev resources
* @request POST:/v1/dev_resources
* @secure
*/
postDevResources: (data, params = {}) => this.request({
path: `/v1/dev_resources`,
method: "POST",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Bulk update dev resources across multiple files. Ids for dev resources that are successfully updated will show up in the `links_updated` array in the response. If there are any dev resources that cannot be updated, you may still get a 200 response. These resources will show up in the `errors` array.
*
* @tags Dev Resources
* @name PutDevResources
* @summary Update dev resources
* @request PUT:/v1/dev_resources
* @secure
*/
putDevResources: (data, params = {}) => this.request({
path: `/v1/dev_resources`,
method: "PUT",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Delete a dev resource from a file
*
* @tags Dev Resources
* @name DeleteDevResource
* @summary Delete dev resource
* @request DELETE:/v1/files/{file_key}/dev_resources/{dev_resource_id}
* @secure
*/
deleteDevResource: (fileKey, devResourceId, params = {}) => this.request({
path: `/v1/files/${fileKey}/dev_resources/${devResourceId}`,
method: "DELETE",
secure: true,
...params
}),
/**
* @description Returns a list of library analytics component actions data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsComponentActions
* @summary Get library analytics component action data.
* @request GET:/v1/analytics/libraries/{file_key}/component/actions
* @secure
*/
getLibraryAnalyticsComponentActions: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/component/actions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics component usage data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsComponentUsages
* @summary Get library analytics component usage data.
* @request GET:/v1/analytics/libraries/{file_key}/component/usages
* @secure
*/
getLibraryAnalyticsComponentUsages: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/component/usages`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics style actions data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsStyleActions
* @summary Get library analytics style action data.
* @request GET:/v1/analytics/libraries/{file_key}/style/actions
* @secure
*/
getLibraryAnalyticsStyleActions: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/style/actions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics style usage data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsStyleUsages
* @summary Get library analytics style usage data.
* @request GET:/v1/analytics/libraries/{file_key}/style/usages
* @secure
*/
getLibraryAnalyticsStyleUsages: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/style/usages`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics variable actions data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsVariableActions
* @summary Get library analytics variable action data.
* @request GET:/v1/analytics/libraries/{file_key}/variable/actions
* @secure
*/
getLibraryAnalyticsVariableActions: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/variable/actions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics variable usage data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsVariableUsages
* @summary Get library analytics variable usage data.
* @request GET:/v1/analytics/libraries/{file_key}/variable/usages
* @secure
*/
getLibraryAnalyticsVariableUsages: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/variable/usages`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics actions data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsActions
* @summary Get library analytics action data.
* @request GET:/v1/analytics/libraries/{file_key}/actions
* @secure
*/
getLibraryAnalyticsActions: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/actions`,
method: "GET",
query,
secure: true,
...params
}),
/**
* @description Returns a list of library analytics usage data broken down by the requested dimension.
*
* @tags Library Analytics
* @name GetLibraryAnalyticsUsages
* @summary Get library analytics usage data.
* @request GET:/v1/analytics/libraries/{file_key}/usages
* @secure
*/
getLibraryAnalyticsUsages: (fileKey, query, params = {}) => this.request({
path: `/v1/analytics/libraries/${fileKey}/usages`,
method: "GET",
query,
secure: true,
...params
})
};
v2 = {
/**
* @description Create a new webhook which will call the specified endpoint when the event triggers. By default, this webhook will automatically send a PING event to the endpoint when it is created. If this behavior is not desired, you can create the webhook and set the status to PAUSED and reactivate it later.
*
* @tags Webhooks
* @name PostWebhook
* @summary Create a webhook
* @request POST:/v2/webhooks
* @secure
*/
postWebhook: (data, params = {}) => this.request({
path: `/v2/webhooks`,
method: "POST",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Get a webhook by ID.
*
* @tags Webhooks
* @name GetWebhook
* @summary Get a webhook
* @request GET:/v2/webhooks/{webhook_id}
* @secure
*/
getWebhook: (webhookId, params = {}) => this.request({
path: `/v2/webhooks/${webhookId}`,
method: "GET",
secure: true,
...params
}),
/**
* @description Update a webhook by ID.
*
* @tags Webhooks
* @name PutWebhook
* @summary Update a webhook
* @request PUT:/v2/webhooks/{webhook_id}
* @secure
*/
putWebhook: (webhookId, data, params = {}) => this.request({
path: `/v2/webhooks/${webhookId}`,
method: "PUT",
body: data,
secure: true,
type: "application/json" /* Json */,
...params
}),
/**
* @description Deletes the specified webhook. This operation cannot be reversed.
*
* @tags Webhooks
* @name DeleteWebhook
* @summary Delete a webhook
* @request DELETE:/v2/webhooks/{webhook_id}
* @secure
*/
deleteWebhook: (webhookId, params = {}) => this.request({
path: `/v2/webhooks/${webhookId}`,
method: "DELETE",
secure: true,
...params
}),
/**
* @description Returns all webhooks registered under the specified team.
*
* @tags Webhooks
* @name GetTeamWebhooks
* @summary Get team webhooks
* @request GET:/v2/teams/{team_id}/webhooks
* @secure
*/
getTeamWebhooks: (teamId, params = {}) => this.request({
path: `/v2/teams/${teamId}/webhooks`,
method: "GET",
secure: true,
...params
}),
/**
* @description Returns all webhook requests sent within the last week. Useful for debugging.
*
* @tags Webhooks
* @name GetWebhookRequests
* @summary Get webhook requests
* @request GET:/v2/webhooks/{webhook_id}/requests
* @secure
*/
getWebhookRequests: (webhookId, params = {}) => this.request({
path: `/v2/webhooks/${webhookId}/requests`,
method: "GET",
secure: true,
...params
})
};
};
// src/client.ts
import axiosRetry, { exponentialDelay, isNetworkOrIdempotentRequestError } from "axios-retry";
import { log as log4 } from "@figmarine/logger";
// src/cache.ts
import {
buildStorage,
setupCache
} from "axios-cache-interceptor";
import { makeCache } from "@figmarine/cache";
import { log } from "@figmarine/logger";
var KEY_SEPARATOR = " @ ";
function generatePredictableKey({ url, method, params, data }) {
return `${method?.toUpperCase() ?? "GET"}${KEY_SEPARATOR}${url ?? "/"}${KEY_SEPARATOR}${JSON.stringify(params) ?? "-"}${KEY_SEPARATOR}${JSON.stringify(data) ?? "-"}`;
}
var Cache = class {
#client;
#cache;
#primaryStore;
constructor(c, opts) {
this.#client = c;
log(`API cache middleware: Creating Cacheable instance.`);
const { cache, primary } = makeCache({ location: "rest", ttl: -1, ...opts ?? {} });
this.#cache = cache;
this.#primaryStore = primary;
log(`API cache middleware: Setting up cache interceptor on Axios client.`);
setupCache(this.#client.instance, {
/**
* Ignore "don't cache" headers from Figma by default.
* Let the cache package handle TTL for us, and cache
* invalidation logic clear stale cache.
* @returns A 999999999999 seconds TTL.
*/
headerInterpreter: () => 999999999999,
/**
* Our cache package is used as a storage middleware for
* the Axios cache, allowing us to save API results to disk
* between two runs of the program in development mode.
*/
storage: buildStorage({
clear: async () => await this.clear(),
find: async (key) => await this.get(key),
remove: async (key) => await this.delete(key),
set: async (key, value) => await this.set(key, value)
}),
/**
* We customise the cache key so that if someone wants to
* iterate over cached data and manually invalidate it, they
* can make sense of it. The axios-cache-interceptor recommended
* approach is harder to use in our generated client; adding a
* `cache.update` param messes with our TS types too much.
*/
generateKey: generatePredictableKey
});
}
async get(key) {
const value = await this.#cache.get(key);
log(`API cache middleware: getting '${key}', cache ${value ? "hit" : "miss"}.`);
return value ? JSON.parse(value) : void 0;
}
async has(key) {
const found = await this.#cache.has(key);
log(`API cache middleware: looked up '${key}', cache ${found ? "hit" : "miss"}.`);
return found;
}
async set(key, value) {
log(`API cache middleware: setting '${key}'.`);
await this.#cache.set(key, JSON.stringify(value));
}
async delete(key) {
log(`API cache middleware: deleting '${key}'.`);
await this.#cache.delete(key);
}
async clear() {
log("API cache middleware: resetting.");
await this.#cache.clear();
}
getCache() {
return this.#cache;
}
async *iterator() {
log("API cache middleware: iterating over primary store.");
if (this.#primaryStore.iterator === void 0) {
throw new Error(
"API cache middleware: Keyv store is missing an iterator, cannot be used. Please report a bug on the figmarine repository."
);
}
for await (const [key, value] of this.#primaryStore.iterator(void 0)) {
yield [key, value];
}
}
};
// src/interceptors.ts
import { log as log3 } from "@figmarine/logger";
// src/rateLimit.ts
import { log as log2 } from "@figmarine/logger";
// src/rateLimit.config.ts
var WINDOW_BUDGET = 10;
var WINDOW_LENGTH = 60;
var INITIAL_DELAY = 500;
var reqLog = [];
function getConfig() {
return {
reqLog,
WINDOW_BUDGET,
WINDOW_LENGTH
};
}
function get429Config() {
return {
INITIAL_DELAY
};
}
// src/rateLimit.ts
function getNextRequestLegalTime(now, requestCost, reqLog2, WINDOW_BUDGET2, WINDOW_LENGTH2) {
if (WINDOW_BUDGET2 < requestCost) {
const errMsg = `Rate limit: request cannot proceed due to improper configuration (request cost: ${requestCost}, max cost in sliding window: ${WINDOW_BUDGET2}).`;
throw new Error(errMsg);
}
const startOfWindow = now - WINDOW_LENGTH2;
const indexOfFirstRelevantRequest = reqLog2.findIndex(
({ timestamp }) => timestamp > startOfWindow
);
if (indexOfFirstRelevantRequest > -1) {
reqLog2.splice(0, indexOfFirstRelevantRequest);
} else {
reqLog2.splice(0, reqLog2.length);
}
log2(
`Rate limit: sliding window starts at ${startOfWindow}, request log contains ${reqLog2.length} relevant${indexOfFirstRelevantRequest > 0 ? ` and ${indexOfFirstRelevantRequest} stale` : ""} requests.`
);
let remainingBudget = WINDOW_BUDGET2;
for (let i = reqLog2.length - 1; i >= 0; i--) {
remainingBudget -= reqLog2[i].budget;
if (remainingBudget < requestCost) {
log2(
`Rate limit: we're over budget (time of offending request ${reqLog2[i].timestamp}, budget freed by it: ${reqLog2[i].budget}).`
);
return reqLog2[i].timestamp + WINDOW_LENGTH2;
}
}
log2(
`Rate limit: we're within budget (remaining: ${remainingBudget}, cost of next request: ${requestCost}).`
);
return now;
}
async function interceptRequest(requestCost) {
const { reqLog: reqLog2, WINDOW_BUDGET: WINDOW_BUDGET2, WINDOW_LENGTH: WINDOW_LENGTH2 } = getConfig();
const now = Math.floor(Date.now() / 1e3);
log2(
`Rate limit: checking if we can send a request at ${now} (cost: ${requestCost}, budget: ${WINDOW_BUDGET2} every ${WINDOW_LENGTH2} seconds)`
);
const runNextRequest = getNextRequestLegalTime(
now,
requestCost,
reqLog2,
WINDOW_BUDGET2,
WINDOW_LENGTH2
);
const timeDelta = runNextRequest - now;
log2(`Rate limit: request can be sent in ${timeDelta} seconds (at ${runNextRequest})`);
reqLog2.push({ timestamp: runNextRequest, budget: requestCost });
if (timeDelta > 0) {
log2(`Waiting ${timeDelta} seconds to respect API rate limits.
`);
await new Promise(
(resolve) => setTimeout(() => {
resolve();
}, timeDelta * 1e3)
);
} else {
log2(`Rate limit: sending request immediately
`);
}
}
// package.json
var package_default = {
name: "@figmarine/rest",
version: "0.0.0-semantically-released",
license: "MIT",
type: "module",
description: "TypeScript client for the Figma REST API with built-in cache and auto-retry. Always up-to-date.",
repository: {
type: "git",
url: "https://github.com/Sidnioulz/figmarine",
directory: "packages/rest"
},
bugs: {
url: "https://github.com/Sidnioulz/figmarine/issues"
},
keywords: ["figma", "rest", "api", "openapi-specification", "oas", "figmarine"],
author: "Steve Dodier-Lazaro",
homepage: "https://github.com/Sidnioulz/figmarine",
scripts: {
"api:regen": "node ./scripts/regenFigmaRestApi.mjs",
build: "tsc && tsup --env.NODE_ENV production",
"build:debug": "tsc && tsup --entry src/debug.ts --entry src/index.ts --env.NODE_ENV development",
dev: 'tsc-watch --onSuccess "tsup --env.NODE_ENV production"',
"dev:debug": 'tsc-watch --onSuccess "tsup --entry src/debug.ts --entry src/index.ts --env.NODE_ENV development"',
"docs:build": "echo 'TODO: vitepress build docs'",
"docs:dev": "echo 'TODO: vitepress dev docs --port 1227'",
"docs:serve": "echo 'TODO: vitepress serve docs'",
lint: "eslint .",
"lint:files": "eslint --",
"lint:fix": "eslint . --fix",
"lint:staged": "lint-staged",
test: "vitest run",
"test:changed": "vitest run --changed HEAD~1",
"test:coverage": "vitest --coverage run",
"test:dev": "vitest dev",
typecheck: "tsc --noEmit"
},
exports: {
".": {
types: "./dist/index.d.js",
default: "./dist/index.js"
},
"./*": {
types: "./dist/*.d.js",
default: "./dist/*.js"
}
},
files: ["dist/**"],
publishConfig: {
access: "public"
},
devDependencies: {
"@faker-js/faker": "^9.7.0",
"@figma/rest-api-spec": "^0.31.0",
"@figmarine/config-eslint": "workspace:*",
"@figmarine/config-prettier": "workspace:*",
"@figmarine/config-tsup": "workspace:*",
"@figmarine/config-typescript": "workspace:*",
"@figmarine/config-vitest": "workspace:*",
"@types/node": "^22.14.1",
"@vitest/coverage-istanbul": "^3.1.1",
"@vitest/coverage-v8": "^3.1.1",
cacheable: "^1.8.10",
keyv: "^5.3.2",
"lint-staged": "^15.5.1",
memfs: "^4.17.0",
"mocked-env": "^1.3.5",
nock: "^14.0.3",
"swagger-typescript-api": "^13.1.1",
"tsc-watch": "^6.2.1",
tsup: "^8.4.0",
typescript: "latest",
vitest: "^3.1.1",
yaml: "^2.7.1"
},
dependencies: {
"@figmarine/cache": "workspace:*",
"@figmarine/logger": "w