@payloadcms/figma 0.0.1-alpha.62 → 0.0.1-alpha.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/crypto-utils.d.ts +11 -0
- package/dist/auth/crypto-utils.js +51 -0
- package/dist/auth/oauth-flow.js +4 -3
- package/dist/auth/project-token.d.ts +32 -16
- package/dist/auth/project-token.js +165 -64
- package/dist/auth/token-store-migration.d.ts +58 -0
- package/dist/auth/token-store-migration.js +156 -0
- package/dist/auth/token-store.d.ts +51 -128
- package/dist/auth/token-store.js +326 -187
- package/dist/auth/types.d.ts +12 -1
- package/dist/cli.js +15 -0
- package/dist/commands/bootstrap.d.ts +18 -0
- package/dist/commands/bootstrap.js +90 -0
- package/dist/commands/debug.js +16 -12
- package/dist/commands/dump-tokens.d.ts +12 -0
- package/dist/commands/dump-tokens.js +69 -0
- package/dist/commands/init.js +39 -5
- package/dist/commands/list-tokens.js +2 -2
- package/dist/commands/login.js +1 -1
- package/dist/commands/logout.js +23 -4
- package/dist/db-content-api/index.js +27 -73
- package/dist/db-content-api/utilities/auth.js +4 -1
- package/dist/oauth/defaults.d.ts +3 -1
- package/dist/oauth/defaults.js +6 -5
- package/dist/oauth/endpoints/getLoginEndpoint.js +1 -1
- package/dist/oauth/index.js +1 -0
- package/dist/oauth/types.d.ts +10 -0
- package/dist/plugin/auth-preflight.d.ts +8 -0
- package/dist/plugin/auth-preflight.js +20 -0
- package/dist/plugin/bootstrap-preflight.d.ts +23 -0
- package/dist/plugin/bootstrap-preflight.js +45 -0
- package/dist/plugin/build-config.js +135 -58
- package/dist/plugin/dev-cookie-names.d.ts +14 -0
- package/dist/plugin/dev-cookie-names.js +19 -0
- package/dist/storage-content-api/client.js +4 -1
- package/dist/utils/messages.js +7 -0
- package/dist/utils/payload-config-modifier.js +96 -107
- package/dist/utils/payload-package-check.d.ts +21 -1
- package/dist/utils/payload-package-check.js +66 -26
- package/dist/utils/token-display.d.ts +5 -1
- package/dist/utils/token-display.js +47 -26
- package/package.json +2 -1
|
@@ -5,7 +5,7 @@ import * as log from './log.js';
|
|
|
5
5
|
import { getAddCommand, getRunCommand } from './package-manager.js';
|
|
6
6
|
import { addFigmaProperty, applyModifications, detectRequiredChanges } from './payload-config-ast.js';
|
|
7
7
|
import { findPayloadConfig } from './payload-config-finder.js';
|
|
8
|
-
import { checkPackageInstalled, getPayloadVersion,
|
|
8
|
+
import { checkPackageInstalled, getPayloadVersion, installPackages, uninstallPackages } from './payload-package-check.js';
|
|
9
9
|
import { runTypeScriptCheck } from './typescript-validator.js';
|
|
10
10
|
import { getOwnVersion } from './version-check.js';
|
|
11
11
|
/**
|
|
@@ -14,10 +14,9 @@ import { getOwnVersion } from './version-check.js';
|
|
|
14
14
|
*/ export async function ensurePayloadFigmaConfig(projectPath, packageManager, figmaConfig) {
|
|
15
15
|
const changes = [];
|
|
16
16
|
const warnings = [];
|
|
17
|
-
let
|
|
17
|
+
let astModified = false;
|
|
18
18
|
try {
|
|
19
19
|
log.debug(`Starting payload config modification for: ${projectPath}`);
|
|
20
|
-
// 1. Find config file
|
|
21
20
|
const configPath = await findPayloadConfig(projectPath);
|
|
22
21
|
if (!configPath) {
|
|
23
22
|
log.debug(`Config file not found in: ${projectPath}`);
|
|
@@ -29,32 +28,10 @@ import { getOwnVersion } from './version-check.js';
|
|
|
29
28
|
};
|
|
30
29
|
}
|
|
31
30
|
log.debug(`Found config file: ${configPath}`);
|
|
32
|
-
//
|
|
31
|
+
// Pin @payloadcms/* packages to the project's payload version when possible.
|
|
33
32
|
const payloadVersion = await getPayloadVersion(projectPath);
|
|
34
33
|
log.debug(`Detected payload version: ${payloadVersion || 'unknown'}`);
|
|
35
|
-
//
|
|
36
|
-
const isInstalled = await checkPackageInstalled(projectPath, '@payloadcms/figma');
|
|
37
|
-
if (!isInstalled) {
|
|
38
|
-
log.debug('@payloadcms/figma not installed, attempting installation...');
|
|
39
|
-
try {
|
|
40
|
-
const figmaVersion = await getOwnVersion();
|
|
41
|
-
await installPackage(projectPath, '@payloadcms/figma', packageManager, figmaVersion);
|
|
42
|
-
changes.push('Installed @payloadcms/figma');
|
|
43
|
-
modified = true;
|
|
44
|
-
log.debug('@payloadcms/figma installed successfully');
|
|
45
|
-
} catch (error) {
|
|
46
|
-
log.debug(`Failed to install @payloadcms/figma: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
47
|
-
return {
|
|
48
|
-
changes: [],
|
|
49
|
-
error: 'Failed to install @payloadcms/figma',
|
|
50
|
-
modified: false,
|
|
51
|
-
success: false
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
log.debug('@payloadcms/figma already installed');
|
|
56
|
-
}
|
|
57
|
-
// 3. Parse config with ts-morph
|
|
34
|
+
// Parse first so a malformed config fails fast before we touch node_modules.
|
|
58
35
|
log.debug('Parsing config file with ts-morph...');
|
|
59
36
|
const project = new Project({
|
|
60
37
|
manipulationSettings: {
|
|
@@ -64,17 +41,15 @@ import { getOwnVersion } from './version-check.js';
|
|
|
64
41
|
skipAddingFilesFromTsConfig: true
|
|
65
42
|
});
|
|
66
43
|
const sourceFile = project.addSourceFileAtPath(configPath);
|
|
67
|
-
// 4. Detect required changes
|
|
68
44
|
log.debug('Detecting required changes...');
|
|
69
45
|
const detection = detectRequiredChanges(sourceFile);
|
|
70
46
|
log.debug(`Detection results: needsImportChange=${detection.needsImportChange}, hasAlias=${detection.hasAlias}, hasBuildConfig=${detection.hasBuildConfig}`);
|
|
71
|
-
// Handle failure modes
|
|
72
47
|
if (detection.hasAlias) {
|
|
73
48
|
log.debug('Config uses import alias (e.g., buildConfig as X)');
|
|
74
49
|
return {
|
|
75
50
|
changes,
|
|
76
51
|
error: 'Config uses import alias - manual modification required',
|
|
77
|
-
modified,
|
|
52
|
+
modified: false,
|
|
78
53
|
success: false
|
|
79
54
|
};
|
|
80
55
|
}
|
|
@@ -83,25 +58,95 @@ import { getOwnVersion } from './version-check.js';
|
|
|
83
58
|
return {
|
|
84
59
|
changes,
|
|
85
60
|
error: 'Config structure not recognized (no buildConfig call found)',
|
|
86
|
-
modified,
|
|
61
|
+
modified: false,
|
|
87
62
|
success: false
|
|
88
63
|
};
|
|
89
64
|
}
|
|
90
|
-
//
|
|
65
|
+
// Compute the full install/uninstall diff up front so each can run as a
|
|
66
|
+
// single package-manager call. npm leaves node_modules transient between
|
|
67
|
+
// back-to-back calls, which causes generate:importmap to silently miss
|
|
68
|
+
// subpath components — batching avoids that intermediate state.
|
|
69
|
+
const packagesToInstall = [];
|
|
70
|
+
const packagesToUninstall = [];
|
|
71
|
+
const figmaInstalled = await checkPackageInstalled(projectPath, '@payloadcms/figma');
|
|
72
|
+
if (!figmaInstalled) {
|
|
73
|
+
const figmaVersion = await getOwnVersion();
|
|
74
|
+
packagesToInstall.push({
|
|
75
|
+
name: '@payloadcms/figma',
|
|
76
|
+
changeMessage: 'Installed @payloadcms/figma',
|
|
77
|
+
version: figmaVersion
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const editorIsDefault = !detection.editorProperty || detection.editorProperty.isDefault;
|
|
81
|
+
if (editorIsDefault) {
|
|
82
|
+
const hasLexical = await checkPackageInstalled(projectPath, '@payloadcms/richtext-lexical');
|
|
83
|
+
if (!hasLexical) {
|
|
84
|
+
packagesToInstall.push({
|
|
85
|
+
name: '@payloadcms/richtext-lexical',
|
|
86
|
+
changeMessage: 'Installed @payloadcms/richtext-lexical (default editor)',
|
|
87
|
+
version: payloadVersion
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
log.debug(`Custom editor detected (${detection.editorProperty?.importSource}) - skipping lexical installation`);
|
|
92
|
+
}
|
|
93
|
+
const hasCloudStorage = await checkPackageInstalled(projectPath, '@payloadcms/plugin-cloud-storage');
|
|
94
|
+
if (!hasCloudStorage) {
|
|
95
|
+
packagesToInstall.push({
|
|
96
|
+
name: '@payloadcms/plugin-cloud-storage',
|
|
97
|
+
changeMessage: 'Installed @payloadcms/plugin-cloud-storage',
|
|
98
|
+
version: payloadVersion
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (detection.dbProperty) {
|
|
102
|
+
packagesToUninstall.push(detection.dbProperty.importSource);
|
|
103
|
+
}
|
|
104
|
+
if (detection.sharpProperty) {
|
|
105
|
+
packagesToUninstall.push('sharp');
|
|
106
|
+
}
|
|
107
|
+
if (packagesToInstall.length > 0) {
|
|
108
|
+
log.debug(`Installing ${packagesToInstall.length} packages in a single operation: ${packagesToInstall.map((p)=>p.name).join(', ')}`);
|
|
109
|
+
try {
|
|
110
|
+
await installPackages(projectPath, packagesToInstall.map(({ name, version })=>({
|
|
111
|
+
name,
|
|
112
|
+
version
|
|
113
|
+
})), packageManager);
|
|
114
|
+
for (const { changeMessage } of packagesToInstall){
|
|
115
|
+
changes.push(changeMessage);
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
119
|
+
log.debug(`Batched install failed: ${errorMessage}`);
|
|
120
|
+
const figmaInBatch = packagesToInstall.some((p)=>p.name === '@payloadcms/figma');
|
|
121
|
+
if (figmaInBatch) {
|
|
122
|
+
// Without @payloadcms/figma the rewritten config would import a
|
|
123
|
+
// missing package, so abort before touching the file.
|
|
124
|
+
return {
|
|
125
|
+
changes: [],
|
|
126
|
+
error: 'Failed to install @payloadcms/figma',
|
|
127
|
+
modified: false,
|
|
128
|
+
success: false
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Lexical and cloud-storage are non-fatal — payload still loads without
|
|
132
|
+
// them, so warn (with package names) and continue.
|
|
133
|
+
const failedNames = packagesToInstall.map((p)=>p.name).join(', ');
|
|
134
|
+
warnings.push(`Could not install dependencies (${failedNames}) — install them manually. Details: ${errorMessage}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
91
137
|
log.debug('Applying modifications...');
|
|
92
138
|
const modResult = applyModifications(sourceFile, detection);
|
|
93
139
|
if (modResult.modified) {
|
|
94
140
|
changes.push(...modResult.changes);
|
|
95
|
-
|
|
141
|
+
astModified = true;
|
|
96
142
|
log.debug(`Applied ${modResult.changes.length} modifications`);
|
|
97
143
|
}
|
|
98
|
-
// 6. Add figma property if config provided and doesn't exist
|
|
99
144
|
if (figmaConfig && !detection.figmaObjectExists) {
|
|
100
145
|
log.debug('Adding figma property to buildConfig...');
|
|
101
146
|
const figmaResult = addFigmaProperty(sourceFile, figmaConfig);
|
|
102
147
|
if (figmaResult.modified) {
|
|
103
148
|
changes.push(...figmaResult.changes);
|
|
104
|
-
|
|
149
|
+
astModified = true;
|
|
105
150
|
log.debug(`Added figma property`);
|
|
106
151
|
} else {
|
|
107
152
|
log.debug('Figma property not added (may already exist)');
|
|
@@ -109,95 +154,39 @@ import { getOwnVersion } from './version-check.js';
|
|
|
109
154
|
} else if (detection.figmaObjectExists) {
|
|
110
155
|
log.debug('Figma property already exists, skipping');
|
|
111
156
|
}
|
|
112
|
-
|
|
113
|
-
if (modified) {
|
|
157
|
+
if (astModified) {
|
|
114
158
|
sourceFile.formatText({
|
|
115
159
|
indentSize: 2,
|
|
116
160
|
tabSize: 2
|
|
117
161
|
});
|
|
118
162
|
await sourceFile.save();
|
|
119
163
|
log.debug('Config file saved');
|
|
120
|
-
// 7. Handle package management
|
|
121
|
-
const packagesToUninstall = [];
|
|
122
|
-
// Uninstall db adapter (buildFigmaConfig provides its own)
|
|
123
|
-
if (detection.dbProperty) {
|
|
124
|
-
packagesToUninstall.push(detection.dbProperty.importSource);
|
|
125
|
-
}
|
|
126
|
-
// Uninstall sharp (Figma infrastructure handles image processing)
|
|
127
|
-
if (detection.sharpProperty) {
|
|
128
|
-
packagesToUninstall.push('sharp');
|
|
129
|
-
}
|
|
130
|
-
// Ensure lexical is installed if user doesn't have a custom editor
|
|
131
|
-
// (buildFigmaConfig uses lexicalEditor() as default)
|
|
132
|
-
if (!detection.editorProperty) {
|
|
133
|
-
log.debug('No editor property detected - will ensure lexical is installed for default editor');
|
|
134
|
-
} else if (detection.editorProperty.isDefault) {
|
|
135
|
-
log.debug('Default lexicalEditor() detected - will ensure lexical is installed');
|
|
136
|
-
} else {
|
|
137
|
-
log.debug(`Custom editor detected (${detection.editorProperty.importSource}) - skipping lexical installation`);
|
|
138
|
-
}
|
|
139
|
-
if (!detection.editorProperty || detection.editorProperty.isDefault) {
|
|
140
|
-
log.debug('Checking if @payloadcms/richtext-lexical is installed...');
|
|
141
|
-
const hasLexical = await checkPackageInstalled(projectPath, '@payloadcms/richtext-lexical');
|
|
142
|
-
if (!hasLexical) {
|
|
143
|
-
log.debug('@payloadcms/richtext-lexical not found, installing...');
|
|
144
|
-
try {
|
|
145
|
-
await installPackage(projectPath, '@payloadcms/richtext-lexical', packageManager, payloadVersion);
|
|
146
|
-
changes.push('Installed @payloadcms/richtext-lexical (default editor)');
|
|
147
|
-
log.debug('Successfully installed @payloadcms/richtext-lexical');
|
|
148
|
-
} catch (error) {
|
|
149
|
-
log.debug(`Failed to install @payloadcms/richtext-lexical: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
150
|
-
// Don't fail on install error - user can install manually if needed
|
|
151
|
-
warnings.push('Could not install @payloadcms/richtext-lexical - you may need to install it manually');
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
log.debug('@payloadcms/richtext-lexical already installed, skipping');
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
// Ensure cloud-storage is installed (required peer dependency for buildFigmaConfig)
|
|
158
|
-
log.debug('Checking if @payloadcms/plugin-cloud-storage is installed...');
|
|
159
|
-
const hasCloudStorage = await checkPackageInstalled(projectPath, '@payloadcms/plugin-cloud-storage');
|
|
160
|
-
if (!hasCloudStorage) {
|
|
161
|
-
log.debug('@payloadcms/plugin-cloud-storage not found, installing...');
|
|
162
|
-
try {
|
|
163
|
-
await installPackage(projectPath, '@payloadcms/plugin-cloud-storage', packageManager, payloadVersion);
|
|
164
|
-
changes.push('Installed @payloadcms/plugin-cloud-storage');
|
|
165
|
-
log.debug('Successfully installed @payloadcms/plugin-cloud-storage');
|
|
166
|
-
} catch (error) {
|
|
167
|
-
log.debug(`Failed to install @payloadcms/plugin-cloud-storage: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
168
|
-
warnings.push('Could not install @payloadcms/plugin-cloud-storage - you may need to install it manually');
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
log.debug('@payloadcms/plugin-cloud-storage already installed, skipping');
|
|
172
|
-
}
|
|
173
|
-
if (packagesToUninstall.length > 0) {
|
|
174
|
-
log.debug(`Uninstalling ${packagesToUninstall.length} orphaned packages...`);
|
|
175
|
-
}
|
|
176
|
-
for (const pkg of packagesToUninstall){
|
|
177
|
-
try {
|
|
178
|
-
await uninstallPackage(projectPath, pkg, packageManager);
|
|
179
|
-
changes.push(`Uninstalled ${pkg}`);
|
|
180
|
-
log.debug(`Uninstalled ${pkg}`);
|
|
181
|
-
} catch (error) {
|
|
182
|
-
log.debug(`Failed to uninstall ${pkg}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
183
|
-
// Don't fail on uninstall errors - orphaned package is better than broken config
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// 8. Format file
|
|
187
164
|
log.debug('Formatting config file...');
|
|
188
165
|
const formatResult = await formatFile(configPath, packageManager);
|
|
189
166
|
if (!formatResult.success && formatResult.warning) {
|
|
190
167
|
warnings.push(formatResult.warning);
|
|
191
168
|
log.debug(`Formatting warning: ${formatResult.warning}`);
|
|
192
169
|
}
|
|
193
|
-
// 9. Run TypeScript validation
|
|
194
170
|
log.debug('Running TypeScript validation...');
|
|
195
171
|
const tsResult = await runTypeScriptCheck(projectPath, packageManager);
|
|
196
172
|
if (!tsResult.success && tsResult.errors.length > 0) {
|
|
197
173
|
warnings.push(`TypeScript validation found issues - run '${getRunCommand(packageManager)} build' for details`);
|
|
198
174
|
log.debug(`TypeScript validation found ${tsResult.errors.length} issues`);
|
|
199
175
|
}
|
|
200
|
-
}
|
|
176
|
+
}
|
|
177
|
+
if (packagesToUninstall.length > 0) {
|
|
178
|
+
log.debug(`Uninstalling ${packagesToUninstall.length} orphaned packages: ${packagesToUninstall.join(', ')}`);
|
|
179
|
+
const uninstallResult = await uninstallPackages(projectPath, packagesToUninstall, packageManager);
|
|
180
|
+
if (uninstallResult.success) {
|
|
181
|
+
for (const pkg of packagesToUninstall){
|
|
182
|
+
changes.push(`Uninstalled ${pkg}`);
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
warnings.push(`Could not uninstall ${uninstallResult.failedPackages.join(', ')} — they may remain as orphaned dependencies in package.json`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const modified = astModified || changes.length > 0;
|
|
189
|
+
if (!modified) {
|
|
201
190
|
log.debug('No modifications needed - config already correct');
|
|
202
191
|
}
|
|
203
192
|
log.debug('Payload config modification completed successfully');
|
|
@@ -215,7 +204,7 @@ import { getOwnVersion } from './version-check.js';
|
|
|
215
204
|
return {
|
|
216
205
|
changes,
|
|
217
206
|
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
218
|
-
modified,
|
|
207
|
+
modified: astModified,
|
|
219
208
|
success: false
|
|
220
209
|
};
|
|
221
210
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { PackageManager } from './package-manager.js';
|
|
2
|
+
export type PackageSpec = {
|
|
3
|
+
name: string;
|
|
4
|
+
version?: string;
|
|
5
|
+
};
|
|
6
|
+
export type UninstallResult = {
|
|
7
|
+
failedPackages: string[];
|
|
8
|
+
success: boolean;
|
|
9
|
+
};
|
|
2
10
|
/**
|
|
3
11
|
* Check if a package is installed in dependencies (not devDependencies)
|
|
4
12
|
*/
|
|
@@ -13,11 +21,23 @@ export declare function getPayloadVersion(projectPath: string): Promise<string |
|
|
|
13
21
|
* @param version - Version to install (without caret). Defaults to 'latest'.
|
|
14
22
|
*/
|
|
15
23
|
export declare function installPackage(projectPath: string, packageName: string, packageManager: PackageManager, version?: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Install multiple packages as production dependencies in a single package-manager call.
|
|
26
|
+
* No-op when packages is empty. Throws on failure with exit code and truncated stderr.
|
|
27
|
+
*/
|
|
28
|
+
export declare function installPackages(projectPath: string, packages: PackageSpec[], packageManager: PackageManager): Promise<void>;
|
|
16
29
|
/**
|
|
17
30
|
* Uninstall a package
|
|
18
31
|
* Does not throw on failure - orphaned package is better than broken config
|
|
19
32
|
*/
|
|
20
|
-
export declare function uninstallPackage(projectPath: string, packageName: string, packageManager: PackageManager): Promise<
|
|
33
|
+
export declare function uninstallPackage(projectPath: string, packageName: string, packageManager: PackageManager): Promise<UninstallResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Uninstall multiple packages in a single package-manager call.
|
|
36
|
+
* No-op when packageNames is empty. Does not throw — orphaned packages are
|
|
37
|
+
* preferable to a crash mid-config-rewrite. Returns a success flag so callers
|
|
38
|
+
* can avoid claiming "Uninstalled X" when the package manager actually failed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function uninstallPackages(projectPath: string, packageNames: string[], packageManager: PackageManager): Promise<UninstallResult>;
|
|
21
41
|
/**
|
|
22
42
|
* Run an npm script from package.json
|
|
23
43
|
* Does not throw on failure - logs warning and continues
|
|
@@ -40,24 +40,33 @@ import * as log from './log.js';
|
|
|
40
40
|
* Install a package as a production dependency
|
|
41
41
|
* @param version - Version to install (without caret). Defaults to 'latest'.
|
|
42
42
|
*/ export async function installPackage(projectPath, packageName, packageManager, version = 'latest') {
|
|
43
|
+
return installPackages(projectPath, [
|
|
44
|
+
{
|
|
45
|
+
name: packageName,
|
|
46
|
+
version
|
|
47
|
+
}
|
|
48
|
+
], packageManager);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Install multiple packages as production dependencies in a single package-manager call.
|
|
52
|
+
* No-op when packages is empty. Throws on failure with exit code and truncated stderr.
|
|
53
|
+
*/ export async function installPackages(projectPath, packages, packageManager) {
|
|
54
|
+
if (packages.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
43
57
|
return new Promise((resolve, reject)=>{
|
|
44
58
|
const command = packageManager;
|
|
45
|
-
const
|
|
59
|
+
const packageSpecs = packages.map(({ name, version })=>name.endsWith('.tgz') ? name : `${name}@${version ?? 'latest'}`);
|
|
46
60
|
const args = [
|
|
47
|
-
'add',
|
|
48
|
-
|
|
61
|
+
packageManager === 'npm' ? 'install' : 'add',
|
|
62
|
+
...packageSpecs
|
|
49
63
|
];
|
|
50
|
-
// npm uses 'install' instead of 'add'
|
|
51
|
-
if (packageManager === 'npm') {
|
|
52
|
-
args[0] = 'install';
|
|
53
|
-
}
|
|
54
64
|
log.debug(`Running: ${command} ${args.join(' ')} in ${projectPath}`);
|
|
55
65
|
let stderr = '';
|
|
56
66
|
const child = spawn(command, args, {
|
|
57
67
|
cwd: projectPath,
|
|
58
68
|
stdio: 'pipe'
|
|
59
69
|
});
|
|
60
|
-
// Capture stderr for debug logging
|
|
61
70
|
if (child.stderr) {
|
|
62
71
|
child.stderr.on('data', (data)=>{
|
|
63
72
|
stderr += data.toString();
|
|
@@ -69,15 +78,17 @@ import * as log from './log.js';
|
|
|
69
78
|
});
|
|
70
79
|
child.on('close', (code)=>{
|
|
71
80
|
if (code === 0) {
|
|
72
|
-
log.debug(`Successfully installed ${
|
|
81
|
+
log.debug(`Successfully installed ${packageSpecs.join(', ')}`);
|
|
73
82
|
resolve();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
reject(new Error(`Failed to install ${packageName}`));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
log.debug(`Batched install failed (exit code: ${code})`);
|
|
86
|
+
if (stderr) {
|
|
87
|
+
log.debug(`stderr: ${stderr}`);
|
|
80
88
|
}
|
|
89
|
+
const truncatedStderr = stderr.trim().slice(-500);
|
|
90
|
+
const detail = truncatedStderr ? `\n${truncatedStderr}` : '';
|
|
91
|
+
reject(new Error(`Failed to install: ${packageSpecs.join(', ')} (exit code ${code})${detail}`));
|
|
81
92
|
});
|
|
82
93
|
});
|
|
83
94
|
}
|
|
@@ -85,29 +96,58 @@ import * as log from './log.js';
|
|
|
85
96
|
* Uninstall a package
|
|
86
97
|
* Does not throw on failure - orphaned package is better than broken config
|
|
87
98
|
*/ export async function uninstallPackage(projectPath, packageName, packageManager) {
|
|
99
|
+
return uninstallPackages(projectPath, [
|
|
100
|
+
packageName
|
|
101
|
+
], packageManager);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Uninstall multiple packages in a single package-manager call.
|
|
105
|
+
* No-op when packageNames is empty. Does not throw — orphaned packages are
|
|
106
|
+
* preferable to a crash mid-config-rewrite. Returns a success flag so callers
|
|
107
|
+
* can avoid claiming "Uninstalled X" when the package manager actually failed.
|
|
108
|
+
*/ export async function uninstallPackages(projectPath, packageNames, packageManager) {
|
|
109
|
+
if (packageNames.length === 0) {
|
|
110
|
+
return {
|
|
111
|
+
failedPackages: [],
|
|
112
|
+
success: true
|
|
113
|
+
};
|
|
114
|
+
}
|
|
88
115
|
return new Promise((resolve)=>{
|
|
89
116
|
const command = packageManager;
|
|
90
117
|
const args = [
|
|
91
|
-
'remove',
|
|
92
|
-
|
|
118
|
+
packageManager === 'npm' ? 'uninstall' : 'remove',
|
|
119
|
+
...packageNames
|
|
93
120
|
];
|
|
94
|
-
// npm uses 'uninstall' instead of 'remove'
|
|
95
|
-
if (packageManager === 'npm') {
|
|
96
|
-
args[0] = 'uninstall';
|
|
97
|
-
}
|
|
98
121
|
log.debug(`Running: ${command} ${args.join(' ')} in ${projectPath}`);
|
|
99
122
|
const child = spawn(command, args, {
|
|
100
123
|
cwd: projectPath,
|
|
101
124
|
stdio: 'pipe'
|
|
102
125
|
});
|
|
126
|
+
child.on('error', (error)=>{
|
|
127
|
+
log.debug(`Spawn error for ${command}: ${error.message}`);
|
|
128
|
+
resolve({
|
|
129
|
+
failedPackages: [
|
|
130
|
+
...packageNames
|
|
131
|
+
],
|
|
132
|
+
success: false
|
|
133
|
+
});
|
|
134
|
+
});
|
|
103
135
|
child.on('close', (code)=>{
|
|
104
136
|
if (code === 0) {
|
|
105
|
-
log.debug(`Successfully uninstalled ${
|
|
106
|
-
|
|
107
|
-
|
|
137
|
+
log.debug(`Successfully uninstalled ${packageNames.join(', ')}`);
|
|
138
|
+
resolve({
|
|
139
|
+
failedPackages: [],
|
|
140
|
+
success: true
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
108
143
|
}
|
|
109
|
-
|
|
110
|
-
resolve(
|
|
144
|
+
log.debug(`Batched uninstall failed (exit code: ${code}), continuing anyway`);
|
|
145
|
+
resolve({
|
|
146
|
+
failedPackages: [
|
|
147
|
+
...packageNames
|
|
148
|
+
],
|
|
149
|
+
success: false
|
|
150
|
+
});
|
|
111
151
|
});
|
|
112
152
|
});
|
|
113
153
|
}
|
|
@@ -8,7 +8,11 @@ export declare function maskToken(token: string): string;
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function formatTimestamp(timestamp: number): string;
|
|
10
10
|
/**
|
|
11
|
-
* Show
|
|
11
|
+
* Show the project token for the current project + environment scope.
|
|
12
|
+
*
|
|
13
|
+
* Resolves `projectId` and `environmentName` from env vars
|
|
14
|
+
* (`FIGMA_PROJECT_ID`, `FIGMA_ENVIRONMENT_NAME`) — the *user's* project
|
|
15
|
+
* environment, which is independent of the infra env (production/staging).
|
|
12
16
|
*/
|
|
13
17
|
export declare function showProjectTokens(tokenStore: TokenStore): void;
|
|
14
18
|
//# sourceMappingURL=token-display.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import pc from 'picocolors';
|
|
3
|
+
import { getEnvVarSync } from './env-management.js';
|
|
3
4
|
import { isDebug } from './is-debug.js';
|
|
4
5
|
/**
|
|
5
6
|
* Mask token for display (show first 4 and last 4 characters)
|
|
@@ -32,38 +33,58 @@ import { isDebug } from './is-debug.js';
|
|
|
32
33
|
return pc.red(`${minutes}m`);
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
|
-
* Show
|
|
36
|
+
* Show the project token for the current project + environment scope.
|
|
37
|
+
*
|
|
38
|
+
* Resolves `projectId` and `environmentName` from env vars
|
|
39
|
+
* (`FIGMA_PROJECT_ID`, `FIGMA_ENVIRONMENT_NAME`) — the *user's* project
|
|
40
|
+
* environment, which is independent of the infra env (production/staging).
|
|
36
41
|
*/ export function showProjectTokens(tokenStore) {
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
const projectId = getEnvVarSync(cwd, 'FIGMA_PROJECT_ID');
|
|
44
|
+
const environmentName = getEnvVarSync(cwd, 'FIGMA_ENVIRONMENT_NAME');
|
|
45
|
+
if (!projectId || !environmentName) {
|
|
46
|
+
p.note(pc.dim('Set FIGMA_PROJECT_ID and FIGMA_ENVIRONMENT_NAME in your .env to view project tokens.'), 'Project Tokens');
|
|
41
47
|
return;
|
|
42
48
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
const header = [
|
|
50
|
+
`Project ID: ${projectId}`,
|
|
51
|
+
`Environment: ${environmentName}`
|
|
52
|
+
];
|
|
53
|
+
const bootstrapData = tokenStore.getBootstrapData(projectId, environmentName);
|
|
54
|
+
if (!bootstrapData) {
|
|
55
|
+
p.note([
|
|
56
|
+
...header,
|
|
57
|
+
pc.dim('No bootstrap data. Run `@payloadcms/figma init` to set up.')
|
|
58
|
+
].join('\n'), 'Project Token');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const projectInfo = {
|
|
62
|
+
environmentName,
|
|
63
|
+
projectId
|
|
64
|
+
};
|
|
65
|
+
const projectToken = tokenStore.getProjectToken({
|
|
66
|
+
projectInfo
|
|
60
67
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
if (!projectToken) {
|
|
69
|
+
p.note([
|
|
70
|
+
...header,
|
|
71
|
+
`Tenant ID: ${bootstrapData.contentSystemId}`,
|
|
72
|
+
pc.dim('No stored token.')
|
|
73
|
+
].join('\n'), 'Project Token');
|
|
64
74
|
return;
|
|
65
75
|
}
|
|
66
|
-
|
|
76
|
+
const isValid = tokenStore.hasValidProjectToken({
|
|
77
|
+
projectInfo
|
|
78
|
+
});
|
|
79
|
+
const status = isValid ? pc.green('✓ Valid') : pc.red('✗ Expired');
|
|
80
|
+
const projectTokenLines = [
|
|
81
|
+
...header,
|
|
82
|
+
`Tenant ID: ${bootstrapData.contentSystemId}`,
|
|
83
|
+
`Status: ${status}`,
|
|
84
|
+
`Token: ${isDebug() ? projectToken.token : maskToken(projectToken.token)}`,
|
|
85
|
+
`Expires: ${formatTimestamp(projectToken.expiresAt)}`
|
|
86
|
+
];
|
|
87
|
+
p.note(projectTokenLines.join('\n'), 'Project Token');
|
|
67
88
|
}
|
|
68
89
|
|
|
69
90
|
//# sourceMappingURL=token-display.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/figma",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.64",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"arg": "^5.0.2",
|
|
35
35
|
"conf": "^13.1.0",
|
|
36
36
|
"cross-spawn": "7.0.6",
|
|
37
|
+
"env-paths": "^3.0.0",
|
|
37
38
|
"figures": "^6.1.0",
|
|
38
39
|
"jose": "6.0.12",
|
|
39
40
|
"jsonwebtoken": "9.0.3",
|