@umijs/plugins
Version:
198 lines (176 loc) • 6.42 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/access.ts
var access_exports = {};
__export(access_exports, {
default: () => access_default
});
module.exports = __toCommonJS(access_exports);
var import_fs = __toESM(require("fs"));
var import_path = require("path");
var import_withTmpPath = require("./utils/withTmpPath");
var access_default = (api) => {
api.describe({
config: {
schema({ zod }) {
return zod.record(zod.any());
}
},
enableBy: api.EnableBy.config
});
api.onGenerateFiles(async () => {
const hasAccessFile = ["js", "jsx", "ts", "tsx"].some(
(ext) => import_fs.default.existsSync((0, import_path.join)(api.paths.absSrcPath, `access.${ext}`))
);
api.writeTmpFile({
path: "runtime.tsx",
content: `
import React from 'react';${hasAccessFile ? `
import accessFactory from '@/access';
import { useModel } from '@@/plugin-model';
` : ""}
import { AccessContext } from './context';
function Provider(props) {${hasAccessFile ? `
const { initialState } = useModel('@@initialState');
const access = React.useMemo(() => accessFactory(initialState), [initialState]);
` : `
const access = {};
`}
return (
<AccessContext.Provider value={access}>
{ props.children }
</AccessContext.Provider>
);
}
export function accessProvider(container) {
return <Provider>{ container }</Provider>;
}
`
});
api.writeTmpFile({
path: "index.tsx",
content: `
import React, { PropsWithChildren } from 'react';
import { AccessContext } from './context';
import type { IRoute } from 'umi';
export const useAccess = () => {
return React.useContext(AccessContext);
};
export interface AccessProps {
accessible: boolean;
fallback?: React.ReactNode;
}
export const Access: React.FC<PropsWithChildren<AccessProps>> = (props) => {
if (process.env.NODE_ENV === 'development' && typeof props.accessible !== 'boolean') {
throw new Error('[access] the \`accessible\` property on <Access /> should be a boolean');
}
return <>{ props.accessible ? props.children : props.fallback }</>;
};
export const useAccessMarkedRoutes = (routes: IRoute[]) => {
const access = useAccess();
const markdedRoutes: IRoute[] = React.useMemo(() => {
const process = (route, parentAccessCode, parentRoute) => {
let accessCode = route.access;
// 用父级的路由检测父级的 accessCode
let detectorRoute = route;
if (!accessCode && parentAccessCode) {
accessCode = parentAccessCode;
detectorRoute = parentRoute;
}
// set default status
route.unaccessible = ${api.config.access.strictMode ? "true" : "false"};
// check access code
if (typeof accessCode === 'string') {
const detector = access[accessCode];
if (typeof detector === 'function') {
route.unaccessible = !detector(detectorRoute);
} else if (typeof detector === 'boolean') {
route.unaccessible = !detector;
} else if (typeof detector === 'undefined') {
route.unaccessible = true;
}
}
// check children access code
if (route.children?.length) {
const isNoAccessibleChild = !route.children.reduce((hasAccessibleChild, child) => {
process(child, accessCode, route);
return hasAccessibleChild || !child.unaccessible;
}, false);
// make sure parent route is unaccessible if all children are unaccessible
if (isNoAccessibleChild) {
route.unaccessible = true;
}
}
// check children access code
if (route.routes?.length) {
const isNoAccessibleChild = !route.routes.reduce((hasAccessibleChild, child) => {
process(child, accessCode, route);
return hasAccessibleChild || !child.unaccessible;
}, false);
// make sure parent route is unaccessible if all children are unaccessible
if (isNoAccessibleChild) {
route.unaccessible = true;
}
}
return route;
}
return routes.map(route => process(route));
}, [routes.length, access]);
return markdedRoutes;
}
`
});
api.writeTmpFile({
path: "context.ts",
content: `
import React from 'react';${hasAccessFile ? `
import { AccessInstance } from './types.d';
export const AccessContext = React.createContext<AccessInstance>(null);
` : `
export const AccessContext = React.createContext<any>(null);
`}
`
});
api.writeTmpFile({
path: "types.d.ts",
content: hasAccessFile ? `
import accessFactory from '@/access';
export type AccessInstance = ReturnType<typeof accessFactory>;
` : "export {}"
});
});
api.addRuntimePlugin(() => {
return [(0, import_withTmpPath.withTmpPath)({ api, path: "runtime.tsx" })];
});
api.addTmpGenerateWatcherPaths(() => [
(0, import_path.join)(api.paths.absSrcPath, "access.ts"),
(0, import_path.join)(api.paths.absSrcPath, "access.js")
]);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {});