@canva/cli 0.0.1-beta.3 → 0.0.1-beta.5
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/README.md +180 -110
- package/cli.js +422 -358
- package/package.json +1 -1
- package/templates/base/eslint.config.mjs +0 -2
- package/templates/base/package.json +22 -19
- package/templates/common/.gitignore.template +5 -6
- package/templates/common/.nvmrc +1 -0
- package/templates/common/.prettierrc +21 -0
- package/templates/common/.vscode/extensions.json +6 -0
- package/templates/common/README.md +4 -7
- package/templates/common/conf/eslint-general.mjs +26 -0
- package/templates/common/conf/eslint-i18n.mjs +18 -3
- package/templates/dam/package.json +23 -23
- package/templates/gen_ai/README.md +1 -40
- package/templates/gen_ai/backend/routers/image.ts +3 -3
- package/templates/gen_ai/backend/server.ts +0 -7
- package/templates/gen_ai/eslint.config.mjs +0 -2
- package/templates/gen_ai/package.json +24 -24
- package/templates/gen_ai/src/api/api.ts +24 -79
- package/templates/gen_ai/src/components/footer.messages.ts +0 -5
- package/templates/gen_ai/src/components/footer.tsx +7 -25
- package/templates/gen_ai/src/components/index.ts +0 -1
- package/templates/gen_ai/src/components/loading_results.tsx +4 -8
- package/templates/gen_ai/src/context/app_context.tsx +5 -33
- package/templates/gen_ai/src/context/context.messages.ts +1 -12
- package/templates/hello_world/eslint.config.mjs +0 -2
- package/templates/hello_world/package.json +18 -18
- package/templates/gen_ai/backend/routers/oauth.ts +0 -393
- package/templates/gen_ai/src/components/logged_in_status.tsx +0 -44
- package/templates/gen_ai/src/services/auth.tsx +0 -26
- package/templates/gen_ai/src/services/index.ts +0 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Oauth } from "@canva/user";
|
|
2
1
|
import { POLLING_INTERVAL_IN_SECONDS } from "src/config";
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -41,22 +40,12 @@ interface RemainingCreditsResult {
|
|
|
41
40
|
credits: number;
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
/**
|
|
45
|
-
* Represents the result of retrieving the logged in status of the user.
|
|
46
|
-
*/
|
|
47
|
-
export type LoggedInState =
|
|
48
|
-
| "authenticated"
|
|
49
|
-
| "not_authenticated"
|
|
50
|
-
| "checking"
|
|
51
|
-
| "error";
|
|
52
|
-
|
|
53
43
|
const endpoints = {
|
|
54
44
|
queueImageGeneration: "/api/queue-image-generation",
|
|
55
45
|
getImageGenerationJobStatus: "/api/job-status",
|
|
56
46
|
cancelImageGenerationJob: "/api/job-status/cancel",
|
|
57
47
|
getRemainingCredits: "/api/credits",
|
|
58
48
|
purchaseCredits: "/api/purchase-credits",
|
|
59
|
-
getLoggedInStatus: "/api/authentication/status",
|
|
60
49
|
};
|
|
61
50
|
|
|
62
51
|
/**
|
|
@@ -66,21 +55,18 @@ const endpoints = {
|
|
|
66
55
|
* @param {number} options.numberOfImages - The number of images to generate.
|
|
67
56
|
* @returns {Promise<QueueImageGenerationResponse>} A promise that resolves to the created job ID.
|
|
68
57
|
*/
|
|
69
|
-
export const queueImageGeneration = async (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
oauth: Oauth,
|
|
78
|
-
): Promise<QueueImageGenerationResponse> => {
|
|
58
|
+
export const queueImageGeneration = async ({
|
|
59
|
+
prompt,
|
|
60
|
+
numberOfImages,
|
|
61
|
+
}: {
|
|
62
|
+
prompt: string;
|
|
63
|
+
numberOfImages: number;
|
|
64
|
+
}): Promise<QueueImageGenerationResponse> => {
|
|
79
65
|
const url = new URL(endpoints.queueImageGeneration, BACKEND_HOST);
|
|
80
66
|
url.searchParams.append("count", numberOfImages.toString());
|
|
81
67
|
url.searchParams.append("prompt", prompt);
|
|
82
68
|
|
|
83
|
-
const result: QueueImageGenerationResponse = await sendRequest(url
|
|
69
|
+
const result: QueueImageGenerationResponse = await sendRequest(url);
|
|
84
70
|
|
|
85
71
|
return result;
|
|
86
72
|
};
|
|
@@ -90,14 +76,11 @@ export const queueImageGeneration = async (
|
|
|
90
76
|
* @param {string} jobId - The ID of the job to retrieve status for.
|
|
91
77
|
* @returns {Promise<ImageGenerationResult>} A promise that resolves to the image generation result.
|
|
92
78
|
*/
|
|
93
|
-
export const getImageGenerationJobStatus = async (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
99
|
-
oauth: Oauth,
|
|
100
|
-
): Promise<ImageGenerationResult> => {
|
|
79
|
+
export const getImageGenerationJobStatus = async ({
|
|
80
|
+
jobId,
|
|
81
|
+
}: {
|
|
82
|
+
jobId: string;
|
|
83
|
+
}): Promise<ImageGenerationResult> => {
|
|
101
84
|
const url = new URL(endpoints.getImageGenerationJobStatus, BACKEND_HOST);
|
|
102
85
|
url.searchParams.append("jobId", jobId);
|
|
103
86
|
|
|
@@ -109,7 +92,6 @@ export const getImageGenerationJobStatus = async (
|
|
|
109
92
|
try {
|
|
110
93
|
const response = (await sendRequest(
|
|
111
94
|
url,
|
|
112
|
-
oauth,
|
|
113
95
|
)) as ImageGenerationJobStatusResponse;
|
|
114
96
|
if (response.status === "completed") {
|
|
115
97
|
return { images: response.images, credits: response.credits };
|
|
@@ -138,13 +120,12 @@ export const getImageGenerationJobStatus = async (
|
|
|
138
120
|
*/
|
|
139
121
|
export const cancelImageGenerationJob = async (
|
|
140
122
|
jobId: string,
|
|
141
|
-
oauth: Oauth,
|
|
142
123
|
): Promise<void> => {
|
|
143
124
|
const url = new URL(endpoints.cancelImageGenerationJob, BACKEND_HOST);
|
|
144
125
|
url.searchParams.append("jobId", jobId);
|
|
145
126
|
|
|
146
127
|
try {
|
|
147
|
-
await sendRequest(url,
|
|
128
|
+
await sendRequest(url, {
|
|
148
129
|
method: "POST",
|
|
149
130
|
});
|
|
150
131
|
} catch {
|
|
@@ -156,26 +137,23 @@ export const cancelImageGenerationJob = async (
|
|
|
156
137
|
* Retrieves the remaining credits.
|
|
157
138
|
* @returns {Promise<RemainingCreditsResult>} - A promise that resolves to the remaining credits.
|
|
158
139
|
*/
|
|
159
|
-
export const getRemainingCredits =
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const url = new URL(endpoints.getRemainingCredits, BACKEND_HOST);
|
|
140
|
+
export const getRemainingCredits =
|
|
141
|
+
async (): Promise<RemainingCreditsResult> => {
|
|
142
|
+
const url = new URL(endpoints.getRemainingCredits, BACKEND_HOST);
|
|
163
143
|
|
|
164
|
-
|
|
144
|
+
const result: RemainingCreditsResult = await sendRequest(url);
|
|
165
145
|
|
|
166
|
-
|
|
167
|
-
};
|
|
146
|
+
return result;
|
|
147
|
+
};
|
|
168
148
|
|
|
169
149
|
/**
|
|
170
150
|
* Purchases credits for the user.
|
|
171
151
|
* @returns {Promise<RemainingCreditsResult>} - A promise that resolves to the remaining credits after purchasing.
|
|
172
152
|
*/
|
|
173
|
-
export const purchaseCredits = async (
|
|
174
|
-
oauth: Oauth,
|
|
175
|
-
): Promise<RemainingCreditsResult> => {
|
|
153
|
+
export const purchaseCredits = async (): Promise<RemainingCreditsResult> => {
|
|
176
154
|
const url = new URL(endpoints.purchaseCredits, BACKEND_HOST);
|
|
177
155
|
|
|
178
|
-
const result: RemainingCreditsResult = await sendRequest(url,
|
|
156
|
+
const result: RemainingCreditsResult = await sendRequest(url, {
|
|
179
157
|
method: "POST",
|
|
180
158
|
});
|
|
181
159
|
|
|
@@ -183,48 +161,15 @@ export const purchaseCredits = async (
|
|
|
183
161
|
};
|
|
184
162
|
|
|
185
163
|
/**
|
|
186
|
-
*
|
|
187
|
-
* This is example code, intended to convey the basic idea. When implementing this in your app, you might want more advanced checks.
|
|
188
|
-
*
|
|
189
|
-
* Note: You must register the provided endpoint via the Developer Portal.
|
|
190
|
-
*/
|
|
191
|
-
export const checkAuthenticationStatus = async (
|
|
192
|
-
oauth: Oauth,
|
|
193
|
-
): Promise<LoggedInState> => {
|
|
194
|
-
try {
|
|
195
|
-
const url = new URL(endpoints.getLoggedInStatus, BACKEND_HOST);
|
|
196
|
-
const result: { isAuthenticated: string } = await sendRequest(url, oauth, {
|
|
197
|
-
method: "POST",
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
if (result?.isAuthenticated) {
|
|
201
|
-
return "authenticated";
|
|
202
|
-
} else {
|
|
203
|
-
return "not_authenticated";
|
|
204
|
-
}
|
|
205
|
-
} catch (error) {
|
|
206
|
-
// eslint-disable-next-line no-console
|
|
207
|
-
console.error(error);
|
|
208
|
-
return "error";
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Sends a request to the specified URL with authorization headers.
|
|
164
|
+
* Sends a request to the specified URL.
|
|
214
165
|
* @param {URL} url - The URL to send the request to.
|
|
215
166
|
* @param {RequestInit} [options] - Optional fetch options to be passed to the fetch function.
|
|
216
167
|
* @returns {Promise<Object>} - A promise that resolves to the response body.
|
|
217
168
|
*/
|
|
218
|
-
const sendRequest = async <T>(
|
|
219
|
-
url: URL,
|
|
220
|
-
oauth: Oauth,
|
|
221
|
-
options?: RequestInit,
|
|
222
|
-
): Promise<T> => {
|
|
223
|
-
const token = (await oauth.getAccessToken())?.token;
|
|
169
|
+
const sendRequest = async <T>(url: URL, options?: RequestInit): Promise<T> => {
|
|
224
170
|
const res = await fetch(url, {
|
|
225
171
|
headers: {
|
|
226
172
|
...options?.headers,
|
|
227
|
-
Authorization: `Bearer ${token}`,
|
|
228
173
|
},
|
|
229
174
|
...options,
|
|
230
175
|
});
|
|
@@ -11,11 +11,6 @@ export const FooterMessages = defineMessages({
|
|
|
11
11
|
defaultMessage: "Generate image",
|
|
12
12
|
description: "A button label to generate an image from a prompt",
|
|
13
13
|
},
|
|
14
|
-
signUpOrLogin: {
|
|
15
|
-
defaultMessage: "Sign up or log in to generate",
|
|
16
|
-
description:
|
|
17
|
-
"A button label to sign up or log in, before the user is able to generate an image",
|
|
18
|
-
},
|
|
19
14
|
purchaseMoreCredits: {
|
|
20
15
|
defaultMessage: "Purchase more credits",
|
|
21
16
|
description:
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { useNavigate, useLocation } from "react-router-dom";
|
|
2
2
|
import { Rows, Button } from "@canva/app-ui-kit";
|
|
3
3
|
import { queueImageGeneration, purchaseCredits } from "src/api";
|
|
4
|
-
import {
|
|
4
|
+
import { RemainingCredits } from "src/components";
|
|
5
5
|
import { NUMBER_OF_IMAGES_TO_GENERATE } from "src/config";
|
|
6
6
|
import { useAppContext } from "src/context";
|
|
7
7
|
import { Paths } from "src/routes";
|
|
8
|
-
import { useAuth } from "src/services";
|
|
9
8
|
import { getObsceneWords } from "src/utils";
|
|
10
9
|
import { useIntl } from "react-intl";
|
|
11
10
|
import { FooterMessages as Messages } from "./footer.messages";
|
|
@@ -13,10 +12,8 @@ import { FooterMessages as Messages } from "./footer.messages";
|
|
|
13
12
|
export const Footer = () => {
|
|
14
13
|
const navigate = useNavigate();
|
|
15
14
|
const { pathname } = useLocation();
|
|
16
|
-
const { requestAuthentication } = useAuth();
|
|
17
15
|
const isRootRoute = pathname === Paths.HOME;
|
|
18
16
|
const {
|
|
19
|
-
loggedInState,
|
|
20
17
|
setAppError,
|
|
21
18
|
promptInput,
|
|
22
19
|
setPromptInput,
|
|
@@ -27,7 +24,6 @@ export const Footer = () => {
|
|
|
27
24
|
setIsLoadingImages,
|
|
28
25
|
remainingCredits,
|
|
29
26
|
setRemainingCredits,
|
|
30
|
-
oauth,
|
|
31
27
|
} = useAppContext();
|
|
32
28
|
const intl = useIntl();
|
|
33
29
|
|
|
@@ -75,13 +71,10 @@ export const Footer = () => {
|
|
|
75
71
|
|
|
76
72
|
setIsLoadingImages(true);
|
|
77
73
|
try {
|
|
78
|
-
const { jobId } = await queueImageGeneration(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
},
|
|
83
|
-
oauth,
|
|
84
|
-
);
|
|
74
|
+
const { jobId } = await queueImageGeneration({
|
|
75
|
+
prompt: promptInput,
|
|
76
|
+
numberOfImages: NUMBER_OF_IMAGES_TO_GENERATE,
|
|
77
|
+
});
|
|
85
78
|
|
|
86
79
|
setJobId(jobId);
|
|
87
80
|
} catch {
|
|
@@ -90,12 +83,8 @@ export const Footer = () => {
|
|
|
90
83
|
navigate(Paths.RESULTS);
|
|
91
84
|
};
|
|
92
85
|
|
|
93
|
-
const onSignUpOrLogInClick = async () => {
|
|
94
|
-
await requestAuthentication();
|
|
95
|
-
};
|
|
96
|
-
|
|
97
86
|
const onPurchaseMoreCredits = async () => {
|
|
98
|
-
const { credits } = await purchaseCredits(
|
|
87
|
+
const { credits } = await purchaseCredits();
|
|
99
88
|
|
|
100
89
|
setRemainingCredits(credits);
|
|
101
90
|
};
|
|
@@ -114,17 +103,11 @@ export const Footer = () => {
|
|
|
114
103
|
: intl.formatMessage(Messages.generateAgain),
|
|
115
104
|
visible: hasRemainingCredits,
|
|
116
105
|
},
|
|
117
|
-
{
|
|
118
|
-
variant: "primary" as const,
|
|
119
|
-
onClick: onSignUpOrLogInClick,
|
|
120
|
-
value: intl.formatMessage(Messages.signUpOrLogin),
|
|
121
|
-
visible: loggedInState === "not_authenticated" && !hasRemainingCredits,
|
|
122
|
-
},
|
|
123
106
|
{
|
|
124
107
|
variant: "primary" as const,
|
|
125
108
|
onClick: onPurchaseMoreCredits,
|
|
126
109
|
value: intl.formatMessage(Messages.purchaseMoreCredits),
|
|
127
|
-
visible:
|
|
110
|
+
visible: !hasRemainingCredits,
|
|
128
111
|
},
|
|
129
112
|
{
|
|
130
113
|
variant: "secondary" as const,
|
|
@@ -155,7 +138,6 @@ export const Footer = () => {
|
|
|
155
138
|
),
|
|
156
139
|
)}
|
|
157
140
|
<RemainingCredits />
|
|
158
|
-
<LoggedInStatus />
|
|
159
141
|
</Rows>
|
|
160
142
|
);
|
|
161
143
|
};
|
|
@@ -70,7 +70,6 @@ export const LoadingResults = ({
|
|
|
70
70
|
promptInput,
|
|
71
71
|
setGeneratedImages,
|
|
72
72
|
setRemainingCredits,
|
|
73
|
-
oauth,
|
|
74
73
|
} = useAppContext();
|
|
75
74
|
|
|
76
75
|
useEffect(() => {
|
|
@@ -83,12 +82,9 @@ export const LoadingResults = ({
|
|
|
83
82
|
const pollJobStatus = async () => {
|
|
84
83
|
if (jobId) {
|
|
85
84
|
try {
|
|
86
|
-
const { images, credits } = await getImageGenerationJobStatus(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
oauth,
|
|
91
|
-
);
|
|
85
|
+
const { images, credits } = await getImageGenerationJobStatus({
|
|
86
|
+
jobId,
|
|
87
|
+
});
|
|
92
88
|
setGeneratedImages(images);
|
|
93
89
|
setRemainingCredits(credits);
|
|
94
90
|
// Clear the jobId after fetching images
|
|
@@ -121,7 +117,7 @@ export const LoadingResults = ({
|
|
|
121
117
|
]);
|
|
122
118
|
|
|
123
119
|
const onCancelClick = async () => {
|
|
124
|
-
await cancelImageGenerationJob(jobId
|
|
120
|
+
await cancelImageGenerationJob(jobId);
|
|
125
121
|
setIsLoadingImages(false);
|
|
126
122
|
navigate(Paths.HOME);
|
|
127
123
|
};
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { createContext, useEffect, useState } from "react";
|
|
2
2
|
import { useIntl } from "react-intl";
|
|
3
|
-
import type { ImageType
|
|
4
|
-
import {
|
|
3
|
+
import type { ImageType } from "src/api";
|
|
4
|
+
import { getRemainingCredits } from "src/api";
|
|
5
5
|
import { ContextMessages as Messages } from "./context.messages";
|
|
6
|
-
import type { Oauth } from "@canva/user";
|
|
7
|
-
import { auth } from "@canva/user";
|
|
8
6
|
|
|
9
7
|
export interface AppContextType {
|
|
10
|
-
loggedInState: LoggedInState;
|
|
11
|
-
setLoggedInState: (value: LoggedInState) => void;
|
|
12
8
|
appError: string;
|
|
13
9
|
setAppError: (value: string) => void;
|
|
14
10
|
creditsError: string;
|
|
@@ -27,12 +23,9 @@ export interface AppContextType {
|
|
|
27
23
|
setPromptInputError: (value: string) => void;
|
|
28
24
|
generatedImages: ImageType[];
|
|
29
25
|
setGeneratedImages: (value: ImageType[]) => void;
|
|
30
|
-
oauth: Oauth;
|
|
31
26
|
}
|
|
32
27
|
|
|
33
28
|
export const AppContext = createContext<AppContextType>({
|
|
34
|
-
loggedInState: "not_authenticated",
|
|
35
|
-
setLoggedInState: () => {},
|
|
36
29
|
appError: "",
|
|
37
30
|
setAppError: () => {},
|
|
38
31
|
creditsError: "",
|
|
@@ -51,7 +44,6 @@ export const AppContext = createContext<AppContextType>({
|
|
|
51
44
|
setPromptInputError: () => {},
|
|
52
45
|
generatedImages: [] as ImageType[],
|
|
53
46
|
setGeneratedImages: () => {},
|
|
54
|
-
oauth: {} as Oauth,
|
|
55
47
|
});
|
|
56
48
|
|
|
57
49
|
/**
|
|
@@ -69,8 +61,6 @@ export const ContextProvider = ({
|
|
|
69
61
|
}: {
|
|
70
62
|
children: React.ReactNode;
|
|
71
63
|
}): JSX.Element => {
|
|
72
|
-
const [loggedInState, setLoggedInState] =
|
|
73
|
-
useState<LoggedInState>("not_authenticated");
|
|
74
64
|
const [appError, setAppError] = useState<string>("");
|
|
75
65
|
const [loadingApp, setLoadingApp] = useState<boolean>(true); // set to true to prevent ui flash on load
|
|
76
66
|
const [isLoadingImages, setIsLoadingImages] = useState<boolean>(false);
|
|
@@ -81,7 +71,6 @@ export const ContextProvider = ({
|
|
|
81
71
|
const [generatedImages, setGeneratedImages] = useState<ImageType[]>([]);
|
|
82
72
|
const [creditsError, setCreditsError] = useState<string>("");
|
|
83
73
|
const intl = useIntl();
|
|
84
|
-
const oauth = auth.initOauth();
|
|
85
74
|
|
|
86
75
|
// Fetches initial data on component mount
|
|
87
76
|
useEffect(() => {
|
|
@@ -91,7 +80,7 @@ export const ContextProvider = ({
|
|
|
91
80
|
|
|
92
81
|
// Fetch remaining credits
|
|
93
82
|
try {
|
|
94
|
-
const { credits } = await getRemainingCredits(
|
|
83
|
+
const { credits } = await getRemainingCredits();
|
|
95
84
|
setRemainingCredits(credits);
|
|
96
85
|
} catch (error) {
|
|
97
86
|
setAppError(
|
|
@@ -100,17 +89,6 @@ export const ContextProvider = ({
|
|
|
100
89
|
// eslint-disable-next-line no-console
|
|
101
90
|
console.error("Error fetching remaining credits:", error);
|
|
102
91
|
}
|
|
103
|
-
|
|
104
|
-
// Fetch login status
|
|
105
|
-
try {
|
|
106
|
-
checkAuthenticationStatus(oauth);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
setAppError(
|
|
109
|
-
intl.formatMessage(Messages.appErrorGetLoggedInStatusFailed),
|
|
110
|
-
);
|
|
111
|
-
// eslint-disable-next-line no-console
|
|
112
|
-
console.error("Error fetching login status:", error);
|
|
113
|
-
}
|
|
114
92
|
} catch (error) {
|
|
115
93
|
setAppError(intl.formatMessage(Messages.appErrorGeneral));
|
|
116
94
|
// eslint-disable-next-line no-console
|
|
@@ -130,13 +108,10 @@ export const ContextProvider = ({
|
|
|
130
108
|
return;
|
|
131
109
|
}
|
|
132
110
|
|
|
133
|
-
const errorMessage =
|
|
134
|
-
loggedInState === "authenticated"
|
|
135
|
-
? intl.formatMessage(Messages.alertNotEnoughCreditsLoggedIn)
|
|
136
|
-
: intl.formatMessage(Messages.alertNotEnoughCreditsLoggedOut);
|
|
111
|
+
const errorMessage = intl.formatMessage(Messages.alertNotEnoughCredits);
|
|
137
112
|
|
|
138
113
|
setCreditsError(errorMessage);
|
|
139
|
-
}, [loadingApp, remainingCredits
|
|
114
|
+
}, [loadingApp, remainingCredits]);
|
|
140
115
|
|
|
141
116
|
const setPromptInputHandler = (value: string) => {
|
|
142
117
|
if (
|
|
@@ -153,8 +128,6 @@ export const ContextProvider = ({
|
|
|
153
128
|
};
|
|
154
129
|
|
|
155
130
|
const value: AppContextType = {
|
|
156
|
-
loggedInState,
|
|
157
|
-
setLoggedInState,
|
|
158
131
|
appError,
|
|
159
132
|
setAppError,
|
|
160
133
|
creditsError,
|
|
@@ -173,7 +146,6 @@ export const ContextProvider = ({
|
|
|
173
146
|
setPromptInputError,
|
|
174
147
|
generatedImages,
|
|
175
148
|
setGeneratedImages,
|
|
176
|
-
oauth,
|
|
177
149
|
};
|
|
178
150
|
|
|
179
151
|
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
|
|
@@ -12,11 +12,6 @@ export const ContextMessages = defineMessages({
|
|
|
12
12
|
description:
|
|
13
13
|
"A message to indicate that there was a failure to get the number of credits the user has",
|
|
14
14
|
},
|
|
15
|
-
appErrorGetLoggedInStatusFailed: {
|
|
16
|
-
defaultMessage: "Retrieving logged in status has failed.",
|
|
17
|
-
description:
|
|
18
|
-
"A message to indicate that due to an unexpected problem, the app was unable to determine if the user is logged in",
|
|
19
|
-
},
|
|
20
15
|
|
|
21
16
|
/** Messages related to prompts and user input validation. */
|
|
22
17
|
promptMissingErrorMessage: {
|
|
@@ -26,16 +21,10 @@ export const ContextMessages = defineMessages({
|
|
|
26
21
|
},
|
|
27
22
|
|
|
28
23
|
/** Messages related to credits, including their availability and purchasing options. */
|
|
29
|
-
|
|
24
|
+
alertNotEnoughCredits: {
|
|
30
25
|
defaultMessage:
|
|
31
26
|
"You don’t have enough credits left to generate an image. Please purchase more.",
|
|
32
27
|
description:
|
|
33
28
|
"A message to indicate that the user doesn't have enough credits to generate an image, and will need to buy more to continue",
|
|
34
29
|
},
|
|
35
|
-
alertNotEnoughCreditsLoggedOut: {
|
|
36
|
-
defaultMessage:
|
|
37
|
-
"You don’t have enough credits left to generate an image. Please sign up or log in to purchase more.",
|
|
38
|
-
description:
|
|
39
|
-
"A message to indicate that the user doesn't have enough credits to generate an image, and will need to sign up or log in to buy more",
|
|
40
|
-
},
|
|
41
30
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "empty-template",
|
|
4
4
|
"description": "An empty Canva App",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"extract": "formatjs extract
|
|
6
|
+
"extract": "formatjs extract src/**/*.{ts,tsx} --out-file dist/messages_en.json",
|
|
7
7
|
"build": "webpack --config webpack.config.cjs --mode production && npm run extract",
|
|
8
8
|
"format": "prettier '**/*.{css,ts,tsx}' --no-config --write",
|
|
9
9
|
"format:check": "prettier '**/*.{css,ts,tsx}' --no-config --check --ignore-path",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"test:watch": "jest --watchAll"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@canva/app-ui-kit": "^4.
|
|
20
|
-
"@canva/app-i18n-kit": "^0.0
|
|
19
|
+
"@canva/app-ui-kit": "^4.2.0",
|
|
20
|
+
"@canva/app-i18n-kit": "^1.0.0",
|
|
21
21
|
"@canva/design": "^2.1.0",
|
|
22
22
|
"@canva/platform": "^2.0.0",
|
|
23
23
|
"@canva/error": "^2.0.0",
|
|
@@ -27,32 +27,32 @@
|
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@eslint/eslintrc": "3.1.0",
|
|
30
|
-
"@eslint/js": "9.
|
|
30
|
+
"@eslint/js": "9.12.0",
|
|
31
31
|
"@formatjs/cli": "6.2.12",
|
|
32
32
|
"@formatjs/ts-transformer": "3.13.14",
|
|
33
33
|
"@ngrok/ngrok": "1.4.1",
|
|
34
34
|
"@svgr/webpack": "8.1.0",
|
|
35
|
-
"@types/jest": "29.5.
|
|
35
|
+
"@types/jest": "29.5.13",
|
|
36
36
|
"@types/node": "20.10.0",
|
|
37
37
|
"@types/node-fetch": "2.6.11",
|
|
38
38
|
"@types/node-forge": "1.3.11",
|
|
39
39
|
"@types/nodemon": "1.19.6",
|
|
40
|
-
"@types/react": "18.3.
|
|
41
|
-
"@types/react-dom": "18.3.
|
|
40
|
+
"@types/react": "18.3.11",
|
|
41
|
+
"@types/react-dom": "18.3.1",
|
|
42
42
|
"@types/webpack-env": "1.18.5",
|
|
43
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
44
|
-
"@typescript-eslint/parser": "8.
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "8.9.0",
|
|
44
|
+
"@typescript-eslint/parser": "8.9.0",
|
|
45
45
|
"chalk": "4.1.2",
|
|
46
46
|
"cli-table3": "0.6.5",
|
|
47
47
|
"css-loader": "7.1.2",
|
|
48
48
|
"css-modules-typescript-loader": "4.0.1",
|
|
49
|
-
"cssnano": "7.0.
|
|
50
|
-
"debug": "4.3.
|
|
49
|
+
"cssnano": "7.0.6",
|
|
50
|
+
"debug": "4.3.7",
|
|
51
51
|
"dotenv": "16.4.5",
|
|
52
|
-
"eslint": "
|
|
53
|
-
"eslint-plugin-formatjs": "
|
|
54
|
-
"eslint-plugin-jest": "28.8.
|
|
55
|
-
"eslint-plugin-react": "7.
|
|
52
|
+
"eslint": "9.12.0",
|
|
53
|
+
"eslint-plugin-formatjs": "5.0.0",
|
|
54
|
+
"eslint-plugin-jest": "28.8.3",
|
|
55
|
+
"eslint-plugin-react": "7.37.1",
|
|
56
56
|
"jest": "29.7.0",
|
|
57
57
|
"mini-css-extract-plugin": "2.9.1",
|
|
58
58
|
"node-fetch": "3.3.2",
|
|
@@ -62,14 +62,14 @@
|
|
|
62
62
|
"prettier": "3.3.3",
|
|
63
63
|
"style-loader": "4.0.0",
|
|
64
64
|
"terser-webpack-plugin": "5.3.10",
|
|
65
|
-
"ts-jest": "29.2.
|
|
65
|
+
"ts-jest": "29.2.5",
|
|
66
66
|
"ts-loader": "9.5.1",
|
|
67
67
|
"ts-node": "10.9.2",
|
|
68
68
|
"typescript": "5.5.4",
|
|
69
69
|
"url-loader": "4.1.1",
|
|
70
|
-
"webpack": "5.
|
|
70
|
+
"webpack": "5.95.0",
|
|
71
71
|
"webpack-cli": "5.1.4",
|
|
72
|
-
"webpack-dev-server": "5.0
|
|
72
|
+
"webpack-dev-server": "5.1.0",
|
|
73
73
|
"yargs": "17.7.2"
|
|
74
74
|
}
|
|
75
75
|
}
|