refactor: enforce import directions and expose source factories

This commit is contained in:
Sameh Khamis committed 2026-09-14 21:12:01 -07:00
1 parent 704e0fcc51
commit cc960b0dbe
41 files changed
+1080 -417

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ import { createApplicationFirms } from './layers/firms.js';
import { createApplicationEarthquakes } from './layers/earthquakes.js';
import { createApplicationCables } from './layers/submarineCables.js';
import { createInfrastructureLayers } from '../data/infrastructure.js';
import { localGeoJsonServices } from '../data/localGeojson.js';
import { localGeoJsonServices } from './localGeojsonServices.js';
const SOURCE_METHODS = Object.freeze({
flights: ['getSnapshot'],
+25
View File
@@ -0,0 +1,25 @@
import { governorRequestRender } from '../renderGovernor.js';
import {
clearSelectedEntityContextForLayer,
registerEntityContext,
removeEntityContextsForLayer,
selectEntityContext,
} from '../data/contextStore.js';
import {
clearOverlaySource,
setOverlayEntries,
setOverlaySourceVisible,
} from '../overlays/worldOverlay.js';
/** Existing standalone application operations, shared by its local layers. */
export const localGeoJsonServices = Object.freeze({
overlayHost: Object.freeze({
clearSource: clearOverlaySource,
setEntries: setOverlayEntries,
setVisible: setOverlaySourceVisible,
}),
clearSelectedEntityContextForLayer,
registerEntityContext,
removeEntityContextsForLayer,
selectEntityContext,
governorRequestRender,
});
+2 -52
View File
@@ -1,52 +1,2 @@
/** Bind a source contract once for the application without replacing its layer instance. */
export function createSourceSlot(
initial,
methods,
label = 'Source',
optional = {},
) {
let active = initial;
let binding = null;
const source = Object.fromEntries(
[...methods, ...Object.keys(optional)].map((method) => [
method,
(...args) => {
if (typeof active?.[method] !== 'function' && optional[method])
return optional[method](...args);
if (typeof active?.[method] !== 'function')
throw new Error(`${label} is not configured`);
const owner = binding;
const provider = active;
const value = provider[method](...args);
if (value && typeof value.then === 'function')
return value.then((result) => {
if (binding !== owner || active !== provider)
throw new DOMException(`${label} was replaced`, 'AbortError');
return result;
});
return value;
},
]),
);
for (const property of ['label', 'attribution']) {
Object.defineProperty(source, property, {
enumerable: true,
get: () => active?.[property],
});
}
return {
source,
configure(next) {
if (methods.some((method) => typeof next?.[method] !== 'function'))
throw new TypeError(`Invalid ${label.toLowerCase()}`);
const owner = Symbol(label);
active = next;
binding = owner;
return () => {
if (binding !== owner) return;
active = null;
binding = null;
};
},
};
}
// Compatibility entry; source contracts are owned by sources/.
export { createSourceSlot } from '../sources/sourceSlot.js';