@payloadcms/figma 0.0.1-alpha.5 → 0.0.1-alpha.51

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 (326) hide show
  1. package/dist/api/control-plane.d.ts +31 -1
  2. package/dist/api/control-plane.js +137 -67
  3. package/dist/api/figma-api.d.ts +20 -0
  4. package/dist/api/figma-api.js +77 -21
  5. package/dist/auth/callback-server.js +2 -1
  6. package/dist/auth/crypto-utils.js +5 -5
  7. package/dist/auth/jwt-validator.d.ts +2 -1
  8. package/dist/auth/jwt-validator.js +2 -2
  9. package/dist/auth/oauth-flow.d.ts +1 -1
  10. package/dist/auth/oauth-flow.js +15 -11
  11. package/dist/auth/project-token.js +11 -6
  12. package/dist/auth/refresh.d.ts +2 -1
  13. package/dist/auth/refresh.js +25 -12
  14. package/dist/auth/token-store.d.ts +40 -1
  15. package/dist/auth/token-store.js +65 -5
  16. package/dist/auth/types.d.ts +17 -4
  17. package/dist/cli.js +54 -6
  18. package/dist/commands/build-lambda-zip.d.ts +5 -0
  19. package/dist/commands/build-lambda-zip.js +19 -0
  20. package/dist/commands/debug.d.ts +8 -0
  21. package/dist/commands/debug.js +161 -0
  22. package/dist/commands/deploy.d.ts +6 -0
  23. package/dist/commands/deploy.js +94 -126
  24. package/dist/commands/env.d.ts +13 -0
  25. package/dist/commands/env.js +88 -0
  26. package/dist/commands/init.d.ts +3 -5
  27. package/dist/commands/init.js +118 -94
  28. package/dist/commands/list-tokens.d.ts +3 -3
  29. package/dist/commands/list-tokens.js +22 -7
  30. package/dist/commands/login.d.ts +8 -1
  31. package/dist/commands/login.js +30 -12
  32. package/dist/commands/logout.d.ts +5 -4
  33. package/dist/commands/logout.js +56 -13
  34. package/dist/config/oauth.d.ts +4 -14
  35. package/dist/config/oauth.js +18 -40
  36. package/dist/constants.d.ts +36 -19
  37. package/dist/constants.js +58 -20
  38. package/dist/db-content-api/README.md +98 -0
  39. package/dist/db-content-api/generated/content-api-types.d.ts +3746 -0
  40. package/dist/db-content-api/generated/content-api-types.js +7 -0
  41. package/dist/db-content-api/index.d.ts +20 -0
  42. package/dist/db-content-api/index.js +702 -0
  43. package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
  44. package/dist/db-content-api/temp-utilities/slug.js +3 -0
  45. package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
  46. package/dist/db-content-api/temp-utilities/sorting.js +32 -0
  47. package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
  48. package/dist/db-content-api/temp-utilities/types.js +15 -0
  49. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +34 -0
  50. package/dist/db-content-api/temp-utilities/unwrapDocument.js +53 -0
  51. package/dist/db-content-api/utilities/auth.d.ts +30 -0
  52. package/dist/db-content-api/utilities/auth.js +81 -0
  53. package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
  54. package/dist/db-content-api/utilities/data/applyDefaults.js +59 -0
  55. package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
  56. package/dist/db-content-api/utilities/data/castFieldValue.js +69 -0
  57. package/dist/db-content-api/utilities/data/index.d.ts +42 -0
  58. package/dist/db-content-api/utilities/data/index.js +211 -0
  59. package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
  60. package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
  61. package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
  62. package/dist/db-content-api/utilities/data/stripFields.js +195 -0
  63. package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
  64. package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
  65. package/dist/db-content-api/utilities/joins.d.ts +55 -0
  66. package/dist/db-content-api/utilities/joins.js +136 -0
  67. package/dist/db-content-api/utilities/locale/index.d.ts +10 -0
  68. package/dist/db-content-api/utilities/locale/index.js +21 -0
  69. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
  70. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +66 -0
  71. package/dist/db-content-api/utilities/meta/buildMeta.d.ts +37 -0
  72. package/dist/db-content-api/utilities/meta/buildMeta.js +33 -0
  73. package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +13 -0
  74. package/dist/db-content-api/utilities/meta/buildPathTypes.js +181 -0
  75. package/dist/db-content-api/utilities/where.d.ts +20 -0
  76. package/dist/db-content-api/utilities/where.js +127 -0
  77. package/dist/endpoints/health.d.ts +3 -0
  78. package/dist/endpoints/health.js +11 -0
  79. package/dist/endpoints/schema.d.ts +3 -0
  80. package/dist/endpoints/schema.js +29 -0
  81. package/dist/exports/client.d.ts +3 -0
  82. package/dist/exports/client.js +3 -0
  83. package/dist/index.d.ts +2 -1
  84. package/dist/index.js +3 -1
  85. package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
  86. package/dist/oauth/components/FigmaAvatar/index.js +27 -0
  87. package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
  88. package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
  89. package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
  90. package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
  91. package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
  92. package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
  93. package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
  94. package/dist/oauth/components/LoginButton/index.js +50 -6
  95. package/dist/oauth/components/LoginButton/index.scss +50 -3
  96. package/dist/oauth/components/LogoutButton/index.js +5 -4
  97. package/dist/oauth/defaults.js +67 -10
  98. package/dist/oauth/endpoints/getLoginEndpoint.js +69 -24
  99. package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
  100. package/dist/oauth/index.js +40 -5
  101. package/dist/oauth/strategy/index.d.ts +0 -2
  102. package/dist/oauth/strategy/index.js +40 -17
  103. package/dist/oauth/types.d.ts +6 -6
  104. package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
  105. package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
  106. package/dist/oauth/utilities/refreshTokens.js +3 -3
  107. package/dist/plugin/build-config.d.ts +21 -14
  108. package/dist/plugin/build-config.js +208 -17
  109. package/dist/storage-content-api/api-types.d.ts +168 -0
  110. package/dist/storage-content-api/api-types.js +6 -0
  111. package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
  112. package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +42 -0
  113. package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
  114. package/dist/storage-content-api/client-uploads/generateSignedURL.js +39 -0
  115. package/dist/storage-content-api/client.d.ts +6 -0
  116. package/dist/storage-content-api/client.js +36 -0
  117. package/dist/storage-content-api/generateURL.d.ts +7 -0
  118. package/dist/storage-content-api/generateURL.js +8 -0
  119. package/dist/storage-content-api/handleDelete.d.ts +8 -0
  120. package/dist/storage-content-api/handleDelete.js +17 -0
  121. package/dist/storage-content-api/handleUpload.d.ts +11 -0
  122. package/dist/storage-content-api/handleUpload.js +144 -0
  123. package/dist/storage-content-api/index.d.ts +5 -0
  124. package/dist/storage-content-api/index.js +31 -0
  125. package/dist/storage-content-api/staticHandler.d.ts +10 -0
  126. package/dist/storage-content-api/staticHandler.js +56 -0
  127. package/dist/storage-content-api/types.d.ts +10 -0
  128. package/dist/storage-content-api/types.js +3 -0
  129. package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
  130. package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
  131. package/dist/storage-content-api/utilities/index.d.ts +2 -0
  132. package/dist/storage-content-api/utilities/index.js +3 -0
  133. package/dist/templates/.env.example +5 -0
  134. package/dist/templates/README.md +19 -0
  135. package/dist/types/config.d.ts +2 -1
  136. package/dist/types/config.js +0 -2
  137. package/dist/types.d.ts +3 -1
  138. package/dist/utils/asset-collection.d.ts +3 -6
  139. package/dist/utils/asset-collection.js +10 -34
  140. package/dist/utils/build-lambda-zip.d.ts +14 -0
  141. package/dist/utils/build-lambda-zip.js +81 -0
  142. package/dist/utils/cache-bootstrap.d.ts +8 -0
  143. package/dist/utils/cache-bootstrap.js +18 -0
  144. package/dist/utils/config.js +1 -1
  145. package/dist/utils/env-management.d.ts +16 -7
  146. package/dist/utils/env-management.js +85 -64
  147. package/dist/utils/format-env-suffix.d.ts +12 -0
  148. package/dist/utils/format-env-suffix.js +13 -0
  149. package/dist/utils/formatter.js +3 -5
  150. package/dist/utils/lambda-config.d.ts +3 -1
  151. package/dist/utils/lambda-config.js +38 -32
  152. package/dist/utils/messages.d.ts +1 -1
  153. package/dist/utils/messages.js +22 -8
  154. package/dist/utils/package-manager.d.ts +24 -0
  155. package/dist/utils/package-manager.js +53 -0
  156. package/dist/utils/payload-config-ast.d.ts +22 -3
  157. package/dist/utils/payload-config-ast.js +96 -31
  158. package/dist/utils/payload-config-finder.d.ts +2 -2
  159. package/dist/utils/payload-config-finder.js +48 -9
  160. package/dist/utils/payload-config-modifier.d.ts +1 -1
  161. package/dist/utils/payload-config-modifier.js +61 -10
  162. package/dist/utils/payload-package-check.d.ts +12 -1
  163. package/dist/utils/payload-package-check.js +63 -5
  164. package/dist/utils/project.d.ts +3 -2
  165. package/dist/utils/project.js +29 -15
  166. package/dist/utils/resolve-environment.d.ts +14 -0
  167. package/dist/utils/resolve-environment.js +28 -0
  168. package/dist/utils/s3-upload.d.ts +0 -1
  169. package/dist/utils/s3-upload.js +10 -3
  170. package/dist/utils/token-display.js +11 -5
  171. package/dist/utils/typescript-validator.js +4 -6
  172. package/dist/utils/version-check.d.ts +3 -0
  173. package/dist/utils/version-check.js +38 -0
  174. package/package.json +29 -10
  175. package/dist/api/control-plane.d.ts.map +0 -1
  176. package/dist/api/control-plane.js.map +0 -1
  177. package/dist/api/figma-api.d.ts.map +0 -1
  178. package/dist/api/figma-api.js.map +0 -1
  179. package/dist/auth/browser.d.ts.map +0 -1
  180. package/dist/auth/browser.js.map +0 -1
  181. package/dist/auth/callback-server.d.ts.map +0 -1
  182. package/dist/auth/callback-server.js.map +0 -1
  183. package/dist/auth/crypto-utils.d.ts.map +0 -1
  184. package/dist/auth/crypto-utils.js.map +0 -1
  185. package/dist/auth/jwt-validator.d.ts.map +0 -1
  186. package/dist/auth/jwt-validator.js.map +0 -1
  187. package/dist/auth/oauth-flow.d.ts.map +0 -1
  188. package/dist/auth/oauth-flow.js.map +0 -1
  189. package/dist/auth/pkce.d.ts.map +0 -1
  190. package/dist/auth/pkce.js.map +0 -1
  191. package/dist/auth/project-token.d.ts.map +0 -1
  192. package/dist/auth/project-token.js.map +0 -1
  193. package/dist/auth/refresh.d.ts.map +0 -1
  194. package/dist/auth/refresh.js.map +0 -1
  195. package/dist/auth/token-store.d.ts.map +0 -1
  196. package/dist/auth/token-store.js.map +0 -1
  197. package/dist/auth/types.d.ts.map +0 -1
  198. package/dist/auth/types.js.map +0 -1
  199. package/dist/cli.d.ts.map +0 -1
  200. package/dist/cli.js.map +0 -1
  201. package/dist/commands/deploy.d.ts.map +0 -1
  202. package/dist/commands/deploy.js.map +0 -1
  203. package/dist/commands/init.d.ts.map +0 -1
  204. package/dist/commands/init.js.map +0 -1
  205. package/dist/commands/list-tokens.d.ts.map +0 -1
  206. package/dist/commands/list-tokens.js.map +0 -1
  207. package/dist/commands/login.d.ts.map +0 -1
  208. package/dist/commands/login.js.map +0 -1
  209. package/dist/commands/logout.d.ts.map +0 -1
  210. package/dist/commands/logout.js.map +0 -1
  211. package/dist/config/oauth.d.ts.map +0 -1
  212. package/dist/config/oauth.js.map +0 -1
  213. package/dist/constants.d.ts.map +0 -1
  214. package/dist/constants.js.map +0 -1
  215. package/dist/exports/client.d.ts.map +0 -1
  216. package/dist/exports/client.js.map +0 -1
  217. package/dist/index.d.ts.map +0 -1
  218. package/dist/index.js.map +0 -1
  219. package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
  220. package/dist/oauth/components/LoginButton/index.js.map +0 -1
  221. package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
  222. package/dist/oauth/components/LogoutButton/index.js.map +0 -1
  223. package/dist/oauth/defaults.d.ts.map +0 -1
  224. package/dist/oauth/defaults.js.map +0 -1
  225. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
  226. package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
  227. package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
  228. package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
  229. package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
  230. package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
  231. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
  232. package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
  233. package/dist/oauth/exports/client.d.ts.map +0 -1
  234. package/dist/oauth/exports/client.js.map +0 -1
  235. package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
  236. package/dist/oauth/hooks/afterLogout.js.map +0 -1
  237. package/dist/oauth/hooks/me.d.ts.map +0 -1
  238. package/dist/oauth/hooks/me.js.map +0 -1
  239. package/dist/oauth/hooks/refresh.d.ts.map +0 -1
  240. package/dist/oauth/hooks/refresh.js.map +0 -1
  241. package/dist/oauth/index.d.ts.map +0 -1
  242. package/dist/oauth/index.js.map +0 -1
  243. package/dist/oauth/strategy/index.d.ts.map +0 -1
  244. package/dist/oauth/strategy/index.js.map +0 -1
  245. package/dist/oauth/types.d.ts.map +0 -1
  246. package/dist/oauth/types.js.map +0 -1
  247. package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
  248. package/dist/oauth/utilities/clearCookie.js.map +0 -1
  249. package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
  250. package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
  251. package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
  252. package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
  253. package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
  254. package/dist/oauth/utilities/extractOrigin.js.map +0 -1
  255. package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
  256. package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
  257. package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
  258. package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
  259. package/dist/oauth/utilities/getAdminPath.js +0 -9
  260. package/dist/oauth/utilities/getAdminPath.js.map +0 -1
  261. package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
  262. package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
  263. package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
  264. package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
  265. package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
  266. package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
  267. package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
  268. package/dist/oauth/utilities/getTokenExp.js.map +0 -1
  269. package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
  270. package/dist/oauth/utilities/getUsernameField.js.map +0 -1
  271. package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
  272. package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
  273. package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
  274. package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
  275. package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
  276. package/dist/oauth/utilities/refreshTokens.js.map +0 -1
  277. package/dist/plugin/adapter.d.ts.map +0 -1
  278. package/dist/plugin/adapter.js.map +0 -1
  279. package/dist/plugin/build-config.d.ts.map +0 -1
  280. package/dist/plugin/build-config.js.map +0 -1
  281. package/dist/types/config.d.ts.map +0 -1
  282. package/dist/types/config.js.map +0 -1
  283. package/dist/types.d.ts.map +0 -1
  284. package/dist/types.js.map +0 -1
  285. package/dist/utils/asset-collection.d.ts.map +0 -1
  286. package/dist/utils/asset-collection.js.map +0 -1
  287. package/dist/utils/build-detection.d.ts.map +0 -1
  288. package/dist/utils/build-detection.js.map +0 -1
  289. package/dist/utils/config.d.ts.map +0 -1
  290. package/dist/utils/config.js.map +0 -1
  291. package/dist/utils/download-template.d.ts.map +0 -1
  292. package/dist/utils/download-template.js.map +0 -1
  293. package/dist/utils/env-management.d.ts.map +0 -1
  294. package/dist/utils/env-management.js.map +0 -1
  295. package/dist/utils/format.d.ts.map +0 -1
  296. package/dist/utils/format.js.map +0 -1
  297. package/dist/utils/formatter.d.ts.map +0 -1
  298. package/dist/utils/formatter.js.map +0 -1
  299. package/dist/utils/git.d.ts.map +0 -1
  300. package/dist/utils/git.js.map +0 -1
  301. package/dist/utils/is-debug.d.ts.map +0 -1
  302. package/dist/utils/is-debug.js.map +0 -1
  303. package/dist/utils/lambda-config.d.ts.map +0 -1
  304. package/dist/utils/lambda-config.js.map +0 -1
  305. package/dist/utils/log.d.ts.map +0 -1
  306. package/dist/utils/log.js.map +0 -1
  307. package/dist/utils/messages.d.ts.map +0 -1
  308. package/dist/utils/messages.js.map +0 -1
  309. package/dist/utils/package-manager.d.ts.map +0 -1
  310. package/dist/utils/package-manager.js.map +0 -1
  311. package/dist/utils/payload-config-ast.d.ts.map +0 -1
  312. package/dist/utils/payload-config-ast.js.map +0 -1
  313. package/dist/utils/payload-config-finder.d.ts.map +0 -1
  314. package/dist/utils/payload-config-finder.js.map +0 -1
  315. package/dist/utils/payload-config-modifier.d.ts.map +0 -1
  316. package/dist/utils/payload-config-modifier.js.map +0 -1
  317. package/dist/utils/payload-package-check.d.ts.map +0 -1
  318. package/dist/utils/payload-package-check.js.map +0 -1
  319. package/dist/utils/project.d.ts.map +0 -1
  320. package/dist/utils/project.js.map +0 -1
  321. package/dist/utils/s3-upload.d.ts.map +0 -1
  322. package/dist/utils/s3-upload.js.map +0 -1
  323. package/dist/utils/token-display.d.ts.map +0 -1
  324. package/dist/utils/token-display.js.map +0 -1
  325. package/dist/utils/typescript-validator.d.ts.map +0 -1
  326. package/dist/utils/typescript-validator.js.map +0 -1
