mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
2fded7bc79
Lets the operator pick between strict JSON (legacy) and JSON5 for every configuration file consumed by Nitro and the renderer. - scripts/configure-json.mjs: interactive prompt (JSON5 recommended), with --if-missing and --non-interactive flags for CI use - package.json: yarn configure / prestart / prebuild hooks - vite.config.mjs: reads .nitro-build.json (or NITRO_JSON_MODE env) and injects the compile-time constant __NITRO_JSON_MODE__ via define - src/bootstrap.ts: routes client-mode.json parsing through the selected mode - .gitignore: ignore the per-deployment .nitro-build.json - README: full usage and override section - public/configuration assets regenerated by the updated prebuild flow The renderer side (@nitrots/utils JsonParser) is updated in the companion Nitro_Render_V3 commit on the dev branch.
151 lines
4.1 KiB
TypeScript
151 lines
4.1 KiB
TypeScript
import JSON5 from 'json5';
|
|
import { configFileUrl, getClientMode, installSecureFetch } from './secure-assets';
|
|
|
|
declare const __NITRO_JSON_MODE__: 'legacy' | 'json5' | 'auto' | undefined;
|
|
|
|
const resolveJsonMode = (): 'legacy' | 'json5' | 'auto' =>
|
|
{
|
|
try
|
|
{
|
|
if(typeof __NITRO_JSON_MODE__ !== 'undefined' && __NITRO_JSON_MODE__)
|
|
{
|
|
if(__NITRO_JSON_MODE__ === 'legacy' || __NITRO_JSON_MODE__ === 'json5' || __NITRO_JSON_MODE__ === 'auto') return __NITRO_JSON_MODE__;
|
|
}
|
|
}
|
|
catch {}
|
|
|
|
return 'auto';
|
|
};
|
|
|
|
const ensureMobileViewport = () =>
|
|
{
|
|
let viewport = document.querySelector<HTMLMetaElement>('meta[name="viewport"]');
|
|
|
|
if(!viewport)
|
|
{
|
|
viewport = document.createElement('meta');
|
|
viewport.name = 'viewport';
|
|
document.head.appendChild(viewport);
|
|
}
|
|
|
|
viewport.content = 'width=device-width, initial-scale=1, viewport-fit=cover';
|
|
};
|
|
|
|
ensureMobileViewport();
|
|
installSecureFetch();
|
|
|
|
const setBootDebug = (message: string) =>
|
|
{
|
|
try
|
|
{
|
|
(window as any).__nitroBootDebug = message;
|
|
const secureNode = document.getElementById('nitro-secure-debug');
|
|
|
|
if(secureNode) secureNode.textContent = `${ secureNode.textContent }\n${ message }`;
|
|
}
|
|
catch {}
|
|
};
|
|
|
|
setBootDebug('boot: secure fetch installed');
|
|
|
|
const deployBaseUrl = (): string =>
|
|
{
|
|
try
|
|
{
|
|
const loaderBase = (window as any).__nitroLoaderBase;
|
|
if(typeof loaderBase === 'string' && loaderBase.length) return new URL('..', loaderBase).toString();
|
|
}
|
|
catch {}
|
|
|
|
try
|
|
{
|
|
const moduleUrl = (import.meta as any).url;
|
|
if(typeof moduleUrl === 'string' && moduleUrl.length) return new URL('..', new URL('.', moduleUrl)).toString();
|
|
}
|
|
catch {}
|
|
|
|
try
|
|
{
|
|
const base = (import.meta as any).env?.BASE_URL;
|
|
if(typeof base === 'string' && base.length)
|
|
{
|
|
const trimmed = base.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
return trimmed ? `${ window.location.origin }/${ trimmed }/` : `${ window.location.origin }/`;
|
|
}
|
|
}
|
|
catch {}
|
|
|
|
return `${ window.location.origin }/`;
|
|
};
|
|
|
|
const loadClientMode = async () =>
|
|
{
|
|
try
|
|
{
|
|
if((window as any).__nitroClientMode) return;
|
|
|
|
const url = new URL('configuration/client-mode.json', deployBaseUrl());
|
|
url.searchParams.set('v', Date.now().toString(36));
|
|
|
|
const response = await fetch(url.toString());
|
|
|
|
if(!response.ok) throw new Error(`HTTP ${ response.status }`);
|
|
|
|
const text = await response.text();
|
|
const mode = resolveJsonMode();
|
|
|
|
if(mode === 'legacy')
|
|
{
|
|
(window as any).__nitroClientMode = JSON.parse(text);
|
|
}
|
|
else if(mode === 'json5')
|
|
{
|
|
(window as any).__nitroClientMode = JSON5.parse(text);
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
(window as any).__nitroClientMode = JSON.parse(text);
|
|
}
|
|
catch
|
|
{
|
|
(window as any).__nitroClientMode = JSON5.parse(text);
|
|
}
|
|
}
|
|
setBootDebug(`boot: client-mode loaded (mode=${ mode })`);
|
|
}
|
|
catch(error)
|
|
{
|
|
setBootDebug(`boot: client-mode fallback ${ error?.message || error }`);
|
|
}
|
|
};
|
|
|
|
await loadClientMode();
|
|
|
|
const search = new URLSearchParams(window.location.search);
|
|
const clientMode = getClientMode();
|
|
|
|
(window as any).NitroSecureApiUrl = clientMode.apiBaseUrl || window.location.origin;
|
|
(window as any).NitroClientMode = clientMode;
|
|
(window as any).NitroConfig = {
|
|
'config.urls': [
|
|
configFileUrl('renderer-config.json', true),
|
|
configFileUrl('ui-config.json', true)
|
|
],
|
|
'sso.ticket': search.get('sso') || null,
|
|
'forward.type': search.get('room') ? 2 : -1,
|
|
'forward.id': search.get('room') || 0,
|
|
'friend.id': search.get('friend') || 0
|
|
};
|
|
|
|
setBootDebug('boot: NitroConfig assigned');
|
|
|
|
import('./index')
|
|
.then(() => setBootDebug('boot: app bundle imported'))
|
|
.catch(error =>
|
|
{
|
|
setBootDebug(`boot: import failed ${ error?.message || error }`);
|
|
throw error;
|
|
});
|