noxt-cli 0.1.10 → 0.1.12
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/README.md +12 -28
- package/package.json +1 -1
- package/starter/package.json +1 -1
- package/starter/public/css/style.css +101 -0
- package/starter/views/layouts/Layout.jsx +4 -4
- package/starter/views/pages/PageIndex.jsx +4 -4
- package/starter/views/pages/PageTask.jsx +16 -6
- package/starter/views/pages/PageTasks.jsx +5 -5
- package/starter/views/templates/AlertButton.jsx +6 -3
- package/starter/views/templates/Json.jsx +18 -0
- package/starter/views/templates/Sidebar.jsx +11 -7
- package/starter/public/css/main.css +0 -31
package/README.md
CHANGED
|
@@ -2,41 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
A command-line interface for [Noxt](https://npmjs.com/package/noxt-server).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
npx noxt-cli
|
|
9
|
-
npx noxt-cli <recipe>
|
|
8
|
+
npx noxt-cli create my-app
|
|
10
9
|
```
|
|
11
10
|
|
|
12
|
-
##
|
|
13
|
-
If you just run `npx noxt-cli`, it will try to find a `noxt.config.yaml` file in your current directory. If it finds one, it will use it. Otherwise, it will use the default config and try to guess some defaults based on common project structure.
|
|
14
|
-
|
|
15
|
-
It will assume the following:
|
|
16
|
-
* `views = "./views"` directory for JSX files, if it exists
|
|
17
|
-
* `static = "./public"` directory for static files, if it exists
|
|
18
|
-
* `port = 3000` port number
|
|
19
|
-
* `hostname = "localhost"` hostname
|
|
20
|
-
* `recipe = "app/main"` if `./units/main.js` exists, it will be used as the recipe
|
|
21
|
-
* `recipe = "noxt-dev"` fallback recipe
|
|
22
|
-
|
|
23
|
-
## Configuration
|
|
24
|
-
|
|
25
|
-
You can override these defaults by creating a `noxt.config.yaml` file in your current directory. It should look like this:
|
|
11
|
+
## Usage
|
|
26
12
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
port: 3000
|
|
31
|
-
hostname: "localhost"
|
|
32
|
-
recipe: "app/main"
|
|
13
|
+
```sh
|
|
14
|
+
cd my-app
|
|
15
|
+
npm run start
|
|
33
16
|
```
|
|
34
17
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Noxt uses [MLM](https://npmjs.com/package/mlm-core) to define recipes and other units that make up the noxt stack. You can extend the [noxt](https://npmjs.com/package/noxt-server) stack by creating your own units in your `./units/` directory.
|
|
18
|
+
or, if you want to run the app with live reload:
|
|
38
19
|
|
|
39
|
-
|
|
20
|
+
```sh
|
|
21
|
+
npm run dev
|
|
22
|
+
```
|
|
40
23
|
|
|
41
24
|
## License
|
|
42
|
-
|
|
25
|
+
|
|
26
|
+
[GPL-3.0-or-later](https://choosealicense.com/licenses/gpl-3.0/)
|
package/package.json
CHANGED
package/starter/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "noxt-cli start app/main",
|
|
8
|
-
"dev": "nodemon -e js,jsx,css,yaml,json,html
|
|
8
|
+
"dev": "nodemon -e js,jsx,css,yaml,json,html --exec noxt-cli start app/main",
|
|
9
9
|
"prod": "NODE_ENV=production noxt-cli start app/main"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
* {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
body {
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 0;
|
|
8
|
+
font-family: sans-serif;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#logo {
|
|
12
|
+
width:100%;
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
article {
|
|
17
|
+
max-width: 1000px;
|
|
18
|
+
margin: 0 auto;
|
|
19
|
+
padding: 0 20px;
|
|
20
|
+
min-height: 100vh;
|
|
21
|
+
display: grid;
|
|
22
|
+
grid-template-columns: max(25%, 200px) 1fr;
|
|
23
|
+
grid-template-rows: max-content 1fr;
|
|
24
|
+
grid-template-areas: "aside header " "aside main ";
|
|
25
|
+
|
|
26
|
+
main {
|
|
27
|
+
grid-area: main;
|
|
28
|
+
padding: 20px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
header {
|
|
32
|
+
grid-area: header;
|
|
33
|
+
padding: 10px 20px;
|
|
34
|
+
border-bottom: solid 1px #ddd;
|
|
35
|
+
color: #004;
|
|
36
|
+
position: sticky;
|
|
37
|
+
top: 0;
|
|
38
|
+
background:#fff;
|
|
39
|
+
|
|
40
|
+
h1 {
|
|
41
|
+
margin: 0;
|
|
42
|
+
padding: 0;
|
|
43
|
+
font-size: 3rem;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
aside {
|
|
48
|
+
grid-area: aside;
|
|
49
|
+
background: #eee;
|
|
50
|
+
|
|
51
|
+
nav {
|
|
52
|
+
position: sticky;
|
|
53
|
+
top: 0;
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
nav ul {
|
|
58
|
+
padding: 0 10px;
|
|
59
|
+
margin: 0;
|
|
60
|
+
list-style: none;
|
|
61
|
+
|
|
62
|
+
li a {
|
|
63
|
+
border: none;
|
|
64
|
+
border-bottom: solid 1px #ddd;
|
|
65
|
+
text-align: left;
|
|
66
|
+
display: block;
|
|
67
|
+
padding: 12px 10px;
|
|
68
|
+
width: 100%;
|
|
69
|
+
text-decoration: none;
|
|
70
|
+
color: #004;
|
|
71
|
+
|
|
72
|
+
&:hover {
|
|
73
|
+
background-color: #eee;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
li button {
|
|
78
|
+
padding: 12px 10px;
|
|
79
|
+
width: 100%;
|
|
80
|
+
border: none;
|
|
81
|
+
background: #004;
|
|
82
|
+
color: #fff;
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
table {
|
|
92
|
+
border-collapse: collapse;
|
|
93
|
+
width: 100%;
|
|
94
|
+
|
|
95
|
+
th,
|
|
96
|
+
td {
|
|
97
|
+
padding: 8px;
|
|
98
|
+
text-align: left;
|
|
99
|
+
border-bottom: 1px solid #ddd;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -4,7 +4,7 @@ export default function Layout({ body }, { slot, Header }) {
|
|
|
4
4
|
const styles = slot('style').map(makeStyleTag).join('\n');
|
|
5
5
|
const inlineJS = slot('js').map(c => `<script>${c}</script>`).join('\n');
|
|
6
6
|
const inlineCSS = slot('css').map(c => `<style>${c}</style>`).join('\n');
|
|
7
|
-
const title=slot('title').join
|
|
7
|
+
const title = slot('title').join(' | ');
|
|
8
8
|
|
|
9
9
|
return (<>
|
|
10
10
|
{{ html: `<!DOCTYPE html>` }}
|
|
@@ -23,10 +23,10 @@ export default function Layout({ body }, { slot, Header }) {
|
|
|
23
23
|
{{ html: inlineCSS }}
|
|
24
24
|
</head>
|
|
25
25
|
<body>
|
|
26
|
-
<
|
|
27
|
-
|
|
26
|
+
<article>
|
|
27
|
+
<Header title={title} />
|
|
28
28
|
{{ html: body }}
|
|
29
|
-
</
|
|
29
|
+
</article>
|
|
30
30
|
{{ html: inlineJS }}
|
|
31
31
|
</body>
|
|
32
32
|
</html>
|
|
@@ -2,7 +2,7 @@ export const route = '/';
|
|
|
2
2
|
|
|
3
3
|
export default function PageIndex({ }, {
|
|
4
4
|
// all components are available here
|
|
5
|
-
|
|
5
|
+
PageTasks, Sidebar,
|
|
6
6
|
// so are request and response objects
|
|
7
7
|
req, res, params,
|
|
8
8
|
// utils are extendable by your units in ../../units
|
|
@@ -10,10 +10,10 @@ export default function PageIndex({ }, {
|
|
|
10
10
|
// use slot(name,value) and slot(name,key,value) to pass values to the layout
|
|
11
11
|
slot,
|
|
12
12
|
}) {
|
|
13
|
-
slot('title', 'Welcome to Noxt');
|
|
13
|
+
slot('title', 'main', 'Welcome to Noxt');
|
|
14
14
|
|
|
15
15
|
return (
|
|
16
|
-
|
|
16
|
+
<>
|
|
17
17
|
<main>
|
|
18
18
|
<h2>{utils.greet('user')}</h2>
|
|
19
19
|
Here are some tasks: <PageTasks.Link text="Tasks" />
|
|
@@ -21,6 +21,6 @@ export default function PageIndex({ }, {
|
|
|
21
21
|
<aside>
|
|
22
22
|
<Sidebar />
|
|
23
23
|
</aside>
|
|
24
|
-
|
|
24
|
+
</>
|
|
25
25
|
);
|
|
26
26
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export const route = '/tasks/:taskid';
|
|
2
2
|
|
|
3
3
|
export const fetch = {
|
|
4
|
-
task: ({ taskid }) => 'https://jsonplaceholder.typicode.com/todos/' + taskid
|
|
4
|
+
task: ({ taskid }) => 'https://jsonplaceholder.typicode.com/todos/' + taskid,
|
|
5
|
+
user: ({ task }) => 'https://jsonplaceholder.typicode.com/users/' + task.userId
|
|
5
6
|
}
|
|
6
7
|
|
|
7
|
-
export default function PageIndex({ task, taskid }, {
|
|
8
|
+
export default function PageIndex({ task, user, taskid }, {
|
|
8
9
|
// all components are available here
|
|
9
10
|
Json, Sidebar,
|
|
10
11
|
// so are request and response objects
|
|
@@ -14,9 +15,9 @@ export default function PageIndex({ task, taskid }, {
|
|
|
14
15
|
// use slot(name,value) and slot(name,key,value) to pass values to the layout
|
|
15
16
|
slot,
|
|
16
17
|
}) {
|
|
17
|
-
slot('title', 'Task ' + taskid);
|
|
18
|
+
slot('title', 'main', 'Task ' + taskid);
|
|
18
19
|
return (
|
|
19
|
-
|
|
20
|
+
<>
|
|
20
21
|
<main>
|
|
21
22
|
<h2>Here is task {taskid}</h2>
|
|
22
23
|
<table>
|
|
@@ -25,22 +26,31 @@ export default function PageIndex({ task, taskid }, {
|
|
|
25
26
|
<th>Id</th>
|
|
26
27
|
<td>{taskid}</td>
|
|
27
28
|
</tr>
|
|
29
|
+
<tr>
|
|
30
|
+
<th>User</th>
|
|
31
|
+
<td>{user.name}</td>
|
|
32
|
+
</tr>
|
|
33
|
+
<tr>
|
|
34
|
+
<th>Email</th>
|
|
35
|
+
<td>{user.email}</td>
|
|
36
|
+
</tr>
|
|
28
37
|
<tr>
|
|
29
38
|
<th>Title</th>
|
|
30
39
|
<td>{task.title}</td>
|
|
31
40
|
</tr>
|
|
32
41
|
<tr>
|
|
33
42
|
<th>Completed</th>
|
|
34
|
-
<td>{task.completed}</td>
|
|
43
|
+
<td>{task.completed ? 'Yes' : 'No'}</td>
|
|
35
44
|
</tr>
|
|
36
45
|
</tbody>
|
|
37
46
|
</table>
|
|
38
47
|
<h2>Here's the data</h2>
|
|
39
48
|
<Json data={task} />
|
|
49
|
+
<Json data={user} />
|
|
40
50
|
</main>
|
|
41
51
|
<aside>
|
|
42
52
|
<Sidebar />
|
|
43
53
|
</aside>
|
|
44
|
-
|
|
54
|
+
</>
|
|
45
55
|
);
|
|
46
56
|
}
|
|
@@ -11,12 +11,12 @@ export default function PageTasks({ tasks }, {
|
|
|
11
11
|
req, res, params,
|
|
12
12
|
// utils are extendable by your units in ../../units
|
|
13
13
|
utils,
|
|
14
|
-
// use slot(name,
|
|
14
|
+
// use slot(name,key,value) to pass values to the layout
|
|
15
15
|
slot,
|
|
16
16
|
}) {
|
|
17
|
-
slot('title', '
|
|
17
|
+
slot('title', 'main', 'Tasks');
|
|
18
18
|
return (
|
|
19
|
-
|
|
19
|
+
<>
|
|
20
20
|
<main>
|
|
21
21
|
<h2>Here are some tasks</h2>
|
|
22
22
|
<table>
|
|
@@ -31,7 +31,7 @@ export default function PageTasks({ tasks }, {
|
|
|
31
31
|
{tasks.map(({ id, title, completed }) => (
|
|
32
32
|
<tr key={id}>
|
|
33
33
|
<td>{id}</td>
|
|
34
|
-
<td><
|
|
34
|
+
<td><PageTask.Link taskid={id} text={title} /></td>
|
|
35
35
|
<td>{completed ? 'Yes' : 'No'}</td>
|
|
36
36
|
</tr>
|
|
37
37
|
))}
|
|
@@ -43,6 +43,6 @@ export default function PageTasks({ tasks }, {
|
|
|
43
43
|
<aside>
|
|
44
44
|
<Sidebar />
|
|
45
45
|
</aside>
|
|
46
|
-
|
|
46
|
+
</>
|
|
47
47
|
);
|
|
48
48
|
}
|
|
@@ -4,10 +4,13 @@ const jsAlert = `
|
|
|
4
4
|
}
|
|
5
5
|
`;
|
|
6
6
|
|
|
7
|
-
export default function AlertButton({ label, message }) {
|
|
7
|
+
export default function AlertButton({ label, message },{ slot }) {
|
|
8
|
+
|
|
9
|
+
slot('js', 'alert-button', jsAlert);
|
|
10
|
+
|
|
8
11
|
return (
|
|
9
|
-
<
|
|
12
|
+
<button onclick="doAlert(this)" data-message={message}>
|
|
10
13
|
{label}
|
|
11
|
-
</
|
|
14
|
+
</button>
|
|
12
15
|
);
|
|
13
16
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default function Json({ data, title= "JSON"}, { DEV }) {
|
|
2
|
+
|
|
3
|
+
//hide in production
|
|
4
|
+
//if (!DEV) return null;
|
|
5
|
+
|
|
6
|
+
let json;
|
|
7
|
+
try {
|
|
8
|
+
json = JSON.stringify(data, null, 2);
|
|
9
|
+
} catch (e) {
|
|
10
|
+
json = String(data);
|
|
11
|
+
}
|
|
12
|
+
return (
|
|
13
|
+
<details>
|
|
14
|
+
<summary>{title}</summary>
|
|
15
|
+
<pre>{json}</pre>
|
|
16
|
+
</details>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
export default function SideBar({},{ PageIndex, AlertButton }) {
|
|
1
|
+
export default function SideBar({ }, { PageIndex, PageTasks, AlertButton }) {
|
|
2
2
|
return (
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
<>
|
|
4
|
+
<nav>
|
|
5
|
+
<img src="/img/favicon.png" id="logo" />
|
|
6
|
+
<ul>
|
|
7
|
+
<li><PageIndex.Link text="Go Home" /></li>
|
|
8
|
+
<li><PageTasks.Link text="Tasks" /></li>
|
|
9
|
+
<li><AlertButton label="Alert" message="Hello" /></li>
|
|
10
|
+
</ul>
|
|
11
|
+
</nav>
|
|
12
|
+
</>
|
|
9
13
|
);
|
|
10
14
|
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
* {
|
|
2
|
-
box-sizing: border-box;
|
|
3
|
-
}
|
|
4
|
-
body {
|
|
5
|
-
margin: 0;
|
|
6
|
-
padding: 0;
|
|
7
|
-
font-family: sans-serif;
|
|
8
|
-
}
|
|
9
|
-
article {
|
|
10
|
-
max-width:1000px;
|
|
11
|
-
margin: 0 auto;
|
|
12
|
-
padding: 0 10px;
|
|
13
|
-
display: grid;
|
|
14
|
-
grid-template-columns: 1fr max(25%, 200px);
|
|
15
|
-
grid-template-areas: "header header" "main aside";
|
|
16
|
-
gap: 20px;
|
|
17
|
-
|
|
18
|
-
main {
|
|
19
|
-
grid-area:main
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
header {
|
|
23
|
-
grid-area:header
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
aside {
|
|
27
|
-
grid-area:aside
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|