parent
570f735a2a
commit
99e3a04ea2
|
@ -280,6 +280,27 @@ jobs:
|
|||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
|
||||
test_docs_examples_ivy:
|
||||
<<: *job_defaults
|
||||
docker:
|
||||
# Needed because the example e2e tests depend on Chrome.
|
||||
- image: *browsers_docker_image
|
||||
parallelism: 3
|
||||
steps:
|
||||
- checkout:
|
||||
<<: *post_checkout
|
||||
- *restore_cache
|
||||
- attach_workspace:
|
||||
at: dist
|
||||
- *define_env_vars
|
||||
- *download_yarn
|
||||
# Install aio
|
||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||
- run: yarn --cwd aio example-e2e --setup --local --ivy --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||
|
||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||
aio_preview:
|
||||
<<: *job_defaults
|
||||
|
@ -593,6 +614,9 @@ workflows:
|
|||
- test_docs_examples:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- test_docs_examples_ivy:
|
||||
requires:
|
||||
- build-npm-packages
|
||||
- aio_preview:
|
||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||
filters:
|
||||
|
@ -618,7 +642,8 @@ workflows:
|
|||
- test_aio_local
|
||||
- test_aio_local_ivy
|
||||
- test_docs_examples
|
||||
# Get the artifacts to publish from the build-npm-packages job
|
||||
- test_docs_examples_ivy
|
||||
# Get the artifacts to publish from the build-packages-dist job
|
||||
# since the publishing script expects the legacy outputs layout.
|
||||
- build-npm-packages
|
||||
- build-ivy-npm-packages
|
||||
|
|
|
@ -57,7 +57,9 @@ dist/
|
|||
|
||||
# aot
|
||||
**/*.ngsummary.json
|
||||
upgrade-module/tsconfig-aot.json
|
||||
!rollup-config.js
|
||||
upgrade-module/rollup-config.js
|
||||
aot-compiler/**/*.d.ts
|
||||
aot-compiler/**/*.factory.d.ts
|
||||
upgrade-phonecat-2-hybrid/aot/**/*
|
||||
|
@ -84,5 +86,9 @@ upgrade-phonecat-2-hybrid/aot/**/*
|
|||
*stackblitz.no-link.html
|
||||
|
||||
# ngUpgrade testing
|
||||
upgrade-phonecat-1-typescript/tsconfig-aot.json
|
||||
upgrade-phonecat-1-typescript/rollup-config.js
|
||||
upgrade-phonecat-3-final/tsconfig-aot.json
|
||||
upgrade-phonecat-3-final/rollup-config.js
|
||||
!upgrade-phonecat-*/**/karma.conf.js
|
||||
!upgrade-phonecat-*/**/karma-test-shim.js
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
"preserve-and-sync": "yarn docs",
|
||||
"serve-and-sync": "run-p \"start\" \"docs-watch --watch-only\"",
|
||||
"boilerplate:add": "node ./tools/examples/example-boilerplate add",
|
||||
"boilerplate:add:ivy": "yarn boilerplate:add --ivy",
|
||||
"boilerplate:remove": "node ./tools/examples/example-boilerplate remove",
|
||||
"boilerplate:test": "node tools/examples/test.js",
|
||||
"generate-stackblitz": "node ./tools/stackblitz-builder/generateStackblitz",
|
||||
|
|
|
@ -78,23 +78,38 @@ BOILERPLATE_PATHS.universal = [
|
|||
'package.json'
|
||||
];
|
||||
|
||||
BOILERPLATE_PATHS.ivy = {
|
||||
systemjs: [
|
||||
'rollup-config.js',
|
||||
'tsconfig-aot.json'
|
||||
],
|
||||
cli: [
|
||||
'src/tsconfig.app.json'
|
||||
]
|
||||
};
|
||||
|
||||
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
|
||||
|
||||
class ExampleBoilerPlate {
|
||||
/**
|
||||
* Add boilerplate files to all the examples
|
||||
*/
|
||||
add() {
|
||||
add(ivy = false) {
|
||||
// Get all the examples folders, indicated by those that contain a `example-config.json` file
|
||||
const exampleFolders = this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
|
||||
exampleFolders.forEach(exampleFolder => {
|
||||
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
|
||||
|
||||
if (!fs.existsSync(SHARED_NODE_MODULES_PATH)) {
|
||||
throw new Error(`The shared node_modules folder for the examples (${SHARED_NODE_MODULES_PATH}) is missing.\n` +
|
||||
`Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`);
|
||||
}
|
||||
|
||||
if (ivy) {
|
||||
shelljs.exec(`yarn --cwd ${SHARED_PATH} ivy-ngcc`);
|
||||
}
|
||||
|
||||
exampleFolders.forEach(exampleFolder => {
|
||||
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
|
||||
|
||||
// Link the node modules - requires admin access (on Windows) because it adds symlinks
|
||||
const destinationNodeModules = path.resolve(exampleFolder, 'node_modules');
|
||||
fs.ensureSymlinkSync(SHARED_NODE_MODULES_PATH, destinationNodeModules);
|
||||
|
@ -107,6 +122,12 @@ class ExampleBoilerPlate {
|
|||
|
||||
// Copy the boilerplate common files
|
||||
BOILERPLATE_PATHS.common.forEach(filePath => this.copyFile(BOILERPLATE_COMMON_BASE_PATH, exampleFolder, filePath));
|
||||
|
||||
// Copy Ivy specific files
|
||||
if (ivy && BOILERPLATE_PATHS.ivy[boilerPlateType]) {
|
||||
const ivyBoilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, 'ivy', boilerPlateType);
|
||||
BOILERPLATE_PATHS.ivy[boilerPlateType].forEach(filePath => this.copyFile(ivyBoilerPlateBasePath, exampleFolder, filePath));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -120,7 +141,7 @@ class ExampleBoilerPlate {
|
|||
main() {
|
||||
yargs
|
||||
.usage('$0 <cmd> [args]')
|
||||
.command('add', 'add the boilerplate to each example', () => this.add())
|
||||
.command('add', 'add the boilerplate to each example', (yrgs) => this.add(yrgs.argv.ivy))
|
||||
.command('remove', 'remove the boilerplate from each example', () => this.remove())
|
||||
.demandCommand(1, 'Please supply a command from the list above')
|
||||
.argv;
|
||||
|
|
|
@ -15,10 +15,36 @@ const PROTRACTOR_CONFIG_FILENAME = path.join(__dirname, './shared/protractor.con
|
|||
const SJS_SPEC_FILENAME = 'e2e-spec.ts';
|
||||
const CLI_SPEC_FILENAME = 'e2e/src/app.e2e-spec.ts';
|
||||
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
|
||||
const IGNORED_EXAMPLES = [ // temporary ignores
|
||||
const IGNORED_EXAMPLES = [
|
||||
// temporary ignores
|
||||
|
||||
];
|
||||
|
||||
const fixmeIvyExamples = [
|
||||
// fixmeIvy('unknown') movie list route is not rendering
|
||||
'ajs-quick-reference',
|
||||
// fixmeIvy('unknown') version value goes undefined when clicking Major button after clicking
|
||||
// Minor button twice
|
||||
'component-interaction',
|
||||
// fixmeIvy('unknown') failed content projection and applied styles
|
||||
'component-styles',
|
||||
// fails due to incompatible AoT code with a tree-shakable provider and a non-type constructor
|
||||
// argument
|
||||
'dependency-injection',
|
||||
// fixmeIvy('unknown') Error: Internal Error: The name heroForm is already defined in scope to be
|
||||
// [object Object]
|
||||
'forms',
|
||||
// fixmeIvy('unknown') app fails at runtime due to missing external service (goog is undefined)
|
||||
'i18n',
|
||||
// fixmeIvy('unknown') ERROR in HostResourceResolver: could not resolve app/app.component.css
|
||||
// in context of aio/content/examples/styleguide/src/01-01/app/heroes/hero.component.avoid.ts)
|
||||
'styleguide'
|
||||
];
|
||||
|
||||
if (argv.ivy) {
|
||||
IGNORED_EXAMPLES.push(...fixmeIvyExamples);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run Protractor End-to-End Tests for Doc Samples
|
||||
*
|
||||
|
@ -43,7 +69,7 @@ function runE2e() {
|
|||
// Run setup.
|
||||
console.log('runE2e: setup boilerplate');
|
||||
const installPackagesCommand = `example-use-${argv.local ? 'local' : 'npm'}`;
|
||||
const addBoilerplateCommand = 'boilerplate:add';
|
||||
const addBoilerplateCommand = `boilerplate:add${argv.ivy ? ':ivy' : ''}`;
|
||||
shelljs.exec(`yarn ${installPackagesCommand}`, {cwd: AIO_PATH});
|
||||
shelljs.exec(`yarn ${addBoilerplateCommand}`, {cwd: AIO_PATH});
|
||||
}
|
||||
|
@ -57,7 +83,8 @@ function runE2e() {
|
|||
if (status.failed.length > 0) {
|
||||
return Promise.reject('Some test suites failed');
|
||||
}
|
||||
}).catch(function (e) {
|
||||
})
|
||||
.catch(function(e) {
|
||||
console.log(e);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
|
@ -66,7 +93,6 @@ function runE2e() {
|
|||
// Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps
|
||||
// that they should run under. Then run each app/spec collection sequentially.
|
||||
function findAndRunE2eTests(filter, outputFile, shard) {
|
||||
|
||||
const shardParts = shard ? shard.split('/') : [0, 1];
|
||||
const shardModulo = parseInt(shardParts[0], 10);
|
||||
const shardDivider = parseInt(shardParts[1], 10);
|
||||
|
@ -92,7 +118,9 @@ function findAndRunE2eTests(filter, outputFile, shard) {
|
|||
console.log(`E2e specs for shard ${shardParts.join('/')}:`);
|
||||
logSpecs(e2eSpecPaths);
|
||||
|
||||
return e2eSpecPaths.systemjs.reduce((promise, specPath) => {
|
||||
return e2eSpecPaths.systemjs
|
||||
.reduce(
|
||||
(promise, specPath) => {
|
||||
return promise.then(() => {
|
||||
const examplePath = path.dirname(specPath);
|
||||
return runE2eTestsSystemJS(examplePath, outputFile).then(ok => {
|
||||
|
@ -100,7 +128,8 @@ function findAndRunE2eTests(filter, outputFile, shard) {
|
|||
arr.push(examplePath);
|
||||
});
|
||||
});
|
||||
}, Promise.resolve())
|
||||
},
|
||||
Promise.resolve())
|
||||
.then(() => {
|
||||
return e2eSpecPaths.cli.reduce((promise, specPath) => {
|
||||
return promise.then(() => {
|
||||
|
@ -151,12 +180,13 @@ function runProtractorSystemJS(prepPromise, appDir, appRunSpawnInfo, outputFile)
|
|||
|
||||
// Start protractor.
|
||||
console.log(`\n\n=========== Running aio example tests for: ${appDir}`);
|
||||
const spawnInfo = spawnExt('yarn', ['protractor',
|
||||
PROTRACTOR_CONFIG_FILENAME,
|
||||
`--specs=${specFilename}`,
|
||||
'--params.appDir=' + appDir,
|
||||
'--params.outputFile=' + outputFile
|
||||
], { cwd: SHARED_PATH });
|
||||
const spawnInfo = spawnExt(
|
||||
'yarn',
|
||||
[
|
||||
'protractor', PROTRACTOR_CONFIG_FILENAME, `--specs=${specFilename}`,
|
||||
'--params.appDir=' + appDir, '--params.outputFile=' + outputFile
|
||||
],
|
||||
{cwd: SHARED_PATH});
|
||||
|
||||
spawnInfo.proc.stderr.on('data', function(data) {
|
||||
transpileError = transpileError || /npm ERR! Exit status 100/.test(data.toString());
|
||||
|
@ -172,8 +202,7 @@ function runProtractorSystemJS(prepPromise, appDir, appRunSpawnInfo, outputFile)
|
|||
})
|
||||
.then(
|
||||
function() { return finish(appRunSpawnInfo.proc.pid, true); },
|
||||
function () { return finish(appRunSpawnInfo.proc.pid, false); }
|
||||
);
|
||||
function() { return finish(appRunSpawnInfo.proc.pid, false); });
|
||||
}
|
||||
|
||||
function finish(spawnProcId, ok) {
|
||||
|
@ -205,7 +234,8 @@ function runE2eTestsCLI(appDir, outputFile) {
|
|||
console.log(`\n\n=========== Running aio example tests for: ${appDir}`);
|
||||
// `--no-webdriver-update` is needed to preserve the ChromeDriver version already installed.
|
||||
const config = loadExampleConfig(appDir);
|
||||
const commands = config.e2e || [{ cmd: 'yarn', args: ['e2e', '--prod', '--no-webdriver-update'] }];
|
||||
const commands = config.e2e ||
|
||||
[{cmd: 'yarn', args: ['e2e', (argv.ivy ? '--prod' : ''), '--no-webdriver-update']}];
|
||||
|
||||
const e2eSpawnPromise = commands.reduce((prevSpawnPromise, {cmd, args}) => {
|
||||
return prevSpawnPromise.then(() => {
|
||||
|
@ -217,25 +247,39 @@ function runE2eTestsCLI(appDir, outputFile) {
|
|||
}, Promise.resolve());
|
||||
|
||||
return e2eSpawnPromise.then(
|
||||
() => { fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`); return true; },
|
||||
() => { fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`); return false; });
|
||||
() => {
|
||||
fs.appendFileSync(outputFile, `Passed: ${appDir}\n\n`);
|
||||
return true;
|
||||
},
|
||||
() => {
|
||||
fs.appendFileSync(outputFile, `Failed: ${appDir}\n\n`);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// Report final status.
|
||||
function reportStatus(status, outputFile) {
|
||||
let log = [''];
|
||||
|
||||
log.push('Suites ignored due to legacy guides:');
|
||||
IGNORED_EXAMPLES.filter(example => !fixmeIvyExamples.find(ex => ex.startsWith(example)))
|
||||
.forEach(function(val) { log.push(' ' + val); });
|
||||
|
||||
if (argv.ivy) {
|
||||
log.push('');
|
||||
log.push('Suites ignored due to breakage with Ivy:');
|
||||
fixmeIvyExamples.forEach(function(val) { log.push(' ' + val); });
|
||||
}
|
||||
|
||||
log.push('');
|
||||
log.push('Suites passed:');
|
||||
status.passed.forEach(function (val) {
|
||||
log.push(' ' + val);
|
||||
});
|
||||
status.passed.forEach(function(val) { log.push(' ' + val); });
|
||||
|
||||
if (status.failed.length == 0) {
|
||||
log.push('All tests passed');
|
||||
} else {
|
||||
log.push('Suites failed:');
|
||||
status.failed.forEach(function (val) {
|
||||
log.push(' ' + val);
|
||||
});
|
||||
status.failed.forEach(function(val) { log.push(' ' + val); });
|
||||
}
|
||||
log.push('\nElapsed time: ' + status.elapsedTime + ' seconds');
|
||||
log = log.join('\n');
|
||||
|
@ -256,12 +300,8 @@ function spawnExt(command, args, options, ignoreClose = false) {
|
|||
reject(e);
|
||||
return {proc: null, promise};
|
||||
}
|
||||
proc.stdout.on('data', function (data) {
|
||||
process.stdout.write(data.toString());
|
||||
});
|
||||
proc.stderr.on('data', function (data) {
|
||||
process.stdout.write(data.toString());
|
||||
});
|
||||
proc.stdout.on('data', function(data) { process.stdout.write(data.toString()); });
|
||||
proc.stderr.on('data', function(data) { process.stdout.write(data.toString()); });
|
||||
proc.on('close', function(returnCode) {
|
||||
console.log(`completed: ${descr} \n`);
|
||||
// Many tasks (e.g., tsc) complete but are actually errors;
|
||||
|
@ -280,17 +320,15 @@ function spawnExt(command, args, options, ignoreClose = false) {
|
|||
function getE2eSpecs(basePath, filter) {
|
||||
let specs = {};
|
||||
|
||||
return getE2eSpecsFor(basePath, SJS_SPEC_FILENAME, filter).then(sjsPaths => {
|
||||
specs.systemjs = sjsPaths;
|
||||
}).then(() => {
|
||||
return getE2eSpecsFor(basePath, SJS_SPEC_FILENAME, filter)
|
||||
.then(sjsPaths => { specs.systemjs = sjsPaths; })
|
||||
.then(() => {
|
||||
return getE2eSpecsFor(basePath, CLI_SPEC_FILENAME, filter).then(cliPaths => {
|
||||
return cliPaths.map(p => {
|
||||
return p.replace(`${CLI_SPEC_FILENAME}`, '');
|
||||
return cliPaths.map(p => { return p.replace(`${CLI_SPEC_FILENAME}`, ''); });
|
||||
});
|
||||
});
|
||||
}).then(cliPaths => {
|
||||
specs.cli = cliPaths;
|
||||
}).then(() => specs);
|
||||
})
|
||||
.then(cliPaths => { specs.cli = cliPaths; })
|
||||
.then(() => specs);
|
||||
}
|
||||
|
||||
// Find all e2e specs in a given example folder.
|
||||
|
@ -298,24 +336,21 @@ function getE2eSpecsFor(basePath, specFile, filter) {
|
|||
// Only get spec file at the example root.
|
||||
const e2eSpecGlob = `${filter ? ` * ${filter} * ` : '*'}/${specFile}`;
|
||||
return globby(e2eSpecGlob, {cwd: basePath, nodir: true})
|
||||
.then(paths => paths
|
||||
.filter(file => !IGNORED_EXAMPLES.some(ignored => file.startsWith(ignored)))
|
||||
.map(file => path.join(basePath, file))
|
||||
);
|
||||
.then(
|
||||
paths => paths.filter(file => !IGNORED_EXAMPLES.some(ignored => file.startsWith(ignored)))
|
||||
.map(file => path.join(basePath, file)));
|
||||
}
|
||||
|
||||
// Load configuration for an example. Used for SystemJS
|
||||
function loadExampleConfig(exampleFolder) {
|
||||
// Default config.
|
||||
let config = {
|
||||
build: 'build',
|
||||
run: 'serve:e2e'
|
||||
};
|
||||
let config = {build: 'build', run: 'serve:e2e'};
|
||||
|
||||
try {
|
||||
const exampleConfig = fs.readJsonSync(`${exampleFolder}/${EXAMPLE_CONFIG_FILENAME}`);
|
||||
Object.assign(config, exampleConfig);
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"exclude": [
|
||||
"test.ts",
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": "ngtsc",
|
||||
"allowEmptyCodegenFiles": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// #docregion
|
||||
import rollup from 'rollup'
|
||||
import nodeResolve from 'rollup-plugin-node-resolve'
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import uglify from 'rollup-plugin-uglify'
|
||||
|
||||
//paths are relative to the execution path
|
||||
export default {
|
||||
entry: 'app/main.js',
|
||||
dest: 'aot/dist/build.js', // output a single application bundle
|
||||
sourceMap: true,
|
||||
sourceMapFile: 'aot/dist/build.js.map',
|
||||
format: 'iife',
|
||||
plugins: [
|
||||
nodeResolve({ jsnext: true, module: true }),
|
||||
commonjs({
|
||||
include: ['node_modules/rxjs/**']
|
||||
}),
|
||||
uglify()
|
||||
]
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
],
|
||||
"removeComments": false,
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true,
|
||||
"suppressImplicitAnyIndexErrors": true
|
||||
},
|
||||
"files": [
|
||||
"app/app.module.ts",
|
||||
"app/main.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"skipMetadataEmit": true,
|
||||
"enableIvy": "ngtsc"
|
||||
}
|
||||
}
|
|
@ -18,22 +18,22 @@
|
|||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "^7.0.0",
|
||||
"@angular/common": "^7.0.0",
|
||||
"@angular/compiler": "^7.0.0",
|
||||
"@angular/core": "^7.0.0",
|
||||
"@angular/elements": "^7.0.0",
|
||||
"@angular/forms": "^7.0.0",
|
||||
"@angular/http": "^7.0.0",
|
||||
"@angular/platform-browser": "^7.0.0",
|
||||
"@angular/platform-browser-dynamic": "^7.0.0",
|
||||
"@angular/router": "^7.0.0",
|
||||
"@angular/service-worker": "^7.0.0",
|
||||
"@angular/upgrade": "^7.0.0",
|
||||
"@nguniversal/common": "^7.0.0",
|
||||
"@nguniversal/express-engine": "^7.0.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^7.0.0",
|
||||
"angular-in-memory-web-api": "^0.6.0",
|
||||
"@angular/animations": "^7.1.0",
|
||||
"@angular/common": "^7.1.0",
|
||||
"@angular/compiler": "^7.1.0",
|
||||
"@angular/core": "^7.1.0",
|
||||
"@angular/elements": "^7.1.0",
|
||||
"@angular/forms": "^7.1.0",
|
||||
"@angular/http": "^7.1.0",
|
||||
"@angular/platform-browser": "^7.1.0",
|
||||
"@angular/platform-browser-dynamic": "^7.1.0",
|
||||
"@angular/router": "^7.1.0",
|
||||
"@angular/service-worker": "^7.1.0",
|
||||
"@angular/upgrade": "^7.1.0",
|
||||
"@nguniversal/common": "^7.1.0",
|
||||
"@nguniversal/express-engine": "^7.1.0",
|
||||
"@nguniversal/module-map-ngfactory-loader": "^7.1.0",
|
||||
"angular-in-memory-web-api": "github:brandonroberts/in-memory-web-api-bazel#50a34d8",
|
||||
"core-js": "^2.5.4",
|
||||
"express": "^4.14.1",
|
||||
"rxjs": "^6.3.0",
|
||||
|
@ -42,11 +42,11 @@
|
|||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^0.10.0",
|
||||
"@angular/cli": "^7.0.0",
|
||||
"@angular/compiler-cli": "^7.0.0",
|
||||
"@angular/language-service": "^7.0.0",
|
||||
"@angular/platform-server": "^7.0.0",
|
||||
"@angular-devkit/build-angular": "^0.11.0",
|
||||
"@angular/cli": "^7.1.0",
|
||||
"@angular/compiler-cli": "^7.1.0",
|
||||
"@angular/language-service": "^7.1.0",
|
||||
"@angular/platform-server": "^7.1.0",
|
||||
"@types/angular": "^1.6.47",
|
||||
"@types/angular-animate": "^1.5.10",
|
||||
"@types/angular-mocks": "^1.6.0",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue