UNPKG

@nstudio/schematics

Version:

Cross-platform (xplat) tools for Nx workspaces.

230 lines (228 loc) 10.3 kB
"use strict"; 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