93 lines
2.9 KiB
JavaScript
93 lines
2.9 KiB
JavaScript
/**
|
|
* Scans the entire Figma file for nodes tagged with dsb_* pluginData
|
|
* and returns a complete state map for session recovery.
|
|
*
|
|
* Use this at the start of every new session, after context truncation,
|
|
* or when resuming an interrupted build.
|
|
*
|
|
* @param {string} runId - The run ID to filter by (optional — if omitted, returns ALL dsb-tagged nodes)
|
|
* @returns {{ runId: string, taggedNodes: Object<string, {nodeId: string, type: string, name: string, phase: string}>, variableCollections: Array, variables: Array, styles: Array }}
|
|
*/
|
|
async function rehydrateState(runId) {
|
|
const taggedNodes = {}
|
|
const variableCollections = []
|
|
const variables = []
|
|
const styles = []
|
|
|
|
// Scan all pages for dsb-tagged scene nodes
|
|
for (const page of figma.root.children) {
|
|
await figma.setCurrentPageAsync(page)
|
|
|
|
// Check the page itself
|
|
const pageRunId = page.getPluginData('dsb_run_id')
|
|
const pageKey = page.getPluginData('dsb_key')
|
|
if (pageKey && (!runId || pageRunId === runId)) {
|
|
taggedNodes[pageKey] = {
|
|
nodeId: page.id,
|
|
type: page.type,
|
|
name: page.name,
|
|
phase: page.getPluginData('dsb_phase') || 'unknown',
|
|
}
|
|
}
|
|
|
|
// Scan all descendants
|
|
page.findAll((node) => {
|
|
const nodeRunId = node.getPluginData('dsb_run_id')
|
|
const nodeKey = node.getPluginData('dsb_key')
|
|
if (nodeKey && (!runId || nodeRunId === runId)) {
|
|
taggedNodes[nodeKey] = {
|
|
nodeId: node.id,
|
|
type: node.type,
|
|
name: node.name,
|
|
phase: node.getPluginData('dsb_phase') || 'unknown',
|
|
}
|
|
}
|
|
return false // don't collect, just scan
|
|
})
|
|
}
|
|
|
|
// Inventory variable collections (variables don't support pluginData — use name-based lookup)
|
|
const collections = await figma.variables.getLocalVariableCollectionsAsync()
|
|
for (const coll of collections) {
|
|
variableCollections.push({
|
|
id: coll.id,
|
|
name: coll.name,
|
|
modes: coll.modes.map((m) => ({ modeId: m.modeId, name: m.name })),
|
|
variableCount: coll.variableIds.length,
|
|
})
|
|
}
|
|
|
|
// Inventory variables (name + collection for idempotency key)
|
|
const allVars = await figma.variables.getLocalVariablesAsync()
|
|
for (const v of allVars) {
|
|
variables.push({
|
|
id: v.id,
|
|
name: v.name,
|
|
collectionId: v.variableCollectionId,
|
|
resolvedType: v.resolvedType,
|
|
})
|
|
}
|
|
|
|
// Inventory styles
|
|
for (const s of figma.getLocalTextStyles()) {
|
|
styles.push({ id: s.id, name: s.name, type: 'TEXT' })
|
|
}
|
|
for (const s of figma.getLocalEffectStyles()) {
|
|
styles.push({ id: s.id, name: s.name, type: 'EFFECT' })
|
|
}
|
|
for (const s of figma.getLocalPaintStyles()) {
|
|
styles.push({ id: s.id, name: s.name, type: 'PAINT' })
|
|
}
|
|
|
|
return {
|
|
runId: runId || 'all',
|
|
taggedNodes,
|
|
taggedNodeCount: Object.keys(taggedNodes).length,
|
|
variableCollections,
|
|
variableCount: variables.length,
|
|
variables,
|
|
styleCount: styles.length,
|
|
styles,
|
|
}
|
|
}
|