@payloadcms/figma 0.0.1-alpha.57 → 0.0.1-alpha.59

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 (49) hide show
  1. package/dist/api/control-plane.d.ts +8 -7
  2. package/dist/api/control-plane.js +16 -23
  3. package/dist/api/figma-api.d.ts +3 -2
  4. package/dist/api/figma-api.js +6 -9
  5. package/dist/auth/credentials.d.ts +21 -0
  6. package/dist/auth/credentials.js +21 -0
  7. package/dist/auth/oauth-flow.d.ts +13 -4
  8. package/dist/auth/oauth-flow.js +34 -8
  9. package/dist/auth/project-token.js +5 -5
  10. package/dist/cli.js +5 -0
  11. package/dist/commands/deploy.d.ts +3 -0
  12. package/dist/commands/deploy.js +67 -37
  13. package/dist/commands/env.js +4 -4
  14. package/dist/commands/init.js +10 -25
  15. package/dist/commands/login.js +3 -3
  16. package/dist/commands/upgrade.js +11 -11
  17. package/dist/db-content-api/index.js +48 -11
  18. package/dist/db-content-api/temp-utilities/sorting.d.ts +1 -1
  19. package/dist/db-content-api/temp-utilities/sorting.js +4 -1
  20. package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +7 -2
  21. package/dist/db-content-api/temp-utilities/unwrapDocument.js +11 -5
  22. package/dist/db-content-api/utilities/data/castFieldValue.js +11 -12
  23. package/dist/db-content-api/utilities/data/index.d.ts +1 -1
  24. package/dist/db-content-api/utilities/data/index.js +45 -20
  25. package/dist/db-content-api/utilities/joins.js +10 -4
  26. package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +14 -6
  27. package/dist/db-content-api/utilities/meta/buildPathTypes.js +19 -2
  28. package/dist/db-content-api/utilities/where.js +15 -45
  29. package/dist/oauth/endpoints/getLoginEndpoint.js +10 -2
  30. package/dist/oauth/utilities/refreshTokens.js +4 -1
  31. package/dist/plugin/build-config.js +4 -4
  32. package/dist/utils/adapters/nextjs.d.ts +9 -0
  33. package/dist/utils/adapters/nextjs.js +59 -0
  34. package/dist/utils/adapters/nitro.d.ts +9 -0
  35. package/dist/utils/adapters/nitro.js +164 -0
  36. package/dist/utils/adapters/vite.d.ts +10 -0
  37. package/dist/utils/adapters/vite.js +32 -0
  38. package/dist/utils/asset-collection.d.ts +24 -0
  39. package/dist/utils/asset-collection.js +53 -0
  40. package/dist/utils/build-detection.d.ts +5 -11
  41. package/dist/utils/build-detection.js +74 -11
  42. package/dist/utils/deploy-adapter.d.ts +38 -0
  43. package/dist/utils/deploy-adapter.js +58 -0
  44. package/dist/utils/download-template.js +3 -2
  45. package/dist/utils/fs-utils.d.ts +6 -0
  46. package/dist/utils/fs-utils.js +27 -0
  47. package/dist/utils/s3-upload.d.ts +7 -1
  48. package/dist/utils/s3-upload.js +4 -3
  49. package/package.json +1 -1
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * TODO: Replace with real API calls when Control Plane is available
5
5
  */
6
+ import type { AuthCredential } from '../auth/credentials.js';
6
7
  import type { Tenant } from '../types/config.js';
7
8
  /**
8
9
  * Error thrown when Control Plane API calls fail
@@ -85,7 +86,7 @@ export interface PerformDeploymentApiResponse {
85
86
  * @param accessToken - OAuth access token
86
87
  * @returns Array of tenant instances
87
88
  */
88
- export declare function listTenants(accessToken: string): Promise<Tenant[]>;
89
+ export declare function listTenants(credential: AuthCredential): Promise<Tenant[]>;
89
90
  /**
90
91
  * Create a new tenant instance
91
92
  * Maps to: POST /v1/tenant
@@ -94,7 +95,7 @@ export declare function listTenants(accessToken: string): Promise<Tenant[]>;
94
95
  * @param options - Tenant creation options
95
96
  * @returns Newly created tenant
96
97
  */
