create-colonel 0.1.4 → 0.1.6
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 +17 -0
- package/package.json +1 -1
- package/template/README.md +23 -2
- package/template/package.json +4 -3
- package/template/resources/views/base/index.ejs +157 -1
- package/template/src/app/Http/Controllers/AppController.ts +13 -4
- package/template/src/app/Http/Controllers/Controller.ts +22 -0
- package/template/src/app/Services/AppInfoService.ts +8 -1
- package/template/src/bootstrap/server.ts +10 -1
package/README.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Scaffold a new Colonel app from the command line.
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/create-colonel)
|
|
6
|
+
[](../../LICENSE)
|
|
7
|
+
[](https://bun.sh)
|
|
8
|
+
[](template)
|
|
9
|
+
|
|
5
10
|
## Usage
|
|
6
11
|
|
|
7
12
|
```bash
|
|
@@ -45,6 +50,18 @@ bun packages/create-colonel/src/cli.ts my-app
|
|
|
45
50
|
|
|
46
51
|
When run inside this repository, the CLI auto-links the local framework package for easier development.
|
|
47
52
|
|
|
53
|
+
## Tests
|
|
54
|
+
|
|
55
|
+
There are no dedicated automated tests for this package yet.
|
|
56
|
+
|
|
57
|
+
Recommended smoke test from repository root:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
rm -rf /tmp/colonel-smoke && bun packages/create-colonel/src/cli.ts /tmp/colonel-smoke
|
|
61
|
+
cd /tmp/colonel-smoke
|
|
62
|
+
bun run start
|
|
63
|
+
```
|
|
64
|
+
|
|
48
65
|
## Publishing
|
|
49
66
|
|
|
50
67
|
```bash
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
# Colonel App
|
|
1
|
+
# Colonel App Template
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](../README.md)
|
|
4
|
+
[](https://bun.sh)
|
|
5
|
+
[](https://www.npmjs.com/package/@coloneldev/framework)
|
|
6
|
+
|
|
7
|
+
This template is copied into new projects created by `create-colonel`.
|
|
4
8
|
|
|
5
9
|
## Run
|
|
6
10
|
|
|
@@ -10,3 +14,20 @@ bun run start
|
|
|
10
14
|
```
|
|
11
15
|
|
|
12
16
|
Server runs at http://localhost:5000.
|
|
17
|
+
|
|
18
|
+
## Upgrade Colonel
|
|
19
|
+
|
|
20
|
+
Upgrade your app to the latest published framework:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bun run upgrade:colonel
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Tests
|
|
27
|
+
|
|
28
|
+
This template itself does not include app-specific automated tests yet.
|
|
29
|
+
Framework integration tests can be run from the monorepo root where Colonel source is developed:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bun run test
|
|
33
|
+
```
|
package/template/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "colonel-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": true,
|
|
6
6
|
"scripts": {
|
|
7
|
-
"start": "bun --watch src/index.ts"
|
|
7
|
+
"start": "bun --watch src/index.ts",
|
|
8
|
+
"upgrade:colonel": "bun add @coloneldev/framework@latest"
|
|
8
9
|
},
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"@coloneldev/framework": "^0.1.
|
|
11
|
+
"@coloneldev/framework": "^0.1.5",
|
|
11
12
|
"ejs": "^5.0.1"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
@@ -1 +1,157 @@
|
|
|
1
|
-
<
|
|
1
|
+
<section class="landing-shell">
|
|
2
|
+
<style>
|
|
3
|
+
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--ink: #0d1310;
|
|
7
|
+
--ink-soft: #203329;
|
|
8
|
+
--canvas: #f3f1e9;
|
|
9
|
+
--accent: #b8441a;
|
|
10
|
+
--accent-soft: #db7c31;
|
|
11
|
+
--panel: #ffffff;
|
|
12
|
+
--olive: #5e6a39;
|
|
13
|
+
--line: #d8d3c7;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
background: radial-gradient(circle at 80% 10%, #f8e6c7 0%, var(--canvas) 38%, #ede8da 100%);
|
|
19
|
+
color: var(--ink);
|
|
20
|
+
font-family: 'Space Grotesk', sans-serif;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.landing-shell {
|
|
24
|
+
max-width: 1040px;
|
|
25
|
+
margin: 0 auto;
|
|
26
|
+
padding: 2rem 1rem 3rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.hero {
|
|
30
|
+
border: 1px solid var(--line);
|
|
31
|
+
background: linear-gradient(125deg, #fffdf8 0%, #f6f3e9 100%);
|
|
32
|
+
border-radius: 22px;
|
|
33
|
+
padding: 2.2rem;
|
|
34
|
+
box-shadow: 0 16px 45px rgba(32, 51, 41, 0.09);
|
|
35
|
+
animation: rise 0.65s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.kicker {
|
|
39
|
+
font-family: 'IBM Plex Mono', monospace;
|
|
40
|
+
letter-spacing: 0.1em;
|
|
41
|
+
font-size: 0.74rem;
|
|
42
|
+
color: var(--olive);
|
|
43
|
+
margin-bottom: 1rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
h1 {
|
|
47
|
+
font-size: clamp(2rem, 5vw, 3.8rem);
|
|
48
|
+
line-height: 1.03;
|
|
49
|
+
margin: 0;
|
|
50
|
+
max-width: 16ch;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.lead {
|
|
54
|
+
margin-top: 1rem;
|
|
55
|
+
font-size: 1.04rem;
|
|
56
|
+
color: var(--ink-soft);
|
|
57
|
+
max-width: 65ch;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.cta {
|
|
61
|
+
display: flex;
|
|
62
|
+
gap: 0.75rem;
|
|
63
|
+
flex-wrap: wrap;
|
|
64
|
+
margin-top: 1.4rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.btn {
|
|
68
|
+
text-decoration: none;
|
|
69
|
+
padding: 0.72rem 1.05rem;
|
|
70
|
+
border-radius: 999px;
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
border: 1px solid transparent;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.btn-primary {
|
|
76
|
+
background: var(--accent);
|
|
77
|
+
color: #fff;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.btn-secondary {
|
|
81
|
+
border-color: var(--line);
|
|
82
|
+
color: var(--ink);
|
|
83
|
+
background: #fff;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.grid {
|
|
87
|
+
margin-top: 1.25rem;
|
|
88
|
+
display: grid;
|
|
89
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
90
|
+
gap: 0.8rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.tile {
|
|
94
|
+
background: var(--panel);
|
|
95
|
+
border: 1px solid var(--line);
|
|
96
|
+
border-radius: 14px;
|
|
97
|
+
padding: 0.95rem;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.tile strong {
|
|
101
|
+
display: block;
|
|
102
|
+
margin-bottom: 0.35rem;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tile p {
|
|
106
|
+
margin: 0;
|
|
107
|
+
color: var(--ink-soft);
|
|
108
|
+
font-size: 0.94rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.meta {
|
|
112
|
+
margin-top: 1rem;
|
|
113
|
+
font-family: 'IBM Plex Mono', monospace;
|
|
114
|
+
font-size: 0.78rem;
|
|
115
|
+
color: #4f5e54;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@keyframes rise {
|
|
119
|
+
from { opacity: 0; transform: translateY(12px); }
|
|
120
|
+
to { opacity: 1; transform: translateY(0); }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@media (max-width: 840px) {
|
|
124
|
+
.hero { padding: 1.35rem; }
|
|
125
|
+
.grid { grid-template-columns: 1fr; }
|
|
126
|
+
}
|
|
127
|
+
</style>
|
|
128
|
+
|
|
129
|
+
<article class="hero">
|
|
130
|
+
<div class="kicker">COLONEL // APP TEMPLATE</div>
|
|
131
|
+
<h1>Your first Colonel app starts with opinionated clarity.</h1>
|
|
132
|
+
<p class="lead">
|
|
133
|
+
This starter includes route wiring, controller injection, static file handling, and view composition so you can focus on real application behavior from day one.
|
|
134
|
+
</p>
|
|
135
|
+
<div class="cta">
|
|
136
|
+
<a class="btn btn-primary" href="/users">View User Route</a>
|
|
137
|
+
<a class="btn btn-secondary" href="<%= docsUrl || 'https://gwhitdev.github.io/colonel-framework/' %>" target="_blank" rel="noreferrer">Open Documentation</a>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div class="grid">
|
|
141
|
+
<div class="tile">
|
|
142
|
+
<strong>Practical Defaults</strong>
|
|
143
|
+
<p>Project structure and startup wiring are ready for immediate feature work.</p>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="tile">
|
|
146
|
+
<strong>Dependency Injection</strong>
|
|
147
|
+
<p>Controllers receive services explicitly via static inject tokens.</p>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="tile">
|
|
150
|
+
<strong>Upgrade Path</strong>
|
|
151
|
+
<p>Use <code>bun run upgrade:colonel</code> to pull the latest framework release.</p>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div class="meta">GENERATED WITH create-colonel • Runtime: Bun • Language: TypeScript</div>
|
|
156
|
+
</article>
|
|
157
|
+
</section>
|
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
import type { HttpRequest } from "@coloneldev/framework";
|
|
1
2
|
import Controller from './Controller';
|
|
3
|
+
import { AppInfoService } from '../../Services/AppInfoService';
|
|
2
4
|
|
|
3
5
|
export class AppController extends Controller {
|
|
4
|
-
|
|
6
|
+
static inject = [AppInfoService];
|
|
7
|
+
|
|
8
|
+
constructor(private appInfoService: AppInfoService) {
|
|
5
9
|
super();
|
|
6
10
|
}
|
|
7
11
|
|
|
8
|
-
index(): Record<string, any> {
|
|
12
|
+
index(req: HttpRequest): Record<string, any> {
|
|
13
|
+
const previousVisits = this.sessionGet<number>(req, "visits") ?? 0;
|
|
14
|
+
const visits = previousVisits + 1;
|
|
15
|
+
this.sessionPut(req, "visits", visits);
|
|
16
|
+
|
|
9
17
|
return [
|
|
10
18
|
'base/index',
|
|
11
19
|
{
|
|
12
|
-
"titleData":
|
|
13
|
-
|
|
20
|
+
"titleData": this.appInfoService.welcomeTitle(),
|
|
21
|
+
"docsUrl": this.appInfoService.documentationUrl(),
|
|
22
|
+
"footerData": `Session visits: ${visits}`,
|
|
14
23
|
},
|
|
15
24
|
]
|
|
16
25
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { HttpRequest, Session } from "@coloneldev/framework";
|
|
2
|
+
|
|
1
3
|
export default class Controller {
|
|
2
4
|
constructor() {
|
|
3
5
|
// Base constructor logic can be added here if needed
|
|
@@ -6,4 +8,24 @@ export default class Controller {
|
|
|
6
8
|
health(): Record<string, string> {
|
|
7
9
|
return { status: "ok" };
|
|
8
10
|
}
|
|
11
|
+
|
|
12
|
+
protected requireSession(req: HttpRequest): Session {
|
|
13
|
+
if (!req.session) {
|
|
14
|
+
throw new Error("Session is not enabled for this request");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return req.session;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected sessionGet<T = unknown>(req: HttpRequest, key: string): T | undefined {
|
|
21
|
+
return this.requireSession(req).get<T>(key);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
protected sessionPut(req: HttpRequest, key: string, value: unknown): void {
|
|
25
|
+
this.requireSession(req).set(key, value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected sessionForget(req: HttpRequest, key: string): void {
|
|
29
|
+
this.requireSession(req).forget(key);
|
|
30
|
+
}
|
|
9
31
|
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export class AppInfoService {
|
|
2
|
-
constructor(
|
|
2
|
+
constructor(
|
|
3
|
+
private appName: string,
|
|
4
|
+
private docsUrl: string = "https://gwhitdev.github.io/colonel-framework/"
|
|
5
|
+
) {}
|
|
3
6
|
|
|
4
7
|
welcomeTitle(): string {
|
|
5
8
|
return `Welcome to ${this.appName}`;
|
|
6
9
|
}
|
|
10
|
+
|
|
11
|
+
documentationUrl(): string {
|
|
12
|
+
return this.docsUrl;
|
|
13
|
+
}
|
|
7
14
|
}
|
|
@@ -13,11 +13,20 @@ const publicRoot = path.resolve(import.meta.dir, "..", "..", "public");
|
|
|
13
13
|
const controllerRoot = path.resolve(import.meta.dir, "..", "app", "Http", "Controllers");
|
|
14
14
|
const container = new Container();
|
|
15
15
|
|
|
16
|
-
container.singleton(
|
|
16
|
+
container.singleton(
|
|
17
|
+
AppInfoService,
|
|
18
|
+
() => new AppInfoService(
|
|
19
|
+
process.env.appName ?? "Colonel",
|
|
20
|
+
process.env.COLONEL_DOCS_URL ?? "https://gwhitdev.github.io/colonel-framework/"
|
|
21
|
+
)
|
|
22
|
+
);
|
|
17
23
|
|
|
18
24
|
export const server = () => {
|
|
19
25
|
const Colonel = new Kernel(webRouter, [], {
|
|
20
26
|
viewsRoot,
|
|
27
|
+
session: {
|
|
28
|
+
enabled: true,
|
|
29
|
+
},
|
|
21
30
|
controllerResolver: async (name: string) => {
|
|
22
31
|
const modulePath = `${controllerRoot}/${name}.ts`;
|
|
23
32
|
const mod = await import(modulePath);
|