@nstudio/angular
Version:
Angular Plugin for xplat
286 lines (262 loc) • 10.8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const schematics_1 = require("@angular-devkit/schematics");
const devkit_1 = require("@nx/devkit");
const generators_1 = require("@nx/angular/generators");
const xplat_1 = require("@nstudio/xplat");
const xplat_utils_1 = require("@nstudio/xplat-utils");
function default_1(options) {
if (!options.name) {
throw new schematics_1.SchematicsException((0, xplat_1.missingArgument)('name', 'Provide a name for your app.', 'nx g @nstudio/angular:app my-app'));
}
if (options.useXplat) {
// xplat is configured for sass only (at moment)
options.style = 'scss';
}
return (0, schematics_1.chain)([
(0, xplat_utils_1.prerun)(options),
// adjust naming convention
xplat_1.XplatHelpers.applyAppNamingConvention(options, 'web'),
// use xplat or not
options.useXplat
? (0, schematics_1.externalSchematic)('@nstudio/angular', 'xplat', {
platforms: 'web',
framework: 'angular',
})
: (0, schematics_1.noop)(),
(tree, context) => {
const nrwlWebOptions = Object.assign(Object.assign({}, options), { standalone: false, skipInstall: true });
// remove non schema validated properties
delete nrwlWebOptions.groupByName;
delete nrwlWebOptions.useXplat;
delete nrwlWebOptions.skipInstall;
delete nrwlWebOptions.platforms;
delete nrwlWebOptions.framework;
delete nrwlWebOptions.isTesting;
delete nrwlWebOptions.target;
delete nrwlWebOptions.npmScope;
delete nrwlWebOptions.setupSandbox;
if (!options.directory) {
// default to apps
nrwlWebOptions.directory = 'apps';
}
else if (options.directory.indexOf('apps/') === -1) {
// ensure ends up in apps directory
nrwlWebOptions.directory = `apps/${options.directory}`;
}
if (options.useXplat) {
// when generating xplat architecture, ensure:
// 1. sass is used
nrwlWebOptions.style = 'scss';
}
// NOTE: This is what this needs to be:
return (0, devkit_1.convertNxGenerator)(generators_1.applicationGenerator)(nrwlWebOptions);
},
(tree, context) => addHeadlessE2e(options)(tree, context),
options.useXplat
? (tree, context) => addAppFiles(options)(tree, context)
: (0, schematics_1.noop)(),
options.useXplat
? (tree, context) => addAppFiles(options, 'routing')(tree, context)
: (0, schematics_1.noop)(),
// adjust app files
options.useXplat
? (tree, context) => adjustAppFiles(options, tree, context)
: (0, schematics_1.noop)(),
]);
}
/**
* Add headless options to e2e tests
* @param options
*/
function addHeadlessE2e(options) {
const framework = options.e2eTestRunner;
return (0, schematics_1.noop)();
}
function addAppFiles(options, extra = '') {
extra = extra ? `${extra}_` : '';
const directory = options.directory ? `${options.directory}/` : '';
return (0, schematics_1.branchAndMerge)((0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)(`./_${extra}files`), [
(0, schematics_1.template)(Object.assign(Object.assign(Object.assign({}, options), (0, xplat_1.getDefaultTemplateOptions)()), { xplatFolderName: xplat_1.XplatHelpers.getXplatFoldername('web', 'angular') })),
(0, schematics_1.move)(`apps/${directory}${options.name}`),
])));
}
function adjustAppFiles(options, tree, context) {
return __awaiter(this, void 0, void 0, function* () {
const directory = options.directory ? `${options.directory}/` : '';
tree.overwrite(`/apps/${directory}${options.name}/src/index.html`, indexContent(options.name));
tree.overwrite(`/apps/${directory}${options.name}/src/main.ts`, mainContent());
tree.overwrite(`/apps/${directory}${options.name}/src/styles.scss`, `@import 'scss/index';`);
tree.overwrite(`/apps/${directory}${options.name}/src/app/app.component.html`, options.routing
? `<router-outlet></router-outlet>`
: appCmpHtml(options.name));
if (options.routing) {
// update home route to reflect with root cmp would have been
tree.overwrite(`/apps/${directory}${options.name}/src/app/features/home/components/home.component.html`, appCmpHtml(options.name));
}
tree.overwrite(`/apps/${directory}${options.name}/src/app/app.component.ts`, appCmpContent());
tree.overwrite(`/apps/${directory}${options.name}/src/app/app.component.spec.ts`, appCmpSpec());
tree.overwrite(`/apps/${directory}${options.name}/src/app/app.module.ts`, appModuleContent(options));
return (0, schematics_1.noop)();
});
}
function indexContent(name) {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>${(0, xplat_utils_1.getNpmScope)()} ${name}</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<${(0, xplat_utils_1.getPrefix)()}-root></${(0, xplat_utils_1.getPrefix)()}-root>
</body>
</html>`;
}
function mainContent() {
return `import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// libs
import { environment } from '@${(0, xplat_utils_1.getNpmScope)()}/xplat/core';
// app
import { AppModule } from './app/app.module';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.log(err));
`;
}
function appCmpHtml(name) {
return `<div class="p-x-20">
<${(0, xplat_utils_1.getPrefix)()}-header title="${name}"></${(0, xplat_utils_1.getPrefix)()}-header>
<h2>Nx</h2>
Nx is a smart and extensible build framework to help you architect, test, and build at any scale — integrating seamlessly with modern technologies and libraries while providing a robust CLI, caching, dependency management, and more.
<a href="https://nx.dev">Learn more about Nx.</a>
<h1>{{'welcome' | translate}}!</h1>
<h3>Try things out</h3>
<a href="https://nstudio.io/xplat">Learn more about xplat.</a>
</div>`;
}
function appCmpContent() {
return `import { Component } from '@angular/core';
// xplat
import { AppBaseComponent } from '@${(0, xplat_utils_1.getNpmScope)()}/xplat/${xplat_1.XplatHelpers.getXplatFoldername('web', 'angular')}/features';
@Component({
selector: '${(0, xplat_utils_1.getPrefix)()}-root',
templateUrl: './app.component.html'
})
export class AppComponent extends AppBaseComponent {
constructor() {
super();
}
}
`;
}
/**
* @todo Pass this initial tests
*/
function appCmpSpec() {
return `
describe('Web App component generic test', () => {
it('Should be true', () => {
expect(true).toBeTruthy();
});
});
/*import { TestBed, async } from '@angular/core/testing';
import { HttpClient } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { AppComponent } from './app.component';
const translationsEn = require('../assets/i18n/en.json');
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient);
}
describe('AppComponent', () => {
let translate: TranslateService;
let http: HttpTestingController;
beforeEach(
async(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
declarations: [AppComponent],
providers: [TranslateService]
}).compileComponents();
translate = TestBed.get(TranslateService);
http = TestBed.get(HttpTestingController);
})
);
it(
'should create the app',
async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
})
);
it(
'should render xplat hello in a h2 tag',
async(() => {
spyOn(translate, 'getBrowserLang').and.returnValue('en');
translate.use('en');
const fixture = TestBed.createComponent(AppComponent);
const compiled = fixture.debugElement.nativeElement;
// the DOM should be empty for now since the translations haven't been rendered yet
expect(compiled.querySelector('h1').textContent).toEqual('');
http.expectOne('/assets/i18n/en.json').flush(translationsEn);
// Finally, assert that there are no outstanding requests.
http.verify();
fixture.detectChanges();
expect(compiled.querySelector('h2').textContent).toContain(
'Hello xplat'
);
})
);
});
*/
`;
}
function appModuleContent(options) {
return `import { NgModule } from '@angular/core';
// app
import { CoreModule } from './core/core.module';
import { SharedModule } from './features/shared/shared.module';
${options.routing ? `import { AppRoutingModule } from './app.routing';` : ''}
import { AppComponent } from './app.component';
@NgModule({
imports: [
CoreModule,
SharedModule${options.routing
? `,
AppRoutingModule`
: ''}
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
`;
}
;