Merge pull request #152 from bilawalsidhu/fix/pinokio-install-marker
fix: recognize completed Pinokio setup
This commit is contained in:
commit
53a5f01a79
|
|
@ -7,6 +7,10 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
|
|||
|
||||
### Fixed
|
||||
|
||||
- Pinokio now recognizes its nested successful-install marker, so a completed
|
||||
one-click install exposes Start instead of returning to Install.
|
||||
- The keyless `dev-fresh.sh` startup summary now names Esri World Imagery with
|
||||
keyless terrain and identifies OpenStreetMap as the fallback.
|
||||
- All three VIIRS sources now reach the Active Fires layer. Merging a source's
|
||||
detections used argument spread, which exceeds the engine's argument limit on
|
||||
the two largest sources and dropped them entirely — leaving roughly a third of
|
||||
|
|
|
|||
|
|
@ -2253,6 +2253,10 @@ silently demoting every later lookup for the session.
|
|||
## Auth + Launch
|
||||
|
||||
- Recommended launcher: `./scripts/dev-fresh.sh` (also: `dev-secure.sh` for stricter bindings, `dev-cctv.sh` for CCTV source-pack tuning)
|
||||
- A successful Pinokio install writes the owner-only `pinokio/.installed`
|
||||
marker. The nested launcher menu resolves that marker from its own directory:
|
||||
an absent marker exposes Install, a present marker exposes Start, and a
|
||||
running server with a captured ready URL exposes Open God's Eye View.
|
||||
- Build gate: `npm run build`
|
||||
- Network access: local-only by default (`HOST=localhost` in dev-fresh.sh); LAN is an explicit opt-in via `HOST=0.0.0.0` (launcher prints a key-exposure warning + LAN URL; see SECURITY.md)
|
||||
- OpenSky default mode: OAuth (`OPENSKY_AUTH_MODE=oauth`; `anon` works without credentials)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ module.exports = {
|
|||
version: '3.6',
|
||||
title: "God's Eye View",
|
||||
description: 'A live 3D intelligence console for planet Earth.',
|
||||
menu: async (_kernel, info) => {
|
||||
const installed = info.exists('.installed');
|
||||
menu: async (kernel, info) => {
|
||||
const installed = await kernel.exists(__dirname, '.installed');
|
||||
const installing = info.running('install.js');
|
||||
const starting = info.running('start.js');
|
||||
const updating = info.running('update.js');
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ if [[ -n "${GOOGLE_MAPS_API_KEY}" ]]; then
|
|||
elif [[ -n "${CESIUM_ION_TOKEN}" ]]; then
|
||||
echo "Startup map: Google Photorealistic 3D Tiles (Cesium ion)"
|
||||
else
|
||||
echo "Startup map: OpenStreetMap with keyless terrain"
|
||||
echo "Startup map: Esri World Imagery with keyless terrain (OpenStreetMap fallback)"
|
||||
fi
|
||||
[[ -n "${CESIUM_ION_TOKEN}" ]] && echo "Cesium ion token: configured — Google 3D, Bing, and world-terrain stacks available" || echo "Cesium ion token: not set"
|
||||
[[ -n "${TOMTOM_API_KEY}" ]] && echo "TomTom key (live traffic flow): configured" || echo "TomTom key (live traffic flow): not set — simulated traffic"
|
||||
|
|
|
|||
|
|
@ -80,13 +80,38 @@ test('dev-fresh passes names-only boot provenance before resolving file fallback
|
|||
assert.match(source, /put_env GEV_KEY_SETUP_EXTERNAL_KEYS "\$\{KEY_SETUP_EXTERNAL_KEYS_CSV\}"/);
|
||||
});
|
||||
|
||||
const bashTest = process.platform === 'win32' ? test.skip : test;
|
||||
|
||||
bashTest('dev-fresh reports the real keyless startup map and fallback', async () => {
|
||||
const script = await fs.readFile(new URL('../scripts/dev-fresh.sh', import.meta.url), 'utf8');
|
||||
const start = script.indexOf('if [[ -n "${GOOGLE_MAPS_API_KEY}" ]]; then\n echo "Startup map:');
|
||||
const end = script.indexOf('\nfi', start);
|
||||
assert.ok(start >= 0 && end > start, 'startup-map status block not found in dev-fresh.sh');
|
||||
const block = script.slice(start, end + 3);
|
||||
assert.doesNotMatch(block, /Startup map: OpenStreetMap with keyless terrain/);
|
||||
|
||||
const { execFile } = await import('node:child_process');
|
||||
const { promisify } = await import('node:util');
|
||||
const run = promisify(execFile);
|
||||
const keyless = await run('bash', ['-c', block], {
|
||||
env: {
|
||||
PATH: process.env.PATH,
|
||||
GOOGLE_MAPS_API_KEY: '',
|
||||
CESIUM_ION_TOKEN: '',
|
||||
},
|
||||
});
|
||||
assert.equal(
|
||||
keyless.stdout.trim(),
|
||||
'Startup map: Esri World Imagery with keyless terrain (OpenStreetMap fallback)',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Stock macOS ships bash 3.2, where expanding an EMPTY array under `set -u`
|
||||
// is a fatal "unbound variable" — the `:-` guard on the provenance CSV is what
|
||||
// keeps the keyless `dev-fresh.sh` launch alive there. Newer bash never fails
|
||||
// this way, so the idiom itself is asserted textually and the block's behavior
|
||||
// is exercised for both the keyless and the populated case.
|
||||
const bashTest = process.platform === 'win32' ? test.skip : test;
|
||||
bashTest('the external-keys provenance block survives set -u keyless and joins names when keys are exported', async () => {
|
||||
const script = await fs.readFile(new URL('../scripts/dev-fresh.sh', import.meta.url), 'utf8');
|
||||
const start = script.indexOf('KEY_SETUP_EXTERNAL_KEYS=()');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import { realpathSync } from 'node:fs';
|
||||
import { mkdir, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises';
|
||||
import { access, copyFile, mkdir, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises';
|
||||
import { createRequire } from 'node:module';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
|
@ -62,12 +62,9 @@ test('Pinokio start has one fail-closed launcher process', () => {
|
|||
test('Pinokio install records success explicitly instead of trusting node_modules', async () => {
|
||||
const install = require('../pinokio/install.js');
|
||||
const fs = await import('node:fs/promises');
|
||||
const menuSource = await fs.readFile(new URL('../pinokio/pinokio.js', import.meta.url), 'utf8');
|
||||
const installSource = await fs.readFile(new URL('../scripts/pinokio-install.mjs', import.meta.url), 'utf8');
|
||||
assert.equal(install.run.at(-1).params.message, 'node scripts/pinokio-install.mjs');
|
||||
assert.equal(install.run[0].when, "{{!kernel.exists(cwd, 'ENVIRONMENT')}}");
|
||||
assert.match(menuSource, /info\.exists\('\.installed'\)/);
|
||||
assert.doesNotMatch(menuSource, /exists\('\.\.\/node_modules'\)/);
|
||||
assert.match(installSource, /includeKeychain: false/);
|
||||
assert.match(installSource, /authoritativeEnvironment: true/);
|
||||
assert.match(installSource, /applyPinokioEnvironment\(\)/);
|
||||
|
|
@ -80,6 +77,79 @@ test('Pinokio install records success explicitly instead of trusting node_module
|
|||
}
|
||||
});
|
||||
|
||||
test('Pinokio menu resolves the nested install marker and exposes each lifecycle state', async (t) => {
|
||||
const fixture = await mkdtemp(path.join(os.tmpdir(), 'gev-pinokio-menu-'));
|
||||
t.after(() => rm(fixture, { recursive: true, force: true }));
|
||||
const launcherDir = path.join(fixture, 'app', 'pinokio');
|
||||
const launcherPath = path.join(launcherDir, 'pinokio.js');
|
||||
const markerPath = path.join(launcherDir, '.installed');
|
||||
await mkdir(launcherDir, { recursive: true });
|
||||
await copyFile(new URL('../pinokio/pinokio.js', import.meta.url), launcherPath);
|
||||
|
||||
const existsCalls = [];
|
||||
const kernel = {
|
||||
exists: async (...chunks) => {
|
||||
existsCalls.push(chunks);
|
||||
try {
|
||||
await access(path.resolve(...chunks));
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
const runtime = { running: null, url: null };
|
||||
const info = {
|
||||
exists: () => assert.fail('menu must resolve the marker through kernel.exists'),
|
||||
running: (href) => runtime.running === href,
|
||||
local: () => runtime.url ? { url: runtime.url } : {},
|
||||
};
|
||||
const { menu } = require(launcherPath);
|
||||
const render = async ({ installed, running = null, url = null }) => {
|
||||
if (installed) await writeFile(markerPath, 'ready\n');
|
||||
else await rm(markerPath, { force: true });
|
||||
runtime.running = running;
|
||||
runtime.url = url;
|
||||
const items = await menu(kernel, info);
|
||||
assert.equal(items.filter((item) => item.default).length, 1);
|
||||
return items.map(({ text, href, default: isDefault = false }) => ({ text, href, default: isDefault }));
|
||||
};
|
||||
|
||||
assert.deepEqual(await render({ installed: false }), [
|
||||
{ text: 'Install', href: 'install.js', default: true },
|
||||
]);
|
||||
assert.deepEqual(await render({ installed: true }), [
|
||||
{ text: 'Start', href: 'start.js', default: true },
|
||||
{ text: 'Update', href: 'update.js', default: false },
|
||||
{ text: 'Repair installation', href: 'reset.js', default: false },
|
||||
]);
|
||||
for (const [running, text] of [
|
||||
['install.js', 'Installing'],
|
||||
['update.js', 'Updating'],
|
||||
['reset.js', 'Resetting'],
|
||||
]) {
|
||||
assert.deepEqual(await render({ installed: true, running }), [
|
||||
{ text, href: running, default: true },
|
||||
]);
|
||||
}
|
||||
assert.deepEqual(await render({ installed: true, running: 'start.js' }), [
|
||||
{ text: 'Starting', href: 'start.js', default: true },
|
||||
]);
|
||||
assert.deepEqual(await render({
|
||||
installed: true,
|
||||
running: 'start.js',
|
||||
url: 'http://127.0.0.1:4173/',
|
||||
}), [
|
||||
{ text: "Open God's Eye View", href: 'http://127.0.0.1:4173/', default: true },
|
||||
{ text: 'Server', href: 'start.js', default: false },
|
||||
]);
|
||||
assert.ok(existsCalls.length >= 7);
|
||||
const resolvedLauncherDir = realpathSync(launcherDir);
|
||||
for (const chunks of existsCalls) {
|
||||
assert.deepEqual(chunks, [resolvedLauncherDir, '.installed']);
|
||||
}
|
||||
});
|
||||
|
||||
test('Pinokio install recognizes direct execution through a linked app directory', async (t) => {
|
||||
const fixture = await mkdtemp(path.join(os.tmpdir(), 'gev-pinokio-entry-'));
|
||||
t.after(() => rm(fixture, { recursive: true, force: true }));
|
||||
|
|
|
|||
Loading…
Reference in New Issue