@canva/cli 1.19.0 → 1.20.0

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.
Files changed (231) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +1 -9
  3. package/cli.js +408 -409
  4. package/package.json +1 -2
  5. package/templates/base/backend/base_backend/create.ts +0 -114
  6. package/templates/base/backend/database/database.ts +0 -42
  7. package/templates/base/backend/routers/auth.ts +0 -288
  8. package/templates/base/declarations/declarations.d.ts +0 -29
  9. package/templates/base/eslint.config.mjs +0 -14
  10. package/templates/base/package.json +0 -91
  11. package/templates/base/scripts/copy_env.ts +0 -13
  12. package/templates/base/scripts/ssl/ssl.ts +0 -131
  13. package/templates/base/scripts/start/app_runner.ts +0 -223
  14. package/templates/base/scripts/start/context.ts +0 -171
  15. package/templates/base/scripts/start/start.ts +0 -46
  16. package/templates/base/scripts/start.tests.ts +0 -61
  17. package/templates/base/styles/components.css +0 -38
  18. package/templates/base/tsconfig.json +0 -56
  19. package/templates/base/webpack.config.ts +0 -247
  20. package/templates/common/.env.template +0 -6
  21. package/templates/common/.gitignore.template +0 -8
  22. package/templates/common/.nvmrc +0 -1
  23. package/templates/common/.prettierrc +0 -21
  24. package/templates/common/LICENSE.md +0 -48
  25. package/templates/common/README.md +0 -179
  26. package/templates/common/jest.config.mjs +0 -35
  27. package/templates/common/jest.setup.ts +0 -35
  28. package/templates/content_publisher/README.md +0 -58
  29. package/templates/content_publisher/canva-app.json +0 -17
  30. package/templates/content_publisher/declarations/declarations.d.ts +0 -29
  31. package/templates/content_publisher/eslint.config.mjs +0 -14
  32. package/templates/content_publisher/package.json +0 -90
  33. package/templates/content_publisher/scripts/copy_env.ts +0 -13
  34. package/templates/content_publisher/scripts/ssl/ssl.ts +0 -131
  35. package/templates/content_publisher/scripts/start/app_runner.ts +0 -223
  36. package/templates/content_publisher/scripts/start/context.ts +0 -171
  37. package/templates/content_publisher/scripts/start/start.ts +0 -46
  38. package/templates/content_publisher/src/index.tsx +0 -4
  39. package/templates/content_publisher/src/intents/content_publisher/index.tsx +0 -107
  40. package/templates/content_publisher/src/intents/content_publisher/post_preview.tsx +0 -240
  41. package/templates/content_publisher/src/intents/content_publisher/preview_ui.tsx +0 -62
  42. package/templates/content_publisher/src/intents/content_publisher/settings_ui.tsx +0 -81
  43. package/templates/content_publisher/src/intents/content_publisher/types.ts +0 -29
  44. package/templates/content_publisher/styles/components.css +0 -38
  45. package/templates/content_publisher/styles/preview_ui.css +0 -49
  46. package/templates/content_publisher/tsconfig.json +0 -56
  47. package/templates/content_publisher/webpack.config.ts +0 -247
  48. package/templates/dam/backend/routers/dam.ts +0 -108
  49. package/templates/dam/backend/server.ts +0 -65
  50. package/templates/dam/canva-app.json +0 -25
  51. package/templates/dam/declarations/declarations.d.ts +0 -29
  52. package/templates/dam/eslint.config.mjs +0 -14
  53. package/templates/dam/package.json +0 -97
  54. package/templates/dam/scripts/copy_env.ts +0 -13
  55. package/templates/dam/scripts/ssl/ssl.ts +0 -131
  56. package/templates/dam/scripts/start/app_runner.ts +0 -223
  57. package/templates/dam/scripts/start/context.ts +0 -171
  58. package/templates/dam/scripts/start/start.ts +0 -46
  59. package/templates/dam/src/index.tsx +0 -4
  60. package/templates/dam/src/intents/design_editor/adapter.ts +0 -44
  61. package/templates/dam/src/intents/design_editor/app.tsx +0 -35
  62. package/templates/dam/src/intents/design_editor/config.ts +0 -220
  63. package/templates/dam/src/intents/design_editor/index.css +0 -3
  64. package/templates/dam/src/intents/design_editor/index.tsx +0 -25
  65. package/templates/dam/tsconfig.json +0 -56
  66. package/templates/dam/utils/backend/base_backend/create.ts +0 -114
  67. package/templates/dam/webpack.config.ts +0 -247
  68. package/templates/data_connector/README.md +0 -84
  69. package/templates/data_connector/canva-app.json +0 -21
  70. package/templates/data_connector/declarations/declarations.d.ts +0 -29
  71. package/templates/data_connector/eslint.config.mjs +0 -14
  72. package/templates/data_connector/package.json +0 -92
  73. package/templates/data_connector/scripts/copy_env.ts +0 -13
  74. package/templates/data_connector/scripts/ssl/ssl.ts +0 -131
  75. package/templates/data_connector/scripts/start/app_runner.ts +0 -223
  76. package/templates/data_connector/scripts/start/context.ts +0 -171
  77. package/templates/data_connector/scripts/start/start.ts +0 -46
  78. package/templates/data_connector/src/api/connect_client.ts +0 -6
  79. package/templates/data_connector/src/api/data_source.ts +0 -97
  80. package/templates/data_connector/src/api/data_sources/designs.tsx +0 -296
  81. package/templates/data_connector/src/api/data_sources/index.ts +0 -4
  82. package/templates/data_connector/src/api/data_sources/templates.tsx +0 -328
  83. package/templates/data_connector/src/api/fetch_data_table.ts +0 -55
  84. package/templates/data_connector/src/api/index.ts +0 -4
  85. package/templates/data_connector/src/api/oauth.ts +0 -8
  86. package/templates/data_connector/src/api/tests/data_source.test.tsx +0 -99
  87. package/templates/data_connector/src/components/app_error.tsx +0 -15
  88. package/templates/data_connector/src/components/footer.tsx +0 -26
  89. package/templates/data_connector/src/components/header.tsx +0 -40
  90. package/templates/data_connector/src/components/index.ts +0 -3
  91. package/templates/data_connector/src/components/inputs/messages.tsx +0 -95
  92. package/templates/data_connector/src/components/inputs/search_filter.tsx +0 -109
  93. package/templates/data_connector/src/components/inputs/select_field.tsx +0 -26
  94. package/templates/data_connector/src/context/app_context.tsx +0 -125
  95. package/templates/data_connector/src/context/index.ts +0 -2
  96. package/templates/data_connector/src/context/use_app_context.ts +0 -17
  97. package/templates/data_connector/src/index.tsx +0 -4
  98. package/templates/data_connector/src/intents/data_connector/app.tsx +0 -20
  99. package/templates/data_connector/src/intents/data_connector/entrypoint.tsx +0 -70
  100. package/templates/data_connector/src/intents/data_connector/home.tsx +0 -21
  101. package/templates/data_connector/src/intents/data_connector/index.tsx +0 -56
  102. package/templates/data_connector/src/pages/data_source_config.tsx +0 -9
  103. package/templates/data_connector/src/pages/error.tsx +0 -37
  104. package/templates/data_connector/src/pages/index.ts +0 -4
  105. package/templates/data_connector/src/pages/login.tsx +0 -145
  106. package/templates/data_connector/src/pages/select_source.tsx +0 -24
  107. package/templates/data_connector/src/routes/index.ts +0 -2
  108. package/templates/data_connector/src/routes/paths.ts +0 -7
  109. package/templates/data_connector/src/routes/protected_route.tsx +0 -26
  110. package/templates/data_connector/src/routes/routes.tsx +0 -42
  111. package/templates/data_connector/src/utils/data_params.ts +0 -17
  112. package/templates/data_connector/src/utils/data_table.ts +0 -116
  113. package/templates/data_connector/src/utils/fetch_result.ts +0 -36
  114. package/templates/data_connector/src/utils/index.ts +0 -2
  115. package/templates/data_connector/src/utils/tests/data_table.test.ts +0 -133
  116. package/templates/data_connector/styles/components.css +0 -38
  117. package/templates/data_connector/tsconfig.json +0 -56
  118. package/templates/data_connector/webpack.config.ts +0 -247
  119. package/templates/gen_ai/README.md +0 -27
  120. package/templates/gen_ai/backend/routers/image.ts +0 -232
  121. package/templates/gen_ai/backend/server.ts +0 -65
  122. package/templates/gen_ai/canva-app.json +0 -25
  123. package/templates/gen_ai/declarations/declarations.d.ts +0 -29
  124. package/templates/gen_ai/eslint.config.mjs +0 -14
  125. package/templates/gen_ai/package.json +0 -101
  126. package/templates/gen_ai/scripts/copy_env.ts +0 -13
  127. package/templates/gen_ai/scripts/ssl/ssl.ts +0 -131
  128. package/templates/gen_ai/scripts/start/app_runner.ts +0 -223
  129. package/templates/gen_ai/scripts/start/context.ts +0 -171
  130. package/templates/gen_ai/scripts/start/start.ts +0 -46
  131. package/templates/gen_ai/src/api/api.ts +0 -194
  132. package/templates/gen_ai/src/api/index.ts +0 -1
  133. package/templates/gen_ai/src/components/app_error.tsx +0 -18
  134. package/templates/gen_ai/src/components/footer.messages.ts +0 -48
  135. package/templates/gen_ai/src/components/footer.tsx +0 -156
  136. package/templates/gen_ai/src/components/image_grid.tsx +0 -103
  137. package/templates/gen_ai/src/components/index.ts +0 -7
  138. package/templates/gen_ai/src/components/loading_results.tsx +0 -169
  139. package/templates/gen_ai/src/components/prompt_input.messages.ts +0 -14
  140. package/templates/gen_ai/src/components/prompt_input.tsx +0 -154
  141. package/templates/gen_ai/src/components/remaining_credits.tsx +0 -84
  142. package/templates/gen_ai/src/components/report_box.tsx +0 -54
  143. package/templates/gen_ai/src/components/tests/remaining_credit.tests.tsx +0 -47
  144. package/templates/gen_ai/src/config.ts +0 -21
  145. package/templates/gen_ai/src/context/app_context.tsx +0 -153
  146. package/templates/gen_ai/src/context/context.messages.ts +0 -30
  147. package/templates/gen_ai/src/context/index.ts +0 -2
  148. package/templates/gen_ai/src/context/use_app_context.ts +0 -17
  149. package/templates/gen_ai/src/index.tsx +0 -4
  150. package/templates/gen_ai/src/intents/design_editor/app.tsx +0 -19
  151. package/templates/gen_ai/src/intents/design_editor/home.tsx +0 -13
  152. package/templates/gen_ai/src/intents/design_editor/index.tsx +0 -17
  153. package/templates/gen_ai/src/pages/error.tsx +0 -41
  154. package/templates/gen_ai/src/pages/generate.tsx +0 -9
  155. package/templates/gen_ai/src/pages/index.ts +0 -3
  156. package/templates/gen_ai/src/pages/results.tsx +0 -31
  157. package/templates/gen_ai/src/routes/index.ts +0 -1
  158. package/templates/gen_ai/src/routes/paths.ts +0 -4
  159. package/templates/gen_ai/src/routes/routes.tsx +0 -24
  160. package/templates/gen_ai/src/utils/index.ts +0 -1
  161. package/templates/gen_ai/src/utils/obscenity_filter.ts +0 -33
  162. package/templates/gen_ai/styles/components.css +0 -38
  163. package/templates/gen_ai/styles/utils.css +0 -3
  164. package/templates/gen_ai/tsconfig.json +0 -56
  165. package/templates/gen_ai/utils/backend/base_backend/create.ts +0 -114
  166. package/templates/gen_ai/webpack.config.ts +0 -247
  167. package/templates/hello_world/canva-app.json +0 -21
  168. package/templates/hello_world/declarations/declarations.d.ts +0 -29
  169. package/templates/hello_world/eslint.config.mjs +0 -14
  170. package/templates/hello_world/package.json +0 -90
  171. package/templates/hello_world/scripts/copy_env.ts +0 -13
  172. package/templates/hello_world/scripts/ssl/ssl.ts +0 -131
  173. package/templates/hello_world/scripts/start/app_runner.ts +0 -223
  174. package/templates/hello_world/scripts/start/context.ts +0 -171
  175. package/templates/hello_world/scripts/start/start.ts +0 -46
  176. package/templates/hello_world/src/index.tsx +0 -4
  177. package/templates/hello_world/src/intents/design_editor/app.tsx +0 -86
  178. package/templates/hello_world/src/intents/design_editor/index.tsx +0 -25
  179. package/templates/hello_world/src/intents/design_editor/tests/__snapshots__/app.tests.tsx.snap +0 -45
  180. package/templates/hello_world/src/intents/design_editor/tests/app.tests.tsx +0 -92
  181. package/templates/hello_world/styles/components.css +0 -38
  182. package/templates/hello_world/tsconfig.json +0 -56
  183. package/templates/hello_world/webpack.config.ts +0 -247
  184. package/templates/mls/README.md +0 -81
  185. package/templates/mls/canva-app.json +0 -25
  186. package/templates/mls/declarations/declarations.d.ts +0 -29
  187. package/templates/mls/eslint.config.mjs +0 -14
  188. package/templates/mls/jest.config.mjs +0 -36
  189. package/templates/mls/jest.setup.ts +0 -39
  190. package/templates/mls/package.json +0 -117
  191. package/templates/mls/scripts/copy_env.ts +0 -13
  192. package/templates/mls/scripts/ssl/ssl.ts +0 -131
  193. package/templates/mls/scripts/start/app_runner.ts +0 -223
  194. package/templates/mls/scripts/start/context.ts +0 -171
  195. package/templates/mls/scripts/start/start.ts +0 -46
  196. package/templates/mls/src/__tests__/app.tests.tsx +0 -11
  197. package/templates/mls/src/__tests__/office_selection_page.tests.tsx +0 -72
  198. package/templates/mls/src/__tests__/utils.tsx +0 -19
  199. package/templates/mls/src/adapter.ts +0 -126
  200. package/templates/mls/src/components/agent/agent_card.tsx +0 -57
  201. package/templates/mls/src/components/agent/agent_grid.tsx +0 -37
  202. package/templates/mls/src/components/agent/agent_list.tsx +0 -17
  203. package/templates/mls/src/components/agent/agent_search_filters.tsx +0 -88
  204. package/templates/mls/src/components/breadcrumb/breadcrumb.tsx +0 -40
  205. package/templates/mls/src/components/listing/listing_card.tsx +0 -64
  206. package/templates/mls/src/components/listing/listing_grid.tsx +0 -37
  207. package/templates/mls/src/components/listing/listing_list.tsx +0 -21
  208. package/templates/mls/src/components/listing/listing_search_filters.tsx +0 -145
  209. package/templates/mls/src/components/placeholders/placeholders.tsx +0 -65
  210. package/templates/mls/src/data.ts +0 -359
  211. package/templates/mls/src/index.tsx +0 -4
  212. package/templates/mls/src/intents/design_editor/app.tsx +0 -44
  213. package/templates/mls/src/intents/design_editor/index.tsx +0 -25
  214. package/templates/mls/src/pages/agent_details_page/agent_details_page.tsx +0 -175
  215. package/templates/mls/src/pages/list_page/agent_tab_panel.tsx +0 -126
  216. package/templates/mls/src/pages/list_page/list_page.tsx +0 -67
  217. package/templates/mls/src/pages/list_page/listing_tab_panel.tsx +0 -135
  218. package/templates/mls/src/pages/listing_details_page/listing_details_page.tsx +0 -418
  219. package/templates/mls/src/pages/loading_page/loading_page.tsx +0 -152
  220. package/templates/mls/src/pages/office_selection_page/office_selection_page.tsx +0 -144
  221. package/templates/mls/src/real_estate.type.ts +0 -44
  222. package/templates/mls/src/util/use_add_element.tsx +0 -62
  223. package/templates/mls/src/util/use_drag_element.tsx +0 -68
  224. package/templates/mls/styles/components.css +0 -38
  225. package/templates/mls/tsconfig.json +0 -54
  226. package/templates/mls/webpack.config.ts +0 -248
  227. package/templates/optional/.cursor/mcp.json +0 -8
  228. package/templates/optional/.vscode/extensions.json +0 -6
  229. package/templates/optional/.vscode/mcp.json +0 -9
  230. package/templates/optional/AGENTS.md +0 -154
  231. package/templates/optional/CLAUDE.md +0 -154
