@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.
- package/{LICENSE → LICENSE.md} +2 -2
- package/README.md +22 -1
- package/dist/art.js +47 -0
- package/dist/create.js +400 -147
- package/dist/templates/webcomponent/hax/package.json +1 -1
- package/dist/templates/webcomponent/hax/src/webcomponent.js +1 -1
- package/dist/utils.js +44 -0
- package/package.json +61 -59
- package/dist/templates/haxcms/course/package.json +0 -6
- package/dist/templates/theme/default/package.json +0 -6
package/{LICENSE → LICENSE.md}
RENAMED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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 "
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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 "
|
|
67
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
141
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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);
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
+
}
|