askeroo
Version:
A modern CLI prompt library with flow control, history navigation, and conditional prompts
138 lines • 4.74 kB
JavaScript
/**
* FieldDiscoveryService - Handles field discovery for static groups
*
* Static groups need to pre-scan their fields before rendering to know what
* fields will be shown. This service manages the discovery process, tracks
* discovered fields, and provides re-discovery capabilities.
*/
import { debugLogger } from "../utils/logging.js";
export class FieldDiscoveryService {
state;
isScanning = false;
discoveredFieldsByGroup = new Map();
groupBodyFunctions = new Map();
constructor(state) {
this.state = state;
}
// ========== SCANNING STATE ==========
isCurrentlyScanning() {
return this.isScanning;
}
// ========== FIELD RETRIEVAL ==========
getDiscoveredFields(groupId) {
return this.discoveredFieldsByGroup.get(groupId);
}
// ========== FIELD REGISTRATION ==========
registerDiscoveredField(groupId, field) {
const fields = this.discoveredFieldsByGroup.get(groupId) || [];
// Only add if not already present
if (!fields.some((f) => f.id === field.id)) {
fields.push(field);
this.discoveredFieldsByGroup.set(groupId, fields);
debugLogger.log("DISCOVERY_FIELD_ADDED", {
groupId,
fieldId: field.id,
fieldCount: fields.length,
});
}
}
// ========== GROUP BODY STORAGE ==========
storeGroupBodyFunction(groupId, body) {
this.groupBodyFunctions.set(groupId, body);
}
hasStoredBodyFunction(groupId) {
return this.groupBodyFunctions.has(groupId);
}
// ========== FIELD SCANNING ==========
/**
* Scan a static group to discover all its fields
* Executes the group body in scanning mode to find all fields
*/
async scanGroupFields(groupId, body) {
this.isScanning = true;
debugLogger.log("DISCOVERY_START", {
groupId,
groupStack: this.state.getGroupHierarchy(),
});
// Push group to stack temporarily for discovery
this.state.enterGroup(groupId);
try {
// Run discovery once to find all fields
await body();
}
catch (e) {
debugLogger.log("DISCOVERY_ERROR", {
groupId,
error: e,
});
// Ignore errors in discovery mode
}
finally {
// Remove from stack after discovery
this.state.exitGroup();
}
this.isScanning = false;
const discoveredFields = this.discoveredFieldsByGroup.get(groupId);
debugLogger.log("DISCOVERY_END", {
groupId,
fields: discoveredFields,
});
return discoveredFields || [];
}
/**
* Re-scan a static group's fields
* Used when a group needs to be re-rendered with updated fields
*/
async rescanGroupFields(groupId) {
if (this.isScanning) {
// Already scanning, skip
return this.discoveredFieldsByGroup.get(groupId);
}
if (!this.groupBodyFunctions.has(groupId)) {
// No stored body function, return existing fields
return this.discoveredFieldsByGroup.get(groupId);
}
debugLogger.log("REDISCOVERY_START", { groupId });
const body = this.groupBodyFunctions.get(groupId);
// Clear existing discovered fields for this group
this.discoveredFieldsByGroup.delete(groupId);
this.isScanning = true;
this.state.enterGroup(groupId);
try {
await body();
}
catch (e) {
debugLogger.log("REDISCOVERY_ERROR", { groupId, error: e });
}
finally {
this.state.exitGroup();
this.isScanning = false;
}
const rescannedFields = this.discoveredFieldsByGroup.get(groupId);
debugLogger.log("REDISCOVERY_END", {
groupId,
fields: rescannedFields,
});
return rescannedFields;
}
// ========== CLEANUP ==========
/**
* Clear all discovered fields and stored body functions
* Typically used when resetting the runtime
*/
clearAll() {
this.discoveredFieldsByGroup.clear();
this.groupBodyFunctions.clear();
this.isScanning = false;
}
// ========== DEBUG/INSPECTION ==========
getDebugInfo() {
return {
isScanning: this.isScanning,
discoveredGroupsCount: this.discoveredFieldsByGroup.size,
storedBodiesCount: this.groupBodyFunctions.size,
groups: Array.from(this.discoveredFieldsByGroup.keys()),
};
}
}
//# sourceMappingURL=discovery-service.js.map