@kosmic/cli 0.0.1 → 0.0.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/create/scaffold.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAmCD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/create/scaffold.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,OAAO,CAAC,CAOlB;AA8DD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { authTemplateFiles } from "./templates/auth.js";
4
- import { baseTemplateFiles } from "./templates/base.js";
3
+ import { authTemplateDirectory } from "./templates/auth.js";
4
+ import { baseTemplateDirectory } from "./templates/base.js";
5
5
  /**
6
6
  * Check whether a directory exists and contains at least one entry.
7
7
  */
@@ -15,17 +15,36 @@ export async function directoryHasFiles(targetDirectory) {
15
15
  }
16
16
  }
17
17
  /**
18
- * Replace known placeholders in template file content.
18
+ * Render placeholders in template content using the provided context.
19
19
  */
20
20
  function renderTemplate(fileContents, context) {
21
- return fileContents.replaceAll('{{projectName}}', context.projectName);
21
+ return fileContents.replaceAll(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/gv, (match, key) => context[key] ?? match);
22
22
  }
23
23
  /**
24
- * Write all template files to the target directory.
24
+ * Recursively list all files in a template directory.
25
25
  */
26
- async function writeTemplates(targetDirectory, templateFiles, context) {
27
- const writes = Object.entries(templateFiles).map(async ([relativePath, templateValue]) => {
26
+ async function getTemplateFiles(templateDirectory) {
27
+ const entries = await fs.readdir(templateDirectory, { withFileTypes: true });
28
+ const files = await Promise.all(entries.map(async (entry) => {
29
+ const entryPath = path.join(templateDirectory, entry.name);
30
+ if (entry.isDirectory()) {
31
+ return getTemplateFiles(entryPath);
32
+ }
33
+ return [entryPath];
34
+ }));
35
+ return files.flat();
36
+ }
37
+ /**
38
+ * Write template files from a source directory to the target directory.
39
+ */
40
+ async function writeTemplates(targetDirectory, templateDirectory, context) {
41
+ const templateFiles = await getTemplateFiles(templateDirectory);
42
+ const writes = templateFiles.map(async (templatePath) => {
43
+ const relativePath = path
44
+ .relative(templateDirectory, templatePath)
45
+ .replace(/\.tmpl$/v, '');
28
46
  const outputPath = path.join(targetDirectory, relativePath);
47
+ const templateValue = await fs.readFile(templatePath, 'utf8');
29
48
  await fs.mkdir(path.dirname(outputPath), { recursive: true });
30
49
  await fs.writeFile(outputPath, renderTemplate(templateValue, context), 'utf8');
31
50
  });
@@ -41,9 +60,9 @@ export async function scaffoldKosmicProject(options) {
41
60
  }
42
61
  await fs.mkdir(targetDirectory, { recursive: true });
43
62
  const context = { projectName };
44
- await writeTemplates(targetDirectory, baseTemplateFiles, context);
63
+ await writeTemplates(targetDirectory, baseTemplateDirectory, context);
45
64
  if (withAuth) {
46
- await writeTemplates(targetDirectory, authTemplateFiles, context);
65
+ await writeTemplates(targetDirectory, authTemplateDirectory, context);
47
66
  }
48
67
  }
49
68
  //# sourceMappingURL=scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAStD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,eAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,YAAoB,EACpB,OAA8B;IAE9B,OAAO,YAAY,CAAC,UAAU,CAAC,iBAAiB,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,eAAuB,EACvB,aAAqC,EACrC,OAA8B;IAE9B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAC9C,KAAK,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,EAAE;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,SAAS,CAChB,UAAU,EACV,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,EACtC,MAAM,CACP,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAwB;IAExB,MAAM,EAAC,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAC,GAAG,OAAO,CAAC;IAEhE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,EAAC,WAAW,EAAC,CAAC;IAE9B,MAAM,cAAc,CAAC,eAAe,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAElE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,cAAc,CAAC,eAAe,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAS1D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,eAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAClD,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACrB,YAAoB,EACpB,OAA+B;IAE/B,OAAO,YAAY,CAAC,UAAU,CAC5B,iCAAiC,EACjC,CAAC,KAAa,EAAE,GAAW,EAAU,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAC9D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAAC,iBAAyB;IACvD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3D,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,OAAO,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,eAAuB,EACvB,iBAAyB,EACzB,OAA+B;IAE/B,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;QACtD,MAAM,YAAY,GAAG,IAAI;aACtB,QAAQ,CAAC,iBAAiB,EAAE,YAAY,CAAC;aACzC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAE9D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,SAAS,CAChB,UAAU,EACV,cAAc,CAAC,aAAa,EAAE,OAAO,CAAC,EACtC,MAAM,CACP,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAwB;IAExB,MAAM,EAAC,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAC,GAAG,OAAO,CAAC;IAEhE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,EAAC,WAAW,EAAC,CAAC;IAE9B,MAAM,cAAc,CAAC,eAAe,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAEtE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,cAAc,CAAC,eAAe,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const authTemplateFiles: Record<string, string>;
1
+ export declare const authTemplateDirectory: string;
2
2
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/create/templates/auth.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiWpD,CAAC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../../src/create/templates/auth.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,QAAyC,CAAC"}
@@ -1,355 +1,3 @@
1
- export const authTemplateFiles = {
2
- '.env.example': `# Server settings
3
- PORT=3000
4
- SERVER_HOST=127.0.0.1
5
- LOG_LEVEL=info
6
-
7
- # Basic auth credentials for scaffolded login
8
- APP_AUTH_USERNAME=admin
9
- APP_AUTH_PASSWORD=kosmic
10
- `,
11
- 'README.md': `# {{projectName}}
12
-
13
- A minimal Kosmic application scaffolded with optional auth support.
14
-
15
- ## Scripts
16
-
17
- - npm run dev
18
- - npm run build
19
- - npm run start
20
- - npm run lint
21
-
22
- ## Development
23
-
24
- 1. Copy .env.example to .env.
25
- 2. Run npm install.
26
- 3. Run npm run dev.
27
- 4. Visit /login and sign in with APP_AUTH_USERNAME and APP_AUTH_PASSWORD.
28
- `,
29
- 'src/server.ts': `import path from 'node:path';
30
- import {KosmicServer, type SessionStore} from '@kosmic/server';
31
-
32
- class MemorySessionStore implements SessionStore {
33
- readonly #sessions = new Map<string, unknown>();
34
-
35
- /**
36
- * Retrieve a serialized session value.
37
- */
38
- async get(key: string): Promise<unknown> {
39
- return this.#sessions.get(key);
40
- }
41
-
42
- /**
43
- * Persist a serialized session value.
44
- */
45
- async set(key: string, value: unknown): Promise<void> {
46
- this.#sessions.set(key, value);
47
- }
48
-
49
- /**
50
- * Remove an existing session value.
51
- */
52
- async destroy(key: string): Promise<void> {
53
- this.#sessions.delete(key);
54
- }
55
- }
56
-
57
- export const kosmicServer = new KosmicServer({
58
- routesDir: path.join(import.meta.dirname, 'routes'),
59
- sessionStore: new MemorySessionStore(),
60
- });
61
-
62
- /**
63
- * Return the app singleton.
64
- */
65
- export function getServer(): KosmicServer {
66
- return kosmicServer;
67
- }
68
- `,
69
- 'src/routes/index.ts': `import type {Context} from '@kosmic/server';
70
-
71
- /**
72
- * Render the default landing page.
73
- */
74
- export async function get(ctx: Context) {
75
- const user = ctx.session?.user;
76
-
77
- ctx.type = 'html';
78
- ctx.body = \`<!doctype html>
79
- <html lang="en">
80
- <head>
81
- <meta charset="utf-8" />
82
- <meta name="viewport" content="width=device-width, initial-scale=1" />
83
- <title>{{projectName}}</title>
84
- <style>
85
- :root {
86
- --bg: #f6f7fb;
87
- --card: #ffffff;
88
- --text: #14213d;
89
- --muted: #5f6c80;
90
- --accent: #fca311;
91
- }
92
-
93
- body {
94
- margin: 0;
95
- min-height: 100vh;
96
- display: grid;
97
- place-items: center;
98
- font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
99
- color: var(--text);
100
- background: radial-gradient(circle at 20% 20%, #fff9eb 0%, var(--bg) 50%);
101
- }
102
-
103
- main {
104
- max-width: 42rem;
105
- padding: 2rem;
106
- }
107
-
108
- section {
109
- background: var(--card);
110
- border-radius: 14px;
111
- box-shadow: 0 12px 36px rgb(20 33 61 / 0.12);
112
- padding: 2rem;
113
- }
114
-
115
- h1 {
116
- margin-top: 0;
117
- font-size: 2rem;
118
- }
119
-
120
- nav {
121
- margin-top: 1.25rem;
122
- display: flex;
123
- gap: 0.75rem;
124
- }
125
-
126
- a {
127
- color: #7a4a00;
128
- }
129
-
130
- p {
131
- color: var(--muted);
132
- line-height: 1.6;
133
- }
134
- </style>
135
- </head>
136
- <body>
137
- <main>
138
- <section>
139
- <h1>{{projectName}}</h1>
140
- <p>
141
- This app includes optional auth routes. Edit <code>src/routes</code> to
142
- extend the template.
143
- </p>
144
- <nav>
145
- \${
146
- user
147
- ? '<a href="/account">Account</a><a href="/logout">Logout</a>'
148
- : '<a href="/login">Login</a>'
149
- }
150
- </nav>
151
- </section>
152
- </main>
153
- </body>
154
- </html>\`;
155
- }
156
- `,
157
- 'src/routes/login.ts': `import type {Context} from '@kosmic/server';
158
-
159
- /**
160
- * Safely read a trimmed string value from an unknown request body object.
161
- */
162
- function readBodyString(
163
- body: unknown,
164
- key: 'username' | 'password',
165
- ): string | undefined {
166
- if (!body || typeof body !== 'object') {
167
- return undefined;
168
- }
169
-
170
- const value = (body as Record<string, unknown>)[key];
171
-
172
- if (typeof value !== 'string') {
173
- return undefined;
174
- }
175
-
176
- const trimmedValue = value.trim();
177
- return trimmedValue.length > 0 ? trimmedValue : undefined;
178
- }
179
-
180
- /**
181
- * Render the login form.
182
- */
183
- export async function get(ctx: Context) {
184
- ctx.type = 'html';
185
- ctx.body = \`<!doctype html>
186
- <html lang="en">
187
- <head>
188
- <meta charset="utf-8" />
189
- <meta name="viewport" content="width=device-width, initial-scale=1" />
190
- <title>Login</title>
191
- <style>
192
- body {
193
- margin: 0;
194
- min-height: 100vh;
195
- display: grid;
196
- place-items: center;
197
- font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
198
- background: #f6f7fb;
199
- }
200
-
201
- form {
202
- width: min(24rem, calc(100vw - 2rem));
203
- background: #ffffff;
204
- border-radius: 12px;
205
- padding: 1.5rem;
206
- box-shadow: 0 8px 24px rgb(20 33 61 / 0.12);
207
- }
208
-
209
- label {
210
- display: block;
211
- margin-bottom: 0.5rem;
212
- }
213
-
214
- input {
215
- width: 100%;
216
- padding: 0.6rem;
217
- margin-top: 0.25rem;
218
- margin-bottom: 0.75rem;
219
- border: 1px solid #d6dbe7;
220
- border-radius: 8px;
221
- }
222
-
223
- button {
224
- border: 0;
225
- border-radius: 8px;
226
- padding: 0.6rem 0.9rem;
227
- background: #fca311;
228
- color: #1f2937;
229
- font-weight: 600;
230
- }
231
-
232
- .message {
233
- color: #9a3412;
234
- }
235
- </style>
236
- </head>
237
- <body>
238
- <form method="post" action="/login">
239
- <h1>Sign in</h1>
240
- <p class="message">\${ctx.query.error ? 'Invalid credentials.' : ''}</p>
241
- <label>
242
- Username
243
- <input required name="username" autocomplete="username" />
244
- </label>
245
- <label>
246
- Password
247
- <input
248
- required
249
- type="password"
250
- name="password"
251
- autocomplete="current-password"
252
- />
253
- </label>
254
- <button type="submit">Login</button>
255
- </form>
256
- </body>
257
- </html>\`;
258
- }
259
-
260
- /**
261
- * Validate credentials and establish a session.
262
- */
263
- export async function post(ctx: Context) {
264
- const expectedUsername = process.env.APP_AUTH_USERNAME ?? 'admin';
265
- const expectedPassword = process.env.APP_AUTH_PASSWORD ?? 'kosmic';
266
- const username = readBodyString(ctx.request.body, 'username');
267
- const password = readBodyString(ctx.request.body, 'password');
268
-
269
- if (!ctx.session || username !== expectedUsername || password !== expectedPassword) {
270
- ctx.redirect('/login?error=1');
271
- return;
272
- }
273
-
274
- ctx.session.user = {
275
- username,
276
- loggedInAt: new Date().toISOString(),
277
- };
278
-
279
- ctx.redirect('/account');
280
- }
281
- `,
282
- 'src/routes/logout.ts': `import type {Context} from '@kosmic/server';
283
-
284
- /**
285
- * Destroy the local session user and redirect home.
286
- */
287
- export async function get(ctx: Context) {
288
- if (ctx.session) {
289
- delete ctx.session.user;
290
- }
291
-
292
- ctx.redirect('/');
293
- }
294
- `,
295
- 'src/routes/account.ts': `import type {Context} from '@kosmic/server';
296
-
297
- /**
298
- * Render the protected account page.
299
- */
300
- export async function get(ctx: Context) {
301
- const user = ctx.session?.user;
302
-
303
- if (!user) {
304
- ctx.redirect('/login');
305
- return;
306
- }
307
-
308
- ctx.type = 'html';
309
- ctx.body = \`<!doctype html>
310
- <html lang="en">
311
- <head>
312
- <meta charset="utf-8" />
313
- <meta name="viewport" content="width=device-width, initial-scale=1" />
314
- <title>Account</title>
315
- <style>
316
- body {
317
- margin: 0;
318
- min-height: 100vh;
319
- display: grid;
320
- place-items: center;
321
- font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
322
- background: #f6f7fb;
323
- }
324
-
325
- article {
326
- width: min(40rem, calc(100vw - 2rem));
327
- background: #ffffff;
328
- border-radius: 12px;
329
- padding: 1.5rem;
330
- box-shadow: 0 8px 24px rgb(20 33 61 / 0.12);
331
- }
332
- </style>
333
- </head>
334
- <body>
335
- <article>
336
- <h1>Account</h1>
337
- <p>Welcome, \${user.username}.</p>
338
- <p>Logged in at \${new Date(user.loggedInAt).toLocaleString()}.</p>
339
- <p><a href="/logout">Logout</a></p>
340
- </article>
341
- </body>
342
- </html>\`;
343
- }
344
- `,
345
- 'src/types/session.d.ts': `declare module 'koa-session' {
346
- interface Session {
347
- user?: {
348
- username: string;
349
- loggedInAt: string;
350
- };
351
- }
352
- }
353
- `,
354
- };
1
+ import path from 'node:path';
2
+ export const authTemplateDirectory = path.join(import.meta.dirname, 'auth');
355
3
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../src/create/templates/auth.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,cAAc,EAAE;;;;;;;;CAQjB;IACC,WAAW,EAAE;;;;;;;;;;;;;;;;;CAiBd;IACC,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuClB;IACC,qBAAqB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuFxB;IACC,qBAAqB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HxB;IACC,sBAAsB,EAAE;;;;;;;;;;;;CAYzB;IACC,uBAAuB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD1B;IACC,wBAAwB,EAAE;;;;;;;;CAQ3B;CACA,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../src/create/templates/auth.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const baseTemplateFiles: Record<string, string>;
1
+ export declare const baseTemplateDirectory: string;
2
2
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/create/templates/base.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2NpD,CAAC"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/create/templates/base.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,QAAyC,CAAC"}
@@ -1,221 +1,3 @@
1
- export const baseTemplateFiles = {
2
- '.env.example': `# Server settings
3
- PORT=3000
4
- SERVER_HOST=127.0.0.1
5
- LOG_LEVEL=info
6
- `,
7
- '.gitignore': `node_modules
8
- dist
9
- .env
10
- `,
11
- 'README.md': `# {{projectName}}
12
-
13
- A minimal Kosmic application scaffolded with the create command.
14
-
15
- ## Scripts
16
-
17
- - npm run dev
18
- - npm run build
19
- - npm run start
20
- - npm run lint
21
-
22
- ## Development
23
-
24
- 1. Copy .env.example to .env.
25
- 2. Run npm install.
26
- 3. Run npm run dev.
27
- `,
28
- 'package.json': `{
29
- "name": "{{projectName}}",
30
- "version": "0.0.0",
31
- "private": true,
32
- "type": "module",
33
- "main": "dist/src/index.js",
34
- "scripts": {
35
- "build": "kosmic build",
36
- "check": "tsc --noEmit",
37
- "dev": "kosmic dev",
38
- "lint": "xo",
39
- "start": "kosmic start",
40
- "test": "node --test"
41
- },
42
- "dependencies": {
43
- "@kosmic/cli": "latest",
44
- "@kosmic/config": "latest",
45
- "@kosmic/logger": "latest",
46
- "@kosmic/server": "latest"
47
- },
48
- "devDependencies": {
49
- "@types/node": "~25.5.0",
50
- "typescript": "~5.9.3",
51
- "vite": "^8.0.3",
52
- "xo": "^1.2.3"
53
- },
54
- "engines": {
55
- "node": ">=22"
56
- }
57
- }
58
- `,
59
- 'tsconfig.json': `{
60
- "compilerOptions": {
61
- "target": "ES2022",
62
- "module": "NodeNext",
63
- "moduleResolution": "NodeNext",
64
- "strict": true,
65
- "skipLibCheck": true,
66
- "outDir": "dist",
67
- "declaration": true,
68
- "declarationMap": true,
69
- "sourceMap": true,
70
- "types": ["node"]
71
- },
72
- "include": ["src", "vite.config.ts"],
73
- "exclude": ["node_modules", "dist"]
74
- }
75
- `,
76
- 'vite.config.ts': `/* eslint-disable unicorn/prefer-module */
77
1
  import path from 'node:path';
78
- import type {UserConfig} from 'vite';
79
-
80
- const config: UserConfig = {
81
- root: path.join(__dirname, 'src', 'client'),
82
- build: {
83
- manifest: true,
84
- rollupOptions: {
85
- input: path.join(__dirname, 'src', 'client', 'scripts', 'index.ts'),
86
- },
87
- outDir: path.join(__dirname, 'dist', 'src', 'public'),
88
- emptyOutDir: true,
89
- },
90
- };
91
-
92
- export default config;
93
- `,
94
- 'src/index.ts': `import process from 'node:process';
95
- import {config} from '@kosmic/config';
96
- import {logger} from '@kosmic/logger';
97
- import {kosmicServer} from './server.ts';
98
-
99
- const server = await kosmicServer.listen(config.port, config.host);
100
-
101
- logger.info(\`Server listening on \${config.host}:\${config.port}\`);
102
-
103
- if (process.send) {
104
- process.send({status: 'ready'});
105
- }
106
-
107
- process.on('unhandledRejection', (error) => {
108
- throw error;
109
- });
110
-
111
- process.on('uncaughtException', (error) => {
112
- logger.error(error);
113
- process.exit(1);
114
- });
115
-
116
- process.on('beforeExit', () => {
117
- logger.info('Server shutting down');
118
- server.closeAllConnections();
119
- server.close(() => {
120
- process.exit(0);
121
- });
122
- });
123
- `,
124
- 'src/server.ts': `import path from 'node:path';
125
- import {KosmicServer} from '@kosmic/server';
126
-
127
- export const kosmicServer = new KosmicServer({
128
- routesDir: path.join(import.meta.dirname, 'routes'),
129
- });
130
-
131
- /**
132
- * Return the app singleton.
133
- */
134
- export function getServer(): KosmicServer {
135
- return kosmicServer;
136
- }
137
- `,
138
- 'src/routes/index.ts': `import type {Context} from '@kosmic/server';
139
-
140
- /**
141
- * Render the default landing page.
142
- */
143
- export async function get(ctx: Context) {
144
- ctx.type = 'html';
145
- ctx.body = \`<!doctype html>
146
- <html lang="en">
147
- <head>
148
- <meta charset="utf-8" />
149
- <meta name="viewport" content="width=device-width, initial-scale=1" />
150
- <title>{{projectName}}</title>
151
- <style>
152
- :root {
153
- --bg: #f6f7fb;
154
- --card: #ffffff;
155
- --text: #14213d;
156
- --muted: #5f6c80;
157
- --accent: #fca311;
158
- }
159
-
160
- body {
161
- margin: 0;
162
- min-height: 100vh;
163
- display: grid;
164
- place-items: center;
165
- font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
166
- color: var(--text);
167
- background: radial-gradient(circle at 20% 20%, #fff9eb 0%, var(--bg) 50%);
168
- }
169
-
170
- main {
171
- max-width: 42rem;
172
- padding: 2rem;
173
- }
174
-
175
- section {
176
- background: var(--card);
177
- border-radius: 14px;
178
- box-shadow: 0 12px 36px rgb(20 33 61 / 0.12);
179
- padding: 2rem;
180
- }
181
-
182
- h1 {
183
- margin-top: 0;
184
- font-size: 2rem;
185
- }
186
-
187
- p {
188
- color: var(--muted);
189
- line-height: 1.6;
190
- }
191
-
192
- code {
193
- background: #fff1d1;
194
- border-radius: 6px;
195
- padding: 0.2rem 0.4rem;
196
- }
197
- </style>
198
- </head>
199
- <body>
200
- <main>
201
- <section>
202
- <h1>{{projectName}}</h1>
203
- <p>
204
- Your Kosmic app is ready. Edit <code>src/routes/index.ts</code> to start
205
- building your first route.
206
- </p>
207
- </section>
208
- </main>
209
- </body>
210
- </html>\`;
211
- }
212
- `,
213
- 'src/public/.gitkeep': '',
214
- 'src/client/scripts/index.ts': `import '../styles/styles.css';
215
- `,
216
- 'src/client/styles/styles.css': `:root {
217
- color-scheme: light;
218
- }
219
- `,
220
- };
2
+ export const baseTemplateDirectory = path.join(import.meta.dirname, 'base');
221
3
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/create/templates/base.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACvD,cAAc,EAAE;;;;CAIjB;IACC,YAAY,EAAE;;;CAGf;IACC,WAAW,EAAE;;;;;;;;;;;;;;;;CAgBd;IACC,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BjB;IACC,eAAe,EAAE;;;;;;;;;;;;;;;;CAgBlB;IACC,gBAAgB,EAAE;;;;;;;;;;;;;;;;;CAiBnB;IACC,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB;IACC,eAAe,EAAE;;;;;;;;;;;;;CAalB;IACC,qBAAqB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ExB;IACC,qBAAqB,EAAE,EAAE;IACzB,6BAA6B,EAAE;CAChC;IACC,8BAA8B,EAAE;;;CAGjC;CACA,CAAC"}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/create/templates/base.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC"}