@animaapp/anima-sdk-react 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -15
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1324 -1279
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
- package/src/useAnimaCodegen.ts +92 -22
- package/src/utils.ts +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@animaapp/anima-sdk-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Anima's JavaScript utilities library",
|
|
6
6
|
"author": "Anima App, Inc.",
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
"url": "git+https://github.com/AnimaApp/anima-sdk.git"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
20
|
-
"registry": "https://registry.npmjs.org/"
|
|
19
|
+
"access": "public"
|
|
21
20
|
},
|
|
22
21
|
"scripts": {
|
|
23
22
|
"build": "vite build",
|
package/src/useAnimaCodegen.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { arrayBufferToBase64 } from "./utils";
|
|
1
2
|
import type {
|
|
2
3
|
AnimaSDKResult,
|
|
3
4
|
GetCodeParams,
|
|
@@ -7,6 +8,12 @@ import { convertCodegenFilesToAnimaFiles } from "@animaapp/anima-sdk";
|
|
|
7
8
|
import { EventSource } from "eventsource";
|
|
8
9
|
import { useImmer } from "use-immer";
|
|
9
10
|
|
|
11
|
+
export type UseAnimaParams = Omit<GetCodeParams, "assetsStorage"> & {
|
|
12
|
+
assetsStorage?:
|
|
13
|
+
| GetCodeParams["assetsStorage"]
|
|
14
|
+
| { strategy: "local"; path: string };
|
|
15
|
+
};
|
|
16
|
+
|
|
10
17
|
type Status = "idle" | "pending" | "success" | "aborted" | "error";
|
|
11
18
|
|
|
12
19
|
type TaskStatus = "pending" | "running" | "finished";
|
|
@@ -33,7 +40,10 @@ const defaultProgress: CodegenStatus = {
|
|
|
33
40
|
},
|
|
34
41
|
};
|
|
35
42
|
|
|
36
|
-
type StreamMessageByType<T extends StreamCodgenMessage[
|
|
43
|
+
type StreamMessageByType<T extends StreamCodgenMessage["type"]> = Extract<
|
|
44
|
+
StreamCodgenMessage,
|
|
45
|
+
{ type: T }
|
|
46
|
+
>;
|
|
37
47
|
|
|
38
48
|
export const useAnimaCodegen = ({
|
|
39
49
|
url,
|
|
@@ -44,7 +54,9 @@ export const useAnimaCodegen = ({
|
|
|
44
54
|
}) => {
|
|
45
55
|
const [status, updateStatus] = useImmer<CodegenStatus>(defaultProgress);
|
|
46
56
|
|
|
47
|
-
const getCode = async <T =
|
|
57
|
+
const getCode = async <T extends UseAnimaParams = UseAnimaParams>(
|
|
58
|
+
params: T
|
|
59
|
+
) => {
|
|
48
60
|
updateStatus((draft) => {
|
|
49
61
|
draft.status = "pending";
|
|
50
62
|
draft.error = null;
|
|
@@ -52,6 +64,15 @@ export const useAnimaCodegen = ({
|
|
|
52
64
|
draft.tasks = defaultProgress.tasks;
|
|
53
65
|
});
|
|
54
66
|
|
|
67
|
+
const initialParams = structuredClone(params);
|
|
68
|
+
|
|
69
|
+
if (params.assetsStorage?.strategy === "local") {
|
|
70
|
+
params.assetsStorage = {
|
|
71
|
+
strategy: "external",
|
|
72
|
+
url: params.assetsStorage.path,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
55
76
|
const es = new EventSource(url, {
|
|
56
77
|
fetch: (url, init) =>
|
|
57
78
|
fetch(url, {
|
|
@@ -65,12 +86,11 @@ export const useAnimaCodegen = ({
|
|
|
65
86
|
result: AnimaSDKResult | null;
|
|
66
87
|
error: Error | null;
|
|
67
88
|
}>((resolve) => {
|
|
68
|
-
|
|
69
89
|
const result: Partial<AnimaSDKResult> = {};
|
|
70
90
|
|
|
71
91
|
// Add specific event listeners
|
|
72
|
-
es.addEventListener(
|
|
73
|
-
const message = JSON.parse(event.data) as StreamMessageByType<
|
|
92
|
+
es.addEventListener("start", (event) => {
|
|
93
|
+
const message = JSON.parse(event.data) as StreamMessageByType<"start">;
|
|
74
94
|
result.sessionId = message.sessionId;
|
|
75
95
|
|
|
76
96
|
updateStatus((draft) => {
|
|
@@ -78,8 +98,10 @@ export const useAnimaCodegen = ({
|
|
|
78
98
|
});
|
|
79
99
|
});
|
|
80
100
|
|
|
81
|
-
es.addEventListener(
|
|
82
|
-
const message = JSON.parse(
|
|
101
|
+
es.addEventListener("pre_codegen", (event) => {
|
|
102
|
+
const message = JSON.parse(
|
|
103
|
+
event.data
|
|
104
|
+
) as StreamMessageByType<"pre_codegen">;
|
|
83
105
|
if (message.message === "Anima model built") {
|
|
84
106
|
updateStatus((draft) => {
|
|
85
107
|
draft.tasks.fetchDesign.status = "finished";
|
|
@@ -89,13 +111,15 @@ export const useAnimaCodegen = ({
|
|
|
89
111
|
}
|
|
90
112
|
});
|
|
91
113
|
|
|
92
|
-
es.addEventListener(
|
|
93
|
-
const message = JSON.parse(
|
|
114
|
+
es.addEventListener("figma_metadata", (e) => {
|
|
115
|
+
const message = JSON.parse(
|
|
116
|
+
e.data
|
|
117
|
+
) as StreamMessageByType<"figma_metadata">;
|
|
94
118
|
result.figmaFileName = message.figmaFileName;
|
|
95
119
|
result.figmaSelectedFrameName = message.figmaSelectedFrameName;
|
|
96
120
|
});
|
|
97
121
|
|
|
98
|
-
es.addEventListener(
|
|
122
|
+
es.addEventListener("aborted", () => {
|
|
99
123
|
updateStatus((draft) => {
|
|
100
124
|
draft.status = "aborted";
|
|
101
125
|
});
|
|
@@ -105,8 +129,10 @@ export const useAnimaCodegen = ({
|
|
|
105
129
|
});
|
|
106
130
|
});
|
|
107
131
|
|
|
108
|
-
es.addEventListener(
|
|
109
|
-
const message = JSON.parse(
|
|
132
|
+
es.addEventListener("generating_code", (event) => {
|
|
133
|
+
const message = JSON.parse(
|
|
134
|
+
event.data
|
|
135
|
+
) as StreamMessageByType<"generating_code">;
|
|
110
136
|
if (message.payload.status === "success") {
|
|
111
137
|
const codegenFiles = message.payload.files as Record<
|
|
112
138
|
string,
|
|
@@ -121,22 +147,33 @@ export const useAnimaCodegen = ({
|
|
|
121
147
|
});
|
|
122
148
|
});
|
|
123
149
|
|
|
124
|
-
es.addEventListener(
|
|
150
|
+
es.addEventListener("codegen_completed", () => {
|
|
125
151
|
updateStatus((draft) => {
|
|
126
152
|
draft.tasks.codeGeneration.status = "finished";
|
|
127
153
|
});
|
|
128
154
|
});
|
|
129
155
|
|
|
130
|
-
es.addEventListener(
|
|
156
|
+
es.addEventListener("assets_uploaded", () => {
|
|
131
157
|
updateStatus((draft) => {
|
|
132
158
|
draft.tasks.uploadAssets.status = "finished";
|
|
133
159
|
});
|
|
134
160
|
});
|
|
135
161
|
|
|
136
|
-
es.addEventListener(
|
|
162
|
+
es.addEventListener("assets_list", (event) => {
|
|
163
|
+
const message = JSON.parse(
|
|
164
|
+
event.data
|
|
165
|
+
) as StreamMessageByType<"assets_list">;
|
|
166
|
+
|
|
167
|
+
result.assets = message.payload.assets;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// TODO: For some reason, we receive errors even after the `done` event is triggered.
|
|
171
|
+
es.addEventListener("error", (error: ErrorEvent | MessageEvent) => {
|
|
137
172
|
// Differentiate between an error message from the server and an error event from the EventSource
|
|
138
|
-
if (
|
|
139
|
-
const message = JSON.parse(
|
|
173
|
+
if (error instanceof MessageEvent) {
|
|
174
|
+
const message = JSON.parse(
|
|
175
|
+
error.data
|
|
176
|
+
) as StreamMessageByType<"error">;
|
|
140
177
|
updateStatus((draft) => {
|
|
141
178
|
draft.status = "error";
|
|
142
179
|
draft.error = new Error(message.payload.message);
|
|
@@ -148,21 +185,21 @@ export const useAnimaCodegen = ({
|
|
|
148
185
|
});
|
|
149
186
|
} else {
|
|
150
187
|
// It's an EventSource error (e.g. HTTP error)
|
|
151
|
-
console.error(
|
|
188
|
+
console.error("EventSource error:", error);
|
|
152
189
|
|
|
153
190
|
updateStatus((draft) => {
|
|
154
191
|
draft.status = "error";
|
|
155
|
-
draft.error = new Error("HTTP error: " +
|
|
192
|
+
draft.error = new Error("HTTP error: " + error.message);
|
|
156
193
|
});
|
|
157
194
|
|
|
158
195
|
resolve({
|
|
159
196
|
result: null,
|
|
160
|
-
error: new Error("HTTP error: " +
|
|
197
|
+
error: new Error("HTTP error: " + error.message),
|
|
161
198
|
});
|
|
162
199
|
}
|
|
163
200
|
});
|
|
164
201
|
|
|
165
|
-
es.addEventListener(
|
|
202
|
+
es.addEventListener("done", () => {
|
|
166
203
|
updateStatus((draft) => {
|
|
167
204
|
draft.status = "success";
|
|
168
205
|
draft.result = result as AnimaSDKResult;
|
|
@@ -173,7 +210,40 @@ export const useAnimaCodegen = ({
|
|
|
173
210
|
});
|
|
174
211
|
|
|
175
212
|
try {
|
|
176
|
-
const { result, error } = await promise;
|
|
213
|
+
const { result: r, error } = await promise;
|
|
214
|
+
|
|
215
|
+
const result = structuredClone(r);
|
|
216
|
+
|
|
217
|
+
// Ideally, we should download the assets within the `assets_uploaded` event handler, since it'll improve the performance.
|
|
218
|
+
// But for some reason, it doesn't work. So, we download the assets here.
|
|
219
|
+
if (
|
|
220
|
+
initialParams.assetsStorage?.strategy === "local" &&
|
|
221
|
+
result?.assets?.length
|
|
222
|
+
) {
|
|
223
|
+
const downloadAssetsPromises = result.assets.map(async (asset) => {
|
|
224
|
+
const response = await fetch(asset.url);
|
|
225
|
+
const buffer = await response.arrayBuffer();
|
|
226
|
+
return {
|
|
227
|
+
assetName: asset.name,
|
|
228
|
+
base64: arrayBufferToBase64(buffer),
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const assets = await Promise.allSettled(downloadAssetsPromises);
|
|
233
|
+
for (const assetPromise of assets) {
|
|
234
|
+
const assetsList: Record<string, string> = {};
|
|
235
|
+
if (assetPromise.status === "fulfilled") {
|
|
236
|
+
const { assetName, base64 } = assetPromise.value;
|
|
237
|
+
|
|
238
|
+
assetsList[assetName] = base64;
|
|
239
|
+
|
|
240
|
+
result.files[`${initialParams.assetsStorage.path}/${assetName}`] = {
|
|
241
|
+
content: base64,
|
|
242
|
+
isBinary: true,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
177
247
|
|
|
178
248
|
if (error) {
|
|
179
249
|
return { result: null, error };
|
package/src/utils.ts
ADDED