Skip to content

Commit 3215071

Browse files
committed
wip: ionic core angular build, ionic:build, ionic:serve
1 parent 18f4e51 commit 3215071

19 files changed

Lines changed: 220 additions & 83 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.DS_Store
12
*.sw*
23
*.cookies
34
node_modules/

packages/@ionic/cli-framework/src/utils/format.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ export function indent(n: number = 4): string {
4444
return new Array(n).fill(' ').join('');
4545
}
4646

47-
export function wordWrap(msg: string, { indentation = 0, append = '' }: { indentation?: number, append?: string }) {
48-
return wrapAnsi(msg, TTY_WIDTH - indentation - append.length, { trim: false }).split('\n').join(`${append}\n${indent(indentation)}`);
47+
export function wordWrap(msg: string, { width = TTY_WIDTH, indentation = 0, append = '' }: { width?: number; indentation?: number; append?: string; }) {
48+
return wrapAnsi(msg, width - indentation - append.length, { trim: false }).split('\n').join(`${append}\n${indent(indentation)}`);
4949
}
5050

5151
export function generateFillSpaceStringList(list: string[], optimalLength: number = 1, fillCharacter: string = ' '): string[] {

packages/@ionic/cli-utils/src/commands/build.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import chalk from 'chalk';
2+
import * as Debug from 'debug';
23

34
import { CommandLineInputs, CommandLineOptions, IonicEnvironment } from '../definitions';
5+
import { BUILD_AFTER_HOOK, BUILD_AFTER_SCRIPT, BUILD_BEFORE_HOOK, BUILD_BEFORE_SCRIPT } from '../lib/build';
6+
import { FatalException } from '../lib/errors';
7+
import { PROJECT_FILE } from '../lib/project';
48

5-
const BUILD_BEFORE_HOOK = 'build:before';
6-
const BUILD_BEFORE_SCRIPT = `ionic:${BUILD_BEFORE_HOOK}`;
7-
const BUILD_AFTER_HOOK = 'build:after';
8-
const BUILD_AFTER_SCRIPT = `ionic:${BUILD_AFTER_HOOK}`;
9+
const debug = Debug('ionic:cli-utils:commands:build');
910

1011
export async function build(env: IonicEnvironment, inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
12+
const { pkgManagerArgs } = await import('../lib/utils/npm');
1113
const [ platform ] = inputs;
12-
const packageJson = await env.project.loadPackageJson();
1314

14-
if (packageJson.scripts && packageJson.scripts[BUILD_BEFORE_SCRIPT]) {
15-
env.log.debug(() => `Invoking ${chalk.cyan(BUILD_BEFORE_SCRIPT)} npm script.`);
16-
await env.shell.run('npm', ['run', BUILD_BEFORE_SCRIPT], { showExecution: true });
15+
const pkg = await env.project.loadPackageJson();
16+
17+
debug(`Looking for ${chalk.cyan(BUILD_BEFORE_SCRIPT)} npm script.`);
18+
19+
if (pkg.scripts && pkg.scripts[BUILD_BEFORE_SCRIPT]) {
20+
debug(`Invoking ${chalk.cyan(BUILD_BEFORE_SCRIPT)} npm script.`);
21+
const [ pkgManager, ...pkgArgs ] = await pkgManagerArgs(env, { command: 'run', script: BUILD_BEFORE_SCRIPT });
22+
await env.shell.run(pkgManager, pkgArgs, { showExecution: true });
1723
}
1824

1925
const assign = await import('lodash/assign');
20-
const deps = assign({}, packageJson.dependencies, packageJson.devDependencies);
26+
const deps = assign({}, pkg.dependencies, pkg.devDependencies);
2127

2228
if (deps['@ionic/cli-plugin-cordova']) {
2329
const { checkCordova } = await import('../lib/cordova/utils');
@@ -28,17 +34,29 @@ export async function build(env: IonicEnvironment, inputs: CommandLineInputs, op
2834

2935
const project = await env.project.load();
3036

31-
if (project.type === 'ionic-angular') {
37+
if (project.type === 'ionic1') {
38+
const { build } = await import('../lib/ionic1/build');
39+
await build({ env, options: { platform, ...options } });
40+
} else if (project.type === 'ionic-angular') {
3241
const { build } = await import('../lib/ionic-angular/build');
3342
await build({ env, options: { platform, ...options } });
34-
} else {
35-
const { build } = await import('../lib/ionic1/build');
43+
} else if (project.type === 'ionic-core-angular') {
44+
const { build } = await import('../lib/ionic-core-angular/build');
3645
await build({ env, options: { platform, ...options } });
46+
} else {
47+
throw new FatalException(
48+
`Cannot perform Ionic build for project type: ${chalk.bold(project.type)}.\n` +
49+
(project.type === 'custom' ? `Since you're using the ${chalk.bold('custom')} project type, this command won't work. The Ionic CLI doesn't know how to build custom projects.\n\n` : '') +
50+
`If you'd like the CLI to try to detect your project type, you can unset the ${chalk.bold('type')} attribute in ${chalk.bold(PROJECT_FILE)}.`
51+
);
3752
}
3853

39-
if (packageJson.scripts && packageJson.scripts[BUILD_AFTER_SCRIPT]) {
40-
env.log.debug(() => `Invoking ${chalk.cyan(BUILD_AFTER_SCRIPT)} npm script.`);
41-
await env.shell.run('npm', ['run', BUILD_AFTER_SCRIPT], { showExecution: true });
54+
debug(`Looking for ${chalk.cyan(BUILD_AFTER_SCRIPT)} npm script.`);
55+
56+
if (pkg.scripts && pkg.scripts[BUILD_AFTER_SCRIPT]) {
57+
debug(`Invoking ${chalk.cyan(BUILD_AFTER_SCRIPT)} npm script.`);
58+
const [ pkgManager, ...pkgArgs ] = await pkgManagerArgs(env, { command: 'run', script: BUILD_AFTER_SCRIPT });
59+
await env.shell.run(pkgManager, pkgArgs, { showExecution: true });
4260
}
4361

4462
await env.hooks.fire(BUILD_AFTER_HOOK, { env, platform });

packages/@ionic/cli-utils/src/commands/serve.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { str2num } from '@ionic/cli-framework/utils/string';
66
import { CommandLineInputs, CommandLineOptions, IonicEnvironment, LabServeDetails, ServeDetails } from '../definitions';
77
import { isCordovaPackageJson } from '../guards';
88
import { FatalException } from '../lib/errors';
9+
import { PROJECT_FILE } from '../lib/project';
910

1011
import {
1112
BIND_ALL_ADDRESS,
@@ -82,7 +83,7 @@ export async function serve(env: IonicEnvironment, inputs: CommandLineInputs, op
8283
throw new FatalException(
8384
`Cannot perform Ionic serve for project type: ${chalk.bold(project.type)}.\n` +
8485
(project.type === 'custom' ? `Since you're using the ${chalk.bold('custom')} project type, this command won't work. The Ionic CLI doesn't know how to serve custom projects.\n\n` : '') +
85-
`If you'd like the CLI to try to detect your project type, you can unset the ${chalk.bold('type')} attribute in ${chalk.bold('ionic.config.json')}.\n`
86+
`If you'd like the CLI to try to detect your project type, you can unset the ${chalk.bold('type')} attribute in ${chalk.bold(PROJECT_FILE)}.`
8687
);
8788
}
8889

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export const BUILD_BEFORE_HOOK = 'build:before';
2+
export const BUILD_AFTER_HOOK = 'build:after';
3+
4+
// npm script names
5+
const npmPrefix = 'ionic';
6+
export const BUILD_SCRIPT = `${npmPrefix}:build`;
7+
export const BUILD_BEFORE_SCRIPT = `${npmPrefix}:${BUILD_BEFORE_HOOK}`;
8+
export const BUILD_AFTER_SCRIPT = `${npmPrefix}:${BUILD_AFTER_HOOK}`;

packages/@ionic/cli-utils/src/lib/ionic-angular/build.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
import chalk from 'chalk';
2+
import * as Debug from 'debug';
23
import { parsedArgsToArgv } from '@ionic/cli-framework/lib';
34

45
import { IonicEnvironment } from '../../definitions';
5-
import { importAppScripts } from './app-scripts';
6+
7+
import { BUILD_SCRIPT } from '../build';
8+
9+
const debug = Debug('ionic:cli-utils:lib:ionic-angular:build');
610

711
export async function build({ env, options }: { env: IonicEnvironment; options: { _: string[]; [key: string]: any; }; }): Promise<void> {
12+
const { pkgManagerArgs } = await import('../utils/npm');
13+
const pkg = await env.project.loadPackageJson();
14+
815
const appScriptsArgs = await buildOptionsToAppScriptsArgs(options);
9-
process.argv = ['node', 'appscripts'].concat(appScriptsArgs);
16+
const shellOptions = { showExecution: true, cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } };
1017

11-
const AppScripts = await importAppScripts(env);
12-
const context = AppScripts.generateContext();
18+
debug(`Looking for ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
1319

14-
env.log.info(`Running app-scripts build: ${chalk.bold(appScriptsArgs.join(' '))}\n`);
15-
return await AppScripts.build(context);
20+
if (pkg.scripts && pkg.scripts[BUILD_SCRIPT]) {
21+
debug(`Invoking ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
22+
const [ pkgManager, ...pkgArgs ] = await pkgManagerArgs(env, { command: 'run', script: BUILD_SCRIPT, scriptArgs: appScriptsArgs });
23+
await env.shell.run(pkgManager, pkgArgs, shellOptions);
24+
} else {
25+
await env.shell.run('ionic-app-scripts', ['build', ...appScriptsArgs], shellOptions);
26+
}
1627
}
1728

1829
export async function buildOptionsToAppScriptsArgs(options: { _: string[]; [key: string]: any; }) {
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
1+
import chalk from 'chalk';
2+
import * as Debug from 'debug';
3+
14
import { IonicEnvironment } from '../../definitions';
25

6+
import { BUILD_SCRIPT } from '../build';
7+
8+
const debug = Debug('ionic:cli-utils:lib:ionic-core-angular:build');
9+
310
export async function build({ env, options }: { env: IonicEnvironment; options: { _: string[]; [key: string]: any; }; }): Promise<void> {
4-
// TODO
11+
const { pkgManagerArgs } = await import('../utils/npm');
12+
const pkg = await env.project.loadPackageJson();
13+
14+
const ngArgs = ['build'];
15+
const shellOptions = { showExecution: true, cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } };
16+
17+
debug(`Looking for ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
18+
19+
if (pkg.scripts && pkg.scripts[BUILD_SCRIPT]) {
20+
debug(`Invoking ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
21+
const [ pkgManager, ...pkgArgs ] = await pkgManagerArgs(env, { command: 'run', script: BUILD_SCRIPT });
22+
await env.shell.run(pkgManager, pkgArgs, shellOptions);
23+
} else {
24+
await env.shell.run('ng', ngArgs, shellOptions);
25+
}
526
}

packages/@ionic/cli-utils/src/lib/ionic-core-angular/serve.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ async function ngServe(env: IonicEnvironment, host: string, port: number): Promi
4141
const { registerShutdownFunction } = await import('../process');
4242

4343
const ngArgs: string[] = ['serve', '--host', host, '--port', String(port), '--progress', 'false'];
44+
const shellOptions = { showExecution: true, cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } };
4445

4546
if (await pathAccessible(path.resolve(env.project.directory, NG_AUTODETECTED_PROXY_FILE), fs.constants.R_OK)) {
4647
ngArgs.push('--proxy-config');
4748
ngArgs.push(NG_AUTODETECTED_PROXY_FILE); // this is fine as long as cwd is the project directory
4849
}
4950

50-
const p = await env.shell.spawn('ng', ngArgs, { cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } });
51+
const p = await env.shell.spawn('ng', ngArgs, shellOptions);
5152

5253
registerShutdownFunction(() => p.kill());
5354

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
import chalk from 'chalk';
2+
import * as Debug from 'debug';
23

34
import { IonicEnvironment } from '../../definitions';
45

6+
import { BUILD_SCRIPT } from '../build';
7+
8+
const debug = Debug('ionic:cli-utils:lib:ionic1:build');
9+
510
export async function build({ env, options }: { env: IonicEnvironment; options: { _: string[]; [key: string]: any; }; }): Promise<void> {
6-
await env.shell.run('ionic-v1', ['build'], { showExecution: true, cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } });
11+
const { pkgManagerArgs } = await import('../utils/npm');
12+
const pkg = await env.project.loadPackageJson();
13+
const shellOptions = { showExecution: true, cwd: env.project.directory, env: { FORCE_COLOR: chalk.enabled ? '1' : '0' } };
14+
15+
debug(`Looking for ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
16+
17+
if (pkg.scripts && pkg.scripts[BUILD_SCRIPT]) {
18+
debug(`Invoking ${chalk.cyan(BUILD_SCRIPT)} npm script.`);
19+
const [ pkgManager, ...pkgArgs ] = await pkgManagerArgs(env, { command: 'run', script: BUILD_SCRIPT });
20+
await env.shell.run(pkgManager, pkgArgs, shellOptions);
21+
} else {
22+
await env.shell.run('ionic-v1', ['build'], shellOptions);
23+
}
724
}

packages/@ionic/cli-utils/src/lib/project.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import chalk from 'chalk';
44

55
import { ERROR_FILE_INVALID_JSON } from '@ionic/cli-framework/utils/fs';
6-
import { prettyPath } from '@ionic/cli-framework/utils/format';
6+
import { TTY_WIDTH, prettyPath, wordWrap } from '@ionic/cli-framework/utils/format';
77
import { ERROR_INVALID_BOWER_JSON, ERROR_INVALID_PACKAGE_JSON, readBowerJsonFile, readPackageJsonFile } from '@ionic/cli-framework/utils/npm';
88

99
import { BowerJson, IProject, PackageJson, ProjectFile, ProjectType } from '../definitions';
@@ -12,7 +12,7 @@ import { FatalException } from './errors';
1212

1313
export const PROJECT_FILE = 'ionic.config.json';
1414
export const PROJECT_FILE_LEGACY = 'ionic.project';
15-
export const PROJECT_TYPES: ProjectType[] = ['ionic-angular', 'ionic1', 'custom'];
15+
export const PROJECT_TYPES: ProjectType[] = ['ionic-core-angular', 'ionic-angular', 'ionic1', 'custom'];
1616

1717
export class Project extends BaseConfig<ProjectFile> implements IProject {
1818
public directory: string;
@@ -116,7 +116,9 @@ export class Project extends BaseConfig<ProjectFile> implements IProject {
116116
}
117117

118118
formatType(type: ProjectType) {
119-
if (type === 'ionic-angular') {
119+
if (type === 'ionic-core-angular') {
120+
return 'Ionic Angular'; // TODO: special name?
121+
} else if (type === 'ionic-angular') {
120122
return 'Ionic Angular';
121123
} else if (type === 'ionic1') {
122124
return 'Ionic 1';
@@ -126,6 +128,18 @@ export class Project extends BaseConfig<ProjectFile> implements IProject {
126128
}
127129

128130
protected async determineType(): Promise<ProjectType> {
131+
try {
132+
const packageJson = await this.loadPackageJson();
133+
134+
if (packageJson.dependencies && typeof packageJson.dependencies['@ionic/angular'] === 'string') {
135+
return 'ionic-core-angular';
136+
}
137+
} catch (e) {
138+
if (e.fatal) {
139+
throw e;
140+
}
141+
}
142+
129143
try {
130144
const packageJson = await this.loadPackageJson();
131145

@@ -150,11 +164,16 @@ export class Project extends BaseConfig<ProjectFile> implements IProject {
150164
}
151165
}
152166

167+
const listWrapOptions = { width: TTY_WIDTH - 8 - 3, indentation: 1 };
168+
169+
// TODO: move some of this to the website
170+
153171
throw new FatalException(
154172
`Could not determine project type (project config: ${chalk.bold(prettyPath(this.filePath))}).\n` +
155-
`For ${this.formatType('ionic-angular')} projects, make sure ${chalk.green('ionic-angular')} is listed as a dependency in ${chalk.bold('package.json')}.\n` +
156-
`For ${this.formatType('ionic1')} projects, make sure ${chalk.green('ionic')} is listed as a dependency in ${chalk.bold('bower.json')}.\n\n` +
157-
`Alternatively, set ${chalk.bold('type')} attribute in ${chalk.bold('ionic.config.json')} to one of: ${PROJECT_TYPES.map(v => chalk.green(v)).join(', ')}.\n\n` +
173+
`- ${wordWrap(`For ${this.formatType('ionic-core-angular')} projects (Ionic Angular v4+, with ${chalk.bold('@angular/cli')}), make sure ${chalk.green('@ionic/angular')} is listed as a dependency in ${chalk.bold('package.json')}.`, listWrapOptions)}\n\n` +
174+
`- ${wordWrap(`For ${this.formatType('ionic-angular')} projects (Ionic Angular v2-v3, with ${chalk.bold('ionic-app-scripts')}), make sure ${chalk.green('ionic-angular')} is listed as a dependency in ${chalk.bold('package.json')}.`, listWrapOptions)}\n\n` +
175+
`- ${wordWrap(`For ${this.formatType('ionic1')} projects, make sure ${chalk.green('ionic')} is listed as a dependency in ${chalk.bold('bower.json')}.`, listWrapOptions)}\n\n` +
176+
`Alternatively, set ${chalk.bold('type')} attribute in ${chalk.bold(PROJECT_FILE)} to one of: ${PROJECT_TYPES.map(v => chalk.green(v)).join(', ')}.\n\n` +
158177
`If the Ionic CLI does not know what type of project this is, ${chalk.green('ionic build')}, ${chalk.green('ionic serve')}, and other commands may not work. You can use the ${chalk.green('custom')} project type if that's okay.\n`
159178
);
160179
}

0 commit comments

Comments
 (0)