Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add "ui5 use/add" commands #315

Merged
merged 37 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f67da37
[FEATURE] Add `ui5 use` command
matz3 Mar 26, 2020
c013b47
Update
matz3 Mar 27, 2020
ddb262a
Refactor / not currently working
matz3 Mar 27, 2020
007f35d
Refactoring / add tests
matz3 Mar 27, 2020
11a4c46
Fix updating multiple documents
matz3 Mar 27, 2020
1e4ff31
Fix tests
matz3 Mar 27, 2020
f970d40
Support adding new framework configuration
matz3 Mar 27, 2020
518827f
Improve updateYaml logic
matz3 Mar 30, 2020
2d1b675
Further improve updateYaml
matz3 Mar 30, 2020
514af81
Fix all existings tests
matz3 Mar 30, 2020
86c7aac
Add tests for framework/use function
matz3 Mar 30, 2020
f369b46
Validate YAML content before writing
matz3 Mar 30, 2020
8090879
Add 'ui5 add' command
matz3 Mar 30, 2020
07931df
updateYaml: Arrays
matz3 Mar 30, 2020
3ccbf30
updateYaml: Finish it
matz3 Mar 30, 2020
2b35413
Remove console.log
matz3 Mar 30, 2020
d25cf49
Throw errors instead of console.log
matz3 Mar 30, 2020
828d5ef
add test
matz3 Mar 30, 2020
8a857af
Add tests for add command
matz3 Mar 31, 2020
25a7347
Add --development/optional options
matz3 Mar 31, 2020
063476d
Update lib/framework/add.js
matz3 Mar 31, 2020
a13aea9
Update lib/framework/add.js
matz3 Mar 31, 2020
cea10d9
Fix ESLint issues
matz3 Mar 31, 2020
e58df24
Update logging
matz3 Mar 31, 2020
2548f06
Adopt error message
matz3 Mar 31, 2020
cef216e
Adopt more texts
matz3 Mar 31, 2020
6395a61
Add more tests
matz3 Mar 31, 2020
46826e0
use / updateYaml: fix bugs / add tests
matz3 Mar 31, 2020
6c76f9a
updateYaml: Fix too many linebreaks
matz3 Mar 31, 2020
d7046aa
Add more tests for framework add
matz3 Mar 31, 2020
fc2b071
Fix ui5 add
matz3 Mar 31, 2020
b92246c
Fix tests on Windows
matz3 Mar 31, 2020
5f672bd
Apply suggestions from code review
matz3 Apr 1, 2020
6eaebfd
Adopt command help
matz3 Apr 1, 2020
ea2484e
Adopt use command
matz3 Apr 1, 2020
e641f26
Typo
matz3 Apr 1, 2020
fd59935
Pass cwd to resolveVersion
matz3 Apr 1, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bin/ui5.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ setTimeout(() => {
shouldNotifyInNpmScript: true
}).notify();

cli.parserConfiguration({
"parse-numbers": false
});

// Explicitly set CLI version as the yargs default might
// be wrong in case a local CLI installation is used
// Also add CLI location
Expand Down
88 changes: 88 additions & 0 deletions lib/cli/commands/add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Add
const addCommand = {
command: "add [--development] [--optional] <framework-libraries..>",
describe: "Add SAPUI5/OpenUI5 framework libraries to the project configuration.",
middlewares: [require("../middlewares/base.js")]
};

addCommand.builder = function(cli) {
return cli
.positional("framework-libraries", {
describe: "Framework library names",
type: "string"
}).option("development", {
describe: "Add as development dependency",
alias: ["D", "dev"],
default: false,
type: "boolean"
}).option("optional", {
describe: "Add as optional dependency",
alias: ["O"],
default: false,
type: "boolean"
})
.example("$0 add sap.ui.core sap.m", "Add the framework libraries sap.ui.core and sap.m as dependencies")
.example("$0 add -D sap.ui.support", "Add the framework library sap.ui.support as development dependency")
.example("$0 add --optional themelib_sap_fiori_3",
"Add the framework library themelib_sap_fiori_3 as optional dependency");
};

addCommand.handler = async function(argv) {
const libraryNames = argv["framework-libraries"] || [];
const development = argv["development"];
const optional = argv["optional"];

if (libraryNames.length === 0) {
// Should not happen via yargs as parameter is mandatory
throw new Error("Missing mandatory parameter framework-libraries");
}

if (development && optional) {
throw new Error("Options 'development' and 'optional' cannot be combined");
}

const normalizerOptions = {
translatorName: argv.translator,
configPath: argv.config
};

const libraries = libraryNames.map((name) => {
const library = {name};
if (optional) {
library.optional = true;
} else if (development) {
library.development = true;
}
return library;
});

const {yamlUpdated} = await require("../../framework/add")({
normalizerOptions,
libraries
});

const library = libraries.length === 1 ? "library": "libraries";
if (!yamlUpdated) {
if (argv.config) {
throw new Error(
`Internal error while adding framework ${library} ${libraryNames.join(" ")} to config at ${argv.config}`
);
} else {
throw new Error(
`Internal error while adding framework ${library} ${libraryNames.join(" ")} to ui5.yaml`
);
}
} else {
console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
let logMessage = `Added framework ${library} ${libraryNames.join(" ")} as`;
if (development) {
logMessage += " development";
} else if (optional) {
logMessage += " optional";
}
logMessage += libraries.length === 1 ? " dependency": " dependencies";
console.log(logMessage);
}
};

module.exports = addCommand;
83 changes: 83 additions & 0 deletions lib/cli/commands/use.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Use
const useCommand = {
command: "use <framework-info>",
describe: "Initialize or update the project's framework configuration.",
middlewares: [require("../middlewares/base.js")]
};

useCommand.builder = function(cli) {
return cli
.positional("framework-info", {
describe: "Framework name, version or both (name@version).\n" +
"Name can be \"SAPUI5\" or \"OpenUI5\" (case-insensitive).\n" +
"Version can be \"latest\", \"1.xx\" or \"1.xx.x\".",
type: "string"
})
.example("$0 use sapui5@latest", "Use SAPUI5 in the latest available version")
.example("$0 use openui5@1.76", "Use OpenUI5 in the latest available 1.76 patch version")
.example("$0 use latest", "Use the latest available version of the configured framework")
.example("$0 use openui5", "Use OpenUI5 without a version (or use existing version)");
};

const versionRegExp = /^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?$/;

function parseFrameworkInfo(frameworkInfo) {
RandomByte marked this conversation as resolved.
Show resolved Hide resolved
const parts = frameworkInfo.split("@");
if (parts.length > 2) {
// More than one @ sign
throw new Error("Invalid framework info: " + frameworkInfo);
}
if (parts.length === 1) {
// No @ sign, only name or version
const nameOrVersion = parts[0];
if (!nameOrVersion) {
throw new Error("Invalid framework info: " + frameworkInfo);
}
if (nameOrVersion === "latest" || versionRegExp.test(nameOrVersion)) {
return {
name: null,
version: nameOrVersion
};
} else {
return {
name: nameOrVersion,
version: null
};
}
} else {
const [name, version] = parts;
if (!name || !version) {
throw new Error("Invalid framework info: " + frameworkInfo);
}
return {name, version};
}
}

useCommand.handler = async function(argv) {
const frameworkOptions = parseFrameworkInfo(argv["framework-info"]);

const normalizerOptions = {
translatorName: argv.translator,
configPath: argv.config
};

const {usedFramework, usedVersion, yamlUpdated} = await require("../../framework/use")({
normalizerOptions,
frameworkOptions
});

if (!yamlUpdated) {
if (argv.config) {
throw new Error(
`Internal error while updating config at ${argv.config} to ${usedFramework} version ${usedVersion}`
);
} else {
throw new Error(`Internal error while updating ui5.yaml to ${usedFramework} version ${usedVersion}`);
}
} else {
console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
console.log(`This project is now using ${usedFramework} version ${usedVersion}`);
}
};

module.exports = useCommand;
77 changes: 77 additions & 0 deletions lib/framework/add.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const {getRootProjectConfiguration, getFrameworkResolver, isValidSpecVersion} = require("./utils");

module.exports = async function({normalizerOptions, libraries}) {
const project = await getRootProjectConfiguration({normalizerOptions});

if (!isValidSpecVersion(project.specVersion)) {
throw new Error(
`ui5 add command requires specVersion "2.0" or higher. ` +
`Project ${project.metadata.name} uses specVersion "${project.specVersion}"`
);
}

if (!project.framework) {
throw new Error(
`Project ${project.metadata.name} is missing a framework configuration. ` +
`Please use "ui5 use" to configure a framework and version.`
);
}
if (!project.framework.version) {
throw new Error(
`Project ${project.metadata.name} does not define a framework version configuration. ` +
`Please use "ui5 use" to configure a version.`
);
}

const Resolver = getFrameworkResolver(project.framework.name);

const resolver = new Resolver({
cwd: project.path,
version: project.framework.version
});

// Get metadata of all libraries to verify that they can be installed
await Promise.all(libraries.map(async ({name}) => {
try {
await resolver.getLibraryMetadata(name);
} catch (err) {
throw new Error(`Failed to find ${project.framework.name} framework library ${name}: ` + err.message);
}
}));

// Shallow copy of given libraries to not modify the input parameter when pushing other libraries
const allLibraries = [...libraries];

if (project.framework.libraries) {
project.framework.libraries.forEach((library) => {
// Don't add libraries twice!
if (allLibraries.findIndex(($) => $.name === library.name) === -1) {
allLibraries.push(library);
}
});
}
allLibraries.sort((a, b) => {
return a.name.localeCompare(b.name);
});

// Try to update YAML file but still return with name and resolved version in case it failed
let yamlUpdated = false;
try {
await require("./updateYaml")({
project,
data: {
framework: {
libraries: allLibraries
}
}
});
yamlUpdated = true;
} catch (err) {
if (err.name !== "FrameworkUpdateYamlFailed") {
throw err;
}
}
return {
yamlUpdated
};
};
Loading