0

I am writing a basic Angular 2 app. I am creating a class User that has a function validPassword() that uses bcrypt to validate a password:

import { compareSync, genSaltSync, hashSync } from 'bcrypt';
import { Document, Schema, model } from 'mongoose';

export class User {
  username: string;
  password: string;

  isValidPassword(password: string): boolean {
    return compareSync(password, this.password)
  }
}

let userSchema = new Schema({
  username: { required: true, type: String },
  password: { required: true, type: String }
}, { timestamps: true });

userSchema.pre('save', function (next) {
  this.password = hashSync(this.password, genSaltSync(8));
  next();
});

export interface UserDocument extends User, Document {}

export const Users = model<UserDocument>('User', userSchema);

As you see, I am using the bcrypt and mongoose npm packages.

My SystemJS is configured as follows:

(function (global) {
  System.config({
    map: {
      '@angular': 'node_modules/@angular',
      'bcrypt': 'node_modules/bcrypt',
      'bindings': 'node_modules/bindings',
      'mongoose': 'node_modules/mongoose',
      'rxjs': 'node_modules/rxjs'
    },
    paths: {
      'node_modules/@angular/*': 'node_modules/@angular/*/bundles'
    },
    meta: {
      '@angular/*': {'format': 'cjs'}
    },
    packages: {
      'src': {main: 'main', defaultExtension: 'js'},
      '@angular/core': {main: 'core.umd.min.js'},
      '@angular/common': {main: 'common.umd.min.js'},
      '@angular/compiler': {main: 'compiler.umd.min.js'},
      '@angular/forms': {main: 'forms.umd.min.js'},
      '@angular/http': {main: 'http.umd.min.js'},
      '@angular/platform-browser': {main: 'platform-browser.umd.min.js'},
      '@angular/platform-browser-dynamic': {main:'platform-browser-dynamic.umd.min.js'},
      'bcrypt': {main: 'bCrypt.js'},
      'mongoose': {main: 'index.js'},
      'rxjs': {defaultExtension: 'js'}
    }
  });
}(this));

My typings dependencies are:

{
  "globalDependencies": {
    "bcrypt": "registry:dt/bcrypt#0.0.0+20160316155526",
    "core-js": "registry:dt/core-js#0.0.0+20160914114559",
    "jasmine": "registry:dt/jasmine#2.5.0+20161003201800",
    "mongodb": "registry:dt/mongodb#2.1.0+20160602142941",
    "mongoose": "registry:dt/mongoose#4.5.9+20161010180758",
    "node": "registry:dt/node#6.0.0+20161014191813"
  }
}

My tsconfig is as follows:

{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

When I go to run the project, the following errors display in the console:

1274 GET http://localhost:8080/crypto 404 (Not Found)
http://localhost:8080/node_modules/mongoose/lib.js 404 (Not Found)
http://localhost:8080/node_modules/bindings/ 404 (Not Found)

I understand this is a SystemJS issue. When I go to add, say,

'bindings': 'node_modules/bindings'

to the map object and,

'bindings': {main: 'bindings.js'},

to the packages object in SystemJS, I get a whole new set of errors (cannot find fs and path).

Should I be manually adding all missing package paths each time I install a new package? Is there a better way to do this?

4
  • A better way would be to use the Angular CLI, does a lot of things automatically. And makes it easier to include 3rd party scripts. Commented Oct 17, 2016 at 4:44
  • Thank you. I've done this and it still won't work. The require function is then not found. Commented Oct 17, 2016 at 12:43
  • did you fixed it? i have the same problem. Commented Dec 4, 2016 at 18:41
  • I had to use an entirely different module loader. However, if you're using angular-cli, you probably won't have this problem. Commented Dec 5, 2016 at 12:48

2 Answers 2

1

I recently had the same issue when bundling my server-side into one file with SystemJS. The problem, at least with mongoose (and I suspect the others), is that SystemJS does not support node extension format so it doesn't understand to look for index.js inside the "./lib" folder. And even if you add "mongoose/lib" to your System.config, mongoose depends on a slew of node modules that would require an obnoxious amount of mapping in your System.config.package.mongoose to compensate.

A solution that I've found is to create a new System module and set it to the "package" that you need, above your System.config.

System.set('package', System.newModule({
  default: require('package') 
}));

Unfortunately if you're using typescript your import statements require your "package" to have a type. These are basically just a set of interfaces and abstract classes so that your entire typescript project can understand the "package" library has functions, classes, etc...

But some package types, like mongoose, do not have a default export. So if you set the mongoose module like above and import like below..

import mongoose from 'mongoose';

you are sure to get either transpiler or IDE typescript errors because as said above the typings type does not have a corresponding default export.

To fix this just set allowSyntheticDefaultImports option to true in your tsconfig.json

Hope this helps :)

Sign up to request clarification or add additional context in comments.

Comments

0

I was stuck with the same problem for some time, and I was using Angular-cli so guess no SystemJs involved. I was trying to load 'diff' node module, and following worked for me:

import * as JsDiff from 'diff';

Source: https://medium.com/@s_eschweiler/using-external-libraries-with-angular-2-87e06db8e5d1

Hope it helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.