telefunc
Version:
Remote functions. Instead of API.
81 lines (80 loc) • 4.24 kB
JavaScript
export { loadTelefuncFilesUsingVite };
import { importServerProductionEntry } from '@brillout/vite-plugin-server-entry/runtime';
import { assert, assertWarning, getNodeEnv, hasProp, isObject, isProduction, isTelefuncFilePath } from '../utils.js';
import { loadTelefuncFilesWithImportBuild } from './loadTelefuncFilesUsingVite/loadBuildEntry.js';
import { getViteDevServer } from '../globalContext.js';
import { VIRTUAL_FILE_ENTRY_ID } from '../../vite/plugins/pluginVirtualFileEntry/VIRTUAL_FILE_ENTRY_ID.js';
async function loadTelefuncFilesUsingVite(runContext, failOnFailure) {
const res = await loadVirtualFile(failOnFailure);
if (!res)
return null;
const { moduleExports, viteProvider } = res;
assert(isObject(moduleExports), { moduleExports, viteProvider });
assert(hasProp(moduleExports, 'telefuncFilesGlob'), { moduleExports, viteProvider });
const telefuncFilesGlob = moduleExports.telefuncFilesGlob;
const { telefuncFilesLoaded, telefuncFilesAll } = await loadViteGlobbedFiles(telefuncFilesGlob, runContext);
assert(isObjectOfObjects(telefuncFilesLoaded));
return { telefuncFilesLoaded, viteProvider, telefuncFilesAll };
}
async function loadVirtualFile(failOnFailure) {
if (globalThis.__TELEFUNC__IS_NON_RUNNABLE_DEV) {
// We don't directly use import() because:
// - Avoid Cloudflare Workers (without @cloudflare/vite-plugin) to try to bundle `import('virtual:id')`.
// - Using import() seems to lead to a Vite HMR bug:
// ```js
// assert(false)
// // This line breaks the HMR of regular (runnable) apps, even though (as per the assert() above) it's never run. It seems to be a Vite bug: handleHotUpdate() receives an empty `modules` list.
// import('virtual:vike:global-entry:server')
// ```
const moduleExports = await __TELEFUNC__DYNAMIC_IMPORT('virtual:vite:telefunc:entry');
return { moduleExports, viteProvider: 'Vite with `import()`' };
}
const viteDevServer = getViteDevServer();
if (viteDevServer) {
const moduleExports = await viteDevServer.ssrLoadModule(VIRTUAL_FILE_ENTRY_ID, { fixStacktrace: true });
return { moduleExports, viteProvider: 'Vite with `ssrLoadModule()`' };
}
else {
let moduleExports;
moduleExports = await loadTelefuncFilesWithImportBuild();
if (moduleExports === null) {
const tolerateDoesNotExist = !failOnFailure;
const success = await importServerProductionEntry({ tolerateDoesNotExist });
moduleExports = await loadTelefuncFilesWithImportBuild();
if (success === false) {
assert(tolerateDoesNotExist);
assert(!moduleExports);
return null;
}
assert(moduleExports);
}
else {
assert(moduleExports);
}
assertProd();
return { moduleExports, viteProvider: 'Vite with `@brillout/vite-plugin-server-entry`' };
}
}
function assertProd() {
if (!isProduction()) {
const env = getNodeEnv();
assert(env === undefined || env === 'development' || env === '');
assertWarning(false, `This seems to be a production environment yet process.env.NODE_ENV is ${JSON.stringify(env)}. Set it to a different value such as "production" or "staging".`, { onlyOnce: true });
}
}
function isObjectOfObjects(obj) {
return isObject(obj) && Object.values(obj).every(isObject);
}
// Vite's import.meta.glob() returns promises
async function loadViteGlobbedFiles(telefuncFilesGlob, runContext) {
const telefuncFilesAll = Object.keys(telefuncFilesGlob);
const telefuncFilesLoaded = Object.fromEntries(await Promise.all(Object.entries(telefuncFilesGlob)
.filter(([telefuncFilePath]) => {
assert(isTelefuncFilePath(telefuncFilePath));
assert(isTelefuncFilePath(runContext.telefuncFilePath));
return telefuncFilePath === runContext.telefuncFilePath;
})
.map(async ([telefuncFilePath, loadModuleExports]) => [telefuncFilePath, await loadModuleExports()])));
assert(Object.keys(telefuncFilesLoaded).length <= 1);
return { telefuncFilesAll, telefuncFilesLoaded };
}