/
figma.ts
134 lines (110 loc) · 3.82 KB
/
figma.ts
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import {
Client,
FileImageParams,
PostCommentParams,
FileImageResponse,
CommentsResponse,
TeamProjectsResponse,
ProjectFilesResponse,
FileParams,
} from "figma-js";
import { config } from "dotenv";
import { processFile, ProcessedFile } from "figma-transformer";
config();
// Setup types
enum RequestType {
File,
Comments,
Images,
Projects,
ProjectFiles,
PostComment,
}
type FigmaOptions = {
requestType: RequestType;
id: string;
params?: FileParams | FileImageParams | PostCommentParams;
noCache?: boolean;
};
type FigmaResponse =
| ProcessedFile
| FileImageResponse
| Comment
| CommentsResponse
| TeamProjectsResponse
| ProjectFilesResponse;
// Initialise FigmaJS Client and import all necessary functions
const client = Client({
personalAccessToken: process.env.FIGMA_TOKEN,
});
const { file, fileImages, comments, postComment, teamProjects, projectFiles } = client;
const mapTypeToFunctionWithParams = {
[RequestType.File]: file,
[RequestType.Images]: fileImages,
[RequestType.PostComment]: postComment,
};
const mapTypeToFunction = {
[RequestType.File]: file,
[RequestType.Comments]: comments,
[RequestType.Projects]: teamProjects,
[RequestType.ProjectFiles]: projectFiles,
};
type Values<O extends object> = O[keyof O];
type FigmaFunction =
| ((id: string) => ReturnType<Values<typeof mapTypeToFunction>>)
| ((
id: string,
params?: FileParams | FileImageParams | PostCommentParams
) => ReturnType<Values<typeof mapTypeToFunctionWithParams>>);
// Initialise cache
const cache = new Map();
async function getFigma<T extends FigmaResponse>({
requestType,
id,
params,
noCache = false,
}: FigmaOptions): Promise<T> {
const key = `${id}_${requestType}`;
if (noCache === false && params === undefined && cache.has(key)) {
// eslint-disable-next-line no-console
console.log("returning from cache", key);
return cache.get(key);
}
// eslint-disable-next-line no-console
console.log("fetching", key);
const fn: FigmaFunction =
params === undefined
? mapTypeToFunction[requestType]
: mapTypeToFunctionWithParams[requestType];
try {
const { data } = await fn(id, { ...params });
// We just need to parse the response if it's for a file, otherwise we return the raw data
const processedData =
"document" in data && requestType === RequestType.File ? processFile(data, id) : data;
// Only store data that doesn't change depending on the params
// We store it even if noCache is true so we can update the cache
if (params === undefined) {
cache.set(key, processedData);
}
return processedData as T;
} catch (e) {
throw new Error(e);
}
}
export const loadFile = (id: string, noCache: boolean = false): Promise<ProcessedFile> =>
getFigma({ requestType: RequestType.File, id, noCache });
export const loadComments = (id: string, noCache: boolean = false): Promise<CommentsResponse> =>
getFigma({ requestType: RequestType.Comments, id, noCache });
export const loadImages = (id: string, params: FileImageParams): Promise<FileImageResponse> =>
getFigma({ requestType: RequestType.Images, id, params });
export const loadTeamProjects = (
id: string,
noCache: boolean = false
): Promise<TeamProjectsResponse> => getFigma({ requestType: RequestType.Projects, id, noCache });
export const loadProjectFiles = (
id: string,
noCache: boolean = false
): Promise<ProjectFilesResponse> =>
getFigma({ requestType: RequestType.ProjectFiles, id, noCache });
export const createComment = (id: string, params: PostCommentParams): Promise<Comment> =>
getFigma({ requestType: RequestType.PostComment, id, params });