create-celsian 0.3.10 → 0.3.11
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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +60 -33
- package/dist/index.js.map +1 -1
- package/dist/templates/full.d.ts.map +1 -1
- package/dist/templates/full.js +29 -25
- package/dist/templates/full.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAgBA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AA6DjE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAqCzE"}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// create-celsian — Project scaffolder
|
|
3
3
|
// Zero external dependencies. Interactive prompts via raw stdin.
|
|
4
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
-
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync, readdirSync, realpathSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { createInterface } from "node:readline";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
import { basicTemplate } from "./templates/basic.js";
|
|
8
9
|
import { fullTemplate } from "./templates/full.js";
|
|
9
10
|
import { restApiTemplate } from "./templates/rest-api.js";
|
|
10
11
|
import { rpcApiTemplate } from "./templates/rpc-api.js";
|
|
11
|
-
// ─── Template Registry ───
|
|
12
12
|
const templates = {
|
|
13
13
|
full: fullTemplate,
|
|
14
14
|
basic: basicTemplate,
|
|
@@ -21,17 +21,6 @@ const templateDescriptions = {
|
|
|
21
21
|
"rest-api": "REST API with TypeBox schemas",
|
|
22
22
|
"rpc-api": "RPC-first with typed client",
|
|
23
23
|
};
|
|
24
|
-
// ─── CLI Argument Parsing ───
|
|
25
|
-
const args = process.argv.slice(2);
|
|
26
|
-
// Handle --help
|
|
27
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
28
|
-
printUsage();
|
|
29
|
-
process.exit(0);
|
|
30
|
-
}
|
|
31
|
-
// Extract flags
|
|
32
|
-
const templateFlag = args.indexOf("--template");
|
|
33
|
-
const templateArg = templateFlag !== -1 ? args[templateFlag + 1] : undefined;
|
|
34
|
-
const nameArg = args.find((a) => !a.startsWith("--") && (templateFlag === -1 || args.indexOf(a) !== templateFlag + 1));
|
|
35
24
|
// ─── Interactive Mode ───
|
|
36
25
|
async function prompt(question, defaultValue) {
|
|
37
26
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -69,27 +58,14 @@ async function interactiveMode() {
|
|
|
69
58
|
return { name, template, pm };
|
|
70
59
|
}
|
|
71
60
|
// ─── Scaffold ───
|
|
72
|
-
function scaffold(name, template, pm) {
|
|
61
|
+
export function scaffold(name, template, pm) {
|
|
73
62
|
const files = templates[template];
|
|
74
63
|
if (!files) {
|
|
75
64
|
console.error(`\n Unknown template: ${template}`);
|
|
76
65
|
console.error(` Available: ${Object.keys(templates).join(", ")}\n`);
|
|
77
66
|
process.exit(1);
|
|
78
67
|
}
|
|
79
|
-
|
|
80
|
-
if (name.includes("..")) {
|
|
81
|
-
console.error("\n Invalid project name: must not contain '..'.\n");
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
const cwd = process.cwd();
|
|
85
|
-
const dir = isAbsolute(name) ? name : join(cwd, name);
|
|
86
|
-
const resolved = resolve(dir);
|
|
87
|
-
// Ensure the resolved path is a child of cwd
|
|
88
|
-
if (!resolved.startsWith(cwd + "/") && resolved !== cwd) {
|
|
89
|
-
console.error("\n Invalid project name: resolved path must be inside the current directory.\n");
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
const projectName = basename(dir);
|
|
68
|
+
const { dir, projectName } = validateTarget(name);
|
|
93
69
|
console.log(`\n Creating Celsian project: ${projectName}`);
|
|
94
70
|
console.log(` Template: ${template}`);
|
|
95
71
|
console.log("");
|
|
@@ -115,8 +91,57 @@ function scaffold(name, template, pm) {
|
|
|
115
91
|
}
|
|
116
92
|
console.log("");
|
|
117
93
|
}
|
|
94
|
+
function validateTarget(name) {
|
|
95
|
+
const trimmedName = name.trim();
|
|
96
|
+
if (!trimmedName) {
|
|
97
|
+
console.error("\n Invalid project name: name is required.\n");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
if (trimmedName.split(/[\\/]+/).includes("..")) {
|
|
101
|
+
console.error("\n Invalid project name: must not contain '..'.\n");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
const cwd = resolve(process.cwd());
|
|
105
|
+
const dir = resolve(isAbsolute(trimmedName) ? trimmedName : join(cwd, trimmedName));
|
|
106
|
+
const rel = relative(cwd, dir);
|
|
107
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
|
|
108
|
+
console.error("\n Invalid project name: resolved path must be inside the current directory.\n");
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
if (existsSync(dir)) {
|
|
112
|
+
const entries = readdirSync(dir);
|
|
113
|
+
if (entries.length > 0) {
|
|
114
|
+
console.error("\n Refusing to create project: target directory already exists and is not empty.\n");
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const projectName = sanitizePackageName(basename(dir));
|
|
119
|
+
if (!projectName) {
|
|
120
|
+
console.error("\n Invalid project name: cannot derive a valid package name.\n");
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
return { dir, projectName };
|
|
124
|
+
}
|
|
125
|
+
function sanitizePackageName(name) {
|
|
126
|
+
return name
|
|
127
|
+
.trim()
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.replace(/^[._-]+/, "")
|
|
130
|
+
.replace(/[._\s]+/g, "-")
|
|
131
|
+
.replace(/[^a-z0-9-]/g, "")
|
|
132
|
+
.replace(/-+/g, "-")
|
|
133
|
+
.replace(/-+$/g, "");
|
|
134
|
+
}
|
|
118
135
|
// ─── Main ───
|
|
119
136
|
async function main() {
|
|
137
|
+
const args = process.argv.slice(2);
|
|
138
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
139
|
+
printUsage();
|
|
140
|
+
process.exit(0);
|
|
141
|
+
}
|
|
142
|
+
const templateFlag = args.indexOf("--template");
|
|
143
|
+
const templateArg = templateFlag !== -1 ? args[templateFlag + 1] : undefined;
|
|
144
|
+
const nameArg = args.find((a) => !a.startsWith("--") && (templateFlag === -1 || args.indexOf(a) !== templateFlag + 1));
|
|
120
145
|
// If both name and template are provided via CLI args, skip interactive mode
|
|
121
146
|
if (nameArg) {
|
|
122
147
|
const template = templateArg ?? "full";
|
|
@@ -148,8 +173,10 @@ function printUsage() {
|
|
|
148
173
|
console.log(" Run without arguments for interactive mode.");
|
|
149
174
|
console.log("");
|
|
150
175
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
176
|
+
if (process.argv[1] && realpathSync(resolve(process.argv[1])) === fileURLToPath(import.meta.url)) {
|
|
177
|
+
main().catch((err) => {
|
|
178
|
+
console.error(err);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
155
182
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,sCAAsC;AACtC,iEAAiE;AAEjE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"full.d.ts","sourceRoot":"","sources":["../../src/templates/full.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"full.d.ts","sourceRoot":"","sources":["../../src/templates/full.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAq4B/C,CAAC"}
|
package/dist/templates/full.js
CHANGED
|
@@ -11,7 +11,7 @@ export const fullTemplate = {
|
|
|
11
11
|
lint: "npx tsc --noEmit",
|
|
12
12
|
},
|
|
13
13
|
dependencies: {
|
|
14
|
-
celsian: "^0.3.
|
|
14
|
+
celsian: "^0.3.10",
|
|
15
15
|
"@celsian/core": "^0.3.9",
|
|
16
16
|
"@celsian/jwt": "^0.3.9",
|
|
17
17
|
"@celsian/rpc": "^0.3.8",
|
|
@@ -248,8 +248,8 @@ export default function healthRoutes(): PluginFunction {
|
|
|
248
248
|
// Full REST: GET (list), POST (create), GET/:id, PUT/:id, DELETE/:id
|
|
249
249
|
|
|
250
250
|
import { Type } from '@sinclair/typebox';
|
|
251
|
-
import type { PluginFunction } from '@celsian/core';
|
|
252
|
-
import type { User } from '../types.js';
|
|
251
|
+
import type { CelsianReply, CelsianRequest, PluginFunction } from '@celsian/core';
|
|
252
|
+
import type { UpdateUserInput, User, CreateUserInput } from '../types.js';
|
|
253
253
|
import { db } from '../plugins/database.js';
|
|
254
254
|
import { requireAuth } from '../plugins/auth.js';
|
|
255
255
|
|
|
@@ -275,7 +275,7 @@ export default function userRoutes(): PluginFunction {
|
|
|
275
275
|
app.post('/users', {
|
|
276
276
|
schema: { body: CreateUserSchema },
|
|
277
277
|
}, (req, reply) => {
|
|
278
|
-
const { name, email } = req.parsedBody;
|
|
278
|
+
const { name, email } = req.parsedBody as CreateUserInput;
|
|
279
279
|
const user: User = {
|
|
280
280
|
id: db.generateId(),
|
|
281
281
|
name,
|
|
@@ -300,7 +300,7 @@ export default function userRoutes(): PluginFunction {
|
|
|
300
300
|
}, (req, reply) => {
|
|
301
301
|
const user = db.users.get(req.params.id);
|
|
302
302
|
if (!user) return reply.status(404).json({ error: 'User not found' });
|
|
303
|
-
const updates = req.parsedBody;
|
|
303
|
+
const updates = req.parsedBody as UpdateUserInput;
|
|
304
304
|
if (updates.name !== undefined) user.name = updates.name;
|
|
305
305
|
if (updates.email !== undefined) user.email = updates.email;
|
|
306
306
|
db.users.set(user.id, user);
|
|
@@ -315,7 +315,7 @@ export default function userRoutes(): PluginFunction {
|
|
|
315
315
|
handler(req: CelsianRequest, reply: CelsianReply) {
|
|
316
316
|
const existed = db.users.delete(req.params.id);
|
|
317
317
|
if (!existed) return reply.status(404).json({ error: 'User not found' });
|
|
318
|
-
return reply.status(204).
|
|
318
|
+
return reply.status(204).send(null);
|
|
319
319
|
},
|
|
320
320
|
});
|
|
321
321
|
};
|
|
@@ -333,21 +333,24 @@ import type { PluginFunction } from '@celsian/core';
|
|
|
333
333
|
const appRouter = router({
|
|
334
334
|
greeting: {
|
|
335
335
|
hello: procedure
|
|
336
|
-
.input
|
|
336
|
+
.input(Type.Object({ name: Type.String() }))
|
|
337
337
|
.query(({ input }) => {
|
|
338
|
-
|
|
338
|
+
const data = input as { name: string };
|
|
339
|
+
return { message: \`Hello, \${data.name}!\` };
|
|
339
340
|
}),
|
|
340
341
|
},
|
|
341
342
|
math: {
|
|
342
343
|
add: procedure
|
|
343
|
-
.input
|
|
344
|
+
.input(Type.Object({ a: Type.Number(), b: Type.Number() }))
|
|
344
345
|
.query(({ input }) => {
|
|
345
|
-
|
|
346
|
+
const data = input as { a: number; b: number };
|
|
347
|
+
return { result: data.a + data.b };
|
|
346
348
|
}),
|
|
347
349
|
multiply: procedure
|
|
348
|
-
.input
|
|
350
|
+
.input(Type.Object({ a: Type.Number(), b: Type.Number() }))
|
|
349
351
|
.mutation(({ input }) => {
|
|
350
|
-
|
|
352
|
+
const data = input as { a: number; b: number };
|
|
353
|
+
return { result: data.a * data.b };
|
|
351
354
|
}),
|
|
352
355
|
},
|
|
353
356
|
system: {
|
|
@@ -506,18 +509,19 @@ import healthRoutes from '../src/routes/health.js';
|
|
|
506
509
|
import userRoutes from '../src/routes/users.js';
|
|
507
510
|
import rpcRoutes from '../src/routes/rpc.js';
|
|
508
511
|
|
|
509
|
-
function createTestApp() {
|
|
512
|
+
async function createTestApp() {
|
|
510
513
|
const app = createApp();
|
|
511
514
|
// Register just what we need — skip auth/security for tests
|
|
512
|
-
app.register(healthRoutes());
|
|
513
|
-
app.register(userRoutes());
|
|
514
|
-
app.register(rpcRoutes());
|
|
515
|
+
await app.register(healthRoutes());
|
|
516
|
+
await app.register(userRoutes());
|
|
517
|
+
await app.register(rpcRoutes());
|
|
518
|
+
await app.ready();
|
|
515
519
|
return app;
|
|
516
520
|
}
|
|
517
521
|
|
|
518
522
|
describe('Health', () => {
|
|
519
523
|
it('GET /health returns status ok', async () => {
|
|
520
|
-
const app = createTestApp();
|
|
524
|
+
const app = await createTestApp();
|
|
521
525
|
const res = await app.inject({ url: '/health' });
|
|
522
526
|
expect(res.status).toBe(200);
|
|
523
527
|
const body = await res.json();
|
|
@@ -529,7 +533,7 @@ describe('Health', () => {
|
|
|
529
533
|
|
|
530
534
|
describe('Users CRUD', () => {
|
|
531
535
|
it('GET /users returns the seeded user', async () => {
|
|
532
|
-
const app = createTestApp();
|
|
536
|
+
const app = await createTestApp();
|
|
533
537
|
const res = await app.inject({ url: '/users' });
|
|
534
538
|
expect(res.status).toBe(200);
|
|
535
539
|
const users = await res.json();
|
|
@@ -539,7 +543,7 @@ describe('Users CRUD', () => {
|
|
|
539
543
|
});
|
|
540
544
|
|
|
541
545
|
it('POST /users creates a new user', async () => {
|
|
542
|
-
const app = createTestApp();
|
|
546
|
+
const app = await createTestApp();
|
|
543
547
|
const res = await app.inject({
|
|
544
548
|
method: 'POST',
|
|
545
549
|
url: '/users',
|
|
@@ -554,7 +558,7 @@ describe('Users CRUD', () => {
|
|
|
554
558
|
});
|
|
555
559
|
|
|
556
560
|
it('GET /users/:id returns a specific user', async () => {
|
|
557
|
-
const app = createTestApp();
|
|
561
|
+
const app = await createTestApp();
|
|
558
562
|
|
|
559
563
|
// Create a user first
|
|
560
564
|
const createRes = await app.inject({
|
|
@@ -572,13 +576,13 @@ describe('Users CRUD', () => {
|
|
|
572
576
|
});
|
|
573
577
|
|
|
574
578
|
it('GET /users/:id returns 404 for unknown user', async () => {
|
|
575
|
-
const app = createTestApp();
|
|
579
|
+
const app = await createTestApp();
|
|
576
580
|
const res = await app.inject({ url: '/users/99999' });
|
|
577
581
|
expect(res.status).toBe(404);
|
|
578
582
|
});
|
|
579
583
|
|
|
580
584
|
it('DELETE /users/:id without auth returns 401', async () => {
|
|
581
|
-
const app = createTestApp();
|
|
585
|
+
const app = await createTestApp();
|
|
582
586
|
const res = await app.inject({ method: 'DELETE', url: '/users/1' });
|
|
583
587
|
// Without the JWT guard registered in test mode, the route handler runs directly.
|
|
584
588
|
// In the full app with auth, this would return 401.
|
|
@@ -589,7 +593,7 @@ describe('Users CRUD', () => {
|
|
|
589
593
|
|
|
590
594
|
describe('RPC', () => {
|
|
591
595
|
it('GET /_rpc/system.ping returns pong', async () => {
|
|
592
|
-
const app = createTestApp();
|
|
596
|
+
const app = await createTestApp();
|
|
593
597
|
const res = await app.inject({ url: '/_rpc/system.ping' });
|
|
594
598
|
expect(res.status).toBe(200);
|
|
595
599
|
const body = await res.json();
|
|
@@ -597,7 +601,7 @@ describe('RPC', () => {
|
|
|
597
601
|
});
|
|
598
602
|
|
|
599
603
|
it('GET /_rpc/greeting.hello returns greeting', async () => {
|
|
600
|
-
const app = createTestApp();
|
|
604
|
+
const app = await createTestApp();
|
|
601
605
|
const res = await app.inject({
|
|
602
606
|
url: '/_rpc/greeting.hello?input=' + encodeURIComponent(JSON.stringify({ name: 'World' })),
|
|
603
607
|
});
|
|
@@ -607,7 +611,7 @@ describe('RPC', () => {
|
|
|
607
611
|
});
|
|
608
612
|
|
|
609
613
|
it('POST /_rpc/math.multiply performs mutation', async () => {
|
|
610
|
-
const app = createTestApp();
|
|
614
|
+
const app = await createTestApp();
|
|
611
615
|
const res = await app.inject({
|
|
612
616
|
method: 'POST',
|
|
613
617
|
url: '/_rpc/math.multiply',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"full.js","sourceRoot":"","sources":["../../src/templates/full.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,cAAc,EAAE,IAAI,CAAC,SAAS,CAC5B;QACE,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE;YACP,GAAG,EAAE,8BAA8B;YACnC,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,oBAAoB;YAC3B,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,kBAAkB;SACzB;QACD,YAAY,EAAE;YACZ,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"full.js","sourceRoot":"","sources":["../../src/templates/full.ts"],"names":[],"mappings":"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"}
|