@haxtheweb/create 9.0.5 → 9.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/create.js CHANGED
@@ -4,15 +4,17 @@
4
4
 
5
5
  var fs = _interopRequireWildcard(require("node:fs"));
6
6
  var path = _interopRequireWildcard(require("node:path"));
7
- var hax = _interopRequireWildcard(require("@haxtheweb/haxcms-nodejs"));
8
- var _art = require("./art.js");
9
- var _utils = require("./utils.js");
10
7
  var _promises = require("node:timers/promises");
11
8
  var ejs = _interopRequireWildcard(require("ejs"));
12
9
  var p = _interopRequireWildcard(require("@clack/prompts"));
13
10
  var _picocolors = _interopRequireDefault(require("picocolors"));
11
+ var _statements = require("./lib/statements.js");
12
+ var _utils = require("./lib/utils.js");
13
+ var hax = _interopRequireWildcard(require("@haxtheweb/haxcms-nodejs"));
14
+ var haxcmsNodejsCli = _interopRequireWildcard(require("@haxtheweb/haxcms-nodejs/dist/cli.js"));
14
15
  var child_process = _interopRequireWildcard(require("child_process"));
15
16
  var util = _interopRequireWildcard(require("node:util"));
17
+ var _commander = require("commander");
16
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
20
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -23,127 +25,241 @@ const fakeSend = {
23
25
  send: json => console.log(json),
24
26
  sendStatus: data => console.log(data)
25
27
  };
