fix: simplify Google Maps provider setup

This commit is contained in:
Sameh Khamis committed 2026-09-12 11:36:23 -07:00
1 parent aacfa06a31
commit c6462be066
5 files changed
+30 -13

No files matched your search

+4
View File
@@ -13,6 +13,10 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
## [Unreleased]
- Simplify POWER UP to one Google Maps entry. Keep the optional server key
available through environment configuration without a second setup row or
missing-key reminder.
- Separate terrain, traffic, FIRMS and GBFS middleware into focused provider
modules, preserving local configuration, routes and cache/error behavior.
+2 -1
View File
@@ -51,7 +51,8 @@ Terminal development uses one ignored repository-root `.env` for both
`GOOGLE_MAPS_API_KEY` (browser) and `GOOGLE_MAPS_SERVER_API_KEY` (server).
The tracked `.env.example` documents both without credentials. Vite injects
only the browser key; sharing an environment file does not expose the server
key. Both entries are available in Provider Settings. Pinokio saves them in
key. Provider Settings presents only the browser key as Google Maps; configure
the optional server key manually in the environment file. Pinokio uses
its ignored `pinokio/ENVIRONMENT` instead, with app values and blanks taking
precedence over inherited global values. An absent server key retains the
browser-key fallback for existing single-key setups.
+5 -3
View File
@@ -75,9 +75,11 @@ See [component ownership and adoption](CODE-BOUNDARIES.md).
Local Places nearby/text search and the CCTV Street View fallback prefer
`GOOGLE_MAPS_SERVER_API_KEY`, falling back to `GOOGLE_MAPS_API_KEY` when the
server key is blank or absent. Only the browser key is injected into client
code. Both are optional and configured in the same ignored root `.env`, or
Pinokio's ignored `pinokio/ENVIRONMENT`, through Provider Settings or manual
editing. `.env.example` and `pinokio/_ENVIRONMENT` document the two entries.
code. POWER UP presents one Google Maps entry for the browser key. The optional
server key is configured manually in the same ignored root `.env`, or Pinokio's
ignored `pinokio/ENVIRONMENT`; it is omitted from Provider Settings and its
missing-key count. Existing server keys and the single-key fallback remain
supported. `.env.example` and `pinokio/_ENVIRONMENT` document both entries.
The Street View headings tool uses the same server-first selection after
resolving environment overrides per variable; its explicit `--key` wins.
+6 -4
View File
@@ -21,16 +21,17 @@ export const KEY_SETUP_UPDATE_LIMIT = 16;
export const KEY_SETUP_APPEND_HEADER = '# Keys added by the in-app POWER UP panel';
/**
* Every key the panel offers, in the order it offers them — most magic per
* Provider credentials, in display order — most magic per
* minute first. `tier` mirrors the README's color legend: 'metered' (🔴) is a
* billing-enabled account, 'free' (🟡) is a register-and-paste key.
* `clientExposed` marks the two keys that are injected into the browser
* bundle by design (restrict them at the provider, per SECURITY.md).
* `hidden` keeps advanced configuration out of the panel and missing-key count.
*/
export const KEY_SETUP_KEYS = Object.freeze([
Object.freeze({
id: 'google-maps',
title: 'GOOGLE MAPS — BROWSER',
title: 'GOOGLE MAPS',
unlocks: 'The photorealistic 3D planet + place search',
getUrl: 'https://developers.google.com/maps/documentation/tile/get-api-key',
envVars: Object.freeze(['GOOGLE_MAPS_API_KEY']),
@@ -44,6 +45,7 @@ export const KEY_SETUP_KEYS = Object.freeze([
getUrl: 'https://developers.google.com/maps/documentation/places/web-service/get-api-key',
envVars: Object.freeze(['GOOGLE_MAPS_SERVER_API_KEY']),
tier: 'metered',
hidden: true,
}),
Object.freeze({
id: 'openai',
@@ -274,7 +276,7 @@ export function knownKeySetupEnvVars() {
/** Tooltip guidance for a control gated by one registry entry. */
export function keySetupRequirement(id) {
const entry = KEY_SETUP_KEYS.find((candidate) => candidate.id === id);
if (!entry) return '';
if (!entry || entry.hidden) return '';
return `Needs ${entry.envVars.join(' + ')} — add it in Provider Settings`;
}
@@ -303,7 +305,7 @@ export function isKeySetupExternallyManaged({
* @param {Record<string, string|undefined>} env e.g. process.env
*/
export function keySetupStatus(env = {}) {
const keys = KEY_SETUP_KEYS.map((entry) => {
const keys = KEY_SETUP_KEYS.filter((entry) => !entry.hidden).map((entry) => {
const values = entry.envVars.map((name) => String(env[name] ?? '').trim());
const set = values.every((value) => value.length > 0);
return {
+13 -5
View File
@@ -63,7 +63,7 @@ test('the status payload reports presence without any credential material', () =
// Secret missing: the OpenSky pair must read as NOT set.
};
const status = keySetupStatus(env);
assert.equal(status.total, KEY_SETUP_KEYS.length);
assert.equal(status.total, KEY_SETUP_KEYS.filter((key) => !key.hidden).length);
const google = status.keys.find((key) => key.id === 'google-maps');
assert.equal(google.set, true);
const opensky = status.keys.find((key) => key.id === 'opensky');
@@ -342,15 +342,23 @@ test('validation rejects dotenv metacharacters that would round-trip wrong', ()
}
});
test('server Google key can be saved and removed without appearing in status values', () => {
test('server Google key remains supported without appearing in setup or its missing count', () => {
const secret = 'server-key-fixture';
assert.deepEqual(validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: secret }), {
ok: true, updates: { GOOGLE_MAPS_SERVER_API_KEY: secret },
});
assert.equal(validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: null }).ok, true);
const status = keySetupStatus({ GOOGLE_MAPS_SERVER_API_KEY: secret });
const entry = status.keys.find((key) => key.id === 'google-maps-server');
assert.equal(entry.set, true);
assert.ok(!entry.clientExposed);
assert.deepEqual(status, keySetupStatus({}));
assert.equal(status.keys.some((key) => key.id === 'google-maps-server'), false);
assert.equal(keySetupRequirement('google-maps-server'), '');
assert.equal(status.keys.find((key) => key.id === 'google-maps').title, 'GOOGLE MAPS');
const allVisibleConfigured = Object.fromEntries(status.keys.flatMap((key) =>
key.envVars.map((name) => [name, 'configured-fixture']),
));
const complete = keySetupStatus(allVisibleConfigured);
assert.equal(complete.setCount, complete.total, 'an absent server key must not leave setup incomplete');
assert.deepEqual(complete, keySetupStatus({ ...allVisibleConfigured, GOOGLE_MAPS_SERVER_API_KEY: secret }));
assert.ok(!JSON.stringify(status).includes('GOOGLE_MAPS_SERVER_API_KEY'));
assert.ok(!JSON.stringify(status).includes(secret));
});