@haxtheweb/create 0.1.0 → 0.1.3

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.
@@ -178,7 +178,7 @@
178
178
  APPENDIX: How to apply the Apache License to your work.
179
179
 
180
180
  To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
182
  replaced with your own identifying information. (Don't include
183
183
  the brackets!) The text should be enclosed in the appropriate
184
184
  comment syntax for the file format. We also recommend that a
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright [yyyy] [name of copyright owner]
189
+ Copyright 2024 The Pennsylvania State University
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -5,11 +5,32 @@ Rapidly build web components for the Web that work with HAX. HAX The Web's CLI t
5
5
  ## Future state
6
6
  - Create new HAX sites and administer them from the CLI
7
7
  - Create new themes for HAXcms
8
+ - Interface w/ docs / AI agent on website
8
9
 
9
10
  # Usage
10
11
 
11
12
  ```bash
13
+ npx @haxtheweb/create
14
+ #or
12
15
  npm init @haxtheweb
13
16
  ```
14
17
 
15
- Follow the prompts and let's HAX the Web together!
18
+ Follow the prompts and let's HAX the Web together!
19
+
20
+ ## Web component
21
+
22
+ Step through answering basic install questions to build a HAX capable web component that works anywhere! Features:
23
+ - LitElement based
24
+ - DDDSuper class which adds our design system in
25
+ - Common conventions used to demonstrate and work with property binding
26
+ - Minor CSS variable inclusion for initial learning
27
+
28
+ ## HAX Site
29
+
30
+ Build a HAX site that can be published and transported anywhere. Your users might love it on the front end, now you get the simplicity of building on the CLI.
31
+ - Same HAX sites you can create via front end
32
+ - Templated files that work just like any HAX site
33
+ - End points baked in to do CLI commands for common endpoint operations like adding pages, deleting and editing.
34
+ - Ability to import via URL just like the front-end
35
+ - Theme development starting point to be able to build themes locally
36
+ - Primed to publish to gh-pages, vercel and more
package/dist/art.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.characters = void 0;
7
+ const characters = exports.characters = [];
8
+ characters.push(` █
9
+ ██ ██ ███ ██ ███
10
+ ██ ██ ████ █████
11
+ ███████ ██████ ████
12
+ ███████ ██████ ████
13
+ ██ ██ ███████ ██████
14
+ ██ ██ ███ █████ ███ `);
15
+ characters.push(`████████ ██████████████
16
+ █ ██ ███ ███ █ ██
17
+ ██ ██ ███ ███ ██
18
+ ███ ██ ███ ██
19
+ ██ █ ███ ██
20
+ ██ ██ ██ ██ ██
21
+ ██ ██ █ ██ ██ ██
22
+ ███████████████████████ `);
23
+ characters.push(`░░░░░░░░ ░░░░░░░░░░░░░░
24
+ ░█▓░░▓▒░░░▓█▓░░░▓▓░▒▓▒░░
25
+ ░░█▓░░█▒░░▒███░░░▒███▓░░
26
+ ░░▒█████▓░▒▒███▒░░▒▒██░░
27
+ ░░█▓█▓██░░▒█▒▒█▒░░▒██▓░░
28
+ ░░█▓░░█▒░▒█████░░▒█▓▓█▒░
29
+ ░░▓▓░░▓▓░▒▓░░░▓▒▒▓▒░░▓▓░░
30
+ ░░░░░░░░░░░░░░░░░░░░░░░ `);
31
+ characters.push(`████████ ██████████████
32
+ █ ██ ███ ███ █ ██
33
+ ██ ██ ██ ███ ██
34
+ ██ █ ██ ██
35
+ ██ ██ ▒██ ██
36
+ ██ ██ █ ██ ██
37
+ ██ ██ █ ███ █▒ ██
38
+ ███████████████████████ `);
39
+ characters.push(`
40
+ ████████ ██████████████
41
+ █░▒██░▓███░░▒███░▒█▓░███
42
+ ██░▒██░▓███░░░███▒░░░▒██
43
+ ██▓░░░░░▓██▒▒▒░███▓▒░░██
44
+ ██░▒░░░▒██▒░▓▒░███▓░░▒██
45
+ ██░▒██░▓█▓░░░░░██▒░▒░░██
46
+ ██▒▒██▒▒█▓▒███░▓▓▒▓██▒▒██
47
+ ███████████████████████ `);
package/dist/create.js CHANGED
@@ -1,174 +1,427 @@
1
1
  #!/usr/bin/env node
