start.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.STARTER_TEMPLATES = exports.SUPPORTED_FRAMEWORKS = exports.getStarterProjectTypes = exports.getStarterList = exports.getAdvertisement = exports.readStarterManifest = exports.verifyOptions = exports.STARTER_BASE_URL = void 0;
  4. const tslib_1 = require("tslib");
  5. const utils_fs_1 = require("@ionic/utils-fs");
  6. const utils_terminal_1 = require("@ionic/utils-terminal");
  7. const lodash = tslib_1.__importStar(require("lodash"));
  8. const constants_1 = require("../constants");
  9. const guards_1 = require("../guards");
  10. const color_1 = require("./color");
  11. const errors_1 = require("./errors");
  12. const project_1 = require("./project");
  13. const emoji_1 = require("./utils/emoji");
  14. const http_1 = require("./utils/http");
  15. exports.STARTER_BASE_URL = 'https://d2ql0qc7j8u4b2.cloudfront.net';
  16. function verifyOptions(options, { log }) {
  17. // If the action is list then lets just end here.
  18. if (options['list']) {
  19. const typeOption = options['type'] ? String(options['type']) : undefined;
  20. if (typeOption && !constants_1.PROJECT_TYPES.includes(typeOption)) {
  21. throw new errors_1.FatalException(`${(0, color_1.input)(typeOption)} is not a valid project type.\n` +
  22. `Valid project types are: ${getStarterProjectTypes().map(type => (0, color_1.input)(type)).join(', ')}`);
  23. }
  24. const headers = ['name', 'description'].map(h => (0, color_1.strong)(h));
  25. const starterTypes = typeOption ? [typeOption] : getStarterProjectTypes();
  26. for (const starterType of starterTypes) {
  27. const starters = exports.STARTER_TEMPLATES.filter(template => template.projectType === starterType);
  28. log.rawmsg(`\n${(0, color_1.strong)(`Starters for ${(0, project_1.prettyProjectName)(starterType)}`)} (${(0, color_1.input)(`--type=${starterType}`)})\n\n`);
  29. log.rawmsg((0, utils_terminal_1.columnar)(starters.map(({ name, description }) => [(0, color_1.input)(name), description || '']), { ...constants_1.COLUMNAR_OPTIONS, headers }));
  30. log.rawmsg('\n');
  31. }
  32. throw new errors_1.FatalException('', 0);
  33. }
  34. if (options['skip-deps']) {
  35. log.warn(`The ${(0, color_1.input)('--skip-deps')} option has been deprecated. Please use ${(0, color_1.input)('--no-deps')}.`);
  36. options['deps'] = false;
  37. }
  38. if (options['skip-link']) {
  39. log.warn(`The ${(0, color_1.input)('--skip-link')} option has been deprecated. Please use ${(0, color_1.input)('--no-link')}.`);
  40. options['link'] = false;
  41. }
  42. if (options['pro-id']) {
  43. log.warn(`The ${(0, color_1.input)('--pro-id')} option has been deprecated. Please use ${(0, color_1.input)('--id')}.`);
  44. options['id'] = options['pro-id'];
  45. }
  46. if (options['id']) {
  47. if (options['link'] === false) {
  48. log.warn(`The ${(0, color_1.input)('--no-link')} option has no effect with ${(0, color_1.input)('--id')}. App must be linked.`);
  49. }
  50. options['link'] = true;
  51. if (!options['git']) {
  52. log.warn(`The ${(0, color_1.input)('--no-git')} option has no effect with ${(0, color_1.input)('--id')}. Git must be used.`);
  53. }
  54. options['git'] = true;
  55. }
  56. }
  57. exports.verifyOptions = verifyOptions;
  58. async function readStarterManifest(p) {
  59. try {
  60. const manifest = await (0, utils_fs_1.readJson)(p);
  61. if (!(0, guards_1.isStarterManifest)(manifest)) {
  62. throw new Error(`${p} is not a valid starter manifest.`);
  63. }
  64. return manifest;
  65. }
  66. catch (e) {
  67. if (e.code === 'ENOENT') {
  68. throw new Error(`${p} not found`);
  69. }
  70. else if (e instanceof SyntaxError) {
  71. throw new Error(`${p} is not valid JSON.`);
  72. }
  73. throw e;
  74. }
  75. }
  76. exports.readStarterManifest = readStarterManifest;
  77. function getAdvertisement() {
  78. const choices = [getAppflowAdvertisement, getAdvisoryAdvertisement, getEnterpriseAdvertisement];
  79. const idx = Math.floor(Math.random() * choices.length);
  80. return `${choices[idx]()}\n\n`;
  81. }
  82. exports.getAdvertisement = getAdvertisement;
  83. function getAppflowAdvertisement() {
  84. return `
  85. ──────────────────────────────────────────────────────────────
  86. ${(0, color_1.title)('Ionic Appflow')}, the mobile DevOps solution by Ionic
  87. Continuously build, deploy, and ship apps ${(0, emoji_1.emoji)('🚀', '')}
  88. Focus on building apps while we automate the rest ${(0, emoji_1.emoji)('🎁', '')}
  89. ${(0, emoji_1.emoji)(' 👉 ', 'Learn more:')} ${(0, color_1.strong)('https://ion.link/appflow')} ${(0, emoji_1.emoji)(' 👈', '')}
  90. ──────────────────────────────────────────────────────────────
  91. `;
  92. }
  93. function getAdvisoryAdvertisement() {
  94. return `
  95. ──────────────────────────────────────────────────────────────────────────────
  96. ${(0, color_1.title)('Ionic Advisory')}, tailored solutions and expert services by Ionic
  97. Go to market faster ${(0, emoji_1.emoji)('🏆', '')}
  98. Real-time troubleshooting and guidance ${(0, emoji_1.emoji)('💁', '')}
  99. Custom training, best practices, code and architecture reviews ${(0, emoji_1.emoji)('🔎', '')}
  100. Customized strategies for every phase of the development lifecycle ${(0, emoji_1.emoji)('🔮', '')}
  101. ${(0, emoji_1.emoji)(' 👉 ', 'Learn more:')} ${(0, color_1.strong)('https://ion.link/advisory')} ${(0, emoji_1.emoji)(' 👈', '')}
  102. ──────────────────────────────────────────────────────────────────────────────
  103. `;
  104. }
  105. function getEnterpriseAdvertisement() {
  106. return `
  107. ──────────────────────────────────────────────────────────────────────
  108. ${(0, color_1.title)('Ionic Enterprise')}, platform and solutions for teams by Ionic
  109. Powerful library of native APIs ${(0, emoji_1.emoji)('⚡️', '')}
  110. A supercharged platform for teams ${(0, emoji_1.emoji)('💪', '')}
  111. ${(0, emoji_1.emoji)(' 👉 ', 'Learn more:')} ${(0, color_1.strong)('https://ion.link/enterprise')} ${(0, emoji_1.emoji)(' 👈', '')}
  112. ──────────────────────────────────────────────────────────────────────
  113. `;
  114. }
  115. async function getStarterList(config, tag = 'latest') {
  116. const { req } = await (0, http_1.createRequest)('GET', `${exports.STARTER_BASE_URL}/${tag === 'latest' ? '' : `${tag}/`}starters.json`, config.getHTTPConfig());
  117. const res = await req;
  118. // TODO: typecheck
  119. return res.body;
  120. }
  121. exports.getStarterList = getStarterList;
  122. function getStarterProjectTypes() {
  123. return lodash.uniq(exports.STARTER_TEMPLATES.map(t => t.projectType));
  124. }
  125. exports.getStarterProjectTypes = getStarterProjectTypes;
  126. exports.SUPPORTED_FRAMEWORKS = [
  127. {
  128. name: 'Angular',
  129. type: 'angular',
  130. description: 'https://angular.io',
  131. },
  132. {
  133. name: 'React',
  134. type: 'react',
  135. description: 'https://reactjs.org',
  136. },
  137. {
  138. name: 'Vue',
  139. type: 'vue',
  140. description: 'https://vuejs.org',
  141. },
  142. ];
  143. exports.STARTER_TEMPLATES = [
  144. // Vue
  145. {
  146. name: 'tabs',
  147. projectType: 'vue',
  148. type: 'managed',
  149. description: 'A starting project with a simple tabbed interface',
  150. id: 'vue-vite-official-tabs',
  151. },
  152. {
  153. name: 'sidemenu',
  154. projectType: 'vue',
  155. type: 'managed',
  156. description: 'A starting project with a side menu with navigation in the content area',
  157. id: 'vue-vite-official-sidemenu',
  158. },
  159. {
  160. name: 'blank',
  161. projectType: 'vue',
  162. type: 'managed',
  163. description: 'A blank starter project',
  164. id: 'vue-vite-official-blank',
  165. },
  166. {
  167. name: 'list',
  168. projectType: 'vue',
  169. type: 'managed',
  170. description: 'A starting project with a list',
  171. id: 'vue-vite-official-list',
  172. },
  173. // Angular
  174. {
  175. name: 'tabs',
  176. projectType: 'angular',
  177. type: 'managed',
  178. description: 'A starting project with a simple tabbed interface',
  179. id: 'angular-official-tabs',
  180. },
  181. {
  182. name: 'sidemenu',
  183. projectType: 'angular',
  184. type: 'managed',
  185. description: 'A starting project with a side menu with navigation in the content area',
  186. id: 'angular-official-sidemenu',
  187. },
  188. {
  189. name: 'blank',
  190. projectType: 'angular',
  191. type: 'managed',
  192. description: 'A blank starter project',
  193. id: 'angular-official-blank',
  194. },
  195. {
  196. name: 'list',
  197. projectType: 'angular',
  198. type: 'managed',
  199. description: 'A starting project with a list',
  200. id: 'angular-official-list',
  201. },
  202. {
  203. name: 'my-first-app',
  204. projectType: 'angular',
  205. type: 'repo',
  206. description: 'A template for the "Build Your First App" tutorial',
  207. repo: 'https://github.com/ionic-team/photo-gallery-capacitor-ng',
  208. },
  209. {
  210. name: 'tabs',
  211. projectType: constants_1.ANGULAR_STANDALONE,
  212. type: 'managed',
  213. description: 'A starting project with a simple tabbed interface',
  214. id: 'angular-standalone-official-tabs',
  215. },
  216. {
  217. name: 'sidemenu',
  218. projectType: constants_1.ANGULAR_STANDALONE,
  219. type: 'managed',
  220. description: 'A starting project with a side menu with navigation in the content area',
  221. id: 'angular-standalone-official-sidemenu',
  222. },
  223. {
  224. name: 'blank',
  225. projectType: constants_1.ANGULAR_STANDALONE,
  226. type: 'managed',
  227. description: 'A blank starter project',
  228. id: 'angular-standalone-official-blank',
  229. },
  230. {
  231. name: 'list',
  232. projectType: constants_1.ANGULAR_STANDALONE,
  233. type: 'managed',
  234. description: 'A starting project with a list',
  235. id: 'angular-standalone-official-list',
  236. },
  237. {
  238. name: 'my-first-app',
  239. projectType: constants_1.ANGULAR_STANDALONE,
  240. type: 'repo',
  241. description: 'A template for the "Build Your First App" tutorial',
  242. repo: 'https://github.com/ionic-team/photo-gallery-capacitor-ng',
  243. },
  244. // React
  245. {
  246. name: 'blank',
  247. projectType: 'react',
  248. type: 'managed',
  249. description: 'A blank starter project',
  250. id: 'react-vite-official-blank',
  251. },
  252. {
  253. name: 'list',
  254. projectType: 'react',
  255. type: 'managed',
  256. description: 'A starting project with a list',
  257. id: 'react-vite-official-list',
  258. },
  259. {
  260. name: 'my-first-app',
  261. projectType: 'react',
  262. type: 'repo',
  263. description: 'A template for the "Build Your First App" tutorial',
  264. repo: 'https://github.com/ionic-team/photo-gallery-capacitor-react',
  265. },
  266. {
  267. name: 'sidemenu',
  268. projectType: 'react',
  269. type: 'managed',
  270. description: 'A starting project with a side menu with navigation in the content area',
  271. id: 'react-vite-official-sidemenu',
  272. },
  273. {
  274. name: 'tabs',
  275. projectType: 'react',
  276. type: 'managed',
  277. description: 'A starting project with a simple tabbed interface',
  278. id: 'react-vite-official-tabs',
  279. },
  280. ];