@kozojs/cli 0.1.22 → 0.1.23
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/lib/index.d.ts +2 -0
- package/lib/{index.mjs → index.js} +210 -185
- package/package.json +1 -1
package/lib/index.d.ts
ADDED
|
@@ -1,17 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
1
26
|
// src/index.ts
|
|
2
|
-
|
|
27
|
+
var import_commander = require("commander");
|
|
3
28
|
|
|
4
29
|
// src/commands/new.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
30
|
+
var p = __toESM(require("@clack/prompts"));
|
|
31
|
+
var import_picocolors2 = __toESM(require("picocolors"));
|
|
32
|
+
var import_execa = require("execa");
|
|
8
33
|
|
|
9
34
|
// src/utils/scaffold.ts
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
var import_fs_extra = __toESM(require("fs-extra"));
|
|
36
|
+
var import_node_path = __toESM(require("path"));
|
|
12
37
|
async function scaffoldProject(options) {
|
|
13
38
|
const { projectName, runtime, database, dbPort, auth, packageSource, template, frontend, extras } = options;
|
|
14
|
-
const projectDir =
|
|
39
|
+
const projectDir = import_node_path.default.resolve(process.cwd(), projectName);
|
|
15
40
|
const kozoCoreDep = packageSource === "local" ? "workspace:*" : "^0.3.1";
|
|
16
41
|
if (frontend !== "none") {
|
|
17
42
|
await scaffoldFullstackProject(projectDir, projectName, kozoCoreDep, runtime, database, dbPort, auth, frontend, extras, template);
|
|
@@ -30,9 +55,9 @@ async function scaffoldProject(options) {
|
|
|
30
55
|
if (extras.includes("github-actions")) await createGitHubActions(projectDir);
|
|
31
56
|
return;
|
|
32
57
|
}
|
|
33
|
-
await
|
|
34
|
-
await
|
|
35
|
-
await
|
|
58
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes"));
|
|
59
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "db"));
|
|
60
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "services"));
|
|
36
61
|
const packageJson = {
|
|
37
62
|
name: projectName,
|
|
38
63
|
version: "0.1.0",
|
|
@@ -63,7 +88,7 @@ async function scaffoldProject(options) {
|
|
|
63
88
|
...database === "sqlite" && { "@types/better-sqlite3": "^7.6.0" }
|
|
64
89
|
}
|
|
65
90
|
};
|
|
66
|
-
await
|
|
91
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "package.json"), packageJson, { spaces: 2 });
|
|
67
92
|
const tsconfig = {
|
|
68
93
|
compilerOptions: {
|
|
69
94
|
target: "ES2022",
|
|
@@ -79,7 +104,7 @@ async function scaffoldProject(options) {
|
|
|
79
104
|
include: ["src/**/*"],
|
|
80
105
|
exclude: ["node_modules", "dist"]
|
|
81
106
|
};
|
|
82
|
-
await
|
|
107
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
83
108
|
const drizzleConfig = `import { defineConfig } from 'drizzle-kit';
|
|
84
109
|
|
|
85
110
|
export default defineConfig({
|
|
@@ -91,21 +116,21 @@ export default defineConfig({
|
|
|
91
116
|
}
|
|
92
117
|
});
|
|
93
118
|
`;
|
|
94
|
-
await
|
|
119
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "drizzle.config.ts"), drizzleConfig);
|
|
95
120
|
const envExample = `# Database
|
|
96
121
|
${database === "sqlite" ? "# SQLite uses local file, no URL needed" : "DATABASE_URL="}
|
|
97
122
|
|
|
98
123
|
# Server
|
|
99
124
|
PORT=3000
|
|
100
125
|
`;
|
|
101
|
-
await
|
|
126
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".env.example"), envExample);
|
|
102
127
|
const gitignore = `node_modules/
|
|
103
128
|
dist/
|
|
104
129
|
.env
|
|
105
130
|
*.db
|
|
106
131
|
.turbo/
|
|
107
132
|
`;
|
|
108
|
-
await
|
|
133
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".gitignore"), gitignore);
|
|
109
134
|
const indexTs = `import { createKozo } from '@kozojs/core';
|
|
110
135
|
import { services } from './services/index.js';
|
|
111
136
|
|
|
@@ -129,7 +154,7 @@ const app = createKozo({
|
|
|
129
154
|
|
|
130
155
|
await app.nativeListen();
|
|
131
156
|
`;
|
|
132
|
-
await
|
|
157
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "index.ts"), indexTs);
|
|
133
158
|
const servicesTs = `import { db } from '../db/index.js';
|
|
134
159
|
|
|
135
160
|
export const services = {
|
|
@@ -143,14 +168,14 @@ declare module '@kozojs/core' {
|
|
|
143
168
|
}
|
|
144
169
|
}
|
|
145
170
|
`;
|
|
146
|
-
await
|
|
171
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "services", "index.ts"), servicesTs);
|
|
147
172
|
const schemaTs = getDatabaseSchema(database);
|
|
148
|
-
await
|
|
173
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "schema.ts"), schemaTs);
|
|
149
174
|
const dbIndexTs = getDatabaseIndex(database);
|
|
150
|
-
await
|
|
175
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "index.ts"), dbIndexTs);
|
|
151
176
|
if (database === "sqlite") {
|
|
152
177
|
const seedTs = getSQLiteSeed();
|
|
153
|
-
await
|
|
178
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "seed.ts"), seedTs);
|
|
154
179
|
}
|
|
155
180
|
await createExampleRoutes(projectDir);
|
|
156
181
|
const readme = `# ${projectName}
|
|
@@ -226,7 +251,7 @@ ${database === "sqlite" ? "## SQLite Notes\n\nThe database is automatically init
|
|
|
226
251
|
- [Drizzle ORM](https://orm.drizzle.team)
|
|
227
252
|
- [Hono](https://hono.dev)
|
|
228
253
|
`;
|
|
229
|
-
await
|
|
254
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "README.md"), readme);
|
|
230
255
|
if (database !== "none" && database !== "sqlite") await createDockerCompose(projectDir, projectName, database, dbPort);
|
|
231
256
|
if (extras.includes("docker")) await createDockerfile(projectDir, runtime);
|
|
232
257
|
if (extras.includes("github-actions")) await createGitHubActions(projectDir);
|
|
@@ -346,8 +371,8 @@ async function createExampleRoutes(projectDir) {
|
|
|
346
371
|
};
|
|
347
372
|
};
|
|
348
373
|
`;
|
|
349
|
-
await
|
|
350
|
-
await
|
|
374
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "index.ts"), indexRoute);
|
|
375
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes", "users"));
|
|
351
376
|
const getUsersRoute = `import type { HandlerContext } from '@kozojs/core';
|
|
352
377
|
import { users } from '../../db/schema.js';
|
|
353
378
|
|
|
@@ -361,7 +386,7 @@ export default async ({ services: { db } }: HandlerContext) => {
|
|
|
361
386
|
return { users: allUsers };
|
|
362
387
|
};
|
|
363
388
|
`;
|
|
364
|
-
await
|
|
389
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "users", "get.ts"), getUsersRoute);
|
|
365
390
|
const postUsersRoute = `import { z } from 'zod';
|
|
366
391
|
import type { HandlerContext } from '@kozojs/core';
|
|
367
392
|
import { users } from '../../db/schema.js';
|
|
@@ -389,26 +414,26 @@ export default async ({ body, services: { db } }: HandlerContext<Body>) => {
|
|
|
389
414
|
return { success: true, user };
|
|
390
415
|
};
|
|
391
416
|
`;
|
|
392
|
-
await
|
|
417
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "users", "post.ts"), postUsersRoute);
|
|
393
418
|
}
|
|
394
419
|
async function scaffoldCompleteTemplate(projectDir, projectName, kozoCoreDep, runtime, database = "none", dbPort, auth = true) {
|
|
395
|
-
await
|
|
396
|
-
await
|
|
397
|
-
await
|
|
398
|
-
await
|
|
399
|
-
await
|
|
400
|
-
await
|
|
401
|
-
await
|
|
402
|
-
await
|
|
403
|
-
await
|
|
404
|
-
await
|
|
420
|
+
await import_fs_extra.default.ensureDir(projectDir);
|
|
421
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src"));
|
|
422
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "schemas"));
|
|
423
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes"));
|
|
424
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes", "auth"));
|
|
425
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes", "users"));
|
|
426
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "routes", "posts"));
|
|
427
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "middleware"));
|
|
428
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "utils"));
|
|
429
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "data"));
|
|
405
430
|
const hasDb = database !== "none";
|
|
406
431
|
if (hasDb) {
|
|
407
|
-
await
|
|
408
|
-
await
|
|
409
|
-
await
|
|
432
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src", "db"));
|
|
433
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "schema.ts"), getDatabaseSchema(database));
|
|
434
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "index.ts"), getDatabaseIndex(database));
|
|
410
435
|
if (database === "sqlite") {
|
|
411
|
-
await
|
|
436
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "db", "seed.ts"), getSQLiteSeed());
|
|
412
437
|
}
|
|
413
438
|
}
|
|
414
439
|
const packageJson = {
|
|
@@ -447,7 +472,7 @@ async function scaffoldCompleteTemplate(projectDir, projectName, kozoCoreDep, ru
|
|
|
447
472
|
...database === "sqlite" && { "@types/better-sqlite3": "^7.6.0" }
|
|
448
473
|
}
|
|
449
474
|
};
|
|
450
|
-
await
|
|
475
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "package.json"), packageJson, { spaces: 2 });
|
|
451
476
|
const tsconfig = {
|
|
452
477
|
compilerOptions: {
|
|
453
478
|
target: "ES2022",
|
|
@@ -465,14 +490,14 @@ async function scaffoldCompleteTemplate(projectDir, projectName, kozoCoreDep, ru
|
|
|
465
490
|
include: ["src/**/*"],
|
|
466
491
|
exclude: ["node_modules", "dist"]
|
|
467
492
|
};
|
|
468
|
-
await
|
|
493
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
469
494
|
const gitignore = `node_modules/
|
|
470
495
|
dist/
|
|
471
496
|
.env
|
|
472
497
|
.turbo/
|
|
473
498
|
*.log
|
|
474
499
|
`;
|
|
475
|
-
await
|
|
500
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".gitignore"), gitignore);
|
|
476
501
|
const pgPort = dbPort ?? 5436;
|
|
477
502
|
const dbUrl = database === "postgresql" ? `postgresql://postgres:postgres@localhost:${pgPort}/${projectName}` : database === "mysql" ? `mysql://root:root@localhost:3306/${projectName}` : void 0;
|
|
478
503
|
const envExample = `# Server
|
|
@@ -492,8 +517,8 @@ CORS_ORIGIN=http://localhost:5173
|
|
|
492
517
|
RATE_LIMIT_MAX=100
|
|
493
518
|
RATE_LIMIT_WINDOW=60000
|
|
494
519
|
`;
|
|
495
|
-
await
|
|
496
|
-
await
|
|
520
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".env.example"), envExample);
|
|
521
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".env"), envExample);
|
|
497
522
|
if (hasDb) {
|
|
498
523
|
const dialect = database === "postgresql" ? "postgresql" : database === "mysql" ? "mysql" : "sqlite";
|
|
499
524
|
const drizzleConfig = `import { defineConfig } from 'drizzle-kit';
|
|
@@ -508,7 +533,7 @@ export default defineConfig({
|
|
|
508
533
|
},
|
|
509
534
|
});
|
|
510
535
|
`;
|
|
511
|
-
await
|
|
536
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "drizzle.config.ts"), drizzleConfig);
|
|
512
537
|
}
|
|
513
538
|
const indexTs = `import { createKozo, cors, logger, rateLimit } from '@kozojs/core';
|
|
514
539
|
${auth ? "import { authenticateJWT } from '@kozojs/auth';" : ""}
|
|
@@ -571,7 +596,7 @@ console.log('');
|
|
|
571
596
|
console.log('\u{1F512} Middleware: CORS \xB7 Rate limit \xB7 JWT \xB7 Logger');
|
|
572
597
|
console.log('\u{1F6E1}\uFE0F Graceful shutdown enabled (SIGTERM / SIGINT)');
|
|
573
598
|
`;
|
|
574
|
-
await
|
|
599
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "index.ts"), indexTs);
|
|
575
600
|
await createCompleteSchemas(projectDir);
|
|
576
601
|
await createCompleteUtils(projectDir);
|
|
577
602
|
await createCompleteDataStore(projectDir);
|
|
@@ -736,7 +761,7 @@ Request \u2500\u2500\u25BA \u2502 uWebSockets \u2502 C++ HTTP parser + epoll/kq
|
|
|
736
761
|
|
|
737
762
|
Built with \u2764\uFE0F using Kozo Framework
|
|
738
763
|
`;
|
|
739
|
-
await
|
|
764
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "README.md"), readme);
|
|
740
765
|
}
|
|
741
766
|
async function createCompleteSchemas(projectDir) {
|
|
742
767
|
const userSchemas = `import { z } from 'zod';
|
|
@@ -765,7 +790,7 @@ export type User = z.infer<typeof UserSchema>;
|
|
|
765
790
|
export type CreateUser = z.infer<typeof CreateUserSchema>;
|
|
766
791
|
export type UpdateUser = z.infer<typeof UpdateUserSchema>;
|
|
767
792
|
`;
|
|
768
|
-
await
|
|
793
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "schemas", "user.ts"), userSchemas);
|
|
769
794
|
const postSchemas = `import { z } from 'zod';
|
|
770
795
|
import { UserSchema } from './user.js';
|
|
771
796
|
|
|
@@ -795,7 +820,7 @@ export type Post = z.infer<typeof PostSchema>;
|
|
|
795
820
|
export type PostWithAuthor = z.infer<typeof PostWithAuthorSchema>;
|
|
796
821
|
export type CreatePost = z.infer<typeof CreatePostSchema>;
|
|
797
822
|
`;
|
|
798
|
-
await
|
|
823
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "schemas", "post.ts"), postSchemas);
|
|
799
824
|
const commonSchemas = `import { z } from 'zod';
|
|
800
825
|
|
|
801
826
|
export const PaginationSchema = z.object({
|
|
@@ -812,7 +837,7 @@ export const PostFiltersSchema = z.object({
|
|
|
812
837
|
export type Pagination = z.infer<typeof PaginationSchema>;
|
|
813
838
|
export type PostFilters = z.infer<typeof PostFiltersSchema>;
|
|
814
839
|
`;
|
|
815
|
-
await
|
|
840
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "schemas", "common.ts"), commonSchemas);
|
|
816
841
|
}
|
|
817
842
|
async function createCompleteUtils(projectDir) {
|
|
818
843
|
const helpers = `export function generateUUID(): string {
|
|
@@ -835,7 +860,7 @@ export function paginate<T>(items: T[], page: number, limit: number) {
|
|
|
835
860
|
};
|
|
836
861
|
}
|
|
837
862
|
`;
|
|
838
|
-
await
|
|
863
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "utils", "helpers.ts"), helpers);
|
|
839
864
|
}
|
|
840
865
|
async function createCompleteDataStore(projectDir) {
|
|
841
866
|
const store = `import type { User } from '../schemas/user.js';
|
|
@@ -873,7 +898,7 @@ export const posts: Post[] = [
|
|
|
873
898
|
},
|
|
874
899
|
];
|
|
875
900
|
`;
|
|
876
|
-
await
|
|
901
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "data", "store.ts"), store);
|
|
877
902
|
}
|
|
878
903
|
async function createCompleteRoutes(projectDir) {
|
|
879
904
|
const healthRoute = `import type { Kozo } from '@kozojs/core';
|
|
@@ -889,7 +914,7 @@ export function registerHealthRoute(app: Kozo) {
|
|
|
889
914
|
});
|
|
890
915
|
}
|
|
891
916
|
`;
|
|
892
|
-
await
|
|
917
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "health.ts"), healthRoute);
|
|
893
918
|
const statsRoute = `import { z } from 'zod';
|
|
894
919
|
import type { Kozo } from '@kozojs/core';
|
|
895
920
|
import { users } from '../data/store.js';
|
|
@@ -944,7 +969,7 @@ export function registerStatsRoute(app: Kozo) {
|
|
|
944
969
|
});
|
|
945
970
|
}
|
|
946
971
|
`;
|
|
947
|
-
await
|
|
972
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "stats.ts"), statsRoute);
|
|
948
973
|
const authRoutes = `import { z } from 'zod';
|
|
949
974
|
import type { Kozo } from '@kozojs/core';
|
|
950
975
|
import { createJWT } from '@kozojs/auth';
|
|
@@ -990,7 +1015,7 @@ export function registerAuthRoutes(app: Kozo) {
|
|
|
990
1015
|
});
|
|
991
1016
|
}
|
|
992
1017
|
`;
|
|
993
|
-
await
|
|
1018
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "auth", "index.ts"), authRoutes);
|
|
994
1019
|
const userRoutes = `import { z } from 'zod';
|
|
995
1020
|
import type { Kozo } from '@kozojs/core';
|
|
996
1021
|
import { UserSchema, CreateUserSchema, UpdateUserSchema } from '../../schemas/user.js';
|
|
@@ -1075,7 +1100,7 @@ export function registerUserRoutes(app: Kozo) {
|
|
|
1075
1100
|
});
|
|
1076
1101
|
}
|
|
1077
1102
|
`;
|
|
1078
|
-
await
|
|
1103
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "users", "index.ts"), userRoutes);
|
|
1079
1104
|
const postRoutes = `import { z } from 'zod';
|
|
1080
1105
|
import type { Kozo } from '@kozojs/core';
|
|
1081
1106
|
import { PostSchema, PostWithAuthorSchema, CreatePostSchema } from '../../schemas/post.js';
|
|
@@ -1151,10 +1176,10 @@ export function registerPostRoutes(app: Kozo) {
|
|
|
1151
1176
|
});
|
|
1152
1177
|
}
|
|
1153
1178
|
`;
|
|
1154
|
-
await
|
|
1179
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "routes", "posts", "index.ts"), postRoutes);
|
|
1155
1180
|
}
|
|
1156
1181
|
async function scaffoldApiOnlyTemplate(projectDir, projectName, kozoCoreDep, runtime) {
|
|
1157
|
-
await
|
|
1182
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "src"));
|
|
1158
1183
|
const packageJson = {
|
|
1159
1184
|
name: projectName,
|
|
1160
1185
|
version: "1.0.0",
|
|
@@ -1177,7 +1202,7 @@ async function scaffoldApiOnlyTemplate(projectDir, projectName, kozoCoreDep, run
|
|
|
1177
1202
|
typescript: "^5.6.0"
|
|
1178
1203
|
}
|
|
1179
1204
|
};
|
|
1180
|
-
await
|
|
1205
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "package.json"), packageJson, { spaces: 2 });
|
|
1181
1206
|
const tsconfig = {
|
|
1182
1207
|
compilerOptions: {
|
|
1183
1208
|
target: "ES2022",
|
|
@@ -1192,7 +1217,7 @@ async function scaffoldApiOnlyTemplate(projectDir, projectName, kozoCoreDep, run
|
|
|
1192
1217
|
include: ["src/**/*"],
|
|
1193
1218
|
exclude: ["node_modules", "dist"]
|
|
1194
1219
|
};
|
|
1195
|
-
await
|
|
1220
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
1196
1221
|
const indexTs = `import { createKozo } from '@kozojs/core';
|
|
1197
1222
|
import { z } from 'zod';
|
|
1198
1223
|
|
|
@@ -1215,8 +1240,8 @@ app.get('/hello/:name', {
|
|
|
1215
1240
|
console.log('\u{1F525} Kozo running on http://localhost:3000');
|
|
1216
1241
|
await app.nativeListen();
|
|
1217
1242
|
`;
|
|
1218
|
-
await
|
|
1219
|
-
await
|
|
1243
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "src", "index.ts"), indexTs);
|
|
1244
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".gitignore"), "node_modules/\ndist/\n.env\n");
|
|
1220
1245
|
}
|
|
1221
1246
|
async function createDockerCompose(dir, projectName, database, dbPort, includeApiService = false, runtime = "node") {
|
|
1222
1247
|
if (database === "none" || database === "sqlite") return;
|
|
@@ -1297,7 +1322,7 @@ async function createDockerCompose(dir, projectName, database, dbPort, includeAp
|
|
|
1297
1322
|
const volumes = database === "postgresql" ? "\nvolumes:\n postgres_data:\n" : database === "mysql" ? "\nvolumes:\n mysql_data:\n" : "";
|
|
1298
1323
|
const compose = `services:
|
|
1299
1324
|
${services}${volumes}`;
|
|
1300
|
-
await
|
|
1325
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(dir, "docker-compose.yml"), compose);
|
|
1301
1326
|
}
|
|
1302
1327
|
async function createDockerfile(projectDir, runtime) {
|
|
1303
1328
|
const dockerfile = runtime === "bun" ? `FROM oven/bun:1 AS builder
|
|
@@ -1328,11 +1353,11 @@ RUN npm ci --omit=dev
|
|
|
1328
1353
|
EXPOSE 3000
|
|
1329
1354
|
CMD ["node", "dist/index.js"]
|
|
1330
1355
|
`;
|
|
1331
|
-
await
|
|
1332
|
-
await
|
|
1356
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "Dockerfile"), dockerfile);
|
|
1357
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".dockerignore"), "node_modules\ndist\n.git\n.env\n");
|
|
1333
1358
|
}
|
|
1334
1359
|
async function createGitHubActions(projectDir) {
|
|
1335
|
-
await
|
|
1360
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, ".github", "workflows"));
|
|
1336
1361
|
const workflow = `name: CI
|
|
1337
1362
|
|
|
1338
1363
|
on:
|
|
@@ -1354,15 +1379,15 @@ jobs:
|
|
|
1354
1379
|
- run: npm run build
|
|
1355
1380
|
- run: npm test --if-present
|
|
1356
1381
|
`;
|
|
1357
|
-
await
|
|
1382
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".github", "workflows", "ci.yml"), workflow);
|
|
1358
1383
|
}
|
|
1359
1384
|
async function scaffoldFullstackProject(projectDir, projectName, kozoCoreDep, runtime, database, dbPort, auth, frontend, extras, template) {
|
|
1360
1385
|
const hasDb = database !== "none";
|
|
1361
|
-
await
|
|
1362
|
-
await
|
|
1363
|
-
if (hasDb) await
|
|
1364
|
-
await
|
|
1365
|
-
await
|
|
1386
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "apps", "api", "src", "routes"));
|
|
1387
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "apps", "api", "src", "data"));
|
|
1388
|
+
if (hasDb) await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "apps", "api", "src", "db"));
|
|
1389
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, "apps", "web", "src", "lib"));
|
|
1390
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(projectDir, ".vscode"));
|
|
1366
1391
|
const rootPackageJson = {
|
|
1367
1392
|
name: projectName,
|
|
1368
1393
|
private: true,
|
|
@@ -1371,32 +1396,32 @@ async function scaffoldFullstackProject(projectDir, projectName, kozoCoreDep, ru
|
|
|
1371
1396
|
build: "pnpm run --recursive build"
|
|
1372
1397
|
}
|
|
1373
1398
|
};
|
|
1374
|
-
await
|
|
1375
|
-
await
|
|
1399
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(projectDir, "package.json"), rootPackageJson, { spaces: 2 });
|
|
1400
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "pnpm-workspace.yaml"), `packages:
|
|
1376
1401
|
- 'apps/*'
|
|
1377
1402
|
`);
|
|
1378
|
-
await
|
|
1403
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, ".gitignore"), "node_modules/\ndist/\n.env\n*.log\n");
|
|
1379
1404
|
await scaffoldFullstackApi(projectDir, projectName, kozoCoreDep, runtime, database, dbPort, auth);
|
|
1380
1405
|
await scaffoldFullstackWeb(projectDir, projectName, frontend, auth);
|
|
1381
1406
|
await scaffoldFullstackReadme(projectDir, projectName);
|
|
1382
1407
|
if (database !== "none" && database !== "sqlite") await createDockerCompose(projectDir, projectName, database, dbPort);
|
|
1383
|
-
if (extras.includes("docker")) await createDockerfile(
|
|
1408
|
+
if (extras.includes("docker")) await createDockerfile(import_node_path.default.join(projectDir, "apps", "api"), runtime);
|
|
1384
1409
|
if (extras.includes("github-actions")) await createGitHubActions(projectDir);
|
|
1385
1410
|
}
|
|
1386
1411
|
async function scaffoldFullstackApi(projectDir, projectName, kozoCoreDep, runtime, database = "none", dbPort, auth = true) {
|
|
1387
|
-
const apiDir =
|
|
1412
|
+
const apiDir = import_node_path.default.join(projectDir, "apps", "api");
|
|
1388
1413
|
const hasDb = database !== "none";
|
|
1389
1414
|
if (hasDb) {
|
|
1390
|
-
await
|
|
1391
|
-
await
|
|
1392
|
-
await
|
|
1415
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(apiDir, "src", "db"));
|
|
1416
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, "src", "db", "schema.ts"), getDatabaseSchema(database));
|
|
1417
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, "src", "db", "index.ts"), getDatabaseIndex(database));
|
|
1393
1418
|
if (database === "sqlite") {
|
|
1394
|
-
await
|
|
1419
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, "src", "db", "seed.ts"), getSQLiteSeed());
|
|
1395
1420
|
}
|
|
1396
1421
|
const dialect = database === "postgresql" ? "postgresql" : database === "mysql" ? "mysql" : "sqlite";
|
|
1397
1422
|
const pgPort = dbPort ?? 5436;
|
|
1398
1423
|
const dbUrl = database === "postgresql" ? `postgresql://postgres:postgres@localhost:${pgPort}/${projectName}` : database === "mysql" ? `mysql://root:root@localhost:3306/${projectName}` : void 0;
|
|
1399
|
-
await
|
|
1424
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, "drizzle.config.ts"), `import { defineConfig } from 'drizzle-kit';
|
|
1400
1425
|
import 'dotenv/config';
|
|
1401
1426
|
|
|
1402
1427
|
export default defineConfig({
|
|
@@ -1412,14 +1437,14 @@ export default defineConfig({
|
|
|
1412
1437
|
NODE_ENV=development
|
|
1413
1438
|
${dbUrl ? `DATABASE_URL=${dbUrl}
|
|
1414
1439
|
` : ""}${auth ? "JWT_SECRET=change-me-to-a-random-secret-at-least-32-chars\n" : ""}`;
|
|
1415
|
-
await
|
|
1416
|
-
await
|
|
1440
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, ".env"), envContent);
|
|
1441
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, ".env.example"), envContent);
|
|
1417
1442
|
} else {
|
|
1418
1443
|
const envContent = `PORT=3000
|
|
1419
1444
|
NODE_ENV=development
|
|
1420
1445
|
${auth ? "JWT_SECRET=change-me-to-a-random-secret-at-least-32-chars\n" : ""}`;
|
|
1421
|
-
await
|
|
1422
|
-
await
|
|
1446
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, ".env"), envContent);
|
|
1447
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(apiDir, ".env.example"), envContent);
|
|
1423
1448
|
}
|
|
1424
1449
|
const apiPackageJson = {
|
|
1425
1450
|
name: `@${projectName}/api`,
|
|
@@ -1455,7 +1480,7 @@ ${auth ? "JWT_SECRET=change-me-to-a-random-secret-at-least-32-chars\n" : ""}`;
|
|
|
1455
1480
|
...database === "sqlite" && { "@types/better-sqlite3": "^7.6.0" }
|
|
1456
1481
|
}
|
|
1457
1482
|
};
|
|
1458
|
-
await
|
|
1483
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(apiDir, "package.json"), apiPackageJson, { spaces: 2 });
|
|
1459
1484
|
const tsconfig = {
|
|
1460
1485
|
compilerOptions: {
|
|
1461
1486
|
target: "ES2022",
|
|
@@ -1470,7 +1495,7 @@ ${auth ? "JWT_SECRET=change-me-to-a-random-secret-at-least-32-chars\n" : ""}`;
|
|
|
1470
1495
|
include: ["src/**/*"],
|
|
1471
1496
|
exclude: ["node_modules", "dist"]
|
|
1472
1497
|
};
|
|
1473
|
-
await
|
|
1498
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(apiDir, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
1474
1499
|
const authImport = auth ? `import { authenticateJWT } from '@kozojs/auth';
|
|
1475
1500
|
` : "";
|
|
1476
1501
|
const authMiddleware = auth ? `
|
|
@@ -1483,7 +1508,7 @@ app.getApp().use('/api/*', (c, next) => {
|
|
|
1483
1508
|
return _jwt(c, next);
|
|
1484
1509
|
});
|
|
1485
1510
|
` : "";
|
|
1486
|
-
await
|
|
1511
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "index.ts"), `import 'dotenv/config';
|
|
1487
1512
|
import { createKozo } from '@kozojs/core';
|
|
1488
1513
|
${authImport}import { fileURLToPath } from 'node:url';
|
|
1489
1514
|
import { dirname, join } from 'node:path';
|
|
@@ -1498,7 +1523,7 @@ export type AppType = typeof app;
|
|
|
1498
1523
|
console.log(\`\u{1F525} ${projectName} API on http://localhost:\${PORT}\`);
|
|
1499
1524
|
${runtime === "node" ? "await app.nativeListen();" : "await app.listen();"}
|
|
1500
1525
|
`);
|
|
1501
|
-
await
|
|
1526
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "schemas", "index.ts"), `import { z } from 'zod';
|
|
1502
1527
|
|
|
1503
1528
|
export const UserSchema = z.object({
|
|
1504
1529
|
id: z.string(),
|
|
@@ -1561,7 +1586,7 @@ export const UpdateTaskBody = z.object({
|
|
|
1561
1586
|
priority: z.enum(['low', 'medium', 'high']).optional(),
|
|
1562
1587
|
});
|
|
1563
1588
|
`);
|
|
1564
|
-
await
|
|
1589
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "data", "index.ts"), `export const users = [
|
|
1565
1590
|
{ id: '1', name: 'Alice', email: 'alice@example.com', role: 'admin' as const, createdAt: new Date().toISOString() },
|
|
1566
1591
|
{ id: '2', name: 'Bob', email: 'bob@example.com', role: 'user' as const, createdAt: new Date().toISOString() },
|
|
1567
1592
|
];
|
|
@@ -1577,7 +1602,7 @@ export const tasks = [
|
|
|
1577
1602
|
{ id: '3', title: 'Deploy', completed: false, priority: 'low' as const, createdAt: new Date().toISOString() },
|
|
1578
1603
|
];
|
|
1579
1604
|
`);
|
|
1580
|
-
await
|
|
1605
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "health", "get.ts"), `import { z } from 'zod';
|
|
1581
1606
|
|
|
1582
1607
|
export const schema = {
|
|
1583
1608
|
response: z.object({
|
|
@@ -1595,7 +1620,7 @@ export default async () => ({
|
|
|
1595
1620
|
uptime: process.uptime(),
|
|
1596
1621
|
});
|
|
1597
1622
|
`);
|
|
1598
|
-
await
|
|
1623
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "stats", "get.ts"), `import { z } from 'zod';
|
|
1599
1624
|
import { users, posts, tasks } from '../../../data/index.js';
|
|
1600
1625
|
|
|
1601
1626
|
export const schema = {
|
|
@@ -1616,7 +1641,7 @@ export default async () => ({
|
|
|
1616
1641
|
completedTasks: tasks.filter(t => t.completed).length,
|
|
1617
1642
|
});
|
|
1618
1643
|
`);
|
|
1619
|
-
await
|
|
1644
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "echo", "get.ts"), `import { z } from 'zod';
|
|
1620
1645
|
|
|
1621
1646
|
export const schema = {
|
|
1622
1647
|
query: z.object({ message: z.string() }),
|
|
@@ -1631,7 +1656,7 @@ export default async ({ query }: { query: { message: string } }) => ({
|
|
|
1631
1656
|
timestamp: new Date().toISOString(),
|
|
1632
1657
|
});
|
|
1633
1658
|
`);
|
|
1634
|
-
await
|
|
1659
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "validate", "post.ts"), `import { z } from 'zod';
|
|
1635
1660
|
|
|
1636
1661
|
export const schema = {
|
|
1637
1662
|
body: z.object({
|
|
@@ -1649,7 +1674,7 @@ export default async ({ body }: { body: { email: string; age: number } }) => ({
|
|
|
1649
1674
|
data: body,
|
|
1650
1675
|
});
|
|
1651
1676
|
`);
|
|
1652
|
-
await
|
|
1677
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "users", "get.ts"), `import { z } from 'zod';
|
|
1653
1678
|
import { users } from '../../../data/index.js';
|
|
1654
1679
|
import { UserSchema } from '../../../schemas/index.js';
|
|
1655
1680
|
|
|
@@ -1659,7 +1684,7 @@ export const schema = {
|
|
|
1659
1684
|
|
|
1660
1685
|
export default async () => users;
|
|
1661
1686
|
`);
|
|
1662
|
-
await
|
|
1687
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "users", "post.ts"), `import { users } from '../../../data/index.js';
|
|
1663
1688
|
import { UserSchema, CreateUserBody } from '../../../schemas/index.js';
|
|
1664
1689
|
|
|
1665
1690
|
export const schema = {
|
|
@@ -1679,7 +1704,7 @@ export default async ({ body }: { body: { name: string; email: string; role?: 'a
|
|
|
1679
1704
|
return newUser;
|
|
1680
1705
|
};
|
|
1681
1706
|
`);
|
|
1682
|
-
await
|
|
1707
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "users", "[id]", "get.ts"), `import { z } from 'zod';
|
|
1683
1708
|
import { KozoError } from '@kozojs/core';
|
|
1684
1709
|
import { users } from '../../../../data/index.js';
|
|
1685
1710
|
import { UserSchema } from '../../../../schemas/index.js';
|
|
@@ -1695,7 +1720,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1695
1720
|
return user;
|
|
1696
1721
|
};
|
|
1697
1722
|
`);
|
|
1698
|
-
await
|
|
1723
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "users", "[id]", "put.ts"), `import { z } from 'zod';
|
|
1699
1724
|
import { KozoError } from '@kozojs/core';
|
|
1700
1725
|
import { users } from '../../../../data/index.js';
|
|
1701
1726
|
import { UserSchema, UpdateUserBody } from '../../../../schemas/index.js';
|
|
@@ -1719,7 +1744,7 @@ export default async ({
|
|
|
1719
1744
|
return users[idx];
|
|
1720
1745
|
};
|
|
1721
1746
|
`);
|
|
1722
|
-
await
|
|
1747
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "users", "[id]", "delete.ts"), `import { z } from 'zod';
|
|
1723
1748
|
import { KozoError } from '@kozojs/core';
|
|
1724
1749
|
import { users } from '../../../../data/index.js';
|
|
1725
1750
|
|
|
@@ -1735,7 +1760,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1735
1760
|
return { success: true, message: 'User deleted' };
|
|
1736
1761
|
};
|
|
1737
1762
|
`);
|
|
1738
|
-
await
|
|
1763
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "posts", "get.ts"), `import { z } from 'zod';
|
|
1739
1764
|
import { posts } from '../../../data/index.js';
|
|
1740
1765
|
import { PostSchema } from '../../../schemas/index.js';
|
|
1741
1766
|
|
|
@@ -1751,7 +1776,7 @@ export default async ({ query }: { query: { published?: boolean } }) => {
|
|
|
1751
1776
|
return posts;
|
|
1752
1777
|
};
|
|
1753
1778
|
`);
|
|
1754
|
-
await
|
|
1779
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "posts", "post.ts"), `import { posts, users } from '../../../data/index.js';
|
|
1755
1780
|
import { PostSchema, CreatePostBody } from '../../../schemas/index.js';
|
|
1756
1781
|
|
|
1757
1782
|
export const schema = {
|
|
@@ -1777,7 +1802,7 @@ export default async ({
|
|
|
1777
1802
|
return newPost;
|
|
1778
1803
|
};
|
|
1779
1804
|
`);
|
|
1780
|
-
await
|
|
1805
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "posts", "[id]", "get.ts"), `import { z } from 'zod';
|
|
1781
1806
|
import { KozoError } from '@kozojs/core';
|
|
1782
1807
|
import { posts } from '../../../../data/index.js';
|
|
1783
1808
|
import { PostSchema } from '../../../../schemas/index.js';
|
|
@@ -1793,7 +1818,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1793
1818
|
return post;
|
|
1794
1819
|
};
|
|
1795
1820
|
`);
|
|
1796
|
-
await
|
|
1821
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "posts", "[id]", "put.ts"), `import { z } from 'zod';
|
|
1797
1822
|
import { KozoError } from '@kozojs/core';
|
|
1798
1823
|
import { posts } from '../../../../data/index.js';
|
|
1799
1824
|
import { PostSchema, UpdatePostBody } from '../../../../schemas/index.js';
|
|
@@ -1817,7 +1842,7 @@ export default async ({
|
|
|
1817
1842
|
return posts[idx];
|
|
1818
1843
|
};
|
|
1819
1844
|
`);
|
|
1820
|
-
await
|
|
1845
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "posts", "[id]", "delete.ts"), `import { z } from 'zod';
|
|
1821
1846
|
import { KozoError } from '@kozojs/core';
|
|
1822
1847
|
import { posts } from '../../../../data/index.js';
|
|
1823
1848
|
|
|
@@ -1833,7 +1858,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1833
1858
|
return { success: true, message: 'Post deleted' };
|
|
1834
1859
|
};
|
|
1835
1860
|
`);
|
|
1836
|
-
await
|
|
1861
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "get.ts"), `import { z } from 'zod';
|
|
1837
1862
|
import { tasks } from '../../../data/index.js';
|
|
1838
1863
|
import { TaskSchema } from '../../../schemas/index.js';
|
|
1839
1864
|
|
|
@@ -1860,7 +1885,7 @@ export default async ({
|
|
|
1860
1885
|
return result;
|
|
1861
1886
|
};
|
|
1862
1887
|
`);
|
|
1863
|
-
await
|
|
1888
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "post.ts"), `import { tasks } from '../../../data/index.js';
|
|
1864
1889
|
import { TaskSchema, CreateTaskBody } from '../../../schemas/index.js';
|
|
1865
1890
|
|
|
1866
1891
|
export const schema = {
|
|
@@ -1884,7 +1909,7 @@ export default async ({
|
|
|
1884
1909
|
return newTask;
|
|
1885
1910
|
};
|
|
1886
1911
|
`);
|
|
1887
|
-
await
|
|
1912
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "[id]", "get.ts"), `import { z } from 'zod';
|
|
1888
1913
|
import { KozoError } from '@kozojs/core';
|
|
1889
1914
|
import { tasks } from '../../../../data/index.js';
|
|
1890
1915
|
import { TaskSchema } from '../../../../schemas/index.js';
|
|
@@ -1900,7 +1925,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1900
1925
|
return task;
|
|
1901
1926
|
};
|
|
1902
1927
|
`);
|
|
1903
|
-
await
|
|
1928
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "[id]", "put.ts"), `import { z } from 'zod';
|
|
1904
1929
|
import { KozoError } from '@kozojs/core';
|
|
1905
1930
|
import { tasks } from '../../../../data/index.js';
|
|
1906
1931
|
import { TaskSchema, UpdateTaskBody } from '../../../../schemas/index.js';
|
|
@@ -1924,7 +1949,7 @@ export default async ({
|
|
|
1924
1949
|
return tasks[idx];
|
|
1925
1950
|
};
|
|
1926
1951
|
`);
|
|
1927
|
-
await
|
|
1952
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "[id]", "delete.ts"), `import { z } from 'zod';
|
|
1928
1953
|
import { KozoError } from '@kozojs/core';
|
|
1929
1954
|
import { tasks } from '../../../../data/index.js';
|
|
1930
1955
|
|
|
@@ -1940,7 +1965,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1940
1965
|
return { success: true, message: 'Task deleted' };
|
|
1941
1966
|
};
|
|
1942
1967
|
`);
|
|
1943
|
-
await
|
|
1968
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "tasks", "[id]", "toggle", "patch.ts"), `import { z } from 'zod';
|
|
1944
1969
|
import { KozoError } from '@kozojs/core';
|
|
1945
1970
|
import { tasks } from '../../../../../data/index.js';
|
|
1946
1971
|
import { TaskSchema } from '../../../../../schemas/index.js';
|
|
@@ -1958,7 +1983,7 @@ export default async ({ params }: { params: { id: string } }) => {
|
|
|
1958
1983
|
};
|
|
1959
1984
|
`);
|
|
1960
1985
|
if (auth) {
|
|
1961
|
-
await
|
|
1986
|
+
await import_fs_extra.default.outputFile(import_node_path.default.join(apiDir, "src", "routes", "api", "auth", "login", "post.ts"), `import { z } from 'zod';
|
|
1962
1987
|
import { createJWT, UnauthorizedError } from '@kozojs/auth';
|
|
1963
1988
|
|
|
1964
1989
|
const JWT_SECRET = process.env.JWT_SECRET || 'change-me';
|
|
@@ -1997,9 +2022,9 @@ export default async ({ body }: { body: { email: string; password: string } }) =
|
|
|
1997
2022
|
}
|
|
1998
2023
|
}
|
|
1999
2024
|
async function scaffoldFullstackWeb(projectDir, projectName, frontend, auth = false) {
|
|
2000
|
-
const webDir =
|
|
2001
|
-
await
|
|
2002
|
-
await
|
|
2025
|
+
const webDir = import_node_path.default.join(projectDir, "apps", "web");
|
|
2026
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(webDir, "src", "lib"));
|
|
2027
|
+
await import_fs_extra.default.ensureDir(import_node_path.default.join(webDir, "src", "pages"));
|
|
2003
2028
|
const packageJson = {
|
|
2004
2029
|
name: `@${projectName}/web`,
|
|
2005
2030
|
version: "1.0.0",
|
|
@@ -2021,8 +2046,8 @@ async function scaffoldFullstackWeb(projectDir, projectName, frontend, auth = fa
|
|
|
2021
2046
|
tailwindcss: "^4.0.0"
|
|
2022
2047
|
}
|
|
2023
2048
|
};
|
|
2024
|
-
await
|
|
2025
|
-
await
|
|
2049
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(webDir, "package.json"), packageJson, { spaces: 2 });
|
|
2050
|
+
await import_fs_extra.default.writeJSON(import_node_path.default.join(webDir, "tsconfig.json"), {
|
|
2026
2051
|
compilerOptions: {
|
|
2027
2052
|
target: "ES2020",
|
|
2028
2053
|
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
@@ -2040,7 +2065,7 @@ async function scaffoldFullstackWeb(projectDir, projectName, frontend, auth = fa
|
|
|
2040
2065
|
},
|
|
2041
2066
|
include: ["src"]
|
|
2042
2067
|
}, { spaces: 2 });
|
|
2043
|
-
await
|
|
2068
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "vite.config.ts"), `import { defineConfig } from 'vite';
|
|
2044
2069
|
import react from '@vitejs/plugin-react';
|
|
2045
2070
|
import tailwindcss from '@tailwindcss/vite';
|
|
2046
2071
|
|
|
@@ -2054,7 +2079,7 @@ export default defineConfig({
|
|
|
2054
2079
|
},
|
|
2055
2080
|
});
|
|
2056
2081
|
`);
|
|
2057
|
-
await
|
|
2082
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "index.html"), `<!DOCTYPE html>
|
|
2058
2083
|
<html lang="en">
|
|
2059
2084
|
<head>
|
|
2060
2085
|
<meta charset="UTF-8" />
|
|
@@ -2067,12 +2092,12 @@ export default defineConfig({
|
|
|
2067
2092
|
</body>
|
|
2068
2093
|
</html>
|
|
2069
2094
|
`);
|
|
2070
|
-
await
|
|
2095
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "index.css"), `@import "tailwindcss";
|
|
2071
2096
|
|
|
2072
2097
|
body { background-color: rgb(15 23 42); color: rgb(241 245 249); font-family: ui-sans-serif, system-ui, sans-serif; }
|
|
2073
2098
|
* { box-sizing: border-box; }
|
|
2074
2099
|
`);
|
|
2075
|
-
await
|
|
2100
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "lib", "api.ts"), `const API_BASE = '';
|
|
2076
2101
|
|
|
2077
2102
|
${auth ? `export function getToken(): string | null {
|
|
2078
2103
|
return localStorage.getItem('kozo_token');
|
|
@@ -2109,7 +2134,7 @@ ${auth ? ` const token = getToken();
|
|
|
2109
2134
|
return { data, status: res.status, ms: Math.round(performance.now() - start) };
|
|
2110
2135
|
}
|
|
2111
2136
|
`);
|
|
2112
|
-
await
|
|
2137
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "main.tsx"), `import React from 'react';
|
|
2113
2138
|
import ReactDOM from 'react-dom/client';
|
|
2114
2139
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2115
2140
|
import App from './App';
|
|
@@ -2127,14 +2152,14 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
2127
2152
|
</React.StrictMode>
|
|
2128
2153
|
);
|
|
2129
2154
|
`);
|
|
2130
|
-
await
|
|
2131
|
-
await
|
|
2132
|
-
await
|
|
2133
|
-
await
|
|
2155
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "pages", "Dashboard.tsx"), generateDashboardPage());
|
|
2156
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "pages", "Users.tsx"), generateUsersPage());
|
|
2157
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "pages", "Posts.tsx"), generatePostsPage());
|
|
2158
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "pages", "Tasks.tsx"), generateTasksPage());
|
|
2134
2159
|
if (auth) {
|
|
2135
|
-
await
|
|
2160
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "pages", "Login.tsx"), generateLoginPage());
|
|
2136
2161
|
}
|
|
2137
|
-
await
|
|
2162
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(webDir, "src", "App.tsx"), generateAppTsx(projectName, auth));
|
|
2138
2163
|
}
|
|
2139
2164
|
function generateAppTsx(projectName, auth) {
|
|
2140
2165
|
const authImports = auth ? `import { getToken, clearToken } from './lib/api';` : "";
|
|
@@ -2918,19 +2943,19 @@ const res = await client.api.users.$get();
|
|
|
2918
2943
|
const users = await res.json(); // Fully typed!
|
|
2919
2944
|
\`\`\`
|
|
2920
2945
|
`;
|
|
2921
|
-
await
|
|
2946
|
+
await import_fs_extra.default.writeFile(import_node_path.default.join(projectDir, "README.md"), readme);
|
|
2922
2947
|
}
|
|
2923
2948
|
|
|
2924
2949
|
// src/utils/ascii-art.ts
|
|
2925
|
-
|
|
2950
|
+
var import_picocolors = __toESM(require("picocolors"));
|
|
2926
2951
|
var KOZO_LOGO = `
|
|
2927
|
-
${
|
|
2928
|
-
${
|
|
2929
|
-
${
|
|
2930
|
-
${
|
|
2952
|
+
${import_picocolors.default.red(" _ __")}${import_picocolors.default.yellow("___ ")}${import_picocolors.default.red("______")}${import_picocolors.default.yellow("___ ")}
|
|
2953
|
+
${import_picocolors.default.red("| |/ /")}${import_picocolors.default.yellow(" _ \\\\")}${import_picocolors.default.red("|_ /")}${import_picocolors.default.yellow(" _ \\\\")}
|
|
2954
|
+
${import_picocolors.default.red("| ' /")}${import_picocolors.default.yellow(" (_) |")}${import_picocolors.default.red("/ /")}${import_picocolors.default.yellow(" (_) |")}
|
|
2955
|
+
${import_picocolors.default.red("|_|\\_\\\\")}${import_picocolors.default.yellow("___/")}${import_picocolors.default.red("___|\\\\")}${import_picocolors.default.yellow("___/")}
|
|
2931
2956
|
`;
|
|
2932
2957
|
var KOZO_BANNER = `
|
|
2933
|
-
${
|
|
2958
|
+
${import_picocolors.default.bold(import_picocolors.default.red("\u{1F525} KOZO"))} ${import_picocolors.default.dim("- The Structure for the Edge")}
|
|
2934
2959
|
`;
|
|
2935
2960
|
function printLogo() {
|
|
2936
2961
|
console.log(KOZO_LOGO);
|
|
@@ -2939,7 +2964,7 @@ function printLogo() {
|
|
|
2939
2964
|
// src/commands/new.ts
|
|
2940
2965
|
async function newCommand(projectName) {
|
|
2941
2966
|
printLogo();
|
|
2942
|
-
p.intro(
|
|
2967
|
+
p.intro(import_picocolors2.default.bold(import_picocolors2.default.red("\u{1F525} Create a new Kozo project")));
|
|
2943
2968
|
const isLocalWorkspace = process.env.KOZO_LOCAL === "true";
|
|
2944
2969
|
const project = await p.group(
|
|
2945
2970
|
{
|
|
@@ -3057,14 +3082,14 @@ async function newCommand(projectName) {
|
|
|
3057
3082
|
if (project.install) {
|
|
3058
3083
|
s.start("Installing dependencies...");
|
|
3059
3084
|
try {
|
|
3060
|
-
await execa("pnpm", ["install"], {
|
|
3085
|
+
await (0, import_execa.execa)("pnpm", ["install"], {
|
|
3061
3086
|
cwd: project.name,
|
|
3062
3087
|
stdio: "pipe"
|
|
3063
3088
|
});
|
|
3064
3089
|
s.stop("Dependencies installed!");
|
|
3065
3090
|
} catch {
|
|
3066
3091
|
try {
|
|
3067
|
-
await execa("npm", ["install"], {
|
|
3092
|
+
await (0, import_execa.execa)("npm", ["install"], {
|
|
3068
3093
|
cwd: project.name,
|
|
3069
3094
|
stdio: "pipe"
|
|
3070
3095
|
});
|
|
@@ -3075,33 +3100,33 @@ async function newCommand(projectName) {
|
|
|
3075
3100
|
}
|
|
3076
3101
|
}
|
|
3077
3102
|
}
|
|
3078
|
-
p.outro(
|
|
3103
|
+
p.outro(import_picocolors2.default.green("\u2728 Project ready!"));
|
|
3079
3104
|
console.log(`
|
|
3080
|
-
${
|
|
3105
|
+
${import_picocolors2.default.bold("Next steps:")}
|
|
3081
3106
|
|
|
3082
|
-
${
|
|
3083
|
-
${!project.install ?
|
|
3107
|
+
${import_picocolors2.default.cyan(`cd ${project.name}`)}
|
|
3108
|
+
${!project.install ? import_picocolors2.default.cyan("pnpm install") + "\n " : ""}${import_picocolors2.default.cyan("pnpm dev")}
|
|
3084
3109
|
|
|
3085
|
-
${
|
|
3110
|
+
${import_picocolors2.default.dim("Documentation:")} ${import_picocolors2.default.underline("https://kozo-docs.vercel.app")}
|
|
3086
3111
|
`);
|
|
3087
3112
|
}
|
|
3088
3113
|
|
|
3089
3114
|
// src/commands/build.ts
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3115
|
+
var import_execa2 = require("execa");
|
|
3116
|
+
var import_picocolors3 = __toESM(require("picocolors"));
|
|
3117
|
+
var import_fs_extra2 = __toESM(require("fs-extra"));
|
|
3118
|
+
var import_node_path4 = __toESM(require("path"));
|
|
3094
3119
|
|
|
3095
3120
|
// src/routing/manifest.ts
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3121
|
+
var import_node_crypto = require("crypto");
|
|
3122
|
+
var import_node_fs2 = require("fs");
|
|
3123
|
+
var import_node_path3 = require("path");
|
|
3124
|
+
var import_glob2 = require("glob");
|
|
3100
3125
|
|
|
3101
3126
|
// src/routing/scan.ts
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3127
|
+
var import_glob = require("glob");
|
|
3128
|
+
var import_node_path2 = require("path");
|
|
3129
|
+
var import_node_fs = require("fs");
|
|
3105
3130
|
var HTTP_METHODS = ["get", "post", "put", "patch", "delete"];
|
|
3106
3131
|
function fileToRoute(filePath) {
|
|
3107
3132
|
const normalized = filePath.replace(/\\/g, "/");
|
|
@@ -3139,7 +3164,7 @@ function isRouteFile(file) {
|
|
|
3139
3164
|
function detectSchemas(absolutePath) {
|
|
3140
3165
|
let source = "";
|
|
3141
3166
|
try {
|
|
3142
|
-
source = readFileSync(absolutePath, "utf8");
|
|
3167
|
+
source = (0, import_node_fs.readFileSync)(absolutePath, "utf8");
|
|
3143
3168
|
} catch {
|
|
3144
3169
|
return { hasBodySchema: false, hasQuerySchema: false };
|
|
3145
3170
|
}
|
|
@@ -3159,7 +3184,7 @@ function routeScore(urlPath) {
|
|
|
3159
3184
|
}
|
|
3160
3185
|
async function scanRoutes(options) {
|
|
3161
3186
|
const { routesDir, verbose = false } = options;
|
|
3162
|
-
const files = await glob("**/*.{ts,js}", {
|
|
3187
|
+
const files = await (0, import_glob.glob)("**/*.{ts,js}", {
|
|
3163
3188
|
cwd: routesDir,
|
|
3164
3189
|
nodir: true,
|
|
3165
3190
|
ignore: ["**/_*.ts", "**/_*.js", "**/*.test.ts", "**/*.spec.ts", "**/*.test.js", "**/*.spec.js"]
|
|
@@ -3169,7 +3194,7 @@ async function scanRoutes(options) {
|
|
|
3169
3194
|
if (!isRouteFile(file)) continue;
|
|
3170
3195
|
const parsed = fileToRoute(file);
|
|
3171
3196
|
if (!parsed) continue;
|
|
3172
|
-
const absolutePath = join(routesDir, file);
|
|
3197
|
+
const absolutePath = (0, import_node_path2.join)(routesDir, file);
|
|
3173
3198
|
const { hasBodySchema, hasQuerySchema } = detectSchemas(absolutePath);
|
|
3174
3199
|
const params = extractParams(parsed.path);
|
|
3175
3200
|
routes.push({
|
|
@@ -3194,17 +3219,17 @@ async function scanRoutes(options) {
|
|
|
3194
3219
|
|
|
3195
3220
|
// src/routing/manifest.ts
|
|
3196
3221
|
async function hashRouteFiles(routesDir) {
|
|
3197
|
-
const files = await
|
|
3222
|
+
const files = await (0, import_glob2.glob)("**/*.{ts,js}", {
|
|
3198
3223
|
cwd: routesDir,
|
|
3199
3224
|
nodir: true,
|
|
3200
3225
|
ignore: ["**/_*.ts", "**/_*.js", "**/*.test.ts", "**/*.spec.ts", "**/*.test.js", "**/*.spec.js"]
|
|
3201
3226
|
});
|
|
3202
3227
|
files.sort();
|
|
3203
|
-
const hash = createHash("sha256");
|
|
3228
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
3204
3229
|
for (const file of files) {
|
|
3205
3230
|
hash.update(file);
|
|
3206
3231
|
try {
|
|
3207
|
-
const content =
|
|
3232
|
+
const content = (0, import_node_fs2.readFileSync)((0, import_node_path3.join)(routesDir, file));
|
|
3208
3233
|
hash.update(content);
|
|
3209
3234
|
} catch {
|
|
3210
3235
|
}
|
|
@@ -3212,9 +3237,9 @@ async function hashRouteFiles(routesDir) {
|
|
|
3212
3237
|
return hash.digest("hex");
|
|
3213
3238
|
}
|
|
3214
3239
|
function readExistingManifest(manifestPath) {
|
|
3215
|
-
if (!existsSync(manifestPath)) return null;
|
|
3240
|
+
if (!(0, import_node_fs2.existsSync)(manifestPath)) return null;
|
|
3216
3241
|
try {
|
|
3217
|
-
const raw =
|
|
3242
|
+
const raw = (0, import_node_fs2.readFileSync)(manifestPath, "utf8");
|
|
3218
3243
|
return JSON.parse(raw);
|
|
3219
3244
|
} catch {
|
|
3220
3245
|
return null;
|
|
@@ -3224,7 +3249,7 @@ async function generateManifest(options) {
|
|
|
3224
3249
|
const {
|
|
3225
3250
|
routesDir,
|
|
3226
3251
|
projectRoot,
|
|
3227
|
-
outputPath =
|
|
3252
|
+
outputPath = (0, import_node_path3.join)(projectRoot, "routes-manifest.json"),
|
|
3228
3253
|
cache = true,
|
|
3229
3254
|
verbose = false
|
|
3230
3255
|
} = options;
|
|
@@ -3257,11 +3282,11 @@ async function generateManifest(options) {
|
|
|
3257
3282
|
contentHash,
|
|
3258
3283
|
routes: entries
|
|
3259
3284
|
};
|
|
3260
|
-
const dir = dirname(outputPath);
|
|
3261
|
-
if (!existsSync(dir)) {
|
|
3262
|
-
mkdirSync(dir, { recursive: true });
|
|
3285
|
+
const dir = (0, import_node_path3.dirname)(outputPath);
|
|
3286
|
+
if (!(0, import_node_fs2.existsSync)(dir)) {
|
|
3287
|
+
(0, import_node_fs2.mkdirSync)(dir, { recursive: true });
|
|
3263
3288
|
}
|
|
3264
|
-
writeFileSync(outputPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
3289
|
+
(0, import_node_fs2.writeFileSync)(outputPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
|
|
3265
3290
|
if (verbose) {
|
|
3266
3291
|
console.log(` \u2713 Generated routes-manifest.json (${entries.length} routes, hash: ${contentHash.slice(0, 8)}\u2026)`);
|
|
3267
3292
|
}
|
|
@@ -3274,22 +3299,22 @@ function printBox(title) {
|
|
|
3274
3299
|
const width = 50;
|
|
3275
3300
|
const pad = Math.max(0, Math.floor((width - title.length) / 2));
|
|
3276
3301
|
const line = "\u2500".repeat(width);
|
|
3277
|
-
console.log(
|
|
3278
|
-
console.log(
|
|
3279
|
-
console.log(
|
|
3302
|
+
console.log(import_picocolors3.default.cyan(`\u250C${line}\u2510`));
|
|
3303
|
+
console.log(import_picocolors3.default.cyan("\u2502") + " ".repeat(pad) + import_picocolors3.default.bold(title) + " ".repeat(width - pad - title.length) + import_picocolors3.default.cyan("\u2502"));
|
|
3304
|
+
console.log(import_picocolors3.default.cyan(`\u2514${line}\u2518`));
|
|
3280
3305
|
console.log();
|
|
3281
3306
|
}
|
|
3282
3307
|
function step(n, total, label) {
|
|
3283
|
-
console.log(
|
|
3308
|
+
console.log(import_picocolors3.default.dim(`[${n}/${total}]`) + " " + import_picocolors3.default.cyan("\u2192") + " " + label);
|
|
3284
3309
|
}
|
|
3285
3310
|
function ok(label) {
|
|
3286
|
-
console.log(
|
|
3311
|
+
console.log(import_picocolors3.default.green(" \u2713") + " " + label);
|
|
3287
3312
|
}
|
|
3288
3313
|
function fail(label, err) {
|
|
3289
|
-
console.log(
|
|
3314
|
+
console.log(import_picocolors3.default.red(" \u2717") + " " + label);
|
|
3290
3315
|
if (err) {
|
|
3291
3316
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3292
|
-
console.log(
|
|
3317
|
+
console.log(import_picocolors3.default.dim(" " + msg));
|
|
3293
3318
|
}
|
|
3294
3319
|
}
|
|
3295
3320
|
async function buildCommand(options = {}) {
|
|
@@ -3300,11 +3325,11 @@ async function buildCommand(options = {}) {
|
|
|
3300
3325
|
let currentStep = 0;
|
|
3301
3326
|
currentStep++;
|
|
3302
3327
|
step(currentStep, TOTAL_STEPS, "Checking project structure\u2026");
|
|
3303
|
-
if (!
|
|
3328
|
+
if (!import_fs_extra2.default.existsSync(import_node_path4.default.join(cwd, "package.json"))) {
|
|
3304
3329
|
fail("No package.json found. Run this command inside a Kozo project.");
|
|
3305
3330
|
process.exit(1);
|
|
3306
3331
|
}
|
|
3307
|
-
if (!
|
|
3332
|
+
if (!import_fs_extra2.default.existsSync(import_node_path4.default.join(cwd, "node_modules"))) {
|
|
3308
3333
|
fail("Dependencies not installed. Run `npm install` first.");
|
|
3309
3334
|
process.exit(1);
|
|
3310
3335
|
}
|
|
@@ -3312,7 +3337,7 @@ async function buildCommand(options = {}) {
|
|
|
3312
3337
|
currentStep++;
|
|
3313
3338
|
step(currentStep, TOTAL_STEPS, "Cleaning previous build\u2026");
|
|
3314
3339
|
try {
|
|
3315
|
-
await
|
|
3340
|
+
await import_fs_extra2.default.remove(import_node_path4.default.join(cwd, "dist"));
|
|
3316
3341
|
ok("dist/ cleaned");
|
|
3317
3342
|
} catch (err) {
|
|
3318
3343
|
fail("Failed to clean dist/", err);
|
|
@@ -3322,12 +3347,12 @@ async function buildCommand(options = {}) {
|
|
|
3322
3347
|
currentStep++;
|
|
3323
3348
|
step(currentStep, TOTAL_STEPS, "Generating routes manifest\u2026");
|
|
3324
3349
|
const routesDirRel = options.routesDir ?? "src/routes";
|
|
3325
|
-
const routesDirAbs =
|
|
3326
|
-
if (!
|
|
3327
|
-
console.log(
|
|
3350
|
+
const routesDirAbs = import_node_path4.default.join(cwd, routesDirRel);
|
|
3351
|
+
if (!import_fs_extra2.default.existsSync(routesDirAbs)) {
|
|
3352
|
+
console.log(import_picocolors3.default.dim(` \u26A0 Routes directory not found (${routesDirRel}), skipping manifest.`));
|
|
3328
3353
|
} else {
|
|
3329
3354
|
try {
|
|
3330
|
-
const manifestOutAbs = options.manifestOut ?
|
|
3355
|
+
const manifestOutAbs = options.manifestOut ? import_node_path4.default.join(cwd, options.manifestOut) : import_node_path4.default.join(cwd, "routes-manifest.json");
|
|
3331
3356
|
const manifest = await generateManifest({
|
|
3332
3357
|
routesDir: routesDirAbs,
|
|
3333
3358
|
projectRoot: cwd,
|
|
@@ -3338,7 +3363,7 @@ async function buildCommand(options = {}) {
|
|
|
3338
3363
|
ok(`Manifest ready \u2014 ${manifest.routes.length} route(s)`);
|
|
3339
3364
|
} catch (err) {
|
|
3340
3365
|
fail("Manifest generation failed", err);
|
|
3341
|
-
console.log(
|
|
3366
|
+
console.log(import_picocolors3.default.dim(" Continuing build without manifest\u2026"));
|
|
3342
3367
|
}
|
|
3343
3368
|
}
|
|
3344
3369
|
}
|
|
@@ -3346,7 +3371,7 @@ async function buildCommand(options = {}) {
|
|
|
3346
3371
|
step(currentStep, TOTAL_STEPS, "Compiling with tsup\u2026");
|
|
3347
3372
|
try {
|
|
3348
3373
|
const tsupArgs = ["tsup", ...options.tsupArgs ?? []];
|
|
3349
|
-
await
|
|
3374
|
+
await (0, import_execa2.execa)("npx", tsupArgs, {
|
|
3350
3375
|
cwd,
|
|
3351
3376
|
stdio: "inherit",
|
|
3352
3377
|
env: { ...process.env, NODE_ENV: "production" }
|
|
@@ -3357,12 +3382,12 @@ async function buildCommand(options = {}) {
|
|
|
3357
3382
|
process.exit(1);
|
|
3358
3383
|
}
|
|
3359
3384
|
console.log();
|
|
3360
|
-
console.log(
|
|
3385
|
+
console.log(import_picocolors3.default.green("\u2705 Build successful"));
|
|
3361
3386
|
console.log();
|
|
3362
3387
|
}
|
|
3363
3388
|
|
|
3364
3389
|
// src/index.ts
|
|
3365
|
-
var program = new Command();
|
|
3390
|
+
var program = new import_commander.Command();
|
|
3366
3391
|
program.name("kozo").description("CLI to scaffold new Kozo Framework projects").version("0.2.6");
|
|
3367
3392
|
program.argument("[project-name]", "Name of the project").action(async (projectName) => {
|
|
3368
3393
|
await newCommand(projectName);
|