26
- // standardize merlin statements visually
27
- function merlinSays(text) {
28
- return `${_picocolors.default.yellow(_picocolors.default.bgBlack(` 🧙 Merlin: `))} ${_picocolors.default.bgBlack(_picocolors.default.green(` ${text} `))}`;
29
- }
28
+ var hasGit = true;
29
+ exec('git --version', error => {
30
+ if (error) {
31
+ hasGit = false;
32
+ }
33
+ });
34
+ var hasSurge = true;
35
+ exec('surge --version', error => {
36
+ if (error) {
37
+ hasSurge = false;
38
+ }
39
+ });
30
40
  async function main() {
31
- console.clear();
32
- p.intro(`${_picocolors.default.bgBlack(_picocolors.default.underline(_picocolors.default.gray(`Never`)))}`);
33
- await (0, _promises.setTimeout)(300);
34
- p.intro(`${_picocolors.default.bgBlack(_picocolors.default.red(` stop `))}`);
35
- await (0, _promises.setTimeout)(300);
36
- p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` never`))}`);
37
- await (0, _promises.setTimeout)(300);
38
- p.intro(`${_picocolors.default.bgBlack(_picocolors.default.cyan(` stopping `))}`);
39
- await (0, _promises.setTimeout)(500);
40
- let colors = ['blue', 'yellow', 'red', 'magenta'];
41
- for (let i in _art.characters) {
42
- if (i < _art.characters.length - 1) {
43
- console.clear();
44
- p.intro(`${_picocolors.default.bgBlack(_picocolors.default[colors[i]](`Better future loading..`))}`);
45
- p.intro(_picocolors.default.bgBlack(_picocolors.default[colors[i]](_art.characters[i])));
46
- let rockets = '';
47
- for (let step = 0; step < i; step++) {
48
- rockets += "🚀🚀🚀";
49
- }
50
- p.intro(rockets);
51
- await (0, _promises.setTimeout)(Math.random() * 400 + 150);
41
+ _commander.program.option('--y', 'yes to all questions') // skip steps
42
+ .option('--skip', 'skip frills like animations') // skip steps
43
+ .option('--auto', 'yes to all questions, alias of y') // select defaults whenever possible
44
+ .option('--type <char>', 'type of project, haxsite or webcomponent') // haxsite, webcomponent
45
+ .option('--name <char>', 'name of the project') // haxsite / webcomponent name
46
+ .option('--title <char>', 'site: node title') // page title
47
+ .option('--domain <char>', 'site: published domain name') // haxsite / webcomponent name
48
+ .option('--action <char>', 'site: action to take') // action to take
49
+ .option('--org <char>', 'organization for package.json') // organization name
50
+ .option('--author <char>', 'author for site / package.json') // organization name
51
+ .option('--path <char>', 'where to perform operation') // path
52
+ .option('--npm-client <char>', 'npm client to use (must be installed) npm, yarn, pnpm') // npm yarn pnpm etc
53
+ .option('--').helpCommand(true);
54
+ _commander.program.parse();
55
+ var cliOptions = _commander.program.opts();
56
+ // auto and y assume same thing
57
+ if (cliOptions.y || cliOptions.auto) {
58
+ cliOptions.y = true;
59
+ cliOptions.auto = true;
60
+ // assume we are creating a webcomponent if name supplied but no type defined
61
+ if (!cliOptions.type) {
62
+ cliOptions.type = 'webcomponent';
52
63
  }
53
64
  }
54
- console.clear();
55
- p.intro(_picocolors.default.bgBlack(_picocolors.default.green(_art.characters.pop())));
56
- p.intro(`${_picocolors.default.bgGreen(_picocolors.default.black(` The Web : CLI `))}
57
-
58
-
59
- ${merlinSays('Welcome wary web wanderer')}`);
60
- // should be able to grab
65
+ if (!cliOptions.y && !cliOptions.auto && !cliOptions.skip) {
66
+ await (0, _statements.haxIntro)();
67
+ }
68
+ if (!cliOptions.npmClient) {
69
+ cliOptions.npmClient = 'npm';
70
+ }
61
71
  let author = '';
72
+ // should be able to grab if not predefined
62
73
  try {
63
74
  let value = await exec(`git config user.name`);
64
75
  author = value.stdout.trim();
65
76
  } catch (e) {
66
- console.log(e);
77
+ console.log('git user name not configured. Run the following to do this:');
78
+ console.log('git config --global user.name "namehere"');
79
+ console.log('git config --global user.email "email@here');
80
+ }
81
+ if (cliOptions.auto) {
82
+ cliOptions.path = process.cwd();
83
+ cliOptions.org = '';
84
+ cliOptions.author = author;
67
85
  }
68
86
  var port = "3000";
69
87
  // delay so that we clear and then let them visually react to change
70
88
  const siteData = await hax.systemStructureContext();
89
+ let packageData = {};
90
+ let testPackages = [path.join(process.cwd(), 'package.json'), path.join(process.cwd(), '../', 'package.json'), path.join(process.cwd(), '../', '../', 'package.json')];
91
+ // test within reason, for package.json files seeing if anything is available to suggest
92
+ // that we might be in a local package or a monorepo.
93
+ while (testPackages.length > 0) {
94
+ let packLoc = testPackages.shift();
95
+ if (fs.existsSync(packLoc)) {
96
+ try {
97
+ packageData = JSON.parse(fs.readFileSync(`${process.cwd()}/package.json`));
98
+ // assume we are working on a web component / existing if we find this key
99
+ if (packageData.hax && packageData.hax.cli) {
100
+ cliOptions.type = 'webcomponent';
101
+ }
102
+ // leverage these values if they exist downstream
103
+ if (packageData.npmClient) {
104
+ cliOptions.npmClient = packageData.npmClient;
105
+ }
106
+ // see if we're in a monorepo
107
+ if (packageData.useWorkspaces && packageData.workspaces && packageData.workspaces.packages && packageData.workspaces.packages[0]) {
108
+ p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` Monorepo detected : Setting relative defaults `))}`);
109
+ cliOptions.isMonorepo = true;
110
+ cliOptions.auto = true;
111
+ // assumed if monorepo
112
+ cliOptions.type = 'webcomponent';
113
+ cliOptions.path = path.join(process.cwd(), packageData.workspaces.packages[0].replace('/*', ''));
114
+ if (packageData.orgNpm) {
115
+ cliOptions.org = packageData.orgNpm;
116
+ }
117
+ cliOptions.gitRepo = packageData.repository.url;
118
+ cliOptions.author = packageData.author.name ? packageData.author.name : author;
119
+ }
120
+ } catch (err) {
121
+ console.error(err);
122
+ }
123
+ }
124
+ }
71
125
  // delay so that we clear and then let them visually react to change
72
126
  // CLI works within context of the site if one is detected, otherwise we can do other thingss
