mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
style: format standalone configuration and build boundaries
This commit is contained in:
1 parent
8de1018c21
commit
fb67024f43
9 files changed
+111
-61
No files matched your search
+12
-4
@@ -2,16 +2,24 @@ import cesium from 'vite-plugin-cesium';
|
|||||||
|
|
||||||
/** Build browser assets with explicit inputs; never load environment or providers. */
|
/** Build browser assets with explicit inputs; never load environment or providers. */
|
||||||
export function createBrowserViteConfig({
|
export function createBrowserViteConfig({
|
||||||
plugins = [], googleApiKey, cesiumToken, host = 'localhost', port = 4173,
|
plugins = [],
|
||||||
|
googleApiKey,
|
||||||
|
cesiumToken,
|
||||||
|
host = 'localhost',
|
||||||
|
port = 4173,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return {
|
return {
|
||||||
plugins: [cesium(), ...plugins],
|
plugins: [cesium(), ...plugins],
|
||||||
server: {
|
server: {
|
||||||
host: host || 'localhost',
|
host: host || 'localhost',
|
||||||
port: parseInt(port, 10) || 4173,
|
port: parseInt(port, 10) || 4173,
|
||||||
allowedHosts: host === '0.0.0.0' || host === '::'
|
allowedHosts:
|
||||||
? true : ['localhost', '127.0.0.1', '.local'],
|
host === '0.0.0.0' || host === '::'
|
||||||
fs: { deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**', '**/ENVIRONMENT'] },
|
? true
|
||||||
|
: ['localhost', '127.0.0.1', '.local'],
|
||||||
|
fs: {
|
||||||
|
deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**', '**/ENVIRONMENT'],
|
||||||
|
},
|
||||||
// These headers protect the document containing Provider Settings.
|
// These headers protect the document containing Provider Settings.
|
||||||
headers: {
|
headers: {
|
||||||
'X-Frame-Options': 'DENY',
|
'X-Frame-Options': 'DENY',
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ excluded. The formatter validates every entry before writing any file.
|
|||||||
|
|
||||||
## Current component ownership
|
## Current component ownership
|
||||||
|
|
||||||
| Surface | Owns | Receives from its caller |
|
| 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` | 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/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 |
|
| `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/data/localGeojson.js` | Standalone compatibility wiring | The application's existing shared services |
|
||||||
| `src/main.js` and `src/standalone/` | Standalone browser startup | Local configuration |
|
| `src/main.js` and `src/standalone/` | Standalone browser startup | Local configuration |
|
||||||
|
|
||||||
The application and infrastructure exports are browser source modules. Use their documented
|
The application and infrastructure exports are browser source modules. Use their documented
|
||||||
exports instead of importing standalone startup or reaching into internal files.
|
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
|
UI panels and individual source adapters remain future extractions. They should
|
||||||
become smaller modules with explicit lifecycle owners as their callers migrate.
|
become smaller modules with explicit lifecycle owners as their callers migrate.
|
||||||
|
|
||||||
|
|
||||||
## Build and standalone server configuration
|
## Build and standalone server configuration
|
||||||
|
|
||||||
`gods-eye-view/build/vite` is a separate Node-only export. `build/vite.js`
|
`gods-eye-view/build/vite` is a separate Node-only export. `build/vite.js`
|
||||||
|
|||||||
@@ -70,7 +70,11 @@ export async function checkPackageBoundaries(root) {
|
|||||||
const input = group.exports.map((key) => {
|
const input = group.exports.map((key) => {
|
||||||
const declaration = pkg.exports[key];
|
const declaration = pkg.exports[key];
|
||||||
const target = node ? declaration?.node : declaration;
|
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}`);
|
throw new Error(`Node export must have only a node condition: ${key}`);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -27,5 +27,9 @@
|
|||||||
"src/standalone/scene.js",
|
"src/standalone/scene.js",
|
||||||
"src/standalone/startupChrome.js",
|
"src/standalone/startupChrome.js",
|
||||||
"src/standalone/startupChrome.test.mjs",
|
"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"
|
||||||
]
|
]
|
||||||
@@ -10,40 +10,22 @@
|
|||||||
"src/data/localGeojsonCore.js",
|
"src/data/localGeojsonCore.js",
|
||||||
"src/data/localGeojsonLod.js"
|
"src/data/localGeojsonLod.js"
|
||||||
],
|
],
|
||||||
"external": [
|
"external": ["cesium"]
|
||||||
"cesium"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"exports": [
|
"exports": ["./application"],
|
||||||
"./application"
|
"modules": ["src/app/application.js"],
|
||||||
],
|
|
||||||
"modules": [
|
|
||||||
"src/app/application.js"
|
|
||||||
],
|
|
||||||
"external": []
|
"external": []
|
||||||
},
|
},
|
||||||
"viewer": {
|
"viewer": {
|
||||||
"exports": [
|
"exports": ["./application/viewer"],
|
||||||
"./application/viewer"
|
"modules": ["src/app/viewer.js"],
|
||||||
],
|
"external": ["cesium"]
|
||||||
"modules": [
|
|
||||||
"src/app/viewer.js"
|
|
||||||
],
|
|
||||||
"external": [
|
|
||||||
"cesium"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"vite-build": {
|
"vite-build": {
|
||||||
"runtime": "node",
|
"runtime": "node",
|
||||||
"exports": [
|
"exports": ["./build/vite"],
|
||||||
"./build/vite"
|
"modules": ["build/vite.js"],
|
||||||
],
|
"external": ["vite-plugin-cesium"]
|
||||||
"modules": [
|
|
||||||
"build/vite.js"
|
|
||||||
],
|
|
||||||
"external": [
|
|
||||||
"vite-plugin-cesium"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,11 +20,17 @@ export function createStandaloneApplication({
|
|||||||
const loaderStatus = loadingScreen.querySelector('.loader-status');
|
const loaderStatus = loadingScreen.querySelector('.loader-status');
|
||||||
return createApplication({
|
return createApplication({
|
||||||
createScene: (context) =>
|
createScene: (context) =>
|
||||||
createStandaloneScene({ ...context, googleApiKey, cesiumToken, loaderStatus }),
|
createStandaloneScene({
|
||||||
|
...context,
|
||||||
|
googleApiKey,
|
||||||
|
cesiumToken,
|
||||||
|
loaderStatus,
|
||||||
|
}),
|
||||||
createControls: (context) =>
|
createControls: (context) =>
|
||||||
createStandaloneControls({ ...context, loaderStatus }),
|
createStandaloneControls({ ...context, loaderStatus }),
|
||||||
createData: (context) =>
|
createData: (context) =>
|
||||||
createStandaloneData({ ...context, allowQaRegistration }),
|
createStandaloneData({ ...context, allowQaRegistration }),
|
||||||
createTools: (context) => createStandaloneTools({ ...context, loadingScreen }),
|
createTools: (context) =>
|
||||||
|
createStandaloneTools({ ...context, loadingScreen }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,9 @@ export function createStandaloneTools({
|
|||||||
if (window.__gevAnnotations === annotations) delete window.__gevAnnotations;
|
if (window.__gevAnnotations === annotations) delete window.__gevAnnotations;
|
||||||
annotations.destroy();
|
annotations.destroy();
|
||||||
});
|
});
|
||||||
defer(startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal }));
|
defer(
|
||||||
|
startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal }),
|
||||||
|
);
|
||||||
// Idle render governor: flips the scene into requestRenderMode whenever
|
// Idle render governor: flips the scene into requestRenderMode whenever
|
||||||
// nothing animates per frame. Installed AFTER every module above has had
|
// nothing animates per frame. Installed AFTER every module above has had
|
||||||
// its chance to register pre-install holds. (perf wave 2)
|
// its chance to register pre-install holds. (perf wave 2)
|
||||||
|
|||||||
@@ -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) => {
|
test('a Node build export must be explicitly classified and scoped', async (t) => {
|
||||||
const root = await fixture(t);
|
const root = await fixture(t);
|
||||||
await writeFile(path.join(root, 'package.json'), JSON.stringify({
|
await writeFile(
|
||||||
name: 'boundary-fixture', type: 'module', exports: { './feature': { node: './entry.js' } },
|
path.join(root, 'package.json'),
|
||||||
}));
|
JSON.stringify({
|
||||||
await writeFile(path.join(root, 'scripts/package-boundaries.json'), JSON.stringify({
|
name: 'boundary-fixture',
|
||||||
feature: { runtime: 'node', exports: ['./feature'], modules: ['entry.js'], external: [] },
|
type: 'module',
|
||||||
}));
|
exports: { './feature': { node: './entry.js' } },
|
||||||
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, '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 writeFile(path.join(root, 'startup.js'), 'export const app = 2;');
|
||||||
await assert.rejects(checkPackageBoundaries(root), /unowned module.*startup/);
|
await assert.rejects(checkPackageBoundaries(root), /unowned module.*startup/);
|
||||||
});
|
});
|
||||||
@@ -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', () => {
|
test('explicit build inputs preserve browser-only defines, plugin order and loopback protections', () => {
|
||||||
const plugin = { name: 'fixture-provider' };
|
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.plugins[1], plugin);
|
||||||
assert.equal(config.server.host, 'localhost');
|
assert.equal(config.server.host, 'localhost');
|
||||||
assert.equal(config.server.port, 4173);
|
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('**/ENVIRONMENT'));
|
||||||
assert.ok(config.server.fs.deny.includes('.env.*'));
|
assert.ok(config.server.fs.deny.includes('.env.*'));
|
||||||
assert.equal(config.server.headers['X-Frame-Options'], 'DENY');
|
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, {
|
assert.deepEqual(config.define, {
|
||||||
'import.meta.env.GOOGLE_MAPS_API_KEY': '"browser-fixture"',
|
'import.meta.env.GOOGLE_MAPS_API_KEY': '"browser-fixture"',
|
||||||
'import.meta.env.CESIUM_ION_TOKEN': '"ion-fixture"',
|
'import.meta.env.CESIUM_ION_TOKEN': '"ion-fixture"',
|
||||||
});
|
});
|
||||||
assert.equal(createBrowserViteConfig({ host: '0.0.0.0', port: '4800' }).server.allowedHosts, true);
|
assert.equal(
|
||||||
assert.equal(createBrowserViteConfig({ host: '::', port: '4800' }).server.port, 4800);
|
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', () => {
|
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';
|
process.env.GOOGLE_MAPS_API_KEY = 'environment-fixture';
|
||||||
try {
|
try {
|
||||||
const config = createBrowserViteConfig();
|
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);
|
assert.equal(config.plugins.length, 1);
|
||||||
} finally {
|
} finally {
|
||||||
if (before === undefined) delete process.env.GOOGLE_MAPS_API_KEY;
|
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', () => {
|
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' });
|
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');
|
assert.equal(config.plugins.at(-1).name, 'gev-key-setup');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('build export resolves in Node and has no browser fallback', async () => {
|
test('build export resolves in Node and has no browser fallback', async () => {
|
||||||
const exported = await import('gods-eye-view/build/vite');
|
const exported = await import('gods-eye-view/build/vite');
|
||||||
assert.equal(exported.createBrowserViteConfig, createBrowserViteConfig);
|
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' });
|
assert.deepEqual(pkg.exports['./build/vite'], { node: './build/vite.js' });
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user