Merge branch 'main' into feat/aqhi

Port to current main: main reserved layer-state token 0 for street-level, so
air-quality takes the next free token, 4 (registry, ledger, and the allocation
tests shift by one). Main moved source contracts into sourceComposition.js, so
air-quality registers its getSnapshot contract there. Package boundaries keep
main's lists plus this branch's air-quality modules and packages.
This commit is contained in:
Sameh Khamis committed 2026-10-15 12:39:00 -07:00
commit 046126eb36
675 files changed
+102751 -4110

No files matched your search

+54 -2
View File
@@ -5,6 +5,7 @@ import { createApplicationCatalog } from './constructCatalog.js';
import { createStandaloneLayerSources } from '../standalone/layerSources.js';
import { catalogControlServices } from './catalog.js';
import { LayerLifecycle } from '../data/lifecycle.js';
import { fakeStreetLevelProvider } from '../testSupport/streetLevelFakes.mjs';
function fixtureSources(ids, calls) {
const sources = createStandaloneLayerSources();
@@ -39,7 +40,7 @@ test('catalogs construct distinct layers and classification from their supplied
signal: b.signal,
surface: fixtureSurface(b.signal),
});
assert.equal(first.layers.length, 30);
assert.equal(first.layers.length, 32);
assert.ok(first.get('local-adsb'), 'Local ADS-B is registered');
assert.deepEqual(
first.metadata.find(({ id }) => id === 'local-adsb'),
@@ -59,6 +60,7 @@ test('catalogs construct distinct layers and classification from their supplied
'2026-09-21T12:00:00.000Z',
);
assert.ok(first.get('fire-perimeters'));
assert.ok(first.get('gnss-integrity'));
assert.ok(first.get('transit'));
const order = first.layers.map(({ id }) => id);
assert.deepEqual(
@@ -116,7 +118,7 @@ test('invalid or already cancelled construction fails before classification can
assert.throws(
() =>
createApplicationCatalog({
sources: {},
sources: { flights: {} },
signal: lifetime.signal,
surface: fixtureSurface(lifetime.signal),
}),
@@ -140,3 +142,53 @@ function fixtureSurface(signal) {
eventTarget: null,
});
}
test('Mapillary can be omitted or replaced without changing catalog membership', (t) => {
const lifetime = new AbortController();
t.after(() => lifetime.abort());
const sources = fixtureSources([], []);
delete sources.mapillary;
const options = {
sources,
signal: lifetime.signal,
surface: fixtureSurface(lifetime.signal),
};
const catalog = createApplicationCatalog(options);
assert.equal(catalog.layers.length, 32);
assert.deepEqual(catalog.get('street-level').providerIds, []);
assert.equal(
catalogControlServices(catalog).streetLevelLayer,
catalog.get('street-level'),
);
assert.match(
catalog.get('street-level').getUIState().coverage.hint,
/No street-level imagery providers/,
);
const provider = fakeStreetLevelProvider({
id: 'example',
pickPrefix: 'example:',
});
const replacement = createApplicationCatalog({
...options,
streetLevelProviders: [provider],
});
assert.deepEqual(replacement.get('street-level').providerIds, ['example']);
assert.deepEqual(replacement.metadata, catalog.metadata);
assert.equal(provider.calls.activate, 0, 'construction must not acquire');
assert.deepEqual(
createApplicationCatalog({
...options,
sources: fixtureSources([], []),
streetLevelProviders: [],
}).get('street-level').providerIds,
[],
);
assert.throws(
() =>
createApplicationCatalog({
...options,
sources: { ...sources, mapillary: {} },
}),
/Mapillary source/,
);
});