@nstudio/schematics
Version:
Cross-platform (xplat) tools for Nx workspaces.
230 lines (228 loc) • 10.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const schematics_1 = require("@angular-devkit/schematics");
const utils_1 = require("../utils");
const test_1 = require("@schematics/angular/utility/test");
let customElementList;
let componentSymbols;
let componentSymbolList;
let htmlElements;
function default_1(options) {
if (!options.builderModule) {
const example = `ng g elements menu --barrel=@mycompany/ui --components=menu,footer`;
if (!options.name) {
throw new schematics_1.SchematicsException(utils_1.missingArgument("name", "Provide a name for the custom element module.", example));
}
if (!options.barrel) {
throw new schematics_1.SchematicsException(utils_1.missingArgument("barrel", "Provide the name of the workspace barrel where your components live.", example));
}
if (!options.components) {
throw new schematics_1.SchematicsException(utils_1.missingArgument("components", `Provide a comma delimited list of components you'd like to create as custom elements.`, example));
}
}
return schematics_1.chain([
utils_1.prerun(options),
(tree) => {
if (!options.builderModule) {
const workspacePrefix = options.prefix || utils_1.getPrefix() || "";
const htmlElementList = [];
componentSymbols = [];
// parse component names to standard convention
const componentNames = options.components.split(",");
for (let component of componentNames) {
// using short name ("menu" for a component named "MenuComponent")
// convert to fully best practice name
const isShortName = component.toLowerCase().indexOf("component") === -1;
let selector = `${workspacePrefix ? `${workspacePrefix}-` : ""}`;
if (isShortName) {
selector += component.toLowerCase();
}
else {
const parts = component.toLowerCase().split("component");
selector += parts[0];
}
componentSymbols.push({
selector,
symbol: `${utils_1.stringUtils.classify(component)}${isShortName ? "Component" : ""}`
});
htmlElementList.push(`<${selector}></${selector}>`);
}
componentSymbolList = componentSymbols.map(c => c.symbol).join(", ");
htmlElements = htmlElementList.join("\n");
customElementList = createCustomElementList(componentSymbols);
}
return tree;
},
// add custom element module
(tree, context) => {
return options.builderModule ? schematics_1.noop() : addFiles(options)(tree, context);
},
// add builder files or update them
(tree, context) => {
if (tree.exists('xplat/web/elements/builder/index.html')) {
return updateBuilder(tree, options);
}
else {
return addFiles(options, 'builder')(tree, context);
}
},
// adjust app files
// (tree: Tree) => adjustAppFiles(options, tree),
// add build scripts
(tree) => {
if (options.builderModule) {
return schematics_1.noop();
}
else {
const scripts = {};
scripts[`build.web.elements`] = `ng build web-elements --prod --output-hashing=none --single-bundle=true --keep-polyfills=true`;
scripts[`preview.web.elements`] = `http-server dist/ngelements`;
return utils_1.updatePackageScripts(tree, scripts);
}
},
(tree) => {
if (options.builderModule) {
return schematics_1.noop();
}
else {
const projects = {};
projects[`web-elements`] = {
root: "",
sourceRoot: "xplat/web/elements/builder",
projectType: "application",
prefix: "web-elements",
schematics: {},
architect: {
build: {
builder: "ngx-build-plus:build",
options: {
outputPath: "dist/ngelements",
index: "xplat/web/elements/builder/index.html",
main: "xplat/web/elements/builder/elements.ts",
polyfills: "xplat/web/elements/builder/polyfills.ts",
tsConfig: "xplat/web/elements/builder/tsconfig.elements.json"
},
configurations: {
production: {
optimization: true,
outputHashing: "all",
sourceMap: false,
extractCss: true,
namedChunks: false,
aot: true,
extractLicenses: true,
vendorChunk: false,
buildOptimizer: true
}
}
},
serve: {
builder: "ngx-build-plus:dev-server",
options: {
browserTarget: "web-elements:build"
},
configurations: {
production: {
browserTarget: "web-elements:build:production"
}
}
}
}
};
return utils_1.updateAngularProjects(tree, projects);
}
},
// update dependencies
(tree, context) => {
return options.builderModule ? schematics_1.noop() : updateWorkspaceSupport(options, tree, context);
},
// update for builderModule if desired
(tree, context) => {
if (options.builderModule) {
}
else {
return schematics_1.noop();
}
},
// formatting
options.skipFormat ? schematics_1.noop() : utils_1.formatFiles(options)
]);
}
exports.default = default_1;
function addFiles(options, extra = "") {
extra = extra ? `${extra}_` : "";
return schematics_1.branchAndMerge(schematics_1.mergeWith(schematics_1.apply(schematics_1.url(`./_${extra}files`), [
schematics_1.template(Object.assign({}, options, { name: options.name.toLowerCase(), customElementList,
componentSymbolList,
componentSymbols,
htmlElements, npmScope: utils_1.getNpmScope(), prefix: utils_1.getPrefix(), dot: ".", utils: utils_1.stringUtils })),
schematics_1.move(`xplat/web/elements`)
])));
}
function updateWorkspaceSupport(options, tree, context) {
return utils_1.updateJsonInTree("package.json", json => {
json.scripts = json.scripts || {};
json.dependencies = json.dependencies || {};
const angularVersion = json.dependencies["@angular/core"];
json.dependencies = Object.assign({}, json.dependencies, { "@angular/elements": angularVersion, "@webcomponents/webcomponentsjs": "^2.2.7" });
json.devDependencies = json.devDependencies || {};
json.devDependencies = Object.assign({}, json.devDependencies, { "http-server": "^0.11.1", "ngx-build-plus": "^7.7.5" });
return json;
})(tree, context);
}
function createCustomElementList(componentSymbols) {
const customElements = ["let component;"];
for (const comp of componentSymbols) {
customElements.push(`component = createCustomElement(${comp.symbol}, { injector: this.injector });
customElements.define('${comp.selector}', component);`);
}
return customElements.join("\n");
}
function updateBuilder(tree, options) {
if (options.builderModule) {
tree.overwrite(`xplat/web/elements/builder/elements.ts`, builderElementsContent(options.builderModule));
const moduleFilePath = `xplat/web/elements/${options.builderModule}.module.ts`;
if (tree.exists(moduleFilePath)) {
const moduleFile = test_1.getFileContent(tree, moduleFilePath);
const selectorParts = moduleFile.split('.define(');
selectorParts.splice(0, 1); // remove starting data
const customElements = [];
for (const part of selectorParts) {
let selector = part.split(',')[0].replace(/'/ig, '').replace(/"/ig, '');
customElements.push(`<${selector}></${selector}>`);
}
tree.overwrite(`xplat/web/elements/builder/index.html`, buildIndexContent(customElements.join('\n')));
}
else {
throw new schematics_1.SchematicsException(`${moduleFilePath} does not exist.`);
}
}
else {
tree.overwrite(`xplat/web/elements/builder/elements.ts`, builderElementsContent(options.name));
tree.overwrite(`xplat/web/elements/builder/index.html`, buildIndexContent(htmlElements));
}
return tree;
}
function builderElementsContent(name) {
return `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { ${utils_1.stringUtils.classify(name)}Module } from '../${name}.module';
platformBrowserDynamic()
.bootstrapModule(${utils_1.stringUtils.classify(name)}Module)
.catch(err => console.log(err));
`;
}
function buildIndexContent(customElements) {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Custom Elements</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
${customElements}
</body>
</html>`;
}
//# sourceMappingURL=index.js.map