2
+ // forces middleware into CLI mode so we don't automatically perform certain operations like pathing context
2
3
  "use strict";
3
4
 
4
5
  var fs = _interopRequireWildcard(require("node:fs"));
5
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");
6
10
  var _promises = require("node:timers/promises");
7
11
  var ejs = _interopRequireWildcard(require("ejs"));
8
12
  var p = _interopRequireWildcard(require("@clack/prompts"));
9
- var sh = _interopRequireWildcard(require("sync-exec"));
10
13
  var _picocolors = _interopRequireDefault(require("picocolors"));
14
+ var child_process = _interopRequireWildcard(require("child_process"));
15
+ var util = _interopRequireWildcard(require("node:util"));
11
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
17
  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); }
13
18
  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; }
14
- const exec = sh.default;
19
+ process.env.haxcms_middleware = "node-cli";
20
+ const HAXCMS = hax.HAXCMS;
21
+ const exec = util.promisify(child_process.exec);
22
+ const fakeSend = {
23
+ send: json => console.log(json),
24
+ sendStatus: data => console.log(data)
25
+ };
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
+ }
15
30
  async function main() {
16
31
  console.clear();
17
- // should be able to grab author off the git config in most instances
18
- let value = await exec(`git config user.name`);
19
- let author = value.stdout.trim();
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 `))}`);
20
39
  await (0, _promises.setTimeout)(500);