@@ -0,0 +1,161 @@
1
+ import fsSync from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { getTokenStore } from '../auth/token-store.js';
6
+ import { getInfraEnvironment } from '../constants.js';
7
+ import { getEnvVarSync } from '../utils/env-management.js';
8
+ import { maskToken } from '../utils/token-display.js';
9
+ import { getOwnVersion } from '../utils/version-check.js';
10
+ /**
11
+ * Handle the `@payloadcms/figma debug` command
12
+ *
13
+ * Outputs environment, auth, project, and package info for debugging.
14
+ * All data is local — no network calls are made.
15
+ */ export async function debugCommand() {
16
+ const env = getInfraEnvironment();
17
+ const tokenStore = getTokenStore(env);
18
+ const cwd = process.cwd();
19
+ const lines = [
20
+ 'Debug Info:',
21
+ ''
22
+ ];
23
+ appendSystemSection(lines, env);
24
+ appendAuthSection(lines, tokenStore, cwd);
25
+ appendProjectSection(lines, tokenStore, cwd);
26
+ await appendPackagesSection(lines);
27
+ // eslint-disable-next-line no-console
28
+ console.log(lines.join('\n'));
29
+ }
30
+ function appendSystemSection(lines, env) {
31
+ lines.push(`Infra Environment: ${env}`);
32
+ lines.push(`Node: ${process.version}`);
33
+ lines.push(`OS: ${os.platform()} ${os.arch()}`);
34
+ lines.push('');
35
+ }
36
+ function appendAuthSection(lines, tokenStore, cwd) {
37
+ const tokens = tokenStore.getTokens();
38
+ lines.push('Auth:');
39
+ if (!tokens) {
40
+ lines.push(' Status: Not authenticated');
41
+ lines.push('');
42
+ return;
43
+ }
44
+ const isValid = tokenStore.hasValidTokens();
45
+ lines.push(` Status: ${isValid ? 'Authenticated' : 'Token expired'}`);
46
+ const email = getEmailFromClaims(tokenStore, cwd);
47
+ if (email) {
48
+ lines.push(` Email: ${email}`);
49
+ } else if (tokens.userId) {
50
+ lines.push(` User ID: ${tokens.userId}`);
51
+ }
52
+ lines.push(` Token Expires: ${formatExpiryTime(tokens.expiresAt)}`);
53
+ lines.push('');
54
+ }
55
+ function appendProjectSection(lines, tokenStore, cwd) {
56
+ const projectId = getEnvVarSync(cwd, 'FIGMA_PROJECT_ID');
57
+ const environmentName = getEnvVarSync(cwd, 'FIGMA_ENVIRONMENT_NAME');
58
+ lines.push('Project:');
59
+ if (!projectId) {
60
+ lines.push(" Not initialized (run 'init' first)");
61
+ lines.push('');
62
+ return;
63
+ }
64
+ lines.push(` Project ID: ${projectId}`);
65
+ lines.push(` Environment: ${environmentName ?? '(not set)'}`);
66
+ // Show bootstrap data from local store
67
+ if (projectId && environmentName) {
68
+ const bootstrapData = tokenStore.getBootstrapData(projectId, environmentName);
69
+ if (bootstrapData) {
70
+ lines.push(` Content System ID: ${bootstrapData.contentSystemId}`);
71
+ lines.push(` Tenant Instance ID: ${bootstrapData.tenantInstanceId}`);
72
+ lines.push(` OAuth Client ID: ${maskToken(bootstrapData.oauthClientId)}`);
73
+ const projectToken = tokenStore.getProjectToken(bootstrapData.contentSystemId);
74
+ if (projectToken) {
75
+ lines.push(` Project Token: ${formatExpiryTime(projectToken.expiresAt)}`);
76
+ }
77
+ } else {
78
+ lines.push(' Bootstrap Data: (not cached)');
79
+ }
80
+ }
81
+ lines.push('');
82
+ }
83
+ async function appendPackagesSection(lines) {
84
+ lines.push('Packages:');
85
+ const cliVersion = await getOwnVersion();
86
+ lines.push(` @payloadcms/figma: ${cliVersion}`);
87
+ const payloadVersion = getPayloadVersion();
88
+ lines.push(` payload: ${payloadVersion}`);
89
+ }
90
+ /**
91
+ * Try resolving email from bootstrap data, then iterate all stored project tokens.
92
+ */ function getEmailFromClaims(tokenStore, cwd) {
93
+ const projectId = getEnvVarSync(cwd, 'FIGMA_PROJECT_ID');
94
+ const environmentName = getEnvVarSync(cwd, 'FIGMA_ENVIRONMENT_NAME');
95
+ if (projectId && environmentName) {
96
+ const bootstrapData = tokenStore.getBootstrapData(projectId, environmentName);
97
+ if (bootstrapData) {
98
+ const email = tokenStore.getProjectTokenClaims(bootstrapData.contentSystemId)?.email;
99
+ if (email) {
100
+ return email;
101
+ }
102
+ }
103
+ }
104
+ for (const id of tokenStore.getAllProjectTokenTenantIds()){
105
+ const email = tokenStore.getProjectTokenClaims(id)?.email;
106
+ if (email) {
107
+ return email;
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ function getPayloadVersion() {
113
+ try {
114
+ const require = createRequire(path.join(process.cwd(), 'noop.js'));
115
+ const resolved = require.resolve('payload');
116
+ const packageJsonPath = findPackageJson(path.dirname(resolved));
117
+ if (!packageJsonPath) {
118
+ return 'not found';
119
+ }
120
+ const content = fsSync.readFileSync(packageJsonPath, 'utf-8');
121
+ return JSON.parse(content).version;
122
+ } catch {
123
+ return 'not found';
124
+ }
125
+ }
126
+ function findPackageJson(dir) {
127
+ const { root } = path.parse(dir);
128
+ while(dir !== root){
129
+ const candidate = path.join(dir, 'package.json');
130
+ if (fsSync.existsSync(candidate)) {
131
+ return candidate;
132
+ }
133
+ dir = path.dirname(dir);
134
+ }
135
+ return null;
136
+ }
137
+ /**
138
+ * Format expiry timestamp as ISO string with relative time
139
+ * e.g. "2026-02-11T10:30:00.000Z (in 23h 15m)" or "2026-02-10T08:00:00.000Z (expired 2h ago)"
140
+ */ function formatExpiryTime(expiresAt) {
141
+ const iso = new Date(expiresAt).toISOString();
142
+ const diff = expiresAt - Date.now();
143
+ if (diff < 0) {
144
+ return `${iso} (expired ${formatDuration(Math.abs(diff))} ago)`;
145
+ }
146
+ return `${iso} (in ${formatDuration(diff)})`;
147
+ }
148
+ function formatDuration(ms) {
149
+ const minutes = Math.floor(ms / 60000);
150
+ const hours = Math.floor(minutes / 60);
151
+ const days = Math.floor(hours / 24);
152
+ if (days > 0) {
153
+ return `${days}d ${hours % 24}h`;
154
+ }
155
+ if (hours > 0) {
156
+ return `${hours}h ${minutes % 60}m`;
157
+ }
158
+ return `${minutes}m`;
159
+ }
160
+
161
+ //# sourceMappingURL=debug.js.map
@@ -4,6 +4,12 @@
4
4
  export interface DeployCommandOptions {
5
5
  /** Enable debug mode */
6
6
  debug?: boolean;
7
+ /** Figma environment name (e.g. 'production', 'staging') */
8
+ env?: string;
9
+ /** CMS Resource ID (overrides FIGMA_PROJECT_ID) */
10
+ id?: string;
11
+ /** Skip the build step (use existing build) */
12
+ skipBuild?: boolean;
7
13
  /** Skip confirmation prompts */
8
14
  yes?: boolean;
9
15
  }
@@ -1,19 +1,18 @@
1
1
  import * as p from '@clack/prompts';
2
- import { spawn } from 'child_process';
2
+ import spawn from 'cross-spawn';
3
3
  import path from 'path';
4
4
  import pc from 'picocolors';
5
- import { Project } from 'ts-morph';
6
- import { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js';
5
+ import { ControlPlaneError, createDeployment, getBootstrapInfo, performDeployment } from '../api/control-plane.js';
7
6
  import { getValidAccessToken } from '../auth/oauth-flow.js';
8
- import { getValidProjectToken } from '../auth/project-token.js';
9
- import { TokenStore } from '../auth/token-store.js';
7
+ import { getTokenStore } from '../auth/token-store.js';
8
+ import { CONTENT_SYSTEM_NOT_FOUND_MESSAGE } from '../constants.js';
10
9
  import { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js';
11
10
  import { detectBuild, getBuildCommand } from '../utils/build-detection.js';
11
+ import { getEnvVar } from '../utils/env-management.js';
12
12
  import * as log from '../utils/log.js';
13
13
  import { getPackageManager } from '../utils/package-manager.js';
14
- import { readFigmaConfig } from '../utils/payload-config-ast.js';
15
- import { findPayloadConfig } from '../utils/payload-config-finder.js';
16
14
  import { isInProjectDirectory } from '../utils/project.js';
15
+ import { resolveEnvironment } from '../utils/resolve-environment.js';
17
16
  import { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js';
18
17
  import { loginCommand } from './login.js';
19
18
  /**
@@ -51,6 +50,17 @@ import { loginCommand } from './login.js';
51
50
  */ export async function deployCommand(options) {
52
51
  const projectPath = process.cwd();
53
52
  const spinner = p.spinner();
53
+ // Resolve project ID
54
+ let projectId = options.id;
55
+ if (!projectId) {
56
+ projectId = await getEnvVar(projectPath, 'FIGMA_PROJECT_ID') ?? undefined;
57
+ }
58
+ if (!projectId) {
59
+ p.log.error(pc.red('✗ Project ID not found. Run `@payloadcms/figma init` first, or use --id.'));
60
+ process.exit(1);
61
+ }
62
+ // Resolve environment name
63
+ const environmentName = options.env ?? await getEnvVar(projectPath, 'FIGMA_ENVIRONMENT_NAME') ?? undefined;
54
64
  try {
55
65
  // ===== PRE-FLIGHT CHECKS =====
56
66
  // Check if in project directory
@@ -59,27 +69,8 @@ import { loginCommand } from './login.js';
59
69
  p.note('Create a project or connect an existing one to Figma: npx @payloadcms/figma init', 'Tip');
60
70
  process.exit(1);
61
71
  }
62
- // Find and read payload config
63
- const configPath = await findPayloadConfig(projectPath);
64
- if (!configPath) {
65
- p.log.error(pc.red('✗ payload.config.ts not found'));
66
- p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip');
67
- process.exit(1);
68
- }
69
- // Parse config with ts-morph
70
- const project = new Project({
71
- skipAddingFilesFromTsConfig: true
72
- });
73
- const sourceFile = project.addSourceFileAtPath(configPath);
74
- // Read figma configuration from buildConfig
75
- const config = readFigmaConfig(sourceFile);
76
- if (!config || !config.tenantId) {
77
- p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'));
78
- p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip');
79
- process.exit(1);
80
- }
81
72
  // Check authentication
82
- const tokenStore = new TokenStore();
73
+ const tokenStore = getTokenStore();
83
74
  let accessToken = await getValidAccessToken(tokenStore);
84
75
  if (!accessToken) {
85
76
  p.log.message('Please log in to continue');
@@ -90,40 +81,54 @@ import { loginCommand } from './login.js';
90
81
  process.exit(1);
91
82
  }
92
83
  }
93
- // Get project token
84
+ // Resolve tenant instance ID via bootstrap
85
+ spinner.start('Resolving deployment target...');
86
+ let tenantInstanceId;
94
87
  try {
95
- await getValidProjectToken(tokenStore, config.tenantId);
88
+ const bootstrapInfo = await getBootstrapInfo(accessToken, projectId);
89
+ const resolvedEnv = resolveEnvironment({
90
+ environmentName,
91
+ environments: bootstrapInfo.environments
92
+ });
93
+ tenantInstanceId = resolvedEnv.tenantInstanceId;
94
+ spinner.stop(pc.green(`✓ Target: ${resolvedEnv.name}`));
96
95
  } catch (error) {
97
- p.log.error(pc.yellow('⚠ Project token invalid'));
98
- throw error;
96
+ if (error instanceof ControlPlaneError && (error.statusCode === 404 || error.statusCode === 410)) {
97
+ spinner.stop(pc.red('✗ Content system not found'));
98
+ p.log.error(pc.red(CONTENT_SYSTEM_NOT_FOUND_MESSAGE));
99
+ process.exit(1);
100
+ }
101
+ spinner.stop(pc.red('✗ Failed to resolve deployment target'));
102
+ p.log.error(error instanceof Error ? error.message : 'Unknown error');
103
+ process.exit(1);
99
104
  }
100
- // ===== BUILD VALIDATION =====
101
- spinner.start('Checking for build...');
102
- let buildInfo = await detectBuild(projectPath);
103
- if (!buildInfo) {
104
- spinner.stop(pc.yellow(' No build found for this project.'));
105
- // Try to find build command
105
+ // ===== BUILD =====
106
+ let buildInfo;
107
+ if (options.skipBuild) {
108
+ // User asserts build exists - verify it
109
+ spinner.start('Checking for build...');
110
+ buildInfo = await detectBuild(projectPath);
111
+ if (!buildInfo) {
112
+ spinner.stop(pc.red('✗ No build found'));
113
+ p.log.error('Use deploy without --skip-build to build first.');
114
+ process.exit(1);
115
+ }
116
+ spinner.stop(pc.green('✓ Build found'));
117
+ p.note([
118
+ `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,
119
+ `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`
120
+ ].join('\n'), 'Build Details');
121
+ } else {
122
+ // Always build (no prompt)
106
123
  const buildCmd = await getBuildCommand(projectPath);
107
124
  if (!buildCmd) {
108
125
  p.log.error('No build script found in package.json');
109
126
  p.note('Add a build script to package.json: "build": "next build"', 'Tip');
110
127
  process.exit(1);
111
128
  }
112
- // Prompt to run build
113
- if (!options.yes) {
114
- const shouldBuild = await p.confirm({
115
- initialValue: true,
116
- message: `Build command found in package.json. Run it?`
117
- });
118
- if (p.isCancel(shouldBuild) || !shouldBuild) {
119
- p.log.message('Cancelling deployment...');
120
- process.exit(0);
121
- }
122
- }
123
- // Run build
124
129
  const packageManager = await getPackageManager(projectPath);
125
130
  const buildCommand = `${packageManager} run build`;
126
- spinner.stop(`Running ${buildCommand}...\n`);
131
+ p.log.step(`Running ${buildCommand}...\n`);
127
132
  try {
128
133
  // Stream build output to user with formatting
129
134
  const buildProcess = spawn(packageManager, [
@@ -139,20 +144,20 @@ import { loginCommand } from './login.js';
139
144
  });
140
145
  // Indent and dim output
141
146
  buildProcess.stdout?.on('data', (data)=>{
142
- const lines = data.toString().split('\n');
147
+ const lines = data.toString().split(/\r?\n/);
143
148
  lines.forEach((line)=>{
144
149
  if (line.trim()) {
145
150
  // eslint-disable-next-line no-console
146
- console.log(pc.dim(` ${line}`)); // Standard output
151
+ console.log(pc.dim(` ${line}`));
147
152
  }
148
153
  });
149
154
  });
150
155
  buildProcess.stderr?.on('data', (data)=>{
151
- const lines = data.toString().split('\n');
156
+ const lines = data.toString().split(/\r?\n/);
152
157
  lines.forEach((line)=>{
153
158
  if (line.trim()) {
154
159
  // eslint-disable-next-line no-console
155
- console.log(pc.dim(` ${line}`)); // Standard error
160
+ console.log(pc.dim(` ${line}`));
156
161
  }
157
162
  });
158
163
  });
@@ -170,19 +175,13 @@ import { loginCommand } from './login.js';
170
175
  }
171
176
  process.exit(1);
172
177
  }
173
- // Re-check for build
178
+ // Verify build output
174
179
  buildInfo = await detectBuild(projectPath);
175
180
  if (!buildInfo) {
176
181
  p.log.error(pc.red('✗ Build completed but standalone build not found'));
177
182
  p.note('Ensure next.config.js has output: "standalone"', 'Check Lambda Configuration');
178
183
  process.exit(1);
179
184
  }
180
- } else {
181
- spinner.stop(pc.green('✓ Build found'));
182
- p.note([
183
- `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,
184
- `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`
185
- ].join('\n'), 'Build Details');
186
185
  }
187
186
  // ===== DEPLOYMENT PREPARATION =====
188
187
  // Create Lambda zip
@@ -210,90 +209,59 @@ import { loginCommand } from './login.js';
210
209
  `${pc.cyan('Code size:')} ${formatBytes(zipSize)}`,
211
210
  `${pc.cyan('Static assets:')} ${staticAssets.length} files`
212
211
  ].join('\n'), 'Details');
213
- const shouldDeploy = await p.confirm({
214
- initialValue: true,
215
- message: 'Deploy this build to Figma?'
216
- });
217
- if (p.isCancel(shouldDeploy) || !shouldDeploy) {
218
- p.log.message('Cancelling deployment...');
219
- process.exit(0);
220
- }
221
212
  }
222
213
  // ===== DEPLOYMENT EXECUTION =====
223
214
  // Step 1: Create deployment
224
215
  spinner.start('Creating deployment...');
225
- let deploymentId;
226
- let codeUploadUrl;
227
- let staticAssetUploadUrls;
228
- try {
229
- const createResponse = await createDeployment(accessToken, config.tenantId, {
230
- staticAssets
231
- });
232
- deploymentId = createResponse.deploymentId;
233
- codeUploadUrl = createResponse.codeUploadUrl;
234
- staticAssetUploadUrls = createResponse.staticAssetUploadUrls;
235
- log.debug(`Deployment ID: ${deploymentId}`);
236
- } catch (error) {
237
- spinner.stop(pc.red('✗ Failed to create deployment'));
238
- throw error;
239
- }
216
+ const createResponse = await createDeployment(accessToken, tenantInstanceId, {
217
+ staticAssets
218
+ });
219
+ const deploymentId = createResponse.deploymentId;
220
+ const codeUploadUrl = createResponse.codeUploadUrl;
221
+ const staticAssetUploadUrls = createResponse.staticAssetUploadUrls;
222
+ log.debug(`Deployment ID: ${deploymentId}`);
240
223
  // Step 2: Upload code
241
224
  spinner.message(`Uploading code (${formatBytes(zipSize)})...`);
242
- try {
243
- await uploadLambdaZip(zipPath, codeUploadUrl);
244
- spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`));
245
- } catch (error) {
246
- spinner.stop(pc.red('✗ Failed to upload code'));
247
- throw error;
248
- }
225
+ await uploadLambdaZip(zipPath, codeUploadUrl);
226
+ spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`));
249
227
  // Step 3: Upload static assets
250
228
  if (staticAssets.length > 0) {
251
229
  spinner.start('Uploading static assets...');
252
- try {
253
- const uploadResults = await uploadStaticAssets(projectPath, staticAssetUploadUrls, (uploaded, total)=>{
254
- spinner.message(`Uploading static assets (${uploaded}/${total})...`);
255
- });
256
- if (uploadResults.assetsFailed > 0) {
257
- spinner.stop(pc.yellow(`⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`));
258
- p.log.warning(`${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`);
259
- } else {
260
- spinner.stop(pc.green(`✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`));
261
- }
262
- } catch (error) {
263
- spinner.stop(pc.red('✗ Failed to upload assets'));
264
- throw error;
230
+ const uploadResults = await uploadStaticAssets(projectPath, staticAssetUploadUrls, (uploaded, total)=>{
231
+ spinner.message(`Uploading static assets (${uploaded}/${total})...`);
232
+ });
233
+ if (uploadResults.assetsFailed > 0) {
234
+ spinner.stop(pc.yellow(`⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`));
235
+ p.log.warning(`${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`);
236
+ } else {
237
+ spinner.stop(pc.green(`✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`));
265
238
  }
266
239
  }
267
240
  // Step 4: Perform deployment
268
241
  spinner.start('Performing deployment...');
269
- try {
270
- await performDeployment(accessToken, config.tenantId, {
271
- deploymentId
272
- });
273
- spinner.stop(pc.green('✓ Deployment initiated'));
274
- } catch (error) {
275
- spinner.stop(pc.red('✗ Failed to perform deployment'));
276
- throw error;
277
- }
242
+ const result = await performDeployment(accessToken, tenantInstanceId, {
243
+ deploymentId
244
+ });
245
+ const tenantDomains = result.tenantDomains ?? [];
246
+ spinner.stop(pc.green('✓ Deployment initiated'));
278
247
  // TODO: Add deployment progress tracking
279
248
  // Future: Poll deployment status and show progress
280
249
  // API endpoint: GET /v1/tenant/{tenant_id}/deploy/{deployment_id}/status
281
250
  // Success output
282
- p.log.message('This usually takes 2-3 minutes to complete.');
283
- // Get tenant details for URL
284
- try {
285
- const tenant = await getTenantDetails(accessToken, config.tenantId);
286
- if (tenant.domain) {
287
- p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`);
288
- }
289
- } catch {
290
- // Non-critical - just skip URL display
251
+ if (tenantDomains.length > 0) {
252
+ p.log.step(`URL: ${pc.cyan(`https://${tenantDomains[0]}`)}`);
291
253
  }
292
- p.note(`Manage your deployment at:\n${pc.cyan(`https://cms.figma.com/manage/tenants/${config.tenantId}`)}`, 'Next Steps');
254
+ p.log.step('This usually takes 2-3 minutes to complete.');
293
255
  } catch (error) {
294
- spinner.stop(pc.red('✗ Failed'));
295
- const message = error instanceof Error ? error.message : 'Unknown error';
296
- p.log.error(pc.red(`✗ ${message}`));
256
+ if (error instanceof ControlPlaneError) {
257
+ spinner.stop(pc.red(`✗ ${error.message}`));
258
+ if (error.statusCode) {
259
+ p.log.message(pc.dim(` HTTP ${error.statusCode}`));
260
+ }
261
+ } else {
262
+ const message = error instanceof Error ? error.message : 'Unknown error';
263
+ spinner.stop(pc.red(`✗ ${message}`));
264
+ }
297
265
  if (options.debug && error instanceof Error && error.stack) {
298
266
  log.error(`Stack trace: ${error.stack}`);
299
267
  }
@@ -0,0 +1,13 @@
1
+ export interface EnvCommandOptions {
2
+ /** Environment name to switch to (skips interactive prompt) */
3
+ name?: string;
4
+ }
5
+ /**
6
+ * Handle the `@payloadcms/figma env [name]` command
7
+ *
8
+ * If name is provided, switches directly. Otherwise lists available
9
+ * environments with an interactive picker.
10
+ * Updates FIGMA_ENVIRONMENT_NAME in .env and caches all bootstrap data.
11
+ */
12
+ export declare function envCommand(options: EnvCommandOptions): Promise<void>;
13
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1,88 @@
1
+ import * as p from '@clack/prompts';
2
+ import pc from 'picocolors';
3
+ import { getBootstrapInfo } from '../api/control-plane.js';
4
+ import { getValidAccessToken } from '../auth/oauth-flow.js';
5
+ import { getTokenStore } from '../auth/token-store.js';
6
+ import { cacheAllEnvironments } from '../utils/cache-bootstrap.js';
7
+ import { addOrUpdateEnvVar, getEnvVar } from '../utils/env-management.js';
8
+ import * as log from '../utils/log.js';
9
+ /**
10
+ * Handle the `@payloadcms/figma env [name]` command
11
+ *
12
+ * If name is provided, switches directly. Otherwise lists available
13
+ * environments with an interactive picker.
14
+ * Updates FIGMA_ENVIRONMENT_NAME in .env and caches all bootstrap data.
15
+ */ export async function envCommand(options) {
16
+ const cwd = process.cwd();
17
+ const projectId = await getEnvVar(cwd, 'FIGMA_PROJECT_ID');
18
+ if (!projectId) {
19
+ p.log.error(pc.red('No project configured. Run `@payloadcms/figma init` first.'));
20
+ process.exit(1);
21
+ }
22
+ const currentEnv = await getEnvVar(cwd, 'FIGMA_ENVIRONMENT_NAME');
23
+ // Authenticate
24
+ const tokenStore = getTokenStore();
25
+ const accessToken = await getValidAccessToken(tokenStore);
26
+ if (!accessToken) {
27
+ p.log.error(pc.red('Not authenticated. Run `@payloadcms/figma login` first.'));
28
+ process.exit(1);
29
+ }
30
+ // Fetch available environments
31
+ const spinner = p.spinner();
32
+ spinner.start('Fetching environments...');
33
+ let environments;
34
+ try {
35
+ const bootstrapInfo = await getBootstrapInfo(accessToken, projectId);
36
+ environments = bootstrapInfo.environments;
37
+ cacheAllEnvironments(tokenStore, projectId, bootstrapInfo);
38
+ } catch (error) {
39
+ spinner.stop(pc.red('✗ Failed to fetch environments'));
40
+ p.log.error(pc.dim(`Details: ${error instanceof Error ? error.message : 'Unknown error'}`));
41
+ process.exit(1);
42
+ }
43
+ if (environments.length === 0) {
44
+ spinner.stop(pc.red('✗ No environments found'));
45
+ process.exit(1);
46
+ }
47
+ spinner.stop(pc.green(`✓ ${environments.length} environment(s) available`));
48
+ // Resolve target environment
49
+ let targetName;
50
+ if (options.name) {
51
+ const match = environments.find((e)=>e.name === options.name);
52
+ if (!match) {
53
+ const available = environments.map((e)=>e.name).join(', ');
54
+ p.log.error(pc.red(`Unknown environment: ${options.name}`));
55
+ p.log.message(`Available: ${available}`);
56
+ process.exit(1);
57
+ }
58
+ targetName = match.name;
59
+ } else if (environments.length === 1) {
60
+ targetName = environments[0].name;
61
+ p.log.message(`Only one environment available: ${pc.cyan(targetName)}`);
62
+ } else {
63
+ const selected = await p.select({
64
+ message: 'Select an environment',
65
+ options: environments.map((env)=>({
66
+ hint: env.name === currentEnv ? 'current' : undefined,
67
+ label: env.name,
68
+ value: env.name
69
+ }))
70
+ });
71
+ if (p.isCancel(selected)) {
72
+ p.cancel('Cancelled');
73
+ process.exit(0);
74
+ }
75
+ targetName = selected;
76
+ }
77
+ if (targetName === currentEnv) {
78
+ p.log.message(`Already on ${pc.cyan(targetName)}`);
79
+ return;
80
+ }
81
+ // Update .env
82
+ await addOrUpdateEnvVar(cwd, 'FIGMA_ENVIRONMENT_NAME', targetName);
83
+ log.debug(`Updated FIGMA_ENVIRONMENT_NAME to ${targetName}`);
84
+ p.log.success(pc.green(`✓ Switched to ${pc.cyan(targetName)}`));
85
+ p.log.message(pc.dim('Restart your dev server to apply the change.'));
86
+ }
87
+
88
+ //# sourceMappingURL=env.js.map
@@ -4,16 +4,14 @@
4
4
  export interface InitCommandOptions {
5
5
  /** Enable debug mode */
6
6
  debug?: boolean;
7
+ /** Figma environment name (e.g. 'production', 'staging') */
8
+ env?: string;
7
9
  /** Force reconfiguration of existing project */
8
10
  force?: boolean;
9
- /** Tenant ID to use (optional - will prompt if not provided) */
11
+ /** Content System ID to use */
10
12
  id?: string;
11
13
  /** Project name (for scaffolding) */
12
14
  name?: string;
13
- /** Disable Content System (defaults to enabled) */
14
- noContentSystem?: boolean;
15
- /** AWS region for deployment (defaults to us-east-1) */
16
- region?: string;
17
15
  /** Skip authentication check (for testing/development) */
18
16
  skipAuth?: boolean;
19
17
  /** Skip prompts and use defaults where possible */