From fb67024f438c1e10dda923d89f829d127b732968 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Fri, 11 Sep 2026 18:08:26 -0700 Subject: [PATCH] style: format standalone configuration and build boundaries --- build/vite.js | 16 ++++++--- docs/CODE-BOUNDARIES.md | 15 ++++----- scripts/check-package-boundaries.mjs | 6 +++- scripts/format-scope.json | 6 +++- scripts/package-boundaries.json | 36 ++++++--------------- src/standalone/application.js | 10 ++++-- src/standalone/tools.js | 4 ++- src/tooling/packageBoundaries.test.mjs | 34 ++++++++++++++----- src/tooling/viteBuild.test.mjs | 45 ++++++++++++++++++++------ 9 files changed, 111 insertions(+), 61 deletions(-) diff --git a/build/vite.js b/build/vite.js index 7cdf1f318..5d990f3a1 100644 --- a/build/vite.js +++ b/build/vite.js @@ -2,16 +2,24 @@ import cesium from 'vite-plugin-cesium'; /** Build browser assets with explicit inputs; never load environment or providers. */ export function createBrowserViteConfig({ - plugins = [], googleApiKey, cesiumToken, host = 'localhost', port = 4173, + plugins = [], + googleApiKey, + cesiumToken, + host = 'localhost', + port = 4173, } = {}) { return { plugins: [cesium(), ...plugins], server: { host: host || 'localhost', port: parseInt(port, 10) || 4173, - allowedHosts: host === '0.0.0.0' || host === '::' - ? true : ['localhost', '127.0.0.1', '.local'], - fs: { deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**', '**/ENVIRONMENT'] }, + allowedHosts: + host === '0.0.0.0' || host === '::' + ? true + : ['localhost', '127.0.0.1', '.local'], + fs: { + deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**', '**/ENVIRONMENT'], + }, // These headers protect the document containing Provider Settings. headers: { 'X-Frame-Options': 'DENY', diff --git a/docs/CODE-BOUNDARIES.md b/docs/CODE-BOUNDARIES.md index 34bea3f10..6970b768d 100644 --- a/docs/CODE-BOUNDARIES.md +++ b/docs/CODE-BOUNDARIES.md @@ -16,13 +16,13 @@ excluded. The formatter validates every entry before writing any file. ## Current component ownership -| Surface | Owns | Receives from its caller | -| --------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------- | -| `gods-eye-view/infrastructure` | Datacenter/dam definitions and fresh layer construction | Context, overlay and render operations | -| `gods-eye-view/infrastructure/geojson` | Data loading, Cesium entities, selection handling and resource cleanup | A viewer and those same operations | -| `gods-eye-view/infrastructure/lod` | Pure visibility budgets and selection policy | Position/visibility records and camera measurements | -| `src/data/localGeojson.js` | Standalone compatibility wiring | The application's existing shared services | -| `src/main.js` and `src/standalone/` | Standalone browser startup | Local configuration | +| Surface | Owns | Receives from its caller | +| -------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------- | +| `gods-eye-view/infrastructure` | Datacenter/dam definitions and fresh layer construction | Context, overlay and render operations | +| `gods-eye-view/infrastructure/geojson` | Data loading, Cesium entities, selection handling and resource cleanup | A viewer and those same operations | +| `gods-eye-view/infrastructure/lod` | Pure visibility budgets and selection policy | Position/visibility records and camera measurements | +| `src/data/localGeojson.js` | Standalone compatibility wiring | The application's existing shared services | +| `src/main.js` and `src/standalone/` | Standalone browser startup | Local configuration | The application and infrastructure exports are browser source modules. Use their documented exports instead of importing standalone startup or reaching into internal files. @@ -54,7 +54,6 @@ Neither export imports standalone UI, layers, tools or configuration. See UI panels and individual source adapters remain future extractions. They should become smaller modules with explicit lifecycle owners as their callers migrate. - ## Build and standalone server configuration `gods-eye-view/build/vite` is a separate Node-only export. `build/vite.js` diff --git a/scripts/check-package-boundaries.mjs b/scripts/check-package-boundaries.mjs index ef36bf858..3655cd998 100644 --- a/scripts/check-package-boundaries.mjs +++ b/scripts/check-package-boundaries.mjs @@ -70,7 +70,11 @@ export async function checkPackageBoundaries(root) { const input = group.exports.map((key) => { const declaration = pkg.exports[key]; const target = node ? declaration?.node : declaration; - if (node && (typeof declaration !== 'object' || Object.keys(declaration).join() !== 'node')) { + if ( + node && + (typeof declaration !== 'object' || + Object.keys(declaration).join() !== 'node') + ) { throw new Error(`Node export must have only a node condition: ${key}`); } if ( diff --git a/scripts/format-scope.json b/scripts/format-scope.json index f52cabecc..5384e0a23 100644 --- a/scripts/format-scope.json +++ b/scripts/format-scope.json @@ -27,5 +27,9 @@ "src/standalone/scene.js", "src/standalone/startupChrome.js", "src/standalone/startupChrome.test.mjs", - "src/standalone/tools.js" + "src/standalone/tools.js", + "build/vite.js", + "server/standalone/vite.config.js", + "vite.config.js", + "src/tooling/viteBuild.test.mjs" ] diff --git a/scripts/package-boundaries.json b/scripts/package-boundaries.json index 3de432d07..cda46b637 100644 --- a/scripts/package-boundaries.json +++ b/scripts/package-boundaries.json @@ -10,40 +10,22 @@ "src/data/localGeojsonCore.js", "src/data/localGeojsonLod.js" ], - "external": [ - "cesium" - ] + "external": ["cesium"] }, "application": { - "exports": [ - "./application" - ], - "modules": [ - "src/app/application.js" - ], + "exports": ["./application"], + "modules": ["src/app/application.js"], "external": [] }, "viewer": { - "exports": [ - "./application/viewer" - ], - "modules": [ - "src/app/viewer.js" - ], - "external": [ - "cesium" - ] + "exports": ["./application/viewer"], + "modules": ["src/app/viewer.js"], + "external": ["cesium"] }, "vite-build": { "runtime": "node", - "exports": [ - "./build/vite" - ], - "modules": [ - "build/vite.js" - ], - "external": [ - "vite-plugin-cesium" - ] + "exports": ["./build/vite"], + "modules": ["build/vite.js"], + "external": ["vite-plugin-cesium"] } } diff --git a/src/standalone/application.js b/src/standalone/application.js index c026173a5..4ae94cde7 100644 --- a/src/standalone/application.js +++ b/src/standalone/application.js @@ -20,11 +20,17 @@ export function createStandaloneApplication({ const loaderStatus = loadingScreen.querySelector('.loader-status'); return createApplication({ createScene: (context) => - createStandaloneScene({ ...context, googleApiKey, cesiumToken, loaderStatus }), + createStandaloneScene({ + ...context, + googleApiKey, + cesiumToken, + loaderStatus, + }), createControls: (context) => createStandaloneControls({ ...context, loaderStatus }), createData: (context) => createStandaloneData({ ...context, allowQaRegistration }), - createTools: (context) => createStandaloneTools({ ...context, loadingScreen }), + createTools: (context) => + createStandaloneTools({ ...context, loadingScreen }), }); } diff --git a/src/standalone/tools.js b/src/standalone/tools.js index 3e506523c..534509448 100644 --- a/src/standalone/tools.js +++ b/src/standalone/tools.js @@ -30,7 +30,9 @@ export function createStandaloneTools({ if (window.__gevAnnotations === annotations) delete window.__gevAnnotations; annotations.destroy(); }); - defer(startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal })); + defer( + startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal }), + ); // Idle render governor: flips the scene into requestRenderMode whenever // nothing animates per frame. Installed AFTER every module above has had // its chance to register pre-install holds. (perf wave 2) diff --git a/src/tooling/packageBoundaries.test.mjs b/src/tooling/packageBoundaries.test.mjs index b98d36d5c..ecb2d3ff8 100644 --- a/src/tooling/packageBoundaries.test.mjs +++ b/src/tooling/packageBoundaries.test.mjs @@ -78,14 +78,32 @@ test('dynamic imports obey the same component ownership rule', async (t) => { test('a Node build export must be explicitly classified and scoped', async (t) => { const root = await fixture(t); - await writeFile(path.join(root, 'package.json'), JSON.stringify({ - name: 'boundary-fixture', type: 'module', exports: { './feature': { node: './entry.js' } }, - })); - await writeFile(path.join(root, 'scripts/package-boundaries.json'), JSON.stringify({ - feature: { runtime: 'node', exports: ['./feature'], modules: ['entry.js'], external: [] }, - })); - assert.deepEqual(await checkPackageBoundaries(root), [{ name: 'feature', exports: 1, modules: 1 }]); - await writeFile(path.join(root, 'entry.js'), "import './startup.js'; export const value = 1;"); + await writeFile( + path.join(root, 'package.json'), + JSON.stringify({ + name: 'boundary-fixture', + type: 'module', + exports: { './feature': { node: './entry.js' } }, + }), + ); + await writeFile( + path.join(root, 'scripts/package-boundaries.json'), + JSON.stringify({ + feature: { + runtime: 'node', + exports: ['./feature'], + modules: ['entry.js'], + external: [], + }, + }), + ); + assert.deepEqual(await checkPackageBoundaries(root), [ + { name: 'feature', exports: 1, modules: 1 }, + ]); + await writeFile( + path.join(root, 'entry.js'), + "import './startup.js'; export const value = 1;", + ); await writeFile(path.join(root, 'startup.js'), 'export const app = 2;'); await assert.rejects(checkPackageBoundaries(root), /unowned module.*startup/); }); diff --git a/src/tooling/viteBuild.test.mjs b/src/tooling/viteBuild.test.mjs index 2896e1093..3754b5650 100644 --- a/src/tooling/viteBuild.test.mjs +++ b/src/tooling/viteBuild.test.mjs @@ -7,21 +7,39 @@ import * as providers from '../../server/providers/local.js'; test('explicit build inputs preserve browser-only defines, plugin order and loopback protections', () => { const plugin = { name: 'fixture-provider' }; - const config = createBrowserViteConfig({ plugins: [plugin], googleApiKey: 'browser-fixture', cesiumToken: 'ion-fixture' }); + const config = createBrowserViteConfig({ + plugins: [plugin], + googleApiKey: 'browser-fixture', + cesiumToken: 'ion-fixture', + }); assert.equal(config.plugins[1], plugin); assert.equal(config.server.host, 'localhost'); assert.equal(config.server.port, 4173); - assert.deepEqual(config.server.allowedHosts, ['localhost', '127.0.0.1', '.local']); + assert.deepEqual(config.server.allowedHosts, [ + 'localhost', + '127.0.0.1', + '.local', + ]); assert.ok(config.server.fs.deny.includes('**/ENVIRONMENT')); assert.ok(config.server.fs.deny.includes('.env.*')); assert.equal(config.server.headers['X-Frame-Options'], 'DENY'); - assert.equal(config.server.headers['Content-Security-Policy'], "frame-ancestors 'none'"); + assert.equal( + config.server.headers['Content-Security-Policy'], + "frame-ancestors 'none'", + ); assert.deepEqual(config.define, { 'import.meta.env.GOOGLE_MAPS_API_KEY': '"browser-fixture"', 'import.meta.env.CESIUM_ION_TOKEN': '"ion-fixture"', }); - assert.equal(createBrowserViteConfig({ host: '0.0.0.0', port: '4800' }).server.allowedHosts, true); - assert.equal(createBrowserViteConfig({ host: '::', port: '4800' }).server.port, 4800); + assert.equal( + createBrowserViteConfig({ host: '0.0.0.0', port: '4800' }).server + .allowedHosts, + true, + ); + assert.equal( + createBrowserViteConfig({ host: '::', port: '4800' }).server.port, + 4800, + ); }); test('build helper does not discover environment values or construct local providers', () => { @@ -29,7 +47,10 @@ test('build helper does not discover environment values or construct local provi process.env.GOOGLE_MAPS_API_KEY = 'environment-fixture'; try { const config = createBrowserViteConfig(); - assert.equal(config.define['import.meta.env.GOOGLE_MAPS_API_KEY'], undefined); + assert.equal( + config.define['import.meta.env.GOOGLE_MAPS_API_KEY'], + undefined, + ); assert.equal(config.plugins.length, 1); } finally { if (before === undefined) delete process.env.GOOGLE_MAPS_API_KEY; @@ -38,15 +59,21 @@ test('build helper does not discover environment values or construct local provi }); test('root config retains existing named exports and standalone provider order', () => { - for (const [name, value] of Object.entries(providers)) assert.equal(compatibility[name], value, name); + for (const [name, value] of Object.entries(providers)) + assert.equal(compatibility[name], value, name); const config = standaloneConfig({ mode: 'test' }); - assert.deepEqual(config.plugins.slice(1).map((plugin) => plugin.name), providers.localProviderPlugins().map((plugin) => plugin.name)); + assert.deepEqual( + config.plugins.slice(1).map((plugin) => plugin.name), + providers.localProviderPlugins().map((plugin) => plugin.name), + ); assert.equal(config.plugins.at(-1).name, 'gev-key-setup'); }); test('build export resolves in Node and has no browser fallback', async () => { const exported = await import('gods-eye-view/build/vite'); assert.equal(exported.createBrowserViteConfig, createBrowserViteConfig); - const pkg = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url))); + const pkg = JSON.parse( + readFileSync(new URL('../../package.json', import.meta.url)), + ); assert.deepEqual(pkg.exports['./build/vite'], { node: './build/vite.js' }); });