error TS2307: Cannot find module '#microsoft/sp-webpart-base' - javascript

I have a sharepoint framework project with the following folder structure:
It has a library called dataaccess and a webpart factory method
Sharepointdataprovider.ts file
import {
SPHttpClient,
SPHttpClientBatch,
SPHttpClientResponse
} from '#microsoft/sp-http';
import { IWebPartContext } from '#microsoft/sp-webpart-base';
import List from '../models/List';
import IDataProvider from './IDataProvider';
export default class SharePointDataProvider implements IDataProvider {
private _selectedList: List;
private _lists: List[];
private _listsUrl: string;
private _listItemsUrl: string;
private _webPartContext: IWebPartContext;
public set selectedList(value: List) {
this._selectedList = value;
this._listItemsUrl = `${this._listsUrl}(guid'${value.Id}')/items`;
}
public get selectedList(): List {
return this._selectedList;
}
public set webPartContext(value: IWebPartContext) {
this._webPartContext = value;
this._listsUrl = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists`;
}
public get webPartContext(): IWebPartContext {
return this._webPartContext;
}
public getLists(): Promise<List[]> {
const listTemplateId: string = '171';
const queryString: string = `?$filter=BaseTemplate eq ${listTemplateId}`;
const queryUrl: string = this._listsUrl + queryString;
return this._webPartContext.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
})
.then((json: { value: List[] }) => {
return this._lists = json.value;
});
}
}
In my gulpfile.js I have this:
'use strict';
const gulp = require('gulp');
const build = require('#microsoft/sp-build-web');
//Required libraries to update typings
var through = require('through2'),
util = require('gulp-util'),
spawn = require('child_process').spawn,
clean = require('gulp-clean'),
ts = require('gulp-typescript');
//ootb
build.initialize(gulp);
// required variables to make configuration easier on the gulp tasks below
var libsPath = 'lib/libraries';
var srcPath = 'src/libraries';
var spdataaccessLibraryFolder = 'spdataaccess';
gulp.task('watch-spdataaccess-lib', (cb) => {
var watcher = gulp.watch(`${srcPath}/${spdataaccessLibraryFolder}/**/*.ts`, ['update-spdataaccess-typings']);
watcher.on('change', (event) => {
console.log(`File ${event.path} was ${event.type}, Rebuilding library typings...`);
});
});
gulp.task('update-spdataaccess-typings', [
'update-spdataaccess-typings:clean-old-typings',
'update-spdataaccess-typings:get-latest-typings',
'update-spdataaccess-typings:build-lib-typings'
], () => {
});
gulp.task('update-spdataaccess-typings:clean-old-typings', () => {
return gulp.src(`${libsPath}/${spdataaccessLibraryFolder}/**`, { read: false })
.pipe(clean());
});
gulp.task('update-spdataaccess-typings:get-latest-typings', ['update-spdataaccess-typings:clean-old-typings'], () => {
var tsResult = gulp.src(`${srcPath}/${spdataaccessLibraryFolder}/**/*.ts`)
.pipe(ts({
outDir: `${libsPath}/${spdataaccessLibraryFolder}`,
module: 'umd',
declaration: true
}));
return tsResult.dts.pipe(gulp.dest(`${libsPath}/${spdataaccessLibraryFolder}`));
});
gulp.task('update-spdataaccess-typings:build-lib-typings', ['update-spdataaccess-typings:get-latest-typings'], () => {
return gulp.src(`${libsPath}/${spdataaccessLibraryFolder}/**/*.d.ts`)
.pipe(updateLibTypings('spdataaccessLibrary.d.ts'))
.pipe(gulp.dest('./typings'));
});
var updateLibTypings = function (typingsFilePath, opt) {
var typings = ["declare module 'spdataaccess' {"];
var latestFile;
function processTypings(file, encoding, cb) {
if (file.isNull() || file.isStream()) {
cb();
return;
}
latestFile = file;
var contents = file.contents.toString('utf8');
if (contents.indexOf('export declare class ') === -1) {
cb();
return;
}
contents = contents.replace('export declare class ', 'class ');
typings.push(contents);
cb();
}
function endStream(cb) {
if (!latestFile) {
cb();
return;
}
typings.push('}');
var file = latestFile.clone({ contents: false });
file.path = latestFile.base + typingsFilePath;
file.contents = new Buffer(typings.join('\r\n'));
this.push(file)
cb();
}
return through.obj(processTypings, endStream);
}
However when I try to run:
gulp update-spdataaccess-typings
I get these errors:
error TS2307: Cannot find module '#microsoft/sp-webpart-base'.
If I check tsconfig.json, it seems to be fine
{
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "commonjs",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"types": [
"es6-promise",
"es6-collections",
"webpack-env"
]
}
}

I had the same error today when I set up SharePoint framework.
You need to use the following command:
npm install #microsoft/sp-webpart-base

Related

TypeError: (intermediate value).mandatoryProps is not iterable

I'm getting this error after using transpiled javascript from typescript code.
super keyword is not working as it supposed to I'm trying to access a one property of parent class but it throws error saying TypeError: (intermediate value).mandatoryProps is not iterable
tsconfig.json
{
"compilerOptions": {
"module": "CommonJS",
"declaration": true,
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"moduleResolution": "node",
"target": "es6",
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"outDir": "src",
},
"include": [
"lib/**/*.ts"
],
"exclude": [
"node_modules",
]
}
actual typescript file
export abstract class VMSchemaRegistryEvent extends VMEvent {
#Transform(({ value }) =>
Object.values(SchemaRegistryNotificationSubject).find((code) => code == value)
|| Object.values(SchemaRegistryRequestEventSubject).find((code) => code == value)
|| Object.values(SchemaRegistryErrorEventSubject).find((code) => code == value))
schemaRegistryEventSubject: SchemaRegistryEventSubject;
constructor(schemaRegistryEventSubject: SchemaRegistryEventSubject) {
super(
new VMEventIdentity(vmEventsSpecBuilder.buildSchemaRegistryEventName(schemaRegistryEventSubject),
SCHEMA_REGISTRY_NAMESPACE_CONST))
this.schemaRegistryEventSubject = schemaRegistryEventSubject;
}
static fromPlainObject(baseEvent: any): VMSchemaRegistryEvent {
return vmEventsSpecBuilder.buildSchemaRegistryConcreteEventFromBaseEvent(baseEvent)
}
#Expose()
get toPlainObject(): StringIndexedObject {
let objectToReturn: StringIndexedObject = { ...super.toPlainObject }
objectToReturn[VMEventPropertyKeys.SCHEMA_REGISTRY_EVENT_SUBJECT_KEY] = this.schemaRegistryEventSubject;
return objectToReturn;
}
mandatoryProps: VMEventPropertyKeys[] = [...super.mandatoryProps, VMEventPropertyKeys.SCHEMA_REGISTRY_EVENT_SUBJECT_KEY]
}
export class VMEvent implements Publishable, Buildable {
#Type(() => ObjectId)
#Transform(({ value }) => resolveTimeBasedId(value))
_id?: ObjectId;
#Type(() => VMEventIdentity)
eventIdentity: VMEventIdentity;
constructor(eventIdentity: object | VMEventIdentity, _id?: string | ObjectId | ObjectIdLike) {
this._id = resolveOrGenerateTimeBasedId(_id);
if (vmEventsSpecResolver.isVMEventIdentity(eventIdentity)) {
this.eventIdentity = eventIdentity;
} else {
this.eventIdentity = VMEventIdentity.fromPlainObject(eventIdentity);
}
}
static fromPlainObject(eventPlain: object): VMEvent {
return plainToClass(VMEvent, eventPlain);
}
#Expose()
get toPlainObject(): StringIndexedObject {
let objectToReturn: StringIndexedObject = {};
objectToReturn[VMEventPropertyKeys.EVENT_IDENTITY_KEY] = this.eventIdentity.toPlainObject
objectToReturn[VMEventPropertyKeys.OBJECT_ID_KEY] = this._id
return objectToReturn;
}
mandatoryProps: VMEventPropertyKeys[] = [VMEventPropertyKeys.EVENT_IDENTITY_KEY]
}
transpiled Javascript
class VMSchemaRegistryEvent extends vmBaseEvent_1.VMEvent {
constructor(schemaRegistryEventSubject) {
super(new vmBaseEvent_1.VMEventIdentity(vmEventsSpecBuilder_1.vmEventsSpecBuilder.buildSchemaRegistryEventName(schemaRegistryEventSubject), vmEventCommonTypes_1.SCHEMA_REGISTRY_NAMESPACE_CONST));
this.mandatoryProps = [...super.mandatoryProps, vmEventPropertyKeys_1.VMEventPropertyKeys.SCHEMA_REGISTRY_EVENT_SUBJECT_KEY];
this.schemaRegistryEventSubject = schemaRegistryEventSubject;
}
static fromPlainObject(baseEvent) {
return vmEventsSpecBuilder_1.vmEventsSpecBuilder.buildSchemaRegistryConcreteEventFromBaseEvent(baseEvent);
}
get toPlainObject() {
let objectToReturn = { ...super.toPlainObject };
objectToReturn[vmEventPropertyKeys_1.VMEventPropertyKeys.SCHEMA_REGISTRY_EVENT_SUBJECT_KEY] = this.schemaRegistryEventSubject;
return objectToReturn;
}
}
class VMEvent {
constructor(eventIdentity, _id) {
this.mandatoryProps = [vmEventPropertyKeys_1.VMEventPropertyKeys.EVENT_IDENTITY_KEY];
this._id = utils_1.resolveOrGenerateTimeBasedId(_id);
if (vmEventsSpecResolver_1.vmEventsSpecResolver.isVMEventIdentity(eventIdentity)) {
this.eventIdentity = eventIdentity;
}
else {
this.eventIdentity = VMEventIdentity.fromPlainObject(eventIdentity);
}
}
static fromPlainObject(eventPlain) {
return class_transformer_1.plainToClass(VMEvent, eventPlain);
}
get toPlainObject() {
let objectToReturn = {};
objectToReturn[vmEventPropertyKeys_1.VMEventPropertyKeys.EVENT_IDENTITY_KEY] = this.eventIdentity.toPlainObject;
objectToReturn[vmEventPropertyKeys_1.VMEventPropertyKeys.OBJECT_ID_KEY] = this._id;
return objectToReturn;
}
}

How can I rewrite/repack code written for AMD to CommonJs without bundling it?

I have a project written for browser using AMD modules, now I need to run the same code in nodejs, so I need to rewrite each file into using CommonJs modules instead. I tried webpack, but it gives me a bundle which I don't need. All I want is to keep my files like they are but rewrite define(.. imports to require(..)
thank to Felix Kling's advice i wrote the following transformer in typescript
import { FileInfo, API, Options } from 'jscodeshift';
import { resolve, normalize, relative } from 'path';
export default function transformer(file: FileInfo, api: API, options: Options) {
const { j } = api;
return j(file.source)
.find(j.ExpressionStatement, { expression: { callee: { name: 'define' } } })
.replaceWith(({ node }) => {
const { expression: defineCallExpression } = node;
if (defineCallExpression.type !== 'CallExpression') return crash('No call to define function of AMD.');
const [moduleLocationsArray, callback] = defineCallExpression.arguments;
if (callback.type !== 'FunctionExpression') return;
if (moduleLocationsArray.type !== 'ArrayExpression') return;
const imports = moduleLocationsArray.elements.map((element, index) => {
if (element === null) return crash('Module name skipped.');
if (element.type !== 'Literal') return crash('Module name is not a literal');
const param = callback.params[index];
if (param.type !== 'Identifier') return crash('Module parameter is not an identifier.');
return {
location: element.value as string,
name: param.name,
};
}).filter(pair => shouldKeepModule(pair.location));
const filePath = normalize(resolve(__dirname, file.path));
const baseDir = normalize(resolve(__dirname, options.where));
const importStatements = imports.map(({name, location}) => {
const modulePath = normalize(resolve(baseDir, location));
const relativeModuleName = slashings(relative(filePath, modulePath));
const text = `const ${name} = require('${relativeModuleName}');`;
const statement = api.j(text, options);
return statement;
});
const statementsBefore = callback.body.body;
const statementsAfter = [...importStatements, ...statementsBefore];
return statementsAfter;
})
.toSource();
}
function shouldKeepModule(location: string): boolean {
return location !== 'module' && location !== 'exports' && location !== 'require';
}
function crash(message: string): never { throw new Error(message); }
function slashings(text: string): string { return text.replace(/\\/g, '/'); }
with the following tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"strict": true,
"target": "es6",
"module": "commonjs",
"lib": ["es6"],
"types": ["node", "jscodeshift"],
"outDir": "../../node_modules/amd-to-commonjs"
}
}
with the following package.json
{
"private": true,
"devDependencies": {
"#types/node": "7.0.4",
"#types/jscodeshift": "0.6.0",
"jscodeshift": "0.6.3",
"typescript": "3.4.0-dev.20190227"
}
}
built by the following command
npm install
node ../../node_modules/typescript/bin/tsc --project ./
and run by the following command
node ../../node_modules/jscodeshift/bin/jscodeshift.js --transform=../../node_modules/amd-to-commonjs/transformer.js --where=../../scripts/built ../../scripts/built

How to read json file in typescript?

I am trying to get object from api.json but it throws error , based on typescript i have added declare module "*.json" into the project , Any idea how can i achieve this task ?
api.json
{
"Refills": {
"getPatientInfo": "Refills/patientInfo/GetPatientInfo"
}
}
index.ts
import {ModuleExecutor} from "./common/ModuleExecutor";
import {Identity} from "./common/Enums";
export class Index {
private executor: ModuleExecutor = null;
// Any string prepended with # is handled by grunt before building the project
// grunt dynamically reads the config/api.json and loads only the apis that are listed there
// api.json consists of the API name and the folder path for grunt
private _apisConfig: string = '#api'
constructor(identity: string) {
this.executor = new ModuleExecutor(Identity[identity]);
const apiConfig = JSON.parse(this._apisConfig);
console.log('API', apiConfig);
for (const module in apiConfig) {
if (apiConfig.hasOwnProperty(module)) {
this[module] = {};
for (const api in apiConfig[module]) {
if (apiConfig[module].hasOwnProperty(api)) {
this[module][api] = this.executor.execute(apiConfig[module][api]);
}
}
}
}
}
}
Error
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
Compiled index.js file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ModuleExecutor_1 = require("./common/ModuleExecutor");
const Enums_1 = require("./common/Enums");
class Index {
constructor(identity) {
this.executor = null;
this._apisConfig = '';
this.executor = new ModuleExecutor_1.ModuleExecutor(Enums_1.Identity[identity]);
const apiConfig = JSON.parse(this._apisConfig);
console.log('API', apiConfig);
for (const module in apiConfig) {
if (apiConfig.hasOwnProperty(module)) {
this[module] = {};
for (const api in apiConfig[module]) {
if (apiConfig[module].hasOwnProperty(api)) {
this[module][api] = this.executor.execute(apiConfig[module][api]);
}
}
}
}
}
}
exports.Index = Index;
//# sourceMappingURL=index.js.map

TS2307: Cannot find module 'calculator'

I am running an easy Sharepoint Framework project in Visual Studio Code:
I have this structure:
My files are as follows:
ComplexCalculator.ts
export class ComplexCalculator {
public sqr(v1: number): number {
return v1*v1;
}
public multiply(v1:number, v2:number): number {
return v1*v2;
}
}
EasyCalculator.ts
export class EasyCalculator {
public sum(v1: number, v2: number): number {
return v1 + v2;
}
public subtraction(v1: number, v2: number): number {
return v1 - v2;
}
}
Calculator.ts
export * from './ComplexCalculator';
export * from './EasyCalculator';
Calculator.manifest.json
{
"$schema": "../../../node_modules/#microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
"id": "8de800b0-6a4f-4cb0-bf75-62c32e6ea66b",
"componentType": "Library",
"version": "0.0.1",
"manifestVersion": 2
}
On my config.json I have this:
{
"entries": [
{
"entry": "./lib/webparts/librarysample/LibrarysampleWebPart.js",
"manifest": "./src/webparts/librarysample/LibrarysampleWebPart.manifest.json",
"outputPath": "./dist/librarysample.bundle.js"
},
{
"entry": "./lib/libraries/calculator/Calculator.js",
"manifest": "./src/libraries/calculator/Calculator.manifest.json",
"outputPath": "./dist/calculator.bundle.js"
}
],
"externals": {
"#microsoft/sp-client-base": "node_modules/#microsoft/sp-client-base/dist/sp-client-base.js",
"#microsoft/sp-client-preview": "node_modules/#microsoft/sp-client-preview/dist/sp-client-preview.js",
"#microsoft/sp-lodash-subset": "node_modules/#microsoft/sp-lodash-subset/dist/sp-lodash-subset.js",
"office-ui-fabric-react": "node_modules/office-ui-fabric-react/dist/office-ui-fabric-react.js",
"react": "node_modules/react/dist/react.min.js",
"react-dom": "node_modules/react-dom/dist/react-dom.min.js",
"react-dom/server": "node_modules/react-dom/dist/react-dom-server.min.js",
"calculator": "./dist/calculator.bundle.js"
},
"localizedResources": {
"librarysampleStrings": "webparts/librarysample/loc/{locale}.js"
}
}
and finally on my gulpfile.js
const gulp = require('gulp');
const build = require('#microsoft/sp-build-web');
var through = require('through2'),
util = require('gulp-util'),
spawn = require('child_process').spawn,
clean = require('gulp-clean'),
ts = require('gulp-typescript');
build.initialize(gulp);
var libsPath = 'lib/libraries';
var srcPath = 'src/libraries';
var calculatorLibraryFolder = 'calculator';
gulp.task('watch-calculator-lib', (cb) => {
var watcher = gulp.watch(`${srcPath}/${calculatorLibraryFolder}/**/*.ts`, ['update-calculator-typings']);
watcher.on('change', (event) => {
console.log(`File ${event.path} was ${event.type}, Rebuilding library typings...`);
});
});
gulp.task('update-calculator-typings', [
'update-calculator-typings:clean-old-typings',
'update-calculator-typings:get-latest-typings',
'update-calculator-typings:build-lib-typings'
], () => {
});
gulp.task('update-calculator-typings:clean-old-typings', () => {
return gulp.src(`${libsPath}/${calculatorLibraryFolder}/**`, { read: false })
.pipe(clean());
});
gulp.task('update-calculator-typings:get-latest-typings', ['update-calculator-typings:clean-old-typings'], () => {
var tsResult = gulp.src(`${srcPath}/${calculatorLibraryFolder}/**/*.ts`)
.pipe(ts({
outDir: `${libsPath}/${calculatorLibraryFolder}`,
module: 'umd',
declaration: true
}));
return tsResult.dts.pipe(gulp.dest(`${libsPath}/${calculatorLibraryFolder}`));
});
gulp.task('update-calculator-typings:build-lib-typings', ['update-calculator-typings:get-latest-typings'], () => {
return gulp.src(`${libsPath}/${calculatorLibraryFolder}/**/*.d.ts`)
.pipe(updateLibTypings('calculator.d.ts'))
.pipe(gulp.dest('./typings'));
});
var updateLibTypings = function (typingsFilePath, opt) {
var typings = ["declare module 'calculator' {"];
var latestFile;
function processTypings(file, encoding, cb) {
if (file.isNull() || file.isStream()) {
cb();
return;
}
latestFile = file;
var contents = file.contents.toString('utf8');
if (contents.indexOf('export declare class ') === -1) {
cb();
return;
}
contents = contents.replace('export declare class ', 'class ');
typings.push(contents);
cb();
}
function endStream(cb) {
if (!latestFile) {
cb();
return;
}
typings.push('}');
var file = latestFile.clone({ contents: false });
file.path = latestFile.base + typingsFilePath;
file.contents = new Buffer(typings.join('\r\n'));
this.push(file)
cb();
}
return through.obj(processTypings, endStream);
}
the typings file is generated correctly on the dist folder
calculator.d.ts
declare module 'calculator' {
class ComplexCalculator {
sqr(v1: number): number;
multiply(v1: number, v2: number): number;
}
class EasyCalculator {
sum(v1: number, v2: number): number;
subtraction(v1: number, v2: number): number;
}
}
However, when I try to reference it into my webpart file
import * as calculator from 'calculator';
and then I try to compile
I get this error
Error - typescript - src/webparts/librarysample/LibrarysampleWebPart.ts(13,29): error TS2307: Cannot find module 'calculator'.
Your code import * as calculator from 'calculator'; is wrong. You need to import modules in your project using relative paths. e.g.
import * as calculator from './path/to/Calculator';
More
Be careful about file casing. I prefer camelCase for consistency.
Master node_modules : https://nodejs.org/docs/latest/api/modules.html

How to Change gulpfile.babel.js to Add HTML Locations when Running Build?

Below is the original gulpfile that came when running the generator-angular-fullstack (basically - I removed a task from running in development).
I have HTML files in 'client/components/modal/templates/' that are not getting added to the project when I run gulp build, so when I try serving the built code, I got an error saying:
"Failed to load template: ./components/modal/templates/event.html (HTTP status: 404 Not Found)"
Can someone tell me what to change so the files in this location are brought into the project?
// Generated on 2016-06-21 using generator-angular-fullstack 3.7.6
'use strict';
import _ from 'lodash';
import del from 'del';
import gulp from 'gulp';
import grunt from 'grunt';
import path from 'path';
import gulpLoadPlugins from 'gulp-load-plugins';
import http from 'http';
import open from 'open';
import lazypipe from 'lazypipe';
import {stream as wiredep} from 'wiredep';
import nodemon from 'nodemon';
import {Server as KarmaServer} from 'karma';
import runSequence from 'run-sequence';
import {protractor, webdriver_update} from 'gulp-protractor';
import {Instrumenter} from 'isparta';
var plugins = gulpLoadPlugins();
var config;
const clientPath = require('./bower.json').appPath || 'client';
const serverPath = 'server';
const paths = {
client: {
assets: `${clientPath}/assets/**/*`,
images: `${clientPath}/assets/images/**/*`,
scripts: [
`${clientPath}/**/!(*.spec|*.mock).ts`,
`!${clientPath}/bower_components/**/*`,
`!${clientPath}/{typings,test_typings}/**/*`
],
styles: [`${clientPath}/{app,components}/**/*.less`],
mainStyle: `${clientPath}/app/app.less`,
views: `${clientPath}/{app,components}/**/*.html`,
mainView: `${clientPath}/index.html`,
test: [`${clientPath}/{app,components}/**/*.{spec,mock}.ts`],
e2e: ['e2e/**/*.spec.js'],
bower: `${clientPath}/bower_components/`
},
server: {
scripts: [
`${serverPath}/**/!(*.spec|*.integration).js`,
`!${serverPath}/config/local.env.sample.js`
],
json: [`${serverPath}/**/*.json`],
test: {
integration: [`${serverPath}/**/*.integration.js`, 'mocha.global.js'],
unit: [`${serverPath}/**/*.spec.js`, 'mocha.global.js']
}
},
karma: 'karma.conf.js',
dist: 'dist'
};
/********************
* Helper functions
********************/
function onServerLog(log) {
console.log(plugins.util.colors.white('[') +
plugins.util.colors.yellow('nodemon') +
plugins.util.colors.white('] ') +
log.message);
}
function checkAppReady(cb) {
var options = {
host: 'localhost',
port: config.port
};
http
.get(options, () => cb(true))
.on('error', () => cb(false));
}
// Call page until first success
function whenServerReady(cb) {
var serverReady = false;
var appReadyInterval = setInterval(() =>
checkAppReady((ready) => {
if (!ready || serverReady) {
return;
}
clearInterval(appReadyInterval);
serverReady = true;
cb();
}),
100);
}
function sortModulesFirst(a, b) {
var module = /\.module\.ts$/;
var aMod = module.test(a.path);
var bMod = module.test(b.path);
// inject *.module.js first
if (aMod === bMod) {
// either both modules or both non-modules, so just sort normally
if (a.path < b.path) {
return -1;
}
if (a.path > b.path) {
return 1;
}
return 0;
} else {
return (aMod ? -1 : 1);
}
}
/********************
* Reusable pipelines
********************/
let lintClientScripts = lazypipe()
.pipe(plugins.tslint, require(`./${clientPath}/tslint.json`))
.pipe(plugins.tslint.report, 'verbose');
let lintServerScripts = lazypipe()
.pipe(plugins.jshint, `${serverPath}/.jshintrc`)
.pipe(plugins.jshint.reporter, 'jshint-stylish');
let lintServerTestScripts = lazypipe()
.pipe(plugins.jshint, `${serverPath}/.jshintrc-spec`)
.pipe(plugins.jshint.reporter, 'jshint-stylish');
let styles = lazypipe()
.pipe(plugins.sourcemaps.init)
.pipe(plugins.less)
.pipe(plugins.autoprefixer, {browsers: ['last 1 version']})
.pipe(plugins.sourcemaps.write, '.');
let transpileServer = lazypipe()
.pipe(plugins.sourcemaps.init)
.pipe(plugins.babel, {
plugins: [
'transform-class-properties',
'transform-runtime'
]
})
.pipe(plugins.sourcemaps.write, '.');
let mocha = lazypipe()
.pipe(plugins.mocha, {
reporter: 'spec',
timeout: 5000,
require: [
'./mocha.conf'
]
});
let istanbul = lazypipe()
.pipe(plugins.istanbul.writeReports)
.pipe(plugins.istanbulEnforcer, {
thresholds: {
global: {
lines: 80,
statements: 80,
branches: 80,
functions: 80
}
},
coverageDirectory: './coverage',
rootDirectory : ''
});
/********************
* Env
********************/
gulp.task('env:all', () => {
let localConfig;
try {
localConfig = require(`./${serverPath}/config/local.env`);
} catch (e) {
localConfig = {};
}
plugins.env({
vars: localConfig
});
});
gulp.task('env:test', () => {
plugins.env({
vars: {NODE_ENV: 'test'}
});
});
gulp.task('env:prod', () => {
plugins.env({
vars: {NODE_ENV: 'production'}
});
});
/********************
* Tasks
********************/
gulp.task('inject', cb => {
runSequence(['inject:js', 'inject:css', 'inject:less', 'inject:tsconfig'], cb);
});
gulp.task('inject:js', () => {
return gulp.src(paths.client.mainView)
.pipe(plugins.inject(
gulp.src(_.union(paths.client.scripts, ['client/app/app.constant.js', `!${clientPath}/**/*.{spec,mock}.ts`, `!${clientPath}/app/app.ts`]), {read: false})
.pipe(plugins.sort(sortModulesFirst)),
{
starttag: '<!-- injector:js -->',
endtag: '<!-- endinjector -->',
transform: (filepath) => '<script src="' + filepath.replace(`/${clientPath}/`, '').replace('.ts', '.js') + '"></script>'
}))
.pipe(gulp.dest(clientPath));
});
function injectTsConfig(filesGlob, tsconfigPath){
let src = gulp.src(filesGlob, {read: false})
.pipe(plugins.sort());
return gulp.src(tsconfigPath)
.pipe(plugins.inject(src, {
starttag: '"files": [',
endtag: ']',
transform: (filepath, file, i, length) => {
return `"${filepath.substr(1)}"${i + 1 < length ? ',' : ''}`;
}
}))
.pipe(gulp.dest('./'));
}
gulp.task('inject:tsconfig', () => {
return injectTsConfig([
`${clientPath}/**/!(*.spec|*.mock).ts`,
`!${clientPath}/bower_components/**/*`,
`typings/main.d.ts`
],
'./tsconfig.client.json');
});
gulp.task('inject:tsconfigTest', () => {
return injectTsConfig([
`${clientPath}/**/+(*.spec|*.mock).ts`,
`!${clientPath}/bower_components/**/*`,
`typings/main.d.ts`
],
'./tsconfig.client.test.json');
});
gulp.task('inject:css', () => {
return gulp.src(paths.client.mainView)
.pipe(plugins.inject(
gulp.src(`${clientPath}/{app,components}/**/*.css`, {read: false})
.pipe(plugins.sort()),
{
starttag: '<!-- injector:css -->',
endtag: '<!-- endinjector -->',
transform: (filepath) => '<link rel="stylesheet" href="' + filepath.replace(`/${clientPath}/`, '').replace('/.tmp/', '') + '">'
}))
.pipe(gulp.dest(clientPath));
});
gulp.task('inject:less', () => {
return gulp.src(paths.client.mainStyle)
.pipe(plugins.inject(
gulp.src(_.union(paths.client.styles, ['!' + paths.client.mainStyle]), {read: false})
.pipe(plugins.sort()),
{
transform: (filepath) => {
let newPath = filepath
.replace(`/${clientPath}/app/`, '')
.replace(`/${clientPath}/components/`, '../components/')
.replace(/_(.*).less/, (match, p1, offset, string) => p1)
.replace('.less', '');
return `#import '${newPath}';`;
}
}))
.pipe(gulp.dest(`${clientPath}/app`));
});
// Install DefinitelyTyped TypeScript definition files
gulp.task('typings', () => {
return gulp.src("./typings.json")
.pipe(plugins.typings());
});
gulp.task('styles', () => {
return gulp.src(paths.client.mainStyle)
.pipe(styles())
.pipe(gulp.dest('.tmp/app'));
});
gulp.task('copy:constant', ['constant'], () => {
return gulp.src(`${clientPath}/app/app.constant.js`, { dot: true })
.pipe(gulp.dest('.tmp/app'));
})
gulp.task('transpile:client', ['typings', 'copy:constant'], () => {
return gulp.src(['client/{app,components}/**/!(*.spec|*.mock).ts', 'typings/main.d.ts'])
.pipe(plugins.sourcemaps.init())
.pipe(plugins.typescript()).js
.pipe(plugins.sourcemaps.write('.'))
.pipe(gulp.dest('.tmp'));
});
gulp.task('transpile:client:test', ['typings'], () => {
return gulp.src(['client/{app,components}/**/+(*.spec|*.mock).ts', 'typings/main.d.ts'])
.pipe(plugins.sourcemaps.init())
.pipe(plugins.typescript()).js
.pipe(plugins.sourcemaps.write('.'))
.pipe(gulp.dest('.tmp/test'));
});
gulp.task('transpile:server', () => {
return gulp.src(_.union(paths.server.scripts, paths.server.json))
.pipe(transpileServer())
.pipe(gulp.dest(`${paths.dist}/${serverPath}`));
});
gulp.task('lint:scripts', cb => runSequence(['lint:scripts:client', 'lint:scripts:server'], cb));
gulp.task('lint:scripts:client', () => {
return gulp.src(_.union(
paths.client.scripts,
_.map(paths.client.test, blob => '!' + blob),
[`!${clientPath}/app/app.constant.ts`]
))
.pipe(lintClientScripts());
});
gulp.task('lint:scripts:server', () => {
return gulp.src(_.union(paths.server.scripts, _.map(paths.server.test, blob => '!' + blob)))
.pipe(lintServerScripts());
});
gulp.task('lint:scripts:clientTest', () => {
return gulp.src(paths.client.test)
.pipe(lintClientScripts());
});
gulp.task('lint:scripts:serverTest', () => {
return gulp.src(paths.server.test)
.pipe(lintServerTestScripts());
});
gulp.task('jscs', () => {
return gulp.src(_.union(paths.client.scripts, paths.server.scripts))
.pipe(plugins.jscs())
.pipe(plugins.jscs.reporter());
});
gulp.task('clean:tmp', () => del(['.tmp/**/*'], {dot: true}));
gulp.task('start:client', cb => {
whenServerReady(() => {
open('http://localhost:' + config.port);
cb();
});
});
gulp.task('start:server', () => {
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
config = require(`./${serverPath}/config/environment`);
nodemon(`-w ${serverPath} ${serverPath}`)
.on('log', onServerLog);
});
gulp.task('start:server:prod', () => {
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
config = require(`./${paths.dist}/${serverPath}/config/environment`);
nodemon(`-w ${paths.dist}/${serverPath} ${paths.dist}/${serverPath}`)
.on('log', onServerLog);
});
gulp.task('start:inspector', () => {
gulp.src([])
.pipe(plugins.nodeInspector());
});
gulp.task('start:server:debug', () => {
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
config = require(`./${serverPath}/config/environment`);
nodemon(`-w ${serverPath} --debug-brk ${serverPath}`)
.on('log', onServerLog);
});
gulp.task('watch', () => {
var testFiles = _.union(paths.client.test, paths.server.test.unit, paths.server.test.integration);
plugins.livereload.listen();
plugins.watch(paths.client.styles, () => { //['inject:less']
gulp.src(paths.client.mainStyle)
.pipe(plugins.plumber())
.pipe(styles())
.pipe(gulp.dest('.tmp/app'))
.pipe(plugins.livereload());
});
plugins.watch(paths.client.views)
.pipe(plugins.plumber())
.pipe(plugins.livereload());
gulp.watch(paths.client.scripts, ['transpile:client']);// gulp.watch(paths.client.scripts, ['lint:scripts:client', 'transpile:client']);
plugins.watch(_.union(paths.server.scripts, testFiles))
.pipe(plugins.plumber())
.pipe(lintServerScripts())
.pipe(plugins.livereload());
gulp.watch('bower.json', ['wiredep:client']);
});
gulp.task('serve', cb => {
runSequence(['clean:tmp', 'constant', 'env:all', 'typings'],
['inject'],// ['lint:scripts', 'inject'],
['wiredep:client'],
['transpile:client', 'styles'],
['start:server', 'start:client'],
'watch',
cb);
});
gulp.task('serve:dist', cb => {
runSequence(
'build',
'env:all',
'env:prod',
['start:server:prod', 'start:client'],
cb);
});
gulp.task('serve:debug', cb => {
runSequence(['clean:tmp', 'constant', 'typings'],
['lint:scripts', 'inject'],
['wiredep:client'],
['transpile:client', 'styles'],
'start:inspector',
['start:server:debug', 'start:client'],
'watch',
cb);
});
gulp.task('test', cb => {
return runSequence('test:server', 'test:client', cb);
});
gulp.task('test:server', cb => {
runSequence(
'env:all',
'env:test',
'mocha:unit',
'mocha:integration',
'mocha:coverage',
cb);
});
gulp.task('mocha:unit', () => {
return gulp.src(paths.server.test.unit)
.pipe(mocha());
});
gulp.task('mocha:integration', () => {
return gulp.src(paths.server.test.integration)
.pipe(mocha());
});
gulp.task('test:client', ['wiredep:test', 'constant', 'transpile:client', 'transpile:client:test'], (done) => {
new KarmaServer({
configFile: `${__dirname}/${paths.karma}`,
singleRun: true
}, done).start();
});
// inject bower components
gulp.task('wiredep:client', () => {
return gulp.src(paths.client.mainView)
.pipe(wiredep({
exclude: [
/bootstrap.js/,
'/json3/',
'/es5-shim/',
/font-awesome\.css/,
/bootstrap\.css/
],
ignorePath: clientPath
}))
.pipe(gulp.dest(`${clientPath}/`));
});
gulp.task('wiredep:test', () => {
return gulp.src(paths.karma)
.pipe(wiredep({
exclude: [
/bootstrap.js/,
'/json3/',
'/es5-shim/',
/font-awesome\.css/,
/bootstrap\.css/
],
devDependencies: true
}))
.pipe(gulp.dest('./'));
});
/********************
* Build
********************/
//FIXME: looks like font-awesome isn't getting loaded
gulp.task('build', cb => {
runSequence(
[
'clean:dist',
'clean:tmp'
],
'inject',
'wiredep:client',
'typings',
[
'transpile:client',
'transpile:server'
],
[
'build:images',
'copy:extras',
'copy:fonts',
'copy:assets',
'copy:server',
'build:client'
],
cb);
});
gulp.task('clean:dist', () => del([`${paths.dist}/!(.git*|.openshift|Procfile)**`], {dot: true}));
gulp.task('build:client', ['styles', 'html', 'constant', 'build:images'], () => {
var manifest = gulp.src(`${paths.dist}/${clientPath}/assets/rev-manifest.json`);
var appFilter = plugins.filter('**/app.js', {restore: true});
var jsFilter = plugins.filter('**/*.js', {restore: true});
var cssFilter = plugins.filter('**/*.css', {restore: true});
var htmlBlock = plugins.filter(['**/*.!(html)'], {restore: true});
return gulp.src(paths.client.mainView)
.pipe(plugins.useref())
.pipe(appFilter)
.pipe(plugins.addSrc.append('.tmp/templates.js'))
.pipe(plugins.concat('app/app.js'))
.pipe(appFilter.restore)
.pipe(jsFilter)
.pipe(plugins.ngAnnotate())
.pipe(plugins.uglify())
.pipe(jsFilter.restore)
.pipe(cssFilter)
.pipe(plugins.cleanCss({
processImportFrom: ['!fonts.googleapis.com']
}))
.pipe(cssFilter.restore)
.pipe(htmlBlock)
.pipe(plugins.rev())
.pipe(htmlBlock.restore)
.pipe(plugins.revReplace({manifest}))
.pipe(gulp.dest(`${paths.dist}/${clientPath}`));
});
gulp.task('html', function() {
return gulp.src(`${clientPath}/{app,components}/**/*.html`)
.pipe(plugins.angularTemplatecache({
module: 'intranetApp'
}))
.pipe(gulp.dest('.tmp'));
});
gulp.task('constant', function() {
let sharedConfig = require(`./${serverPath}/config/environment/shared`);
return plugins.ngConstant({
name: 'intranetApp.constants',
deps: [],
wrap: true,
stream: true,
constants: { appConfig: sharedConfig }
})
.pipe(plugins.rename({
basename: 'app.constant'
}))
.pipe(gulp.dest(`${clientPath}/app/`))
});
gulp.task('build:images', () => {
return gulp.src(paths.client.images)
.pipe(plugins.imagemin({
optimizationLevel: 5,
progressive: true,
interlaced: true
}))
.pipe(plugins.rev())
.pipe(gulp.dest(`${paths.dist}/${clientPath}/assets/images`))
.pipe(plugins.rev.manifest(`${paths.dist}/${clientPath}/assets/rev-manifest.json`, {
base: `${paths.dist}/${clientPath}/assets`,
merge: true
}))
.pipe(gulp.dest(`${paths.dist}/${clientPath}/assets`));
});
gulp.task('copy:extras', () => {
return gulp.src([
`${clientPath}/favicon.ico`,
`${clientPath}/robots.txt`,
`${clientPath}/.htaccess`
], { dot: true })
.pipe(gulp.dest(`${paths.dist}/${clientPath}`));
});
gulp.task('copy:fonts', () => {
return gulp.src(`${clientPath}/bower_components/{bootstrap,font-awesome}/fonts/**/*`, { dot: true })
.pipe(gulp.dest(`${paths.dist}/${clientPath}/bower_components`));
});
gulp.task('copy:assets', () => {
return gulp.src([paths.client.assets, '!' + paths.client.images])
.pipe(gulp.dest(`${paths.dist}/${clientPath}/assets`));
});
gulp.task('copy:server', () => {
return gulp.src([
'package.json',
'bower.json',
'.bowerrc'
], {cwdbase: true})
.pipe(gulp.dest(paths.dist));
});
gulp.task('coverage:pre', () => {
return gulp.src(paths.server.scripts)
// Covering files
.pipe(plugins.istanbul({
instrumenter: Instrumenter, // Use the isparta instrumenter (code coverage for ES6)
includeUntested: true
}))
// Force `require` to return covered files
.pipe(plugins.istanbul.hookRequire());
});
gulp.task('coverage:unit', () => {
return gulp.src(paths.server.test.unit)
.pipe(mocha())
.pipe(istanbul())
// Creating the reports after tests ran
});
gulp.task('coverage:integration', () => {
return gulp.src(paths.server.test.integration)
.pipe(mocha())
.pipe(istanbul())
// Creating the reports after tests ran
});
gulp.task('mocha:coverage', cb => {
runSequence('coverage:pre',
'env:all',
'env:test',
'coverage:unit',
'coverage:integration',
cb);
});
// Downloads the selenium webdriver
gulp.task('webdriver_update', webdriver_update);
gulp.task('test:e2e', ['env:all', 'env:test', 'start:server', 'webdriver_update'], cb => {
gulp.src(paths.client.e2e)
.pipe(protractor({
configFile: 'protractor.conf.js',
})).on('error', err => {
console.log(err)
}).on('end', () => {
process.exit();
});
});
/********************
* Grunt ported tasks
********************/
grunt.initConfig({
buildcontrol: {
options: {
dir: paths.dist,
commit: true,
push: true,
connectCommits: false,
message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
},
heroku: {
options: {
remote: 'heroku',
branch: 'master'
}
},
openshift: {
options: {
remote: 'openshift',
branch: 'master'
}
}
}
});
grunt.loadNpmTasks('grunt-build-control');
gulp.task('buildcontrol:heroku', function(done) {
grunt.tasks(
['buildcontrol:heroku'], //you can add more grunt tasks in this array
{gruntfile: false}, //don't look for a Gruntfile - there is none. :-)
function() {done();}
);
});
gulp.task('buildcontrol:openshift', function(done) {
grunt.tasks(
['buildcontrol:openshift'], //you can add more grunt tasks in this array
{gruntfile: false}, //don't look for a Gruntfile - there is none. :-)
function() {done();}
);
});
In case anyone stumbles on the same issue... the gulpfile actually does find files in places that aren't really standard (like inside subfolders of places where they'd normally be at). My problem was that I specified the dot (.) in the beginning. When I changed the paths to components/modal/someFolder/someFile.html it worked fine. The relative path I initially had gets messed up in production.

Categories