@payloadcms/figma 0.0.1-alpha.6 → 0.0.1-alpha.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/control-plane.d.ts +52 -6
- package/dist/api/control-plane.js +174 -72
- package/dist/api/figma-api.d.ts +22 -1
- package/dist/api/figma-api.js +78 -25
- package/dist/auth/callback-server.js +2 -1
- package/dist/auth/credentials.d.ts +21 -0
- package/dist/auth/credentials.js +21 -0
- package/dist/auth/crypto-utils.d.ts +6 -0
- package/dist/auth/crypto-utils.js +16 -14
- package/dist/auth/jwt-validator.d.ts +2 -1
- package/dist/auth/jwt-validator.js +2 -2
- package/dist/auth/oauth-flow.d.ts +17 -3
- package/dist/auth/oauth-flow.js +63 -16
- package/dist/auth/project-token.js +16 -11
- package/dist/auth/refresh.d.ts +2 -1
- package/dist/auth/refresh.js +25 -12
- package/dist/auth/token-store.d.ts +42 -1
- package/dist/auth/token-store.js +118 -14
- package/dist/auth/types.d.ts +17 -4
- package/dist/cli.js +68 -5
- package/dist/commands/build-lambda-zip.d.ts +5 -0
- package/dist/commands/build-lambda-zip.js +19 -0
- package/dist/commands/debug.d.ts +8 -0
- package/dist/commands/debug.js +176 -0
- package/dist/commands/deploy.d.ts +9 -0
- package/dist/commands/deploy.js +178 -151
- package/dist/commands/env.d.ts +13 -0
- package/dist/commands/env.js +88 -0
- package/dist/commands/init.d.ts +3 -5
- package/dist/commands/init.js +165 -148
- package/dist/commands/list-tokens.d.ts +3 -3
- package/dist/commands/list-tokens.js +22 -7
- package/dist/commands/login.d.ts +8 -1
- package/dist/commands/login.js +33 -15
- package/dist/commands/logout.d.ts +5 -4
- package/dist/commands/logout.js +56 -13
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.js +331 -0
- package/dist/config/oauth.d.ts +4 -14
- package/dist/config/oauth.js +18 -40
- package/dist/constants.d.ts +44 -19
- package/dist/constants.js +73 -20
- package/dist/db-content-api/README.md +98 -0
- package/dist/db-content-api/generated/content-api-types.d.ts +3972 -0
- package/dist/db-content-api/generated/content-api-types.js +7 -0
- package/dist/db-content-api/index.d.ts +21 -0
- package/dist/db-content-api/index.js +787 -0
- package/dist/db-content-api/temp-utilities/slug.d.ts +2 -0
- package/dist/db-content-api/temp-utilities/slug.js +3 -0
- package/dist/db-content-api/temp-utilities/sorting.d.ts +3 -0
- package/dist/db-content-api/temp-utilities/sorting.js +39 -0
- package/dist/db-content-api/temp-utilities/types.d.ts +22 -0
- package/dist/db-content-api/temp-utilities/types.js +15 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +39 -0
- package/dist/db-content-api/temp-utilities/unwrapDocument.js +59 -0
- package/dist/db-content-api/utilities/auth.d.ts +30 -0
- package/dist/db-content-api/utilities/auth.js +81 -0
- package/dist/db-content-api/utilities/data/applyDefaults.d.ts +7 -0
- package/dist/db-content-api/utilities/data/applyDefaults.js +59 -0
- package/dist/db-content-api/utilities/data/castFieldValue.d.ts +11 -0
- package/dist/db-content-api/utilities/data/castFieldValue.js +68 -0
- package/dist/db-content-api/utilities/data/index.d.ts +49 -0
- package/dist/db-content-api/utilities/data/index.js +284 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.d.ts +12 -0
- package/dist/db-content-api/utilities/data/removeVirtualFields.js +54 -0
- package/dist/db-content-api/utilities/data/stripFields.d.ts +48 -0
- package/dist/db-content-api/utilities/data/stripFields.js +195 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.d.ts +23 -0
- package/dist/db-content-api/utilities/data/transformPublishedLocale.js +42 -0
- package/dist/db-content-api/utilities/joins.d.ts +55 -0
- package/dist/db-content-api/utilities/joins.js +135 -0
- package/dist/db-content-api/utilities/locale/index.d.ts +10 -0
- package/dist/db-content-api/utilities/locale/index.js +21 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.d.ts +11 -0
- package/dist/db-content-api/utilities/meta/buildLocalizedPaths.js +74 -0
- package/dist/db-content-api/utilities/meta/buildMeta.d.ts +42 -0
- package/dist/db-content-api/utilities/meta/buildMeta.js +41 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.d.ts +17 -0
- package/dist/db-content-api/utilities/meta/buildPathTypes.js +244 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.d.ts +13 -0
- package/dist/db-content-api/utilities/meta/buildUniquePaths.js +62 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.d.ts +10 -0
- package/dist/db-content-api/utilities/meta/normalizeLocaleInWhere.js +102 -0
- package/dist/db-content-api/utilities/where.d.ts +20 -0
- package/dist/db-content-api/utilities/where.js +104 -0
- package/dist/deploy/schedule-extract-plugin.d.ts +11 -0
- package/dist/deploy/schedule-extract-plugin.js +34 -0
- package/dist/endpoints/health.d.ts +3 -0
- package/dist/endpoints/health.js +11 -0
- package/dist/endpoints/schema.d.ts +3 -0
- package/dist/endpoints/schema.js +29 -0
- package/dist/exports/client.d.ts +3 -0
- package/dist/exports/client.js +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/dist/oauth/components/FigmaAvatar/index.d.ts +4 -0
- package/dist/oauth/components/FigmaAvatar/index.js +27 -0
- package/dist/oauth/components/FigmaAvatar/index.scss +12 -0
- package/dist/oauth/components/FigmaAvatarCell/index.d.ts +5 -0
- package/dist/oauth/components/FigmaAvatarCell/index.js +25 -0
- package/dist/oauth/components/FigmaAvatarCell/index.scss +5 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.d.ts +9 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.js +37 -0
- package/dist/oauth/components/FigmaAvatarPlaceholder/index.scss +28 -0
- package/dist/oauth/components/LoginButton/index.js +50 -6
- package/dist/oauth/components/LoginButton/index.scss +50 -3
- package/dist/oauth/components/LogoutButton/index.js +5 -4
- package/dist/oauth/defaults.js +67 -10
- package/dist/oauth/endpoints/getLoginEndpoint.js +77 -24
- package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
- package/dist/oauth/index.js +40 -13
- package/dist/oauth/strategy/index.d.ts +0 -2
- package/dist/oauth/strategy/index.js +40 -17
- package/dist/oauth/types.d.ts +6 -6
- package/dist/oauth/utilities/isDuplicateKeyError.d.ts +7 -0
- package/dist/oauth/utilities/isDuplicateKeyError.js +14 -0
- package/dist/oauth/utilities/refreshTokens.js +6 -3
- package/dist/plugin/build-config.d.ts +18 -15
- package/dist/plugin/build-config.js +213 -18
- package/dist/storage-content-api/api-types.d.ts +168 -0
- package/dist/storage-content-api/api-types.js +6 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.d.ts +9 -0
- package/dist/storage-content-api/client-uploads/ClientUploadHandler.js +42 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.d.ts +13 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.js +39 -0
- package/dist/storage-content-api/client.d.ts +6 -0
- package/dist/storage-content-api/client.js +36 -0
- package/dist/storage-content-api/generateURL.d.ts +7 -0
- package/dist/storage-content-api/generateURL.js +8 -0
- package/dist/storage-content-api/handleDelete.d.ts +8 -0
- package/dist/storage-content-api/handleDelete.js +17 -0
- package/dist/storage-content-api/handleUpload.d.ts +11 -0
- package/dist/storage-content-api/handleUpload.js +144 -0
- package/dist/storage-content-api/index.d.ts +5 -0
- package/dist/storage-content-api/index.js +31 -0
- package/dist/storage-content-api/staticHandler.d.ts +10 -0
- package/dist/storage-content-api/staticHandler.js +56 -0
- package/dist/storage-content-api/types.d.ts +10 -0
- package/dist/storage-content-api/types.js +3 -0
- package/dist/storage-content-api/utilities/getSafeFilename.d.ts +12 -0
- package/dist/storage-content-api/utilities/getSafeFilename.js +61 -0
- package/dist/storage-content-api/utilities/index.d.ts +2 -0
- package/dist/storage-content-api/utilities/index.js +3 -0
- package/dist/templates/.env.example +5 -0
- package/dist/templates/README.md +19 -0
- package/dist/types/config.d.ts +2 -1
- package/dist/types/config.js +0 -2
- package/dist/types.d.ts +8 -1
- package/dist/utils/adapters/nextjs.d.ts +9 -0
- package/dist/utils/adapters/nextjs.js +64 -0
- package/dist/utils/adapters/nitro.d.ts +9 -0
- package/dist/utils/adapters/nitro.js +169 -0
- package/dist/utils/adapters/vite.d.ts +10 -0
- package/dist/utils/adapters/vite.js +33 -0
- package/dist/utils/asset-collection.d.ts +27 -6
- package/dist/utils/asset-collection.js +59 -30
- package/dist/utils/build-detection.d.ts +5 -11
- package/dist/utils/build-detection.js +74 -11
- package/dist/utils/build-lambda-zip.d.ts +14 -0
- package/dist/utils/build-lambda-zip.js +81 -0
- package/dist/utils/cache-bootstrap.d.ts +8 -0
- package/dist/utils/cache-bootstrap.js +18 -0
- package/dist/utils/config.js +1 -1
- package/dist/utils/deploy-adapter.d.ts +40 -0
- package/dist/utils/deploy-adapter.js +58 -0
- package/dist/utils/download-template.js +3 -2
- package/dist/utils/env-management.d.ts +24 -7
- package/dist/utils/env-management.js +119 -64
- package/dist/utils/format-env-suffix.d.ts +12 -0
- package/dist/utils/format-env-suffix.js +13 -0
- package/dist/utils/formatter.js +23 -11
- package/dist/utils/fs-utils.d.ts +6 -0
- package/dist/utils/fs-utils.js +27 -0
- package/dist/utils/handle-upgrade.d.ts +9 -0
- package/dist/utils/handle-upgrade.js +41 -0
- package/dist/utils/lambda-config.d.ts +3 -1
- package/dist/utils/lambda-config.js +87 -79
- package/dist/utils/messages.d.ts +1 -2
- package/dist/utils/messages.js +29 -11
- package/dist/utils/package-manager.d.ts +24 -0
- package/dist/utils/package-manager.js +53 -0
- package/dist/utils/payload-config-ast.d.ts +27 -6
- package/dist/utils/payload-config-ast.js +84 -54
- package/dist/utils/payload-config-finder.d.ts +2 -2
- package/dist/utils/payload-config-finder.js +48 -9
- package/dist/utils/payload-config-modifier.d.ts +1 -1
- package/dist/utils/payload-config-modifier.js +70 -11
- package/dist/utils/payload-package-check.d.ts +12 -1
- package/dist/utils/payload-package-check.js +63 -5
- package/dist/utils/project.d.ts +3 -2
- package/dist/utils/project.js +29 -15
- package/dist/utils/resolve-environment.d.ts +14 -0
- package/dist/utils/resolve-environment.js +31 -0
- package/dist/utils/s3-upload.d.ts +7 -2
- package/dist/utils/s3-upload.js +39 -6
- package/dist/utils/token-display.js +11 -5
- package/dist/utils/typescript-validator.js +4 -6
- package/dist/utils/version-check.d.ts +3 -0
- package/dist/utils/version-check.js +38 -0
- package/package.json +29 -11
- package/dist/api/control-plane.d.ts.map +0 -1
- package/dist/api/control-plane.js.map +0 -1
- package/dist/api/figma-api.d.ts.map +0 -1
- package/dist/api/figma-api.js.map +0 -1
- package/dist/auth/browser.d.ts.map +0 -1
- package/dist/auth/browser.js.map +0 -1
- package/dist/auth/callback-server.d.ts.map +0 -1
- package/dist/auth/callback-server.js.map +0 -1
- package/dist/auth/crypto-utils.d.ts.map +0 -1
- package/dist/auth/crypto-utils.js.map +0 -1
- package/dist/auth/jwt-validator.d.ts.map +0 -1
- package/dist/auth/jwt-validator.js.map +0 -1
- package/dist/auth/oauth-flow.d.ts.map +0 -1
- package/dist/auth/oauth-flow.js.map +0 -1
- package/dist/auth/pkce.d.ts.map +0 -1
- package/dist/auth/pkce.js.map +0 -1
- package/dist/auth/project-token.d.ts.map +0 -1
- package/dist/auth/project-token.js.map +0 -1
- package/dist/auth/refresh.d.ts.map +0 -1
- package/dist/auth/refresh.js.map +0 -1
- package/dist/auth/token-store.d.ts.map +0 -1
- package/dist/auth/token-store.js.map +0 -1
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/deploy.d.ts.map +0 -1
- package/dist/commands/deploy.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/list-tokens.d.ts.map +0 -1
- package/dist/commands/list-tokens.js.map +0 -1
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js.map +0 -1
- package/dist/config/oauth.d.ts.map +0 -1
- package/dist/config/oauth.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/exports/client.d.ts.map +0 -1
- package/dist/exports/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/oauth/components/LoginButton/index.d.ts.map +0 -1
- package/dist/oauth/components/LoginButton/index.js.map +0 -1
- package/dist/oauth/components/LogoutButton/index.d.ts.map +0 -1
- package/dist/oauth/components/LogoutButton/index.js.map +0 -1
- package/dist/oauth/defaults.d.ts.map +0 -1
- package/dist/oauth/defaults.js.map +0 -1
- package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getLoginEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getMetaEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getMetaEndpoint.js.map +0 -1
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.d.ts.map +0 -1
- package/dist/oauth/endpoints/getRedirectToLoginEndpoint.js.map +0 -1
- package/dist/oauth/exports/client.d.ts.map +0 -1
- package/dist/oauth/exports/client.js.map +0 -1
- package/dist/oauth/hooks/afterLogout.d.ts.map +0 -1
- package/dist/oauth/hooks/afterLogout.js.map +0 -1
- package/dist/oauth/hooks/me.d.ts.map +0 -1
- package/dist/oauth/hooks/me.js.map +0 -1
- package/dist/oauth/hooks/refresh.d.ts.map +0 -1
- package/dist/oauth/hooks/refresh.js.map +0 -1
- package/dist/oauth/index.d.ts.map +0 -1
- package/dist/oauth/index.js.map +0 -1
- package/dist/oauth/strategy/index.d.ts.map +0 -1
- package/dist/oauth/strategy/index.js.map +0 -1
- package/dist/oauth/types.d.ts.map +0 -1
- package/dist/oauth/types.js.map +0 -1
- package/dist/oauth/utilities/clearCookie.d.ts.map +0 -1
- package/dist/oauth/utilities/clearCookie.js.map +0 -1
- package/dist/oauth/utilities/createCookieOptions.d.ts.map +0 -1
- package/dist/oauth/utilities/createCookieOptions.js.map +0 -1
- package/dist/oauth/utilities/createDebugLogger.d.ts.map +0 -1
- package/dist/oauth/utilities/createDebugLogger.js.map +0 -1
- package/dist/oauth/utilities/extractOrigin.d.ts.map +0 -1
- package/dist/oauth/utilities/extractOrigin.js.map +0 -1
- package/dist/oauth/utilities/getAdminCollectionSlug.d.ts.map +0 -1
- package/dist/oauth/utilities/getAdminCollectionSlug.js.map +0 -1
- package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
- package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
- package/dist/oauth/utilities/getAdminPath.js +0 -9
- package/dist/oauth/utilities/getAdminPath.js.map +0 -1
- package/dist/oauth/utilities/getAuthorizeURL.d.ts.map +0 -1
- package/dist/oauth/utilities/getAuthorizeURL.js.map +0 -1
- package/dist/oauth/utilities/getCookieExpiration.d.ts.map +0 -1
- package/dist/oauth/utilities/getCookieExpiration.js.map +0 -1
- package/dist/oauth/utilities/getSecondsFromTokenExp.d.ts.map +0 -1
- package/dist/oauth/utilities/getSecondsFromTokenExp.js.map +0 -1
- package/dist/oauth/utilities/getTokenExp.d.ts.map +0 -1
- package/dist/oauth/utilities/getTokenExp.js.map +0 -1
- package/dist/oauth/utilities/getUsernameField.d.ts.map +0 -1
- package/dist/oauth/utilities/getUsernameField.js.map +0 -1
- package/dist/oauth/utilities/hasUserTokenPropsChanged.d.ts.map +0 -1
- package/dist/oauth/utilities/hasUserTokenPropsChanged.js.map +0 -1
- package/dist/oauth/utilities/mergeHeaders.d.ts.map +0 -1
- package/dist/oauth/utilities/mergeHeaders.js.map +0 -1
- package/dist/oauth/utilities/refreshTokens.d.ts.map +0 -1
- package/dist/oauth/utilities/refreshTokens.js.map +0 -1
- package/dist/plugin/adapter.d.ts.map +0 -1
- package/dist/plugin/adapter.js.map +0 -1
- package/dist/plugin/build-config.d.ts.map +0 -1
- package/dist/plugin/build-config.js.map +0 -1
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/asset-collection.d.ts.map +0 -1
- package/dist/utils/asset-collection.js.map +0 -1
- package/dist/utils/build-detection.d.ts.map +0 -1
- package/dist/utils/build-detection.js.map +0 -1
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/download-template.d.ts.map +0 -1
- package/dist/utils/download-template.js.map +0 -1
- package/dist/utils/env-management.d.ts.map +0 -1
- package/dist/utils/env-management.js.map +0 -1
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/formatter.d.ts.map +0 -1
- package/dist/utils/formatter.js.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- package/dist/utils/git.js.map +0 -1
- package/dist/utils/is-debug.d.ts.map +0 -1
- package/dist/utils/is-debug.js.map +0 -1
- package/dist/utils/lambda-config.d.ts.map +0 -1
- package/dist/utils/lambda-config.js.map +0 -1
- package/dist/utils/log.d.ts.map +0 -1
- package/dist/utils/log.js.map +0 -1
- package/dist/utils/messages.d.ts.map +0 -1
- package/dist/utils/messages.js.map +0 -1
- package/dist/utils/package-manager.d.ts.map +0 -1
- package/dist/utils/package-manager.js.map +0 -1
- package/dist/utils/payload-config-ast.d.ts.map +0 -1
- package/dist/utils/payload-config-ast.js.map +0 -1
- package/dist/utils/payload-config-finder.d.ts.map +0 -1
- package/dist/utils/payload-config-finder.js.map +0 -1
- package/dist/utils/payload-config-modifier.d.ts.map +0 -1
- package/dist/utils/payload-config-modifier.js.map +0 -1
- package/dist/utils/payload-package-check.d.ts.map +0 -1
- package/dist/utils/payload-package-check.js.map +0 -1
- package/dist/utils/project.d.ts.map +0 -1
- package/dist/utils/project.js.map +0 -1
- package/dist/utils/s3-upload.d.ts.map +0 -1
- package/dist/utils/s3-upload.js.map +0 -1
- package/dist/utils/token-display.d.ts.map +0 -1
- package/dist/utils/token-display.js.map +0 -1
- package/dist/utils/typescript-validator.d.ts.map +0 -1
- package/dist/utils/typescript-validator.js.map +0 -1
|
@@ -2,6 +2,7 @@ import { readFileSync } from 'fs';
|
|
|
2
2
|
import { createServer } from 'http';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
+
import { DEFAULT_CALLBACK_PORT } from '../config/oauth.js';
|
|
5
6
|
const filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const dirname = path.dirname(filename);
|
|
7
8
|
/**
|
|
@@ -27,7 +28,7 @@ const dirname = path.dirname(filename);
|
|
|
27
28
|
server = null;
|
|
28
29
|
timeoutMs;
|
|
29
30
|
constructor(options = {}){
|
|
30
|
-
this.preferredPort = options.port ||
|
|
31
|
+
this.preferredPort = options.port || DEFAULT_CALLBACK_PORT;
|
|
31
32
|
this.timeoutMs = options.timeoutMs || 120000; // 2 minutes default
|
|
32
33
|
this.server = createServer();
|
|
33
34
|
}
|
|
@@ -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
|
|
@@ -30,4 +30,10 @@
|
|
|
30
30
|
* @throws Error if unable to derive key due to missing machine information
|
|
31
31
|
*/
|
|
32
32
|
export declare function deriveEncryptionKey(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get a short hash of the encryption key for diagnostics.
|
|
35
|
+
* Returns first 8 chars of SHA-256 hash — enough to compare across invocations
|
|
36
|
+
* without exposing the actual key.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getEncryptionKeyHash(): string;
|
|
33
39
|
//# sourceMappingURL=crypto-utils.d.ts.map
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
2
|
import crypto from 'crypto';
|
|
3
3
|
import os from 'os';
|
|
4
|
-
// Configuration store for cryptographic salt
|
|
5
|
-
const cryptoConf = new Conf({
|
|
6
|
-
configName: 'payloadcms-figma-crypto',
|
|
7
|
-
projectName: 'payloadcms-figma'
|
|
8
|
-
});
|
|
9
4
|
/**
|
|
10
5
|
* Get or generate a random salt for key derivation
|
|
11
6
|
*
|
|
@@ -15,6 +10,11 @@ const cryptoConf = new Conf({
|
|
|
15
10
|
*
|
|
16
11
|
* @returns 32-byte hex string (64 characters)
|
|
17
12
|
*/ function getOrCreateSalt() {
|
|
13
|
+
// Configuration store for cryptographic salt
|
|
14
|
+
const cryptoConf = new Conf({
|
|
15
|
+
configName: 'payloadcms-figma-crypto',
|
|
16
|
+
projectName: 'payloadcms-figma'
|
|
17
|
+
});
|
|
18
18
|
let salt = cryptoConf.get('salt');
|
|
19
19
|
if (!salt) {
|
|
20
20
|
// Generate cryptographically secure random salt (32 bytes = 256 bits)
|
|
@@ -33,19 +33,13 @@ const cryptoConf = new Conf({
|
|
|
33
33
|
* @throws Error if unable to gather sufficient entropy
|
|
34
34
|
*/ function gatherMachineEntropy() {
|
|
35
35
|
try {
|
|
36
|
-
const userInfo = os.userInfo();
|
|
37
|
-
const networkInterfaces = os.networkInterfaces();
|
|
38
|
-
// Get MAC address from first available network interface (if available)
|
|
39
|
-
const macAddress = Object.values(networkInterfaces).flat().find((iface)=>iface && !iface.internal && iface.mac !== '00:00:00:00:00:00')?.mac;
|
|
40
36
|
const entropy = [
|
|
41
37
|
os.hostname(),
|
|
42
38
|
os.homedir(),
|
|
43
|
-
userInfo.username,
|
|
39
|
+
os.userInfo().username,
|
|
44
40
|
os.platform(),
|
|
45
|
-
os.arch()
|
|
46
|
-
|
|
47
|
-
].filter(Boolean) // Remove any undefined values
|
|
48
|
-
;
|
|
41
|
+
os.arch()
|
|
42
|
+
];
|
|
49
43
|
if (entropy.length < 4) {
|
|
50
44
|
throw new Error('Insufficient machine entropy available');
|
|
51
45
|
}
|
|
@@ -92,5 +86,13 @@ const cryptoConf = new Conf({
|
|
|
92
86
|
const key = crypto.pbkdf2Sync(machineId, salt, 100000, 32, 'sha256');
|
|
93
87
|
return key.toString('hex');
|
|
94
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Get a short hash of the encryption key for diagnostics.
|
|
91
|
+
* Returns first 8 chars of SHA-256 hash — enough to compare across invocations
|
|
92
|
+
* without exposing the actual key.
|
|
93
|
+
*/ export function getEncryptionKeyHash() {
|
|
94
|
+
const key = deriveEncryptionKey();
|
|
95
|
+
return crypto.createHash('sha256').update(key).digest('hex').substring(0, 8);
|
|
96
|
+
}
|
|
95
97
|
|
|
96
98
|
//# sourceMappingURL=crypto-utils.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Environment } from '../constants.js';
|
|
1
2
|
import type { JWTPayload } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* JWT validation error with specific error codes
|
|
@@ -27,7 +28,7 @@ export declare class JWTValidationError extends Error {
|
|
|
27
28
|
* @returns Promise resolving to validated JWT payload
|
|
28
29
|
* @throws {JWTValidationError} If validation fails
|
|
29
30
|
*/
|
|
30
|
-
export declare function validateProjectToken(token: string, environment:
|
|
31
|
+
export declare function validateProjectToken(token: string, environment: Environment): Promise<JWTPayload>;
|
|
31
32
|
/**
|
|
32
33
|
* Clear JWKS cache (useful for testing or forcing refresh)
|
|
33
34
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
2
2
|
import { JWKSMultipleMatchingKeys, JWKSNoMatchingKey, JWSInvalid, JWSSignatureVerificationFailed, JWTExpired } from 'jose/errors';
|
|
3
|
-
import {
|
|
3
|
+
import { ENV_CONFIG } from '../constants.js';
|
|
4
4
|
/**
|
|
5
5
|
* JWT validation error with specific error codes
|
|
6
6
|
*/ export class JWTValidationError extends Error {
|
|
@@ -28,7 +28,7 @@ import { getJWKSUri } from '../constants.js';
|
|
|
28
28
|
* @param environment - Figma environment ('production' or 'staging')
|
|
29
29
|
* @returns JWKS resolver function
|
|
30
30
|
*/ function getJWKSResolver(environment) {
|
|
31
|
-
const jwksUri =
|
|
31
|
+
const jwksUri = ENV_CONFIG[environment].jwksUri;
|
|
32
32
|
if (!jwksResolvers.has(jwksUri)) {
|
|
33
33
|
jwksResolvers.set(jwksUri, createRemoteJWKSet(new URL(jwksUri), {
|
|
34
34
|
cacheMaxAge: 24 * 60 * 60 * 1000,
|
|
@@ -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
|
/**
|
|
@@ -13,7 +14,7 @@ export declare class OAuthFlowError extends Error {
|
|
|
13
14
|
export interface OAuthFlowOptions {
|
|
14
15
|
/** OAuth2 client ID (defaults to config) */
|
|
15
16
|
clientId?: string;
|
|
16
|
-
/** Callback server port (defaults to
|
|
17
|
+
/** Callback server port (defaults to DEFAULT_CALLBACK_PORT) */
|
|
17
18
|
port?: number;
|
|
18
19
|
/** Redirect URI (defaults to config) */
|
|
19
20
|
redirectUri?: string;
|
|
@@ -55,8 +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
|
|
62
|
+
export declare function getValidOAuthAccessToken(tokenStore: TokenStore): Promise<AuthCredential | null>;
|
|
63
|
+
/**
|
|
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.
|
|
73
|
+
* Use in commands that want to fall through to a login prompt on failure.
|
|
74
|
+
*/
|
|
75
|
+
export declare function tryGetCredential(tokenStore: TokenStore): Promise<AuthCredential | null>;
|
|
62
76
|
//# sourceMappingURL=oauth-flow.d.ts.map
|
package/dist/auth/oauth-flow.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import crypto from 'crypto';
|
|
3
|
-
import {
|
|
3
|
+
import { DEFAULT_CALLBACK_PORT, getOAuthConfig } from '../config/oauth.js';
|
|
4
4
|
import * as log from '../utils/log.js';
|
|
5
5
|
import { buildAuthorizationUrl, openBrowser } from './browser.js';
|
|
6
6
|
import { CallbackServer } from './callback-server.js';
|
|
7
7
|
import { generatePKCEPair } from './pkce.js';
|
|
8
|
-
import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
8
|
+
import { exchangeCodeForTokens, refreshAccessToken, TokenRefreshError } from './refresh.js';
|
|
9
9
|
/**
|
|
10
10
|
* Error during OAuth flow
|
|
11
11
|
*/ export class OAuthFlowError extends Error {
|
|
@@ -32,16 +32,17 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
32
32
|
* @throws OAuthFlowError if any step fails
|
|
33
33
|
*/ export async function executeOAuthFlow(tokenStore, options = {}) {
|
|
34
34
|
// Check if OAuth flow should be mocked
|
|
35
|
-
// Default to
|
|
36
|
-
const shouldMock = process.env.FIGMA_MOCK_OAUTH
|
|
35
|
+
// Default to false for OAuth
|
|
36
|
+
const shouldMock = process.env.FIGMA_MOCK_OAUTH === 'true';
|
|
37
|
+
const oauthConfig = getOAuthConfig();
|
|
37
38
|
if (shouldMock) {
|
|
38
39
|
// MOCK IMPLEMENTATION: Return mock tokens for testing
|
|
39
|
-
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH
|
|
40
|
+
log.debug('Using mock OAuth flow (FIGMA_MOCK_OAUTH = true)');
|
|
40
41
|
const mockTokens = {
|
|
41
42
|
accessToken: 'figt_mock_access_token_' + crypto.randomBytes(16).toString('hex'),
|
|
42
43
|
expiresAt: Date.now() + 2 * 60 * 60 * 1000,
|
|
43
44
|
refreshToken: 'figt_mock_refresh_token_' + crypto.randomBytes(16).toString('hex'),
|
|
44
|
-
scopes: options.scopes ||
|
|
45
|
+
scopes: options.scopes || oauthConfig.scopes,
|
|
45
46
|
tokenType: 'Bearer'
|
|
46
47
|
};
|
|
47
48
|
// Store mock tokens
|
|
@@ -52,7 +53,7 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
// REAL OAUTH IMPLEMENTATION
|
|
55
|
-
const { clientId =
|
|
56
|
+
const { clientId = oauthConfig.clientId, port = DEFAULT_CALLBACK_PORT, redirectUri = oauthConfig.redirectUri, scopes = oauthConfig.scopes, timeoutMs = 120000 } = options;
|
|
56
57
|
// Generate PKCE pair for enhanced security
|
|
57
58
|
const { codeChallenge, codeChallengeMethod, codeVerifier } = generatePKCEPair();
|
|
58
59
|
// Generate random state for CSRF protection
|
|
@@ -73,7 +74,7 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
73
74
|
const actualRedirectUri = redirectUri.replace(/:\d+/, `:${actualPort}`);
|
|
74
75
|
// Build authorization URL
|
|
75
76
|
const authUrl = buildAuthorizationUrl({
|
|
76
|
-
authorizationUrl:
|
|
77
|
+
authorizationUrl: oauthConfig.authorizationUrl,
|
|
77
78
|
clientId,
|
|
78
79
|
codeChallenge,
|
|
79
80
|
codeChallengeMethod,
|
|
@@ -84,7 +85,7 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
84
85
|
// Prompt user to open browser
|
|
85
86
|
const shouldOpenBrowser = await p.confirm({
|
|
86
87
|
initialValue: true,
|
|
87
|
-
message: '
|
|
88
|
+
message: 'Authenticate with Figma in your browser?'
|
|
88
89
|
});
|
|
89
90
|
if (p.isCancel(shouldOpenBrowser)) {
|
|
90
91
|
throw new OAuthFlowError('Authentication cancelled by user');
|
|
@@ -142,28 +143,74 @@ import { exchangeCodeForTokens, refreshAccessToken } from './refresh.js';
|
|
|
142
143
|
* refreshes using the refresh token. If no tokens exist, returns null.
|
|
143
144
|
*
|
|
144
145
|
* @param tokenStore - Token store to use
|
|
145
|
-
* @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
|
|
146
147
|
* @throws OAuthFlowError if refresh fails
|
|
147
|
-
*/ export async function
|
|
148
|
+
*/ export async function getValidOAuthAccessToken(tokenStore) {
|
|
148
149
|
// Check if we have valid tokens
|
|
149
150
|
if (tokenStore.hasValidTokens()) {
|
|
150
|
-
|
|
151
|
+
const token = tokenStore.getAccessToken();
|
|
152
|
+
return token ? {
|
|
153
|
+
type: 'oauth',
|
|
154
|
+
token
|
|
155
|
+
} : null;
|
|
151
156
|
}
|
|
152
157
|
// Check if we have a refresh token
|
|
153
158
|
const refreshToken = tokenStore.getRefreshToken();
|
|
154
159
|
if (!refreshToken) {
|
|
155
160
|
return null;
|
|
156
161
|
}
|
|
157
|
-
// Try to refresh
|
|
162
|
+
// Try to refresh (with one retry for transient auth errors)
|
|
158
163
|
try {
|
|
159
164
|
const tokens = await refreshAccessToken(refreshToken);
|
|
160
165
|
tokenStore.setTokens(tokens);
|
|
161
|
-
return
|
|
166
|
+
return {
|
|
167
|
+
type: 'oauth',
|
|
168
|
+
token: tokens.accessToken
|
|
169
|
+
};
|
|
162
170
|
} catch (error) {
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
const isAuthFailure = error instanceof TokenRefreshError && (error.statusCode === 401 || error.statusCode === 403 || error.statusCode === 400 && error.errorCode === 'invalid_grant');
|
|
172
|
+
if (isAuthFailure) {
|
|
173
|
+
// Retry once — a transient 401 (e.g. misconfigured proxy) shouldn't wipe tokens
|
|
174
|
+
try {
|
|
175
|
+
const tokens = await refreshAccessToken(refreshToken);
|
|
176
|
+
tokenStore.setTokens(tokens);
|
|
177
|
+
return {
|
|
178
|
+
type: 'oauth',
|
|
179
|
+
token: tokens.accessToken
|
|
180
|
+
};
|
|
181
|
+
} catch {
|
|
182
|
+
// Retry also failed — token is genuinely revoked
|
|
183
|
+
tokenStore.clearTokens();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
165
186
|
throw new OAuthFlowError('Failed to refresh access token', error instanceof Error ? error : undefined);
|
|
166
187
|
}
|
|
167
188
|
}
|
|
189
|
+
/**
|
|
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.
|
|
207
|
+
* Use in commands that want to fall through to a login prompt on failure.
|
|
208
|
+
*/ export async function tryGetCredential(tokenStore) {
|
|
209
|
+
try {
|
|
210
|
+
return await getValidCredential(tokenStore);
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
168
215
|
|
|
169
216
|
//# sourceMappingURL=oauth-flow.js.map
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* to the Content API. Project tokens are scoped to a specific tenant/CMS
|
|
6
6
|
* and have a shorter lifespan (15-30 minutes) than OAuth tokens.
|
|
7
7
|
*/ import { getProjectToken as fetchProjectToken } from '../api/figma-api.js';
|
|
8
|
-
import {
|
|
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 {
|
|
11
|
+
import { getValidCredential } from './oauth-flow.js';
|
|
12
12
|
/**
|
|
13
13
|
* Error during project token operations
|
|
14
14
|
*/ export class ProjectTokenError extends Error {
|
|
@@ -60,36 +60,41 @@ import { getValidAccessToken } from './oauth-flow.js';
|
|
|
60
60
|
* @returns Promise resolving to JWT token string or null if failed
|
|
61
61
|
* @throws {ProjectTokenError} If token generation fails
|
|
62
62
|
*/ export async function getValidProjectToken(tokenStore, tenantId) {
|
|
63
|
-
|
|
63
|
+
if (process.env.FIGMA_CONTENT_API_ACCESS_KEY) {
|
|
64
|
+
log.debug('FIGMA_CONTENT_API_ACCESS_KEY is set; skipping project token retrieval from API');
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
// Check for existing valid project token
|
|
64
68
|
if (tokenStore.hasValidProjectToken(tenantId)) {
|
|
65
69
|
const projectToken = tokenStore.getProjectToken(tenantId);
|
|
66
70
|
return projectToken?.token || null;
|
|
67
71
|
}
|
|
68
72
|
// We need to refresh the project token
|
|
69
|
-
//
|
|
70
|
-
let
|
|
73
|
+
// An oauth access token is required for the call
|
|
74
|
+
let credential;
|
|
71
75
|
try {
|
|
72
|
-
|
|
76
|
+
credential = await getValidCredential(tokenStore);
|
|
73
77
|
} catch (error) {
|
|
74
78
|
throw new ProjectTokenError('Failed to get valid access token for project token refresh', error instanceof Error ? error : undefined);
|
|
75
79
|
}
|
|
76
|
-
if (!
|
|
80
|
+
if (!credential) {
|
|
77
81
|
// No valid user tokens available - user needs to authenticate
|
|
78
82
|
return null;
|
|
79
83
|
}
|
|
80
84
|
// Fetch a new project token from the Figma API
|
|
81
|
-
const projectToken = await fetchProjectToken(
|
|
85
|
+
const projectToken = await fetchProjectToken(credential, tenantId);
|
|
82
86
|
// Validate the JWT signature and claims (skip for mocks)
|
|
87
|
+
const hasEnvToken = !!process.env.FIGMA_MOCK_PROJECT_TOKEN_VALUE;
|
|
83
88
|
const shouldMock = process.env.FIGMA_MOCK_PROJECT_TOKEN !== 'false';
|
|
84
89
|
let validatedClaims;
|
|
85
|
-
if (shouldMock) {
|
|
90
|
+
if (hasEnvToken || shouldMock) {
|
|
86
91
|
// MOCK: Skip JWT validation and parse claims directly
|
|
87
|
-
log.debug('Skipping JWT validation for mock project token');
|
|
92
|
+
log.debug('Skipping JWT validation for mock/env project token');
|
|
88
93
|
validatedClaims = parseJWTClaims(projectToken.token);
|
|
89
94
|
} else {
|
|
90
95
|
// REAL: Validate JWT signature against JWKS
|
|
91
96
|
try {
|
|
92
|
-
validatedClaims = await validateProjectToken(projectToken.token,
|
|
97
|
+
validatedClaims = await validateProjectToken(projectToken.token, getInfraEnvironment());
|
|
93
98
|
} catch (validationError) {
|
|
94
99
|
// Handle validation errors
|
|
95
100
|
if (validationError instanceof JWTValidationError) {
|
package/dist/auth/refresh.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type { FigmaTokens } from './types.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class TokenRefreshError extends Error {
|
|
6
6
|
statusCode?: number | undefined;
|
|
7
|
-
|
|
7
|
+
errorCode?: string | undefined;
|
|
8
|
+
constructor(message: string, statusCode?: number | undefined, errorCode?: string | undefined);
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Refresh an expired OAuth2 access token using a refresh token
|
package/dist/auth/refresh.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
/* eslint-disable perfectionist/sort-objects */ import {
|
|
1
|
+
/* eslint-disable perfectionist/sort-objects */ import { getOAuthConfig } from '../config/oauth.js';
|
|
2
2
|
import * as log from '../utils/log.js';
|
|
3
3
|
/**
|
|
4
4
|
* Error thrown when token refresh fails
|
|
5
5
|
*/ export class TokenRefreshError extends Error {
|
|
6
6
|
statusCode;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
errorCode;
|
|
8
|
+
constructor(message, statusCode, errorCode){
|
|
9
|
+
super(message), this.statusCode = statusCode, this.errorCode = errorCode;
|
|
9
10
|
this.name = 'TokenRefreshError';
|
|
10
11
|
}
|
|
11
12
|
}
|
|
@@ -19,15 +20,17 @@ import * as log from '../utils/log.js';
|
|
|
19
20
|
* @param clientId - OAuth2 client ID (defaults to config)
|
|
20
21
|
* @returns Promise resolving to new tokens
|
|
21
22
|
* @throws TokenRefreshError if refresh fails
|
|
22
|
-
*/ export async function refreshAccessToken(refreshToken, clientId
|
|
23
|
+
*/ export async function refreshAccessToken(refreshToken, clientId) {
|
|
24
|
+
const oauthConfig = getOAuthConfig();
|
|
25
|
+
const resolvedClientId = clientId ?? oauthConfig.clientId;
|
|
23
26
|
// Prepare form data for token refresh request (public client)
|
|
24
27
|
const params = new URLSearchParams({
|
|
25
|
-
client_id:
|
|
28
|
+
client_id: resolvedClientId,
|
|
26
29
|
grant_type: 'refresh_token',
|
|
27
30
|
refresh_token: refreshToken
|
|
28
31
|
});
|
|
29
32
|
try {
|
|
30
|
-
const response = await fetch(
|
|
33
|
+
const response = await fetch(oauthConfig.refreshUrl, {
|
|
31
34
|
method: 'POST',
|
|
32
35
|
headers: {
|
|
33
36
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
@@ -36,7 +39,14 @@ import * as log from '../utils/log.js';
|
|
|
36
39
|
});
|
|
37
40
|
if (!response.ok) {
|
|
38
41
|
const errorText = await response.text();
|
|
39
|
-
|
|
42
|
+
let errorCode;
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(errorText);
|
|
45
|
+
errorCode = parsed.error;
|
|
46
|
+
} catch {
|
|
47
|
+
// Not JSON, leave errorCode undefined
|
|
48
|
+
}
|
|
49
|
+
throw new TokenRefreshError(`Token refresh failed: ${response.statusText}. ${errorText}`, response.status, errorCode);
|
|
40
50
|
}
|
|
41
51
|
const data = await response.json();
|
|
42
52
|
// Validate response contains required fields
|
|
@@ -71,14 +81,17 @@ import * as log from '../utils/log.js';
|
|
|
71
81
|
* @param clientId - OAuth2 client ID (defaults to config)
|
|
72
82
|
* @returns Promise resolving to tokens
|
|
73
83
|
* @throws TokenRefreshError if exchange fails
|
|
74
|
-
*/ export async function exchangeCodeForTokens(code, codeVerifier, redirectUri
|
|
84
|
+
*/ export async function exchangeCodeForTokens(code, codeVerifier, redirectUri, clientId) {
|
|
85
|
+
const oauthConfig = getOAuthConfig();
|
|
86
|
+
const resolvedRedirectUri = redirectUri ?? oauthConfig.redirectUri;
|
|
87
|
+
const resolvedClientId = clientId ?? oauthConfig.clientId;
|
|
75
88
|
// Prepare form data for token exchange (public client with PKCE)
|
|
76
89
|
const params = new URLSearchParams({
|
|
77
|
-
client_id:
|
|
90
|
+
client_id: resolvedClientId,
|
|
78
91
|
code,
|
|
79
92
|
code_verifier: codeVerifier,
|
|
80
93
|
grant_type: 'authorization_code',
|
|
81
|
-
redirect_uri:
|
|
94
|
+
redirect_uri: resolvedRedirectUri
|
|
82
95
|
});
|
|
83
96
|
try {
|
|
84
97
|
// Public client - no client secret or Basic Auth header needed
|
|
@@ -88,11 +101,11 @@ import * as log from '../utils/log.js';
|
|
|
88
101
|
};
|
|
89
102
|
// Debug logging
|
|
90
103
|
log.debug(`Token exchange request: ${JSON.stringify({
|
|
91
|
-
url:
|
|
104
|
+
url: oauthConfig.tokenUrl,
|
|
92
105
|
headers,
|
|
93
106
|
body: params.toString()
|
|
94
107
|
})}`);
|
|
95
|
-
const response = await fetch(
|
|
108
|
+
const response = await fetch(oauthConfig.tokenUrl, {
|
|
96
109
|
method: 'POST',
|
|
97
110
|
headers,
|
|
98
111
|
body: params.toString()
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Environment } from '../constants.js';
|
|
2
|
+
import type { BootstrapData, FigmaTokens, JWTPayload, ProjectToken, TokenStoreConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the singleton TokenStore instance for an environment
|
|
5
|
+
* Use this for all production code to ensure a single shared instance per environment
|
|
6
|
+
*
|
|
7
|
+
* @param environment - The environment to get the token store for
|
|
8
|
+
* @returns The singleton TokenStore instance for that environment
|
|
9
|
+
*/
|
|
10
|
+
export declare function getTokenStore(environment?: Environment): TokenStore;
|
|
2
11
|
/**
|
|
3
12
|
* Secure storage manager for Figma OAuth2 tokens
|
|
4
13
|
*
|
|
@@ -9,10 +18,15 @@ import type { FigmaTokens, JWTPayload, ProjectToken, TokenStoreConfig } from './
|
|
|
9
18
|
*
|
|
10
19
|
* Tokens are encrypted at rest with a machine-specific key and file permissions
|
|
11
20
|
* are set to 0600 (owner read/write only)
|
|
21
|
+
*
|
|
22
|
+
* For production code, use getTokenStore() to get the singleton instance.
|
|
23
|
+
* The constructor is still exported for test isolation.
|
|
12
24
|
*/
|
|
13
25
|
export declare class TokenStore {
|
|
14
26
|
private config;
|
|
27
|
+
private environment;
|
|
15
28
|
constructor(options?: TokenStoreConfig);
|
|
29
|
+
private safeGet;
|
|
16
30
|
/**
|
|
17
31
|
* Retrieve stored tokens
|
|
18
32
|
* @returns FigmaTokens if stored, null otherwise
|
|
@@ -106,5 +120,32 @@ export declare class TokenStore {
|
|
|
106
120
|
* @returns Array of tenant IDs
|
|
107
121
|
*/
|
|
108
122
|
getAllProjectTokenTenantIds(): string[];
|
|
123
|
+
/**
|
|
124
|
+
* Build the composite key for bootstrap data storage
|
|
125
|
+
* @param projectId - The CMS resource/project ID
|
|
126
|
+
* @param environmentName - The environment name (e.g. 'production', 'staging')
|
|
127
|
+
* @returns Composite key string
|
|
128
|
+
*/
|
|
129
|
+
private bootstrapKey;
|
|
130
|
+
/**
|
|
131
|
+
* Retrieve bootstrap data for a project + environment
|
|
132
|
+
* @param projectId - The CMS resource/project ID
|
|
133
|
+
* @param environmentName - The environment name
|
|
134
|
+
* @returns BootstrapData if stored, null otherwise
|
|
135
|
+
*/
|
|
136
|
+
getBootstrapData(projectId: string, environmentName: string): BootstrapData | null;
|
|
137
|
+
/**
|
|
138
|
+
* Store bootstrap data for a project + environment
|
|
139
|
+
* @param projectId - The CMS resource/project ID
|
|
140
|
+
* @param environmentName - The environment name
|
|
141
|
+
* @param data - The bootstrap data to store
|
|
142
|
+
*/
|
|
143
|
+
setBootstrapData(projectId: string, environmentName: string, data: BootstrapData): void;
|
|
144
|
+
/**
|
|
145
|
+
* Clear bootstrap data for a project + environment
|
|
146
|
+
* @param projectId - The CMS resource/project ID
|
|
147
|
+
* @param environmentName - The environment name
|
|
148
|
+
*/
|
|
149
|
+
clearBootstrapData(projectId: string, environmentName: string): void;
|
|
109
150
|
}
|
|
110
151
|
//# sourceMappingURL=token-store.d.ts.map
|