@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,123 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
4
|
+
import { generateSecret, manageEnvFiles } from './env-management.js';
|
|
5
|
+
describe('env-management', ()=>{
|
|
6
|
+
describe('generateSecret', ()=>{
|
|
7
|
+
it('should generate a 24-character hex string', ()=>{
|
|
8
|
+
const secret = generateSecret();
|
|
9
|
+
expect(secret).toHaveLength(24);
|
|
10
|
+
expect(secret).toMatch(/^[0-9a-f]{24}$/);
|
|
11
|
+
});
|
|
12
|
+
it('should generate unique secrets', ()=>{
|
|
13
|
+
const secret1 = generateSecret();
|
|
14
|
+
const secret2 = generateSecret();
|
|
15
|
+
expect(secret1).not.toBe(secret2);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe('manageEnvFiles', ()=>{
|
|
19
|
+
let testDir;
|
|
20
|
+
beforeEach(async ()=>{
|
|
21
|
+
testDir = path.join(process.cwd(), '.test-env-management', `test-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`);
|
|
22
|
+
await fs.mkdir(testDir, {
|
|
23
|
+
recursive: true
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
afterEach(async ()=>{
|
|
27
|
+
try {
|
|
28
|
+
await fs.rm(testDir, {
|
|
29
|
+
force: true,
|
|
30
|
+
recursive: true
|
|
31
|
+
});
|
|
32
|
+
} catch {
|
|
33
|
+
// Ignore cleanup errors
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
it('should create .env with PAYLOAD_SECRET when no files exist', async ()=>{
|
|
37
|
+
const secret = await manageEnvFiles(testDir);
|
|
38
|
+
expect(secret).toHaveLength(24);
|
|
39
|
+
expect(secret).toMatch(/^[0-9a-f]{24}$/);
|
|
40
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
41
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`);
|
|
42
|
+
});
|
|
43
|
+
it('should create .env from .env.example with PAYLOAD_SECRET', async ()=>{
|
|
44
|
+
const envExampleContent = `# Example environment variables
|
|
45
|
+
DATABASE_URI=mongodb://localhost/mydb
|
|
46
|
+
NEXT_PUBLIC_API_URL=http://localhost:3000
|
|
47
|
+
PAYLOAD_SECRET=
|
|
48
|
+
`;
|
|
49
|
+
await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent);
|
|
50
|
+
const secret = await manageEnvFiles(testDir);
|
|
51
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
52
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`);
|
|
53
|
+
expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb');
|
|
54
|
+
expect(envContent).toContain('NEXT_PUBLIC_API_URL=http://localhost:3000');
|
|
55
|
+
});
|
|
56
|
+
it('should not overwrite existing .env with PAYLOAD_SECRET', async ()=>{
|
|
57
|
+
const existingSecret = 'existing-secret-value';
|
|
58
|
+
const existingEnv = `DATABASE_URI=mongodb://localhost/mydb
|
|
59
|
+
PAYLOAD_SECRET=${existingSecret}
|
|
60
|
+
NEXT_PUBLIC_API_URL=http://localhost:3000
|
|
61
|
+
`;
|
|
62
|
+
await fs.writeFile(path.join(testDir, '.env'), existingEnv);
|
|
63
|
+
await manageEnvFiles(testDir);
|
|
64
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
65
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${existingSecret}`);
|
|
66
|
+
expect(envContent).not.toMatch(/PAYLOAD_SECRET=[0-9a-f]{24}/);
|
|
67
|
+
});
|
|
68
|
+
it('should add PAYLOAD_SECRET to existing .env that lacks it', async ()=>{
|
|
69
|
+
const existingEnv = `DATABASE_URI=mongodb://localhost/mydb
|
|
70
|
+
NEXT_PUBLIC_API_URL=http://localhost:3000
|
|
71
|
+
`;
|
|
72
|
+
await fs.writeFile(path.join(testDir, '.env'), existingEnv);
|
|
73
|
+
const secret = await manageEnvFiles(testDir);
|
|
74
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
75
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`);
|
|
76
|
+
expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb');
|
|
77
|
+
});
|
|
78
|
+
it('should handle PAYLOAD_SECRET_KEY as alias', async ()=>{
|
|
79
|
+
const envExampleContent = `PAYLOAD_SECRET_KEY=
|
|
80
|
+
DATABASE_URI=mongodb://localhost/mydb
|
|
81
|
+
`;
|
|
82
|
+
await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent);
|
|
83
|
+
const secret = await manageEnvFiles(testDir);
|
|
84
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
85
|
+
// Should normalize to PAYLOAD_SECRET
|
|
86
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`);
|
|
87
|
+
expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb');
|
|
88
|
+
});
|
|
89
|
+
it('should remove duplicate PAYLOAD_SECRET entries', async ()=>{
|
|
90
|
+
const envExampleContent = `PAYLOAD_SECRET=
|
|
91
|
+
DATABASE_URI=mongodb://localhost/mydb
|
|
92
|
+
PAYLOAD_SECRET=duplicate
|
|
93
|
+
`;
|
|
94
|
+
await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent);
|
|
95
|
+
const secret = await manageEnvFiles(testDir);
|
|
96
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
97
|
+
const secretMatches = envContent.match(/PAYLOAD_SECRET=/g);
|
|
98
|
+
expect(secretMatches).toHaveLength(1);
|
|
99
|
+
expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`);
|
|
100
|
+
});
|
|
101
|
+
it('should preserve comments and empty lines', async ()=>{
|
|
102
|
+
const envExampleContent = `# Database configuration
|
|
103
|
+
DATABASE_URI=mongodb://localhost/mydb
|
|
104
|
+
|
|
105
|
+
# API Configuration
|
|
106
|
+
NEXT_PUBLIC_API_URL=http://localhost:3000
|
|
107
|
+
|
|
108
|
+
# Secret key
|
|
109
|
+
PAYLOAD_SECRET=
|
|
110
|
+
`;
|
|
111
|
+
await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent);
|
|
112
|
+
await manageEnvFiles(testDir);
|
|
113
|
+
const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8');
|
|
114
|
+
expect(envContent).toContain('# Database configuration');
|
|
115
|
+
expect(envContent).toContain('# API Configuration');
|
|
116
|
+
expect(envContent).toContain('# Secret key');
|
|
117
|
+
// Check for empty lines (might be normalized)
|
|
118
|
+
expect(envContent.split('\n').some((line)=>line.trim() === '')).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=env-management.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/env-management.spec.ts"],"sourcesContent":["import fs from 'fs/promises'\nimport path from 'path'\nimport { afterEach, beforeEach, describe, expect, it } from 'vitest'\n\nimport { generateSecret, manageEnvFiles } from './env-management.js'\n\ndescribe('env-management', () => {\n describe('generateSecret', () => {\n it('should generate a 24-character hex string', () => {\n const secret = generateSecret()\n expect(secret).toHaveLength(24)\n expect(secret).toMatch(/^[0-9a-f]{24}$/)\n })\n\n it('should generate unique secrets', () => {\n const secret1 = generateSecret()\n const secret2 = generateSecret()\n expect(secret1).not.toBe(secret2)\n })\n })\n\n describe('manageEnvFiles', () => {\n let testDir: string\n\n beforeEach(async () => {\n testDir = path.join(\n process.cwd(),\n '.test-env-management',\n `test-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,\n )\n await fs.mkdir(testDir, { recursive: true })\n })\n\n afterEach(async () => {\n try {\n await fs.rm(testDir, { force: true, recursive: true })\n } catch {\n // Ignore cleanup errors\n }\n })\n\n it('should create .env with PAYLOAD_SECRET when no files exist', async () => {\n const secret = await manageEnvFiles(testDir)\n\n expect(secret).toHaveLength(24)\n expect(secret).toMatch(/^[0-9a-f]{24}$/)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`)\n })\n\n it('should create .env from .env.example with PAYLOAD_SECRET', async () => {\n const envExampleContent = `# Example environment variables\nDATABASE_URI=mongodb://localhost/mydb\nNEXT_PUBLIC_API_URL=http://localhost:3000\nPAYLOAD_SECRET=\n`\n await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent)\n\n const secret = await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`)\n expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb')\n expect(envContent).toContain('NEXT_PUBLIC_API_URL=http://localhost:3000')\n })\n\n it('should not overwrite existing .env with PAYLOAD_SECRET', async () => {\n const existingSecret = 'existing-secret-value'\n const existingEnv = `DATABASE_URI=mongodb://localhost/mydb\nPAYLOAD_SECRET=${existingSecret}\nNEXT_PUBLIC_API_URL=http://localhost:3000\n`\n await fs.writeFile(path.join(testDir, '.env'), existingEnv)\n\n await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n expect(envContent).toContain(`PAYLOAD_SECRET=${existingSecret}`)\n expect(envContent).not.toMatch(/PAYLOAD_SECRET=[0-9a-f]{24}/)\n })\n\n it('should add PAYLOAD_SECRET to existing .env that lacks it', async () => {\n const existingEnv = `DATABASE_URI=mongodb://localhost/mydb\nNEXT_PUBLIC_API_URL=http://localhost:3000\n`\n await fs.writeFile(path.join(testDir, '.env'), existingEnv)\n\n const secret = await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`)\n expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb')\n })\n\n it('should handle PAYLOAD_SECRET_KEY as alias', async () => {\n const envExampleContent = `PAYLOAD_SECRET_KEY=\nDATABASE_URI=mongodb://localhost/mydb\n`\n await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent)\n\n const secret = await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n // Should normalize to PAYLOAD_SECRET\n expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`)\n expect(envContent).toContain('DATABASE_URI=mongodb://localhost/mydb')\n })\n\n it('should remove duplicate PAYLOAD_SECRET entries', async () => {\n const envExampleContent = `PAYLOAD_SECRET=\nDATABASE_URI=mongodb://localhost/mydb\nPAYLOAD_SECRET=duplicate\n`\n await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent)\n\n const secret = await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n const secretMatches = envContent.match(/PAYLOAD_SECRET=/g)\n expect(secretMatches).toHaveLength(1)\n expect(envContent).toContain(`PAYLOAD_SECRET=${secret}`)\n })\n\n it('should preserve comments and empty lines', async () => {\n const envExampleContent = `# Database configuration\nDATABASE_URI=mongodb://localhost/mydb\n\n# API Configuration\nNEXT_PUBLIC_API_URL=http://localhost:3000\n\n# Secret key\nPAYLOAD_SECRET=\n`\n await fs.writeFile(path.join(testDir, '.env.example'), envExampleContent)\n\n await manageEnvFiles(testDir)\n\n const envContent = await fs.readFile(path.join(testDir, '.env'), 'utf-8')\n expect(envContent).toContain('# Database configuration')\n expect(envContent).toContain('# API Configuration')\n expect(envContent).toContain('# Secret key')\n // Check for empty lines (might be normalized)\n expect(envContent.split('\\n').some((line) => line.trim() === '')).toBe(true)\n })\n })\n})\n"],"names":["fs","path","afterEach","beforeEach","describe","expect","it","generateSecret","manageEnvFiles","secret","toHaveLength","toMatch","secret1","secret2","not","toBe","testDir","join","process","cwd","Date","now","Math","random","toString","substring","mkdir","recursive","rm","force","envContent","readFile","toContain","envExampleContent","writeFile","existingSecret","existingEnv","secretMatches","match","split","some","line","trim"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared formatting utilities for CLI output
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Format a timestamp (in milliseconds) to a localized string
|
|
6
|
+
* @param ms - Timestamp in milliseconds since epoch
|
|
7
|
+
* @returns Localized date/time string
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatTime(ms: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Get a human-readable string describing time until expiry
|
|
12
|
+
* @param expiresAt - Expiry timestamp in milliseconds since epoch
|
|
13
|
+
* @returns Human-readable time until/since expiry (e.g., "in 2 hours", "expired 5 minutes ago")
|
|
14
|
+
*/
|
|
15
|
+
export declare function getTimeUntilExpiry(expiresAt: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* Mask a token for safe display
|
|
18
|
+
* Shows first 4 and last 4 characters, masks the middle
|
|
19
|
+
* @param token - Token string to mask
|
|
20
|
+
* @returns Masked token string (e.g., "eyJh********************************mFbc")
|
|
21
|
+
*/
|
|
22
|
+
export declare function maskToken(token: string): string;
|
|
23
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA0B5D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK/C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared formatting utilities for CLI output
|
|
3
|
+
*/ /**
|
|
4
|
+
* Format a timestamp (in milliseconds) to a localized string
|
|
5
|
+
* @param ms - Timestamp in milliseconds since epoch
|
|
6
|
+
* @returns Localized date/time string
|
|
7
|
+
*/ export function formatTime(ms) {
|
|
8
|
+
const date = new Date(ms);
|
|
9
|
+
return date.toLocaleString();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Get a human-readable string describing time until expiry
|
|
13
|
+
* @param expiresAt - Expiry timestamp in milliseconds since epoch
|
|
14
|
+
* @returns Human-readable time until/since expiry (e.g., "in 2 hours", "expired 5 minutes ago")
|
|
15
|
+
*/ export function getTimeUntilExpiry(expiresAt) {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const diff = expiresAt - now;
|
|
18
|
+
if (diff < 0) {
|
|
19
|
+
const minutes = Math.floor(Math.abs(diff) / 60000);
|
|
20
|
+
const hours = Math.floor(minutes / 60);
|
|
21
|
+
if (hours > 0) {
|
|
22
|
+
return `expired ${hours} hour${hours > 1 ? 's' : ''} ago`;
|
|
23
|
+
}
|
|
24
|
+
return `expired ${minutes} minute${minutes > 1 ? 's' : ''} ago`;
|
|
25
|
+
}
|
|
26
|
+
const minutes = Math.floor(diff / 60000);
|
|
27
|
+
const hours = Math.floor(minutes / 60);
|
|
28
|
+
if (hours > 0) {
|
|
29
|
+
const remainingMinutes = minutes % 60;
|
|
30
|
+
if (remainingMinutes > 0) {
|
|
31
|
+
return `in ${hours} hour${hours > 1 ? 's' : ''} ${remainingMinutes} minute${remainingMinutes > 1 ? 's' : ''}`;
|
|
32
|
+
}
|
|
33
|
+
return `in ${hours} hour${hours > 1 ? 's' : ''}`;
|
|
34
|
+
}
|
|
35
|
+
return `in ${minutes} minute${minutes > 1 ? 's' : ''}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Mask a token for safe display
|
|
39
|
+
* Shows first 4 and last 4 characters, masks the middle
|
|
40
|
+
* @param token - Token string to mask
|
|
41
|
+
* @returns Masked token string (e.g., "eyJh********************************mFbc")
|
|
42
|
+
*/ export function maskToken(token) {
|
|
43
|
+
if (token.length <= 8) {
|
|
44
|
+
return '***';
|
|
45
|
+
}
|
|
46
|
+
return `${token.slice(0, 4)}${'*'.repeat(Math.min(token.length - 8, 32))}${token.slice(-4)}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/format.ts"],"sourcesContent":["/**\n * Shared formatting utilities for CLI output\n */\n\n/**\n * Format a timestamp (in milliseconds) to a localized string\n * @param ms - Timestamp in milliseconds since epoch\n * @returns Localized date/time string\n */\nexport function formatTime(ms: number): string {\n const date = new Date(ms)\n return date.toLocaleString()\n}\n\n/**\n * Get a human-readable string describing time until expiry\n * @param expiresAt - Expiry timestamp in milliseconds since epoch\n * @returns Human-readable time until/since expiry (e.g., \"in 2 hours\", \"expired 5 minutes ago\")\n */\nexport function getTimeUntilExpiry(expiresAt: number): string {\n const now = Date.now()\n const diff = expiresAt - now\n\n if (diff < 0) {\n const minutes = Math.floor(Math.abs(diff) / 60000)\n const hours = Math.floor(minutes / 60)\n\n if (hours > 0) {\n return `expired ${hours} hour${hours > 1 ? 's' : ''} ago`\n }\n return `expired ${minutes} minute${minutes > 1 ? 's' : ''} ago`\n }\n\n const minutes = Math.floor(diff / 60000)\n const hours = Math.floor(minutes / 60)\n\n if (hours > 0) {\n const remainingMinutes = minutes % 60\n if (remainingMinutes > 0) {\n return `in ${hours} hour${hours > 1 ? 's' : ''} ${remainingMinutes} minute${remainingMinutes > 1 ? 's' : ''}`\n }\n return `in ${hours} hour${hours > 1 ? 's' : ''}`\n }\n\n return `in ${minutes} minute${minutes > 1 ? 's' : ''}`\n}\n\n/**\n * Mask a token for safe display\n * Shows first 4 and last 4 characters, masks the middle\n * @param token - Token string to mask\n * @returns Masked token string (e.g., \"eyJh********************************mFbc\")\n */\nexport function maskToken(token: string): string {\n if (token.length <= 8) {\n return '***'\n }\n return `${token.slice(0, 4)}${'*'.repeat(Math.min(token.length - 8, 32))}${token.slice(-4)}`\n}\n"],"names":["formatTime","ms","date","Date","toLocaleString","getTimeUntilExpiry","expiresAt","now","diff","minutes","Math","floor","abs","hours","remainingMinutes","maskToken","token","length","slice","repeat","min"],"mappings":"AAAA;;CAEC,GAED;;;;CAIC,GACD,OAAO,SAASA,WAAWC,EAAU;IACnC,MAAMC,OAAO,IAAIC,KAAKF;IACtB,OAAOC,KAAKE,cAAc;AAC5B;AAEA;;;;CAIC,GACD,OAAO,SAASC,mBAAmBC,SAAiB;IAClD,MAAMC,MAAMJ,KAAKI,GAAG;IACpB,MAAMC,OAAOF,YAAYC;IAEzB,IAAIC,OAAO,GAAG;QACZ,MAAMC,UAAUC,KAAKC,KAAK,CAACD,KAAKE,GAAG,CAACJ,QAAQ;QAC5C,MAAMK,QAAQH,KAAKC,KAAK,CAACF,UAAU;QAEnC,IAAII,QAAQ,GAAG;YACb,OAAO,CAAC,QAAQ,EAAEA,MAAM,KAAK,EAAEA,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC;QAC3D;QACA,OAAO,CAAC,QAAQ,EAAEJ,QAAQ,OAAO,EAAEA,UAAU,IAAI,MAAM,GAAG,IAAI,CAAC;IACjE;IAEA,MAAMA,UAAUC,KAAKC,KAAK,CAACH,OAAO;IAClC,MAAMK,QAAQH,KAAKC,KAAK,CAACF,UAAU;IAEnC,IAAII,QAAQ,GAAG;QACb,MAAMC,mBAAmBL,UAAU;QACnC,IAAIK,mBAAmB,GAAG;YACxB,OAAO,CAAC,GAAG,EAAED,MAAM,KAAK,EAAEA,QAAQ,IAAI,MAAM,GAAG,CAAC,EAAEC,iBAAiB,OAAO,EAAEA,mBAAmB,IAAI,MAAM,IAAI;QAC/G;QACA,OAAO,CAAC,GAAG,EAAED,MAAM,KAAK,EAAEA,QAAQ,IAAI,MAAM,IAAI;IAClD;IAEA,OAAO,CAAC,GAAG,EAAEJ,QAAQ,OAAO,EAAEA,UAAU,IAAI,MAAM,IAAI;AACxD;AAEA;;;;;CAKC,GACD,OAAO,SAASM,UAAUC,KAAa;IACrC,IAAIA,MAAMC,MAAM,IAAI,GAAG;QACrB,OAAO;IACT;IACA,OAAO,GAAGD,MAAME,KAAK,CAAC,GAAG,KAAK,IAAIC,MAAM,CAACT,KAAKU,GAAG,CAACJ,MAAMC,MAAM,GAAG,GAAG,OAAOD,MAAME,KAAK,CAAC,CAAC,IAAI;AAC9F"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PackageManager } from './package-manager.js';
|
|
2
|
+
export type FormatResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
warning?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Format file with Prettier
|
|
8
|
+
* Returns warning if formatting fails but does not throw
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatFile(filePath: string, packageManager: PackageManager): Promise<FormatResult>;
|
|
11
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,YAAY,CAAC,CAmCvB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Format file with Prettier
|
|
5
|
+
* Returns warning if formatting fails but does not throw
|
|
6
|
+
*/ export async function formatFile(filePath, packageManager) {
|
|
7
|
+
return new Promise((resolve)=>{
|
|
8
|
+
try {
|
|
9
|
+
const args = [
|
|
10
|
+
'exec',
|
|
11
|
+
'prettier',
|
|
12
|
+
'--write',
|
|
13
|
+
filePath
|
|
14
|
+
];
|
|
15
|
+
const child = spawn(packageManager, args, {
|
|
16
|
+
cwd: path.dirname(filePath),
|
|
17
|
+
shell: true,
|
|
18
|
+
stdio: 'pipe'
|
|
19
|
+
});
|
|
20
|
+
child.on('close', (code)=>{
|
|
21
|
+
if (code === 0) {
|
|
22
|
+
resolve({
|
|
23
|
+
success: true
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
resolve({
|
|
27
|
+
success: false,
|
|
28
|
+
warning: 'Could not format file with Prettier'
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
child.on('error', ()=>{
|
|
33
|
+
resolve({
|
|
34
|
+
success: false,
|
|
35
|
+
warning: 'Could not format file with Prettier'
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
} catch {
|
|
39
|
+
resolve({
|
|
40
|
+
success: false,
|
|
41
|
+
warning: 'Could not format file with Prettier'
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/formatter.ts"],"sourcesContent":["import { spawn } from 'child_process'\nimport path from 'path'\n\nimport type { PackageManager } from './package-manager.js'\n\nexport type FormatResult = {\n success: boolean\n warning?: string\n}\n\n/**\n * Format file with Prettier\n * Returns warning if formatting fails but does not throw\n */\nexport async function formatFile(\n filePath: string,\n packageManager: PackageManager,\n): Promise<FormatResult> {\n return new Promise((resolve) => {\n try {\n const args = ['exec', 'prettier', '--write', filePath]\n\n const child = spawn(packageManager, args, {\n cwd: path.dirname(filePath),\n shell: true,\n stdio: 'pipe',\n })\n\n child.on('close', (code) => {\n if (code === 0) {\n resolve({ success: true })\n } else {\n resolve({\n success: false,\n warning: 'Could not format file with Prettier',\n })\n }\n })\n\n child.on('error', () => {\n resolve({\n success: false,\n warning: 'Could not format file with Prettier',\n })\n })\n } catch {\n resolve({\n success: false,\n warning: 'Could not format file with Prettier',\n })\n }\n })\n}\n"],"names":["spawn","path","formatFile","filePath","packageManager","Promise","resolve","args","child","cwd","dirname","shell","stdio","on","code","success","warning"],"mappings":"AAAA,SAASA,KAAK,QAAQ,gBAAe;AACrC,OAAOC,UAAU,OAAM;AASvB;;;CAGC,GACD,OAAO,eAAeC,WACpBC,QAAgB,EAChBC,cAA8B;IAE9B,OAAO,IAAIC,QAAQ,CAACC;QAClB,IAAI;YACF,MAAMC,OAAO;gBAAC;gBAAQ;gBAAY;gBAAWJ;aAAS;YAEtD,MAAMK,QAAQR,MAAMI,gBAAgBG,MAAM;gBACxCE,KAAKR,KAAKS,OAAO,CAACP;gBAClBQ,OAAO;gBACPC,OAAO;YACT;YAEAJ,MAAMK,EAAE,CAAC,SAAS,CAACC;gBACjB,IAAIA,SAAS,GAAG;oBACdR,QAAQ;wBAAES,SAAS;oBAAK;gBAC1B,OAAO;oBACLT,QAAQ;wBACNS,SAAS;wBACTC,SAAS;oBACX;gBACF;YACF;YAEAR,MAAMK,EAAE,CAAC,SAAS;gBAChBP,QAAQ;oBACNS,SAAS;oBACTC,SAAS;gBACX;YACF;QACF,EAAE,OAAM;YACNV,QAAQ;gBACNS,SAAS;gBACTC,SAAS;YACX;QACF;IACF;AACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a directory is already a git repository
|
|
3
|
+
*
|
|
4
|
+
* @param projectPath - Path to check
|
|
5
|
+
* @returns True if directory is a git repo
|
|
6
|
+
*/
|
|
7
|
+
export declare function isGitRepo(projectPath: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Initialize a git repository and create an initial commit
|
|
10
|
+
*
|
|
11
|
+
* @param projectPath - Path to initialize git in
|
|
12
|
+
* @returns True if successful, false otherwise
|
|
13
|
+
*/
|
|
14
|
+
export declare function tryInitRepoAndCommit(projectPath: string): boolean;
|
|
15
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAUtD;AAkBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CA4DjE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Check if a directory is already a git repository
|
|
4
|
+
*
|
|
5
|
+
* @param projectPath - Path to check
|
|
6
|
+
* @returns True if directory is a git repo
|
|
7
|
+
*/ export function isGitRepo(projectPath) {
|
|
8
|
+
try {
|
|
9
|
+
execSync('git rev-parse --is-inside-work-tree', {
|
|
10
|
+
cwd: projectPath,
|
|
11
|
+
stdio: 'ignore'
|
|
12
|
+
});
|
|
13
|
+
return true;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if git has a default branch configured
|
|
20
|
+
*
|
|
21
|
+
* @returns True if default branch is configured
|
|
22
|
+
*/ function ensureHasDefaultBranch() {
|
|
23
|
+
try {
|
|
24
|
+
execSync('git config init.defaultBranch', {
|
|
25
|
+
stdio: 'ignore'
|
|
26
|
+
});
|
|
27
|
+
return true;
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Initialize a git repository and create an initial commit
|
|
34
|
+
*
|
|
35
|
+
* @param projectPath - Path to initialize git in
|
|
36
|
+
* @returns True if successful, false otherwise
|
|
37
|
+
*/ export function tryInitRepoAndCommit(projectPath) {
|
|
38
|
+
try {
|
|
39
|
+
// Check if git is available
|
|
40
|
+
execSync('git -v', {
|
|
41
|
+
stdio: 'ignore'
|
|
42
|
+
});
|
|
43
|
+
} catch {
|
|
44
|
+
// Git not available
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Skip if already in a git repo
|
|
48
|
+
if (isGitRepo(projectPath)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
// Initialize git repository
|
|
53
|
+
execSync('git init', {
|
|
54
|
+
cwd: projectPath,
|
|
55
|
+
stdio: 'ignore'
|
|
56
|
+
});
|
|
57
|
+
// Configure git user in CI environments (required for commits)
|
|
58
|
+
if (process.env.CI) {
|
|
59
|
+
execSync('git config user.email "ci@payloadcms.com"', {
|
|
60
|
+
cwd: projectPath,
|
|
61
|
+
stdio: 'ignore'
|
|
62
|
+
});
|
|
63
|
+
execSync('git config user.name "Payload CI"', {
|
|
64
|
+
cwd: projectPath,
|
|
65
|
+
stdio: 'ignore'
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// Create main branch if no default branch configured
|
|
69
|
+
if (!ensureHasDefaultBranch()) {
|
|
70
|
+
execSync('git checkout -b main', {
|
|
71
|
+
cwd: projectPath,
|
|
72
|
+
stdio: 'ignore'
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// Stage all files
|
|
76
|
+
execSync('git add -A', {
|
|
77
|
+
cwd: projectPath,
|
|
78
|
+
stdio: 'ignore'
|
|
79
|
+
});
|
|
80
|
+
// Create initial commit
|
|
81
|
+
execSync('git commit -m "feat: initial commit"', {
|
|
82
|
+
cwd: projectPath,
|
|
83
|
+
stdio: 'ignore'
|
|
84
|
+
});
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
// Git operations failed
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/git.ts"],"sourcesContent":["import { execSync } from 'child_process'\n\n/**\n * Check if a directory is already a git repository\n *\n * @param projectPath - Path to check\n * @returns True if directory is a git repo\n */\nexport function isGitRepo(projectPath: string): boolean {\n try {\n execSync('git rev-parse --is-inside-work-tree', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Check if git has a default branch configured\n *\n * @returns True if default branch is configured\n */\nfunction ensureHasDefaultBranch(): boolean {\n try {\n execSync('git config init.defaultBranch', {\n stdio: 'ignore',\n })\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Initialize a git repository and create an initial commit\n *\n * @param projectPath - Path to initialize git in\n * @returns True if successful, false otherwise\n */\nexport function tryInitRepoAndCommit(projectPath: string): boolean {\n try {\n // Check if git is available\n execSync('git -v', {\n stdio: 'ignore',\n })\n } catch {\n // Git not available\n return false\n }\n\n // Skip if already in a git repo\n if (isGitRepo(projectPath)) {\n return false\n }\n\n try {\n // Initialize git repository\n execSync('git init', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n\n // Configure git user in CI environments (required for commits)\n if (process.env.CI) {\n execSync('git config user.email \"ci@payloadcms.com\"', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n execSync('git config user.name \"Payload CI\"', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n }\n\n // Create main branch if no default branch configured\n if (!ensureHasDefaultBranch()) {\n execSync('git checkout -b main', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n }\n\n // Stage all files\n execSync('git add -A', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n\n // Create initial commit\n execSync('git commit -m \"feat: initial commit\"', {\n cwd: projectPath,\n stdio: 'ignore',\n })\n\n return true\n } catch {\n // Git operations failed\n return false\n }\n}\n"],"names":["execSync","isGitRepo","projectPath","cwd","stdio","ensureHasDefaultBranch","tryInitRepoAndCommit","process","env","CI"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,gBAAe;AAExC;;;;;CAKC,GACD,OAAO,SAASC,UAAUC,WAAmB;IAC3C,IAAI;QACFF,SAAS,uCAAuC;YAC9CG,KAAKD;YACLE,OAAO;QACT;QACA,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;CAIC,GACD,SAASC;IACP,IAAI;QACFL,SAAS,iCAAiC;YACxCI,OAAO;QACT;QACA,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;CAKC,GACD,OAAO,SAASE,qBAAqBJ,WAAmB;IACtD,IAAI;QACF,4BAA4B;QAC5BF,SAAS,UAAU;YACjBI,OAAO;QACT;IACF,EAAE,OAAM;QACN,oBAAoB;QACpB,OAAO;IACT;IAEA,gCAAgC;IAChC,IAAIH,UAAUC,cAAc;QAC1B,OAAO;IACT;IAEA,IAAI;QACF,4BAA4B;QAC5BF,SAAS,YAAY;YACnBG,KAAKD;YACLE,OAAO;QACT;QAEA,+DAA+D;QAC/D,IAAIG,QAAQC,GAAG,CAACC,EAAE,EAAE;YAClBT,SAAS,6CAA6C;gBACpDG,KAAKD;gBACLE,OAAO;YACT;YACAJ,SAAS,qCAAqC;gBAC5CG,KAAKD;gBACLE,OAAO;YACT;QACF;QAEA,qDAAqD;QACrD,IAAI,CAACC,0BAA0B;YAC7BL,SAAS,wBAAwB;gBAC/BG,KAAKD;gBACLE,OAAO;YACT;QACF;QAEA,kBAAkB;QAClBJ,SAAS,cAAc;YACrBG,KAAKD;YACLE,OAAO;QACT;QAEA,wBAAwB;QACxBJ,SAAS,wCAAwC;YAC/CG,KAAKD;YACLE,OAAO;QACT;QAEA,OAAO;IACT,EAAE,OAAM;QACN,wBAAwB;QACxB,OAAO;IACT;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.spec.d.ts","sourceRoot":"","sources":["../../src/utils/git.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { isGitRepo, tryInitRepoAndCommit } from './git.js';
|
|
7
|
+
describe('git utilities', ()=>{
|
|
8
|
+
let testDir;
|
|
9
|
+
beforeEach(async ()=>{
|
|
10
|
+
// Create test directory in OS temp directory to avoid parent git repo
|
|
11
|
+
testDir = path.join(os.tmpdir(), `figma-cli-git-test-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`);
|
|
12
|
+
await fs.mkdir(testDir, {
|
|
13
|
+
recursive: true
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
afterEach(async ()=>{
|
|
17
|
+
try {
|
|
18
|
+
await fs.rm(testDir, {
|
|
19
|
+
force: true,
|
|
20
|
+
recursive: true
|
|
21
|
+
});
|
|
22
|
+
} catch {
|
|
23
|
+
// Ignore cleanup errors
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
describe('isGitRepo', ()=>{
|
|
27
|
+
it('should return false for non-git directory', ()=>{
|
|
28
|
+
expect(isGitRepo(testDir)).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
it('should return true for git repository', ()=>{
|
|
31
|
+
execSync('git init', {
|
|
32
|
+
cwd: testDir,
|
|
33
|
+
stdio: 'ignore'
|
|
34
|
+
});
|
|
35
|
+
expect(isGitRepo(testDir)).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('tryInitRepoAndCommit', ()=>{
|
|
39
|
+
it('should initialize git repo and create initial commit', async ()=>{
|
|
40
|
+
// Create a file to commit
|
|
41
|
+
await fs.writeFile(path.join(testDir, 'README.md'), '# Test Project');
|
|
42
|
+
const result = tryInitRepoAndCommit(testDir);
|
|
43
|
+
expect(result).toBe(true);
|
|
44
|
+
expect(isGitRepo(testDir)).toBe(true);
|
|
45
|
+
// Verify commit exists
|
|
46
|
+
const log = execSync('git log --oneline', {
|
|
47
|
+
cwd: testDir,
|
|
48
|
+
encoding: 'utf-8'
|
|
49
|
+
});
|
|
50
|
+
expect(log).toContain('feat: initial commit');
|
|
51
|
+
});
|
|
52
|
+
it('should return false if already a git repo', ()=>{
|
|
53
|
+
execSync('git init', {
|
|
54
|
+
cwd: testDir,
|
|
55
|
+
stdio: 'ignore'
|
|
56
|
+
});
|
|
57
|
+
const result = tryInitRepoAndCommit(testDir);
|
|
58
|
+
expect(result).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
it('should create main branch when no default configured', async ()=>{
|
|
61
|
+
await fs.writeFile(path.join(testDir, 'README.md'), '# Test Project');
|
|
62
|
+
tryInitRepoAndCommit(testDir);
|
|
63
|
+
const branch = execSync('git branch --show-current', {
|
|
64
|
+
cwd: testDir,
|
|
65
|
+
encoding: 'utf-8'
|
|
66
|
+
});
|
|
67
|
+
expect(branch.trim()).toBe('main');
|
|
68
|
+
});
|
|
69
|
+
it('should stage all files for initial commit', async ()=>{
|
|
70
|
+
await fs.writeFile(path.join(testDir, 'file1.txt'), 'content 1');
|
|
71
|
+
await fs.writeFile(path.join(testDir, 'file2.txt'), 'content 2');
|
|
72
|
+
await fs.mkdir(path.join(testDir, 'subdir'));
|
|
73
|
+
await fs.writeFile(path.join(testDir, 'subdir', 'file3.txt'), 'content 3');
|
|
74
|
+
tryInitRepoAndCommit(testDir);
|
|
75
|
+
// Check that all files are committed
|
|
76
|
+
const files = execSync('git ls-files', {
|
|
77
|
+
cwd: testDir,
|
|
78
|
+
encoding: 'utf-8'
|
|
79
|
+
});
|
|
80
|
+
expect(files).toContain('file1.txt');
|
|
81
|
+
expect(files).toContain('file2.txt');
|
|
82
|
+
expect(files).toContain('subdir/file3.txt');
|
|
83
|
+
});
|
|
84
|
+
it('should handle empty directory gracefully', ()=>{
|
|
85
|
+
// Empty directory should still create repo but commit might fail
|
|
86
|
+
const result = tryInitRepoAndCommit(testDir);
|
|
87
|
+
// Either succeeds with empty commit or fails gracefully
|
|
88
|
+
// Both are acceptable behaviors
|
|
89
|
+
if (result) {
|
|
90
|
+
expect(isGitRepo(testDir)).toBe(true);
|
|
91
|
+
} else {
|
|
92
|
+
// Failed gracefully, no error thrown
|
|
93
|
+
expect(true).toBe(true);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=git.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/git.spec.ts"],"sourcesContent":["import { execSync } from 'child_process'\nimport fs from 'fs/promises'\nimport os from 'os'\nimport path from 'path'\nimport { afterEach, beforeEach, describe, expect, it } from 'vitest'\n\nimport { isGitRepo, tryInitRepoAndCommit } from './git.js'\n\ndescribe('git utilities', () => {\n let testDir: string\n\n beforeEach(async () => {\n // Create test directory in OS temp directory to avoid parent git repo\n testDir = path.join(\n os.tmpdir(),\n `figma-cli-git-test-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,\n )\n await fs.mkdir(testDir, { recursive: true })\n })\n\n afterEach(async () => {\n try {\n await fs.rm(testDir, { force: true, recursive: true })\n } catch {\n // Ignore cleanup errors\n }\n })\n\n describe('isGitRepo', () => {\n it('should return false for non-git directory', () => {\n expect(isGitRepo(testDir)).toBe(false)\n })\n\n it('should return true for git repository', () => {\n execSync('git init', { cwd: testDir, stdio: 'ignore' })\n expect(isGitRepo(testDir)).toBe(true)\n })\n })\n\n describe('tryInitRepoAndCommit', () => {\n it('should initialize git repo and create initial commit', async () => {\n // Create a file to commit\n await fs.writeFile(path.join(testDir, 'README.md'), '# Test Project')\n\n const result = tryInitRepoAndCommit(testDir)\n\n expect(result).toBe(true)\n expect(isGitRepo(testDir)).toBe(true)\n\n // Verify commit exists\n const log = execSync('git log --oneline', { cwd: testDir, encoding: 'utf-8' })\n expect(log).toContain('feat: initial commit')\n })\n\n it('should return false if already a git repo', () => {\n execSync('git init', { cwd: testDir, stdio: 'ignore' })\n\n const result = tryInitRepoAndCommit(testDir)\n\n expect(result).toBe(false)\n })\n\n it('should create main branch when no default configured', async () => {\n await fs.writeFile(path.join(testDir, 'README.md'), '# Test Project')\n\n tryInitRepoAndCommit(testDir)\n\n const branch = execSync('git branch --show-current', { cwd: testDir, encoding: 'utf-8' })\n expect(branch.trim()).toBe('main')\n })\n\n it('should stage all files for initial commit', async () => {\n await fs.writeFile(path.join(testDir, 'file1.txt'), 'content 1')\n await fs.writeFile(path.join(testDir, 'file2.txt'), 'content 2')\n await fs.mkdir(path.join(testDir, 'subdir'))\n await fs.writeFile(path.join(testDir, 'subdir', 'file3.txt'), 'content 3')\n\n tryInitRepoAndCommit(testDir)\n\n // Check that all files are committed\n const files = execSync('git ls-files', { cwd: testDir, encoding: 'utf-8' })\n expect(files).toContain('file1.txt')\n expect(files).toContain('file2.txt')\n expect(files).toContain('subdir/file3.txt')\n })\n\n it('should handle empty directory gracefully', () => {\n // Empty directory should still create repo but commit might fail\n const result = tryInitRepoAndCommit(testDir)\n\n // Either succeeds with empty commit or fails gracefully\n // Both are acceptable behaviors\n if (result) {\n expect(isGitRepo(testDir)).toBe(true)\n } else {\n // Failed gracefully, no error thrown\n expect(true).toBe(true)\n }\n })\n })\n})\n"],"names":["execSync","fs","os","path","afterEach","beforeEach","describe","expect","it","isGitRepo","tryInitRepoAndCommit","testDir","join","tmpdir","Date","now","Math","random","toString","substring","mkdir","recursive","rm","force","toBe","cwd","stdio","writeFile","result","log","encoding","toContain","branch","trim","files"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-debug.d.ts","sourceRoot":"","sources":["../../src/utils/is-debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,OAAO,QAAO,OAE1B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/is-debug.ts"],"sourcesContent":["/**\n * Check if debug mode is enabled via DEBUG environment variable\n * @returns true if DEBUG environment variable is set to 'true'\n */\nexport const isDebug = (): boolean => {\n return process.env.DEBUG === 'true'\n}\n"],"names":["isDebug","process","env","DEBUG"],"mappings":"AAAA;;;CAGC,GACD,OAAO,MAAMA,UAAU;IACrB,OAAOC,QAAQC,GAAG,CAACC,KAAK,KAAK;AAC/B,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lambda-config.d.ts","sourceRoot":"","sources":["../../src/utils/lambda-config.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCjF"}
|