73
127
  if (siteData) {
74
128
  p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` HAXTheWeb : Site detected `))}`);
75
- p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Title: ${siteData.site.title} `))}`);
129
+ cliOptions.type = "haxsite";
130
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Name: ${siteData.name} `))}`);
131
+ // defaults if nothing set via CLI
76
132
  let operation = {
77
- action: null
133
+ action: null,
134
+ title: "New Page",
135
+ domain: `haxcli-${siteData.name}.surge.sh`
136
+ };
137
+ operation = {
138
+ ...operation,
139
+ ...cliOptions
78
140
  };
79
141
  // infinite loop until quitting the cli
80
142
  while (operation.action !== 'quit') {
81
- operation = await p.group({
82
- action: ({
83
- results
84
- }) => p.select({
85
- message: `Actions you can take`,
86
- options: [{
87
- value: 'stats',
88
- label: "Site stats"
89
- }, {
90
- value: 'localhost',
91
- label: "Open Site (localhost)"
92
- }, {
93
- value: 'node-add',
94
- label: "New Page"
95
- }, {
96
- value: 'sync-git',
97
- label: "Sync code in git"
98
- }, {
99
- value: 'publish',
100
- label: "Publish site to the web"
101
- }, {
102
- value: 'quit',
103
- label: "🚪 Quit"
104
- }]
105
- })
143
+ let actions = [{
144
+ value: 'status',
145
+ label: "Site Status"
106
146
  }, {
107
- onCancel: () => {
108
- p.cancel('🧙 Merlin: Canceling CLI.. HAX ya later 🪄');
109
- communityStatement();
110
- process.exit(0);
111
- }
147
+ value: 'localhost',
148
+ label: "Open Site (localhost)"
149
+ }, {
150
+ value: 'sync-git',
151
+ label: "Sync code in git"
152
+ }, {
153
+ value: 'node-add',
154
+ label: "Add New Page"
155
+ }];
156
+ if (hasSurge) {
157
+ actions.push({
158
+ value: 'publish-surge',
159
+ label: "Publish site using Surge.sh"
160
+ });
161
+ }
162
+ actions.push({
163
+ value: 'quit',
164
+ label: "🚪 Quit"
112
165
  });
166
+ if (!operation.action) {
167
+ operation = await p.group({
168
+ action: ({
169
+ results
170
+ }) => p.select({
171
+ message: `Actions you can take`,
172
+ options: actions
173
+ })
174
+ }, {
175
+ onCancel: () => {
176
+ p.cancel('🧙 Merlin: Canceling CLI.. HAX ya later 🪄');
177
+ (0, _statements.communityStatement)();
178
+ process.exit(0);
179
+ }
180
+ });
181
+ }
113
182
  switch (operation.action) {
114
- case "stats":
115
- p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Title: ${siteData.site.title} `))}`);
116
- p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Description: ${siteData.site.description} `))}`);
117
- p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Pages: ${siteData.site.items.length} `))}`);
183
+ case "status":
184
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Title: ${siteData.manifest.title} `))}`);
185
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Description: ${siteData.manifest.description} `))}`);
186
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Pages: ${siteData.manifest.items.length} `))}`);
118
187
  break;
119
188
  case "localhost":
120
189
  try {
121
- await exec(`cd ${siteData.path} && npx @haxtheweb/haxcms-nodejs`);
122
- } catch (e) {}
190
+ await exec(`cd ${siteData.directory} && npx @haxtheweb/haxcms-nodejs`);
191
+ } catch (e) {
192
+ console.log(e.stderr);
193
+ }
123
194
  break;
124
195
  case "node-add":
125
- // @todo add new page option
196
+ // @todo need to accept arguments
197
+ try {
198
+ haxcmsNodejsCli.cliBridge('createNode', {
199
+ site: siteData,
200
+ node: {
201
+ title: operation.title
202
+ }
203
+ });
204
+ console.log(`"${operation.title}" added to site`);
205
+ } catch (e) {
206
+ console.log(e.stderr);
207
+ }
126
208
  break;
127
209
  case "sync-git":
128
210
  // @todo git sync might need other arguments / be combined with publishing
129
211
  try {
130
- await exec(`cd ${siteData.path} && git pull && git push`);
212
+ await exec(`cd ${siteData.directory} && git pull && git push`);
131
213
  } catch (e) {
132
- console.log(e);
214
+ console.log(e.stderr);
133
215
  }
134
216
  break;
135
- case "publish":
136
- // @todo support other forms of publishing
217
+ case "publish-surge":
137
218
  try {
138
- await exec(`cd ${siteData.path} && npm install --global surge && surge .`);
219
+ // @todo should provide an option for setting the domain
220
+ let execOutput = await exec(`cd ${siteData.directory} && surge . ${operation.domain}`);
221
+ console.log(execOutput.stdout.trim());
139
222
  } catch (e) {
140
- console.log(e);
223
+ console.log(e.stderr);
141
224
  }
142
225
  break;
143
226
  case "quit":
144
227
  // quit
145
228
  break;
146
229
  }
230
+ if (cliOptions.y) {
231
+ process.exit(0);
232
+ }
233
+ operation.action = null;
234
+ }
235
+ } else if (packageData && packageData.hax && packageData.hax.cli && packageData.scripts.start) {
236
+ p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` HAXTheWeb : Webcomponent detected `))}`);
237
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Name: ${packageData.name} `))}`);
238
+ port = "8000";
239
+ p.note(`${(0, _statements.merlinSays)(`I have summoned a sub-process daemon 👹`)}
240
+
241
+ 🚀 Running your ${_picocolors.default.bold('webcomponent')} ${_picocolors.default.bold(packageData.name)}:
242
+ ${_picocolors.default.underline(_picocolors.default.cyan(`http://localhost:${port}`))}
243
+
244
+ 🏠 Launched: ${_picocolors.default.underline(_picocolors.default.bold(_picocolors.default.yellow(_picocolors.default.bgBlack(`${process.cwd()}`))))}
245
+ 💻 Folder: ${_picocolors.default.bold(_picocolors.default.yellow(_picocolors.default.bgBlack(`cd ${process.cwd()}`)))}
246
+ 📂 Open folder: ${_picocolors.default.bold(_picocolors.default.yellow(_picocolors.default.bgBlack(`open ${process.cwd()}`)))}
247
+ 📘 VS Code Project: ${_picocolors.default.bold(_picocolors.default.yellow(_picocolors.default.bgBlack(`code ${process.cwd()}`)))}
248
+ 🚧 Launch later: ${_picocolors.default.bold(_picocolors.default.yellow(_picocolors.default.bgBlack(`${cliOptions.npmClient} start`)))}
249
+
250
+ ⌨️ To exit 🧙 Merlin press: ${_picocolors.default.bold(_picocolors.default.black(_picocolors.default.bgRed(` CTRL + C `)))}
251
+ `);
252
+ try {
253
+ // ensure it's installed first, unless it's a monorepo
254
+ if (!cliOptions.isMonorepo) {
255
+ let s = p.spinner();
256
+ s.start((0, _statements.merlinSays)(`Installation magic (${cliOptions.npmClient} install)`));
257
+ await exec(`${cliOptions.npmClient} install`);
258
+ s.stop((0, _statements.merlinSays)(`Everything is installed. It's go time`));
259
+ }
260
+ await exec(`${cliOptions.npmClient} start`);
261
+ } catch (e) {
262
+ // don't log bc output is odd
147
263
  }
