added hal serializer

This commit is contained in:
Art Lowel
2017-02-14 09:51:13 +01:00
parent b8ee768d0e
commit adc79e957f
15 changed files with 833 additions and 2 deletions

16
npm-shrinkwrap.json generated
View File

@@ -220,6 +220,12 @@
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.41.tgz", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.41.tgz",
"dev": true "dev": true
}, },
"@types/jsonschema": {
"version": "0.0.5",
"from": "@types/jsonschema@0.0.5",
"resolved": "https://registry.npmjs.org/@types/jsonschema/-/jsonschema-0.0.5.tgz",
"dev": true
},
"@types/lodash": { "@types/lodash": {
"version": "4.14.50", "version": "4.14.50",
"from": "@types/lodash@>=4.14.37 <5.0.0", "from": "@types/lodash@>=4.14.37 <5.0.0",
@@ -951,6 +957,11 @@
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"dev": true "dev": true
}, },
"cerialize": {
"version": "0.1.13",
"from": "cerialize@>=0.1.13 <0.2.0",
"resolved": "https://registry.npmjs.org/cerialize/-/cerialize-0.1.13.tgz"
},
"chalk": { "chalk": {
"version": "1.1.3", "version": "1.1.3",
"from": "chalk@>=1.1.3 <2.0.0", "from": "chalk@>=1.1.3 <2.0.0",
@@ -3150,6 +3161,11 @@
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
"dev": true "dev": true
}, },
"jsonschema": {
"version": "1.1.1",
"from": "jsonschema@>=1.1.1 <2.0.0",
"resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.1.1.tgz"
},
"jsprim": { "jsprim": {
"version": "1.3.1", "version": "1.3.1",
"from": "jsprim@>=1.2.2 <2.0.0", "from": "jsprim@>=1.2.2 <2.0.0",

View File

@@ -83,6 +83,7 @@
"@ngrx/router-store": "^1.2.5", "@ngrx/router-store": "^1.2.5",
"@ngrx/store": "^2.2.1", "@ngrx/store": "^2.2.1",
"@ngrx/store-devtools": "^3.2.2", "@ngrx/store-devtools": "^3.2.2",
"@types/jsonschema": "0.0.5",
"angular2-express-engine": "2.1.0-rc.1", "angular2-express-engine": "2.1.0-rc.1",
"angular2-platform-node": "2.1.0-rc.1", "angular2-platform-node": "2.1.0-rc.1",
"angular2-universal": "2.1.0-rc.1", "angular2-universal": "2.1.0-rc.1",
@@ -90,11 +91,13 @@
"autoprefixer": "^6.5.4", "autoprefixer": "^6.5.4",
"body-parser": "1.15.2", "body-parser": "1.15.2",
"bootstrap": "4.0.0-alpha.5", "bootstrap": "4.0.0-alpha.5",
"cerialize": "^0.1.13",
"compression": "1.6.2", "compression": "1.6.2",
"express": "4.14.0", "express": "4.14.0",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"http-server": "^0.9.0", "http-server": "^0.9.0",
"js.clone": "0.0.3", "js.clone": "0.0.3",
"jsonschema": "^1.1.1",
"methods": "1.1.2", "methods": "1.1.2",
"morgan": "1.7.0", "morgan": "1.7.0",
"ng2-translate": "4.2.0", "ng2-translate": "4.2.0",

View File

@@ -15,6 +15,7 @@ import { StoreDevtoolsModule } from "@ngrx/store-devtools";
import { rootReducer } from './app.reducers'; import { rootReducer } from './app.reducers';
import { effects } from './app.effects'; import { effects } from './app.effects';
import { CoreModule } from "./core/core.module";
@NgModule({ @NgModule({
declarations: [ declarations: [
@@ -25,6 +26,7 @@ import { effects } from './app.effects';
imports: [ imports: [
SharedModule, SharedModule,
HomeModule, HomeModule,
CoreModule.forRoot(),
AppRoutingModule, AppRoutingModule,
/** /**
* StoreModule.provideStore is imported once in the root module, accepting a reducer * StoreModule.provideStore is imported once in the root module, accepting a reducer

View File

@@ -0,0 +1,42 @@
import { NgModule, Optional, SkipSelf, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from "../shared/shared.module";
import { isNotEmpty } from "../shared/empty.util";
const IMPORTS = [
CommonModule,
];
const DECLARATIONS = [
];
const EXPORTS = [
];
const PROVIDERS = [
];
@NgModule({
imports: [ ...IMPORTS ],
declarations: [...DECLARATIONS],
exports: [...EXPORTS],
providers: [...PROVIDERS]
})
export class CoreModule {
constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
if (isNotEmpty(parentModule)) {
throw new Error(
'CoreModule is already loaded. Import it in the AppModule only');
}
}
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [
...PROVIDERS
]
};
}
}

View File

@@ -0,0 +1,4 @@
export interface DSpaceRESTV2Response {
_embedded?: any;
_links?: any;
}

View File

@@ -0,0 +1,93 @@
{
"title": "DSpace REST v2 json-schema",
"description": "Based on http://hyperschema.org/mediatypes/hal",
"type": "object",
"properties": {
"_links": {
"$ref": "#/definitions/links"
},
"_embedded": {
"$ref": "#/definitions/embedded"
}
},
"definitions": {
"links": {
"title": "HAL Links",
"description": "Object of links with the rels as the keys",
"type": "object",
"additionalProperties": {
"oneOf": [
{
"$ref": "#/definitions/linkObject"
},
{
"$ref": "#/definitions/linkArray"
}
]
}
},
"linkArray": {
"title": "HAL Link Array",
"description": "An array of linkObjects of the same link relation",
"type": "array",
"items": {
"$ref": "#/definitions/linkObject"
}
},
"linkObject": {
"title": "HAL Link Object",
"description": "An object with link information",
"type": "object",
"properties": {
"name": {
"$ref": "http://hyperschema.org/core/base#/definitions/name"
},
"href": {
"anyOf": [
{
"$ref": "http://hyperschema.org/core/link#/definitions/href"
},
{
"$ref": "http://hyperschema.org/core/link#/definitions/hrefTemplated"
}
]
},
"templated": {
"$ref": "http://hyperschema.org/core/link#/definitions/isTemplated"
},
"type": {
"$ref": "http://hyperschema.org/core/base#/definitions/mediaType"
},
"deprecation": {
"$ref": "http://hyperschema.org/core/link#/definitions/isDeprecated"
}
},
"required": [
"href"
]
},
"embedded": {
"title": "HAL Embedded Resource",
"description": "An embedded HAL resource",
"type": "object",
"additionalProperties": {
"oneOf": [
{
"$ref": "#"
},
{
"$ref": "#/definitions/embeddedArray"
}
]
}
},
"embeddedArray": {
"title": "HAL Embedded Array",
"description": "An array of embedded resources with the same link relation",
"type": "array",
"items": {
"$ref": "#"
}
}
}
}

View File

@@ -0,0 +1,201 @@
import { DSpaceRESTv2Serializer } from "./dspace-rest-v2.serializer";
import { autoserialize, autoserializeAs } from "cerialize";
class TestModel {
@autoserialize
id: string;
@autoserialize
name: string;
@autoserializeAs(TestModel)
parents?: Array<TestModel>;
}
const testModels = [
{
"id": "d4466d54-d73b-4d8f-b73f-c702020baa14",
"name": "Model 1",
},
{
"id": "752a1250-949a-46ad-9bea-fbc45f0b656d",
"name": "Model 2",
}
];
const testResponses = [
{
"_links": {
"self": "/testmodels/9e32a2e2-6b91-4236-a361-995ccdc14c60",
"parents": [
{ "href": "/testmodels/21539b1d-9ef1-4eda-9c77-49565b5bfb78" },
{ "href": "/testmodels/be8325f7-243b-49f4-8a4b-df2b793ff3b5" }
]
},
"id": "9e32a2e2-6b91-4236-a361-995ccdc14c60",
"type": "testModels",
"name": "A Test Model"
},
{
"_links": {
"self": "/testmodels/598ce822-c357-46f3-ab70-63724d02d6ad",
"parents": [
{ "href": "/testmodels/be8325f7-243b-49f4-8a4b-df2b793ff3b5" },
{ "href": "/testmodels/21539b1d-9ef1-4eda-9c77-49565b5bfb78" }
]
},
"id": "598ce822-c357-46f3-ab70-63724d02d6ad",
"type": "testModels",
"name": "Another Test Model"
}
];
const parentHrefRegex = /^\/testmodels\/(.+)$/g;
describe("DSpaceRESTv2Serializer", () => {
describe("serialize", () => {
it("should turn a model in to a valid document", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = serializer.serialize(testModels[0]);
expect(testModels[0].id).toBe(doc._embedded.id);
expect(testModels[0].name).toBe(doc._embedded.name);
});
});
describe("serializeArray", () => {
it("should turn an array of models in to a valid document", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = serializer.serializeArray(testModels);
expect(testModels[0].id).toBe(doc._embedded[0].id);
expect(testModels[0].name).toBe(doc._embedded[0].name);
expect(testModels[1].id).toBe(doc._embedded[1].id);
expect(testModels[1].name).toBe(doc._embedded[1].name);
});
});
describe("deserialize", () => {
it("should turn a valid document describing a single entity in to a valid model", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = {
"_embedded": testResponses[0],
};
const model = serializer.deserialize(doc);
expect(model.id).toBe(doc._embedded.id);
expect(model.name).toBe(doc._embedded.name);
});
//TODO cant implement/test this yet - depends on how relationships
// will be handled in the rest api
// it("should retain relationship information", () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel);
// const doc = {
// "_embedded": testResponses[0],
// };
//
// const model = serializer.deserialize(doc);
//
// console.log(model);
//
// const modelParentIds = model.parents.map(parent => parent.id).sort();
// const responseParentIds = doc._embedded._links.parents
// .map(parent => parent.href)
// .map(href => href.replace(parentHrefRegex, '$1'))
// .sort();
//
// expect(modelParentIds).toEqual(responseParentIds);
// });
// TODO enable once validation is enabled in the serializer
// it("should throw an error when dealing with an invalid document", () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel);
// const doc = testResponses[0];
//
// expect(() => {
// serializer.deserialize(doc);
// }).toThrow();
// });
it("should throw an error when dealing with a document describing an array", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = {
"_embedded": testResponses
};
expect(() => {
serializer.deserialize(doc);
}).toThrow();
});
});
describe("deserializeArray", () => {
it("should turn a valid document describing a collection of objects in to an array of valid models", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = {
"_embedded": testResponses
};
const models = serializer.deserializeArray(doc);
expect(models[0].id).toBe(doc._embedded[0].id);
expect(models[0].name).toBe(doc._embedded[0].name);
expect(models[1].id).toBe(doc._embedded[1].id);
expect(models[1].name).toBe(doc._embedded[1].name);
});
//TODO cant implement/test this yet - depends on how relationships
// will be handled in the rest api
// it("should retain relationship information", () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel);
// const doc = {
// "_embedded": testResponses,
// };
//
// const models = serializer.deserializeArray(doc);
//
// models.forEach((model, i) => {
// const modelParentIds = model.parents.map(parent => parent.id).sort();
// const responseParentIds = doc._embedded[i]._links.parents
// .map(parent => parent.href)
// .map(href => href.replace(parentHrefRegex, '$1'))
// .sort();
//
// expect(modelParentIds).toEqual(responseParentIds);
// });
// });
// TODO enable once validation is enabled in the serializer
// it("should throw an error when dealing with an invalid document", () => {
// const serializer = new DSpaceRESTv2Serializer(TestModel);
// const doc = testResponses[0];
//
// expect(() => {
// serializer.deserializeArray(doc);
// }).toThrow();
// });
it("should throw an error when dealing with a document describing a single model", () => {
const serializer = new DSpaceRESTv2Serializer(TestModel);
const doc = {
"_embedded": testResponses[0]
};
expect(() => {
serializer.deserializeArray(doc);
}).toThrow();
});
});
});

View File

@@ -0,0 +1,82 @@
import { Serialize, Deserialize } from "cerialize";
import { Serializer } from "../serializer";
import { DSpaceRESTV2Response } from "./dspace-rest-v2-response.model";
import { DSpaceRESTv2Validator } from "./dspace-rest-v2.validator";
/**
* ensures we can use 'typeof T' as a type
* more details:
* https://github.com/Microsoft/TypeScript/issues/204#issuecomment-257722306
*/
type Constructor<T> = { new (...args: any[]): T } | ((...args: any[]) => T) | Function;
/**
* This Serializer turns responses from v2 of DSpace's REST API
* to models and vice versa
*/
export class DSpaceRESTv2Serializer<T> implements Serializer<T> {
/**
* Create a new DSpaceRESTv2Serializer instance
*
* @param modelType a class or interface to indicate
* the kind of model this serializer should work with
*/
constructor(private modelType: Constructor<T>) {
}
/**
* Convert a model in to the format expected by the backend
*
* @param model The model to serialize
* @returns An object to send to the backend
*/
serialize(model: T): DSpaceRESTV2Response {
return {
"_embedded": Serialize(model, this.modelType)
};
}
/**
* Convert an array of models in to the format expected by the backend
*
* @param models The array of models to serialize
* @returns An object to send to the backend
*/
serializeArray(models: Array<T>): DSpaceRESTV2Response {
return {
"_embedded": Serialize(models, this.modelType)
};
}
/**
* Convert a response from the backend in to a model.
*
* @param response An object returned by the backend
* @returns a model of type T
*/
deserialize(response: DSpaceRESTV2Response): T {
// TODO enable validation, once rest data stabilizes
// new DSpaceRESTv2Validator(response).validate();
if (Array.isArray(response._embedded)) {
throw new Error('Expected a single model, use deserializeArray() instead');
}
return <T> Deserialize(response._embedded, this.modelType);
}
/**
* Convert a response from the backend in to an array of models
*
* @param response An object returned by the backend
* @returns an array of models of type T
*/
deserializeArray(response: DSpaceRESTV2Response): Array<T> {
//TODO enable validation, once rest data stabilizes
// new DSpaceRESTv2Validator(response).validate();
if (!Array.isArray(response._embedded)) {
throw new Error('Expected an Array, use deserialize() instead');
}
return <Array<T>> Deserialize(response._embedded, this.modelType);
}
}

View File

@@ -0,0 +1,26 @@
import * as schema from './dspace-rest-v2.schema.json'
import { Validator } from "jsonschema";
export class DSpaceRESTv2Validator {
constructor(private document: any) {
}
validate(): void {
const validator = new Validator();
const result = validator.validate(this.document, schema);
if (!result.valid) {
if (result.errors && result.errors.length > 0) {
const message = result.errors
.map((error) => error.message)
.join("\n");
throw new Error(message);
}
else {
throw new Error("JSON API validation failed for an unknown reason");
}
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* A Serializer turns responses from the backend to models
* and vice versa
*/
export interface Serializer<T> {
/**
* Convert a model in to the format expected by the backend
*
* @param model The model to serialize
* @returns An object to send to the backend
*/
serialize(model: T): any;
/**
* Convert an array of models in to the format expected by the backend
*
* @param models The array of models to serialize
* @returns An object to send to the backend
*/
serializeArray(models: Array<T>): any;
/**
* Convert a response from the backend in to a model.
*
* @param response An object returned by the backend
* @returns a model of type T
*/
deserialize(response: any): T;
/**
* Convert a response from the backend in to an array of models
*
* @param response An object returned by the backend
* @returns an array of models of type T
*/
deserializeArray(response: any): Array<T>;
}

View File

@@ -0,0 +1,219 @@
import { isEmpty, hasNoValue, hasValue, isNotEmpty } from "./empty.util";
describe("Empty Utils", () => {
const string: string = 'string';
const fn: () => void = function () {};
const object: any = { length: 0 };
const emptyMap: Map<any, any> = new Map();
let fullMap: Map<string,string> = new Map();
fullMap.set('foo', 'bar');
describe("hasNoValue", () => {
it("should return true for null", () => {
expect(hasNoValue(null)).toBe(true);
});
it("should return true for undefined", () => {
expect(hasNoValue(undefined)).toBe(true);
});
it("should return false for an empty String", () => {
expect(hasNoValue('')).toBe(false);
});
it("should return false for true", () => {
expect(hasNoValue(true)).toBe(false);
});
it("should return false for false", () => {
expect(hasNoValue(false)).toBe(false);
});
it("should return false for a String", () => {
expect(hasNoValue(string)).toBe(false);
});
it("should return false for a Function", () => {
expect(hasNoValue(fn)).toBe(false);
});
it("should return false for 0", () => {
expect(hasNoValue(0)).toBe(false);
});
it("should return false for an empty Array", () => {
expect(hasNoValue([])).toBe(false);
});
it("should return false for an empty Object", () => {
expect(hasNoValue({})).toBe(false);
});
});
describe("hasValue", () => {
it("should return false for null", () => {
expect(hasValue(null)).toBe(false);
});
it("should return false for undefined", () => {
expect(hasValue(undefined)).toBe(false);
});
it("should return true for an empty String", () => {
expect(hasValue('')).toBe(true);
});
it("should return true for false", () => {
expect(hasValue(false)).toBe(true);
});
it("should return true for true", () => {
expect(hasValue(true)).toBe(true);
});
it("should return true for a String", () => {
expect(hasValue(string)).toBe(true);
});
it("should return true for a Function", () => {
expect(hasValue(fn)).toBe(true);
});
it("should return true for 0", () => {
expect(hasValue(0)).toBe(true);
});
it("should return true for an empty Array", () => {
expect(hasValue([])).toBe(true);
});
it("should return true for an empty Object", () => {
expect(hasValue({})).toBe(true);
});
});
describe("isEmpty", () => {
it("should return true for null", () => {
expect(isEmpty(null)).toBe(true);
});
it("should return true for undefined", () => {
expect(isEmpty(undefined)).toBe(true);
});
it("should return true for an empty String", () => {
expect(isEmpty('')).toBe(true);
});
it("should return false for a whitespace String", () => {
expect(isEmpty(' ')).toBe(false);
expect(isEmpty('\n\t')).toBe(false);
});
it("should return false for true", () => {
expect(isEmpty(true)).toBe(false);
});
it("should return false for false", () => {
expect(isEmpty(false)).toBe(false);
});
it("should return false for a String", () => {
expect(isEmpty(string)).toBe(false);
});
it("should return false for a Function", () => {
expect(isEmpty(fn)).toBe(false);
});
it("should return false for 0", () => {
expect(isEmpty(0)).toBe(false);
});
it("should return true for an empty Array", () => {
expect(isEmpty([])).toBe(true);
});
it("should return false for an empty Object", () => {
expect(isEmpty({})).toBe(false);
});
it("should return true for an Object that has zero \'length\'", () => {
expect(isEmpty(object)).toBe(true);
});
it("should return true for an Empty map", () => {
expect(isEmpty(emptyMap)).toBe(true);
});
it("should return false for a Map that is not empty", () => {
expect(isEmpty(fullMap)).toBe(false);
});
});
describe("isNotEmpty", () => {
it("should return false for null", () => {
expect(isNotEmpty(null)).toBe(false);
});
it("should return false for undefined", () => {
expect(isNotEmpty(undefined)).toBe(false);
});
it("should return false for an empty String", () => {
expect(isNotEmpty('')).toBe(false);
});
it("should return true for a whitespace String", () => {
expect(isNotEmpty(' ')).toBe(true);
expect(isNotEmpty('\n\t')).toBe(true);
});
it("should return true for false", () => {
expect(isNotEmpty(false)).toBe(true);
});
it("should return true for true", () => {
expect(isNotEmpty(true)).toBe(true);
});
it("should return true for a String", () => {
expect(isNotEmpty(string)).toBe(true);
});
it("should return true for a Function", () => {
expect(isNotEmpty(fn)).toBe(true);
});
it("should return true for 0", () => {
expect(isNotEmpty(0)).toBe(true);
});
it("should return false for an empty Array", () => {
expect(isNotEmpty([])).toBe(false);
});
it("should return true for an empty Object", () => {
expect(isNotEmpty({})).toBe(true);
});
it("should return false for an Object that has zero length", () => {
expect(isNotEmpty(object)).toBe(false);
});
it("should return false for an Empty map", () => {
expect(isNotEmpty(emptyMap)).toBe(false);
});
it("should return true for a Map that is not empty", () => {
expect(isNotEmpty(fullMap)).toBe(true);
});
});
});

View File

@@ -0,0 +1,94 @@
/**
Returns true if the passed value is null or undefined.
hasNoValue(); // true
hasNoValue(null); // true
hasNoValue(undefined); // true
hasNoValue(''); // false
hasNoValue([]); // false
hasNoValue(function() {}); // false
*/
export function hasNoValue(obj?: any): boolean {
return obj === null || obj === undefined;
}
/**
Returns true if the passed value is not null or undefined.
hasValue(); // false
hasValue(null); // false
hasValue(undefined); // false
hasValue(''); // true
hasValue([]); // true
hasValue(function() {}); // true
*/
export function hasValue(obj?: any): boolean {
return !hasNoValue(obj);
}
/**
Verifies that a value is `null` or an empty string, empty array,
or empty function.
isEmpty(); // true
isEmpty(null); // true
isEmpty(undefined); // true
isEmpty(''); // true
isEmpty([]); // true
isEmpty({}); // false
isEmpty('Adam Hawkins'); // false
isEmpty([0,1,2]); // false
isEmpty('\n\t'); // false
isEmpty(' '); // false
*/
export function isEmpty(obj?: any): boolean {
if (hasNoValue(obj)) {
return true;
}
if (typeof obj.size === 'number') {
return !obj.size;
}
let objectType = typeof obj;
if (objectType === 'object') {
let size = obj['size'];
if (typeof size === 'number') {
return !size;
}
}
if (typeof obj.length === 'number' && objectType !== 'function') {
return !obj.length;
}
if (objectType === 'object') {
let length = obj['length'];
if (typeof length === 'number') {
return !length;
}
}
return false;
}
/**
Verifies that a value is not `null`, an empty string, empty array,
or empty function.
isNotEmpty(); // false
isNotEmpty(null); // false
isNotEmpty(undefined); // false
isNotEmpty(''); // false
isNotEmpty([]); // false
isNotEmpty({}); // true
isNotEmpty('Adam Hawkins'); // true
isNotEmpty([0,1,2]); // true
isNotEmpty('\n\t'); // true
isNotEmpty(' '); // true
*/
export function isNotEmpty(obj?: any): boolean {
return !isEmpty(obj);
}

View File

@@ -11,6 +11,7 @@ import { TranslateLoader, TranslateModule, TranslateStaticLoader } from 'ng2-tra
import { AppModule, AppComponent } from './app/app.module'; import { AppModule, AppComponent } from './app/app.module';
import { SharedModule } from './app/shared/shared.module'; import { SharedModule } from './app/shared/shared.module';
import { CacheService } from './app/shared/cache.service'; import { CacheService } from './app/shared/cache.service';
import { CoreModule } from "./app/core/core.module";
// Will be merged into @angular/platform-browser in a later release // Will be merged into @angular/platform-browser in a later release
// see https://github.com/angular/angular/pull/12322 // see https://github.com/angular/angular/pull/12322
@@ -56,7 +57,8 @@ export const UNIVERSAL_KEY = 'UNIVERSAL_CACHE';
RouterModule.forRoot([], { useHash: false, preloadingStrategy: IdlePreload }), RouterModule.forRoot([], { useHash: false, preloadingStrategy: IdlePreload }),
IdlePreloadModule.forRoot(), IdlePreloadModule.forRoot(),
SharedModule.forRoot(), CoreModule.forRoot(),
SharedModule,
AppModule, AppModule,
], ],
providers: [ providers: [

View File

@@ -10,6 +10,7 @@ import { TranslateLoader, TranslateModule, TranslateStaticLoader } from 'ng2-tra
import { AppModule, AppComponent } from './app/app.module'; import { AppModule, AppComponent } from './app/app.module';
import { SharedModule } from './app/shared/shared.module'; import { SharedModule } from './app/shared/shared.module';
import { CacheService } from './app/shared/cache.service'; import { CacheService } from './app/shared/cache.service';
import { CoreModule } from "./app/core/core.module";
// Will be merged into @angular/platform-browser in a later release // Will be merged into @angular/platform-browser in a later release
// see https://github.com/angular/angular/pull/12322 // see https://github.com/angular/angular/pull/12322
@@ -47,7 +48,8 @@ export const UNIVERSAL_KEY = 'UNIVERSAL_CACHE';
FormsModule, FormsModule,
RouterModule.forRoot([], { useHash: false }), RouterModule.forRoot([], { useHash: false }),
SharedModule.forRoot(), CoreModule.forRoot(),
SharedModule,
AppModule, AppModule,
], ],
providers: [ providers: [

7
src/typings.d.ts vendored
View File

@@ -71,3 +71,10 @@ interface WebpackRequire {
interface NodeRequire extends WebpackRequire { } interface NodeRequire extends WebpackRequire { }
interface NodeModule extends WebpackModule { } interface NodeModule extends WebpackModule { }
interface Global extends GlobalEnvironment { } interface Global extends GlobalEnvironment { }
// Allows us to import json files in typescript
// See https://hackernoon.com/import-json-into-typescript-8d465beded79#.88tfoy2df
declare module "*.json" {
const value: any;
export default value;
}