feat: 🎸 搞定 Rax 出码的时候的 package.json 中的 dependencies

This commit is contained in:
牧毅 2020-08-12 15:55:06 +08:00
parent 4572b53f47
commit eba172ce51
9 changed files with 145 additions and 7 deletions

View File

@ -26,6 +26,7 @@
"change-case": "^3.1.0",
"jszip": "^3.5.0",
"prettier": "^2.0.2",
"semver": "^7.3.2",
"short-uuid": "^3.1.1"
},
"devDependencies": {
@ -40,7 +41,7 @@
"compileEnhancements": false,
"snapshotDir": "test/fixtures/__snapshots__",
"files": [
"test/*.test.ts"
"test/**/*.test.ts"
],
"extensions": [
"ts"

View File

@ -16,6 +16,7 @@ import {
IComponentNodeItem,
IContainerInfo,
IContainerNodeItem,
IDependency,
IExternalDependency,
IInternalDependency,
InternalDependencyType,
@ -138,6 +139,8 @@ class SchemaParser implements ISchemaParser {
}
});
const containersDeps = ([] as IDependency[]).concat(...containers.map(c => c.deps || []));
// 分析路由配置
const routes = containers
.filter(container => container.containerType === 'Page')
@ -187,6 +190,8 @@ class SchemaParser implements ISchemaParser {
css: schema.css,
constants: schema.constants,
i18n: schema.i18n,
containersDeps,
utilsDeps,
},
};
}

View File

@ -1,3 +1,4 @@
import { NpmInfo } from '@ali/lowcode-types';
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
import {
@ -9,6 +10,8 @@ import {
IPackageJSON,
IProjectInfo,
} from '../../../../../types';
import { isNpmInfo } from '../../../../../utils/schema';
import { calcCompatibleVersion } from '../../../../../utils/version';
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
@ -18,6 +21,8 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
const ir = next.ir as IProjectInfo;
const npmDeps = getNpmDependencies(ir);
const packageJson: IPackageJSON = {
name: '@ali/rax-app-demo',
private: true,
@ -34,8 +39,13 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
rax: '^1.1.0',
'rax-app': '^2.0.0',
'rax-document': '^0.1.0',
'rax-text': '^1.0.0',
'rax-view': '^1.0.0',
...npmDeps.reduce(
(acc, npm) => ({
...acc,
[npm.package]: npm.version || '*',
}),
{} as Record<string, string>,
),
},
devDependencies: {
'build-plugin-rax-app': '^5.0.0',
@ -66,3 +76,36 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
};
export default pluginFactory;
function getNpmDependencies(project: IProjectInfo): NpmInfo[] {
const npmDeps: NpmInfo[] = [];
const npmNameToPkgMap = new Map<string, NpmInfo>();
const allDeps = [...(project.containersDeps || []), ...(project.utilsDeps || [])];
allDeps.forEach((dep) => {
if (!isNpmInfo(dep)) {
return;
}
const existing = npmNameToPkgMap.get(dep.package);
if (!existing) {
npmNameToPkgMap.set(dep.package, dep);
npmDeps.push(dep);
return;
}
if (existing.version !== dep.version) {
try {
npmNameToPkgMap.set(dep.package, {
...existing,
version: calcCompatibleVersion(existing.version, dep.version),
});
} catch (e) {
throw new Error(`Cannot find compatible version for ${dep.package}. Detail: ${e.message}`);
}
}
});
return npmDeps;
}

View File

@ -42,6 +42,8 @@ export interface IProjectInfo {
css?: string;
constants?: Record<string, string>;
i18n?: II18nMap;
containersDeps?: IDependency[];
utilsDeps?: IDependency[];
}
/**

View File

@ -1,5 +1,9 @@
import { ContainerSchema } from '@ali/lowcode-types';
import { ContainerSchema, NpmInfo } from '@ali/lowcode-types';
export function isContainerSchema(x: any): x is ContainerSchema {
return typeof x === 'object' && x && typeof x.componentName === 'string' && typeof x.fileName === 'string';
}
export function isNpmInfo(x: any): x is NpmInfo {
return typeof x === 'object' && x && typeof x.package === 'string';
}

View File

@ -0,0 +1,29 @@
import semver from 'semver';
export function calcCompatibleVersion(v1: string | undefined | null, v2: string | undefined | null): string {
if (!v1 && !v2) {
return '*';
}
if (!v1 || v1 === '*') {
return v2 || '*';
}
if (!v2 || v2 === '*') {
return v1;
}
if (v1 === v2) {
return v1;
}
if (!semver.intersects(v1, v2, { loose: true })) {
throw new Error(`no compatible versions for "${v1}" and "${v2}"`);
}
if (semver.subset(v1, v2, { loose: true })) {
return v1;
}
return v2;
}

View File

@ -13,8 +13,8 @@
"rax": "^1.1.0",
"rax-app": "^2.0.0",
"rax-document": "^0.1.0",
"rax-text": "^1.0.0",
"rax-view": "^1.0.0"
"rax-view": "^1.0.0",
"rax-text": "^1.0.0"
},
"devDependencies": {
"build-plugin-rax-app": "^5.0.0",

View File

@ -85,7 +85,11 @@ function ensureShellExec(
});
if (res.status !== 0) {
throw new Error(`Shell command "${shellCmd} ${args.slice(0,2).join(' ')}..." failed with status: ${res.status} (Full command: "${shellCmd} ${args.join(' ')}" )`);
throw new Error(
`Shell command "${shellCmd} ${args.slice(0, 2).join(' ')}..." failed with status: ${
res.status
} (Full command: "${shellCmd} ${args.join(' ')}" )`,
);
}
return res;

View File

@ -0,0 +1,50 @@
import test from 'ava';
import type { ExecutionContext, Macro } from 'ava';
import { calcCompatibleVersion } from '../../src/utils/version';
const NO_COMPATIBLE_VERSIONS = /no compatible versions/;
const testCalcCompatibleVersion: Macro<any[]> = (
t: ExecutionContext<{}>,
input: [string | null | undefined, string | null | undefined],
expected: string,
error?: { message: RegExp },
) => {
if (!error) {
t.is(calcCompatibleVersion(input[0], input[1]), expected);
t.is(calcCompatibleVersion(input[1], input[0]), expected); // 应该满足交换律
} else {
t.throws(() => {
calcCompatibleVersion(input[0], input[1]);
}, error.message);
t.throws(() => {
calcCompatibleVersion(input[1], input[0]); // 应该满足交换律
}, error.message);
}
};
testCalcCompatibleVersion.title = (providedTitle: string | undefined, ...args: any[]): string => {
const [input, expected] = args;
return `calc compatible versions "${input[0]}" & "${input[1]}" should be "${expected}"`;
};
test(testCalcCompatibleVersion, ['*', '*'], '*');
test(testCalcCompatibleVersion, ['1.0.0', '1.0.0'], '1.0.0');
test(testCalcCompatibleVersion, ['^1.0.0', '^1.0.0'], '^1.0.0');
test(testCalcCompatibleVersion, ['*', undefined], '*');
test(testCalcCompatibleVersion, [undefined, undefined], '*');
test(testCalcCompatibleVersion, ['^1.0.0', undefined], '^1.0.0');
test(testCalcCompatibleVersion, ['*', '^1.0.0'], '^1.0.0');
test(testCalcCompatibleVersion, ['^1.0.0', '^1.0.2'], '^1.0.2');
test(testCalcCompatibleVersion, ['^1.2.0', '^1.1.2'], '^1.2.0');
test(testCalcCompatibleVersion, ['^1.0.0', '1.0.2'], '1.0.2');
test(testCalcCompatibleVersion, ['^0.2.0', '^0.1.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });
test(testCalcCompatibleVersion, ['>0.2.0', '^0.1.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });
test(testCalcCompatibleVersion, ['1.0.1', '1.0.2'], 'error', { message: NO_COMPATIBLE_VERSIONS });