21
- p.intro(`${_picocolors.default.bgCyan(_picocolors.default.black(` HAX The CLI `))}`);
22
- const project = await p.group({
23
- type: ({
24
- results
25
- }) => p.select({
26
- message: `What type of project are you building`,
27
- initialValue: 'webcomponent',
28
- maxItems: 3,
29
- options: [{
30
- value: 'webcomponent',
31
- label: 'Web component'
32
- }, {
33
- value: 'haxcms',
34
- label: "HAX Site"
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);
52
+ }
53
+ }
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
61
+ let author = '';
62
+ try {
63
+ let value = await exec(`git config user.name`);
64
+ author = value.stdout.trim();
65
+ } catch (e) {
66
+ console.log(e);
67
+ }
68
+ // delay so that we clear and then let them visually react to change
69
+ const siteData = await hax.systemStructureContext();
70
+ // delay so that we clear and then let them visually react to change
71
+ // CLI works within context of the site if one is detected, otherwise we can do other thingss
72
+ if (siteData) {
73
+ p.intro(`${_picocolors.default.bgBlack(_picocolors.default.white(` HAXTheWeb : Site detected `))}`);
74
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Title: ${siteData.site.title} `))}`);
75
+ let operation = {
76
+ action: null
77
+ };
78
+ // infinite loop until quitting the cli
79
+ while (operation.action !== 'quit') {
80
+ operation = await p.group({
81
+ action: ({
82
+ results
83
+ }) => p.select({
84
+ message: `Actions you can take`,
85
+ options: [{
86
+ value: 'stats',
87
+ label: "Site stats"
88
+ }, {
89
+ value: 'localhost',
90
+ label: "Open Site (localhost)"
91
+ }, {
92
+ value: 'node-add',
93
+ label: "New Page"
94
+ }, {
95
+ value: 'sync-git',
96
+ label: "Sync code in git"
97
+ }, {
98
+ value: 'publish',
99
+ label: "Publish site to the web"
100
+ }, {
101
+ value: 'quit',
102
+ label: "🚪 Quit"
103
+ }]
104
+ })
35
105
  }, {
36
- value: 'theme',
37
- label: "HAX Theme"
38
- }]
39
- }),
40
- typeOption: ({
41
- results
42
- }) => {
43
- switch (results.type) {
44
- case "webcomponent":
45
- return p.select({
46
- message: `What kind of web component do you want to create?`,
47
- initialValue: 'hax',
48
- maxItems: 1,
49
- options: [{
50
- value: 'hax',
51
- label: "HAX recommended starter"
52
- }]
53
- });
106
+ onCancel: () => {
107
+ p.cancel('🧙 Merlin: Canceling CLI.. HAX ya later 🪄');
108
+ process.exit(0);
109
+ }
110
+ });
111
+ switch (operation.action) {
112
+ case "stats":
113
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Title: ${siteData.site.title} `))}`);
114
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Description: ${siteData.site.description} `))}`);
115
+ p.intro(`${_picocolors.default.bgBlue(_picocolors.default.white(` Pages: ${siteData.site.items.length} `))}`);
54
116
  break;
55
- case "haxcms":
56
- return p.select({
57
- message: `What kind of site is it`,
58
- initialValue: 'course',
59
- maxItems: 2,
60
- options: [{
61
- value: 'course',
62
- label: "Course"
63
- }]
64
- });
117
+ case "localhost":
118
+ try {
119
+ await exec(`cd ${siteData.path} && npx @haxtheweb/haxcms-nodejs`);
120
+ } catch (e) {}
65
121
  break;
66
- case "theme":
67
- return p.select({
68
- message: `Theme base`,
69
- initialValue: 'course',
70
- maxItems: 2,
71
- options: [{
72
- value: 'default',
73
- label: "Default"
74
- }]
75
- });
122
+ case "node-add":
123
+ // @todo add new page option
76
124
  break;
77
- }
78
- },
79
- name: ({
80
- results
81
- }) => {
82
- return p.text({
83
- message: 'Element name:',
84
- initialValue: "my-element",
85
- validate: value => {
86
- if (value.indexOf(' ') !== -1) {
87
- return "No spaces allowed in project name";
125
+ case "sync-git":
126
+ // @todo git sync might need other arguments / be combined with publishing
127
+ try {
128
+ await exec(`cd ${siteData.path} && git pull && git push`);
129
+ } catch (e) {
130
+ console.log(e);
88
131
  }
89
- if (value.indexOf('-') === -1) {
90
- return "Name must include at least one `-`";
132
+ break;
133
+ case "publish":
134
+ // @todo support other forms of publishing
135
+ try {
136
+ await exec(`cd ${siteData.path} && npm install --global surge && surge .`);
137
+ } catch (e) {
138
+ console.log(e);
91
139
  }
140
+ break;
141
+ case "quit":
142
+ p.outro(`Have a great day! Ideas to HAX faster? ${_picocolors.default.underline(_picocolors.default.cyan('https://github.com/haxtheweb/issues'))}`);
143
+ break;
144
+ }
145
+ }
146
+ } else {
147
+ let activeProject = null;
148
+ let project = {
149
+ type: null
150
+ };
151
+ while (project.type !== 'quit') {
152
+ if (activeProject) {
153
+ p.note(` 🧙🪄 BE GONE ${activeProject} sub-process daemon! 🪄 + ✨ 👹 = 💀 `);
154
+ }
155
+ project = await p.group({
156
+ type: ({
157
+ results
158
+ }) => p.select({
159
+ message: !activeProject ? `What should we build?` : `Thirsty for more? What should we create now?`,
160
+ initialValue: 'haxcms',
161
+ required: true,
162
+ options: [{
163
+ value: 'haxcms',
164
+ label: '🏡 Create a HAXcms site (single)'
165
+ }, {
166
+ value: 'haxcms-multisite',
167
+ label: '🏘️ Create a HAXcms multi-site'
168
+ }, {
169
+ value: 'webcomponent',
170
+ label: '🏗️ Create a Web Component'
171
+ }, {
172
+ value: 'quit',
173
+ label: '🚪 Quit'
174
+ }]
175
+ })
176
+ }, {
177
+ onCancel: () => {
178
+ p.cancel('🧙🪄 Merlin: Leaving so soon? HAX ya later');
179
+ process.exit(0);
92
180
  }
93
181
  });
94
- },
95
- path: ({
96
- results
97
- }) => {
98
- let initialPath = `${process.cwd()}/${results.name.toLowerCase()}`;
99
- return p.text({
100
- message: 'Where should we create your project?',
101
- initialValue: initialPath
102
- });
103
- },
104
- author: ({
105
- results
106
- }) => {
107
- return p.text({
108
- message: 'Author:',
109
- initialValue: author
110
- });
111
- }
112
- }, {
113
- onCancel: () => {
114
- p.cancel('Operation cancelled.');
115
- process.exit(0);
116
- }
117
- });
118
- if (project.path) {
119
- project.className = dashToCamel(project.name);
120
- let s = p.spinner();
121
- s.start('Copying files');
122
- await (0, _promises.setTimeout)(250);
123
- await exec(`cp -R ${process.mainModule.path}/templates/${project.type}/${project.typeOption}/ ${project.path}`);
124
- // rename paths that are of the element name in question
125
- await exec(`mv ${project.path}/src/webcomponent.js ${project.path}/src/${project.name}.js`);
126
- await exec(`mv ${project.path}/lib/webcomponent.haxProperties.json ${project.path}/lib/${project.name}.haxProperties.json`);
127
- s.stop('Files copied');
128
- await (0, _promises.setTimeout)(250);
129
- s.start('Making files awesome');
130
- try {
131
- for (const filePath of readAllFiles(project.path)) {
132
- const ejsString = ejs.fileLoader(filePath, 'utf8');
133
- let content = ejs.render(ejsString, project);
134
- fs.writeFileSync(filePath, content);
182
+ activeProject = project.type;
183
+ // silly but this way we don't have to take options for quitting
184
+ if (project.type !== 'quit') {
185
+ project = await p.group({
186
+ type: ({
187
+ results
188
+ }) => {
189
+ return new Promise((resolve, reject) => {
190
+ resolve(activeProject);
191
+ });
192
+ },
193
+ path: ({
194
+ results
195
+ }) => {
196
+ let initialPath = `${process.cwd()}`;
197
+ return p.text({
198
+ message: `What folder will your ${results.type === "webcomponent" ? "project" : "site"} live in?`,
199
+ placeholder: initialPath,
200
+ validate: value => {
201
+ if (!value) {
202
+ return "Path is required (tab writes default)";
203
+ }
204
+ if (!fs.existsSync(value)) {
205
+ return `${value} does not exist. Select a valid folder`;
206
+ }
207
+ }
208
+ });
209
+ },
210
+ name: ({
211
+ results
212
+ }) => {
213
+ let placeholder = "mysite";
214
+ let message = "Site name:";
215
+ if (results.type === "webcomponent") {
216
+ placeholder = "my-element";
217
+ message = "Element name:";
218
+ } else if (results.type === "haxcms-multisite") {
219
+ placeholder = "mysitefactory";
220
+ message = "Site factory name:";
221
+ }
222
+ return p.text({
223
+ message: message,
224
+ placeholder: placeholder,
225
+ validate: value => {
226
+ if (!value) {
227
+ return "Name is required (tab writes default)";
228
+ }
229
+ if (value.indexOf(' ') !== -1) {
230
+ return "No spaces allowed in project name";
231
+ }
232
+ if (results.type === "webcomponent" && value.indexOf('-') === -1 && value.indexOf('-') !== 0 && value.indexOf('-') !== value.length - 1) {
233
+ return "Name must include at least one `-` and must not start or end name.";
234
+ }
235
+ if (fs.existsSync(path.join(results.path, value))) {
236
+ return `${path.join(results.path, value)} exists, rename this project`;
237
+ }
238
+ }
239
+ });
240
+ },
241
+ author: ({
242
+ results
243
+ }) => {
244
+ return p.text({
245
+ message: 'Author:',
246
+ initialValue: author
247
+ });
248
+ },
249
+ extras: ({
250
+ results
251
+ }) => {
252
+ let options = [];
253
+ let initialValues = [];
254
+ if (results.type === "webcomponent") {
255
+ options = [{
256
+ value: 'install',
257
+ label: 'Install dependencies (via npm)',
258
+ hint: 'recommended'
259
+ }, {
260
+ value: 'git',
261
+ label: 'Put in version control (git)',
262
+ hint: 'recommended'
263
+ }, {
264
+ value: 'launch',
265
+ label: 'Launch project on creation',
266
+ hint: 'recommended (requires install)'
267
+ }];
268
+ initialValues = ['install', 'git', 'launch'];
269
+ } else {
270
+ options = [{
271
+ value: 'launch',
272
+ label: 'Launch project on creation',
273
+ hint: 'recommended'
274
+ }];
275
+ initialValues = ['launch'];
276
+ }
277
+ return p.multiselect({
278
+ message: 'Additional setup options',
279
+ initialValues: initialValues,
280
+ options: options,
281
+ required: false
282
+ });
283
+ }
284
+ }, {
285
+ onCancel: () => {
286
+ p.cancel('🧙🪄 Merlin: Canceling CLI.. HAX ya later');
287
+ process.exit(0);
288
+ }
289
+ });
290
+ // values not set but important for templating
291
+ project.className = (0, _utils.dashToCamel)(project.name);
292
+ project.version = await HAXCMS.getHAXCMSVersion();
293
+ let s = p.spinner();
294
+ // we can do this if it's a multisite
295
+ var site;
296
+ // resolve site vs multi-site
297
+ switch (project.type) {
298
+ case 'haxcms':
299
+ s.start(merlinSays(`Creating new site: ${project.name}`));
300
+ //site = new hax.HAXCMSSite();
301
+ //await site.newSite(project.path, '/', project.name);
302
+ let siteRequest = {
303
+ "site": {
304
+ "name": project.name,
305
+ "description": "own course",
306
+ "theme": "clean-one"
307
+ },
308
+ "build": {
309
+ "type": "own",
310
+ "structure": "course",
311
+ "items": null,
312
+ "files": null
313
+ },
314
+ "theme": {
315
+ "color": "green",
316
+ "icon": "av:library-add"
317
+ }
318
+ };
319
+ HAXCMS.cliWritePath = `${project.path}`;
320
+ await hax.RoutesMap.post.createSite({
321
+ body: siteRequest
322
+ }, fakeSend);
323
+ s.stop(merlinSays(`${project.name} created!`));
324
+ await (0, _promises.setTimeout)(500);
325
+ break;
326
+ case 'haxcms-multisite':
327
+ s.start(merlinSays(`Creating multisite: ${project.name}`));
328
+ await fs.mkdirSync(`${project.path}/${project.name}`);
329
+ s.stop(merlinSays(`${project.name} is setup to be a multi-site!`));
330
+ await (0, _promises.setTimeout)(500);
331
+ break;
332
+ case 'webcomponent':
333
+ s.start(merlinSays('Copying project files'));
334
+ // leverage this little helper from HAXcms
335
+ await HAXCMS.recurseCopy(`${process.mainModule.path}/templates/${project.type}/hax/`, `${project.path}/${project.name}`);
336
+ // rename paths that are of the element name in question
337
+ await fs.renameSync(`${project.path}/${project.name}/src/webcomponent.js`, `${project.path}/${project.name}/src/${project.name}.js`);
338
+ await fs.renameSync(`${project.path}/${project.name}/lib/webcomponent.haxProperties.json`, `${project.path}/${project.name}/lib/${project.name}.haxProperties.json`);
339
+ s.stop(merlinSays('Files copied'));
340
+ await (0, _promises.setTimeout)(500);
341
+ s.start(merlinSays('Making files awesome'));
342
+ for (const filePath of (0, _utils.readAllFiles)(`${project.path}/${project.name}`)) {
343
+ try {
344
+ // ensure we don't try to pattern rewrite image files
345
+ if (!filePath.endsWith('.jpg') && !filePath.endsWith('.png')) {
346
+ const ejsString = ejs.fileLoader(filePath, 'utf8');
347
+ let content = ejs.render(ejsString, project);
348
+ // file written successfully
349
+ fs.writeFileSync(filePath, content);
350
+ }
351
+ } catch (err) {
352
+ console.error(filePath);
353
+ console.error(err);
354
+ }
355
+ }
356
+ s.stop('Files are now awesome!');
357
+ break;
358
+ }
359
+ if (project.extras.includes('git')) {
360
+ project.gitRepo = await p.text({
361
+ message: 'Git Repo location:',
362
+ placeholder: `git@github.com:${project.author}/${project.name}.git`
363
+ });
364
+ try {
365
+ 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}` : ''}`);
366
+ } catch (e) {}
367
+ }
368
+ // options for install, git and other extras
369
+ if (project.extras.includes('install')) {
370
+ s.start(merlinSays(`Let's install everything using magic (npm)`));
371
+ try {
372
+ await exec(`cd ${project.path}/${project.name} && npm install`);
373
+ } catch (e) {
374
+ console.log(e);
375
+ }
376
+ s.stop(merlinSays(`Everything is installed. It's go time`));
377
+ }
378
+ // autolaunch if default was selected
379
+ if (project.extras.includes('launch')) {
380
+ p.note(`${merlinSays(`I have summoned a sub-process daemon 👹`)}
381
+ Running ${project.type}
382
+ Launched from: ${project.path}/${project.name}
383
+
384
+ To resume 🧙 Merlin press ⌨️: ${_picocolors.default.black(_picocolors.default.bgRed(`CTRL + C`))}
385
+ `);
386
+ await (0, _promises.setTimeout)(2000);
387
+ let optionPath = `${project.path}/${project.name}`;
388
+ if (project.type === "webcomponent") {
389
+ try {
390
+ await exec(`cd ${optionPath} && npm start`);
391
+ } catch (e) {}
392
+ } else {
393
+ try {
394
+ await exec(`cd ${optionPath} && npx @haxtheweb/haxcms-nodejs`);
395
+ } catch (e) {}
396
+ }
397
+ } else {
398
+ let nextSteps = `cd ${project.path}/${project.name} && `;
399
+ switch (project.type) {
400
+ case 'haxcms':
401
+ nextSteps += `npx @haxtheweb/haxcms-nodejs`;
402
+ break;
403
+ case 'haxcms-multisite':
404
+ nextSteps = `cd ${project.path} && npx @haxtheweb/haxcms-nodejs\n`;
405
+ break;
406
+ case 'webcomponent':
407
+ nextSteps += `${project.extras.includes('install') ? '' : 'npm install &&'}npm start`;
408
+ break;
409
+ }
410
+ p.note(`${project.name} is ready to go. Run the following to start development:`);
411
+ p.outro(nextSteps);
412
+ }
135
413
  }
136
- // file written successfully
137
- } catch (err) {
138
- console.error(err);
139
414
  }
140
- s.stop('Files are now awesome!');
141
- await (0, _promises.setTimeout)(250);
142
- s.start(`Let's install everything using the magic of yarn`);
143
- await (0, _promises.setTimeout)(250);
144
- await exec(`cd ${project.path} && yarn install`);
145
- await (0, _promises.setTimeout)(250);
146
- s.stop(`Everything is installed. It's go time`);
147
- }
148
- let nextSteps = `cd ${project.path} \nyarn start`;
149
- p.note(nextSteps, `${project.name} is ready to go. To start development:`);
150
- p.outro(`Welcome to the revolution. Ideas to HAX faster? ${_picocolors.default.underline(_picocolors.default.cyan('https://github.com/haxtheweb/issues'))}`);
151
- }
152
- main().catch(console.error);
415
+ p.outro(`
416
+ 🔮 Ideas to HAX better, faster, stronger: ${_picocolors.default.underline(_picocolors.default.cyan('https://github.com/haxtheweb/issues'))}
153
417
 
154
- /**
155
- * Helper to convert dash to camel; important when reading attributes.
156
- */
157
- function dashToCamel(str) {
158
- return str.replace(/-([a-z])/g, function (g) {
159
- return g[1].toUpperCase();
160
- });
161
- }
162
- // read in all files recursively for rewriting
163
- function* readAllFiles(dir) {
164
- const files = fs.readdirSync(dir, {
165
- withFileTypes: true
166
- });
167
- for (const file of files) {
168
- if (file.isDirectory()) {
169
- yield* readAllFiles(path.join(dir, file.name));
170
- } else {
171
- yield path.join(dir, file.name);
172
- }
418
+ 👔 Share on LinkedIn: ${_picocolors.default.underline(_picocolors.default.cyan('https://bit.ly/hax-linkedin'))}
419
+
420
+ 🧵 Share on X: ${_picocolors.default.underline(_picocolors.default.cyan('https://bit.ly/hax-x'))}
421
+
422
+ 💬 Join our Community: ${_picocolors.default.underline(_picocolors.default.cyan('https://bit.ly/hax-discord'))}
423
+
424
+ `);
173
425
  }