@@ -1,81 +0,0 @@
1
- import { FormField, Rows, Text, TextInput } from "@canva/app-ui-kit";
2
- import type {
3
- PublishRefValidityState,
4
- PublishSettingsSettingsUiContext,
5
- RenderSettingsUiRequest,
6
- } from "@canva/intents/content";
7
- import { useCallback, useEffect, useState } from "react";
8
- import { useIntl } from "react-intl";
9
- import * as styles from "styles/components.css";
10
- import type { PublishSettings } from "./types";
11
-
12
- // Settings UI component for configuring publish settings
13
- export const SettingsUi = ({
14
- updatePublishSettings,
15
- registerOnContextChange,
16
- }: RenderSettingsUiRequest) => {
17
- const intl = useIntl();
18
- const [settings, setSettings] = useState<PublishSettings>({ caption: "" });
19
- const [settingsUiContext, setSettingsUiContext] =
20
- useState<PublishSettingsSettingsUiContext | null>(null);
21
-
22
- // Listen for settings UI context changes (e.g., when output type changes)
23
- useEffect(() => {
24
- const dispose = registerOnContextChange({
25
- onContextChange: (context) => {
26
- if (context.reason !== "publish_settings") return;
27
- setSettingsUiContext(context);
28
- },
29
- });
30
- return dispose;
31
- }, [registerOnContextChange]);
32
-
33
- // Helper function to both set the settings locally and propagate them to Canva
34
- const setAndPropagateSettings = useCallback(
35
- (updatedSettings: PublishSettings) => {
36
- setSettings(updatedSettings);
37
- updatePublishSettings({
38
- publishRef: JSON.stringify(updatedSettings),
39
- validityState: validatePublishRef(updatedSettings),
40
- });
41
- },
42
- [updatePublishSettings],
43
- );
44
-
45
- return (
46
- <div className={styles.scrollContainer}>
47
- <Rows spacing="2u">
48
- {settingsUiContext?.outputType.displayName && (
49
- <Text>{settingsUiContext?.outputType.displayName}</Text>
50
- )}
51
- <FormField
52
- label={intl.formatMessage({
53
- defaultMessage: "Caption",
54
- description: "Label for the caption input field",
55
- })}
56
- control={(props) => (
57
- <TextInput
58
- {...props}
59
- value={settings.caption}
60
- onChange={(caption) => {
61
- setAndPropagateSettings({ ...settings, caption });
62
- }}
63
- />
64
- )}
65
- />
66
- </Rows>
67
- </div>
68
- );
69
- };
70
-
71
- // Validates the publish settings to enable/disable the publish button
72
- // Returns "valid" when all required fields are filled
73
- const validatePublishRef = (
74
- publishRef: PublishSettings,
75
- ): PublishRefValidityState => {
76
- // caption is required
77
- if (publishRef.caption.length === 0) {
78
- return "invalid_missing_required_fields";
79
- }
80
- return "valid";
81
- };
@@ -1,29 +0,0 @@
1
- /**
2
- * Type definition for publish settings.
3
- * These settings are serialized and passed between different parts of the publish flow.
4
- * In production, include all platform-specific settings needed for publishing.
5
- */
6
- export interface PublishSettings {
7
- caption: string;
8
- // TODO: Add additional fields for your platform's publishing requirements
9
- // Examples:
10
- // scheduledTime: Date;
11
- // visibility: "public" | "private" | "unlisted";
12
- // tags: string[];
13
- }
14
-
15
- /**
16
- * Utility function to safely parse publish settings from a JSON string.
17
- * This is used to deserialize settings that were passed through the publish flow.
18
- */
19
- export function parsePublishSettings(
20
- publishRef?: string,
21
- ): PublishSettings | undefined {
22
- if (!publishRef) return undefined;
23
-
24
- try {
25
- return JSON.parse(publishRef) as PublishSettings;
26
- } catch {
27
- return undefined;
28
- }
29
- }
@@ -1,38 +0,0 @@
1
- /* Scroll container */
2
- .scrollContainer {
3
- box-sizing: border-box;
4
- overflow-y: scroll;
5
- height: 100%;
6
- padding-top: var(--ui-kit-space-200);
7
- padding-right: var(--ui-kit-space-200);
8
- padding-bottom: var(--ui-kit-space-200);
9
-
10
- /* for firefox */
11
- scrollbar-width: thin;
12
- scrollbar-color: var(--ui-kit-color-content-placeholder-fg) transparent;
13
- }
14
-
15
- .scrollContainer::-webkit-scrollbar {
16
- position: absolute;
17
- width: var(--ui-kit-base-unit);
18
- height: 0;
19
- }
20
-
21
- .scrollContainer::-webkit-scrollbar-track {
22
- background: transparent;
23
- width: var(--ui-kit-base-unit);
24
- margin-top: var(--ui-kit-space-100);
25
- margin-bottom: var(--ui-kit-space-100);
26
- }
27
-
28
- .scrollContainer::-webkit-scrollbar-thumb {
29
- border-radius: var(--ui-kit-radius-element-standard);
30
- background: var(--ui-kit-color-content-placeholder-fg);
31
- visibility: hidden;
32
- }
33
-
34
- .scrollContainer:hover::-webkit-scrollbar-thumb,
35
- .scrollContainer:focus::-webkit-scrollbar-thumb,
36
- .scrollContainer:focus-within::-webkit-scrollbar-thumb {
37
- visibility: visible;
38
- }
@@ -1,49 +0,0 @@
1
- /* Scale down preview on mobile devices */
2
- @media (max-width: 600px) {
3
- .container {
4
- transform: scale(0.3);
5
- }
6
- }
7
-
8
- /* User profile section styling */
9
- .user {
10
- display: flex;
11
- align-items: center;
12
- gap: 8px;
13
- }
14
-
15
- /* Avatar styling to match social media appearance */
16
- .avatar {
17
- transform: scale(0.6);
18
- width: 24px;
19
- height: 24px;
20
- transform-origin: top left;
21
- }
22
-
23
- /* Text placeholder for loading states */
24
- .textPlaceholder {
25
- min-width: calc(8 * 20);
26
- }
27
-
28
- /* Container for media images */
29
- .imageContainer {
30
- overflow: hidden; /* Enable border radius */
31
- }
32
-
33
- /* Row containing all images */
34
- .imageRow {
35
- overflow-y: hidden;
36
- overflow-x: auto;
37
- height: 400px;
38
- display: flex;
39
- }
40
-
41
- /* Individual image and placeholder styling */
42
- .imagePlaceholder,
43
- .image {
44
- width: 400px;
45
- height: 400px;
46
- object-fit: cover;
47
- display: inline-block;
48
- position: relative;
49
- }
@@ -1,56 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "jsx": "react-jsx",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "es2018",
8
- "es2019.array",
9
- "es2019.object",
10
- "es2019.string",
11
- "es2020.promise",
12
- "es2020.string"
13
- ],
14
- "types": ["node", "webpack-env", "jest"],
15
- "composite": false,
16
- "declaration": false,
17
- "declarationMap": false,
18
- "experimentalDecorators": true,
19
- "importHelpers": true,
20
- "noImplicitOverride": true,
21
- "moduleResolution": "bundler",
22
- "esModuleInterop": true,
23
- "rootDir": ".",
24
- "outDir": "dist",
25
- "strict": true,
26
- "skipLibCheck": true,
27
- "target": "ES2019",
28
- "sourceMap": true,
29
- "inlineSources": true,
30
- "module": "ESNext",
31
- "noImplicitAny": true,
32
- "noImplicitReturns": true,
33
- "noFallthroughCasesInSwitch": true,
34
- "noUncheckedIndexedAccess": true,
35
- "removeComments": true,
36
- "preserveConstEnums": true,
37
- "allowSyntheticDefaultImports": true,
38
- "baseUrl": "./",
39
- "paths": {
40
- "styles": ["./styles"]
41
- }
42
- },
43
- "include": [
44
- "./src/**/*",
45
- "./backend/**/*",
46
- "./utils/**/*",
47
- "./scripts/**/*",
48
- "./declarations/declarations.d.ts",
49
- "./styles/**/*"
50
- ],
51
- "ts-node": {
52
- "compilerOptions": {
53
- "module": "commonjs"
54
- }
55
- }
56
- }
@@ -1,247 +0,0 @@
1
- import type { Configuration } from "webpack";
2
- import { DefinePlugin, optimize } from "webpack";
3
- import path from "path";
4
- import TerserPlugin from "terser-webpack-plugin";
5
- import { transform } from "@formatjs/ts-transformer";
6
- import chalk from "chalk";
7
- import { config } from "dotenv";
8
- import { Configuration as DevServerConfiguration } from "webpack-dev-server";
9
-
10
- config();
11
-
12
- type DevConfig = {
13
- port: number;
14
- enableHmr: boolean;
15
- enableHttps: boolean;
16
- appOrigin?: string;
17
- appId?: string; // Deprecated in favour of appOrigin
18
- certFile?: string;
19
- keyFile?: string;
20
- };
21
-
22
- export function buildConfig({
23
- devConfig,
24
- appEntry = path.join(process.cwd(), "src", "index.tsx"),
25
- backendHost = process.env.CANVA_BACKEND_HOST,
26
- // For IN_HARNESS, refer to the following docs for more information: https://www.canva.dev/docs/apps/test-harness/
27
- inHarness = process.env.IN_HARNESS?.toLowerCase() === "true",
28
- }: {
29
- devConfig?: DevConfig;
30
- appEntry?: string;
31
- backendHost?: string;
32
- inHarness?: boolean;
33
- } = {}): Configuration & DevServerConfiguration {
34
- const mode = devConfig ? "development" : "production";
35
-
36
- if (!backendHost) {
37
- console.warn(
38
- chalk.yellow.bold("BACKEND_HOST is undefined."),
39
- `If your app requires a backend, refer to "Customizing the backend host" in the README.md for more information.`,
40
- );
41
- } else if (backendHost.includes("localhost") && mode === "production") {
42
- console.error(
43
- chalk.redBright.bold(
44
- "BACKEND_HOST should not be set to localhost for production builds!",
45
- ),
46
- `Refer to "Customizing the backend host" in the README.md for more information.`,
47
- );
48
- }
49
-
50
- return {
51
- mode,
52
- context: path.resolve(process.cwd(), "./"),
53
- entry: inHarness
54
- ? {
55
- harness: path.join(process.cwd(), "harness", "harness.tsx"),
56
- init: path.join(process.cwd(), "harness", "init.ts"),
57
- }
58
- : {
59
- app: appEntry,
60
- },
61
- target: "web",
62
- resolve: {
63
- alias: {
64
- styles: path.resolve(process.cwd(), "styles"),
65
- src: path.resolve(process.cwd(), "src"),
66
- },
67
- extensions: [".ts", ".tsx", ".js", ".css", ".svg", ".woff", ".woff2"],
68
- },
69
- infrastructureLogging: {
70
- level: inHarness ? "info" : "none",
71
- },
72
- module: {
73
- rules: [
74
- {
75
- test: /\.tsx?$/,
76
- exclude: /node_modules/,
77
- use: [
78
- {
79
- loader: "ts-loader",
80
- options: {
81
- transpileOnly: true,
82
- getCustomTransformers() {
83
- return {
84
- before: [
85
- transform({
86
- overrideIdFn: "[sha512:contenthash:base64:6]",
87
- }),
88
- ],
89
- };
90
- },
91
- },
92
- },
93
- ],
94
- },
95
- {
96
- test: /\.css$/,
97
- exclude: /node_modules/,
98
- use: [
99
- "style-loader",
100
- {
101
- loader: "css-loader",
102
- options: {
103
- modules: true,
104
- },
105
- },
106
- {
107
- loader: "postcss-loader",
108
- options: {
109
- postcssOptions: {
110
- plugins: [require("cssnano")({ preset: "default" })],
111
- },
112
- },
113
- },
114
- ],
115
- },
116
- {
117
- test: /\.(png|jpg|jpeg)$/i,
118
- type: "asset/inline",
119
- },
120
- {
121
- test: /\.(woff|woff2)$/,
122
- type: "asset/inline",
123
- },
124
- {
125
- test: /\.svg$/,
126
- oneOf: [
127
- {
128
- issuer: /\.[jt]sx?$/,
129
- resourceQuery: /react/, // *.svg?react
130
- use: ["@svgr/webpack", "url-loader"],
131
- },
132
- {
133
- type: "asset/resource",
134
- parser: {
135
- dataUrlCondition: {
136
- maxSize: 200,
137
- },
138
- },
139
- },
140
- ],
141
- },
142
- {
143
- test: /\.css$/,
144
- include: /node_modules/,
145
- use: [
146
- "style-loader",
147
- "css-loader",
148
- {
149
- loader: "postcss-loader",
150
- options: {
151
- postcssOptions: {
152
- plugins: [require("cssnano")({ preset: "default" })],
153
- },
154
- },
155
- },
156
- ],
157
- },
158
- ],
159
- },
160
- optimization: {
161
- minimizer: [
162
- new TerserPlugin({
163
- terserOptions: {
164
- format: {
165
- // Turned on because emoji and regex is not minified properly using default
166
- // https://github.com/facebook/create-react-app/issues/2488
167
- ascii_only: true,
168
- },
169
- },
170
- }),
171
- ],
172
- },
173
- output: {
174
- filename: `[name].js`,
175
- path: path.resolve(process.cwd(), "dist"),
176
- clean: true,
177
- },
178
- plugins: [
179
- new DefinePlugin({
180
- BACKEND_HOST: JSON.stringify(backendHost),
181
- }),
182
- // Apps can only submit a single JS file via the Developer Portal
183
- new optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
184
- ].filter(Boolean),
185
- ...buildDevConfig(devConfig),
186
- };
187
- }
188
-
189
- function buildDevConfig(options?: DevConfig): {
190
- devtool?: string;
191
- devServer?: DevServerConfiguration;
192
- } {
193
- if (!options) {
194
- return {};
195
- }
196
-
197
- const { port, enableHmr, appOrigin, enableHttps, certFile, keyFile } =
198
- options;
199
- const host = "localhost";
200
-
201
- let devServer: DevServerConfiguration = {
202
- server: enableHttps
203
- ? {
204
- type: "https",
205
- options: {
206
- cert: certFile,
207
- key: keyFile,
208
- },
209
- }
210
- : "http",
211
- host,
212
- allowedHosts: [host],
213
- historyApiFallback: {
214
- rewrites: [{ from: /^\/$/, to: "/app.js" }],
215
- },
216
- port,
217
- client: {
218
- logging: "verbose",
219
- },
220
- };
221
-
222
- if (enableHmr && appOrigin) {
223
- devServer = {
224
- ...devServer,
225
- allowedHosts: [host, new URL(appOrigin).hostname],
226
- headers: {
227
- "Access-Control-Allow-Origin": appOrigin,
228
- "Access-Control-Allow-Credentials": "true",
229
- "Access-Control-Allow-Private-Network": "true",
230
- },
231
- };
232
- } else {
233
- if (enableHmr && !appOrigin) {
234
- console.warn(
235
- "Attempted to enable Hot Module Replacement (HMR) without configuring App Origin... Disabling HMR.",
236
- );
237
- }
238
- devServer.webSocketServer = false;
239
- }
240
-
241
- return {
242
- devtool: "source-map",
243
- devServer,
244
- };
245
- }
246
-
247
- export default buildConfig;
@@ -1,108 +0,0 @@
1
- import type { Container, Resource } from "@canva/app-components";
2
- import crypto from "crypto";
3
- import express from "express";
4
-
5
- /**
6
- * Generates a unique hash for a URL.
7
- * Used for creating unique identifiers for digital assets from external URLs.
8
- */
9
- export async function generateHash(message: string) {
10
- const msgUint8 = new TextEncoder().encode(message);
11
- const hashBuffer = await crypto.subtle.digest("SHA-256", msgUint8);
12
- const hashArray = Array.from(new Uint8Array(hashBuffer));
13
- const hashHex = hashArray
14
- .map((b) => b.toString(16).padStart(2, "0"))
15
- .join("");
16
- return hashHex;
17
- }
18
-
19
- // Mock image URLs for demonstration purposes - replace with your actual digital asset sources
20
- const imageUrls = [
21
- "https://images.pexels.com/photos/1495580/pexels-photo-1495580.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
22
- "https://images.pexels.com/photos/3943197/pexels-photo-3943197.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
23
- "https://images.pexels.com/photos/7195267/pexels-photo-7195267.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
24
- "https://images.pexels.com/photos/2904142/pexels-photo-2904142.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
25
- "https://images.pexels.com/photos/5403478/pexels-photo-5403478.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
26
- ];
27
-
28
- export const createDamRouter = () => {
29
- const router = express.Router();
30
-
31
- /*
32
- Main endpoint for finding digital assets and containers.
33
- This should be replaced with actual integration to your digital asset management system.
34
- */
35
- router.post("/resources/find", async (req, res) => {
36
- /*
37
- Extract relevant fields from the FindResourcesRequest.
38
- Replace this mock implementation with actual queries to your digital asset management system.
39
- Consider implementing proper filtering, sorting, and pagination based on these parameters.
40
- */
41
- const {
42
- types,
43
- continuation,
44
- locale,
45
- // other available fields from the `FindResourcesRequest`
46
- // containerTypes,
47
- // limit,
48
- // filters,
49
- // query,
50
- // sort,
51
- // tab,
52
- // containerId,
53
- // parentContainerType,
54
- } = req.body;
55
-
56
- let resources: Resource[] = [];
57
-
58
- // Handle image resource requests
59
- if (types.includes("IMAGE")) {
60
- resources = await Promise.all(
61
- Array.from({ length: 40 }, async (_, i) => {
62
- const imageUrl = imageUrls[i % imageUrls.length];
63
-
64
- if (!imageUrl) {
65
- throw new Error(`Image URL not found for index ${i}`);
66
- }
67
-
68
- return {
69
- id: await generateHash(i + ""),
70
- mimeType: "image/jpeg",
71
- name: `My new thing in ${locale}`, // Uses locale for demonstration - implement proper i18n
72
- type: "IMAGE",
73
- thumbnail: {
74
- url: imageUrl,
75
- },
76
- url: imageUrl,
77
- };
78
- }),
79
- );
80
- }
81
-
82
- // Handle container (folder) resource requests
83
- if (types.includes("CONTAINER")) {
84
- const containers = await Promise.all(
85
- Array.from(
86
- { length: 10 },
87
- async (_, i) =>
88
- ({
89
- id: await generateHash(i + ""),
90
- containerType: "folder",
91
- name: `My folder ${i}`,
92
- type: "CONTAINER",
93
- }) satisfies Container,
94
- ),
95
- );
96
-
97
- resources = resources.concat(containers);
98
- }
99
-
100
- // Send response with resources and pagination token
101
- res.send({
102
- resources,
103
- continuation: +(continuation || 0) + 1,
104
- });
105
- });
106
-
107
- return router;
108
- };
@@ -1,65 +0,0 @@
1
- import { user } from "@canva/app-middleware/express";
2
- import cors from "cors";
3
- import express from "express";
4
- import { createBaseServer } from "../utils/backend/base_backend/create";
5
- import { createDamRouter } from "./routers/dam";
6
-
7
- async function main() {
8
- // TODO: Set the CANVA_APP_ID environment variable in the project's .env file
9
- const APP_ID = process.env.CANVA_APP_ID;
10
-
11
- if (!APP_ID) {
12
- throw new Error(
13
- `The CANVA_APP_ID environment variable is undefined. Set the variable in the project's .env file.`,
14
- );
15
- }
16
-
17
- const router = express.Router();
18
-
19
- /**
20
- * TODO: Configure your CORS Policy
21
- *
22
- * Cross-Origin Resource Sharing
23
- * ([CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS)) is an
24
- * [HTTP](https://developer.mozilla.org/en-US/docs/Glossary/HTTP)-header based
25
- * mechanism that allows a server to indicate any
26
- * [origins](https://developer.mozilla.org/en-US/docs/Glossary/Origin)
27
- * (domain, scheme, or port) other than its own from which a browser should
28
- * permit loading resources.
29
- *
30
- * A basic CORS configuration would include the origin of your app in the
31
- * following example:
32
- * const corsOptions = {
33
- * origin: 'https://app-abcdefg.canva-apps.com',
34
- * optionsSuccessStatus: 200
35
- * }
36
- *
37
- * The origin of your app is https://app-${APP_ID}.canva-apps.com, and note
38
- * that the APP_ID should to be converted to lowercase.
39
- *
40
- * https://www.npmjs.com/package/cors#configuring-cors
41
- *
42
- * You may need to include multiple permissible origins, or dynamic origins
43
- * based on the environment in which the server is running. Further
44
- * information can be found
45
- * [here](https://www.npmjs.com/package/cors#configuring-cors-w-dynamic-origin).
46
- */
47
- router.use(cors());
48
-
49
- /**
50
- * Initialize JWT middleware to verify Canva user tokens
51
- * This middleware validates tokens sent from the frontend and extracts user information
52
- */
53
- router.use(user.verifyToken({ appId: APP_ID }));
54
-
55
- /**
56
- * Add routes for digital asset management.
57
- */
58
- const damRouter = createDamRouter();
59
- router.use(damRouter);
60
-
61
- const server = createBaseServer(router);
62
- server.start(process.env.CANVA_BACKEND_PORT);
63
- }
64
-
65
- main();
@@ -1,25 +0,0 @@
1
- {
2
- "$schema": "https://www.canva.dev/schemas/app/v1/manifest-schema.json",
3
- "manifest_schema_version": 1,
4
- "runtime": {
5
- "permissions": [
6
- {
7
- "name": "canva:asset:private:write",
8
- "type": "mandatory"
9
- },
10
- {
11
- "name": "canva:design:content:read",
12
- "type": "mandatory"
13
- },
14
- {
15
- "name": "canva:design:content:write",
16
- "type": "mandatory"
17
- }
18
- ]
19
- },
20
- "intent": {
21
- "design_editor": {
22
- "enrolled": true
23
- }
24
- }
25
- }