@payloadcms/figma 0.0.1-alpha.2 → 0.0.1-alpha.20

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 (72) hide show
  1. package/dist/api/control-plane.d.ts +1 -1
  2. package/dist/api/control-plane.d.ts.map +1 -1
  3. package/dist/api/control-plane.js +12 -7
  4. package/dist/api/control-plane.js.map +1 -1
  5. package/dist/api/figma-api.d.ts.map +1 -1
  6. package/dist/api/figma-api.js +33 -10
  7. package/dist/api/figma-api.js.map +1 -1
  8. package/dist/auth/crypto-utils.d.ts.map +1 -1
  9. package/dist/auth/crypto-utils.js +5 -5
  10. package/dist/auth/crypto-utils.js.map +1 -1
  11. package/dist/auth/oauth-flow.js +3 -3
  12. package/dist/auth/oauth-flow.js.map +1 -1
  13. package/dist/auth/project-token.d.ts.map +1 -1
  14. package/dist/auth/project-token.js +7 -3
  15. package/dist/auth/project-token.js.map +1 -1
  16. package/dist/auth/token-store.d.ts.map +1 -1
  17. package/dist/auth/token-store.js +3 -0
  18. package/dist/auth/token-store.js.map +1 -1
  19. package/dist/cli.js +1 -0
  20. package/dist/cli.js.map +1 -1
  21. package/dist/commands/deploy.d.ts +2 -0
  22. package/dist/commands/deploy.d.ts.map +1 -1
  23. package/dist/commands/deploy.js +11 -6
  24. package/dist/commands/deploy.js.map +1 -1
  25. package/dist/commands/init.d.ts.map +1 -1
  26. package/dist/commands/init.js +14 -76
  27. package/dist/commands/init.js.map +1 -1
  28. package/dist/commands/login.d.ts +8 -1
  29. package/dist/commands/login.d.ts.map +1 -1
  30. package/dist/commands/login.js +10 -4
  31. package/dist/commands/login.js.map +1 -1
  32. package/dist/config/oauth.d.ts.map +1 -1
  33. package/dist/config/oauth.js +3 -3
  34. package/dist/config/oauth.js.map +1 -1
  35. package/dist/db-adapter.d.ts +17 -0
  36. package/dist/db-adapter.d.ts.map +1 -0
  37. package/dist/db-adapter.js +760 -0
  38. package/dist/db-adapter.js.map +1 -0
  39. package/dist/endpoints/health.d.ts +3 -0
  40. package/dist/endpoints/health.d.ts.map +1 -0
  41. package/dist/endpoints/health.js +11 -0
  42. package/dist/endpoints/health.js.map +1 -0
  43. package/dist/exports/client.d.ts +3 -0
  44. package/dist/exports/client.d.ts.map +1 -0
  45. package/dist/exports/client.js +4 -0
  46. package/dist/exports/client.js.map +1 -0
  47. package/dist/oauth/components/LoginButton/index.d.ts.map +1 -1
  48. package/dist/oauth/components/LoginButton/index.js +50 -6
  49. package/dist/oauth/components/LoginButton/index.js.map +1 -1
  50. package/dist/oauth/components/LoginButton/index.scss +50 -3
  51. package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +1 -1
  52. package/dist/oauth/endpoints/getLoginEndpoint.js +1 -1
  53. package/dist/oauth/endpoints/getLoginEndpoint.js.map +1 -1
  54. package/dist/oauth/index.d.ts.map +1 -1
  55. package/dist/oauth/index.js +30 -6
  56. package/dist/oauth/index.js.map +1 -1
  57. package/dist/oauth/utilities/refreshTokens.d.ts.map +1 -1
  58. package/dist/oauth/utilities/refreshTokens.js +1 -1
  59. package/dist/oauth/utilities/refreshTokens.js.map +1 -1
  60. package/dist/plugin/build-config.d.ts +3 -5
  61. package/dist/plugin/build-config.d.ts.map +1 -1
  62. package/dist/plugin/build-config.js +28 -14
  63. package/dist/plugin/build-config.js.map +1 -1
  64. package/dist/utils/payload-config-ast.d.ts +1 -1
  65. package/dist/utils/payload-config-ast.d.ts.map +1 -1
  66. package/dist/utils/payload-config-ast.js +7 -7
  67. package/dist/utils/payload-config-ast.js.map +1 -1
  68. package/dist/utils/s3-upload.d.ts +0 -1
  69. package/dist/utils/s3-upload.d.ts.map +1 -1
  70. package/dist/utils/s3-upload.js +10 -3
  71. package/dist/utils/s3-upload.js.map +1 -1
  72. package/package.json +10 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/token-store.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-classes */\nimport Conf from 'conf'\n\nimport type { FigmaTokens, JWTPayload, ProjectToken, TokenStoreConfig } from './types.js'\n\nimport { TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js'\nimport { deriveEncryptionKey } from './crypto-utils.js'\n\n/**\n * Secure storage manager for Figma OAuth2 tokens\n *\n * Uses the `conf` library to store tokens in an OS-specific secure location:\n * - macOS: ~/Library/Preferences/payloadcms-figma\n * - Linux: ~/.config/payloadcms-figma or $XDG_CONFIG_HOME/payloadcms-figma\n * - Windows: %APPDATA%/payloadcms-figma/Config\n *\n * Tokens are encrypted at rest with a machine-specific key and file permissions\n * are set to 0600 (owner read/write only)\n */\nexport class TokenStore {\n private config: Conf<{ projectTokens: Record<string, ProjectToken>; tokens: FigmaTokens }>\n\n constructor(options?: TokenStoreConfig) {\n this.config = new Conf<{ projectTokens: Record<string, ProjectToken>; tokens: FigmaTokens }>({\n configName: options?.configName || 'payloadcms-figma',\n projectName: 'payloadcms-figma',\n // Enable encryption with machine-specific key for better security\n encryptionKey: options?.encryptionKey || deriveEncryptionKey(),\n // Clear schema to avoid validation issues\n clearInvalidConfig: true,\n })\n }\n\n /**\n * Retrieve stored tokens\n * @returns FigmaTokens if stored, null otherwise\n */\n getTokens(): FigmaTokens | null {\n const tokens = this.config.get('tokens')\n return tokens || null\n }\n\n /**\n * Store OAuth2 tokens securely\n * @param tokens - Figma OAuth2 tokens to store\n */\n setTokens(tokens: FigmaTokens): void {\n this.config.set('tokens', tokens)\n }\n\n /**\n * Clear all stored tokens (used for logout)\n */\n clearTokens(): void {\n this.config.delete('tokens')\n }\n\n /**\n * Check if valid (non-expired) tokens exist\n * @returns true if tokens exist and are not expired\n */\n hasValidTokens(): boolean {\n const tokens = this.getTokens()\n if (!tokens) {\n return false\n }\n return !this.isExpired()\n }\n\n /**\n * Check if the current access token is expired\n * Includes a buffer time to avoid using tokens that are about to expire\n * @returns true if token is expired or will expire within buffer time\n */\n isExpired(): boolean {\n // Access config directly to avoid circular dependency with getTokens()\n const tokens = this.config.get('tokens')\n if (!tokens) {\n return true\n }\n\n const now = Date.now()\n const bufferMs = TOKEN_EXPIRY_BUFFER_SECONDS * 1000\n const expiryWithBuffer = tokens.expiresAt - bufferMs\n\n return now >= expiryWithBuffer\n }\n\n /**\n * Get the access token if it exists and is valid\n * @returns Access token string or null if expired/missing\n */\n getAccessToken(): null | string {\n if (!this.hasValidTokens()) {\n return null\n }\n const tokens = this.getTokens()\n return tokens?.accessToken || null\n }\n\n /**\n * Get the refresh token if it exists\n * @returns Refresh token string or null if missing\n */\n getRefreshToken(): null | string {\n const tokens = this.getTokens()\n return tokens?.refreshToken || null\n }\n\n /**\n * Update just the access token after a refresh\n * Preserves the existing refresh token and other metadata\n * @param accessToken - New access token\n * @param expiresIn - Expiration time in seconds\n */\n updateAccessToken(accessToken: string, expiresIn: number): void {\n const existingTokens = this.getTokens()\n if (!existingTokens) {\n throw new Error('Cannot update access token: no existing tokens found')\n }\n\n const expiresAt = Date.now() + expiresIn * 1000\n\n this.setTokens({\n ...existingTokens,\n accessToken,\n expiresAt,\n })\n }\n\n /**\n * Get the path to the config file (useful for debugging)\n * @returns Absolute path to the token storage file\n */\n getStoragePath(): string {\n return this.config.path\n }\n\n /**\n * Retrieve a project token for a specific tenant\n * Automatically removes expired tokens from storage\n * @param tenantId - The tenant/CMS ID\n * @returns ProjectToken if stored and valid, null otherwise\n */\n getProjectToken(tenantId: string): null | ProjectToken {\n const projectTokens = this.config.get('projectTokens') || {}\n const projectToken = projectTokens[tenantId]\n\n if (!projectToken) {\n return null\n }\n\n // Auto-cleanup expired project token\n if (this.isProjectTokenExpired(projectToken)) {\n this.clearProjectToken(tenantId)\n return null\n }\n\n return projectToken\n }\n\n /**\n * Store a project token for a specific tenant\n * @param tenantId - The tenant/CMS ID\n * @param projectToken - The project token to store\n */\n setProjectToken(tenantId: string, projectToken: ProjectToken): void {\n const projectTokens = this.config.get('projectTokens') || {}\n projectTokens[tenantId] = projectToken\n this.config.set('projectTokens', projectTokens)\n }\n\n /**\n * Clear a project token for a specific tenant\n * @param tenantId - The tenant/CMS ID\n */\n clearProjectToken(tenantId: string): void {\n const projectTokens = this.config.get('projectTokens') || {}\n delete projectTokens[tenantId]\n this.config.set('projectTokens', projectTokens)\n }\n\n /**\n * Clear all project tokens\n */\n clearAllProjectTokens(): void {\n this.config.delete('projectTokens')\n }\n\n /**\n * Check if a project token is expired\n * Includes a buffer time to avoid using tokens that are about to expire\n * @param projectToken - The project token to check\n * @returns true if token is expired or will expire within buffer time\n */\n isProjectTokenExpired(projectToken: ProjectToken): boolean {\n const now = Date.now()\n const bufferMs = TOKEN_EXPIRY_BUFFER_SECONDS * 1000\n const expiryWithBuffer = projectToken.expiresAt - bufferMs\n\n return now >= expiryWithBuffer\n }\n\n /**\n * Check if a valid (non-expired) project token exists for a tenant\n * @param tenantId - The tenant/CMS ID\n * @returns true if token exists and is not expired\n */\n hasValidProjectToken(tenantId: string): boolean {\n const projectToken = this.getProjectToken(tenantId)\n if (!projectToken) {\n return false\n }\n return !this.isProjectTokenExpired(projectToken)\n }\n\n /**\n * Get validated JWT claims from a project token\n * @param tenantId - The tenant/CMS ID\n * @returns JWT payload claims or null if token not found or has no claims\n */\n getProjectTokenClaims(tenantId: string): JWTPayload | null {\n const projectToken = this.getProjectToken(tenantId)\n return projectToken?.claims || null\n }\n\n /**\n * Get all tenant IDs that have stored project tokens\n * @returns Array of tenant IDs\n */\n getAllProjectTokenTenantIds(): string[] {\n const projectTokens = this.config.get('projectTokens') || {}\n return Object.keys(projectTokens)\n }\n}\n"],"names":["Conf","TOKEN_EXPIRY_BUFFER_SECONDS","deriveEncryptionKey","TokenStore","config","options","configName","projectName","encryptionKey","clearInvalidConfig","getTokens","tokens","get","setTokens","set","clearTokens","delete","hasValidTokens","isExpired","now","Date","bufferMs","expiryWithBuffer","expiresAt","getAccessToken","accessToken","getRefreshToken","refreshToken","updateAccessToken","expiresIn","existingTokens","Error","getStoragePath","path","getProjectToken","tenantId","projectTokens","projectToken","isProjectTokenExpired","clearProjectToken","setProjectToken","clearAllProjectTokens","hasValidProjectToken","getProjectTokenClaims","claims","getAllProjectTokenTenantIds","Object","keys"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/auth/token-store.ts"],"sourcesContent":["/* eslint-disable perfectionist/sort-classes */\nimport Conf from 'conf'\n\nimport type { FigmaTokens, JWTPayload, ProjectToken, TokenStoreConfig } from './types.js'\n\nimport { TOKEN_EXPIRY_BUFFER_SECONDS } from '../config/oauth.js'\nimport { deriveEncryptionKey } from './crypto-utils.js'\n\n/**\n * Secure storage manager for Figma OAuth2 tokens\n *\n * Uses the `conf` library to store tokens in an OS-specific secure location:\n * - macOS: ~/Library/Preferences/payloadcms-figma\n * - Linux: ~/.config/payloadcms-figma or $XDG_CONFIG_HOME/payloadcms-figma\n * - Windows: %APPDATA%/payloadcms-figma/Config\n *\n * Tokens are encrypted at rest with a machine-specific key and file permissions\n * are set to 0600 (owner read/write only)\n */\nexport class TokenStore {\n private config: Conf<{ projectTokens: Record<string, ProjectToken>; tokens: FigmaTokens }>\n\n constructor(options?: TokenStoreConfig) {\n if (process.env.AWS_EXECUTION_ENV) {\n throw new Error('TokenStore cannot be used in AWS Lambda environments')\n }\n this.config = new Conf<{ projectTokens: Record<string, ProjectToken>; tokens: FigmaTokens }>({\n configName: options?.configName || 'payloadcms-figma',\n projectName: 'payloadcms-figma',\n // Enable encryption with machine-specific key for better security\n encryptionKey: options?.encryptionKey || deriveEncryptionKey(),\n // Clear schema to avoid validation issues\n clearInvalidConfig: true,\n })\n }\n\n /**\n * Retrieve stored tokens\n * @returns FigmaTokens if stored, null otherwise\n */\n getTokens(): FigmaTokens | null {\n const tokens = this.config.get('tokens')\n return tokens || null\n }\n\n /**\n * Store OAuth2 tokens securely\n * @param tokens - Figma OAuth2 tokens to store\n */\n setTokens(tokens: FigmaTokens): void {\n this.config.set('tokens', tokens)\n }\n\n /**\n * Clear all stored tokens (used for logout)\n */\n clearTokens(): void {\n this.config.delete('tokens')\n }\n\n /**\n * Check if valid (non-expired) tokens exist\n * @returns true if tokens exist and are not expired\n */\n hasValidTokens(): boolean {\n const tokens = this.getTokens()\n if (!tokens) {\n return false\n }\n return !this.isExpired()\n }\n\n /**\n * Check if the current access token is expired\n * Includes a buffer time to avoid using tokens that are about to expire\n * @returns true if token is expired or will expire within buffer time\n */\n isExpired(): boolean {\n // Access config directly to avoid circular dependency with getTokens()\n const tokens = this.config.get('tokens')\n if (!tokens) {\n return true\n }\n\n const now = Date.now()\n const bufferMs = TOKEN_EXPIRY_BUFFER_SECONDS * 1000\n const expiryWithBuffer = tokens.expiresAt - bufferMs\n\n return now >= expiryWithBuffer\n }\n\n /**\n * Get the access token if it exists and is valid\n * @returns Access token string or null if expired/missing\n */\n getAccessToken(): null | string {\n if (!this.hasValidTokens()) {\n return null\n }\n const tokens = this.getTokens()\n return tokens?.accessToken || null\n }\n\n /**\n * Get the refresh token if it exists\n * @returns Refresh token string or null if missing\n */\n getRefreshToken(): null | string {\n const tokens = this.getTokens()\n return tokens?.refreshToken || null\n }\n\n /**\n * Update just the access token after a refresh\n * Preserves the existing refresh token and other metadata\n * @param accessToken - New access token\n * @param expiresIn - Expiration time in seconds\n */\n updateAccessToken(accessToken: string, expiresIn: number): void {\n const existingTokens = this.getTokens()\n if (!existingTokens) {\n throw new Error('Cannot update access token: no existing tokens found')\n }\n\n const expiresAt = Date.now() + expiresIn * 1000\n\n this.setTokens({\n ...existingTokens,\n accessToken,\n expiresAt,\n })\n }\n\n /**\n * Get the path to the config file (useful for debugging)\n * @returns Absolute path to the token storage file\n */\n getStoragePath(): string {\n return this.config.path\n }\n\n /**\n * Retrieve a project token for a specific tenant\n * Automatically removes expired tokens from storage\n * @param tenantId - The tenant/CMS ID\n * @returns ProjectToken if stored and valid, null otherwise\n */\n getProjectToken(tenantId: string): null | ProjectToken {\n const projectTokens = this.config.get('projectTokens') || {}\n const projectToken = projectTokens[tenantId]\n\n if (!projectToken) {\n return null\n }\n\n // Auto-cleanup expired project token\n if (this.isProjectTokenExpired(projectToken)) {\n this.clearProjectToken(tenantId)\n return null\n }\n\n return projectToken\n }\n\n /**\n * Store a project token for a specific tenant\n * @param tenantId - The tenant/CMS ID\n * @param projectToken - The project token to store\n */\n setProjectToken(tenantId: string, projectToken: ProjectToken): void {\n const projectTokens = this.config.get('projectTokens') || {}\n projectTokens[tenantId] = projectToken\n this.config.set('projectTokens', projectTokens)\n }\n\n /**\n * Clear a project token for a specific tenant\n * @param tenantId - The tenant/CMS ID\n */\n clearProjectToken(tenantId: string): void {\n const projectTokens = this.config.get('projectTokens') || {}\n delete projectTokens[tenantId]\n this.config.set('projectTokens', projectTokens)\n }\n\n /**\n * Clear all project tokens\n */\n clearAllProjectTokens(): void {\n this.config.delete('projectTokens')\n }\n\n /**\n * Check if a project token is expired\n * Includes a buffer time to avoid using tokens that are about to expire\n * @param projectToken - The project token to check\n * @returns true if token is expired or will expire within buffer time\n */\n isProjectTokenExpired(projectToken: ProjectToken): boolean {\n const now = Date.now()\n const bufferMs = TOKEN_EXPIRY_BUFFER_SECONDS * 1000\n const expiryWithBuffer = projectToken.expiresAt - bufferMs\n\n return now >= expiryWithBuffer\n }\n\n /**\n * Check if a valid (non-expired) project token exists for a tenant\n * @param tenantId - The tenant/CMS ID\n * @returns true if token exists and is not expired\n */\n hasValidProjectToken(tenantId: string): boolean {\n const projectToken = this.getProjectToken(tenantId)\n if (!projectToken) {\n return false\n }\n return !this.isProjectTokenExpired(projectToken)\n }\n\n /**\n * Get validated JWT claims from a project token\n * @param tenantId - The tenant/CMS ID\n * @returns JWT payload claims or null if token not found or has no claims\n */\n getProjectTokenClaims(tenantId: string): JWTPayload | null {\n const projectToken = this.getProjectToken(tenantId)\n return projectToken?.claims || null\n }\n\n /**\n * Get all tenant IDs that have stored project tokens\n * @returns Array of tenant IDs\n */\n getAllProjectTokenTenantIds(): string[] {\n const projectTokens = this.config.get('projectTokens') || {}\n return Object.keys(projectTokens)\n }\n}\n"],"names":["Conf","TOKEN_EXPIRY_BUFFER_SECONDS","deriveEncryptionKey","TokenStore","config","options","process","env","AWS_EXECUTION_ENV","Error","configName","projectName","encryptionKey","clearInvalidConfig","getTokens","tokens","get","setTokens","set","clearTokens","delete","hasValidTokens","isExpired","now","Date","bufferMs","expiryWithBuffer","expiresAt","getAccessToken","accessToken","getRefreshToken","refreshToken","updateAccessToken","expiresIn","existingTokens","getStoragePath","path","getProjectToken","tenantId","projectTokens","projectToken","isProjectTokenExpired","clearProjectToken","setProjectToken","clearAllProjectTokens","hasValidProjectToken","getProjectTokenClaims","claims","getAllProjectTokenTenantIds","Object","keys"],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -58,6 +58,7 @@ class Main {
58
58
  switch(subcommand){
59
59
  case 'deploy':
60
60
  await deployCommand({
61
+ id: this.args['--id'],
61
62
  debug: this.args['--debug'],
62
63
  yes: this.args['--yes']
63
64
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport arg from 'arg'\nimport pc from 'picocolors'\n\nimport type { CliArgs } from './types.js'\n\nimport { deployCommand } from './commands/deploy.js'\nimport { initCommand } from './commands/init.js'\nimport { listTokensCommand } from './commands/list-tokens.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { feedbackOutro, helpMessage } from './utils/messages.js'\n\n/**\n * Entrypoint for bin/cli.js\n */\nexport async function main(): Promise<void> {\n try {\n await new Main().init()\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(e.message)\n }\n }\n}\n\nclass Main {\n args: CliArgs\n\n constructor() {\n // @ts-expect-error bad typings\n this.args = arg(\n {\n '--debug': Boolean,\n '--force': Boolean,\n '--help': Boolean,\n '--id': String,\n '--name': String,\n '--skip-auth': Boolean,\n '--yes': Boolean,\n\n // Aliases\n '-f': '--force',\n '-h': '--help',\n '-y': '--yes',\n },\n { permissive: true },\n )\n\n // Set debug flag globally\n if (this.args['--debug']) {\n process.env.DEBUG = 'true'\n }\n }\n\n async init(): Promise<void> {\n try {\n if (this.args['--help']) {\n helpMessage()\n process.exit(0)\n }\n\n // Get the subcommand (first non-flag argument)\n const subcommand = this.args._[0]\n\n // eslint-disable-next-line no-console\n console.log('\\n')\n p.intro(pc.bgCyan(pc.black(' @payloadcms/figma ')))\n\n // Route to appropriate command handler\n switch (subcommand) {\n case 'deploy':\n await deployCommand({\n debug: this.args['--debug'],\n yes: this.args['--yes'],\n })\n break\n\n case 'init':\n await initCommand({\n id: this.args['--id'],\n name: this.args['--name'],\n debug: this.args['--debug'],\n force: this.args['--force'],\n skipAuth: this.args['--skip-auth'],\n })\n break\n\n case 'list-tokens':\n listTokensCommand({\n debug: this.args['--debug'],\n })\n break\n\n case 'login':\n await loginCommand()\n break\n\n case 'logout':\n await logoutCommand({\n debug: this.args['--debug'],\n })\n break\n\n case undefined:\n // No subcommand - show default message\n p.note(\"Let's create a new CMS!\")\n p.outro(feedbackOutro())\n break\n\n default:\n p.log.error(pc.red(`Unknown command: ${subcommand}`))\n p.note('Use --help to see available commands', 'Tip')\n process.exit(1)\n }\n\n process.exit(0)\n } catch (err: unknown) {\n // eslint-disable-next-line no-console\n console.error(err instanceof Error ? err.message : 'An error occurred')\n process.exit(1)\n }\n }\n}\n"],"names":["p","arg","pc","deployCommand","initCommand","listTokensCommand","loginCommand","logoutCommand","feedbackOutro","helpMessage","main","Main","init","e","Error","console","error","message","args","Boolean","String","permissive","process","env","DEBUG","exit","subcommand","_","log","intro","bgCyan","black","debug","yes","id","name","force","skipAuth","undefined","note","outro","red","err"],"mappings":"AAAA,YAAYA,OAAO,iBAAgB;AACnC,OAAOC,SAAS,MAAK;AACrB,OAAOC,QAAQ,aAAY;AAI3B,SAASC,aAAa,QAAQ,uBAAsB;AACpD,SAASC,WAAW,QAAQ,qBAAoB;AAChD,SAASC,iBAAiB,QAAQ,4BAA2B;AAC7D,SAASC,YAAY,QAAQ,sBAAqB;AAClD,SAASC,aAAa,QAAQ,uBAAsB;AACpD,SAASC,aAAa,EAAEC,WAAW,QAAQ,sBAAqB;AAEhE;;CAEC,GACD,OAAO,eAAeC;IACpB,IAAI;QACF,MAAM,IAAIC,OAAOC,IAAI;IACvB,EAAE,OAAOC,GAAG;QACV,IAAIA,aAAaC,OAAO;YACtB,sCAAsC;YACtCC,QAAQC,KAAK,CAACH,EAAEI,OAAO;QACzB;IACF;AACF;AAEA,MAAMN;IACJO,KAAa;IAEb,aAAc;QACZ,+BAA+B;QAC/B,IAAI,CAACA,IAAI,GAAGjB,IACV;YACE,WAAWkB;YACX,WAAWA;YACX,UAAUA;YACV,QAAQC;YACR,UAAUA;YACV,eAAeD;YACf,SAASA;YAET,UAAU;YACV,MAAM;YACN,MAAM;YACN,MAAM;QACR,GACA;YAAEE,YAAY;QAAK;QAGrB,0BAA0B;QAC1B,IAAI,IAAI,CAACH,IAAI,CAAC,UAAU,EAAE;YACxBI,QAAQC,GAAG,CAACC,KAAK,GAAG;QACtB;IACF;IAEA,MAAMZ,OAAsB;QAC1B,IAAI;YACF,IAAI,IAAI,CAACM,IAAI,CAAC,SAAS,EAAE;gBACvBT;gBACAa,QAAQG,IAAI,CAAC;YACf;YAEA,+CAA+C;YAC/C,MAAMC,aAAa,IAAI,CAACR,IAAI,CAACS,CAAC,CAAC,EAAE;YAEjC,sCAAsC;YACtCZ,QAAQa,GAAG,CAAC;YACZ5B,EAAE6B,KAAK,CAAC3B,GAAG4B,MAAM,CAAC5B,GAAG6B,KAAK,CAAC;YAE3B,uCAAuC;YACvC,OAAQL;gBACN,KAAK;oBACH,MAAMvB,cAAc;wBAClB6B,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;wBAC3Be,KAAK,IAAI,CAACf,IAAI,CAAC,QAAQ;oBACzB;oBACA;gBAEF,KAAK;oBACH,MAAMd,YAAY;wBAChB8B,IAAI,IAAI,CAAChB,IAAI,CAAC,OAAO;wBACrBiB,MAAM,IAAI,CAACjB,IAAI,CAAC,SAAS;wBACzBc,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;wBAC3BkB,OAAO,IAAI,CAAClB,IAAI,CAAC,UAAU;wBAC3BmB,UAAU,IAAI,CAACnB,IAAI,CAAC,cAAc;oBACpC;oBACA;gBAEF,KAAK;oBACHb,kBAAkB;wBAChB2B,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;oBAC7B;oBACA;gBAEF,KAAK;oBACH,MAAMZ;oBACN;gBAEF,KAAK;oBACH,MAAMC,cAAc;wBAClByB,OAAO,IAAI,CAACd,IAAI,CAAC,UAAU;oBAC7B;oBACA;gBAEF,KAAKoB;oBACH,uCAAuC;oBACvCtC,EAAEuC,IAAI,CAAC;oBACPvC,EAAEwC,KAAK,CAAChC;oBACR;gBAEF;oBACER,EAAE4B,GAAG,CAACZ,KAAK,CAACd,GAAGuC,GAAG,CAAC,CAAC,iBAAiB,EAAEf,YAAY;oBACnD1B,EAAEuC,IAAI,CAAC,wCAAwC;oBAC/CjB,QAAQG,IAAI,CAAC;YACjB;YAEAH,QAAQG,IAAI,CAAC;QACf,EAAE,OAAOiB,KAAc;YACrB,sCAAsC;YACtC3B,QAAQC,KAAK,CAAC0B,eAAe5B,QAAQ4B,IAAIzB,OAAO,GAAG;YACnDK,QAAQG,IAAI,CAAC;QACf;IACF;AACF"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport arg from 'arg'\nimport pc from 'picocolors'\n\nimport type { CliArgs } from './types.js'\n\nimport { deployCommand } from './commands/deploy.js'\nimport { initCommand } from './commands/init.js'\nimport { listTokensCommand } from './commands/list-tokens.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { feedbackOutro, helpMessage } from './utils/messages.js'\n\n/**\n * Entrypoint for bin/cli.js\n */\nexport async function main(): Promise<void> {\n try {\n await new Main().init()\n } catch (e) {\n if (e instanceof Error) {\n // eslint-disable-next-line no-console\n console.error(e.message)\n }\n }\n}\n\nclass Main {\n args: CliArgs\n\n constructor() {\n // @ts-expect-error bad typings\n this.args = arg(\n {\n '--debug': Boolean,\n '--force': Boolean,\n '--help': Boolean,\n '--id': String,\n '--name': String,\n '--skip-auth': Boolean,\n '--yes': Boolean,\n\n // Aliases\n '-f': '--force',\n '-h': '--help',\n '-y': '--yes',\n },\n { permissive: true },\n )\n\n // Set debug flag globally\n if (this.args['--debug']) {\n process.env.DEBUG = 'true'\n }\n }\n\n async init(): Promise<void> {\n try {\n if (this.args['--help']) {\n helpMessage()\n process.exit(0)\n }\n\n // Get the subcommand (first non-flag argument)\n const subcommand = this.args._[0]\n\n // eslint-disable-next-line no-console\n console.log('\\n')\n p.intro(pc.bgCyan(pc.black(' @payloadcms/figma ')))\n\n // Route to appropriate command handler\n switch (subcommand) {\n case 'deploy':\n await deployCommand({\n id: this.args['--id'],\n debug: this.args['--debug'],\n yes: this.args['--yes'],\n })\n break\n\n case 'init':\n await initCommand({\n id: this.args['--id'],\n name: this.args['--name'],\n debug: this.args['--debug'],\n force: this.args['--force'],\n skipAuth: this.args['--skip-auth'],\n })\n break\n\n case 'list-tokens':\n listTokensCommand({\n debug: this.args['--debug'],\n })\n break\n\n case 'login':\n await loginCommand()\n break\n\n case 'logout':\n await logoutCommand({\n debug: this.args['--debug'],\n })\n break\n\n case undefined:\n // No subcommand - show default message\n p.note(\"Let's create a new CMS!\")\n p.outro(feedbackOutro())\n break\n\n default:\n p.log.error(pc.red(`Unknown command: ${subcommand}`))\n p.note('Use --help to see available commands', 'Tip')\n process.exit(1)\n }\n\n process.exit(0)\n } catch (err: unknown) {\n // eslint-disable-next-line no-console\n console.error(err instanceof Error ? err.message : 'An error occurred')\n process.exit(1)\n }\n }\n}\n"],"names":["p","arg","pc","deployCommand","initCommand","listTokensCommand","loginCommand","logoutCommand","feedbackOutro","helpMessage","main","Main","init","e","Error","console","error","message","args","Boolean","String","permissive","process","env","DEBUG","exit","subcommand","_","log","intro","bgCyan","black","id","debug","yes","name","force","skipAuth","undefined","note","outro","red","err"],"mappings":"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"}
@@ -4,6 +4,8 @@
4
4
  export interface DeployCommandOptions {
5
5
  /** Enable debug mode */
6
6
  debug?: boolean;
7
+ /** Tenant ID */
8
+ id?: string;
7
9
  /** Skip confirmation prompts */
8
10
  yes?: boolean;
9
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AA6BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyThF"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gBAAgB;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,gCAAgC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AA6BD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgUhF"}
@@ -51,6 +51,11 @@ import { loginCommand } from './login.js';
51
51
  */ export async function deployCommand(options) {
52
52
  const projectPath = process.cwd();
53
53
  const spinner = p.spinner();
54
+ if (!options.id) {
55
+ p.log.error(pc.red('✗ Tenant ID is required. Use --id <tenant_id> to specify.'));
56
+ process.exit(1);
57
+ }
58
+ const tenantId = options.id;
54
59
  try {
55
60
  // ===== PRE-FLIGHT CHECKS =====
56
61
  // Check if in project directory
@@ -73,7 +78,7 @@ import { loginCommand } from './login.js';
73
78
  const sourceFile = project.addSourceFileAtPath(configPath);
74
79
  // Read figma configuration from buildConfig
75
80
  const config = readFigmaConfig(sourceFile);
76
- if (!config || !config.tenantId) {
81
+ if (!config || !config.contentSystemId) {
77
82
  p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'));
78
83
  p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip');
79
84
  process.exit(1);
@@ -92,7 +97,7 @@ import { loginCommand } from './login.js';
92
97
  }
93
98
  // Get project token
94
99
  try {
95
- await getValidProjectToken(tokenStore, config.tenantId);
100
+ await getValidProjectToken(tokenStore, tenantId);
96
101
  } catch (error) {
97
102
  p.log.error(pc.yellow('⚠ Project token invalid'));
98
103
  throw error;
@@ -226,7 +231,7 @@ import { loginCommand } from './login.js';
226
231
  let codeUploadUrl;
227
232
  let staticAssetUploadUrls;
228
233
  try {
229
- const createResponse = await createDeployment(accessToken, config.tenantId, {
234
+ const createResponse = await createDeployment(accessToken, tenantId, {
230
235
  staticAssets
231
236
  });
232
237
  deploymentId = createResponse.deploymentId;
@@ -267,7 +272,7 @@ import { loginCommand } from './login.js';
267
272
  // Step 4: Perform deployment
268
273
  spinner.start('Performing deployment...');
269
274
  try {
270
- await performDeployment(accessToken, config.tenantId, {
275
+ await performDeployment(accessToken, tenantId, {
271
276
  deploymentId
272
277
  });
273
278
  spinner.stop(pc.green('✓ Deployment initiated'));
@@ -282,14 +287,14 @@ import { loginCommand } from './login.js';
282
287
  p.log.message('This usually takes 2-3 minutes to complete.');
283
288
  // Get tenant details for URL
284
289
  try {
285
- const tenant = await getTenantDetails(accessToken, config.tenantId);
290
+ const tenant = await getTenantDetails(accessToken, tenantId);
286
291
  if (tenant.domain) {
287
292
  p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`);
288
293
  }
289
294
  } catch {
290
295
  // Non-critical - just skip URL display
291
296
  }
292
- p.note(`Manage your deployment at:\n${pc.cyan(`https://cms.figma.com/manage/tenants/${config.tenantId}`)}`, 'Next Steps');
297
+ p.note(`Manage your deployment at:\n${pc.cyan(`https://cms.figma.com/manage/tenants/${tenantId}`)}`, 'Next Steps');
293
298
  } catch (error) {
294
299
  spinner.stop(pc.red('✗ Failed'));
295
300
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport { spawn } from 'child_process'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { Project } from 'ts-morph'\n\nimport { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js'\nimport { detectBuild, getBuildCommand } from '../utils/build-detection.js'\nimport * as log from '../utils/log.js'\nimport { getPackageManager } from '../utils/package-manager.js'\nimport { readFigmaConfig } from '../utils/payload-config-ast.js'\nimport { findPayloadConfig } from '../utils/payload-config-finder.js'\nimport { isInProjectDirectory } from '../utils/project.js'\nimport { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for deploy command\n */\nexport interface DeployCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Skip confirmation prompts */\n yes?: boolean\n}\n\n/**\n * Format bytes to human-readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return '0 B'\n }\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format date to human-readable string in local time\n */\nfunction formatDate(date: Date): string {\n return date.toLocaleString('en-US', {\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n month: 'long',\n timeZoneName: 'short',\n year: 'numeric',\n })\n}\n\n/**\n * Execute the deploy command\n *\n * @param options - Command options\n */\nexport async function deployCommand(options: DeployCommandOptions): Promise<void> {\n const projectPath = process.cwd()\n const spinner = p.spinner()\n\n try {\n // ===== PRE-FLIGHT CHECKS =====\n\n // Check if in project directory\n if (!(await isInProjectDirectory(projectPath))) {\n p.log.error(pc.red(\"✗ 'deploy' command is not available outside of a Payload project.\"))\n p.note(\n 'Create a project or connect an existing one to Figma: npx @payloadcms/figma init',\n 'Tip',\n )\n process.exit(1)\n }\n\n // Find and read payload config\n const configPath = await findPayloadConfig(projectPath)\n if (!configPath) {\n p.log.error(pc.red('✗ payload.config.ts not found'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Parse config with ts-morph\n const project = new Project({ skipAddingFilesFromTsConfig: true })\n const sourceFile = project.addSourceFileAtPath(configPath)\n\n // Read figma configuration from buildConfig\n const config = readFigmaConfig(sourceFile)\n if (!config || !config.tenantId) {\n p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Check authentication\n const tokenStore = new TokenStore()\n\n let accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.message('Please log in to continue')\n await loginCommand()\n accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.error(pc.red('✗ Authentication failed'))\n process.exit(1)\n }\n }\n\n // Get project token\n try {\n await getValidProjectToken(tokenStore, config.tenantId)\n } catch (error) {\n p.log.error(pc.yellow('⚠ Project token invalid'))\n throw error\n }\n\n // ===== BUILD VALIDATION =====\n\n spinner.start('Checking for build...')\n let buildInfo = await detectBuild(projectPath)\n\n if (!buildInfo) {\n spinner.stop(pc.yellow('⚠ No build found for this project.'))\n\n // Try to find build command\n const buildCmd = await getBuildCommand(projectPath)\n\n if (!buildCmd) {\n p.log.error('No build script found in package.json')\n p.note('Add a build script to package.json: \"build\": \"next build\"', 'Tip')\n process.exit(1)\n }\n\n // Prompt to run build\n if (!options.yes) {\n const shouldBuild = await p.confirm({\n initialValue: true,\n message: `Build command found in package.json. Run it?`,\n })\n\n if (p.isCancel(shouldBuild) || !shouldBuild) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // Run build\n const packageManager = await getPackageManager(projectPath)\n const buildCommand = `${packageManager} run build`\n spinner.stop(`Running ${buildCommand}...\\n`)\n\n try {\n // Stream build output to user with formatting\n const buildProcess = spawn(packageManager, ['run', 'build'], {\n cwd: projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n // Indent and dim output\n buildProcess.stdout?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard output\n }\n })\n })\n\n buildProcess.stderr?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard error\n }\n })\n })\n\n const exitCode = await new Promise<number>((resolve) => {\n buildProcess.on('close', resolve)\n })\n\n if (exitCode !== 0) {\n throw new Error(`Build process exited with code ${exitCode}`)\n }\n\n p.log.success(pc.green('✓ Build completed'))\n } catch (error) {\n p.log.error(pc.red('✗ Build failed'))\n if (error instanceof Error && options.debug) {\n log.error(`Build error: ${error.message}`)\n }\n process.exit(1)\n }\n\n // Re-check for build\n buildInfo = await detectBuild(projectPath)\n if (!buildInfo) {\n p.log.error(pc.red('✗ Build completed but standalone build not found'))\n p.note('Ensure next.config.js has output: \"standalone\"', 'Check Lambda Configuration')\n process.exit(1)\n }\n } else {\n spinner.stop(pc.green('✓ Build found'))\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n ].join('\\n'),\n 'Build Details',\n )\n }\n\n // ===== DEPLOYMENT PREPARATION =====\n\n // Create Lambda zip\n spinner.start('Creating deployment package...')\n try {\n await createLambdaZip(projectPath)\n spinner.stop(pc.green('✓ Deployment package created'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment package'))\n throw error\n }\n\n // Collect static assets\n spinner.start('Collecting static assets...')\n const staticAssets = await collectStaticAssets(projectPath)\n const zipPath = path.join(projectPath, 'lambda.zip')\n const zipSize = await getFileSize(zipPath)\n spinner.stop(pc.green(`✓ ${staticAssets.length} static assets detected`))\n\n log.debug(`Lambda zip size: ${formatBytes(zipSize)}`)\n log.debug(`Static assets: ${staticAssets.length} files`)\n\n // ===== DEPLOYMENT CONFIRMATION =====\n\n if (!options.yes) {\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n `${pc.cyan('Code size:')} ${formatBytes(zipSize)}`,\n `${pc.cyan('Static assets:')} ${staticAssets.length} files`,\n ].join('\\n'),\n 'Details',\n )\n\n const shouldDeploy = await p.confirm({\n initialValue: true,\n message: 'Deploy this build to Figma?',\n })\n\n if (p.isCancel(shouldDeploy) || !shouldDeploy) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // ===== DEPLOYMENT EXECUTION =====\n\n // Step 1: Create deployment\n spinner.start('Creating deployment...')\n let deploymentId: string\n let codeUploadUrl: string\n let staticAssetUploadUrls: Record<string, string>\n\n try {\n const createResponse = await createDeployment(accessToken, config.tenantId, {\n staticAssets,\n })\n\n deploymentId = createResponse.deploymentId\n codeUploadUrl = createResponse.codeUploadUrl\n staticAssetUploadUrls = createResponse.staticAssetUploadUrls\n\n log.debug(`Deployment ID: ${deploymentId}`)\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment'))\n throw error\n }\n\n // Step 2: Upload code\n spinner.message(`Uploading code (${formatBytes(zipSize)})...`)\n try {\n await uploadLambdaZip(zipPath, codeUploadUrl)\n spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload code'))\n throw error\n }\n\n // Step 3: Upload static assets\n if (staticAssets.length > 0) {\n spinner.start('Uploading static assets...')\n\n try {\n const uploadResults = await uploadStaticAssets(\n projectPath,\n staticAssetUploadUrls,\n (uploaded, total) => {\n spinner.message(`Uploading static assets (${uploaded}/${total})...`)\n },\n )\n\n if (uploadResults.assetsFailed > 0) {\n spinner.stop(\n pc.yellow(\n `⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`,\n ),\n )\n p.log.warning(\n `${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`,\n )\n } else {\n spinner.stop(\n pc.green(\n `✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`,\n ),\n )\n }\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload assets'))\n throw error\n }\n }\n\n // Step 4: Perform deployment\n spinner.start('Performing deployment...')\n try {\n await performDeployment(accessToken, config.tenantId, {\n deploymentId,\n })\n spinner.stop(pc.green('✓ Deployment initiated'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to perform deployment'))\n throw error\n }\n\n // TODO: Add deployment progress tracking\n // Future: Poll deployment status and show progress\n // API endpoint: GET /v1/tenant/{tenant_id}/deploy/{deployment_id}/status\n\n // Success output\n p.log.message('This usually takes 2-3 minutes to complete.')\n\n // Get tenant details for URL\n try {\n const tenant = await getTenantDetails(accessToken, config.tenantId)\n if (tenant.domain) {\n p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`)\n }\n } catch {\n // Non-critical - just skip URL display\n }\n\n p.note(\n `Manage your deployment at:\\n${pc.cyan(`https://cms.figma.com/manage/tenants/${config.tenantId}`)}`,\n 'Next Steps',\n )\n } catch (error) {\n spinner.stop(pc.red('✗ Failed'))\n const message = error instanceof Error ? error.message : 'Unknown error'\n p.log.error(pc.red(`✗ ${message}`))\n if (options.debug && error instanceof Error && error.stack) {\n log.error(`Stack trace: ${error.stack}`)\n }\n process.exit(1)\n }\n}\n"],"names":["p","spawn","path","pc","Project","createDeployment","getTenantDetails","performDeployment","getValidAccessToken","getValidProjectToken","TokenStore","collectStaticAssets","createLambdaZip","getFileSize","detectBuild","getBuildCommand","log","getPackageManager","readFigmaConfig","findPayloadConfig","isInProjectDirectory","uploadLambdaZip","uploadStaticAssets","loginCommand","formatBytes","bytes","k","sizes","i","Math","floor","parseFloat","pow","toFixed","formatDate","date","toLocaleString","day","hour","minute","month","timeZoneName","year","deployCommand","options","projectPath","process","cwd","spinner","error","red","note","exit","configPath","project","skipAddingFilesFromTsConfig","sourceFile","addSourceFileAtPath","config","tenantId","tokenStore","accessToken","message","yellow","start","buildInfo","stop","buildCmd","yes","shouldBuild","confirm","initialValue","isCancel","packageManager","buildCommand","buildProcess","stdio","stdout","on","data","lines","toString","split","forEach","line","trim","console","dim","stderr","exitCode","Promise","resolve","Error","success","green","debug","cyan","buildId","timestamp","join","staticAssets","zipPath","zipSize","length","shouldDeploy","deploymentId","codeUploadUrl","staticAssetUploadUrls","createResponse","uploadResults","uploaded","total","assetsFailed","assetsUploaded","warning","totalBytesUploaded","tenant","domain","stack"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/deploy.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport { spawn } from 'child_process'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { Project } from 'ts-morph'\n\nimport { createDeployment, getTenantDetails, performDeployment } from '../api/control-plane.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { collectStaticAssets, createLambdaZip, getFileSize } from '../utils/asset-collection.js'\nimport { detectBuild, getBuildCommand } from '../utils/build-detection.js'\nimport * as log from '../utils/log.js'\nimport { getPackageManager } from '../utils/package-manager.js'\nimport { readFigmaConfig } from '../utils/payload-config-ast.js'\nimport { findPayloadConfig } from '../utils/payload-config-finder.js'\nimport { isInProjectDirectory } from '../utils/project.js'\nimport { uploadLambdaZip, uploadStaticAssets } from '../utils/s3-upload.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for deploy command\n */\nexport interface DeployCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Tenant ID */\n id?: string\n /** Skip confirmation prompts */\n yes?: boolean\n}\n\n/**\n * Format bytes to human-readable string\n */\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n return '0 B'\n }\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format date to human-readable string in local time\n */\nfunction formatDate(date: Date): string {\n return date.toLocaleString('en-US', {\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n month: 'long',\n timeZoneName: 'short',\n year: 'numeric',\n })\n}\n\n/**\n * Execute the deploy command\n *\n * @param options - Command options\n */\nexport async function deployCommand(options: DeployCommandOptions): Promise<void> {\n const projectPath = process.cwd()\n const spinner = p.spinner()\n\n if (!options.id) {\n p.log.error(pc.red('✗ Tenant ID is required. Use --id <tenant_id> to specify.'))\n process.exit(1)\n }\n\n const tenantId = options.id\n\n try {\n // ===== PRE-FLIGHT CHECKS =====\n\n // Check if in project directory\n if (!(await isInProjectDirectory(projectPath))) {\n p.log.error(pc.red(\"✗ 'deploy' command is not available outside of a Payload project.\"))\n p.note(\n 'Create a project or connect an existing one to Figma: npx @payloadcms/figma init',\n 'Tip',\n )\n process.exit(1)\n }\n\n // Find and read payload config\n const configPath = await findPayloadConfig(projectPath)\n if (!configPath) {\n p.log.error(pc.red('✗ payload.config.ts not found'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Parse config with ts-morph\n const project = new Project({ skipAddingFilesFromTsConfig: true })\n const sourceFile = project.addSourceFileAtPath(configPath)\n\n // Read figma configuration from buildConfig\n const config = readFigmaConfig(sourceFile)\n if (!config || !config.contentSystemId) {\n p.log.error(pc.red('✗ No figma configuration found in payload.config.ts'))\n p.note('Run npx @payloadcms/figma init to configure your project.', 'Tip')\n process.exit(1)\n }\n\n // Check authentication\n const tokenStore = new TokenStore()\n\n let accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.message('Please log in to continue')\n await loginCommand()\n accessToken = await getValidAccessToken(tokenStore)\n if (!accessToken) {\n p.log.error(pc.red('✗ Authentication failed'))\n process.exit(1)\n }\n }\n\n // Get project token\n try {\n await getValidProjectToken(tokenStore, tenantId)\n } catch (error) {\n p.log.error(pc.yellow('⚠ Project token invalid'))\n throw error\n }\n\n // ===== BUILD VALIDATION =====\n\n spinner.start('Checking for build...')\n let buildInfo = await detectBuild(projectPath)\n\n if (!buildInfo) {\n spinner.stop(pc.yellow('⚠ No build found for this project.'))\n\n // Try to find build command\n const buildCmd = await getBuildCommand(projectPath)\n\n if (!buildCmd) {\n p.log.error('No build script found in package.json')\n p.note('Add a build script to package.json: \"build\": \"next build\"', 'Tip')\n process.exit(1)\n }\n\n // Prompt to run build\n if (!options.yes) {\n const shouldBuild = await p.confirm({\n initialValue: true,\n message: `Build command found in package.json. Run it?`,\n })\n\n if (p.isCancel(shouldBuild) || !shouldBuild) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // Run build\n const packageManager = await getPackageManager(projectPath)\n const buildCommand = `${packageManager} run build`\n spinner.stop(`Running ${buildCommand}...\\n`)\n\n try {\n // Stream build output to user with formatting\n const buildProcess = spawn(packageManager, ['run', 'build'], {\n cwd: projectPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n // Indent and dim output\n buildProcess.stdout?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard output\n }\n })\n })\n\n buildProcess.stderr?.on('data', (data) => {\n const lines = data.toString().split('\\n')\n lines.forEach((line: string) => {\n if (line.trim()) {\n // eslint-disable-next-line no-console\n console.log(pc.dim(` ${line}`)) // Standard error\n }\n })\n })\n\n const exitCode = await new Promise<number>((resolve) => {\n buildProcess.on('close', resolve)\n })\n\n if (exitCode !== 0) {\n throw new Error(`Build process exited with code ${exitCode}`)\n }\n\n p.log.success(pc.green('✓ Build completed'))\n } catch (error) {\n p.log.error(pc.red('✗ Build failed'))\n if (error instanceof Error && options.debug) {\n log.error(`Build error: ${error.message}`)\n }\n process.exit(1)\n }\n\n // Re-check for build\n buildInfo = await detectBuild(projectPath)\n if (!buildInfo) {\n p.log.error(pc.red('✗ Build completed but standalone build not found'))\n p.note('Ensure next.config.js has output: \"standalone\"', 'Check Lambda Configuration')\n process.exit(1)\n }\n } else {\n spinner.stop(pc.green('✓ Build found'))\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n ].join('\\n'),\n 'Build Details',\n )\n }\n\n // ===== DEPLOYMENT PREPARATION =====\n\n // Create Lambda zip\n spinner.start('Creating deployment package...')\n try {\n await createLambdaZip(projectPath)\n spinner.stop(pc.green('✓ Deployment package created'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment package'))\n throw error\n }\n\n // Collect static assets\n spinner.start('Collecting static assets...')\n const staticAssets = await collectStaticAssets(projectPath)\n const zipPath = path.join(projectPath, 'lambda.zip')\n const zipSize = await getFileSize(zipPath)\n spinner.stop(pc.green(`✓ ${staticAssets.length} static assets detected`))\n\n log.debug(`Lambda zip size: ${formatBytes(zipSize)}`)\n log.debug(`Static assets: ${staticAssets.length} files`)\n\n // ===== DEPLOYMENT CONFIRMATION =====\n\n if (!options.yes) {\n p.note(\n [\n `${pc.cyan('Build ID:')} ${buildInfo.buildId}`,\n `${pc.cyan('Date:')} ${formatDate(buildInfo.timestamp)}`,\n `${pc.cyan('Code size:')} ${formatBytes(zipSize)}`,\n `${pc.cyan('Static assets:')} ${staticAssets.length} files`,\n ].join('\\n'),\n 'Details',\n )\n\n const shouldDeploy = await p.confirm({\n initialValue: true,\n message: 'Deploy this build to Figma?',\n })\n\n if (p.isCancel(shouldDeploy) || !shouldDeploy) {\n p.log.message('Cancelling deployment...')\n process.exit(0)\n }\n }\n\n // ===== DEPLOYMENT EXECUTION =====\n\n // Step 1: Create deployment\n spinner.start('Creating deployment...')\n let deploymentId: string\n let codeUploadUrl: string\n let staticAssetUploadUrls: Record<string, string>\n\n try {\n const createResponse = await createDeployment(accessToken, tenantId, {\n staticAssets,\n })\n\n deploymentId = createResponse.deploymentId\n codeUploadUrl = createResponse.codeUploadUrl\n staticAssetUploadUrls = createResponse.staticAssetUploadUrls\n\n log.debug(`Deployment ID: ${deploymentId}`)\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to create deployment'))\n throw error\n }\n\n // Step 2: Upload code\n spinner.message(`Uploading code (${formatBytes(zipSize)})...`)\n try {\n await uploadLambdaZip(zipPath, codeUploadUrl)\n spinner.stop(pc.green(`✓ Code uploaded (${formatBytes(zipSize)})`))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload code'))\n throw error\n }\n\n // Step 3: Upload static assets\n if (staticAssets.length > 0) {\n spinner.start('Uploading static assets...')\n\n try {\n const uploadResults = await uploadStaticAssets(\n projectPath,\n staticAssetUploadUrls,\n (uploaded, total) => {\n spinner.message(`Uploading static assets (${uploaded}/${total})...`)\n },\n )\n\n if (uploadResults.assetsFailed > 0) {\n spinner.stop(\n pc.yellow(\n `⚠ ${uploadResults.assetsUploaded}/${staticAssets.length} assets uploaded (${uploadResults.assetsFailed} failed)`,\n ),\n )\n p.log.warning(\n `${uploadResults.assetsFailed} assets failed to upload. Deployment may be incomplete.`,\n )\n } else {\n spinner.stop(\n pc.green(\n `✓ Static assets uploaded (${uploadResults.assetsUploaded} files, ${formatBytes(uploadResults.totalBytesUploaded)})`,\n ),\n )\n }\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to upload assets'))\n throw error\n }\n }\n\n // Step 4: Perform deployment\n spinner.start('Performing deployment...')\n try {\n await performDeployment(accessToken, tenantId, {\n deploymentId,\n })\n spinner.stop(pc.green('✓ Deployment initiated'))\n } catch (error) {\n spinner.stop(pc.red('✗ Failed to perform deployment'))\n throw error\n }\n\n // TODO: Add deployment progress tracking\n // Future: Poll deployment status and show progress\n // API endpoint: GET /v1/tenant/{tenant_id}/deploy/{deployment_id}/status\n\n // Success output\n p.log.message('This usually takes 2-3 minutes to complete.')\n\n // Get tenant details for URL\n try {\n const tenant = await getTenantDetails(accessToken, tenantId)\n if (tenant.domain) {\n p.log.message(`View: ${pc.cyan(`https://${tenant.domain}/`)}`)\n }\n } catch {\n // Non-critical - just skip URL display\n }\n\n p.note(\n `Manage your deployment at:\\n${pc.cyan(`https://cms.figma.com/manage/tenants/${tenantId}`)}`,\n 'Next Steps',\n )\n } catch (error) {\n spinner.stop(pc.red('✗ Failed'))\n const message = error instanceof Error ? error.message : 'Unknown error'\n p.log.error(pc.red(`✗ ${message}`))\n if (options.debug && error instanceof Error && error.stack) {\n log.error(`Stack trace: ${error.stack}`)\n }\n process.exit(1)\n }\n}\n"],"names":["p","spawn","path","pc","Project","createDeployment","getTenantDetails","performDeployment","getValidAccessToken","getValidProjectToken","TokenStore","collectStaticAssets","createLambdaZip","getFileSize","detectBuild","getBuildCommand","log","getPackageManager","readFigmaConfig","findPayloadConfig","isInProjectDirectory","uploadLambdaZip","uploadStaticAssets","loginCommand","formatBytes","bytes","k","sizes","i","Math","floor","parseFloat","pow","toFixed","formatDate","date","toLocaleString","day","hour","minute","month","timeZoneName","year","deployCommand","options","projectPath","process","cwd","spinner","id","error","red","exit","tenantId","note","configPath","project","skipAddingFilesFromTsConfig","sourceFile","addSourceFileAtPath","config","contentSystemId","tokenStore","accessToken","message","yellow","start","buildInfo","stop","buildCmd","yes","shouldBuild","confirm","initialValue","isCancel","packageManager","buildCommand","buildProcess","stdio","stdout","on","data","lines","toString","split","forEach","line","trim","console","dim","stderr","exitCode","Promise","resolve","Error","success","green","debug","cyan","buildId","timestamp","join","staticAssets","zipPath","zipSize","length","shouldDeploy","deploymentId","codeUploadUrl","staticAssetUploadUrls","createResponse","uploadResults","uploaded","total","assetsFailed","assetsUploaded","warning","totalBytesUploaded","tenant","domain","stack"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA6BA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mDAAmD;IACnD,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAiDD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmW5E"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA0BA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,mDAAmD;IACnD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mDAAmD;IACnD,GAAG,CAAC,EAAE,OAAO,CAAA;CACd;AAiDD;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsR5E"}
@@ -2,7 +2,6 @@ import * as p from '@clack/prompts';
2
2
  import fs from 'fs/promises';
3
3
  import path from 'path';
4
4
  import pc from 'picocolors';
5
- import { ControlPlaneError, getTenantDetails } from '../api/control-plane.js';
6
5
  import { FigmaApiError } from '../api/figma-api.js';
7
6
  import { getValidAccessToken } from '../auth/oauth-flow.js';
8
7
  import { getValidProjectToken, ProjectTokenError } from '../auth/project-token.js';
@@ -61,45 +60,30 @@ import { loginCommand } from './login.js';
61
60
  // Check authentication
62
61
  const tokenStore = new TokenStore();
63
62
  const s = p.spinner();
64
- let accessToken;
65
63
  if (options.skipAuth) {
66
64
  // Skip authentication for testing/development
67
65
  p.log.warn(pc.yellow('Skipping authentication (--skip-auth mode)'));
68
- accessToken = 'mock-access-token';
69
66
  } else {
70
67
  try {
71
68
  // Check for valid cached tokens first (no API call needed)
72
- if (tokenStore.hasValidTokens()) {
73
- // Use cached token silently - no spinner needed
74
- accessToken = tokenStore.getAccessToken();
75
- } else {
69
+ if (!tokenStore.hasValidTokens()) {
76
70
  // Need to refresh or authenticate - show spinner for API call
77
71
  s.start('Checking authentication...');
78
72
  const token = await getValidAccessToken(tokenStore);
79
73
  if (!token) {
80
74
  s.stop(pc.yellow('⚠ Not authenticated'));
81
75
  p.log.info('Authentication required to continue');
82
- // Prompt user to authenticate now
83
- const shouldAuth = await p.confirm({
84
- initialValue: true,
85
- message: 'Would you like to authenticate now?'
86
- });
87
- if (p.isCancel(shouldAuth) || !shouldAuth) {
88
- p.cancel('Operation cancelled');
89
- process.exit(0);
90
- }
91
76
  // Run login command
92
- await loginCommand();
77
+ await loginCommand({
78
+ showNextSteps: false
79
+ });
93
80
  // Get token after auth
94
81
  const newToken = await getValidAccessToken(tokenStore);
95
82
  if (!newToken) {
96
83
  p.log.error('Authentication failed');
97
84
  process.exit(1);
98
85
  }
99
- accessToken = newToken;
100
- p.log.success(pc.green('✓ Authenticated'));
101
86
  } else {
102
- accessToken = token;
103
87
  s.stop(pc.green('✓ Authenticated'));
104
88
  }
105
89
  }
@@ -113,57 +97,13 @@ import { loginCommand } from './login.js';
113
97
  // Note: We no longer check for figma.config.json here
114
98
  // Instead, the AST detection will check if figma object already exists in payload.config.ts
115
99
  // and skip modification if it does (unless --force is used)
116
- // Step 3: Get CMS ID with retry loop
100
+ // Step 3: Get CMS ID (required argument)
117
101
  log.debug('Configuring Project...');
118
- let tenantId = options.id;
119
- let selectedTenant;
120
- while(!selectedTenant){
121
- // Prompt for ID if not provided
122
- if (!tenantId) {
123
- const input = await p.text({
124
- message: 'Enter your CMS ID:',
125
- placeholder: 'tenant_abc123',
126
- validate: (value)=>{
127
- if (!value || typeof value !== 'string') {
128
- return 'CMS ID is required';
129
- }
130
- return undefined;
131
- }
132
- });
133
- if (p.isCancel(input)) {
134
- p.cancel('Operation cancelled');
135
- process.exit(0);
136
- }
137
- tenantId = input;
138
- }
139
- // Try to fetch tenant details
140
- try {
141
- log.debug('Using mock Control Plane API (no real network calls)');
142
- selectedTenant = await getTenantDetails(accessToken, tenantId);
143
- log.debug(`Using: ${selectedTenant.domain}`);
144
- } catch (error) {
145
- p.log.error(pc.red('✗ Failed to fetch CMS details'));
146
- // Check if permission error (403)
147
- if (error instanceof ControlPlaneError && error.statusCode === 403) {
148
- p.log.error('You do not have permission to access the provided CMS ID. Please try again.');
149
- } else if (error instanceof ControlPlaneError && error.statusCode === 404) {
150
- p.log.error('Tenant ID not found. Verify the ID is correct.');
151
- } else {
152
- p.log.error(error instanceof Error ? error.message : 'Unknown error');
153
- }
154
- // Clear tenantId to prompt again
155
- tenantId = undefined;
156
- // Ask if they want to retry
157
- const shouldRetry = await p.confirm({
158
- initialValue: true,
159
- message: 'Would you like to try a different CMS ID?'
160
- });
161
- if (p.isCancel(shouldRetry) || !shouldRetry) {
162
- p.cancel('Operation cancelled');
163
- process.exit(1);
164
- }
165
- }
102
+ if (!options.id) {
103
+ p.log.error('CMS ID is required. Use --id <tenant_id>');
104
+ process.exit(1);
166
105
  }
106
+ const tenantId = options.id;
167
107
  // Step 4: Detect or scaffold Payload project
168
108
  const isInProject = await isInProjectDirectory();
169
109
  if (isInProject) {
@@ -196,8 +136,8 @@ import { loginCommand } from './login.js';
196
136
  }
197
137
  s.start('Checking Payload configuration...');
198
138
  const modResult = await ensurePayloadFigmaConfig(process.cwd(), projectInfo.packageManager || 'pnpm', {
139
+ contentSystemId: tenantId,
199
140
  region: options.region || 'us-east-1',
200
- tenantId: selectedTenant.id,
201
141
  useContentSystem: !options.noContentSystem
202
142
  });
203
143
  if (!modResult.success) {
@@ -241,14 +181,12 @@ import { loginCommand } from './login.js';
241
181
  }
242
182
  // Generate project token (unless skipping auth)
243
183
  if (!options.skipAuth) {
244
- await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s);
184
+ await generateProjectTokenWithFeedback(tokenStore, tenantId, s);
245
185
  }
246
186
  // Success message for existing project
247
187
  p.outro(pc.green('✓ Project initialized successfully!'));
248
188
  const nextSteps = [
249
- selectedTenant.status === 'provisioning' ? 'Wait for CMS provisioning to complete (check status with `@payloadcms/figma list`)' : undefined,
250
- 'Start development server: `pnpm dev`',
251
- `Access your CMS at: ${pc.cyan(`https://${selectedTenant.domain}`)}`
189
+ 'Start development server: `pnpm dev`'
252
190
  ].filter(Boolean);
253
191
  p.note(nextSteps.join('\n'), 'Next Steps');
254
192
  } else {
@@ -300,8 +238,8 @@ import { loginCommand } from './login.js';
300
238
  // Modify Payload configuration
301
239
  s.start('Checking Payload configuration...');
302
240
  const modResult = await ensurePayloadFigmaConfig(fullPath, 'pnpm', {
241
+ contentSystemId: tenantId,
303
242
  region: options.region || 'us-east-1',
304
- tenantId: selectedTenant.id,
305
243
  useContentSystem: !options.noContentSystem
306
244
  });
307
245
  if (!modResult.success) {
@@ -325,7 +263,7 @@ import { loginCommand } from './login.js';
325
263
  }
326
264
  // Generate project token (unless skipping auth)
327
265
  if (!options.skipAuth) {
328
- await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s);
266
+ await generateProjectTokenWithFeedback(tokenStore, tenantId, s);
329
267
  }
330
268
  // Initialize git repository (after all files including lock file are ready)
331
269
  initializeGitRepo(fullPath);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport fs from 'fs/promises'\nimport path from 'path'\nimport pc from 'picocolors'\n\nimport type { Tenant } from '../types/config.js'\n\nimport { ControlPlaneError, getTenantDetails } from '../api/control-plane.js'\nimport { FigmaApiError } from '../api/figma-api.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken, ProjectTokenError } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { isDebug } from '../utils/is-debug.js'\nimport * as log from '../utils/log.js'\nimport {\n displayManualInstructions,\n ensurePayloadFigmaConfig,\n} from '../utils/payload-config-modifier.js'\nimport {\n detectPayloadProject,\n hasRequiredDependencies,\n initializeGitRepo,\n installDependencies,\n isInProjectDirectory,\n scaffoldProject,\n validatePayloadVersion,\n} from '../utils/project.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for init command\n */\nexport interface InitCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Force reconfiguration of existing project */\n force?: boolean\n /** Tenant ID to use (optional - will prompt if not provided) */\n id?: string\n /** Project name (for scaffolding) */\n name?: string\n /** Disable Content System (defaults to enabled) */\n noContentSystem?: boolean\n /** AWS region for deployment (defaults to us-east-1) */\n region?: string\n /** Skip authentication check (for testing/development) */\n skipAuth?: boolean\n /** Skip prompts and use defaults where possible */\n yes?: boolean\n}\n\n/**\n * Generate and store project token for a tenant\n * Non-blocking - will show warning but not exit on failure\n * Only shows feedback if DEBUG mode is enabled, otherwise runs silently\n *\n * @param tokenStore - Token store instance\n * @param tenantId - Tenant ID to generate token for\n * @param spinner - Clack spinner instance for status updates (only used in debug mode)\n */\nasync function generateProjectTokenWithFeedback(\n tokenStore: TokenStore,\n tenantId: string,\n spinner: ReturnType<typeof p.spinner>,\n): Promise<void> {\n if (isDebug()) {\n spinner.start('Generating project token...')\n }\n\n try {\n const projectToken = await getValidProjectToken(tokenStore, tenantId)\n if (isDebug()) {\n if (projectToken) {\n spinner.stop(pc.green('✓ Project token generated'))\n } else {\n spinner.stop(pc.yellow('⚠ Project token not generated (authentication required)'))\n }\n }\n } catch (error) {\n if (isDebug()) {\n spinner.stop(pc.yellow('⚠ Project token generation failed'))\n }\n // Always show failures, even without debug\n if (error instanceof ProjectTokenError || error instanceof FigmaApiError) {\n log.warning(error.message)\n p.note(\n 'Project token is used for authenticating to the Content API.\\nYou can continue without it, but may need to regenerate later.',\n 'Note',\n )\n } else {\n log.warning(\n `Unable to retrieve project token: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n // Don't exit - token generation failure shouldn't block initialization\n }\n}\n\n/**\n * Handle the `init` command\n *\n * Sets up a project by:\n * 1. Checking authentication\n * 2. Detecting/scaffolding Payload project\n * 3. Fetching tenant details\n * 4. Storing configuration\n *\n * @param options - Command options\n */\nexport async function initCommand(options: InitCommandOptions): Promise<void> {\n // Check authentication\n const tokenStore = new TokenStore()\n const s = p.spinner()\n\n let accessToken: string\n\n if (options.skipAuth) {\n // Skip authentication for testing/development\n p.log.warn(pc.yellow('Skipping authentication (--skip-auth mode)'))\n accessToken = 'mock-access-token'\n } else {\n try {\n // Check for valid cached tokens first (no API call needed)\n if (tokenStore.hasValidTokens()) {\n // Use cached token silently - no spinner needed\n accessToken = tokenStore.getAccessToken()!\n } else {\n // Need to refresh or authenticate - show spinner for API call\n s.start('Checking authentication...')\n const token = await getValidAccessToken(tokenStore)\n if (!token) {\n s.stop(pc.yellow('⚠ Not authenticated'))\n p.log.info('Authentication required to continue')\n\n // Prompt user to authenticate now\n const shouldAuth = await p.confirm({\n initialValue: true,\n message: 'Would you like to authenticate now?',\n })\n\n if (p.isCancel(shouldAuth) || !shouldAuth) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n // Run login command\n await loginCommand()\n\n // Get token after auth\n const newToken = await getValidAccessToken(tokenStore)\n if (!newToken) {\n p.log.error('Authentication failed')\n process.exit(1)\n }\n accessToken = newToken\n p.log.success(pc.green('✓ Authenticated'))\n } else {\n accessToken = token\n s.stop(pc.green('✓ Authenticated'))\n }\n }\n } catch (error) {\n s.stop(pc.red('✗ Authentication failed'))\n log.error(error instanceof Error ? error.message : 'Unknown error')\n p.note('Run `figma auth` to authenticate', 'Tip')\n process.exit(1)\n }\n }\n\n // Note: We no longer check for figma.config.json here\n // Instead, the AST detection will check if figma object already exists in payload.config.ts\n // and skip modification if it does (unless --force is used)\n\n // Step 3: Get CMS ID with retry loop\n log.debug('Configuring Project...')\n\n let tenantId = options.id\n let selectedTenant: Tenant | undefined\n\n while (!selectedTenant) {\n // Prompt for ID if not provided\n if (!tenantId) {\n const input = await p.text({\n message: 'Enter your CMS ID:',\n placeholder: 'tenant_abc123',\n validate: (value) => {\n if (!value || typeof value !== 'string') {\n return 'CMS ID is required'\n }\n return undefined\n },\n })\n\n if (p.isCancel(input)) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n tenantId = input\n }\n\n // Try to fetch tenant details\n try {\n log.debug('Using mock Control Plane API (no real network calls)')\n selectedTenant = await getTenantDetails(accessToken, tenantId)\n log.debug(`Using: ${selectedTenant.domain}`)\n } catch (error) {\n p.log.error(pc.red('✗ Failed to fetch CMS details'))\n\n // Check if permission error (403)\n if (error instanceof ControlPlaneError && error.statusCode === 403) {\n p.log.error('You do not have permission to access the provided CMS ID. Please try again.')\n } else if (error instanceof ControlPlaneError && error.statusCode === 404) {\n p.log.error('Tenant ID not found. Verify the ID is correct.')\n } else {\n p.log.error(error instanceof Error ? error.message : 'Unknown error')\n }\n\n // Clear tenantId to prompt again\n tenantId = undefined\n\n // Ask if they want to retry\n const shouldRetry = await p.confirm({\n initialValue: true,\n message: 'Would you like to try a different CMS ID?',\n })\n\n if (p.isCancel(shouldRetry) || !shouldRetry) {\n p.cancel('Operation cancelled')\n process.exit(1)\n }\n }\n }\n\n // Step 4: Detect or scaffold Payload project\n const isInProject = await isInProjectDirectory()\n\n if (isInProject) {\n // ===== EXISTING PROJECT FLOW =====\n log.debug('Project directory detected')\n\n // Detect Payload\n const projectInfo = await detectPayloadProject()\n\n if (projectInfo.hasPayload) {\n // Validate existing Payload version\n if (projectInfo.payloadVersion && !validatePayloadVersion(projectInfo.payloadVersion)) {\n p.log.warn(\n pc.yellow(\n `Payload version ${projectInfo.payloadVersion} detected. Version 3.x is required.`,\n ),\n )\n p.note('Upgrade to Payload 3.x before continuing', 'Action Required')\n process.exit(1)\n }\n\n p.log.success(pc.green(`✓ Payload ${projectInfo.payloadVersion || 'detected'}`))\n\n // Check dependencies\n s.start('Checking dependencies...')\n const hasDeps = await hasRequiredDependencies(process.cwd())\n s.stop(pc.green('✓ Dependencies checked'))\n\n if (!hasDeps) {\n const shouldInstall = await p.confirm({\n initialValue: true,\n message: 'Install dependencies now?',\n })\n\n if (!p.isCancel(shouldInstall) && shouldInstall) {\n s.start('Installing dependencies...')\n await installDependencies(process.cwd(), projectInfo.packageManager || 'pnpm')\n s.stop(pc.green('✓ Dependencies installed'))\n }\n }\n\n s.start('Checking Payload configuration...')\n const modResult = await ensurePayloadFigmaConfig(\n process.cwd(),\n projectInfo.packageManager || 'pnpm',\n {\n region: options.region || 'us-east-1',\n tenantId: selectedTenant.id,\n useContentSystem: !options.noContentSystem,\n },\n )\n\n if (!modResult.success) {\n s.stop(pc.red('✗ Configuration check failed'))\n displayManualInstructions(modResult.error || 'Unknown error')\n process.exit(1)\n }\n\n if (modResult.modified) {\n s.stop(pc.green('✓ Payload configuration updated'))\n if (modResult.changes.length > 0) {\n modResult.changes.forEach((change) => log.debug(pc.dim(` → ${change}`)))\n }\n } else {\n s.stop(pc.green('✓ Payload configuration valid'))\n }\n\n // Display warnings if any\n if (modResult.warnings && modResult.warnings.length > 0) {\n modResult.warnings.forEach((warning) => {\n p.log.warn(pc.yellow(`⚠ ${warning}`))\n })\n }\n } else {\n // Has package.json but no Payload - offer to add Payload\n p.log.warn(pc.yellow('⚠ No Payload detected in this project'))\n\n const shouldAddPayload = await p.confirm({\n initialValue: true,\n message: 'Would you like to add Payload to this project?',\n })\n\n if (p.isCancel(shouldAddPayload)) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n if (!shouldAddPayload) {\n p.log.error('Payload is required to use Figma CMS')\n process.exit(1)\n }\n\n // TODO: Add Payload to existing project (future enhancement)\n p.log.error('Adding Payload to existing projects is not yet supported')\n p.note('Create a new project or manually add Payload dependencies', 'Action Required')\n process.exit(1)\n }\n\n // Generate project token (unless skipping auth)\n if (!options.skipAuth) {\n await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s)\n }\n\n // Success message for existing project\n p.outro(pc.green('✓ Project initialized successfully!'))\n\n const nextSteps = [\n selectedTenant.status === 'provisioning'\n ? 'Wait for CMS provisioning to complete (check status with `@payloadcms/figma list`)'\n : undefined,\n 'Start development server: `pnpm dev`',\n `Access your CMS at: ${pc.cyan(`https://${selectedTenant.domain}`)}`,\n ].filter(Boolean)\n\n p.note(nextSteps.join('\\n'), 'Next Steps')\n } else {\n // ===== NEW PROJECT FLOW =====\n // p.log.info('No project detected - Creating New Project')\n\n // Prompt for path\n const projectPathInput = await p.text({\n initialValue: './',\n message: 'Enter path to create project:',\n placeholder: './my-cms-project',\n validate: (value) => {\n if (!value) {\n return 'Path is required'\n }\n // Allow relative or absolute paths\n return undefined\n },\n })\n\n if (p.isCancel(projectPathInput)) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n const projectPath = projectPathInput\n const fullPath = path.resolve(process.cwd(), projectPath)\n\n // Get project name from path or prompt\n const projectName = options.name || path.basename(fullPath)\n\n // Create directory\n try {\n await fs.mkdir(fullPath, { recursive: true })\n } catch (error) {\n p.log.error(\n `Failed to create directory: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n process.exit(1)\n }\n\n // Scaffold project\n s.start('Downloading template from GitHub...')\n try {\n await scaffoldProject(fullPath, projectName)\n s.stop(pc.green('✓ Template downloaded'))\n\n s.start('Installing dependencies...')\n await installDependencies(fullPath, 'pnpm')\n s.stop(pc.green('✓ Dependencies installed'))\n } catch (error) {\n s.stop(pc.red('✗ Failed'))\n log.error(error instanceof Error ? error.message : 'Unknown error')\n process.exit(1)\n }\n\n // Modify Payload configuration\n s.start('Checking Payload configuration...')\n const modResult = await ensurePayloadFigmaConfig(fullPath, 'pnpm', {\n region: options.region || 'us-east-1',\n tenantId: selectedTenant.id,\n useContentSystem: !options.noContentSystem,\n })\n\n if (!modResult.success) {\n s.stop(pc.red('✗ Configuration check failed'))\n displayManualInstructions(modResult.error || 'Unknown error')\n process.exit(1)\n }\n\n if (modResult.modified) {\n s.stop(pc.green('✓ Payload configuration updated'))\n if (modResult.changes.length > 0) {\n modResult.changes.forEach((change) => log.debug(pc.dim(` → ${change}`)))\n }\n } else {\n s.stop(pc.green('✓ Payload configuration valid'))\n }\n\n // Display warnings if any\n if (modResult.warnings && modResult.warnings.length > 0) {\n modResult.warnings.forEach((warning) => {\n p.log.warn(pc.yellow(`⚠ ${warning}`))\n })\n }\n\n // Generate project token (unless skipping auth)\n if (!options.skipAuth) {\n await generateProjectTokenWithFeedback(tokenStore, selectedTenant.id, s)\n }\n\n // Initialize git repository (after all files including lock file are ready)\n initializeGitRepo(fullPath)\n\n // Success message for NEW project\n p.log.step(pc.bgGreen(pc.black(' Project created successfully! ')))\n\n const relativePath = path.relative(process.cwd(), fullPath)\n const nextSteps: string[] = []\n\n // Only show cd command if user needs to navigate\n if (relativePath && relativePath !== '.') {\n nextSteps.push(`cd ${relativePath}`)\n }\n\n nextSteps.push(\n 'pnpm dev or follow directions in README.md',\n '',\n 'Documentation:',\n '- Getting Started: https://payloadcms.com/docs/getting-started/what-is-payload',\n '- Configuration: https://payloadcms.com/docs/configuration/overview',\n )\n\n p.note(nextSteps.join('\\n'), 'Next Steps')\n p.outro(pc.green('✓ Done'))\n }\n}\n"],"names":["p","fs","path","pc","ControlPlaneError","getTenantDetails","FigmaApiError","getValidAccessToken","getValidProjectToken","ProjectTokenError","TokenStore","isDebug","log","displayManualInstructions","ensurePayloadFigmaConfig","detectPayloadProject","hasRequiredDependencies","initializeGitRepo","installDependencies","isInProjectDirectory","scaffoldProject","validatePayloadVersion","loginCommand","generateProjectTokenWithFeedback","tokenStore","tenantId","spinner","start","projectToken","stop","green","yellow","error","warning","message","note","Error","initCommand","options","s","accessToken","skipAuth","warn","hasValidTokens","getAccessToken","token","info","shouldAuth","confirm","initialValue","isCancel","cancel","process","exit","newToken","success","red","debug","id","selectedTenant","input","text","placeholder","validate","value","undefined","domain","statusCode","shouldRetry","isInProject","projectInfo","hasPayload","payloadVersion","hasDeps","cwd","shouldInstall","packageManager","modResult","region","useContentSystem","noContentSystem","modified","changes","length","forEach","change","dim","warnings","shouldAddPayload","outro","nextSteps","status","cyan","filter","Boolean","join","projectPathInput","projectPath","fullPath","resolve","projectName","name","basename","mkdir","recursive","step","bgGreen","black","relativePath","relative","push"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/commands/init.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport fs from 'fs/promises'\nimport path from 'path'\nimport pc from 'picocolors'\n\nimport { FigmaApiError } from '../api/figma-api.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport { getValidProjectToken, ProjectTokenError } from '../auth/project-token.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { isDebug } from '../utils/is-debug.js'\nimport * as log from '../utils/log.js'\nimport {\n displayManualInstructions,\n ensurePayloadFigmaConfig,\n} from '../utils/payload-config-modifier.js'\nimport {\n detectPayloadProject,\n hasRequiredDependencies,\n initializeGitRepo,\n installDependencies,\n isInProjectDirectory,\n scaffoldProject,\n validatePayloadVersion,\n} from '../utils/project.js'\nimport { loginCommand } from './login.js'\n\n/**\n * Options for init command\n */\nexport interface InitCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n /** Force reconfiguration of existing project */\n force?: boolean\n /** Tenant ID to use (optional - will prompt if not provided) */\n id?: string\n /** Project name (for scaffolding) */\n name?: string\n /** Disable Content System (defaults to enabled) */\n noContentSystem?: boolean\n /** AWS region for deployment (defaults to us-east-1) */\n region?: string\n /** Skip authentication check (for testing/development) */\n skipAuth?: boolean\n /** Skip prompts and use defaults where possible */\n yes?: boolean\n}\n\n/**\n * Generate and store project token for a tenant\n * Non-blocking - will show warning but not exit on failure\n * Only shows feedback if DEBUG mode is enabled, otherwise runs silently\n *\n * @param tokenStore - Token store instance\n * @param tenantId - Tenant ID to generate token for\n * @param spinner - Clack spinner instance for status updates (only used in debug mode)\n */\nasync function generateProjectTokenWithFeedback(\n tokenStore: TokenStore,\n tenantId: string,\n spinner: ReturnType<typeof p.spinner>,\n): Promise<void> {\n if (isDebug()) {\n spinner.start('Generating project token...')\n }\n\n try {\n const projectToken = await getValidProjectToken(tokenStore, tenantId)\n if (isDebug()) {\n if (projectToken) {\n spinner.stop(pc.green('✓ Project token generated'))\n } else {\n spinner.stop(pc.yellow('⚠ Project token not generated (authentication required)'))\n }\n }\n } catch (error) {\n if (isDebug()) {\n spinner.stop(pc.yellow('⚠ Project token generation failed'))\n }\n // Always show failures, even without debug\n if (error instanceof ProjectTokenError || error instanceof FigmaApiError) {\n log.warning(error.message)\n p.note(\n 'Project token is used for authenticating to the Content API.\\nYou can continue without it, but may need to regenerate later.',\n 'Note',\n )\n } else {\n log.warning(\n `Unable to retrieve project token: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n // Don't exit - token generation failure shouldn't block initialization\n }\n}\n\n/**\n * Handle the `init` command\n *\n * Sets up a project by:\n * 1. Checking authentication\n * 2. Detecting/scaffolding Payload project\n * 3. Fetching tenant details\n * 4. Storing configuration\n *\n * @param options - Command options\n */\nexport async function initCommand(options: InitCommandOptions): Promise<void> {\n // Check authentication\n const tokenStore = new TokenStore()\n const s = p.spinner()\n\n if (options.skipAuth) {\n // Skip authentication for testing/development\n p.log.warn(pc.yellow('Skipping authentication (--skip-auth mode)'))\n } else {\n try {\n // Check for valid cached tokens first (no API call needed)\n if (!tokenStore.hasValidTokens()) {\n // Need to refresh or authenticate - show spinner for API call\n s.start('Checking authentication...')\n const token = await getValidAccessToken(tokenStore)\n if (!token) {\n s.stop(pc.yellow('⚠ Not authenticated'))\n p.log.info('Authentication required to continue')\n\n // Run login command\n await loginCommand({ showNextSteps: false })\n\n // Get token after auth\n const newToken = await getValidAccessToken(tokenStore)\n if (!newToken) {\n p.log.error('Authentication failed')\n process.exit(1)\n }\n } else {\n s.stop(pc.green('✓ Authenticated'))\n }\n }\n } catch (error) {\n s.stop(pc.red('✗ Authentication failed'))\n log.error(error instanceof Error ? error.message : 'Unknown error')\n p.note('Run `figma auth` to authenticate', 'Tip')\n process.exit(1)\n }\n }\n\n // Note: We no longer check for figma.config.json here\n // Instead, the AST detection will check if figma object already exists in payload.config.ts\n // and skip modification if it does (unless --force is used)\n\n // Step 3: Get CMS ID (required argument)\n log.debug('Configuring Project...')\n\n if (!options.id) {\n p.log.error('CMS ID is required. Use --id <tenant_id>')\n process.exit(1)\n }\n\n const tenantId = options.id\n\n // Step 4: Detect or scaffold Payload project\n const isInProject = await isInProjectDirectory()\n\n if (isInProject) {\n // ===== EXISTING PROJECT FLOW =====\n log.debug('Project directory detected')\n\n // Detect Payload\n const projectInfo = await detectPayloadProject()\n\n if (projectInfo.hasPayload) {\n // Validate existing Payload version\n if (projectInfo.payloadVersion && !validatePayloadVersion(projectInfo.payloadVersion)) {\n p.log.warn(\n pc.yellow(\n `Payload version ${projectInfo.payloadVersion} detected. Version 3.x is required.`,\n ),\n )\n p.note('Upgrade to Payload 3.x before continuing', 'Action Required')\n process.exit(1)\n }\n\n p.log.success(pc.green(`✓ Payload ${projectInfo.payloadVersion || 'detected'}`))\n\n // Check dependencies\n s.start('Checking dependencies...')\n const hasDeps = await hasRequiredDependencies(process.cwd())\n s.stop(pc.green('✓ Dependencies checked'))\n\n if (!hasDeps) {\n const shouldInstall = await p.confirm({\n initialValue: true,\n message: 'Install dependencies now?',\n })\n\n if (!p.isCancel(shouldInstall) && shouldInstall) {\n s.start('Installing dependencies...')\n await installDependencies(process.cwd(), projectInfo.packageManager || 'pnpm')\n s.stop(pc.green('✓ Dependencies installed'))\n }\n }\n\n s.start('Checking Payload configuration...')\n const modResult = await ensurePayloadFigmaConfig(\n process.cwd(),\n projectInfo.packageManager || 'pnpm',\n {\n contentSystemId: tenantId,\n region: options.region || 'us-east-1',\n useContentSystem: !options.noContentSystem,\n },\n )\n\n if (!modResult.success) {\n s.stop(pc.red('✗ Configuration check failed'))\n displayManualInstructions(modResult.error || 'Unknown error')\n process.exit(1)\n }\n\n if (modResult.modified) {\n s.stop(pc.green('✓ Payload configuration updated'))\n if (modResult.changes.length > 0) {\n modResult.changes.forEach((change) => log.debug(pc.dim(` → ${change}`)))\n }\n } else {\n s.stop(pc.green('✓ Payload configuration valid'))\n }\n\n // Display warnings if any\n if (modResult.warnings && modResult.warnings.length > 0) {\n modResult.warnings.forEach((warning) => {\n p.log.warn(pc.yellow(`⚠ ${warning}`))\n })\n }\n } else {\n // Has package.json but no Payload - offer to add Payload\n p.log.warn(pc.yellow('⚠ No Payload detected in this project'))\n\n const shouldAddPayload = await p.confirm({\n initialValue: true,\n message: 'Would you like to add Payload to this project?',\n })\n\n if (p.isCancel(shouldAddPayload)) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n if (!shouldAddPayload) {\n p.log.error('Payload is required to use Figma CMS')\n process.exit(1)\n }\n\n // TODO: Add Payload to existing project (future enhancement)\n p.log.error('Adding Payload to existing projects is not yet supported')\n p.note('Create a new project or manually add Payload dependencies', 'Action Required')\n process.exit(1)\n }\n\n // Generate project token (unless skipping auth)\n if (!options.skipAuth) {\n await generateProjectTokenWithFeedback(tokenStore, tenantId, s)\n }\n\n // Success message for existing project\n p.outro(pc.green('✓ Project initialized successfully!'))\n\n const nextSteps = ['Start development server: `pnpm dev`'].filter(Boolean)\n\n p.note(nextSteps.join('\\n'), 'Next Steps')\n } else {\n // ===== NEW PROJECT FLOW =====\n // p.log.info('No project detected - Creating New Project')\n\n // Prompt for path\n const projectPathInput = await p.text({\n initialValue: './',\n message: 'Enter path to create project:',\n placeholder: './my-cms-project',\n validate: (value) => {\n if (!value) {\n return 'Path is required'\n }\n // Allow relative or absolute paths\n return undefined\n },\n })\n\n if (p.isCancel(projectPathInput)) {\n p.cancel('Operation cancelled')\n process.exit(0)\n }\n\n const projectPath = projectPathInput\n const fullPath = path.resolve(process.cwd(), projectPath)\n\n // Get project name from path or prompt\n const projectName = options.name || path.basename(fullPath)\n\n // Create directory\n try {\n await fs.mkdir(fullPath, { recursive: true })\n } catch (error) {\n p.log.error(\n `Failed to create directory: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n process.exit(1)\n }\n\n // Scaffold project\n s.start('Downloading template from GitHub...')\n try {\n await scaffoldProject(fullPath, projectName)\n s.stop(pc.green('✓ Template downloaded'))\n\n s.start('Installing dependencies...')\n await installDependencies(fullPath, 'pnpm')\n s.stop(pc.green('✓ Dependencies installed'))\n } catch (error) {\n s.stop(pc.red('✗ Failed'))\n log.error(error instanceof Error ? error.message : 'Unknown error')\n process.exit(1)\n }\n\n // Modify Payload configuration\n s.start('Checking Payload configuration...')\n const modResult = await ensurePayloadFigmaConfig(fullPath, 'pnpm', {\n contentSystemId: tenantId,\n region: options.region || 'us-east-1',\n useContentSystem: !options.noContentSystem,\n })\n\n if (!modResult.success) {\n s.stop(pc.red('✗ Configuration check failed'))\n displayManualInstructions(modResult.error || 'Unknown error')\n process.exit(1)\n }\n\n if (modResult.modified) {\n s.stop(pc.green('✓ Payload configuration updated'))\n if (modResult.changes.length > 0) {\n modResult.changes.forEach((change) => log.debug(pc.dim(` → ${change}`)))\n }\n } else {\n s.stop(pc.green('✓ Payload configuration valid'))\n }\n\n // Display warnings if any\n if (modResult.warnings && modResult.warnings.length > 0) {\n modResult.warnings.forEach((warning) => {\n p.log.warn(pc.yellow(`⚠ ${warning}`))\n })\n }\n\n // Generate project token (unless skipping auth)\n if (!options.skipAuth) {\n await generateProjectTokenWithFeedback(tokenStore, tenantId, s)\n }\n\n // Initialize git repository (after all files including lock file are ready)\n initializeGitRepo(fullPath)\n\n // Success message for NEW project\n p.log.step(pc.bgGreen(pc.black(' Project created successfully! ')))\n\n const relativePath = path.relative(process.cwd(), fullPath)\n const nextSteps: string[] = []\n\n // Only show cd command if user needs to navigate\n if (relativePath && relativePath !== '.') {\n nextSteps.push(`cd ${relativePath}`)\n }\n\n nextSteps.push(\n 'pnpm dev or follow directions in README.md',\n '',\n 'Documentation:',\n '- Getting Started: https://payloadcms.com/docs/getting-started/what-is-payload',\n '- Configuration: https://payloadcms.com/docs/configuration/overview',\n )\n\n p.note(nextSteps.join('\\n'), 'Next Steps')\n p.outro(pc.green('✓ Done'))\n }\n}\n"],"names":["p","fs","path","pc","FigmaApiError","getValidAccessToken","getValidProjectToken","ProjectTokenError","TokenStore","isDebug","log","displayManualInstructions","ensurePayloadFigmaConfig","detectPayloadProject","hasRequiredDependencies","initializeGitRepo","installDependencies","isInProjectDirectory","scaffoldProject","validatePayloadVersion","loginCommand","generateProjectTokenWithFeedback","tokenStore","tenantId","spinner","start","projectToken","stop","green","yellow","error","warning","message","note","Error","initCommand","options","s","skipAuth","warn","hasValidTokens","token","info","showNextSteps","newToken","process","exit","red","debug","id","isInProject","projectInfo","hasPayload","payloadVersion","success","hasDeps","cwd","shouldInstall","confirm","initialValue","isCancel","packageManager","modResult","contentSystemId","region","useContentSystem","noContentSystem","modified","changes","length","forEach","change","dim","warnings","shouldAddPayload","cancel","outro","nextSteps","filter","Boolean","join","projectPathInput","text","placeholder","validate","value","undefined","projectPath","fullPath","resolve","projectName","name","basename","mkdir","recursive","step","bgGreen","black","relativePath","relative","push"],"mappings":"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"}
@@ -1,8 +1,15 @@
1
+ type LoginArgs = {
2
+ /** Set this to show next steps after login
3
+ * @default true
4
+ */
5
+ showNextSteps: boolean;
6
+ };
1
7
  /**
2
8
  * Handle the `@payloadcms/figma login` command
3
9
  *
4
10
  * Authenticates the user with Figma OAuth2 and stores tokens locally.
5
11
  * If valid tokens already exist, shows an error message.
6
12
  */
7
- export declare function loginCommand(): Promise<void>;
13
+ export declare function loginCommand(args?: LoginArgs): Promise<void>;
14
+ export {};
8
15
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBlD"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAQA,KAAK,SAAS,GAAG;IACf;;OAEG;IACH,aAAa,EAAE,OAAO,CAAA;CACvB,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}