@lineai/municipal-intel
Version:
AI-first municipal data API providing natural language descriptions of building permits and planning applications from major US cities
191 lines • 12.1 kB
JavaScript
/**
* Municipal source registry management
*/
import { builtInRegistry } from './data/municipal-registry';
/**
* Source registry manager
*/
export class SourceRegistryManager {
registry;
runtimeSources = new Map();
constructor() {
this.registry = builtInRegistry;
}
/**
* Get all sources (built-in + runtime)
*/
getAllSources() {
const allSources = [];
// Add built-in sources
for (const state of ['ca', 'ny', 'fl']) {
const sources = this.registry.sources[state].municipalities.map(source => ({
...source,
state: state.toUpperCase()
}));
allSources.push(...sources);
}
// Add runtime sources
allSources.push(...Array.from(this.runtimeSources.values()));
return allSources;
}
/**
* Get sources by state
*/
getSourcesByState(state) {
return this.registry.sources[state]?.municipalities.map(source => ({
...source,
state: state.toUpperCase()
})) || [];
}
/**
* Get source by ID
*/
getSource(id) {
return this.getAllSources().find(source => source.id === id);
}
/**
* Get sources by priority
*/
getSourcesByPriority(priority) {
return this.getAllSources().filter(source => source.priority === priority);
}
/**
* Get sources by type
*/
getSourcesByType(type) {
return this.getAllSources().filter(source => source.type === type);
}
/**
* Get API sources (easiest to implement)
*/
getApiSources() {
return this.getSourcesByType('api');
}
/**
* Get Socrata sources specifically
*/
getSocrataSources() {
return this.getApiSources().filter(source => source.api?.type === 'socrata');
}
/**
* Get enabled sources only
*/
getEnabledSources() {
return this.getAllSources().filter(source => source.enabled !== false);
}
/**
* Get sources for implementation (high priority, API-based)
*/
getImplementationReadySources() {
return this.getAllSources().filter(source => source.priority === 'high' &&
source.type === 'api' &&
source.enabled !== false);
}
/**
* Update source status
*/
updateSourceStatus(id, updates) {
const source = this.getSource(id);
if (source) {
Object.assign(source, updates);
}
}
/**
* Get registry metadata
*/
getRegistryInfo() {
return {
version: this.registry.version,
lastUpdated: this.registry.lastUpdated,
totalSources: this.getAllSources().length
};
}
/**
* Search sources by name or ID
*/
searchSources(query) {
const lowerQuery = query.toLowerCase();
return this.getAllSources().filter(source => source.id.toLowerCase().includes(lowerQuery) ||
source.name.toLowerCase().includes(lowerQuery));
}
/**
* Get sources that cover a specific city/area
*/
getSourcesForLocation(city, state) {
const lowerCity = city.toLowerCase();
return this.getAllSources().filter(source => {
// Check if source name matches city
if (source.name.toLowerCase().includes(lowerCity)) {
return true;
}
// Check coverage area if specified
if (source.coverage) {
return source.coverage.some(area => area.toLowerCase().includes(lowerCity));
}
// Check state if provided
if (state && source.state.toLowerCase() !== state.toLowerCase()) {
return false;
}
return false;
});
}
/**
* Register a new source at runtime
*/
registerSource(source) {
// Validate source has required fields
if (!source.id || !source.name || !source.state || !source.type || !source.priority) {
throw new Error('Source must have id, name, state, type, and priority');
}
// Check for duplicate IDs
if (this.getSource(source.id)) {
throw new Error(`Source with ID '${source.id}' already exists`);
}
// Add to runtime sources
this.runtimeSources.set(source.id, {
...source,
enabled: source.enabled !== false // Default to enabled
});
}
/**
* Unregister a runtime source
*/
unregisterSource(id) {
return this.runtimeSources.delete(id);
}
/**
* Check if a source is built-in or runtime-added
*/
isBuiltInSource(id) {
// Check if source exists in built-in registry
for (const state of ['ca', 'ny', 'fl']) {
const found = this.registry.sources[state].municipalities.find(source => source.id === id);
if (found)
return true;
}
return false;
}
/**
* Get only built-in sources
*/
getBuiltInSources() {
const allSources = [];
for (const state of ['ca', 'ny', 'fl']) {
const sources = this.registry.sources[state].municipalities.map(source => ({
...source,
state: state.toUpperCase()
}));
allSources.push(...sources);
}
return allSources;
}
/**
* Get only runtime sources
*/
getRuntimeSources() {
return Array.from(this.runtimeSources.values());
}
}
// Default registry instance
export const sourceRegistry = new SourceRegistryManager();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFHSCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFNUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBQ3hCLFFBQVEsQ0FBaUI7SUFDekIsY0FBYyxHQUFpQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRWpFO1FBQ0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxlQUFlLENBQUM7SUFDbEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFBYTtRQUNYLE1BQU0sVUFBVSxHQUFzQixFQUFFLENBQUM7UUFFekMsdUJBQXVCO1FBQ3ZCLEtBQUssTUFBTSxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBVSxFQUFFO1lBQy9DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6RSxHQUFHLE1BQU07Z0JBQ1QsS0FBSyxFQUFFLEtBQUssQ0FBQyxXQUFXLEVBQUU7YUFDM0IsQ0FBQyxDQUFDLENBQUM7WUFDSixVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUM7U0FDN0I7UUFFRCxzQkFBc0I7UUFDdEIsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFN0QsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsaUJBQWlCLENBQUMsS0FBeUI7UUFDekMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxj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