one
Version:
One is a new React Framework that makes Vite serve both native and web.
245 lines (238 loc) • 10.3 kB
JavaScript
import { resolve } from "path";
import { pathToFileURL } from "url";
import { configuration } from "@vxrn/compiler";
import micromatch from "micromatch";
import { isNativeEnvironment } from "vxrn";
import { API_ROUTE_GLOB_PATTERN, ROUTE_GLOB_PATTERN, ROUTE_NATIVE_EXCLUSION_GLOB_PATTERNS, ROUTE_WEB_EXCLUSION_GLOB_PATTERNS } from "../../router/glob-patterns.native.js";
import { matchDirectoryRenderMode, matchFileRenderMode } from "../../router/matchers.native.js";
import { resolvedVirtualEntryId, resolvedVirtualEntryIdNative, virtualEntryId, virtualEntryIdNative } from "./virtualEntryConstants.native.js";
var escapeRe = function (s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
};
var VIRTUAL_ENTRY_SOURCE_RE = new RegExp(`^(?:${escapeRe(virtualEntryId)}|${escapeRe(virtualEntryIdNative)})$`);
var VIRTUAL_ENTRY_RESOLVED_RE = new RegExp(`^(?:${escapeRe(resolvedVirtualEntryId)}|${escapeRe(resolvedVirtualEntryIdNative)})$`);
function normalizeSetupFile(setupFile) {
if (!setupFile) return {};
if (typeof setupFile === "string") {
return {
client: setupFile,
server: setupFile,
ios: setupFile,
android: setupFile
};
}
if ("native" in setupFile) {
return {
client: setupFile.client,
server: setupFile.server,
ios: setupFile.native,
android: setupFile.native
};
}
var sf = setupFile;
return {
client: sf.client,
server: sf.server,
ios: sf.ios,
android: sf.android
};
}
function getSetupFileImport(environmentName, setupFiles, useStaticImport, root) {
var envMap = {
client: "client",
ssr: "server",
ios: "ios",
android: "android"
};
var key = envMap[environmentName];
if (!key) return {
importStatement: "",
promiseDeclaration: "",
promiseVarName: ""
};
var setupFile = setupFiles[key];
if (!setupFile) return {
importStatement: "",
promiseDeclaration: "",
promiseVarName: ""
};
var resolvedSetupFile = root ? pathToFileURL(resolve(root, setupFile)).href : setupFile;
if (useStaticImport) {
return {
importStatement: `import ${JSON.stringify(resolvedSetupFile)}`,
promiseDeclaration: "",
promiseVarName: ""
};
}
return {
importStatement: "",
promiseDeclaration: `const __oneGetSetupPromise = () => import(${JSON.stringify(resolvedSetupFile)})`,
promiseVarName: "__oneGetSetupPromise"
};
}
function createVirtualEntry(options) {
var _options_router_ignoredRouteFiles, _options_router;
var routeGlobs = [`/${options.root}/${ROUTE_GLOB_PATTERN}`, ...(((_options_router = options.router) === null || _options_router === void 0 ? void 0 : (_options_router_ignoredRouteFiles = _options_router.ignoredRouteFiles) === null || _options_router_ignoredRouteFiles === void 0 ? void 0 : _options_router_ignoredRouteFiles.map(function (pattern) {
return `!/${options.root}/${pattern}`;
})) || [])];
var apiRouteGlobs = `/${options.root}/${API_ROUTE_GLOB_PATTERN}`;
var setupFiles = normalizeSetupFile(options.setupFile);
var viteRoot = "";
var isDevMode = false;
return {
name: "one-virtual-entry",
enforce: "pre",
configResolved(config) {
viteRoot = config.root;
isDevMode = config.command === "serve";
},
// only the two virtual entry ids reach js; every other import in the graph
// is rejected rust-side
resolveId: {
filter: {
id: VIRTUAL_ENTRY_SOURCE_RE
},
handler(id) {
if (id === virtualEntryId) {
return resolvedVirtualEntryId;
}
if (id === virtualEntryIdNative) {
return resolvedVirtualEntryIdNative;
}
}
},
load: {
filter: {
id: VIRTUAL_ENTRY_RESOLVED_RE
},
handler(id) {
if (id === resolvedVirtualEntryId) {
var _options_router2;
var isNative = isNativeEnvironment(this.environment);
var isSSR = this.environment.name === "ssr";
var serverSpaRouteFiles = isSSR ? options.routeIndex.getPaths().map(function (file) {
return file.replace(/^\.\//, "");
}).filter(function (file) {
return /\.tsx?$/.test(file);
}).filter(function (file) {
return !micromatch.isMatch(file, ROUTE_WEB_EXCLUSION_GLOB_PATTERNS);
}).filter(function (file) {
var parts = file.split("/");
var filename = parts.at(-1) || "";
if (filename.startsWith("_layout") || filename.startsWith("_middleware")) {
return false;
}
var fileMode = matchFileRenderMode(filename);
if (fileMode) return fileMode === "spa";
var parentMode;
var _iteratorNormalCompletion = true,
_didIteratorError = false,
_iteratorError = void 0;
try {
for (var _iterator = parts.slice(0, -1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var directory = _step.value;
var _ref;
var _matchDirectoryRenderMode;
parentMode = (_ref = (_matchDirectoryRenderMode = matchDirectoryRenderMode(directory)) === null || _matchDirectoryRenderMode === void 0 ? void 0 : _matchDirectoryRenderMode.renderMode) !== null && _ref !== void 0 ? _ref : parentMode;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return parentMode === "spa";
}) : [];
var serverSpaRouteStubs = serverSpaRouteFiles.map(function (file) {
return `${JSON.stringify(`/${options.root}/${file}`)}: () => Promise.resolve({})`;
}).join(",\n ");
var serverSpaBuildGlobs = serverSpaRouteFiles.map(function (file) {
return `/${options.root}/${file}`;
});
var serverSpaBuildRoutes = serverSpaBuildGlobs.length ? `{
loader: import.meta.glob(${JSON.stringify(serverSpaBuildGlobs)}, { exhaustive: true, import: 'loader', query: '?one-spa-build' }),
generateStaticParams: import.meta.glob(${JSON.stringify(serverSpaBuildGlobs)}, { exhaustive: true, import: 'generateStaticParams', query: '?one-spa-build' }),
sitemap: import.meta.glob(${JSON.stringify(serverSpaBuildGlobs)}, { exhaustive: true, import: 'sitemap', query: '?one-spa-build' })
}` : "{}";
var webRouteGlobs = [...routeGlobs, ...ROUTE_WEB_EXCLUSION_GLOB_PATTERNS.map(function (pattern) {
return `!${pattern}`;
}), ...serverSpaRouteFiles.map(function (file) {
return `!/${options.root}/${file}`;
})];
var useStaticImport = isNative || isSSR && isDevMode;
var setupResult = getSetupFileImport(this.environment.name, setupFiles, useStaticImport, viteRoot);
var nativewindImport = configuration.enableNativewind ? `import 'react-native-css-interop/dist/runtime/components'` : "";
var setupPromiseArg = setupResult.promiseVarName ? `getSetupPromise: ${setupResult.promiseVarName},` : "";
var linkingArg = ((_options_router2 = options.router) === null || _options_router2 === void 0 ? void 0 : _options_router2.linking) ? `linking: ${JSON.stringify(options.router.linking)},` : "";
var isDevClient = this.environment.mode === "dev" && this.environment.name === "client";
var refreshPreambleImport = isDevClient ? `import { injectIntoGlobalHook as __oneInjectRefresh } from '/@react-refresh'` : "";
var refreshPreambleSetup = isDevClient ? `if (typeof window !== 'undefined' && !window.$RefreshReg$) {
__oneInjectRefresh(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
}` : "";
return `
${setupResult.promiseDeclaration}
${nativewindImport}
${refreshPreambleImport}
import { createApp, registerPreloadedRoute as _registerPreloadedRoute } from 'one'
${setupResult.importStatement}
${refreshPreambleSetup}
// Export registerPreloadedRoute so preload files can import it from this bundle
// Named export that wraps the original function
export function registerPreloadedRoute(key, module) {
return _registerPreloadedRoute(key, module)
}
// Also expose on window for debugging and to prevent tree-shaking
if (typeof window !== 'undefined') {
window.__oneRegisterPreloadedRoute = registerPreloadedRoute
}
// build-only spa exports generate route artifacts without exposing the page
// component to the runtime server route map.
export const oneBuildOnlySpaRoutes = ${serverSpaBuildRoutes}
// globbing ${JSON.stringify(webRouteGlobs)}
export default createApp({
${setupPromiseArg}
routes: {
...import.meta.glob(${JSON.stringify(webRouteGlobs)}, { exhaustive: true }),
${serverSpaRouteStubs}
},
routerRoot: ${JSON.stringify(options.root)},
flags: ${JSON.stringify(options.flags)},
${linkingArg}
})
`;
}
if (id === resolvedVirtualEntryIdNative) {
var _options_router1;
var isNative1 = isNativeEnvironment(this.environment);
var setupResult1 = getSetupFileImport(this.environment.name, setupFiles, isNative1, viteRoot);
var linkingArg1 = ((_options_router1 = options.router) === null || _options_router1 === void 0 ? void 0 : _options_router1.linking) ? `linking: ${JSON.stringify(options.router.linking)},` : "";
return `
import { createApp } from 'one'
${setupResult1.importStatement}
// globbing ${JSON.stringify(routeGlobs)}
export default createApp({
routes: import.meta.glob(${JSON.stringify([...routeGlobs, ...ROUTE_NATIVE_EXCLUSION_GLOB_PATTERNS.map(function (p) {
return `!${p}`;
}), `!${apiRouteGlobs}`])}, { exhaustive: true }),
routerRoot: ${JSON.stringify(options.root)},
flags: ${JSON.stringify(options.flags)},
${linkingArg1}
})
`;
}
}
}
};
}
export { createVirtualEntry };
//# sourceMappingURL=virtualEntryPlugin.native.js.map