148
264
  } else {
149
265
  let activeProject = null;
@@ -153,35 +269,39 @@ async function main() {
153
269
  while (project.type !== 'quit') {
154
270
  if (activeProject) {
155
271
  p.note(` 🧙🪄 BE GONE ${_picocolors.default.bold(_picocolors.default.black(_picocolors.default.bgGreen(activeProject)))} sub-process daemon! 🪄 + ✨ 👹 = 💀 `);
272
+ cliOptions = {};
273
+ }
274
+ if (['site', 'haxsite', 'webcomponent'].includes(cliOptions.type)) {
275
+ project = {
276
+ type: cliOptions.type
277
+ };
278
+ } else {
279
+ project = await p.group({
280
+ type: ({
281
+ results
282
+ }) => p.select({
283
+ message: !activeProject ? `What should we build?` : `Thirsty for more? What should we create now?`,
284
+ initialValue: 'webcomponent',
285
+ required: true,
286
+ options: [{
287
+ value: 'webcomponent',
288
+ label: '🏗️ Create a Web Component'
289
+ }, {
290
+ value: 'haxsite',
291
+ label: '🏡 Create a HAXcms site (single)'
292
+ }, {
293
+ value: 'quit',
294
+ label: '🚪 Quit'
295
+ }]
296
+ })
297
+ }, {
298
+ onCancel: () => {
299
+ p.cancel('🧙🪄 Merlin: Leaving so soon? HAX ya later');
300
+ (0, _statements.communityStatement)();
301
+ process.exit(0);
302
+ }
303
+ });
156
304
  }
157
- project = await p.group({
158
- type: ({
159
- results
160
- }) => p.select({
161
- message: !activeProject ? `What should we build?` : `Thirsty for more? What should we create now?`,
162
- initialValue: 'haxcms',
163
- required: true,
164
- options: [{
165
- value: 'haxcms',
166
- label: '🏡 Create a HAXcms site (single)'
167
- }, {
168
- value: 'haxcms-multisite',
169
- label: '🏘️ Create a HAXcms multi-site'
170
- }, {
171
- value: 'webcomponent',
172
- label: '🏗️ Create a Web Component'
173
- }, {
174
- value: 'quit',
175
- label: '🚪 Quit'
176
- }]
177
- })
178
- }, {
179
- onCancel: () => {
180
- p.cancel('🧙🪄 Merlin: Leaving so soon? HAX ya later');
181
- communityStatement();
182
- process.exit(0);
183
- }
184
- });
185
305
  activeProject = project.type;
186
306
  // silly but this way we don't have to take options for quitting
187
307
  if (project.type !== 'quit') {
@@ -197,116 +317,168 @@ async function main() {
197
317
  results
198
318
  }) => {
199
319
  let initialPath = `${process.cwd()}`;
200
- return p.text({
201
- message: `What folder will your ${results.type === "webcomponent" ? "project" : "site"} live in?`,
202
- placeholder: initialPath,
203
- validate: value => {
204
- if (!value) {
205
- return "Path is required (tab writes default)";
206
- }
207
- if (!fs.existsSync(value)) {
208
- return `${value} does not exist. Select a valid folder`;
320
+ if (!cliOptions.path && !cliOptions.auto) {
321
+ return p.text({
322
+ message: `What folder will your ${cliOptions.type === "webcomponent" || results.type === "webcomponent" ? "project" : "site"} live in?`,
323
+ placeholder: initialPath,
324
+ required: true,
325
+ validate: value => {
326
+ if (!value) {
327
+ return "Path is required (tab writes default)";
328
+ }
329
+ if (!fs.existsSync(value)) {
330
+ return `${value} does not exist. Select a valid folder`;
331
+ }
209
332
  }
210
- }
211
- });
333
+ });
334
+ }
212
335
  },
213
336
  name: ({
214
337
  results
215
338
  }) => {
216
- let placeholder = "mysite";
217
- let message = "Site name:";
218
- if (results.type === "webcomponent") {
219
- placeholder = "my-element";
220
- message = "Element name:";
221
- } else if (results.type === "haxcms-multisite") {
222
- placeholder = "mysitefactory";
223
- message = "Site factory name:";
224
- }
225
- return p.text({
226
- message: message,
227
- placeholder: placeholder,
228
- validate: value => {
229
- if (!value) {
230
- return "Name is required (tab writes default)";
231
- }
232
- if (/^\d/.test(value)) {
233
- return "Name cannot start with a number";
234
- }
235
- if (value.indexOf(' ') !== -1) {
236
- return "No spaces allowed in project name";
237
- }
238
- if (results.type === "webcomponent" && value.indexOf('-') === -1 && value.indexOf('-') !== 0 && value.indexOf('-') !== value.length - 1) {
239
- return "Name must include at least one `-` and must not start or end name.";
339
+ if (!cliOptions.name) {
340
+ let placeholder = "mysite";
341
+ let message = "Site name:";
342
+ if (cliOptions.type === "webcomponent" || results.type === "webcomponent") {
343
+ placeholder = "my-element";
344
+ message = "Element name:";
345
+ }
346
+ return p.text({
347
+ message: message,
348
+ placeholder: placeholder,
349
+ required: true,
350
+ validate: value => {
351
+ if (!value) {
352
+ return "Name is required (tab writes default)";
353
+ }
354
+ if (/^\d/.test(value)) {
355
+ return "Name cannot start with a number";
356
+ }
357
+ if (value.indexOf(' ') !== -1) {
358
+ return "No spaces allowed in project name";
359
+ }
360
+ if (results.type === "webcomponent" && value.indexOf('-') === -1 && value.indexOf('-') !== 0 && value.indexOf('-') !== value.length - 1) {
361
+ return "Name must include at least one `-` and must not start or end name.";
362
+ }
363
+ // assumes auto was selected in CLI
364
+ let joint = process.cwd();
365
+ if (cliOptions.path) {
366
+ joint = cliOptions.path;
367
+ } else if (results.path) {
368
+ joint = results.path;
369
+ }
370
+ if (fs.existsSync(path.join(joint, value))) {
371
+ return `${path.join(joint, value)} exists, rename this project`;
372
+ }
240
373
  }
241
- if (fs.existsSync(path.join(results.path, value))) {
242
- return `${path.join(results.path, value)} exists, rename this project`;
374
+ });
375
+ }
376
+ },
377
+ org: ({
378
+ results
379
+ }) => {
380
+ if (results.type === "webcomponent" && !cliOptions.org && !cliOptions.auto) {
381
+ // @todo detect mono repo and automatically add this
382
+ let initialOrg = '@yourOrganization';
383
+ return p.text({
384
+ message: 'Organization:',
385
+ placeholder: initialOrg,
386
+ required: false,
387
+ validate: value => {
388
+ if (value && !value.startsWith('@')) {
389
+ return "Organizations are not required, but organizations must start with @ if used";
390
+ }
243
391
  }
244
- }
245
- });
392
+ });
393
+ }
246
394
  },
247
395
  author: ({
248
396
  results
249
397
  }) => {
250
- return p.text({
251
- message: 'Author:',
252
- initialValue: author
253
- });
398
+ if (!cliOptions.author && !cliOptions.auto) {
399
+ return p.text({
400
+ message: 'Author:',
401
+ required: false,
402
+ initialValue: author
403
+ });
404
+ }
254
405
  },
255
406
  extras: ({
256
407
  results
257
408
  }) => {
258
- let options = [];
259
- let initialValues = [];
260
- if (results.type === "webcomponent") {
261
- options = [{
262
- value: 'launch',
263
- label: 'Launch project',
264
- hint: 'recommended, requires install'
265
- }, {
266
- value: 'install',
267
- label: 'Install dependencies via npm',
268
- hint: 'recommended'
269
- }, {
270
- value: 'git',
271
- label: 'Apply version control via git',
272
- hint: 'recommended'
273
- }];
274
- initialValues = ['launch', 'install', 'git'];
275
- } else {
276
- options = [{
277
- value: 'launch',
278
- label: 'Launch project on creation',
279
- hint: 'recommended'
280
- }];
281
- initialValues = ['launch'];
409
+ if (!cliOptions.auto && !cliOptions.skip) {
410
+ let options = [];
411
+ let initialValues = [];
412
+ if (cliOptions.type === "webcomponent" || results.type === "webcomponent") {
413
+ options = [{
414
+ value: 'launch',
415
+ label: 'Launch project',
416
+ hint: 'recommended'
417
+ }, {
418
+ value: 'install',
419
+ label: `Install dependencies via ${cliOptions.npmClient}`,
420
+ hint: 'recommended'
421
+ }, {
422
+ value: 'git',
423
+ label: 'Apply version control via git',
424
+ hint: 'recommended'
425
+ }];
426
+ initialValues = ['launch', 'install', 'git'];
427
+ if (!hasGit || cliOptions.isMonorepo) {
428
+ options.pop();
429
+ initialValues.pop();
430
+ }
431
+ } else {
432
+ options = [{
433
+ value: 'launch',
434
+ label: 'Launch project on creation',
435
+ hint: 'recommended'
436
+ }];
437
+ initialValues = ['launch'];
438
+ }
439
+ return p.multiselect({
440
+ message: 'Additional setup',
441
+ initialValues: initialValues,
442
+ options: options,
443
+ required: false
444
+ });
282
445
  }
283
- return p.multiselect({
284
- message: 'Additional setup',
285
- initialValues: initialValues,
286
- options: options,
287
- required: false
288
- });
289
446
  }
290
447
  }, {
291
448
  onCancel: () => {
292
449
  p.cancel('🧙🪄 Merlin: Canceling CLI.. HAX ya later');
293
- communityStatement();
450
+ (0, _statements.communityStatement)();
294
451
  process.exit(0);
295
452
  }
296
453
  });
454
+ // merge cli options with project options assume this is NOT a monorepo
455
+ // but spread will overwrite if needed
456
+ project = {
457
+ isMonorepo: false,
458
+ ...project,
459
+ ...cliOptions
460
+ };
461
+ // auto select operations to perform if requested
462
+ if (project.auto) {
463
+ let extras = ['launch'];
464
+ if (project.type === "webcomponent") {
465
+ extras = ['launch', 'install', 'git'];
466
+ if (!hasGit || project.isMonorepo) {
467
+ extras.pop();
468
+ }
469
+ }
470
+ project.extras = extras;
471
+ }
297
472
  // values not set by user but used in templating
298
473
  project.className = (0, _utils.dashToCamel)(project.name);
299
474
  project.year = new Date().getFullYear();
300
475
  project.version = await HAXCMS.getHAXCMSVersion();
301
476
  let s = p.spinner();
302
- // we can do this if it's a multisite
303
- var site;
304
477
  // resolve site vs multi-site
305
478
  switch (project.type) {
306
- case 'haxcms':
307
- s.start(merlinSays(`Creating new site: ${project.name}`));
308
- //site = new hax.HAXCMSSite();
309
- //await site.newSite(project.path, '/', project.name);
479
+ case 'site':
480
+ case 'haxsite':
481
+ s.start((0, _statements.merlinSays)(`Creating new site: ${project.name}`));
310
482
  let siteRequest = {
311
483
  "site": {
312
484
  "name": project.name,
@@ -328,23 +500,22 @@ async function main() {
328
500
  await hax.RoutesMap.post.createSite({
329
501
  body: siteRequest
330
502
  }, fakeSend);
331
- s.stop(merlinSays(`${project.name} created!`));
332
- await (0, _promises.setTimeout)(500);
333
- break;
334
- case 'haxcms-multisite':
335
- s.start(merlinSays(`Creating multisite: ${project.name}`));
336
- await fs.mkdirSync(`${project.path}/${project.name}`);
337
- s.stop(merlinSays(`${project.name} is setup to be a multi-site!`));
503
+ s.stop((0, _statements.merlinSays)(`${project.name} created!`));
338
504
  await (0, _promises.setTimeout)(500);
339
505
  break;
340
506
  case 'webcomponent':
341
507
  port = "8000";
342
508
  // option to build github repo link for the user
343
509
  if (project.extras.includes('git')) {
344
- project.gitRepo = await p.text({
345
- message: 'Git Repo location:',
346
- placeholder: `git@github.com:${project.author}/${project.name}.git`
347
- });
510
+ // @todo need to support git@ and https methods
511
+ if (cliOptions.auto) {
512
+ project.gitRepo = `https://github.com/${project.author}/${project.name}.git`;
513
+ } else {
514
+ project.gitRepo = await p.text({
515
+ message: 'Git Repo location:',
516
+ placeholder: `https://github.com/${project.author}/${project.name}.git`
517
+ });
518
+ }
348
519
  // if they supplied one and it has github in it, build a link automatically for ejs index
349
520
  if (project.gitRepo && project.gitRepo.includes('github.com')) {
350
521
  project.githubLink = project.gitRepo.replace('git@github.com:', 'https://github.com/').replace('.git', '');
@@ -354,15 +525,32 @@ async function main() {
354
525
  } else {
355
526
  project.githubLink = null;
356
527
  }
357
- s.start(merlinSays('Copying project files'));
528
+ // if we have an org, add a / at the end so file name is written correctly
529
+ if (project.org) {
530
+ project.org += '/';
531
+ } else {
532
+ project.org = '';
533
+ }
534
+ s.start((0, _statements.merlinSays)('Copying project files'));
358
535
  // leverage this little helper from HAXcms
359
536
  await HAXCMS.recurseCopy(`${process.mainModule.path}/templates/${project.type}/hax/`, `${project.path}/${project.name}`);
360
537
  // rename paths that are of the element name in question
361
- await fs.renameSync(`${project.path}/${project.name}/src/webcomponent.js`, `${project.path}/${project.name}/src/${project.name}.js`);
362
538
  await fs.renameSync(`${project.path}/${project.name}/lib/webcomponent.haxProperties.json`, `${project.path}/${project.name}/lib/${project.name}.haxProperties.json`);
363
- s.stop(merlinSays('Files copied'));
539
+ // loop through and rename all the localization files
540
+ fs.readdir(`${project.path}/${project.name}/locales/`, function (err, files) {
541
+ if (err) {
542
+ console.error("Could not list the directory.", err);
543
+ process.exit(1);
544
+ }
545
+ files.forEach(async function (file, index) {
546
+ await fs.renameSync(`${project.path}/${project.name}/locales/${file}`, `${project.path}/${project.name}/locales/${file.replace('webcomponent', project.name)}`);
547
+ });
548
+ });
549
+ await fs.renameSync(`${project.path}/${project.name}/webcomponent.js`, `${project.path}/${project.name}/${project.name}.js`);
550
+ await fs.renameSync(`${project.path}/${project.name}/test/webcomponent.test.js`, `${project.path}/${project.name}/test/${project.name}.test.js`);
551
+ s.stop((0, _statements.merlinSays)('Files copied'));
364
552
  await (0, _promises.setTimeout)(500);
365
- s.start(merlinSays('Making files awesome'));
553
+ s.start((0, _statements.merlinSays)('Making files awesome'));
366
554
  for (const filePath of (0, _utils.readAllFiles)(`${project.path}/${project.name}`)) {
367
555
  try {
368
556
  // ensure we don't try to pattern rewrite image files
@@ -380,7 +568,7 @@ async function main() {
380
568
  s.stop('Files are now awesome!');
381
569
  break;
382
570
  }
383
- if (project.gitRepo) {
571
+ if (project.gitRepo && !cliOptions.isMonorepo) {
384
572
  try {
385
573
  await exec(`cd ${project.path}/${project.name} && git init && git add -A && git commit -m "first commit" && git branch -M main${project.gitRepo ? ` && git remote add origin ${project.gitRepo}` : ''}`);
386
574
  } catch (e) {}
@@ -388,22 +576,25 @@ async function main() {
388
576
  // options for install, git and other extras
389
577
  // can't launch if we didn't install first so launch implies installation
390
578
  if (project.extras.includes('launch') || project.extras.includes('install')) {
391
- s.start(merlinSays(`Installation magic (npm install)`));
579
+ s.start((0, _statements.merlinSays)(`Installation magic (${cliOptions.npmClient} install)`));
392
580
  try {
393
- await exec(`cd ${project.path}/${project.name} && npm install`);
581
+ // monorepos install from top but then still need to launch from local location
582
+ if (!cliOptions.isMonorepo) {
583
+ await exec(`cd ${project.path}/${project.name} && ${cliOptions.npmClient} install`);
584
+ }
394
585
  } catch (e) {
395
586
  console.log(e);
396
587
  }
397
- s.stop(merlinSays(`Everything is installed. It's go time`));
588
+ s.stop((0, _statements.merlinSays)(`Everything is installed. It's go time`));
398
589
  }
399
590
  // autolaunch if default was selected
400
591
  if (project.extras.includes('launch')) {
401
592
  let optionPath = `${project.path}/${project.name}`;
402
593
  let command = `npx @haxtheweb/haxcms-nodejs`;
403
594
  if (project.type === "webcomponent") {
404
- command = `npm start`;
595
+ command = `${cliOptions.npmClient} start`;
405
596
  }
406
- p.note(`${merlinSays(`I have summoned a sub-process daemon 👹`)}
597
+ p.note(`${(0, _statements.merlinSays)(`I have summoned a sub-process daemon 👹`)}
407
598
 
408
599
  🚀 Running your ${_picocolors.default.bold(project.type)} ${_picocolors.default.bold(project.name)}:
409
600
  ${_picocolors.default.underline(_picocolors.default.cyan(`http://localhost:${port}`))}
@@ -426,14 +617,12 @@ async function main() {
426
617
  } else {
427
618
  let nextSteps = `cd ${project.path}/${project.name} && `;
428
619
  switch (project.type) {
429
- case 'haxcms':
620
+ case 'site':
621
+ case 'haxsite':
430
622
  nextSteps += `npx @haxtheweb/haxcms-nodejs`;
431
623
  break;
432
- case 'haxcms-multisite':
433
- nextSteps = `cd ${project.path} && npx @haxtheweb/haxcms-nodejs\n`;
434
- break;
435
624
  case 'webcomponent':
436
- nextSteps += `${project.extras.includes('install') ? '' : 'npm install &&'}npm start`;
625
+ nextSteps += `${project.extras.includes('install') ? '' : `${cliOptions.npmClient} install && `}${cliOptions.npmClient} start`;
437
626
  break;
438
627
  }
439
628
  p.note(`${project.name} is ready to go. Run the following to start development:`);
@@ -442,23 +631,6 @@ async function main() {
442
631
  }
443
632
  }
444
633
  }
445
- communityStatement();
634
+ (0, _statements.communityStatement)();
446
635
  }
447
- main().catch(console.error);
448
-
449
- // standard community statement so we can leverage on cancel executions
450
- function communityStatement() {
451
- p.outro(`
452
- 🧙 HAX @ Penn State: ${_picocolors.default.underline(_picocolors.default.cyan('https://hax.psu.edu'))}
453
-
454
- 🔮 Ideas to HAX Harder, Better, Faster, Stronger: ${_picocolors.default.underline(_picocolors.default.white('https://github.com/haxtheweb/issues/issues'))}
455
-
456
- 👔 Share on LinkedIn: ${_picocolors.default.underline(_picocolors.default.cyan('https://bit.ly/hax-the-linkedin'))}
457
-
458
- 🧵 Tweet on X: ${_picocolors.default.underline(_picocolors.default.white('https://bit.ly/hax-the-x'))}
459
-
460
- 💬 Join Community: ${_picocolors.default.underline(_picocolors.default.cyan('https://bit.ly/hax-discord'))}
461
-
462
- 💡 ${_picocolors.default.bold(_picocolors.default.white(`Never. Stop. Innovating.`))}
463
- `);
464
- }
636
+ main().catch(console.error);