@payloadcms/figma 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +11 -0
- package/bin/cli.js +4 -0
- package/dist/api/control-plane.d.ts +124 -0
- package/dist/api/control-plane.d.ts.map +1 -0
- package/dist/api/control-plane.js +245 -0
- package/dist/api/control-plane.js.map +1 -0
- package/dist/api/control-plane.spec.d.ts +2 -0
- package/dist/api/control-plane.spec.d.ts.map +1 -0
- package/dist/api/control-plane.spec.js +296 -0
- package/dist/api/control-plane.spec.js.map +1 -0
- package/dist/api/figma-api.d.ts +31 -0
- package/dist/api/figma-api.d.ts.map +1 -0
- package/dist/api/figma-api.js +169 -0
- package/dist/api/figma-api.js.map +1 -0
- package/dist/api/figma-api.spec.d.ts +14 -0
- package/dist/api/figma-api.spec.d.ts.map +1 -0
- package/dist/api/figma-api.spec.js +201 -0
- package/dist/api/figma-api.spec.js.map +1 -0
- package/dist/auth/__tests__/fixtures.d.ts +26 -0
- package/dist/auth/__tests__/fixtures.d.ts.map +1 -0
- package/dist/auth/__tests__/fixtures.js +67 -0
- package/dist/auth/__tests__/fixtures.js.map +1 -0
- package/dist/auth/__tests__/mocks.d.ts +33 -0
- package/dist/auth/__tests__/mocks.d.ts.map +1 -0
- package/dist/auth/__tests__/mocks.js +63 -0
- package/dist/auth/__tests__/mocks.js.map +1 -0
- package/dist/auth/browser.d.ts +31 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/browser.js +41 -0
- package/dist/auth/browser.js.map +1 -0
- package/dist/auth/callback-server.d.ts +61 -0
- package/dist/auth/callback-server.d.ts.map +1 -0
- package/dist/auth/callback-server.js +168 -0
- package/dist/auth/callback-server.js.map +1 -0
- package/dist/auth/callback-server.spec.d.ts +2 -0
- package/dist/auth/callback-server.spec.d.ts.map +1 -0
- package/dist/auth/callback-server.spec.js +85 -0
- package/dist/auth/callback-server.spec.js.map +1 -0
- package/dist/auth/crypto-utils.d.ts +33 -0
- package/dist/auth/crypto-utils.d.ts.map +1 -0
- package/dist/auth/crypto-utils.js +96 -0
- package/dist/auth/crypto-utils.js.map +1 -0
- package/dist/auth/crypto-utils.spec.d.ts +2 -0
- package/dist/auth/crypto-utils.spec.d.ts.map +1 -0
- package/dist/auth/crypto-utils.spec.js +36 -0
- package/dist/auth/crypto-utils.spec.js.map +1 -0
- package/dist/auth/jwt-validator.d.ts +41 -0
- package/dist/auth/jwt-validator.d.ts.map +1 -0
- package/dist/auth/jwt-validator.js +113 -0
- package/dist/auth/jwt-validator.js.map +1 -0
- package/dist/auth/jwt-validator.spec.d.ts +10 -0
- package/dist/auth/jwt-validator.spec.d.ts.map +1 -0
- package/dist/auth/jwt-validator.spec.js +236 -0
- package/dist/auth/jwt-validator.spec.js.map +1 -0
- package/dist/auth/oauth-flow.d.ts +62 -0
- package/dist/auth/oauth-flow.d.ts.map +1 -0
- package/dist/auth/oauth-flow.js +172 -0
- package/dist/auth/oauth-flow.js.map +1 -0
- package/dist/auth/oauth-flow.spec.d.ts +2 -0
- package/dist/auth/oauth-flow.spec.d.ts.map +1 -0
- package/dist/auth/oauth-flow.spec.js +134 -0
- package/dist/auth/oauth-flow.spec.js.map +1 -0
- package/dist/auth/pages/error.html +85 -0
- package/dist/auth/pages/success.html +74 -0
- package/dist/auth/pkce.d.ts +51 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +71 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/pkce.spec.d.ts +2 -0
- package/dist/auth/pkce.spec.d.ts.map +1 -0
- package/dist/auth/pkce.spec.js +32 -0
- package/dist/auth/pkce.spec.js.map +1 -0
- package/dist/auth/project-token.d.ts +47 -0
- package/dist/auth/project-token.d.ts.map +1 -0
- package/dist/auth/project-token.js +134 -0
- package/dist/auth/project-token.js.map +1 -0
- package/dist/auth/project-token.spec.d.ts +2 -0
- package/dist/auth/project-token.spec.d.ts.map +1 -0
- package/dist/auth/project-token.spec.js +332 -0
- package/dist/auth/project-token.spec.js.map +1 -0
- package/dist/auth/refresh.d.ts +35 -0
- package/dist/auth/refresh.d.ts.map +1 -0
- package/dist/auth/refresh.js +149 -0
- package/dist/auth/refresh.js.map +1 -0
- package/dist/auth/refresh.spec.d.ts +2 -0
- package/dist/auth/refresh.spec.d.ts.map +1 -0
- package/dist/auth/refresh.spec.js +105 -0
- package/dist/auth/refresh.spec.js.map +1 -0
- package/dist/auth/token-store.d.ts +110 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +188 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/token-store.spec.d.ts +2 -0
- package/dist/auth/token-store.spec.d.ts.map +1 -0
- package/dist/auth/token-store.spec.js +276 -0
- package/dist/auth/token-store.spec.js.map +1 -0
- package/dist/auth/types.d.ts +197 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +108 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/__tests__/test-utils.d.ts +28 -0
- package/dist/commands/__tests__/test-utils.d.ts.map +1 -0
- package/dist/commands/__tests__/test-utils.js +34 -0
- package/dist/commands/__tests__/test-utils.js.map +1 -0
- package/dist/commands/deploy.d.ts +16 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +297 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/deploy.spec.d.ts +2 -0
- package/dist/commands/deploy.spec.d.ts.map +1 -0
- package/dist/commands/deploy.spec.js +18 -0
- package/dist/commands/deploy.spec.js.map +1 -0
- package/dist/commands/init.d.ts +30 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +410 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.spec.d.ts +2 -0
- package/dist/commands/init.spec.d.ts.map +1 -0
- package/dist/commands/init.spec.js +283 -0
- package/dist/commands/init.spec.js.map +1 -0
- package/dist/commands/list-tokens.d.ts +16 -0
- package/dist/commands/list-tokens.d.ts.map +1 -0
- package/dist/commands/list-tokens.js +44 -0
- package/dist/commands/list-tokens.js.map +1 -0
- package/dist/commands/login.d.ts +17 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +69 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +16 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +43 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/config/oauth.d.ts +19 -0
- package/dist/config/oauth.d.ts.map +1 -0
- package/dist/config/oauth.js +43 -0
- package/dist/config/oauth.js.map +1 -0
- package/dist/constants.d.ts +27 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +27 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/adapter.d.ts +5 -0
- package/dist/plugin/adapter.d.ts.map +1 -0
- package/dist/plugin/adapter.js +139 -0
- package/dist/plugin/adapter.js.map +1 -0
- package/dist/plugin/build-config.d.ts +37 -0
- package/dist/plugin/build-config.d.ts.map +1 -0
- package/dist/plugin/build-config.js +25 -0
- package/dist/plugin/build-config.js.map +1 -0
- package/dist/plugin/build-config.spec.d.ts +2 -0
- package/dist/plugin/build-config.spec.d.ts.map +1 -0
- package/dist/plugin/build-config.spec.js +72 -0
- package/dist/plugin/build-config.spec.js.map +1 -0
- package/dist/types/config.d.ts +45 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +9 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/asset-collection.d.ts +30 -0
- package/dist/utils/asset-collection.d.ts.map +1 -0
- package/dist/utils/asset-collection.js +117 -0
- package/dist/utils/asset-collection.js.map +1 -0
- package/dist/utils/asset-collection.spec.d.ts +2 -0
- package/dist/utils/asset-collection.spec.d.ts.map +1 -0
- package/dist/utils/asset-collection.spec.js +155 -0
- package/dist/utils/asset-collection.spec.js.map +1 -0
- package/dist/utils/build-detection.d.ts +32 -0
- package/dist/utils/build-detection.d.ts.map +1 -0
- package/dist/utils/build-detection.js +55 -0
- package/dist/utils/build-detection.js.map +1 -0
- package/dist/utils/build-detection.spec.d.ts +2 -0
- package/dist/utils/build-detection.spec.d.ts.map +1 -0
- package/dist/utils/build-detection.spec.js +110 -0
- package/dist/utils/build-detection.spec.js.map +1 -0
- package/dist/utils/config.d.ts +33 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +78 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/config.spec.d.ts +2 -0
- package/dist/utils/config.spec.d.ts.map +1 -0
- package/dist/utils/config.spec.js +167 -0
- package/dist/utils/config.spec.js.map +1 -0
- package/dist/utils/download-template.d.ts +15 -0
- package/dist/utils/download-template.d.ts.map +1 -0
- package/dist/utils/download-template.js +74 -0
- package/dist/utils/download-template.js.map +1 -0
- package/dist/utils/download-template.spec.d.ts +2 -0
- package/dist/utils/download-template.spec.d.ts.map +1 -0
- package/dist/utils/download-template.spec.js +76 -0
- package/dist/utils/download-template.spec.js.map +1 -0
- package/dist/utils/env-management.d.ts +16 -0
- package/dist/utils/env-management.d.ts.map +1 -0
- package/dist/utils/env-management.js +98 -0
- package/dist/utils/env-management.js.map +1 -0
- package/dist/utils/env-management.spec.d.ts +2 -0
- package/dist/utils/env-management.spec.d.ts.map +1 -0
- package/dist/utils/env-management.spec.js +123 -0
- package/dist/utils/env-management.spec.js.map +1 -0
- package/dist/utils/format.d.ts +23 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +49 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/formatter.d.ts +11 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +47 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/git.d.ts +15 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +92 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/git.spec.d.ts +2 -0
- package/dist/utils/git.spec.d.ts.map +1 -0
- package/dist/utils/git.spec.js +99 -0
- package/dist/utils/git.spec.js.map +1 -0
- package/dist/utils/is-debug.d.ts +6 -0
- package/dist/utils/is-debug.d.ts.map +1 -0
- package/dist/utils/is-debug.js +8 -0
- package/dist/utils/is-debug.js.map +1 -0
- package/dist/utils/lambda-config.d.ts +7 -0
- package/dist/utils/lambda-config.d.ts.map +1 -0
- package/dist/utils/lambda-config.js +144 -0
- package/dist/utils/lambda-config.js.map +1 -0
- package/dist/utils/lambda-config.spec.d.ts +2 -0
- package/dist/utils/lambda-config.spec.d.ts.map +1 -0
- package/dist/utils/lambda-config.spec.js +141 -0
- package/dist/utils/lambda-config.spec.js.map +1 -0
- package/dist/utils/log.d.ts +6 -0
- package/dist/utils/log.d.ts.map +1 -0
- package/dist/utils/log.js +22 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/messages.d.ts +10 -0
- package/dist/utils/messages.d.ts.map +1 -0
- package/dist/utils/messages.js +96 -0
- package/dist/utils/messages.js.map +1 -0
- package/dist/utils/package-manager.d.ts +12 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +37 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/payload-config-ast.d.ts +30 -0
- package/dist/utils/payload-config-ast.d.ts.map +1 -0
- package/dist/utils/payload-config-ast.js +259 -0
- package/dist/utils/payload-config-ast.js.map +1 -0
- package/dist/utils/payload-config-ast.spec.d.ts +2 -0
- package/dist/utils/payload-config-ast.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-ast.spec.js +303 -0
- package/dist/utils/payload-config-ast.spec.js.map +1 -0
- package/dist/utils/payload-config-finder.d.ts +9 -0
- package/dist/utils/payload-config-finder.d.ts.map +1 -0
- package/dist/utils/payload-config-finder.js +26 -0
- package/dist/utils/payload-config-finder.js.map +1 -0
- package/dist/utils/payload-config-modifier.d.ts +18 -0
- package/dist/utils/payload-config-modifier.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.int.spec.d.ts +2 -0
- package/dist/utils/payload-config-modifier.int.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.int.spec.js +116 -0
- package/dist/utils/payload-config-modifier.int.spec.js.map +1 -0
- package/dist/utils/payload-config-modifier.js +232 -0
- package/dist/utils/payload-config-modifier.js.map +1 -0
- package/dist/utils/payload-config-modifier.spec.d.ts +2 -0
- package/dist/utils/payload-config-modifier.spec.d.ts.map +1 -0
- package/dist/utils/payload-config-modifier.spec.js +162 -0
- package/dist/utils/payload-config-modifier.spec.js.map +1 -0
- package/dist/utils/payload-package-check.d.ts +15 -0
- package/dist/utils/payload-package-check.d.ts.map +1 -0
- package/dist/utils/payload-package-check.js +116 -0
- package/dist/utils/payload-package-check.js.map +1 -0
- package/dist/utils/payload-package-check.spec.d.ts +2 -0
- package/dist/utils/payload-package-check.spec.d.ts.map +1 -0
- package/dist/utils/payload-package-check.spec.js +148 -0
- package/dist/utils/payload-package-check.spec.js.map +1 -0
- package/dist/utils/project.d.ts +58 -0
- package/dist/utils/project.d.ts.map +1 -0
- package/dist/utils/project.js +252 -0
- package/dist/utils/project.js.map +1 -0
- package/dist/utils/project.spec.d.ts +2 -0
- package/dist/utils/project.spec.d.ts.map +1 -0
- package/dist/utils/project.spec.js +222 -0
- package/dist/utils/project.spec.js.map +1 -0
- package/dist/utils/s3-upload.d.ts +43 -0
- package/dist/utils/s3-upload.d.ts.map +1 -0
- package/dist/utils/s3-upload.js +128 -0
- package/dist/utils/s3-upload.js.map +1 -0
- package/dist/utils/s3-upload.spec.d.ts +2 -0
- package/dist/utils/s3-upload.spec.d.ts.map +1 -0
- package/dist/utils/s3-upload.spec.js +140 -0
- package/dist/utils/s3-upload.spec.js.map +1 -0
- package/dist/utils/token-display.d.ts +14 -0
- package/dist/utils/token-display.d.ts.map +1 -0
- package/dist/utils/token-display.js +62 -0
- package/dist/utils/token-display.js.map +1 -0
- package/dist/utils/typescript-validator.d.ts +11 -0
- package/dist/utils/typescript-validator.d.ts.map +1 -0
- package/dist/utils/typescript-validator.js +58 -0
- package/dist/utils/typescript-validator.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
import * as controlPlane from '../api/control-plane.js';
|
|
6
|
+
import { getValidAccessToken } from '../auth/oauth-flow.js';
|
|
7
|
+
import * as config from '../utils/config.js';
|
|
8
|
+
import * as payloadConfigModifier from '../utils/payload-config-modifier.js';
|
|
9
|
+
import * as project from '../utils/project.js';
|
|
10
|
+
import { mockProcessExit } from './__tests__/test-utils.js';
|
|
11
|
+
import { initCommand } from './init.js';
|
|
12
|
+
// Mock dependencies
|
|
13
|
+
vi.mock('@clack/prompts', ()=>{
|
|
14
|
+
const mockLog = {
|
|
15
|
+
error: vi.fn(),
|
|
16
|
+
info: vi.fn(),
|
|
17
|
+
step: vi.fn(),
|
|
18
|
+
success: vi.fn(),
|
|
19
|
+
warn: vi.fn()
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
cancel: vi.fn(),
|
|
23
|
+
confirm: vi.fn(),
|
|
24
|
+
intro: vi.fn(),
|
|
25
|
+
isCancel: vi.fn((value)=>value === Symbol.for('clack.cancel')),
|
|
26
|
+
log: mockLog,
|
|
27
|
+
note: vi.fn(),
|
|
28
|
+
outro: vi.fn(),
|
|
29
|
+
select: vi.fn(),
|
|
30
|
+
spinner: vi.fn(()=>({
|
|
31
|
+
start: vi.fn(),
|
|
32
|
+
stop: vi.fn()
|
|
33
|
+
})),
|
|
34
|
+
text: vi.fn()
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
vi.mock('../auth/oauth-flow.js', ()=>({
|
|
38
|
+
getValidAccessToken: vi.fn()
|
|
39
|
+
}));
|
|
40
|
+
vi.mock('../auth/token-store.js', ()=>({
|
|
41
|
+
TokenStore: vi.fn(()=>({
|
|
42
|
+
getAccessToken: vi.fn(()=>'cached-token'),
|
|
43
|
+
hasValidTokens: vi.fn(()=>false)
|
|
44
|
+
}))
|
|
45
|
+
}));
|
|
46
|
+
vi.mock('./login.js', ()=>({
|
|
47
|
+
loginCommand: vi.fn().mockResolvedValue(undefined)
|
|
48
|
+
}));
|
|
49
|
+
vi.mock('../utils/log.js', ()=>({
|
|
50
|
+
debug: vi.fn(),
|
|
51
|
+
error: vi.fn(),
|
|
52
|
+
info: vi.fn(),
|
|
53
|
+
log: vi.fn(),
|
|
54
|
+
warning: vi.fn()
|
|
55
|
+
}));
|
|
56
|
+
// Mock file system operations
|
|
57
|
+
vi.mock('../utils/config.js', async ()=>{
|
|
58
|
+
const actual = await vi.importActual('../utils/config.js');
|
|
59
|
+
return {
|
|
60
|
+
...actual,
|
|
61
|
+
hasFigmaConfig: vi.fn(),
|
|
62
|
+
readFigmaConfig: vi.fn(),
|
|
63
|
+
writeFigmaConfig: vi.fn()
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
vi.mock('../utils/project.js', async ()=>{
|
|
67
|
+
const actual = await vi.importActual('../utils/project.js');
|
|
68
|
+
return {
|
|
69
|
+
...actual,
|
|
70
|
+
detectPayloadProject: vi.fn(),
|
|
71
|
+
hasRequiredDependencies: vi.fn(),
|
|
72
|
+
installDependencies: vi.fn(),
|
|
73
|
+
isInProjectDirectory: vi.fn(),
|
|
74
|
+
scaffoldProject: vi.fn()
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
vi.mock('../api/control-plane.js', ()=>({
|
|
78
|
+
createTenant: vi.fn(),
|
|
79
|
+
getTenantDetails: vi.fn(),
|
|
80
|
+
listTenants: vi.fn()
|
|
81
|
+
}));
|
|
82
|
+
vi.mock('../utils/payload-config-modifier.js', ()=>({
|
|
83
|
+
displayManualInstructions: vi.fn(),
|
|
84
|
+
ensurePayloadFigmaConfig: vi.fn()
|
|
85
|
+
}));
|
|
86
|
+
describe('init command', ()=>{
|
|
87
|
+
let processExitMock;
|
|
88
|
+
let testDir;
|
|
89
|
+
beforeEach(async ()=>{
|
|
90
|
+
vi.clearAllMocks();
|
|
91
|
+
processExitMock = mockProcessExit();
|
|
92
|
+
// Create temp test directory
|
|
93
|
+
testDir = path.join(process.cwd(), '.test-tmp', `init-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`);
|
|
94
|
+
await fs.mkdir(testDir, {
|
|
95
|
+
recursive: true
|
|
96
|
+
});
|
|
97
|
+
// Default mocks
|
|
98
|
+
vi.mocked(config.writeFigmaConfig).mockResolvedValue();
|
|
99
|
+
vi.mocked(project.isInProjectDirectory).mockResolvedValue(true); // Default: existing project
|
|
100
|
+
vi.mocked(project.hasRequiredDependencies).mockResolvedValue(true); // Default: deps installed
|
|
101
|
+
vi.mocked(payloadConfigModifier.ensurePayloadFigmaConfig).mockResolvedValue({
|
|
102
|
+
changes: [],
|
|
103
|
+
modified: false,
|
|
104
|
+
success: true
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
afterEach(async ()=>{
|
|
108
|
+
processExitMock.restore();
|
|
109
|
+
// Clean up test directory
|
|
110
|
+
try {
|
|
111
|
+
await fs.rm(testDir, {
|
|
112
|
+
force: true,
|
|
113
|
+
recursive: true
|
|
114
|
+
});
|
|
115
|
+
} catch {
|
|
116
|
+
// Ignore cleanup errors
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
describe('authentication check', ()=>{
|
|
120
|
+
it('should skip auth when --skip-auth flag is used', async ()=>{
|
|
121
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
122
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
123
|
+
hasPayload: true,
|
|
124
|
+
path: testDir,
|
|
125
|
+
payloadVersion: '^3.54.0'
|
|
126
|
+
});
|
|
127
|
+
vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({
|
|
128
|
+
id: 'tenant_test',
|
|
129
|
+
domain: 'test.figmacms.com',
|
|
130
|
+
parentId: 'team_123',
|
|
131
|
+
parentType: 'team',
|
|
132
|
+
status: 'active'
|
|
133
|
+
});
|
|
134
|
+
await initCommand({
|
|
135
|
+
id: 'tenant_test',
|
|
136
|
+
skipAuth: true
|
|
137
|
+
});
|
|
138
|
+
expect(getValidAccessToken).not.toHaveBeenCalled();
|
|
139
|
+
});
|
|
140
|
+
it('should prompt and authenticate when user confirms', async ()=>{
|
|
141
|
+
// First call returns null (not authenticated), second call returns valid token (after auth)
|
|
142
|
+
vi.mocked(getValidAccessToken).mockResolvedValueOnce(null).mockResolvedValueOnce('valid-token');
|
|
143
|
+
vi.mocked(p.confirm).mockResolvedValue(true);
|
|
144
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
145
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
146
|
+
hasPayload: true,
|
|
147
|
+
path: testDir,
|
|
148
|
+
payloadVersion: '^3.54.0'
|
|
149
|
+
});
|
|
150
|
+
vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({
|
|
151
|
+
id: 'tenant_test',
|
|
152
|
+
domain: 'test.figmacms.com',
|
|
153
|
+
parentId: 'team_123',
|
|
154
|
+
parentType: 'team',
|
|
155
|
+
status: 'active'
|
|
156
|
+
});
|
|
157
|
+
await initCommand({
|
|
158
|
+
id: 'tenant_test'
|
|
159
|
+
});
|
|
160
|
+
expect(p.confirm).toHaveBeenCalledWith(expect.objectContaining({
|
|
161
|
+
message: 'Would you like to authenticate now?'
|
|
162
|
+
}));
|
|
163
|
+
// Verify loginCommand was called
|
|
164
|
+
const { loginCommand } = await import('./login.js');
|
|
165
|
+
expect(loginCommand).toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
describe('already initialized check', ()=>{
|
|
169
|
+
it('should exit if already initialized', async ()=>{
|
|
170
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(true);
|
|
171
|
+
vi.mocked(config.readFigmaConfig).mockResolvedValue({
|
|
172
|
+
domain: 'existing.figmacms.com',
|
|
173
|
+
tenantId: 'tenant_existing'
|
|
174
|
+
});
|
|
175
|
+
await expect(initCommand({
|
|
176
|
+
id: 'tenant_test',
|
|
177
|
+
skipAuth: true
|
|
178
|
+
})).rejects.toThrow('process.exit(0)');
|
|
179
|
+
expect(processExitMock.exitMock).toHaveBeenCalledWith(0);
|
|
180
|
+
});
|
|
181
|
+
it('should proceed if --force flag is used', async ()=>{
|
|
182
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(true);
|
|
183
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
184
|
+
hasPayload: true,
|
|
185
|
+
path: testDir,
|
|
186
|
+
payloadVersion: '^3.54.0'
|
|
187
|
+
});
|
|
188
|
+
vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({
|
|
189
|
+
id: 'tenant_new',
|
|
190
|
+
domain: 'test-cms.figmacms.com',
|
|
191
|
+
parentId: 'team_123',
|
|
192
|
+
parentType: 'team',
|
|
193
|
+
status: 'active'
|
|
194
|
+
});
|
|
195
|
+
await initCommand({
|
|
196
|
+
id: 'tenant_new',
|
|
197
|
+
force: true,
|
|
198
|
+
skipAuth: true
|
|
199
|
+
});
|
|
200
|
+
expect(config.readFigmaConfig).not.toHaveBeenCalled();
|
|
201
|
+
expect(controlPlane.getTenantDetails).toHaveBeenCalled();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
describe('project validation', ()=>{
|
|
205
|
+
it('should reject invalid Payload version', async ()=>{
|
|
206
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
207
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
208
|
+
hasPayload: true,
|
|
209
|
+
path: testDir,
|
|
210
|
+
payloadVersion: '^2.0.0'
|
|
211
|
+
});
|
|
212
|
+
await expect(initCommand({
|
|
213
|
+
id: 'tenant_test',
|
|
214
|
+
skipAuth: true
|
|
215
|
+
})).rejects.toThrow('process.exit(1)');
|
|
216
|
+
expect(processExitMock.exitMock).toHaveBeenCalledWith(1);
|
|
217
|
+
});
|
|
218
|
+
it('should exit if user declines to scaffold project', async ()=>{
|
|
219
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
220
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
221
|
+
hasPayload: false,
|
|
222
|
+
path: testDir
|
|
223
|
+
});
|
|
224
|
+
vi.mocked(p.confirm).mockResolvedValue(false);
|
|
225
|
+
await expect(initCommand({
|
|
226
|
+
id: 'tenant_test',
|
|
227
|
+
skipAuth: true
|
|
228
|
+
})).rejects.toThrow('process.exit(1)');
|
|
229
|
+
expect(processExitMock.exitMock).toHaveBeenCalledWith(1);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('tenant configuration', ()=>{
|
|
233
|
+
it('should fetch tenant details and write config', async ()=>{
|
|
234
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
235
|
+
vi.mocked(project.detectPayloadProject).mockResolvedValue({
|
|
236
|
+
hasPayload: true,
|
|
237
|
+
path: testDir,
|
|
238
|
+
payloadVersion: '^3.54.0'
|
|
239
|
+
});
|
|
240
|
+
vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({
|
|
241
|
+
id: 'tenant_abc',
|
|
242
|
+
domain: 'abc.figmacms.com',
|
|
243
|
+
parentId: 'team_123',
|
|
244
|
+
parentType: 'team',
|
|
245
|
+
status: 'active'
|
|
246
|
+
});
|
|
247
|
+
await initCommand({
|
|
248
|
+
id: 'tenant_abc',
|
|
249
|
+
skipAuth: true
|
|
250
|
+
});
|
|
251
|
+
expect(controlPlane.getTenantDetails).toHaveBeenCalledWith('mock-access-token', 'tenant_abc');
|
|
252
|
+
expect(config.writeFigmaConfig).toHaveBeenCalledWith({
|
|
253
|
+
domain: 'abc.figmacms.com',
|
|
254
|
+
tenantId: 'tenant_abc'
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
describe('Lambda setup verification', ()=>{
|
|
259
|
+
it('should verify scaffoldProject creates Lambda-ready files', async ()=>{
|
|
260
|
+
// This test verifies the integration between scaffoldProject and Lambda modifications
|
|
261
|
+
// by checking that the mocked scaffoldProject was called correctly
|
|
262
|
+
vi.mocked(config.hasFigmaConfig).mockResolvedValue(false);
|
|
263
|
+
vi.mocked(project.isInProjectDirectory).mockResolvedValue(false); // Trigger new project flow
|
|
264
|
+
vi.mocked(p.text).mockResolvedValue('test-project'); // Project path prompt
|
|
265
|
+
vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({
|
|
266
|
+
id: 'tenant_test',
|
|
267
|
+
domain: 'test.figmacms.com',
|
|
268
|
+
parentId: 'team_123',
|
|
269
|
+
parentType: 'team',
|
|
270
|
+
status: 'active'
|
|
271
|
+
});
|
|
272
|
+
await initCommand({
|
|
273
|
+
id: 'tenant_test',
|
|
274
|
+
skipAuth: true
|
|
275
|
+
});
|
|
276
|
+
// Verify scaffoldProject was called (which internally applies Lambda modifications)
|
|
277
|
+
expect(project.scaffoldProject).toHaveBeenCalled();
|
|
278
|
+
expect(project.installDependencies).toHaveBeenCalled();
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
//# sourceMappingURL=init.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/init.spec.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport fs from 'fs/promises'\nimport path from 'path'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport * as controlPlane from '../api/control-plane.js'\nimport { getValidAccessToken } from '../auth/oauth-flow.js'\nimport * as config from '../utils/config.js'\nimport * as payloadConfigModifier from '../utils/payload-config-modifier.js'\nimport * as project from '../utils/project.js'\nimport { mockProcessExit } from './__tests__/test-utils.js'\nimport { initCommand } from './init.js'\n\n// Mock dependencies\nvi.mock('@clack/prompts', () => {\n const mockLog = {\n error: vi.fn(),\n info: vi.fn(),\n step: vi.fn(),\n success: vi.fn(),\n warn: vi.fn(),\n }\n\n return {\n cancel: vi.fn(),\n confirm: vi.fn(),\n intro: vi.fn(),\n isCancel: vi.fn((value) => value === Symbol.for('clack.cancel')),\n log: mockLog,\n note: vi.fn(),\n outro: vi.fn(),\n select: vi.fn(),\n spinner: vi.fn(() => ({\n start: vi.fn(),\n stop: vi.fn(),\n })),\n text: vi.fn(),\n }\n})\n\nvi.mock('../auth/oauth-flow.js', () => ({\n getValidAccessToken: vi.fn(),\n}))\n\nvi.mock('../auth/token-store.js', () => ({\n TokenStore: vi.fn(() => ({\n getAccessToken: vi.fn(() => 'cached-token'),\n hasValidTokens: vi.fn(() => false),\n })),\n}))\n\nvi.mock('./login.js', () => ({\n loginCommand: vi.fn().mockResolvedValue(undefined),\n}))\n\nvi.mock('../utils/log.js', () => ({\n debug: vi.fn(),\n error: vi.fn(),\n info: vi.fn(),\n log: vi.fn(),\n warning: vi.fn(),\n}))\n\n// Mock file system operations\nvi.mock('../utils/config.js', async () => {\n const actual = await vi.importActual<typeof config>('../utils/config.js')\n return {\n ...actual,\n hasFigmaConfig: vi.fn(),\n readFigmaConfig: vi.fn(),\n writeFigmaConfig: vi.fn(),\n }\n})\n\nvi.mock('../utils/project.js', async () => {\n const actual = await vi.importActual<typeof project>('../utils/project.js')\n return {\n ...actual,\n detectPayloadProject: vi.fn(),\n hasRequiredDependencies: vi.fn(),\n installDependencies: vi.fn(),\n isInProjectDirectory: vi.fn(),\n scaffoldProject: vi.fn(),\n }\n})\n\nvi.mock('../api/control-plane.js', () => ({\n createTenant: vi.fn(),\n getTenantDetails: vi.fn(),\n listTenants: vi.fn(),\n}))\n\nvi.mock('../utils/payload-config-modifier.js', () => ({\n displayManualInstructions: vi.fn(),\n ensurePayloadFigmaConfig: vi.fn(),\n}))\n\ndescribe('init command', () => {\n let processExitMock: ReturnType<typeof mockProcessExit>\n let testDir: string\n\n beforeEach(async () => {\n vi.clearAllMocks()\n processExitMock = mockProcessExit()\n\n // Create temp test directory\n testDir = path.join(\n process.cwd(),\n '.test-tmp',\n `init-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,\n )\n await fs.mkdir(testDir, { recursive: true })\n\n // Default mocks\n vi.mocked(config.writeFigmaConfig).mockResolvedValue()\n vi.mocked(project.isInProjectDirectory).mockResolvedValue(true) // Default: existing project\n vi.mocked(project.hasRequiredDependencies).mockResolvedValue(true) // Default: deps installed\n vi.mocked(payloadConfigModifier.ensurePayloadFigmaConfig).mockResolvedValue({\n changes: [],\n modified: false,\n success: true,\n })\n })\n\n afterEach(async () => {\n processExitMock.restore()\n\n // Clean up test directory\n try {\n await fs.rm(testDir, { force: true, recursive: true })\n } catch {\n // Ignore cleanup errors\n }\n })\n\n describe('authentication check', () => {\n it('should skip auth when --skip-auth flag is used', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: true,\n path: testDir,\n payloadVersion: '^3.54.0',\n })\n vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({\n id: 'tenant_test',\n domain: 'test.figmacms.com',\n parentId: 'team_123',\n parentType: 'team',\n status: 'active',\n })\n await initCommand({ id: 'tenant_test', skipAuth: true })\n\n expect(getValidAccessToken).not.toHaveBeenCalled()\n })\n\n it('should prompt and authenticate when user confirms', async () => {\n // First call returns null (not authenticated), second call returns valid token (after auth)\n vi.mocked(getValidAccessToken)\n .mockResolvedValueOnce(null)\n .mockResolvedValueOnce('valid-token')\n vi.mocked(p.confirm).mockResolvedValue(true)\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: true,\n path: testDir,\n payloadVersion: '^3.54.0',\n })\n vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({\n id: 'tenant_test',\n domain: 'test.figmacms.com',\n parentId: 'team_123',\n parentType: 'team',\n status: 'active',\n })\n\n await initCommand({ id: 'tenant_test' })\n\n expect(p.confirm).toHaveBeenCalledWith(\n expect.objectContaining({\n message: 'Would you like to authenticate now?',\n }),\n )\n // Verify loginCommand was called\n const { loginCommand } = await import('./login.js')\n expect(loginCommand).toHaveBeenCalled()\n })\n })\n\n describe('already initialized check', () => {\n it('should exit if already initialized', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(true)\n vi.mocked(config.readFigmaConfig).mockResolvedValue({\n domain: 'existing.figmacms.com',\n tenantId: 'tenant_existing',\n })\n\n await expect(initCommand({ id: 'tenant_test', skipAuth: true })).rejects.toThrow(\n 'process.exit(0)',\n )\n\n expect(processExitMock.exitMock).toHaveBeenCalledWith(0)\n })\n\n it('should proceed if --force flag is used', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(true)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: true,\n path: testDir,\n payloadVersion: '^3.54.0',\n })\n vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({\n id: 'tenant_new',\n domain: 'test-cms.figmacms.com',\n parentId: 'team_123',\n parentType: 'team',\n status: 'active',\n })\n\n await initCommand({ id: 'tenant_new', force: true, skipAuth: true })\n\n expect(config.readFigmaConfig).not.toHaveBeenCalled()\n expect(controlPlane.getTenantDetails).toHaveBeenCalled()\n })\n })\n\n describe('project validation', () => {\n it('should reject invalid Payload version', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: true,\n path: testDir,\n payloadVersion: '^2.0.0',\n })\n\n await expect(initCommand({ id: 'tenant_test', skipAuth: true })).rejects.toThrow(\n 'process.exit(1)',\n )\n\n expect(processExitMock.exitMock).toHaveBeenCalledWith(1)\n })\n\n it('should exit if user declines to scaffold project', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: false,\n path: testDir,\n })\n vi.mocked(p.confirm).mockResolvedValue(false)\n\n await expect(initCommand({ id: 'tenant_test', skipAuth: true })).rejects.toThrow(\n 'process.exit(1)',\n )\n\n expect(processExitMock.exitMock).toHaveBeenCalledWith(1)\n })\n })\n\n describe('tenant configuration', () => {\n it('should fetch tenant details and write config', async () => {\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.detectPayloadProject).mockResolvedValue({\n hasPayload: true,\n path: testDir,\n payloadVersion: '^3.54.0',\n })\n vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({\n id: 'tenant_abc',\n domain: 'abc.figmacms.com',\n parentId: 'team_123',\n parentType: 'team',\n status: 'active',\n })\n\n await initCommand({ id: 'tenant_abc', skipAuth: true })\n\n expect(controlPlane.getTenantDetails).toHaveBeenCalledWith('mock-access-token', 'tenant_abc')\n expect(config.writeFigmaConfig).toHaveBeenCalledWith({\n domain: 'abc.figmacms.com',\n tenantId: 'tenant_abc',\n })\n })\n })\n\n describe('Lambda setup verification', () => {\n it('should verify scaffoldProject creates Lambda-ready files', async () => {\n // This test verifies the integration between scaffoldProject and Lambda modifications\n // by checking that the mocked scaffoldProject was called correctly\n vi.mocked(config.hasFigmaConfig).mockResolvedValue(false)\n vi.mocked(project.isInProjectDirectory).mockResolvedValue(false) // Trigger new project flow\n vi.mocked(p.text).mockResolvedValue('test-project') // Project path prompt\n vi.mocked(controlPlane.getTenantDetails).mockResolvedValue({\n id: 'tenant_test',\n domain: 'test.figmacms.com',\n parentId: 'team_123',\n parentType: 'team',\n status: 'active',\n })\n\n await initCommand({ id: 'tenant_test', skipAuth: true })\n\n // Verify scaffoldProject was called (which internally applies Lambda modifications)\n expect(project.scaffoldProject).toHaveBeenCalled()\n expect(project.installDependencies).toHaveBeenCalled()\n })\n })\n})\n"],"names":["p","fs","path","afterEach","beforeEach","describe","expect","it","vi","controlPlane","getValidAccessToken","config","payloadConfigModifier","project","mockProcessExit","initCommand","mock","mockLog","error","fn","info","step","success","warn","cancel","confirm","intro","isCancel","value","Symbol","for","log","note","outro","select","spinner","start","stop","text","TokenStore","getAccessToken","hasValidTokens","loginCommand","mockResolvedValue","undefined","debug","warning","actual","importActual","hasFigmaConfig","readFigmaConfig","writeFigmaConfig","detectPayloadProject","hasRequiredDependencies","installDependencies","isInProjectDirectory","scaffoldProject","createTenant","getTenantDetails","listTenants","displayManualInstructions","ensurePayloadFigmaConfig","processExitMock","testDir","clearAllMocks","join","process","cwd","Date","now","Math","random","toString","substring","mkdir","recursive","mocked","changes","modified","restore","rm","force","hasPayload","payloadVersion","id","domain","parentId","parentType","status","skipAuth","not","toHaveBeenCalled","mockResolvedValueOnce","toHaveBeenCalledWith","objectContaining","message","tenantId","rejects","toThrow","exitMock"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for list-tokens command
|
|
3
|
+
*/
|
|
4
|
+
export interface ListTokensCommandOptions {
|
|
5
|
+
/** Enable debug mode */
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Handle the `payloadcms-figma list-tokens` command
|
|
10
|
+
*
|
|
11
|
+
* Displays stored token information including OAuth and project tokens.
|
|
12
|
+
*
|
|
13
|
+
* @param _options - Command options (unused)
|
|
14
|
+
*/
|
|
15
|
+
export declare function listTokensCommand(_options?: ListTokensCommandOptions): void;
|
|
16
|
+
//# sourceMappingURL=list-tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-tokens.d.ts","sourceRoot":"","sources":["../../src/commands/list-tokens.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,GAAE,wBAA6B,GAAG,IAAI,CA6C/E"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import { TokenStore } from '../auth/token-store.js';
|
|
4
|
+
import { formatTimestamp, maskToken, showProjectTokens } from '../utils/token-display.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handle the `payloadcms-figma list-tokens` command
|
|
7
|
+
*
|
|
8
|
+
* Displays stored token information including OAuth and project tokens.
|
|
9
|
+
*
|
|
10
|
+
* @param _options - Command options (unused)
|
|
11
|
+
*/ export function listTokensCommand(_options = {}) {
|
|
12
|
+
const tokenStore = new TokenStore();
|
|
13
|
+
const tokens = tokenStore.getTokens();
|
|
14
|
+
if (!tokens) {
|
|
15
|
+
p.log.warn(pc.yellow('No tokens found. Not authenticated.'));
|
|
16
|
+
p.note(`Run ${pc.cyan('payloadcms-figma login')} to authenticate`, 'Tip');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const isValid = tokenStore.hasValidTokens();
|
|
20
|
+
const status = isValid ? pc.green('✓ Valid') : pc.red('✗ Expired');
|
|
21
|
+
p.log.step(pc.bold('Stored Tokens'));
|
|
22
|
+
// Build OAuth token info display
|
|
23
|
+
const lines = [
|
|
24
|
+
`Status: ${status}`,
|
|
25
|
+
`Access Token: ${maskToken(tokens.accessToken)}`,
|
|
26
|
+
`Refresh Token: ${maskToken(tokens.refreshToken)}`,
|
|
27
|
+
`Expires: ${formatTimestamp(tokens.expiresAt)}`
|
|
28
|
+
];
|
|
29
|
+
if (tokens.userId) {
|
|
30
|
+
lines.push(`User ID: ${tokens.userId}`);
|
|
31
|
+
}
|
|
32
|
+
if (tokens.scopes && tokens.scopes.length > 0) {
|
|
33
|
+
lines.push(`Scopes: ${tokens.scopes.join(', ')}`);
|
|
34
|
+
}
|
|
35
|
+
lines.push(`Storage Path: ${pc.dim(tokenStore.getStoragePath())}`);
|
|
36
|
+
p.note(lines.join('\n'), 'OAuth Tokens');
|
|
37
|
+
if (!isValid) {
|
|
38
|
+
p.note(`Tokens have expired. Run ${pc.cyan('payloadcms-figma login')} to re-authenticate`, 'Action Required');
|
|
39
|
+
}
|
|
40
|
+
// Show project tokens if any exist
|
|
41
|
+
showProjectTokens(tokenStore);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=list-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/list-tokens.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { TokenStore } from '../auth/token-store.js'\nimport { formatTimestamp, maskToken, showProjectTokens } from '../utils/token-display.js'\n\n/**\n * Options for list-tokens command\n */\nexport interface ListTokensCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n}\n\n/**\n * Handle the `payloadcms-figma list-tokens` command\n *\n * Displays stored token information including OAuth and project tokens.\n *\n * @param _options - Command options (unused)\n */\nexport function listTokensCommand(_options: ListTokensCommandOptions = {}): void {\n const tokenStore = new TokenStore()\n\n const tokens = tokenStore.getTokens()\n\n if (!tokens) {\n p.log.warn(pc.yellow('No tokens found. Not authenticated.'))\n p.note(`Run ${pc.cyan('payloadcms-figma login')} to authenticate`, 'Tip')\n return\n }\n\n const isValid = tokenStore.hasValidTokens()\n const status = isValid ? pc.green('✓ Valid') : pc.red('✗ Expired')\n\n p.log.step(pc.bold('Stored Tokens'))\n\n // Build OAuth token info display\n const lines = [\n `Status: ${status}`,\n `Access Token: ${maskToken(tokens.accessToken)}`,\n `Refresh Token: ${maskToken(tokens.refreshToken)}`,\n `Expires: ${formatTimestamp(tokens.expiresAt)}`,\n ]\n\n if (tokens.userId) {\n lines.push(`User ID: ${tokens.userId}`)\n }\n\n if (tokens.scopes && tokens.scopes.length > 0) {\n lines.push(`Scopes: ${tokens.scopes.join(', ')}`)\n }\n\n lines.push(`Storage Path: ${pc.dim(tokenStore.getStoragePath())}`)\n\n p.note(lines.join('\\n'), 'OAuth Tokens')\n\n if (!isValid) {\n p.note(\n `Tokens have expired. Run ${pc.cyan('payloadcms-figma login')} to re-authenticate`,\n 'Action Required',\n )\n }\n\n // Show project tokens if any exist\n showProjectTokens(tokenStore)\n}\n"],"names":["p","pc","TokenStore","formatTimestamp","maskToken","showProjectTokens","listTokensCommand","_options","tokenStore","tokens","getTokens","log","warn","yellow","note","cyan","isValid","hasValidTokens","status","green","red","step","bold","lines","accessToken","refreshToken","expiresAt","userId","push","scopes","length","join","dim","getStoragePath"],"mappings":"AAAA,YAAYA,OAAO,iBAAgB;AACnC,OAAOC,QAAQ,aAAY;AAE3B,SAASC,UAAU,QAAQ,yBAAwB;AACnD,SAASC,eAAe,EAAEC,SAAS,EAAEC,iBAAiB,QAAQ,4BAA2B;AAUzF;;;;;;CAMC,GACD,OAAO,SAASC,kBAAkBC,WAAqC,CAAC,CAAC;IACvE,MAAMC,aAAa,IAAIN;IAEvB,MAAMO,SAASD,WAAWE,SAAS;IAEnC,IAAI,CAACD,QAAQ;QACXT,EAAEW,GAAG,CAACC,IAAI,CAACX,GAAGY,MAAM,CAAC;QACrBb,EAAEc,IAAI,CAAC,CAAC,IAAI,EAAEb,GAAGc,IAAI,CAAC,0BAA0B,gBAAgB,CAAC,EAAE;QACnE;IACF;IAEA,MAAMC,UAAUR,WAAWS,cAAc;IACzC,MAAMC,SAASF,UAAUf,GAAGkB,KAAK,CAAC,aAAalB,GAAGmB,GAAG,CAAC;IAEtDpB,EAAEW,GAAG,CAACU,IAAI,CAACpB,GAAGqB,IAAI,CAAC;IAEnB,iCAAiC;IACjC,MAAMC,QAAQ;QACZ,CAAC,gBAAgB,EAAEL,QAAQ;QAC3B,CAAC,gBAAgB,EAAEd,UAAUK,OAAOe,WAAW,GAAG;QAClD,CAAC,gBAAgB,EAAEpB,UAAUK,OAAOgB,YAAY,GAAG;QACnD,CAAC,gBAAgB,EAAEtB,gBAAgBM,OAAOiB,SAAS,GAAG;KACvD;IAED,IAAIjB,OAAOkB,MAAM,EAAE;QACjBJ,MAAMK,IAAI,CAAC,CAAC,gBAAgB,EAAEnB,OAAOkB,MAAM,EAAE;IAC/C;IAEA,IAAIlB,OAAOoB,MAAM,IAAIpB,OAAOoB,MAAM,CAACC,MAAM,GAAG,GAAG;QAC7CP,MAAMK,IAAI,CAAC,CAAC,gBAAgB,EAAEnB,OAAOoB,MAAM,CAACE,IAAI,CAAC,OAAO;IAC1D;IAEAR,MAAMK,IAAI,CAAC,CAAC,gBAAgB,EAAE3B,GAAG+B,GAAG,CAACxB,WAAWyB,cAAc,KAAK;IAEnEjC,EAAEc,IAAI,CAACS,MAAMQ,IAAI,CAAC,OAAO;IAEzB,IAAI,CAACf,SAAS;QACZhB,EAAEc,IAAI,CACJ,CAAC,yBAAyB,EAAEb,GAAGc,IAAI,CAAC,0BAA0B,mBAAmB,CAAC,EAClF;IAEJ;IAEA,mCAAmC;IACnCV,kBAAkBG;AACpB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for login command
|
|
3
|
+
*/
|
|
4
|
+
export interface LoginCommandOptions {
|
|
5
|
+
/** Enable debug mode */
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Handle the `payloadcms-figma login` command
|
|
10
|
+
*
|
|
11
|
+
* Authenticates the user with Figma OAuth2 and stores tokens locally.
|
|
12
|
+
* If valid tokens already exist, shows an error message.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Command options
|
|
15
|
+
*/
|
|
16
|
+
export declare function loginCommand(options?: LoginCommandOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BnF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import { executeOAuthFlow, getValidAccessToken, OAuthFlowError } from '../auth/oauth-flow.js';
|
|
4
|
+
import { TokenStore } from '../auth/token-store.js';
|
|
5
|
+
import { OAUTH_CONFIG } from '../config/oauth.js';
|
|
6
|
+
import * as log from '../utils/log.js';
|
|
7
|
+
/**
|
|
8
|
+
* Handle the `payloadcms-figma login` command
|
|
9
|
+
*
|
|
10
|
+
* Authenticates the user with Figma OAuth2 and stores tokens locally.
|
|
11
|
+
* If valid tokens already exist, shows an error message.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Command options
|
|
14
|
+
*/ export async function loginCommand(options = {}) {
|
|
15
|
+
const tokenStore = new TokenStore();
|
|
16
|
+
// Check for existing valid tokens
|
|
17
|
+
try {
|
|
18
|
+
const existingToken = await getValidAccessToken(tokenStore);
|
|
19
|
+
if (existingToken) {
|
|
20
|
+
const tokens = tokenStore.getTokens();
|
|
21
|
+
p.log.warn(pc.yellow('Already logged in'));
|
|
22
|
+
if (tokens?.userId) {
|
|
23
|
+
log.info(`User ID: ${tokens.userId}`);
|
|
24
|
+
}
|
|
25
|
+
log.info(`Token storage: ${pc.dim(tokenStore.getStoragePath())}`);
|
|
26
|
+
p.note(`To re-authenticate, first run ${pc.cyan('payloadcms-figma logout')}`, 'Tip');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
// Token refresh failed - continue with new auth flow
|
|
31
|
+
log.warning('Existing tokens are invalid. Starting new authentication...');
|
|
32
|
+
}
|
|
33
|
+
// Start OAuth flow
|
|
34
|
+
await handleAuthentication({
|
|
35
|
+
debug: options.debug,
|
|
36
|
+
tokenStore
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Handle authentication flow
|
|
41
|
+
*/ async function handleAuthentication({ debug, tokenStore }) {
|
|
42
|
+
try {
|
|
43
|
+
// Execute OAuth flow
|
|
44
|
+
const result = await executeOAuthFlow(tokenStore, {
|
|
45
|
+
clientId: OAUTH_CONFIG.clientId,
|
|
46
|
+
redirectUri: OAUTH_CONFIG.redirectUri,
|
|
47
|
+
scopes: OAUTH_CONFIG.scopes
|
|
48
|
+
});
|
|
49
|
+
p.log.success(pc.green('✓ You are now authenticated with Figma'));
|
|
50
|
+
if (result.userId) {
|
|
51
|
+
log.debug(`User ID: ${result.userId}`);
|
|
52
|
+
}
|
|
53
|
+
log.debug(`Token storage: ${pc.dim(tokenStore.getStoragePath())}`);
|
|
54
|
+
// Show next steps
|
|
55
|
+
p.note(` ${pc.cyan('@payloadcms/figma init')} Create a new CMS instance`, 'Next Steps');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (error instanceof OAuthFlowError) {
|
|
58
|
+
log.error(error.message);
|
|
59
|
+
if (error.cause) {
|
|
60
|
+
log.debug(`Cause: ${error.cause.message}`);
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
log.error(error instanceof Error ? error.message : 'Unknown error');
|
|
64
|
+
}
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/login.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { executeOAuthFlow, getValidAccessToken, OAuthFlowError } from '../auth/oauth-flow.js'\nimport { TokenStore } from '../auth/token-store.js'\nimport { OAUTH_CONFIG } from '../config/oauth.js'\nimport * as log from '../utils/log.js'\n\n/**\n * Options for login command\n */\nexport interface LoginCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n}\n\n/**\n * Handle the `payloadcms-figma login` command\n *\n * Authenticates the user with Figma OAuth2 and stores tokens locally.\n * If valid tokens already exist, shows an error message.\n *\n * @param options - Command options\n */\nexport async function loginCommand(options: LoginCommandOptions = {}): Promise<void> {\n const tokenStore = new TokenStore()\n\n // Check for existing valid tokens\n try {\n const existingToken = await getValidAccessToken(tokenStore)\n if (existingToken) {\n const tokens = tokenStore.getTokens()\n p.log.warn(pc.yellow('Already logged in'))\n if (tokens?.userId) {\n log.info(`User ID: ${tokens.userId}`)\n }\n log.info(`Token storage: ${pc.dim(tokenStore.getStoragePath())}`)\n p.note(`To re-authenticate, first run ${pc.cyan('payloadcms-figma logout')}`, 'Tip')\n return\n }\n } catch {\n // Token refresh failed - continue with new auth flow\n log.warning('Existing tokens are invalid. Starting new authentication...')\n }\n\n // Start OAuth flow\n await handleAuthentication({\n debug: options.debug,\n tokenStore,\n })\n}\n\n/**\n * Handle authentication flow\n */\nasync function handleAuthentication({\n debug,\n tokenStore,\n}: {\n debug?: boolean\n tokenStore: TokenStore\n}): Promise<void> {\n try {\n // Execute OAuth flow\n const result = await executeOAuthFlow(tokenStore, {\n clientId: OAUTH_CONFIG.clientId,\n redirectUri: OAUTH_CONFIG.redirectUri,\n scopes: OAUTH_CONFIG.scopes,\n })\n\n p.log.success(pc.green('✓ You are now authenticated with Figma'))\n\n if (result.userId) {\n log.debug(`User ID: ${result.userId}`)\n }\n\n log.debug(`Token storage: ${pc.dim(tokenStore.getStoragePath())}`)\n\n // Show next steps\n p.note(` ${pc.cyan('@payloadcms/figma init')} Create a new CMS instance`, 'Next Steps')\n } catch (error) {\n if (error instanceof OAuthFlowError) {\n log.error(error.message)\n\n if (error.cause) {\n log.debug(`Cause: ${error.cause.message}`)\n }\n } else {\n log.error(error instanceof Error ? error.message : 'Unknown error')\n }\n\n process.exit(1)\n }\n}\n"],"names":["p","pc","executeOAuthFlow","getValidAccessToken","OAuthFlowError","TokenStore","OAUTH_CONFIG","log","loginCommand","options","tokenStore","existingToken","tokens","getTokens","warn","yellow","userId","info","dim","getStoragePath","note","cyan","warning","handleAuthentication","debug","result","clientId","redirectUri","scopes","success","green","error","message","cause","Error","process","exit"],"mappings":"AAAA,YAAYA,OAAO,iBAAgB;AACnC,OAAOC,QAAQ,aAAY;AAE3B,SAASC,gBAAgB,EAAEC,mBAAmB,EAAEC,cAAc,QAAQ,wBAAuB;AAC7F,SAASC,UAAU,QAAQ,yBAAwB;AACnD,SAASC,YAAY,QAAQ,qBAAoB;AACjD,YAAYC,SAAS,kBAAiB;AAUtC;;;;;;;CAOC,GACD,OAAO,eAAeC,aAAaC,UAA+B,CAAC,CAAC;IAClE,MAAMC,aAAa,IAAIL;IAEvB,kCAAkC;IAClC,IAAI;QACF,MAAMM,gBAAgB,MAAMR,oBAAoBO;QAChD,IAAIC,eAAe;YACjB,MAAMC,SAASF,WAAWG,SAAS;YACnCb,EAAEO,GAAG,CAACO,IAAI,CAACb,GAAGc,MAAM,CAAC;YACrB,IAAIH,QAAQI,QAAQ;gBAClBT,IAAIU,IAAI,CAAC,CAAC,SAAS,EAAEL,OAAOI,MAAM,EAAE;YACtC;YACAT,IAAIU,IAAI,CAAC,CAAC,eAAe,EAAEhB,GAAGiB,GAAG,CAACR,WAAWS,cAAc,KAAK;YAChEnB,EAAEoB,IAAI,CAAC,CAAC,8BAA8B,EAAEnB,GAAGoB,IAAI,CAAC,4BAA4B,EAAE;YAC9E;QACF;IACF,EAAE,OAAM;QACN,qDAAqD;QACrDd,IAAIe,OAAO,CAAC;IACd;IAEA,mBAAmB;IACnB,MAAMC,qBAAqB;QACzBC,OAAOf,QAAQe,KAAK;QACpBd;IACF;AACF;AAEA;;CAEC,GACD,eAAea,qBAAqB,EAClCC,KAAK,EACLd,UAAU,EAIX;IACC,IAAI;QACF,qBAAqB;QACrB,MAAMe,SAAS,MAAMvB,iBAAiBQ,YAAY;YAChDgB,UAAUpB,aAAaoB,QAAQ;YAC/BC,aAAarB,aAAaqB,WAAW;YACrCC,QAAQtB,aAAasB,MAAM;QAC7B;QAEA5B,EAAEO,GAAG,CAACsB,OAAO,CAAC5B,GAAG6B,KAAK,CAAC;QAEvB,IAAIL,OAAOT,MAAM,EAAE;YACjBT,IAAIiB,KAAK,CAAC,CAAC,SAAS,EAAEC,OAAOT,MAAM,EAAE;QACvC;QAEAT,IAAIiB,KAAK,CAAC,CAAC,eAAe,EAAEvB,GAAGiB,GAAG,CAACR,WAAWS,cAAc,KAAK;QAEjE,kBAAkB;QAClBnB,EAAEoB,IAAI,CAAC,CAAC,EAAE,EAAEnB,GAAGoB,IAAI,CAAC,0BAA0B,2BAA2B,CAAC,EAAE;IAC9E,EAAE,OAAOU,OAAO;QACd,IAAIA,iBAAiB3B,gBAAgB;YACnCG,IAAIwB,KAAK,CAACA,MAAMC,OAAO;YAEvB,IAAID,MAAME,KAAK,EAAE;gBACf1B,IAAIiB,KAAK,CAAC,CAAC,OAAO,EAAEO,MAAME,KAAK,CAACD,OAAO,EAAE;YAC3C;QACF,OAAO;YACLzB,IAAIwB,KAAK,CAACA,iBAAiBG,QAAQH,MAAMC,OAAO,GAAG;QACrD;QAEAG,QAAQC,IAAI,CAAC;IACf;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for logout command
|
|
3
|
+
*/
|
|
4
|
+
export interface LogoutCommandOptions {
|
|
5
|
+
/** Enable debug mode */
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Handle the `payloadcms-figma logout` command
|
|
10
|
+
*
|
|
11
|
+
* Clears all stored tokens (OAuth and project tokens) after confirmation.
|
|
12
|
+
*
|
|
13
|
+
* @param _options - Command options (unused)
|
|
14
|
+
*/
|
|
15
|
+
export declare function logoutCommand(_options?: LogoutCommandOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,QAAQ,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCtF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import { TokenStore } from '../auth/token-store.js';
|
|
4
|
+
import * as log from '../utils/log.js';
|
|
5
|
+
/**
|
|
6
|
+
* Handle the `payloadcms-figma logout` command
|
|
7
|
+
*
|
|
8
|
+
* Clears all stored tokens (OAuth and project tokens) after confirmation.
|
|
9
|
+
*
|
|
10
|
+
* @param _options - Command options (unused)
|
|
11
|
+
*/ export async function logoutCommand(_options = {}) {
|
|
12
|
+
const tokenStore = new TokenStore();
|
|
13
|
+
const hasTokens = tokenStore.getTokens() !== null;
|
|
14
|
+
if (!hasTokens) {
|
|
15
|
+
p.log.warn(pc.yellow('No tokens found. Already logged out.'));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// Confirm logout
|
|
19
|
+
const confirmed = await p.confirm({
|
|
20
|
+
initialValue: false,
|
|
21
|
+
message: 'This will clear all OAuth and project tokens. Continue?'
|
|
22
|
+
});
|
|
23
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
24
|
+
p.log.info('Logout cancelled');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const s = p.spinner();
|
|
28
|
+
s.start('Clearing tokens...');
|
|
29
|
+
try {
|
|
30
|
+
// Clear OAuth tokens
|
|
31
|
+
tokenStore.clearTokens();
|
|
32
|
+
// Clear all project tokens
|
|
33
|
+
tokenStore.clearAllProjectTokens();
|
|
34
|
+
s.stop(pc.green('✓ Logged out successfully'));
|
|
35
|
+
p.log.step('All OAuth and project tokens have been cleared');
|
|
36
|
+
} catch (error) {
|
|
37
|
+
s.stop(pc.red('✗ Failed to clear tokens'));
|
|
38
|
+
log.error(error instanceof Error ? error.message : 'Unknown error');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/logout.ts"],"sourcesContent":["import * as p from '@clack/prompts'\nimport pc from 'picocolors'\n\nimport { TokenStore } from '../auth/token-store.js'\nimport * as log from '../utils/log.js'\n\n/**\n * Options for logout command\n */\nexport interface LogoutCommandOptions {\n /** Enable debug mode */\n debug?: boolean\n}\n\n/**\n * Handle the `payloadcms-figma logout` command\n *\n * Clears all stored tokens (OAuth and project tokens) after confirmation.\n *\n * @param _options - Command options (unused)\n */\nexport async function logoutCommand(_options: LogoutCommandOptions = {}): Promise<void> {\n const tokenStore = new TokenStore()\n\n const hasTokens = tokenStore.getTokens() !== null\n\n if (!hasTokens) {\n p.log.warn(pc.yellow('No tokens found. Already logged out.'))\n return\n }\n\n // Confirm logout\n const confirmed = await p.confirm({\n initialValue: false,\n message: 'This will clear all OAuth and project tokens. Continue?',\n })\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.log.info('Logout cancelled')\n return\n }\n\n const s = p.spinner()\n s.start('Clearing tokens...')\n\n try {\n // Clear OAuth tokens\n tokenStore.clearTokens()\n // Clear all project tokens\n tokenStore.clearAllProjectTokens()\n s.stop(pc.green('✓ Logged out successfully'))\n p.log.step('All OAuth and project tokens have been cleared')\n } catch (error) {\n s.stop(pc.red('✗ Failed to clear tokens'))\n log.error(error instanceof Error ? error.message : 'Unknown error')\n process.exit(1)\n }\n}\n"],"names":["p","pc","TokenStore","log","logoutCommand","_options","tokenStore","hasTokens","getTokens","warn","yellow","confirmed","confirm","initialValue","message","isCancel","info","s","spinner","start","clearTokens","clearAllProjectTokens","stop","green","step","error","red","Error","process","exit"],"mappings":"AAAA,YAAYA,OAAO,iBAAgB;AACnC,OAAOC,QAAQ,aAAY;AAE3B,SAASC,UAAU,QAAQ,yBAAwB;AACnD,YAAYC,SAAS,kBAAiB;AAUtC;;;;;;CAMC,GACD,OAAO,eAAeC,cAAcC,WAAiC,CAAC,CAAC;IACrE,MAAMC,aAAa,IAAIJ;IAEvB,MAAMK,YAAYD,WAAWE,SAAS,OAAO;IAE7C,IAAI,CAACD,WAAW;QACdP,EAAEG,GAAG,CAACM,IAAI,CAACR,GAAGS,MAAM,CAAC;QACrB;IACF;IAEA,iBAAiB;IACjB,MAAMC,YAAY,MAAMX,EAAEY,OAAO,CAAC;QAChCC,cAAc;QACdC,SAAS;IACX;IAEA,IAAId,EAAEe,QAAQ,CAACJ,cAAc,CAACA,WAAW;QACvCX,EAAEG,GAAG,CAACa,IAAI,CAAC;QACX;IACF;IAEA,MAAMC,IAAIjB,EAAEkB,OAAO;IACnBD,EAAEE,KAAK,CAAC;IAER,IAAI;QACF,qBAAqB;QACrBb,WAAWc,WAAW;QACtB,2BAA2B;QAC3Bd,WAAWe,qBAAqB;QAChCJ,EAAEK,IAAI,CAACrB,GAAGsB,KAAK,CAAC;QAChBvB,EAAEG,GAAG,CAACqB,IAAI,CAAC;IACb,EAAE,OAAOC,OAAO;QACdR,EAAEK,IAAI,CAACrB,GAAGyB,GAAG,CAAC;QACdvB,IAAIsB,KAAK,CAACA,iBAAiBE,QAAQF,MAAMX,OAAO,GAAG;QACnDc,QAAQC,IAAI,CAAC;IACf;AACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { OAuthConfig } from '../auth/types.js';
|
|
2
|
+
export declare const URLS: Record<'prod' | 'staging', Pick<OAuthConfig, 'authorizationUrl' | 'refreshUrl' | 'tokenUrl'>>;
|
|
3
|
+
/**
|
|
4
|
+
* Figma OAuth2 configuration for public CLI client
|
|
5
|
+
*
|
|
6
|
+
* This is a PUBLIC OAuth client using PKCE (Proof Key for Code Exchange).
|
|
7
|
+
* No client secret is used because CLIs cannot securely store secrets.
|
|
8
|
+
* PKCE provides security through the code_verifier/code_challenge mechanism.
|
|
9
|
+
*
|
|
10
|
+
* For production use, register a public OAuth app with Figma.
|
|
11
|
+
* To register an OAuth app, visit: https://www.figma.com/developers/api#oauth2
|
|
12
|
+
*/
|
|
13
|
+
export declare const OAUTH_CONFIG: OAuthConfig;
|
|
14
|
+
/**
|
|
15
|
+
* Buffer time (in seconds) before token expiration to consider token as expired
|
|
16
|
+
* This helps avoid using tokens that are about to expire
|
|
17
|
+
*/
|
|
18
|
+
export declare const TOKEN_EXPIRY_BUFFER_SECONDS = 300;
|
|
19
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/config/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAInD,eAAO,MAAM,IAAI,EAAE,MAAM,CACvB,MAAM,GAAG,SAAS,EAClB,IAAI,CAAC,WAAW,EAAE,kBAAkB,GAAG,YAAY,GAAG,UAAU,CAAC,CAYlE,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,EAAE,WAe1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,MAAM,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { FIGMA_CLIENT_IDS } from '../constants.js';
|
|
2
|
+
export const URLS = {
|
|
3
|
+
prod: {
|
|
4
|
+
authorizationUrl: 'https://www.figma.com/oauth',
|
|
5
|
+
refreshUrl: 'https://api.figma.com/v1/oauth/refresh',
|
|
6
|
+
tokenUrl: 'https://api.figma.com/v1/oauth/token'
|
|
7
|
+
},
|
|
8
|
+
staging: {
|
|
9
|
+
authorizationUrl: 'https://staging.figma.com/oauth',
|
|
10
|
+
refreshUrl: 'https://api.staging.figma.com/v1/oauth/refresh',
|
|
11
|
+
tokenUrl: 'https://api.staging.figma.com/v1/oauth/token'
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Figma OAuth2 configuration for public CLI client
|
|
16
|
+
*
|
|
17
|
+
* This is a PUBLIC OAuth client using PKCE (Proof Key for Code Exchange).
|
|
18
|
+
* No client secret is used because CLIs cannot securely store secrets.
|
|
19
|
+
* PKCE provides security through the code_verifier/code_challenge mechanism.
|
|
20
|
+
*
|
|
21
|
+
* For production use, register a public OAuth app with Figma.
|
|
22
|
+
* To register an OAuth app, visit: https://www.figma.com/developers/api#oauth2
|
|
23
|
+
*/ export const OAUTH_CONFIG = {
|
|
24
|
+
// OAuth client ID (public client)
|
|
25
|
+
// Uses staging client ID by default since we use staging endpoints
|
|
26
|
+
clientId: process.env.FIGMA_CLIENT_ID || FIGMA_CLIENT_IDS.staging,
|
|
27
|
+
// No client secret - this is a public OAuth client using PKCE
|
|
28
|
+
// Public clients cannot securely store secrets in CLI environments
|
|
29
|
+
redirectUri: process.env.FIGMA_REDIRECT_URI || 'http://localhost:3000/callback',
|
|
30
|
+
// Only current_user:read scope is needed for basic user info
|
|
31
|
+
scopes: [
|
|
32
|
+
'current_user:read'
|
|
33
|
+
],
|
|
34
|
+
// TODO: Dynamically choose between prod and staging based on environment
|
|
35
|
+
...URLS.staging
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Buffer time (in seconds) before token expiration to consider token as expired
|
|
39
|
+
* This helps avoid using tokens that are about to expire
|
|
40
|
+
*/ export const TOKEN_EXPIRY_BUFFER_SECONDS = 300 // 5 minutes
|
|
41
|
+
;
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=oauth.js.map
|