174
- }
426
+ }
427
+ main().catch(console.error);
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "lit": "^3.1.3",
14
- "@haxtheweb/d-d-d": "^9.0.0-alpha.0"
14
+ "@haxtheweb/d-d-d": "<%= version %>"
15
15
  },
16
16
  "devDependencies": {
17
17
  "@babel/preset-env": "^7.16.4",
@@ -48,4 +48,4 @@ export class <%= className %> extends DDDSuper(LitElement) {
48
48
  }
49
49
  }
50
50
 
51
- globalThis.customElements.define(<%= className %>.tag, <%= className %>);
51
+ globalThis.customElements.define(<%= className %>.tag, <%= className %>);
package/dist/utils.js ADDED
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SITE_FILE_NAME = void 0;
7
+ exports.dashToCamel = dashToCamel;
8
+ exports.generateUUID = generateUUID;
9
+ exports.readAllFiles = readAllFiles;
10
+ var fs = _interopRequireWildcard(require("node:fs"));
11
+ var path = _interopRequireWildcard(require("node:path"));
12
+ 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); }
13
+ 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; }
14
+ const SITE_FILE_NAME = exports.SITE_FILE_NAME = "site.json";
15
+
16
+ /**
17
+ * Helper to convert dash to camel; important when reading attributes.
18
+ */
19
+ function dashToCamel(str) {
20
+ return str.replace(/-([a-z])/g, function (g) {
21
+ return g[1].toUpperCase();
22
+ });
23
+ }
24
+ // generate unique-enough id
25
+ function generateUUID() {
26
+ return "ss-s-s-s-sss".replace(/s/g, _uuidPart);
27
+ }
28
+ function _uuidPart() {
29
+ return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
30
+ }
31
+
32
+ // read in all files recursively for rewriting
33
+ function* readAllFiles(dir) {
34
+ const files = fs.readdirSync(dir, {
35
+ withFileTypes: true
36
+ });
37
+ for (const file of files) {
38
+ if (file.isDirectory()) {
39
+ yield* readAllFiles(path.join(dir, file.name));
40
+ } else {
41
+ yield path.join(dir, file.name);
42
+ }
43
+ }
44
+ }
package/package.json CHANGED
@@ -1,60 +1,62 @@
1
1
  {
2
- "name": "@haxtheweb/create",
3
- "version": "0.1.0",
4
- "publishConfig": {
5
- "access": "public"
6
- },
7
- "description": "Rapidly build web components for the Web that work with HAX",
8
- "author": "HAXTheWeb core team",
9
- "license": "Apache-2.0",
10
- "engines": {
11
- "node": ">=18.20.3"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "https://github.com/haxtheweb/create.git"
16
- },
17
- "bugs": {
18
- "url": "https://github.com/haxtheweb/issues/issues"
19
- },
20
- "homepage": "https://hax.psu.edu/",
21
- "scripts": {
22
- "build": "rm -rf dist && babel src --out-dir dist --copy-files --include-dotfiles",
23
- "start": "npm run build && node ./dist/create.js"
24
- },
25
- "bin": {
26
- "create-haxtheweb": "./dist/create.js"
27
- },
28
- "files": [
29
- "dist"
30
- ],
31
- "keywords": [
32
- "haxtheweb",
33
- "haxcms",
34
- "haxsite",
35
- "htw",
36
- "webcomponents",
37
- "lit",
38
- "generator",
39
- "starter-app"
40
- ],
41
- "dependencies": {
42
- "@clack/core": "0.3.4",
43
- "@clack/prompts": "0.7.0",
44
- "picocolors": "1.0.1",
45
- "sync-exec": "0.6.2",
46
- "ejs": "3.1.10"
47
- },
48
- "devDependencies": {
49
- "@babel/cli": "^7.24.6",
50
- "@babel/core": "^7.24.6",
51
- "@babel/register": "^7.24.6",
52
- "@custom-elements-manifest/analyzer": "^0.10.2",
53
- "@rollup/plugin-babel": "^6.0.4",
54
- "@rollup/plugin-node-resolve": "^15.2.3",
55
- "@web/rollup-plugin-html": "^2.3.0",
56
- "@web/rollup-plugin-import-meta-assets": "^2.2.1",
57
- "babel-plugin-transform-dynamic-import": "^2.1.0",
58
- "@babel/preset-env": "7.24.6"
59
- }
60
- }
2
+ "name": "@haxtheweb/create",
3
+ "version": "0.1.3",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "CLI for all things HAX the web",
8
+ "author": "HAXTheWeb core team",
9
+ "license": "Apache-2.0",
10
+ "engines": {
11
+ "node": ">=18.20.3"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/haxtheweb/create.git"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/haxtheweb/issues/issues"
19
+ },
20
+ "homepage": "https://hax.psu.edu/",
21
+ "scripts": {
22
+ "build": "rm -rf dist && babel src --out-dir dist --copy-files --include-dotfiles && chmod 774 dist/create.js",
23
+ "start": "npm run build && node ./dist/create.js && chmod 774 dist/create.js",
24
+ "release": "npm run build && commit-and-tag-version && git push --follow-tags origin main && npm publish"
25
+ },
26
+ "bin": {
27
+ "create-haxtheweb": "./dist/create.js"
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "keywords": [
33
+ "haxtheweb",
34
+ "haxcms",
35
+ "haxsite",
36
+ "htw",
37
+ "webcomponents",
38
+ "lit",
39
+ "generator",
40
+ "starter-app"
41
+ ],
42
+ "dependencies": {
43
+ "@clack/core": "0.3.4",
44
+ "@clack/prompts": "0.7.0",
45
+ "picocolors": "1.0.1",
46
+ "ejs": "3.1.10",
47
+ "@haxtheweb/haxcms-nodejs": "0.0.13"
48
+ },
49
+ "devDependencies": {
50
+ "@babel/cli": "^7.24.6",
51
+ "@babel/core": "^7.24.6",
52
+ "@babel/register": "^7.24.6",
53
+ "@custom-elements-manifest/analyzer": "^0.10.2",
54
+ "@rollup/plugin-babel": "^6.0.4",
55
+ "@rollup/plugin-node-resolve": "^15.2.3",
56
+ "@web/rollup-plugin-html": "^2.3.0",
57
+ "@web/rollup-plugin-import-meta-assets": "^2.2.1",
58
+ "babel-plugin-transform-dynamic-import": "^2.1.0",
59
+ "@babel/preset-env": "7.24.6",
60
+ "commit-and-tag-version": "12.4.1"
61
+ }
62
+ }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "<%= name %>",
3
- "dependencies": {
4
- "@haxtheweb/d-d-d": "9.0.0-alpha.0"
5
- }
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "<%= name %>",
3
- "dependencies": {
4
- "@haxtheweb/d-d-d": "9.0.0-alpha.0"
5
- }
6
- }