@catchdrift/cli 0.1.7 → 0.1.8
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/package.json +1 -1
- package/src/commands/init.mjs +42 -12
package/package.json
CHANGED
package/src/commands/init.mjs
CHANGED
|
@@ -132,27 +132,51 @@ export async function init(argv) {
|
|
|
132
132
|
// ── Step 3a: Figma ───────────────────────────────────────────────────────────
|
|
133
133
|
let figmaFileKey, figmaToken, figmaWIPPages
|
|
134
134
|
if (sources.includes('figma')) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
// Accept full URL or raw key
|
|
136
|
+
const figmaInput = await p.text({
|
|
137
|
+
message: 'Paste your Figma file URL (or just the file key)',
|
|
138
|
+
placeholder: 'https://www.figma.com/design/ABC123.../My-Design-File',
|
|
139
|
+
hint: 'Open your Figma file in a browser and copy the full URL from the address bar',
|
|
140
|
+
validate: v => (!v?.trim() ? 'Required' : undefined),
|
|
139
141
|
})
|
|
140
|
-
if (p.isCancel(
|
|
141
|
-
figmaFileKey =
|
|
142
|
+
if (p.isCancel(figmaInput)) { p.cancel('Setup cancelled.'); process.exit(EXIT_CANCELED) }
|
|
143
|
+
figmaFileKey = extractFigmaFileKey(figmaInput.trim())
|
|
144
|
+
if (!figmaFileKey) {
|
|
145
|
+
p.log.warn(`Could not extract a file key from "${figmaInput.trim()}". Using it as-is.`)
|
|
146
|
+
figmaFileKey = figmaInput.trim()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Token — show exact steps + required scopes
|
|
150
|
+
console.log('')
|
|
151
|
+
p.log.step('Create a Figma access token — takes about 60 seconds:')
|
|
152
|
+
console.log(`
|
|
153
|
+
1. Open ${pc.cyan('figma.com')} → click your avatar (top-left) → ${pc.bold('Settings')}
|
|
154
|
+
2. Go to the ${pc.bold('Security')} tab → click ${pc.bold('Generate new token')}
|
|
155
|
+
3. Give it a name (e.g. "Drift") and set an expiry
|
|
156
|
+
4. Enable these scopes:
|
|
157
|
+
${pc.green('✓')} File content → ${pc.bold('Read only')}
|
|
158
|
+
${pc.green('✓')} File comments → ${pc.bold('Write')}
|
|
159
|
+
${pc.green('✓')} File variables → ${pc.bold('Read only')}
|
|
160
|
+
5. Click ${pc.bold('Generate token')} and copy it — ${pc.yellow("you won't be able to see it again")}
|
|
161
|
+
`)
|
|
142
162
|
|
|
143
163
|
figmaToken = await p.text({
|
|
144
|
-
message: '
|
|
145
|
-
placeholder: 'figd_...
|
|
146
|
-
hint: '
|
|
164
|
+
message: 'Paste your Figma token here',
|
|
165
|
+
placeholder: 'figd_...',
|
|
166
|
+
hint: 'Stored in your local FIGMA_API_TOKEN env var — never committed to git',
|
|
167
|
+
validate: v => (!v?.trim() ? 'Required — paste the token you just generated' : undefined),
|
|
147
168
|
})
|
|
148
169
|
if (p.isCancel(figmaToken)) { p.cancel('Setup cancelled.'); process.exit(EXIT_CANCELED) }
|
|
149
170
|
figmaToken = figmaToken?.trim() || undefined
|
|
150
171
|
|
|
151
|
-
//
|
|
172
|
+
// Validate token + fetch pages in one call
|
|
152
173
|
if (figmaToken && figmaFileKey) {
|
|
153
|
-
spinner.start('
|
|
174
|
+
spinner.start('Connecting to Figma...')
|
|
154
175
|
const pages = await fetchFigmaPages(figmaFileKey, figmaToken)
|
|
155
|
-
spinner.stop(pages
|
|
176
|
+
spinner.stop(pages
|
|
177
|
+
? pc.green(`Connected ✓ Found ${pages.length} pages`)
|
|
178
|
+
: pc.yellow('Could not reach Figma — check your token scopes. You can re-run `npx catchdrift init` to retry.')
|
|
179
|
+
)
|
|
156
180
|
|
|
157
181
|
if (pages?.length) {
|
|
158
182
|
const selected = await p.multiselect({
|
|
@@ -339,6 +363,12 @@ ${pc.dim('Docs: https://catchdrift.ai · Issues: https://github.com/dyoon92/de
|
|
|
339
363
|
|
|
340
364
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
341
365
|
|
|
366
|
+
function extractFigmaFileKey(input) {
|
|
367
|
+
// Matches: figma.com/design/KEY/... or figma.com/file/KEY/...
|
|
368
|
+
const match = input.match(/figma\.com\/(?:design|file)\/([a-zA-Z0-9]+)/)
|
|
369
|
+
return match ? match[1] : null
|
|
370
|
+
}
|
|
371
|
+
|
|
342
372
|
async function fetchFigmaPages(fileKey, token) {
|
|
343
373
|
try {
|
|
344
374
|
const res = await fetch(`https://api.figma.com/v1/files/${fileKey}?depth=1`, {
|