From 2448ad7e0099ab5922f32fe6041275e460f07a90 Mon Sep 17 00:00:00 2001 From: Mike Hartington Date: Tue, 11 Apr 2023 13:58:01 -0400 Subject: [PATCH 1/8] feat(): add standalone as an option --- packages/@ionic/cli/src/commands/start.ts | 563 +++++++++++++++++----- packages/@ionic/cli/src/definitions.ts | 1 + 2 files changed, 448 insertions(+), 116 deletions(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index e03b5b48b..27ee6e076 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -7,15 +7,40 @@ import * as Debug from 'debug'; import * as path from 'path'; import { COLUMNAR_OPTIONS, PROJECT_FILE } from '../constants'; -import { CommandInstanceInfo, CommandLineInputs, CommandLineOptions, CommandMetadata, CommandPreRun, IProject, IShellRunOptions, ProjectType, ResolvedStarterTemplate, StarterManifest } from '../definitions'; +import { + CommandInstanceInfo, + CommandLineInputs, + CommandLineOptions, + CommandMetadata, + CommandPreRun, + IProject, + IShellRunOptions, + ProjectType, + ResolvedStarterTemplate, + StarterManifest, +} from '../definitions'; import { failure, input, strong } from '../lib/color'; import { Command } from '../lib/command'; import { FatalException } from '../lib/errors'; import { runCommand } from '../lib/executor'; -import { createProjectFromDetails, createProjectFromDirectory, isValidProjectId } from '../lib/project'; +import { + createProjectFromDetails, + createProjectFromDirectory, + isValidProjectId, +} from '../lib/project'; import { promptToSignup } from '../lib/session'; import { prependNodeModulesBinToPath } from '../lib/shell'; -import { AppSchema, STARTER_BASE_URL, STARTER_TEMPLATES, SUPPORTED_FRAMEWORKS, getAdvertisement, getStarterList, getStarterProjectTypes, readStarterManifest, verifyOptions } from '../lib/start'; +import { + AppSchema, + STARTER_BASE_URL, + STARTER_TEMPLATES, + SUPPORTED_FRAMEWORKS, + getAdvertisement, + getStarterList, + getStarterProjectTypes, + readStarterManifest, + verifyOptions, +} from '../lib/start'; import { emoji } from '../lib/utils/emoji'; import { createRequest } from '../lib/utils/http'; @@ -49,36 +74,52 @@ export class StartCommand extends Command implements CommandPreRun { description: ` This command creates a working Ionic app. It installs dependencies for you and sets up your project. -Running ${input('ionic start')} without any arguments will prompt you for information about your new project. - -The first argument is your app's ${input('name')}. Don't worry--you can always change this later. The ${input('--project-id')} is generated from ${input('name')} unless explicitly specified. - -The second argument is the ${input('template')} from which to generate your app. You can list all templates with the ${input('--list')} option. You can also specify a git repository URL for ${input('template')}, in which case the existing project will be cloned. - -Use the ${input('--type')} option to start projects using older versions of Ionic. For example, you can start an Ionic 3 project with ${input('--type=ionic-angular')}. Use ${input('--list')} to see all project types and templates. +Running ${input( + 'ionic start' + )} without any arguments will prompt you for information about your new project. + +The first argument is your app's ${input( + 'name' + )}. Don't worry--you can always change this later. The ${input( + '--project-id' + )} is generated from ${input('name')} unless explicitly specified. + +The second argument is the ${input( + 'template' + )} from which to generate your app. You can list all templates with the ${input( + '--list' + )} option. You can also specify a git repository URL for ${input( + 'template' + )}, in which case the existing project will be cloned. + +Use the ${input( + '--type' + )} option to start projects using older versions of Ionic. For example, you can start an Ionic 3 project with ${input( + '--type=ionic-angular' + )}. Use ${input('--list')} to see all project types and templates. `, exampleCommands: [ '', '--list', 'myApp', 'myApp blank', - 'myApp tabs --cordova', 'myApp tabs --capacitor', - 'myApp super --type=ionic-angular', - 'myApp blank --type=ionic1', - 'cordovaApp tabs --cordova', '"My App" blank', '"Conference App" https://github.com/ionic-team/ionic-conference-app', ], inputs: [ { name: 'name', - summary: `The name of your new project (e.g. ${input('myApp')}, ${input('"My App"')})`, + summary: `The name of your new project (e.g. ${input( + 'myApp' + )}, ${input('"My App"')})`, validators: [validators.required], }, { name: 'template', - summary: `The starter template to use (e.g. ${['blank', 'tabs'].map(t => input(t)).join(', ')}; use ${input('--list')} to see all)`, + summary: `The starter template to use (e.g. ${['blank', 'tabs'] + .map((t) => input(t)) + .join(', ')}; use ${input('--list')} to see all)`, validators: [validators.required], }, ], @@ -91,14 +132,16 @@ Use the ${input('--type')} option to start projects using older versions of Ioni }, { name: 'type', - summary: `Type of project to start (e.g. ${getStarterProjectTypes().map(type => input(type)).join(', ')})`, + summary: `Type of project to start (e.g. ${getStarterProjectTypes() + .map((type) => input(type)) + .join(', ')})`, type: String, }, { name: 'cordova', summary: 'Include Cordova integration', type: Boolean, - groups: [MetadataGroup.DEPRECATED] + groups: [MetadataGroup.DEPRECATED], }, { name: 'capacitor', @@ -131,25 +174,34 @@ Use the ${input('--type')} option to start projects using older versions of Ioni }, { name: 'project-id', - summary: 'Specify a slug for your app (used for the directory name and package name)', + summary: + 'Specify a slug for your app (used for the directory name and package name)', groups: [MetadataGroup.ADVANCED], spec: { value: 'slug' }, }, { name: 'package-id', - summary: 'Specify the bundle ID/application ID for your app (reverse-DNS notation)', + summary: + 'Specify the bundle ID/application ID for your app (reverse-DNS notation)', groups: [MetadataGroup.ADVANCED], spec: { value: 'id' }, }, { name: 'start-id', - summary: 'Used by the Ionic app start experience to generate an associated app locally', + summary: + 'Used by the Ionic app start experience to generate an associated app locally', groups: [MetadataGroup.HIDDEN], spec: { value: 'id' }, }, { name: 'tag', - summary: `Specify a tag to use for the starters (e.g. ${['latest', 'testing', 'next'].map(t => input(t)).join(', ')})`, + summary: `Specify a tag to use for the starters (e.g. ${[ + 'latest', + 'testing', + 'next', + ] + .map((t) => input(t)) + .join(', ')})`, default: 'latest', groups: [MetadataGroup.HIDDEN], }, @@ -160,12 +212,21 @@ Use the ${input('--type')} option to start projects using older versions of Ioni async startIdStart(inputs: CommandLineInputs, options: CommandLineOptions) { const startId = options['start-id']; - const wizardApiUrl = process.env.START_WIZARD_URL_BASE || `https://ionicframework.com`; + const wizardApiUrl = + process.env.START_WIZARD_URL_BASE || `https://ionicframework.com`; - const { req } = await createRequest('GET', `${wizardApiUrl}/api/v1/wizard/app/${startId}`, this.env.config.getHTTPConfig()); + const { req } = await createRequest( + 'GET', + `${wizardApiUrl}/api/v1/wizard/app/${startId}`, + this.env.config.getHTTPConfig() + ); const error = (e?: Error) => { - this.env.log.error(`No such app ${chalk.bold(startId)}. This app configuration may have expired. Please retry at https://ionicframework.com/start`); + this.env.log.error( + `No such app ${chalk.bold( + startId + )}. This app configuration may have expired. Please retry at https://ionicframework.com/start` + ); if (e) { throw e; } @@ -199,13 +260,19 @@ Use the ${input('--type')} option to start projects using older versions of Ioni await this.startIdConvert(startId as string); - const appIconBuffer = data.appIcon ? - Buffer.from(data.appIcon.replace(/^data:image\/\w+;base64,/, ''), 'base64') : - undefined; + const appIconBuffer = data.appIcon + ? Buffer.from( + data.appIcon.replace(/^data:image\/\w+;base64,/, ''), + 'base64' + ) + : undefined; - const splashBuffer = data.appSplash ? - Buffer.from(data.appSplash.replace(/^data:image\/\w+;base64,/, ''), 'base64') : - undefined; + const splashBuffer = data.appSplash + ? Buffer.from( + data.appSplash.replace(/^data:image\/\w+;base64,/, ''), + 'base64' + ) + : undefined; this.schema = { cloned: false, @@ -223,13 +290,18 @@ Use the ${input('--type')} option to start projects using older versions of Ioni } async startIdConvert(id: string) { - const wizardApiUrl = process.env.START_WIZARD_URL_BASE || `https://ionicframework.com`; + const wizardApiUrl = + process.env.START_WIZARD_URL_BASE || `https://ionicframework.com`; if (!wizardApiUrl) { return; } - const { req } = await createRequest('POST', `${wizardApiUrl}/api/v1/wizard/app/${id}/start`, this.env.config.getHTTPConfig()); + const { req } = await createRequest( + 'POST', + `${wizardApiUrl}/api/v1/wizard/app/${id}/start`, + this.env.config.getHTTPConfig() + ); try { await req; @@ -243,7 +315,10 @@ Use the ${input('--type')} option to start projects using older versions of Ioni * We should use if they ran `ionic start` or `ionic start --capacitor` * and they are in an interactive environment. */ - async shouldUseStartWizard(inputs: CommandLineInputs, options: CommandLineOptions) { + async shouldUseStartWizard( + inputs: CommandLineInputs, + options: CommandLineOptions + ) { const flagsToTestFor = [ 'list', 'l', @@ -258,7 +333,7 @@ Use the ${input('--type')} option to start projects using older versions of Ioni 'start-id', ]; - let didUseFlags = false ; + let didUseFlags = false; for (const key of flagsToTestFor) { if (options[key] !== null) { @@ -267,10 +342,19 @@ Use the ${input('--type')} option to start projects using older versions of Ioni } } - return inputs.length === 0 && options['interactive'] && options['deps'] && options['git'] && !didUseFlags; + return ( + inputs.length === 0 && + options['interactive'] && + options['deps'] && + options['git'] && + !didUseFlags + ); } - async preRun(inputs: CommandLineInputs, options: CommandLineOptions): Promise { + async preRun( + inputs: CommandLineInputs, + options: CommandLineOptions + ): Promise { const { promptToLogin } = await import('../lib/session'); verifyOptions(options, this.env); @@ -286,7 +370,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (confirm) { const startId = await this.env.session.wizardLogin(); if (!startId) { - this.env.log.error('There was an issue using the web wizard. Falling back to CLI wizard.'); + this.env.log.error( + 'There was an issue using the web wizard. Falling back to CLI wizard.' + ); } else { options['start-id'] = startId; } @@ -307,10 +393,16 @@ Use the ${input('--type')} option to start projects using older versions of Ioni return; } - const projectType = isValidURL(inputs[1]) ? 'custom' : options['type'] ? String(options['type']) : await this.getProjectType(); + const projectType = isValidURL(inputs[1]) + ? 'custom' + : options['type'] + ? String(options['type']) + : await this.getProjectType(); if (options['cordova']) { - const { checkForUnsupportedProject } = await import('../lib/integrations/cordova/utils'); + const { checkForUnsupportedProject } = await import( + '../lib/integrations/cordova/utils' + ); try { await checkForUnsupportedProject(projectType as ProjectType); @@ -330,7 +422,11 @@ Use the ${input('--type')} option to start projects using older versions of Ioni const app = await appClient.load(appflowId); // TODO: can ask to clone via repo_url tasks.end(); - this.env.log.info(`Using ${strong(app.name)} for ${input('name')} and ${strong(app.slug)} for ${input('--project-id')}.`); + this.env.log.info( + `Using ${strong(app.name)} for ${input('name')} and ${strong( + app.slug + )} for ${input('--project-id')}.` + ); inputs[0] = app.name; options['project-id'] = app.slug; } else { @@ -338,7 +434,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni this.env.log.nl(); this.env.log.msg( `${strong(`Every great app needs a name! ${emoji('😍', '')}`)}\n` + - `Please enter the full name of your app. You can change this at any time. To bypass this prompt next time, supply ${input('name')}, the first argument to ${input('ionic start')}.\n\n` + `Please enter the full name of your app. You can change this at any time. To bypass this prompt next time, supply ${input( + 'name' + )}, the first argument to ${input('ionic start')}.\n\n` ); } @@ -346,7 +444,7 @@ Use the ${input('--type')} option to start projects using older versions of Ioni type: 'input', name: 'name', message: 'Project name:', - validate: v => validators.required(v), + validate: (v) => validators.required(v), }); inputs[0] = name; @@ -357,8 +455,12 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (this.env.flags.interactive) { this.env.log.nl(); this.env.log.msg( - `${strong(`Let's pick the perfect starter template! ${emoji('💪', '')}`)}\n` + - `Starter templates are ready-to-go Ionic apps that come packed with everything you need to build your app. To bypass this prompt next time, supply ${input('template')}, the second argument to ${input('ionic start')}.\n\n` + `${strong( + `Let's pick the perfect starter template! ${emoji('💪', '')}` + )}\n` + + `Starter templates are ready-to-go Ionic apps that come packed with everything you need to build your app. To bypass this prompt next time, supply ${input( + 'template' + )}, the second argument to ${input('ionic start')}.\n\n` ); } @@ -367,11 +469,23 @@ Use the ${input('--type')} option to start projects using older versions of Ioni name: 'template', message: 'Starter template:', choices: () => { - const starterTemplateList = STARTER_TEMPLATES.filter(st => st.projectType === projectType); - const cols = columnar(starterTemplateList.map(({ name, description }) => [input(name), description || '']), COLUMNAR_OPTIONS).split('\n'); + const starterTemplateList = STARTER_TEMPLATES.filter( + (st) => st.projectType === projectType + ); + const cols = columnar( + starterTemplateList.map(({ name, description }) => [ + input(name), + description || '', + ]), + COLUMNAR_OPTIONS + ).split('\n'); if (starterTemplateList.length === 0) { - throw new FatalException(`No starter templates found for project type: ${input(projectType)}.`); + throw new FatalException( + `No starter templates found for project type: ${input( + projectType + )}.` + ); } return starterTemplateList.map((starter, i) => { @@ -387,7 +501,36 @@ Use the ${input('--type')} option to start projects using older versions of Ioni inputs[1] = template; } - const starterTemplate = STARTER_TEMPLATES.find(t => t.name === inputs[1] && t.projectType === projectType); + + const starterTemplate = STARTER_TEMPLATES.find( + (t) => t.name === inputs[1] && t.projectType === projectType + ); + + + if (projectType === 'angular') { + const angularMode = await this.env.prompt({ + type: 'list', + name: 'standalone', + message: 'Would you like to build your app with NgModules or Standalone Components? \n Standalone components are new way to build with Angular that simplifies the how you build your app. \n To learn more, visit the Angular docs\n https://angular.io/guide/standalone-components\n\n', + choices: () => [ + { + name: 'Standalone', + short: 'Standalone', + value: 'standalone', + }, + { + name: 'NgModules', + short: 'NgModules', + value: 'ngModules', + }, + ], + }); + if(angularMode === 'ngModules'){ + starterTemplate!.id = `${starterTemplate!.id}-ngmodules` + } + console.log(angularMode); + console.log(starterTemplate) + } if (starterTemplate && starterTemplate.type === 'repo') { inputs[1] = starterTemplate.repo; @@ -399,7 +542,8 @@ Use the ${input('--type')} option to start projects using older versions of Ioni const confirm = await this.env.prompt({ type: 'confirm', name: 'confirm', - message: 'You are already in an Ionic project directory. Do you really want to start another project here?', + message: + 'You are already in an Ionic project directory. Do you really want to start another project here?', default: false, }); @@ -413,7 +557,11 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (cloned) { if (!options['git']) { - this.env.log.warn(`The ${input('--no-git')} option has no effect when cloning apps. Git must be used.`); + this.env.log.warn( + `The ${input( + '--no-git' + )} option has no effect when cloning apps. Git must be used.` + ); } options['git'] = true; @@ -422,33 +570,55 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (options['v1'] || options['v2']) { throw new FatalException( `The ${input('--v1')} and ${input('--v2')} flags have been removed.\n` + - `Use the ${input('--type')} option. (see ${input('ionic start --help')})` + `Use the ${input('--type')} option. (see ${input( + 'ionic start --help' + )})` ); } if (options['app-name']) { - this.env.log.warn(`The ${input('--app-name')} option has been removed. Use the ${input('name')} argument with double quotes: e.g. ${input('ionic start "My App"')}`); + this.env.log.warn( + `The ${input('--app-name')} option has been removed. Use the ${input( + 'name' + )} argument with double quotes: e.g. ${input('ionic start "My App"')}` + ); } if (options['display-name']) { - this.env.log.warn(`The ${input('--display-name')} option has been removed. Use the ${input('name')} argument with double quotes: e.g. ${input('ionic start "My App"')}`); + this.env.log.warn( + `The ${input( + '--display-name' + )} option has been removed. Use the ${input( + 'name' + )} argument with double quotes: e.g. ${input('ionic start "My App"')}` + ); } if (options['bundle-id']) { - this.env.log.warn(`The ${input('--bundle-id')} option has been deprecated. Please use ${input('--package-id')}.`); + this.env.log.warn( + `The ${input( + '--bundle-id' + )} option has been deprecated. Please use ${input('--package-id')}.` + ); options['package-id'] = options['bundle-id']; } - let projectId = options['project-id'] ? String(options['project-id']) : undefined; + let projectId = options['project-id'] + ? String(options['project-id']) + : undefined; if (projectId) { await this.validateProjectId(projectId); } else { - projectId = options['project-id'] = isValidProjectId(inputs[0]) ? inputs[0] : slugify(inputs[0]); + projectId = options['project-id'] = isValidProjectId(inputs[0]) + ? inputs[0] + : slugify(inputs[0]); } const projectDir = path.resolve(projectId); - const packageId = options['package-id'] ? String(options['package-id']) : undefined; + const packageId = options['package-id'] + ? String(options['package-id']) + : undefined; if (projectId) { await this.checkForExisting(projectDir); @@ -481,7 +651,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni this.env.log.nl(); this.env.log.msg( `${strong(`Pick a framework! ${emoji('😁', '')}`)}\n\n` + - `Please select the JavaScript framework to use for your new app. To bypass this prompt next time, supply a value for the ${input('--type')} option.\n\n` + `Please select the JavaScript framework to use for your new app. To bypass this prompt next time, supply a value for the ${input( + '--type' + )} option.\n\n` ); } @@ -491,7 +663,13 @@ Use the ${input('--type')} option to start projects using older versions of Ioni message: 'Framework:', default: 'angular', choices: () => { - const cols = columnar(SUPPORTED_FRAMEWORKS.map(({ name, description }) => [input(name), description]), COLUMNAR_OPTIONS).split('\n'); + const cols = columnar( + SUPPORTED_FRAMEWORKS.map(({ name, description }) => [ + input(name), + description, + ]), + COLUMNAR_OPTIONS + ).split('\n'); return SUPPORTED_FRAMEWORKS.map((starterTemplate, i) => { return { name: cols[i], @@ -505,7 +683,11 @@ Use the ${input('--type')} option to start projects using older versions of Ioni return frameworkChoice; } - async run(inputs: CommandLineInputs, options: CommandLineOptions, runinfo: CommandInstanceInfo): Promise { + async run( + inputs: CommandLineInputs, + options: CommandLineOptions, + runinfo: CommandInstanceInfo + ): Promise { const { pkgManagerArgs } = await import('../lib/utils/npm'); const { getTopLevel, isGitInstalled } = await import('../lib/git'); @@ -522,28 +704,37 @@ Use the ${input('--type')} option to start projects using older versions of Ioni const gitInstalled = await isGitInstalled(this.env); const gitTopLevel = await getTopLevel(this.env); - let gitIntegration = gitDesired && gitInstalled && !gitTopLevel ? true : false; + let gitIntegration = + gitDesired && gitInstalled && !gitTopLevel ? true : false; if (!gitInstalled) { - const installationDocs = `See installation docs for git: ${strong('https://git-scm.com/book/en/v2/Getting-Started-Installing-Git')}`; + const installationDocs = `See installation docs for git: ${strong( + 'https://git-scm.com/book/en/v2/Getting-Started-Installing-Git' + )}`; if (appflowId) { throw new FatalException( `Git CLI not found on your PATH.\n` + - `Git must be installed to connect this app to Ionic. ${installationDocs}` + `Git must be installed to connect this app to Ionic. ${installationDocs}` ); } if (this.schema.cloned) { throw new FatalException( `Git CLI not found on your PATH.\n` + - `Git must be installed to clone apps with ${input('ionic start')}. ${installationDocs}` + `Git must be installed to clone apps with ${input( + 'ionic start' + )}. ${installationDocs}` ); } } if (gitTopLevel && !this.schema.cloned) { - this.env.log.info(`Existing git project found (${strong(gitTopLevel)}). Git operations are disabled.`); + this.env.log.info( + `Existing git project found (${strong( + gitTopLevel + )}). Git operations are disabled.` + ); } const tasks = this.createTaskChain(); @@ -558,23 +749,52 @@ Use the ${input('--type')} option to start projects using older versions of Ioni tasks.end(); if (this.schema.cloned) { - await this.env.shell.run('git', ['clone', this.schema.url, projectDir, '--progress'], { stdio: 'inherit' }); + await this.env.shell.run( + 'git', + ['clone', this.schema.url, projectDir, '--progress'], + { stdio: 'inherit' } + ); } else { - const starterTemplate = await this.findStarterTemplate(this.schema.template, this.schema.type, tag); + const starterTemplate = await this.findStarterTemplate( + this.schema.template, + this.schema.type, + tag + ); await this.downloadStarterTemplate(projectDir, starterTemplate); } let project: IProject | undefined; - if (this.project && this.project.details.context === 'multiapp' && !this.schema.cloned) { + if ( + this.project && + this.project.details.context === 'multiapp' && + !this.schema.cloned + ) { // We're in a multi-app setup, so the new config file isn't wanted. await unlink(path.resolve(projectDir, PROJECT_FILE)); - project = await createProjectFromDetails({ context: 'multiapp', configPath: path.resolve(this.project.rootDirectory, PROJECT_FILE), id: projectId, type: this.schema.type, errors: [] }, this.env); + project = await createProjectFromDetails( + { + context: 'multiapp', + configPath: path.resolve(this.project.rootDirectory, PROJECT_FILE), + id: projectId, + type: this.schema.type, + errors: [], + }, + this.env + ); project.config.set('type', this.schema.type); - project.config.set('root', path.relative(this.project.rootDirectory, projectDir)); + project.config.set( + 'root', + path.relative(this.project.rootDirectory, projectDir) + ); } else { - project = await createProjectFromDirectory(projectDir, { _: [] }, this.env, { logErrors: false }); + project = await createProjectFromDirectory( + projectDir, + { _: [] }, + this.env, + { logErrors: false } + ); } // start is weird, once the project directory is created, it becomes a @@ -586,24 +806,31 @@ Use the ${input('--type')} option to start projects using older versions of Ioni throw new FatalException('Error while loading project.'); } - this.env.shell.alterPath = p => prependNodeModulesBinToPath(projectDir, p); + this.env.shell.alterPath = (p) => + prependNodeModulesBinToPath(projectDir, p); if (!this.schema.cloned) { if (this.schema.type === 'react' || this.schema.type === 'vue') { - options['capacitor'] = true; + options['capacitor'] = true; } if (this.schema.type === 'angular' && options['cordova'] === null) { options['capacitor'] = true; } - if (options['cordova']) { - const { confirmCordovaUsage } = await import('../lib/integrations/cordova/utils'); + const { confirmCordovaUsage } = await import( + '../lib/integrations/cordova/utils' + ); const confirm = await confirmCordovaUsage(this.env); if (confirm) { - await runCommand(runinfo, ['integrations', 'enable', 'cordova', '--quiet']); + await runCommand(runinfo, [ + 'integrations', + 'enable', + 'cordova', + '--quiet', + ]); } else { options['cordova'] = false; } @@ -613,7 +840,8 @@ Use the ${input('--type')} option to start projects using older versions of Ioni const confirm = await this.env.prompt({ type: 'confirm', name: 'confirm', - message: 'Integrate your new app with Capacitor to target native iOS and Android?', + message: + 'Integrate your new app with Capacitor to target native iOS and Android?', default: false, }); @@ -623,7 +851,15 @@ Use the ${input('--type')} option to start projects using older versions of Ioni } if (options['capacitor']) { - await runCommand(runinfo, ['integrations', 'enable', 'capacitor', '--quiet', '--', this.schema.name, packageId ? packageId : 'io.ionic.starter']); + await runCommand(runinfo, [ + 'integrations', + 'enable', + 'capacitor', + '--quiet', + '--', + this.schema.name, + packageId ? packageId : 'io.ionic.starter', + ]); } await this.project.personalize({ @@ -638,27 +874,41 @@ Use the ${input('--type')} option to start projects using older versions of Ioni this.env.log.nl(); } - const shellOptions: IShellRunOptions = { cwd: projectDir, stdio: 'inherit' }; + const shellOptions: IShellRunOptions = { + cwd: projectDir, + stdio: 'inherit', + }; if (options['deps']) { this.env.log.msg('Installing dependencies may take several minutes.'); this.env.log.rawmsg(getAdvertisement()); - const [installer, ...installerArgs] = await pkgManagerArgs(this.env.config.get('npmClient'), { command: 'install' }); + const [installer, ...installerArgs] = await pkgManagerArgs( + this.env.config.get('npmClient'), + { command: 'install' } + ); await this.env.shell.run(installer, installerArgs, shellOptions); if (options['cordova']) { try { - await this.env.shell.run('ng', ['add', '@ionic/cordova-builders', '--skip-confirmation'], { cwd: this.project.rootDirectory }); + await this.env.shell.run( + 'ng', + ['add', '@ionic/cordova-builders', '--skip-confirmation'], + { cwd: this.project.rootDirectory } + ); } catch (e: any) { debug('Error while adding @ionic/cordova-builders: %O', e); } } } else { // --no-deps flag was used so skip installing dependencies, this also results in the package.json being out sync with the package.json so warn the user - this.env.log.warn('Using the --no-deps flag results in an out of date package lock file. The lock file can be updated by performing an `install` with your package manager.'); + this.env.log.warn( + 'Using the --no-deps flag results in an out of date package lock file. The lock file can be updated by performing an `install` with your package manager.' + ); if (options['cordova']) { - this.env.log.warn('@ionic/cordova-builders couldn\'t be added, make sure you run `ng add @ionic/cordova-builders` after performing an `install` with your package manager.'); + this.env.log.warn( + "@ionic/cordova-builders couldn't be added, make sure you run `ng add @ionic/cordova-builders` after performing an `install` with your package manager." + ); } } @@ -667,7 +917,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni try { await this.env.shell.run('git', ['init'], shellOptions); // TODO: use initializeRepo()? } catch (e: any) { - this.env.log.warn('Error encountered during repo initialization. Disabling further git operations.'); + this.env.log.warn( + 'Error encountered during repo initialization. Disabling further git operations.' + ); gitIntegration = false; } } @@ -700,9 +952,15 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (gitIntegration) { try { await this.env.shell.run('git', ['add', '-A'], shellOptions); - await this.env.shell.run('git', ['commit', '-m', 'Initial commit', '--no-gpg-sign'], shellOptions); + await this.env.shell.run( + 'git', + ['commit', '-m', 'Initial commit', '--no-gpg-sign'], + shellOptions + ); } catch (e: any) { - this.env.log.warn('Error encountered during commit. Disabling further git operations.'); + this.env.log.warn( + 'Error encountered during commit. Disabling further git operations.' + ); gitIntegration = false; } } @@ -714,7 +972,12 @@ Use the ${input('--type')} option to start projects using older versions of Ioni this.env.log.nl(); - await this.showNextSteps(projectDir, this.schema.cloned, linkConfirmed, !options['cordova']); + await this.showNextSteps( + projectDir, + this.schema.cloned, + linkConfirmed, + !options['cordova'] + ); } async checkForExisting(projectDir: string) { @@ -724,12 +987,16 @@ Use the ${input('--type')} option to start projects using older versions of Ioni const confirm = await this.env.prompt({ type: 'confirm', name: 'confirm', - message: `${input(prettyPath(projectDir))} exists. ${failure('Overwrite?')}`, + message: `${input(prettyPath(projectDir))} exists. ${failure( + 'Overwrite?' + )}`, default: false, }); if (!confirm) { - this.env.log.msg(`Not erasing existing project in ${input(prettyPath(projectDir))}.`); + this.env.log.msg( + `Not erasing existing project in ${input(prettyPath(projectDir))}.` + ); throw new FatalException(); } @@ -737,13 +1004,21 @@ Use the ${input('--type')} option to start projects using older versions of Ioni } } - async findStarterTemplate(template: string, type: string, tag: string): Promise { - const starterTemplate = STARTER_TEMPLATES.find(t => t.projectType === type && t.name === template); + async findStarterTemplate( + template: string, + type: string, + tag: string + ): Promise { + const starterTemplate = STARTER_TEMPLATES.find( + (t) => t.projectType === type && t.name === template + ); if (starterTemplate && starterTemplate.type === 'managed') { return { ...starterTemplate, - archive: `${STARTER_BASE_URL}/${tag === 'latest' ? '' : `${tag}/`}${starterTemplate.id}.tar.gz`, + archive: `${STARTER_BASE_URL}/${tag === 'latest' ? '' : `${tag}/`}${ + starterTemplate.id + }.tar.gz`, }; } @@ -751,7 +1026,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni tasks.next('Looking up starter'); const starterList = await getStarterList(this.env.config, tag); - const starter = starterList.starters.find(t => t.type === type && t.name === template); + const starter = starterList.starters.find( + (t) => t.type === type && t.name === template + ); if (starter) { tasks.end(); @@ -759,12 +1036,16 @@ Use the ${input('--type')} option to start projects using older versions of Ioni return { name: starter.name, projectType: starter.type, - archive: `${STARTER_BASE_URL}/${tag === 'latest' ? '' : `${tag}/`}${starter.id}.tar.gz`, + archive: `${STARTER_BASE_URL}/${tag === 'latest' ? '' : `${tag}/`}${ + starter.id + }.tar.gz`, }; } else { throw new FatalException( `Unable to find starter template for ${input(template)}\n` + - `If this is not a typo, please make sure it is a valid starter template within the starters repo: ${strong('https://github.com/ionic-team/starters')}` + `If this is not a typo, please make sure it is a valid starter template within the starters repo: ${strong( + 'https://github.com/ionic-team/starters' + )}` ); } } @@ -775,7 +1056,9 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (!['custom', ...projectTypes].includes(type)) { throw new FatalException( `${input(type)} is not a valid project type.\n` + - `Please choose a different ${input('--type')}. Use ${input('ionic start --list')} to list all available starter templates.` + `Please choose a different ${input('--type')}. Use ${input( + 'ionic start --list' + )} to list all available starter templates.` ); } } @@ -784,16 +1067,22 @@ Use the ${input('--type')} option to start projects using older versions of Ioni if (!isValidProjectId(projectId)) { throw new FatalException( `${input(projectId)} is not a valid package or directory name.\n` + - `Please choose a different ${input('--project-id')}. Alphanumeric characters are always safe.` + `Please choose a different ${input( + '--project-id' + )}. Alphanumeric characters are always safe.` ); } } - async loadManifest(manifestPath: string): Promise { + async loadManifest( + manifestPath: string + ): Promise { try { return await readStarterManifest(manifestPath); } catch (e: any) { - debug(`Error with manifest file ${strong(prettyPath(manifestPath))}: ${e}`); + debug( + `Error with manifest file ${strong(prettyPath(manifestPath))}: ${e}` + ); } } @@ -805,38 +1094,80 @@ Use the ${input('--type')} option to start projects using older versions of Ioni } } - async downloadStarterTemplate(projectDir: string, starterTemplate: ResolvedStarterTemplate) { + async downloadStarterTemplate( + projectDir: string, + starterTemplate: ResolvedStarterTemplate + ) { const { createRequest, download } = await import('../lib/utils/http'); const { tar } = await import('../lib/utils/archive'); const tasks = this.createTaskChain(); - const task = tasks.next(`Downloading and extracting ${input(starterTemplate.name.toString())} starter`); + const task = tasks.next( + `Downloading and extracting ${input( + starterTemplate.name.toString() + )} starter` + ); debug('Tar extraction created for %s', projectDir); const ws = tar.extract({ cwd: projectDir }); - const { req } = await createRequest('GET', starterTemplate.archive, this.env.config.getHTTPConfig()); - await download(req, ws, { progress: (loaded, total) => task.progress(loaded, total) }); + const { req } = await createRequest( + 'GET', + starterTemplate.archive, + this.env.config.getHTTPConfig() + ); + await download(req, ws, { + progress: (loaded, total) => task.progress(loaded, total), + }); tasks.end(); } - async showNextSteps(projectDir: string, cloned: boolean, linkConfirmed: boolean, isCapacitor: boolean) { - const cordovaResCommand = isCapacitor ? 'cordova-res --skip-config --copy' : 'cordova-res'; + async showNextSteps( + projectDir: string, + cloned: boolean, + linkConfirmed: boolean, + isCapacitor: boolean + ) { + const cordovaResCommand = isCapacitor + ? 'cordova-res --skip-config --copy' + : 'cordova-res'; const steps = [ - `Go to your ${cloned ? 'cloned' : 'new'} project: ${input(`cd ${prettyPath(projectDir)}`)}`, - `Run ${input('ionic serve')} within the app directory to see your app in the browser`, - isCapacitor ? - `Run ${input('ionic capacitor add')} to add a native iOS or Android project using Capacitor` : - `Run ${input('ionic cordova platform add')} to add a native iOS or Android project using Cordova`, - `Generate your app icon and splash screens using ${input(cordovaResCommand)}`, - `Explore the Ionic docs for components, tutorials, and more: ${strong('https://ion.link/docs')}`, - `Building an enterprise app? Ionic has Enterprise Support and Features: ${strong('https://ion.link/enterprise-edition')}`, + `Go to your ${cloned ? 'cloned' : 'new'} project: ${input( + `cd ${prettyPath(projectDir)}` + )}`, + `Run ${input( + 'ionic serve' + )} within the app directory to see your app in the browser`, + isCapacitor + ? `Run ${input( + 'ionic capacitor add' + )} to add a native iOS or Android project using Capacitor` + : `Run ${input( + 'ionic cordova platform add' + )} to add a native iOS or Android project using Cordova`, + `Generate your app icon and splash screens using ${input( + cordovaResCommand + )}`, + `Explore the Ionic docs for components, tutorials, and more: ${strong( + 'https://ion.link/docs' + )}`, + `Building an enterprise app? Ionic has Enterprise Support and Features: ${strong( + 'https://ion.link/enterprise-edition' + )}`, ]; if (linkConfirmed) { - steps.push(`Push your code to Ionic Appflow to perform real-time updates, and more: ${input('git push ionic master')}`); + steps.push( + `Push your code to Ionic Appflow to perform real-time updates, and more: ${input( + 'git push ionic master' + )}` + ); } - this.env.log.msg(`${strong('Your Ionic app is ready! Follow these next steps')}:\n${steps.map(s => ` - ${s}`).join('\n')}`); + this.env.log.msg( + `${strong('Your Ionic app is ready! Follow these next steps')}:\n${steps + .map((s) => ` - ${s}`) + .join('\n')}` + ); } } diff --git a/packages/@ionic/cli/src/definitions.ts b/packages/@ionic/cli/src/definitions.ts index 88debe3b5..ec2c8f406 100644 --- a/packages/@ionic/cli/src/definitions.ts +++ b/packages/@ionic/cli/src/definitions.ts @@ -837,6 +837,7 @@ export interface BaseStarterTemplate { name: string; projectType: ProjectType; description?: string; + id?: string } export interface RepoStarterTemplate extends BaseStarterTemplate { From c191763ffac783f1aca9817283bf0563fa0270bb Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 17:27:02 +0000 Subject: [PATCH 2/8] fix typos, make ngmodules first option --- packages/@ionic/cli/src/commands/start.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index 27ee6e076..154ae4224 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -511,18 +511,18 @@ Use the ${input( const angularMode = await this.env.prompt({ type: 'list', name: 'standalone', - message: 'Would you like to build your app with NgModules or Standalone Components? \n Standalone components are new way to build with Angular that simplifies the how you build your app. \n To learn more, visit the Angular docs\n https://angular.io/guide/standalone-components\n\n', + message: 'Would you like to build your app with NgModules or Standalone Components? \n Standalone components are a new way to build with Angular that simplifies the you build your app. \n To learn more, visit the Angular docs:\n https://angular.io/guide/standalone-components\n\n', choices: () => [ - { - name: 'Standalone', - short: 'Standalone', - value: 'standalone', - }, { name: 'NgModules', short: 'NgModules', value: 'ngModules', }, + { + name: 'Standalone', + short: 'Standalone', + value: 'standalone', + } ], }); if(angularMode === 'ngModules'){ From aed203e4570cce2f97319c07e5ff28deab8ca488 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 17:28:50 +0000 Subject: [PATCH 3/8] fix typo --- packages/@ionic/cli/src/commands/start.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index 154ae4224..7730efb11 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -511,7 +511,7 @@ Use the ${input( const angularMode = await this.env.prompt({ type: 'list', name: 'standalone', - message: 'Would you like to build your app with NgModules or Standalone Components? \n Standalone components are a new way to build with Angular that simplifies the you build your app. \n To learn more, visit the Angular docs:\n https://angular.io/guide/standalone-components\n\n', + message: 'Would you like to build your app with NgModules or Standalone Components? \n Standalone components are a new way to build with Angular that simplifies the way you build your app. \n To learn more, visit the Angular docs:\n https://angular.io/guide/standalone-components\n\n', choices: () => [ { name: 'NgModules', From 303a262b553698bbadd9afbfbbb26719d1c4c40e Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 17:30:15 +0000 Subject: [PATCH 4/8] add standalone modifier --- packages/@ionic/cli/src/commands/start.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index 7730efb11..32145e8d4 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -525,11 +525,9 @@ Use the ${input( } ], }); - if(angularMode === 'ngModules'){ - starterTemplate!.id = `${starterTemplate!.id}-ngmodules` + if (angularMode === 'standalone'){ + starterTemplate!.id = `${starterTemplate!.id}-standalone` } - console.log(angularMode); - console.log(starterTemplate) } if (starterTemplate && starterTemplate.type === 'repo') { From 494163a79d544918d74444aae6fd2ff3915bbe08 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 14:32:46 -0400 Subject: [PATCH 5/8] add support for standalone app --- packages/@ionic/cli/src/commands/start.ts | 19 +++++++--- packages/@ionic/cli/src/constants.ts | 3 +- packages/@ionic/cli/src/definitions.ts | 2 +- packages/@ionic/cli/src/lib/project/index.ts | 3 +- packages/@ionic/cli/src/lib/start.ts | 37 +++++++++++++++++++- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index 32145e8d4..5c6cd6861 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -6,7 +6,7 @@ import * as chalk from 'chalk'; import * as Debug from 'debug'; import * as path from 'path'; -import { COLUMNAR_OPTIONS, PROJECT_FILE } from '../constants'; +import { COLUMNAR_OPTIONS, PROJECT_FILE, ANGULAR_STANDALONE } from '../constants'; import { CommandInstanceInfo, CommandLineInputs, @@ -393,7 +393,7 @@ Use the ${input( return; } - const projectType = isValidURL(inputs[1]) + let projectType = isValidURL(inputs[1]) ? 'custom' : options['type'] ? String(options['type']) @@ -502,7 +502,7 @@ Use the ${input( } - const starterTemplate = STARTER_TEMPLATES.find( + let starterTemplate = STARTER_TEMPLATES.find( (t) => t.name === inputs[1] && t.projectType === projectType ); @@ -525,8 +525,17 @@ Use the ${input( } ], }); - if (angularMode === 'standalone'){ - starterTemplate!.id = `${starterTemplate!.id}-standalone` + + /** + * If the developer wants to use standalone + * components then we need to get the correct starter. + */ + if (angularMode === 'standalone') { + const standaloneStarter = STARTER_TEMPLATES.find((t) => t.name === inputs[1] && t.projectType === ANGULAR_STANDALONE); + if (standaloneStarter !== undefined) { + projectType = ANGULAR_STANDALONE; + starterTemplate = standaloneStarter; + } } } diff --git a/packages/@ionic/cli/src/constants.ts b/packages/@ionic/cli/src/constants.ts index 8d74f229f..a3ee49d8d 100644 --- a/packages/@ionic/cli/src/constants.ts +++ b/packages/@ionic/cli/src/constants.ts @@ -5,9 +5,10 @@ import * as path from 'path'; import { ProjectType } from './definitions'; export const ASSETS_DIRECTORY = path.resolve(__dirname, 'assets'); +export const ANGULAR_STANDALONE = 'angular-standalone'; export const PROJECT_FILE = process.env['IONIC_CONFIG_FILE'] ?? 'ionic.config.json'; -export const PROJECT_TYPES: ProjectType[] = ['angular', 'react', 'vue', 'ionic-angular', 'ionic1', 'custom', 'vue-vite', 'react-vite']; +export const PROJECT_TYPES: ProjectType[] = ['angular', ANGULAR_STANDALONE, 'react', 'vue', 'ionic-angular', 'ionic1', 'custom', 'vue-vite', 'react-vite']; export const LEGACY_PROJECT_TYPES: ProjectType[] = ['ionic-angular', 'ionic1']; export const MODERN_PROJECT_TYPES: ProjectType[] = lodash.difference(PROJECT_TYPES, LEGACY_PROJECT_TYPES); diff --git a/packages/@ionic/cli/src/definitions.ts b/packages/@ionic/cli/src/definitions.ts index ec2c8f406..93edc46d4 100644 --- a/packages/@ionic/cli/src/definitions.ts +++ b/packages/@ionic/cli/src/definitions.ts @@ -78,7 +78,7 @@ export interface Runner { run(options: T): Promise; } -export type ProjectType = 'angular' | 'ionic-angular' | 'ionic1' | 'custom' | 'bare' | 'react' | 'vue' | 'react-vite' | 'vue-vite'; +export type ProjectType = 'angular' | 'angular-standalone' | 'ionic-angular' | 'ionic1' | 'custom' | 'bare' | 'react' | 'vue' | 'react-vite' | 'vue-vite'; export type HookName = 'build:before' | 'build:after' | 'serve:before' | 'serve:after' | 'capacitor:run:before' | 'capacitor:build:before' | 'capacitor:sync:after'; export type CapacitorRunHookName = 'capacitor:run:before'; diff --git a/packages/@ionic/cli/src/lib/project/index.ts b/packages/@ionic/cli/src/lib/project/index.ts index 7bdf9b67a..98979e364 100644 --- a/packages/@ionic/cli/src/lib/project/index.ts +++ b/packages/@ionic/cli/src/lib/project/index.ts @@ -8,7 +8,7 @@ import * as Debug from 'debug'; import * as lodash from 'lodash'; import * as path from 'path'; -import { PROJECT_FILE, PROJECT_TYPES } from '../../constants'; +import { PROJECT_FILE, PROJECT_TYPES, ANGULAR_STANDALONE } from '../../constants'; import { IClient, IConfig, IIntegration, ILogger, IMultiProjectConfig, IProject, IProjectConfig, ISession, IShell, InfoItem, IntegrationName, IonicContext, IonicEnvironmentFlags, ProjectIntegration, ProjectPersonalizationDetails, ProjectType } from '../../definitions'; import { isMultiProjectConfig, isProjectConfig } from '../../guards'; import { ancillary, failure, input, strong } from '../color'; @@ -299,6 +299,7 @@ export async function createProjectFromDetails(details: ProjectDetailsResult, de switch (type) { case 'angular': + case ANGULAR_STANDALONE: const { AngularProject } = await import('./angular'); return new AngularProject(details, deps); case 'react': diff --git a/packages/@ionic/cli/src/lib/start.ts b/packages/@ionic/cli/src/lib/start.ts index 8fe47f803..7c76eacfb 100644 --- a/packages/@ionic/cli/src/lib/start.ts +++ b/packages/@ionic/cli/src/lib/start.ts @@ -2,7 +2,7 @@ import { readJson } from '@ionic/utils-fs'; import { columnar } from '@ionic/utils-terminal'; import * as lodash from 'lodash'; -import { COLUMNAR_OPTIONS, PROJECT_TYPES } from '../constants'; +import { COLUMNAR_OPTIONS, PROJECT_TYPES, ANGULAR_STANDALONE } from '../constants'; import { CommandLineOptions, IConfig, ILogger, ProjectType, StarterList, StarterManifest, StarterTemplate } from '../definitions'; import { isStarterManifest } from '../guards'; @@ -272,6 +272,41 @@ export const STARTER_TEMPLATES: StarterTemplate[] = [ description: 'A template for the "Build Your First App" tutorial', repo: 'https://github.com/ionic-team/photo-gallery-capacitor-ng', }, + { + name: 'tabs', + projectType: ANGULAR_STANDALONE, + type: 'managed', + description: 'A starting project with a simple tabbed interface', + id: 'angular-standalone-official-tabs', + }, + { + name: 'sidemenu', + projectType: ANGULAR_STANDALONE, + type: 'managed', + description: 'A starting project with a side menu with navigation in the content area', + id: 'angular-standalone-official-sidemenu', + }, + { + name: 'blank', + projectType: ANGULAR_STANDALONE, + type: 'managed', + description: 'A blank starter project', + id: 'angular-standalone-official-blank', + }, + { + name: 'list', + projectType: ANGULAR_STANDALONE, + type: 'managed', + description: 'A starting project with a list', + id: 'angular-standalone-official-list', + }, + { + name: 'my-first-app', + projectType: ANGULAR_STANDALONE, + type: 'repo', + description: 'A template for the "Build Your First App" tutorial', + repo: 'https://github.com/ionic-team/photo-gallery-capacitor-ng', + }, // React { name: 'blank', From 54ab2651e363ab05b53371a744ca480049e6c2fc Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 14:35:40 -0400 Subject: [PATCH 6/8] add cap --- packages/@ionic/cli/src/commands/start.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index 5c6cd6861..e4425fa40 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -821,7 +821,10 @@ Use the ${input( options['capacitor'] = true; } - if (this.schema.type === 'angular' && options['cordova'] === null) { + if ( + (this.schema.type === 'angular' || this.schema.type === 'angular-standalone') + && options['cordova'] === null + ) { options['capacitor'] = true; } From aa9e382cb78b472086a854c88bc1088d25e8f958 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 18:36:44 +0000 Subject: [PATCH 7/8] remove unused type --- packages/@ionic/cli/src/definitions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@ionic/cli/src/definitions.ts b/packages/@ionic/cli/src/definitions.ts index 93edc46d4..98f2ae619 100644 --- a/packages/@ionic/cli/src/definitions.ts +++ b/packages/@ionic/cli/src/definitions.ts @@ -837,7 +837,6 @@ export interface BaseStarterTemplate { name: string; projectType: ProjectType; description?: string; - id?: string } export interface RepoStarterTemplate extends BaseStarterTemplate { From a766a53e4fa6674245735e9b4fbae9a4f9fb0bd6 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Fri, 28 Apr 2023 18:38:32 +0000 Subject: [PATCH 8/8] add more comments --- packages/@ionic/cli/src/commands/start.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/@ionic/cli/src/commands/start.ts b/packages/@ionic/cli/src/commands/start.ts index e4425fa40..f5d4803df 100644 --- a/packages/@ionic/cli/src/commands/start.ts +++ b/packages/@ionic/cli/src/commands/start.ts @@ -531,7 +531,18 @@ Use the ${input( * components then we need to get the correct starter. */ if (angularMode === 'standalone') { + /** + * Attempt to find the same type of starter + * but with standalone components. + */ const standaloneStarter = STARTER_TEMPLATES.find((t) => t.name === inputs[1] && t.projectType === ANGULAR_STANDALONE); + + /** + * If found, update the projectType and + * starterTemplate vars to use the new project. + * If no project is found it will continue + * to use the NgModule version. + */ if (standaloneStarter !== undefined) { projectType = ANGULAR_STANDALONE; starterTemplate = standaloneStarter;