97
- export declare function createTenant(accessToken: string, options: CreateTenantOptions): Promise<Tenant>;
98
+ export declare function createTenant(credential: AuthCredential, options: CreateTenantOptions): Promise<Tenant>;
98
99
  /**
99
100
  * Get details for a specific tenant
100
101
  * Maps to: GET /v1/tenant/{tenant_id}
@@ -103,7 +104,7 @@ export declare function createTenant(accessToken: string, options: CreateTenantO
103
104
  * @param tenantId - Tenant ID
104
105
  * @returns Tenant details
105
106
  */
106
- export declare function getTenantDetails(accessToken: string, tenantId: string): Promise<Tenant>;
107
+ export declare function getTenantDetails(credential: AuthCredential, tenantId: string): Promise<Tenant>;
107
108
  /**
108
109
  * Create a new deployment and get signed upload URLs
109
110
  * Maps to: POST /v1/tenant/{tenant_id}/deploy/create
@@ -113,7 +114,7 @@ export declare function getTenantDetails(accessToken: string, tenantId: string):
113
114
  * @param options - Deployment creation options
114
115
  * @returns Deployment ID and upload URLs
115
116
  */
116
- export declare function createDeployment(accessToken: string, tenantId: string, options: CreateDeploymentOptions): Promise<CreateDeploymentResponse>;
117
+ export declare function createDeployment(credential: AuthCredential, tenantId: string, options: CreateDeploymentOptions): Promise<CreateDeploymentResponse>;
117
118
  /**
118
119
  * Perform deployment for a created deployment ID
119
120
  * Maps to: POST /v1/tenant/{tenant_id}/deploy/perform
@@ -123,7 +124,7 @@ export declare function createDeployment(accessToken: string, tenantId: string,
123
124
  * @param options - Deployment perform options
124
125
  * @returns Deployment status and message
125
126
  */
126
- export declare function performDeployment(accessToken: string, tenantId: string, options: PerformDeploymentOptions): Promise<PerformDeploymentResponse>;
127
+ export declare function performDeployment(credential: AuthCredential, tenantId: string, options: PerformDeploymentOptions): Promise<PerformDeploymentResponse>;
127
128
  /**
128
129
  * A single environment returned by the bootstrap endpoint
129
130
  */
@@ -150,7 +151,7 @@ export type BootstrapInfo = {
150
151
  * @param cmsResourceId - CMS Resource ID (project ID)
151
152
  * @param environmentName - Optional environment name filter
152
153
  */
153
- export declare function getBootstrapInfo(accessToken: string, cmsResourceId: string, environmentName?: string): Promise<BootstrapInfo>;
154
+ export declare function getBootstrapInfo(credential: AuthCredential, cmsResourceId: string, environmentName?: string): Promise<BootstrapInfo>;
154
155
  /**
155
156
  * Resolve a CMS Resource ID from a legacy dataset (content system) ID.
156
157
  * Maps to: GET /v1/cms/dataset/:datasetId
@@ -158,5 +159,5 @@ export declare function getBootstrapInfo(accessToken: string, cmsResourceId: str
158
159
  * Used during upgrade migration to convert old FIGMA_CONTENT_API_CONTENT_SYSTEM_ID
159
160
  * into the new FIGMA_PROJECT_ID (CMS Resource ID).
160
161
  */
161
- export declare function getCmsResourceId(accessToken: string, datasetId: string): Promise<string>;
162
+ export declare function getCmsResourceId(credential: AuthCredential, datasetId: string): Promise<string>;
162
163
  //# sourceMappingURL=control-plane.d.ts.map
@@ -2,7 +2,8 @@
2
2
  * Control Plane API Client
3
3
  *
4
4
  * TODO: Replace with real API calls when Control Plane is available
5
- */ import { getEnvConfig } from '../constants.js';
5
+ */ import { getAuthHeaders } from '../auth/credentials.js';
6
+ import { getEnvConfig } from '../constants.js';
6
7
  import * as log from '../utils/log.js';
7
8
  /**
8
9
  * Get the Control Plane API base URL based on environment
@@ -25,7 +26,7 @@ import * as log from '../utils/log.js';
25
26
  *
26
27
  * @param accessToken - OAuth access token
27
28
  * @returns Array of tenant instances
28
- */ export async function listTenants(accessToken) {
29
+ */ export async function listTenants(credential) {
29
30
  const shouldMock = process.env.FIGMA_MOCK_CONTROL_PLANE === 'true';
30
31
  if (shouldMock) {
31
32
  // MOCK IMPLEMENTATION: Return sample tenants for testing
@@ -53,9 +54,7 @@ import * as log from '../utils/log.js';
53
54
  const response = await controlPlaneFetch({
54
55
  context: 'list tenants',
55
56
  options: {
56
- headers: {
57
- Authorization: `Bearer ${accessToken}`
58
- }
57
+ headers: getAuthHeaders(credential)
59
58
  },
60
59
  url: `${getControlPlaneBaseUrl()}/v1/tenant`
61
60
  });
@@ -68,7 +67,7 @@ import * as log from '../utils/log.js';
68
67
  * @param accessToken - OAuth access token
69
68
  * @param options - Tenant creation options
70
69
  * @returns Newly created tenant
71
- */ export async function createTenant(accessToken, options) {
70
+ */ export async function createTenant(credential, options) {
72
71
  // Check if control plane API should be mocked
73
72
  const shouldMock = process.env.FIGMA_MOCK_CONTROL_PLANE === 'true';
74
73
  if (shouldMock) {
@@ -94,7 +93,7 @@ import * as log from '../utils/log.js';
94
93
  name: options.name
95
94
  }),
96
95
  headers: {
97
- Authorization: `Bearer ${accessToken}`,
96
+ ...getAuthHeaders(credential),
98
97
  'Content-Type': 'application/json'
99
98
  },
100
99
  method: 'POST'
@@ -110,7 +109,7 @@ import * as log from '../utils/log.js';
110
109
  * @param accessToken - OAuth access token
111
110
  * @param tenantId - Tenant ID
112
111
  * @returns Tenant details
113
- */ export async function getTenantDetails(accessToken, tenantId) {
112
+ */ export async function getTenantDetails(credential, tenantId) {
114
113
  // Check if control plane API should be mocked
115
114
  const shouldMock = process.env.FIGMA_MOCK_CONTROL_PLANE === 'true';
116
115
  if (shouldMock) {
@@ -129,9 +128,7 @@ import * as log from '../utils/log.js';
129
128
  const response = await controlPlaneFetch({
130
129
  context: 'get tenant details',
131
130
  options: {
132
- headers: {
133
- Authorization: `Bearer ${accessToken}`
134
- }
131
+ headers: getAuthHeaders(credential)
135
132
  },
136
133
  url: `${getControlPlaneBaseUrl()}/v1/tenant/${tenantId}`
137
134
  });
@@ -145,7 +142,7 @@ import * as log from '../utils/log.js';
145
142
  * @param tenantId - Tenant ID
146
143
  * @param options - Deployment creation options
147
144
  * @returns Deployment ID and upload URLs
148
- */ export async function createDeployment(accessToken, tenantId, options) {
145
+ */ export async function createDeployment(credential, tenantId, options) {
149
146
  // Check if control plane API should be mocked
150
147
  const shouldMock = process.env.FIGMA_MOCK_CONTROL_PLANE === 'true';
151
148
  if (shouldMock) {
@@ -179,7 +176,7 @@ import * as log from '../utils/log.js';
179
176
  static_assets: options.staticAssets
180
177
  }),
181
178
  headers: {
182
- Authorization: `Bearer ${accessToken}`,
179
+ ...getAuthHeaders(credential),
183
180
  'Content-Type': 'application/json'
184
181
  },
185
182
  method: 'POST'
@@ -202,7 +199,7 @@ import * as log from '../utils/log.js';
202
199
  * @param tenantId - Tenant ID
203
200
  * @param options - Deployment perform options
204
201
  * @returns Deployment status and message
205
- */ export async function performDeployment(accessToken, tenantId, options) {
202
+ */ export async function performDeployment(credential, tenantId, options) {
206
203
  const shouldMock = process.env.FIGMA_MOCK_CONTROL_PLANE === 'true';
207
204
  if (shouldMock) {
208
205
  // MOCK IMPLEMENTATION: Return mock deployment status
@@ -225,7 +222,7 @@ import * as log from '../utils/log.js';
225
222
  deployment_id: options.deploymentId
226
223
  }),
227
224
  headers: {
228
- Authorization: `Bearer ${accessToken}`,
225
+ ...getAuthHeaders(credential),
229
226
  'Content-Type': 'application/json'
230
227
  },
231
228
  method: 'POST'
@@ -247,7 +244,7 @@ import * as log from '../utils/log.js';
247
244
  * @param accessToken - OAuth access token
248
245
  * @param cmsResourceId - CMS Resource ID (project ID)
249
246
  * @param environmentName - Optional environment name filter
250
- */ export async function getBootstrapInfo(accessToken, cmsResourceId, environmentName) {
247
+ */ export async function getBootstrapInfo(credential, cmsResourceId, environmentName) {
251
248
  const baseUrl = getControlPlaneBaseUrl();
252
249
  let url = `${baseUrl}/v1/cms/${cmsResourceId}/bootstrap`;
253
250
  if (environmentName) {
@@ -257,9 +254,7 @@ import * as log from '../utils/log.js';
257
254
  const response = await controlPlaneFetch({
258
255
  context: 'get bootstrap info',
259
256
  options: {
260
- headers: {
261
- Authorization: `Bearer ${accessToken}`
262
- }
257
+ headers: getAuthHeaders(credential)
263
258
  },
264
259
  url
265
260
  });
@@ -282,15 +277,13 @@ import * as log from '../utils/log.js';
282
277
  *
283
278
  * Used during upgrade migration to convert old FIGMA_CONTENT_API_CONTENT_SYSTEM_ID
284
279
  * into the new FIGMA_PROJECT_ID (CMS Resource ID).
285
- */ export async function getCmsResourceId(accessToken, datasetId) {
280
+ */ export async function getCmsResourceId(credential, datasetId) {
286
281
  const url = `${getControlPlaneBaseUrl()}/v1/cms/dataset/${datasetId}`;
287
282
  log.debug(`Calling getCmsResourceId API at ${url}`);
288
283
  const response = await controlPlaneFetch({
289
284
  context: 'get CMS resource ID from dataset',
290
285
  options: {
291
- headers: {
292
- Authorization: `Bearer ${accessToken}`
293
- }
286
+ headers: getAuthHeaders(credential)
294
287
  },
295
288
  url
296
289
  });
@@ -4,6 +4,7 @@
4
4
  * Client for Figma REST API (Pixie) endpoints
5
5
  * Handles project token generation and other CMS-related API calls
6
6
  */
7
+ import type { AuthCredential } from '../auth/credentials.js';
7
8
  import type { ProjectToken } from '../auth/types.js';
8
9
  /**
9
10
  * User info from Figma API /v1/me endpoint
@@ -36,7 +37,7 @@ export declare class FigmaApiError extends Error {
36
37
  * @returns ProjectToken with JWT and expiry information
37
38
  * @throws {FigmaApiError} If the API call fails
38
39
  */
39
- export declare function getProjectToken(accessToken: string, tenantId: string): Promise<ProjectToken>;
40
+ export declare function getProjectToken(credential: AuthCredential, tenantId: string): Promise<ProjectToken>;
40
41
  /**
41
42
  * Get user info from Figma API
42
43
  *
@@ -47,5 +48,5 @@ export declare function getProjectToken(accessToken: string, tenantId: string):
47
48
  * @returns FigmaUserInfo with user profile data
48
49
  * @throws {FigmaApiError} If the API call fails
49
50
  */
50
- export declare function getUserInfo(accessToken: string): Promise<FigmaUserInfo>;
51
+ export declare function getUserInfo(credential: AuthCredential): Promise<FigmaUserInfo>;
51
52
  //# sourceMappingURL=figma-api.d.ts.map
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * Client for Figma REST API (Pixie) endpoints
5
5
  * Handles project token generation and other CMS-related API calls
6
- */ import { getEnvConfig } from '../constants.js';
6
+ */ import { getAuthHeaders } from '../auth/credentials.js';
7
+ import { getEnvConfig } from '../constants.js';
7
8
  import * as log from '../utils/log.js';
8
9
  /**
9
10
  * Error thrown when Figma API calls fail
@@ -28,7 +29,7 @@ import * as log from '../utils/log.js';
28
29
  * @param tenantId - The tenant/CMS ID
29
30
  * @returns ProjectToken with JWT and expiry information
30
31
  * @throws {FigmaApiError} If the API call fails
31
- */ export async function getProjectToken(accessToken, tenantId) {
32
+ */ export async function getProjectToken(credential, tenantId) {
32
33
  // Priority 1: Check for direct token value from environment
33
34
  const envTokenValue = process.env.FIGMA_MOCK_PROJECT_TOKEN_VALUE;
34
35
  if (envTokenValue) {
@@ -87,9 +88,7 @@ import * as log from '../utils/log.js';
87
88
  const baseUrl = process.env.FIGMA_API_BASE_URL || getEnvConfig().apiBaseUrl;
88
89
  const url = `${baseUrl}/v1/cms/${tenantId}/token/`;
89
90
  const response = await fetch(url, {
90
- headers: {
91
- Authorization: `Bearer ${accessToken}`
92
- },
91
+ headers: getAuthHeaders(credential),
93
92
  method: 'POST'
94
93
  });
95
94
  if (!response.ok) {
@@ -197,14 +196,12 @@ import * as log from '../utils/log.js';
197
196
  * @param accessToken - OAuth access token for authentication
198
197
  * @returns FigmaUserInfo with user profile data
199
198
  * @throws {FigmaApiError} If the API call fails
200
- */ export async function getUserInfo(accessToken) {
199
+ */ export async function getUserInfo(credential) {
201
200
  const baseUrl = process.env.FIGMA_API_BASE_URL || getEnvConfig().apiBaseUrl;
202
201
  const url = `${baseUrl}/v1/me`;
203
202
  try {
204
203
  const response = await fetch(url, {
205
- headers: {
206
- Authorization: `Bearer ${accessToken}`
207
- }
204
+ headers: getAuthHeaders(credential)
208
205
  });
209
206
  if (!response.ok) {
210
207
  throw new FigmaApiError(`Failed to get user info: ${response.status} ${response.statusText}`, response.status);
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Auth Access Tokens types for CLI authentication
3
+ *
4
+ * Distinguishes between OAuth tokens (Authorization: Bearer) and
5
+ * Plan Access Tokens (X-Figma-Token header).
6
+ */
7
+ /**
8
+ * Represents an authenticated credential — either OAuth or PAT
9
+ */
10
+ export type AuthCredential = {
11
+ token: string;
12
+ type: 'oauth';
13
+ } | {
14
+ token: string;
15
+ type: 'plan_access_token';
16
+ };
17
+ /**
18
+ * Build the correct auth headers for a credential
19
+ */
20
+ export declare function getAuthHeaders(credential: AuthCredential): Record<string, string>;
21
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Auth Access Tokens types for CLI authentication
3
+ *
4
+ * Distinguishes between OAuth tokens (Authorization: Bearer) and
5
+ * Plan Access Tokens (X-Figma-Token header).
6
+ */ /**
7
+ * Represents an authenticated credential — either OAuth or PAT
8
+ */ /**
9
+ * Build the correct auth headers for a credential
10
+ */ export function getAuthHeaders(credential) {
11
+ if (credential.type === 'plan_access_token') {
12
+ return {
13
+ 'X-Figma-Token': credential.token
14
+ };
15
+ }
16
+ return {
17
+ Authorization: `Bearer ${credential.token}`
18
+ };
19
+ }
20
+
21
+ //# sourceMappingURL=credentials.js.map
@@ -1,3 +1,4 @@
1
+ import type { AuthCredential } from './credentials.js';
1
2
  import type { TokenStore } from './token-store.js';
2
3
  import type { FigmaTokens } from './types.js';
3
4
  /**
@@ -55,13 +56,21 @@ export declare function executeOAuthFlow(tokenStore: TokenStore, options?: OAuth
55
56
  * refreshes using the refresh token. If no tokens exist, returns null.
56
57
  *
57
58
  * @param tokenStore - Token store to use
58
- * @returns Promise resolving to access token or null if no valid tokens
59
+ * @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
59
60
  * @throws OAuthFlowError if refresh fails
60
61
  */
61
- export declare function getValidAccessToken(tokenStore: TokenStore): Promise<null | string>;
62
+ export declare function getValidOAuthAccessToken(tokenStore: TokenStore): Promise<AuthCredential | null>;
62
63
  /**
63
- * Like getValidAccessToken but returns null instead of throwing on refresh failure.
64
+ * Get a valid auth credential, checking process.env for plan access token
65
+ * first before checking tokenStore for OAuth tokens.
66
+ * *
67
+ * @param tokenStore - Token store to use for OAuth tokens
68
+ * @returns Promise resolving to AuthCredential or null
69
+ */
70
+ export declare function getValidCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
71
+ /**
72
+ * Like getValidCredential but returns null instead of throwing on refresh failure.
64
73
  * Use in commands that want to fall through to a login prompt on failure.
65
74
  */
66
- export declare function tryGetAccessToken(tokenStore: TokenStore): Promise<null | string>;
75
+ export declare function tryGetCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
67
76
  //# sourceMappingURL=oauth-flow.d.ts.map
@@ -143,12 +143,16 @@ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './
143
143
  * refreshes using the refresh token. If no tokens exist, returns null.
144
144
  *
145
145
  * @param tokenStore - Token store to use
146
- * @returns Promise resolving to access token or null if no valid tokens
146
+ * @returns Promise resolving to AuthCredential (wrapped access token) or null if no valid tokens
147
147
  * @throws OAuthFlowError if refresh fails
148
- */ export async function getValidAccessToken(tokenStore) {
148
+ */ export async function getValidOAuthAccessToken(tokenStore) {
149
149
  // Check if we have valid tokens
150
150
  if (tokenStore.hasValidTokens()) {
151
- return tokenStore.getAccessToken();
151
+ const token = tokenStore.getAccessToken();
152
+ return token ? {
153
+ type: 'oauth',
154
+ token
155
+ } : null;
152
156
  }
153
157
  // Check if we have a refresh token
154
158
  const refreshToken = tokenStore.getRefreshToken();
@@ -159,7 +163,10 @@ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './
159
163
  try {
160
164
  const tokens = await refreshAccessToken(refreshToken);
161
165
  tokenStore.setTokens(tokens);
162
- return tokens.accessToken;
166
+ return {
167
+ type: 'oauth',
168
+ token: tokens.accessToken
169
+ };
163
170
  } catch (error) {
164
171
  const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
165
172
  if (isAuthFailure) {
@@ -167,7 +174,10 @@ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './
167
174
  try {
168
175
  const tokens = await refreshAccessToken(refreshToken);
169
176
  tokenStore.setTokens(tokens);
170
- return tokens.accessToken;
177
+ return {
178
+ type: 'oauth',
179
+ token: tokens.accessToken
180
+ };
171
181
  } catch {
172
182
  // Retry also failed — token is genuinely revoked
173
183
  tokenStore.clearTokens();
@@ -177,11 +187,27 @@ import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './
177
187
  }
178
188
  }
179
189
  /**
180
- * Like getValidAccessToken but returns null instead of throwing on refresh failure.
190
+ * Get a valid auth credential, checking process.env for plan access token
191
+ * first before checking tokenStore for OAuth tokens.
192
+ * *
193
+ * @param tokenStore - Token store to use for OAuth tokens
194
+ * @returns Promise resolving to AuthCredential or null
195
+ */ export async function getValidCredential(tokenStore) {
196
+ const envFigmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
197
+ if (envFigmaAccessToken) {
198
+ return {
199
+ type: 'plan_access_token',
200
+ token: envFigmaAccessToken
201
+ };
202
+ }
203
+ return getValidOAuthAccessToken(tokenStore);
204
+ }
205
+ /**
206
+ * Like getValidCredential but returns null instead of throwing on refresh failure.
181
207
  * Use in commands that want to fall through to a login prompt on failure.
182
- */ export async function tryGetAccessToken(tokenStore) {
208
+ */ export async function tryGetCredential(tokenStore) {
183
209
  try {
184
- return await getValidAccessToken(tokenStore);
210
+ return await getValidCredential(tokenStore);
185
211
  } catch {
186
212
  return null;
187
213
  }
@@ -8,7 +8,7 @@
8
8
  import { getInfraEnvironment } from '../constants.js';
9
9
  import * as log from '../utils/log.js';
10
10
  import { JWTValidationError, validateProjectToken } from './jwt-validator.js';
11
- import { getValidAccessToken } from './oauth-flow.js';
11
+ import { getValidCredential } from './oauth-flow.js';
12
12
  /**
13
13
  * Error during project token operations
14
14
  */ export class ProjectTokenError extends Error {
@@ -71,18 +71,18 @@ import { getValidAccessToken } from './oauth-flow.js';
71
71
  }
72
72
  // We need to refresh the project token
73
73
  // An oauth access token is required for the call
74
- let accessToken;
74
+ let credential;
75
75
  try {
76
- accessToken = await getValidAccessToken(tokenStore);
76
+ credential = await getValidCredential(tokenStore);
77
77
  } catch (error) {
78
78
  throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
79
79
  }
80
- if (!accessToken) {
80
+ if (!credential) {
81
81
  // No valid user tokens available - user needs to authenticate
82
82
  return null;
83
83
  }
84
84
  // Fetch a new project token from the Figma API
85
- const projectToken = await fetchProjectToken(accessToken, tenantId);
85
+ const projectToken = await fetchProjectToken(credential, tenantId);
86
86
  // Validate the JWT signature and claims (skip for mocks)
87
87
  const hasEnvToken = !!process.env.FIGMA_MOCK_PROJECT_TOKEN_VALUE;
88
88
  const shouldMock = process.env.FIGMA_MOCK_PROJECT_TOKEN !== 'false';
package/dist/cli.js CHANGED
@@ -29,6 +29,10 @@ class Main {
29
29
  constructor(){
30
30
  // @ts-expect-error bad typings
31
31
  this.args = arg({
32
+ // Hidden flag — intentionally not displayed in help output yet.
33
+ // Auto-detection covers most cases; this is an escape hatch for testing.
34
+ // May expose in help text once multi-framework support is public.
35
+ '--adapter': String,
32
36
  '--all': Boolean,
33
37
  '--debug': Boolean,
34
38
  '--dry-run': Boolean,
@@ -106,6 +110,7 @@ class Main {
106
110
  case 'deploy':
107
111
  await deployCommand({
108
112
  id: this.args['--id'],
113
+ adapter: this.args['--adapter'],
109
114
  debug: this.args['--debug'],
110
115
  env: this.args['--env'],
111
116
  skipBuild: this.args['--skip-build'],
@@ -1,7 +1,10 @@
1
+ import type { AdapterName } from '../utils/deploy-adapter.js';
1
2
  /**
2
3
  * Options for deploy command
3
4
  */
4
5
  export interface DeployCommandOptions {
6
+ /** Framework adapter (nextjs, nitro, vite). Auto-detected if omitted. */
7
+ adapter?: AdapterName;
5
8
  /** Enable debug mode */
6
9
  debug?: boolean;
7
10
  /** Figma environment name (e.g. 'production', 'staging') */