feat(cli): 如果识别不要组件文件,则默认从npm包的default导入

This commit is contained in:
roymondchen 2025-03-27 16:25:58 +08:00
parent f17ef325b1
commit b715a87f40
4 changed files with 169 additions and 49 deletions

View File

@ -11,11 +11,14 @@ export default class Core {
public options: UserConfig; public options: UserConfig;
public moduleMainFilePath: ModuleMainFilePath = { public moduleMainFilePath: ModuleMainFilePath = {
componentPackage: {},
componentMap: {}, componentMap: {},
pluginPakcage: {},
pluginMap: {}, pluginMap: {},
configMap: {}, configMap: {},
valueMap: {}, valueMap: {},
eventMap: {}, eventMap: {},
datasourcePackage: {},
datasourceMap: {}, datasourceMap: {},
dsConfigMap: {}, dsConfigMap: {},
dsValueMap: {}, dsValueMap: {},

View File

@ -54,11 +54,14 @@ export interface NpmConfig {
} }
export interface ModuleMainFilePath { export interface ModuleMainFilePath {
componentPackage: Record<string, string>;
componentMap: Record<string, string>; componentMap: Record<string, string>;
pluginPakcage: Record<string, string>;
pluginMap: Record<string, string>; pluginMap: Record<string, string>;
configMap: Record<string, string>; configMap: Record<string, string>;
valueMap: Record<string, string>; valueMap: Record<string, string>;
eventMap: Record<string, string>; eventMap: Record<string, string>;
datasourcePackage: Record<string, string>;
datasourceMap: Record<string, string>; datasourceMap: Record<string, string>;
dsConfigMap: Record<string, string>; dsConfigMap: Record<string, string>;
dsValueMap: Record<string, string>; dsValueMap: Record<string, string>;

View File

@ -5,33 +5,84 @@ import { EntryType } from '../types';
export const prepareEntryFile = async (app: App) => { export const prepareEntryFile = async (app: App) => {
const { moduleMainFilePath, options } = app; const { moduleMainFilePath, options } = app;
const { componentFileAffix, dynamicImport, hooks, useTs = true } = options; const { dynamicImport, hooks, useTs = true } = options;
let contentMap: Record<string, string> = { let contentMap: Record<string, string> = {
'comp-entry': generateContent(useTs, EntryType.COMPONENT, moduleMainFilePath.componentMap, componentFileAffix), 'comp-entry': generateContent(
useTs,
EntryType.COMPONENT,
moduleMainFilePath.componentPackage,
moduleMainFilePath.componentMap,
),
'async-comp-entry': generateContent( 'async-comp-entry': generateContent(
useTs, useTs,
EntryType.COMPONENT, EntryType.COMPONENT,
moduleMainFilePath.componentPackage,
moduleMainFilePath.componentMap, moduleMainFilePath.componentMap,
componentFileAffix,
dynamicImport, dynamicImport,
), ),
'plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap), 'plugin-entry': generateContent(
'async-plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap, '', dynamicImport), useTs,
'config-entry': generateContent(useTs, EntryType.CONFIG, moduleMainFilePath.configMap), EntryType.PLUGIN,
'value-entry': generateContent(useTs, EntryType.VALUE, moduleMainFilePath.valueMap), moduleMainFilePath.pluginPakcage,
'event-entry': generateContent(useTs, EntryType.EVENT, moduleMainFilePath.eventMap), moduleMainFilePath.pluginMap,
'datasource-entry': generateContent(useTs, EntryType.DATASOURCE, moduleMainFilePath.datasourceMap), ),
'async-plugin-entry': generateContent(
useTs,
EntryType.PLUGIN,
moduleMainFilePath.pluginPakcage,
moduleMainFilePath.pluginMap,
dynamicImport,
),
'config-entry': generateContent(
useTs,
EntryType.CONFIG,
moduleMainFilePath.componentPackage,
moduleMainFilePath.configMap,
),
'value-entry': generateContent(
useTs,
EntryType.VALUE,
moduleMainFilePath.componentPackage,
moduleMainFilePath.valueMap,
),
'event-entry': generateContent(
useTs,
EntryType.EVENT,
moduleMainFilePath.componentPackage,
moduleMainFilePath.eventMap,
),
'datasource-entry': generateContent(
useTs,
EntryType.DATASOURCE,
moduleMainFilePath.datasourcePackage,
moduleMainFilePath.datasourceMap,
),
'async-datasource-entry': generateContent( 'async-datasource-entry': generateContent(
useTs, useTs,
EntryType.DATASOURCE, EntryType.DATASOURCE,
moduleMainFilePath.datasourcePackage,
moduleMainFilePath.datasourceMap, moduleMainFilePath.datasourceMap,
'',
dynamicImport, dynamicImport,
), ),
'ds-config-entry': generateContent(useTs, EntryType.DS_CONFIG, moduleMainFilePath.dsConfigMap), 'ds-config-entry': generateContent(
'ds-value-entry': generateContent(useTs, EntryType.DS_VALUE, moduleMainFilePath.dsValueMap), useTs,
'ds-event-entry': generateContent(useTs, EntryType.DS_EVENT, moduleMainFilePath.dsEventMap), EntryType.DS_CONFIG,
moduleMainFilePath.datasourcePackage,
moduleMainFilePath.dsConfigMap,
),
'ds-value-entry': generateContent(
useTs,
EntryType.DS_VALUE,
moduleMainFilePath.datasourcePackage,
moduleMainFilePath.dsValueMap,
),
'ds-event-entry': generateContent(
useTs,
EntryType.DS_EVENT,
moduleMainFilePath.datasourcePackage,
moduleMainFilePath.dsEventMap,
),
}; };
if (typeof hooks?.beforeWriteEntry === 'function') { if (typeof hooks?.beforeWriteEntry === 'function') {
@ -53,8 +104,8 @@ export const prepareEntryFile = async (app: App) => {
export const generateContent = ( export const generateContent = (
useTs: boolean, useTs: boolean,
type: EntryType, type: EntryType,
packageMap: Record<string, string> = {},
map: Record<string, string> = {}, map: Record<string, string> = {},
componentFileAffix = '',
dynamicImport = false, dynamicImport = false,
) => { ) => {
const list: string[] = []; const list: string[] = [];
@ -62,14 +113,14 @@ export const generateContent = (
Object.entries(map).forEach(([key, packagePath]) => { Object.entries(map).forEach(([key, packagePath]) => {
const name = makeCamelCase(key); const name = makeCamelCase(key);
if (dynamicImport) {
list.push( if ([EntryType.CONFIG, EntryType.EVENT, EntryType.VALUE].includes(type) && packagePath === packageMap[key]) {
`'${key}': () => import('${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}')`, importDeclarations.push(`import { ${type} as ${name} } from '${packageMap[key]}'`);
); list.push(`'${key}': ${name}`);
} else if (dynamicImport) {
list.push(`'${key}': () => import('${packagePath}')`);
} else { } else {
importDeclarations.push( importDeclarations.push(`import ${name} from '${packagePath}'`);
`import ${name} from '${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}'`,
);
list.push(`'${key}': ${name}`); list.push(`'${key}': ${name}`);
} }
}); });

View File

@ -38,20 +38,37 @@ const getRelativePath = (str: string, base: string) => (path.isAbsolute(str) ? p
const npmInstall = function (dependencies: Record<string, string>, cwd: string, npmConfig: NpmConfig = {}) { const npmInstall = function (dependencies: Record<string, string>, cwd: string, npmConfig: NpmConfig = {}) {
try { try {
const { client = 'npm', registry, installArgs = '' } = npmConfig; const { client = 'npm', registry, installArgs = '', keepPackageJsonClean } = npmConfig;
const install = { const install = {
npm: 'install', npm: 'install',
yarn: 'add', yarn: 'add',
pnpm: 'add', pnpm: 'add',
}[client]; }[client];
const packages = Object.entries(dependencies) let packages = Object.entries(dependencies);
.map(([name, version]) => (version ? `${name}@${version}` : name))
.join(' '); const newPackages = Object.entries(dependencies).filter(([name]) => {
if (fs.existsSync(path.resolve(cwd, 'node_modules', name))) {
return false;
}
return true;
});
// keepPackageJsonClean会保留原始的package.json这样配置的packages就不会被写入dependencies中
// install 时会删除不在dependencies中的依赖所以需要install packages中配置的所有包
if (!keepPackageJsonClean || !newPackages.length) {
packages = newPackages;
}
if (!packages.length) {
return;
}
const packageNames = packages.map(([name, version]) => (version ? `${name}@${version}` : name)).join(' ');
const installArgsString = `${installArgs ? ` ${installArgs}` : ''}`; const installArgsString = `${installArgs ? ` ${installArgs}` : ''}`;
const registryString = `${registry ? ` --registry ${registry}` : ''}`; const registryString = `${registry ? ` --registry ${registry}` : ''}`;
const command = `${client} ${install}${installArgsString} ${packages}${registryString}`; const command = `${client} ${install}${installArgsString} ${packageNames}${registryString}`;
execInfo(cwd); execInfo(cwd);
execInfo(command); execInfo(command);
@ -318,25 +335,30 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
const tokens = getASTTokenByTraverse({ ast, indexPath }); const tokens = getASTTokenByTraverse({ ast, indexPath });
let { config, value, event, component } = tokens; let { config, value, event, component } = tokens;
if (!config) { if (typeof config === 'undefined') {
info(`${module} 表单配置文件声明缺失`); info(`${module} 表单配置文件声明缺失`);
} }
if (!value) { if (typeof value === 'undefined') {
info(`${module} 初始化数据文件声明缺失`); info(`${module} 初始化数据文件声明缺失`);
} }
if (!event) { if (typeof event === 'undefined') {
info(`${module} 事件声明文件声明缺失`); info(`${module} 事件声明文件声明缺失`);
} }
if (!component) {
info(`${module} 组件或数据源文件声明不合法`);
exit(1);
}
const reg = /^.*[/\\]node_modules[/\\](.*)/; const reg = /^.*[/\\]node_modules[/\\](.*)/;
if (config) {
[, config] = config.match(reg) || [, config]; [, config] = config.match(reg) || [, config];
}
if (value) {
[, value] = value.match(reg) || [, value]; [, value] = value.match(reg) || [, value];
}
if (component) {
[, component] = component.match(reg) || [, component]; [, component] = component.match(reg) || [, component];
}
if (event) {
[, event] = event.match(reg) || [, event]; [, event] = event.match(reg) || [, event];
}
return { return {
config, config,
@ -347,10 +369,10 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
}; };
const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string }) => { const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string }) => {
let config = ''; let config: string | undefined;
let value = ''; let value: string | undefined;
let event = ''; let event: string | undefined;
let component = ''; let component: string | undefined;
const importSpecifiersMap: { [key: string]: string } = {}; const importSpecifiersMap: { [key: string]: string } = {};
const exportSpecifiersMap: { [key: string]: string | undefined } = {}; const exportSpecifiersMap: { [key: string]: string | undefined } = {};
@ -396,7 +418,11 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
visitExportDefaultDeclaration(p) { visitExportDefaultDeclaration(p) {
const { node } = p; const { node } = p;
const { declaration } = node as any; const { declaration } = node as any;
if (importSpecifiersMap[declaration.name]) {
component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]); component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]);
}
this.traverse(p); this.traverse(p);
}, },
}); });
@ -405,7 +431,10 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
const exportValue = exportSpecifiersMap[exportName]; const exportValue = exportSpecifiersMap[exportName];
const importValue = importSpecifiersMap[exportName]; const importValue = importSpecifiersMap[exportName];
const connectValue = exportValue ? importSpecifiersMap[exportValue] : ''; const connectValue = exportValue ? importSpecifiersMap[exportValue] : '';
const filePath = path.resolve(path.dirname(indexPath), connectValue || importValue || exportValue || '');
const fileName = connectValue || importValue || exportValue || '';
const filePath = fileName ? path.resolve(path.dirname(indexPath), fileName) : '';
if (exportName === EntryType.VALUE) { if (exportName === EntryType.VALUE) {
value = filePath; value = filePath;
@ -463,7 +492,7 @@ const getDependencies = (dependencies: Record<string, string>, packagePath: stri
const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string, cwd: string, key?: string) => { const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string, cwd: string, key?: string) => {
const { options } = app; const { options } = app;
const { temp, componentFileAffix, datasoucreSuperClass } = options; const { temp, componentFileAffix = '', datasoucreSuperClass } = options;
let { name: moduleName } = splitNameVersion(packagePath); let { name: moduleName } = splitNameVersion(packagePath);
@ -513,15 +542,45 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
if (!key) return; if (!key) return;
if (result.type === PackageType.COMPONENT) { if (result.type === PackageType.COMPONENT || !result.type) {
packages.componentPackage[key] = moduleName;
// 组件 // 组件
const entry = parseEntry({ ast, package: moduleName, indexPath }); const entry = parseEntry({ ast, package: moduleName, indexPath });
if (entry.component) packages.componentMap[key] = getRelativePath(entry.component, temp); if (entry.component) {
if (entry.config) packages.configMap[key] = getRelativePath(entry.config, temp); const packagePath = getRelativePath(entry.component, temp);
if (entry.event) packages.eventMap[key] = getRelativePath(entry.event, temp); packages.componentMap[key] = `${packagePath}${
if (entry.value) packages.valueMap[key] = getRelativePath(entry.value, temp); packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix
}`;
} else {
packages.componentMap[key] = moduleName;
}
if (typeof entry.config === 'string') {
if (entry.config) {
packages.configMap[key] = getRelativePath(entry.config, temp);
} else {
packages.configMap[key] = moduleName;
}
}
if (typeof entry.event === 'string') {
if (entry.event) {
packages.eventMap[key] = getRelativePath(entry.event, temp);
} else {
packages.eventMap[key] = moduleName;
}
}
if (typeof entry.value === 'string') {
if (entry.value) {
packages.valueMap[key] = getRelativePath(entry.value, temp);
} else {
packages.valueMap[key] = moduleName;
}
}
} else if (result.type === PackageType.DATASOURCE) { } else if (result.type === PackageType.DATASOURCE) {
packages.datasourcePackage[key] = moduleName;
// 数据源 // 数据源
const entry = parseEntry({ ast, package: moduleName, indexPath }); const entry = parseEntry({ ast, package: moduleName, indexPath });
@ -530,6 +589,7 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
if (entry.event) packages.dsEventMap[key] = getRelativePath(entry.event, temp); if (entry.event) packages.dsEventMap[key] = getRelativePath(entry.event, temp);
if (entry.value) packages.dsValueMap[key] = getRelativePath(entry.value, temp); if (entry.value) packages.dsValueMap[key] = getRelativePath(entry.value, temp);
} else if (result.type === PackageType.PLUGIN) { } else if (result.type === PackageType.PLUGIN) {
packages.pluginPakcage[key] = moduleName;
// 插件 // 插件
packages.pluginMap[key] = getRelativePath(moduleName, temp); packages.pluginMap[key] = getRelativePath(moduleName, temp);
} }
@ -573,11 +633,14 @@ export const resolveAppPackages = (app: App): ModuleMainFilePath => {
} }
const packagesMap: ModuleMainFilePath = { const packagesMap: ModuleMainFilePath = {
componentPackage: {},
componentMap: {}, componentMap: {},
configMap: {}, configMap: {},
eventMap: {}, eventMap: {},
valueMap: {}, valueMap: {},
pluginPakcage: {},
pluginMap: {}, pluginMap: {},
datasourcePackage: {},
datasourceMap: {}, datasourceMap: {},
dsConfigMap: {}, dsConfigMap: {},
dsEventMap: {}, dsEventMap: {},