-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] Add "ui5 use/add" commands (#315)
Co-authored-by: Merlin Beutlberger <m.beutlberger@sap.com>
- Loading branch information
1 parent
7539675
commit 920fbfc
Showing
14 changed files
with
2,946 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) { | ||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}; | ||
}; |
Oops, something went wrong.