as-facile-js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/dist/cli/index.js +206 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/templates/health.controller.ts.txt +9 -0
- package/dist/cli/templates/health.payload.ts.txt +3 -0
- package/dist/cli/templates/health.route.ts.txt +6 -0
- package/dist/cli/templates/health.service.ts.txt +9 -0
- package/dist/cli/templates/module.controller.ts.txt +46 -0
- package/dist/cli/templates/module.payload.ts.txt +39 -0
- package/dist/cli/templates/module.route.ts.txt +15 -0
- package/dist/cli/templates/module.service.ts.txt +87 -0
- package/dist/cli/templates/starter.package.json.txt +18 -0
- package/dist/cli/templates/starter.server.ts.txt +11 -0
- package/dist/cli/templates/starter.tsconfig.json.txt +11 -0
- package/dist/core/app.d.ts +16 -0
- package/dist/core/app.d.ts.map +1 -0
- package/dist/core/app.js +84 -0
- package/dist/core/app.js.map +1 -0
- package/dist/core/compose.d.ts +15 -0
- package/dist/core/compose.d.ts.map +1 -0
- package/dist/core/compose.js +43 -0
- package/dist/core/compose.js.map +1 -0
- package/dist/core/response.d.ts +3 -0
- package/dist/core/response.d.ts.map +1 -0
- package/dist/core/response.js +41 -0
- package/dist/core/response.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/json.d.ts +5 -0
- package/dist/middlewares/json.d.ts.map +1 -0
- package/dist/middlewares/json.js +38 -0
- package/dist/middlewares/json.js.map +1 -0
- package/dist/router/match.d.ts +8 -0
- package/dist/router/match.d.ts.map +1 -0
- package/dist/router/match.js +27 -0
- package/dist/router/match.js.map +1 -0
- package/dist/router/router.d.ts +16 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +72 -0
- package/dist/router/router.js.map +1 -0
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
by Abdul Salam
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="https://placehold.co/200x200?text=Facile" alt="Facile logo" width="200" height="200" />
|
|
5
|
+
|
|
6
|
+
<h1>Facile.js</h1>
|
|
7
|
+
<p>Lightweight, minimal API framework with a friendly CLI.</p>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
- ⚡ Lightweight HTTP framework with middleware and routing.
|
|
12
|
+
- 🧩 Simple router with path params and middleware chaining.
|
|
13
|
+
- 🧰 Built-in CLI to scaffold a new project or generate modules.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
```bash
|
|
17
|
+
npm install facile-js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick start
|
|
21
|
+
```ts
|
|
22
|
+
import { createApp, Router, json } from "facile-js";
|
|
23
|
+
|
|
24
|
+
const app = createApp();
|
|
25
|
+
app.use(json());
|
|
26
|
+
|
|
27
|
+
const router = Router();
|
|
28
|
+
router.get("/health", (req, res) => {
|
|
29
|
+
res.json({ ok: true });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
app.use(router);
|
|
33
|
+
|
|
34
|
+
app.listen(3000, () => {
|
|
35
|
+
console.log("Server running on http://localhost:3000");
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## CLI usage
|
|
40
|
+
### Initialize a new project
|
|
41
|
+
```bash
|
|
42
|
+
npx facile-js init my-api
|
|
43
|
+
# or shorthand
|
|
44
|
+
npx facile-js my-api
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Generate a module
|
|
48
|
+
```bash
|
|
49
|
+
cd my-api
|
|
50
|
+
npx facile-js -g users
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### CLI help / version
|
|
54
|
+
```bash
|
|
55
|
+
npx facile-js --help
|
|
56
|
+
npx facile-js --version
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Project structure (generated)
|
|
60
|
+
```
|
|
61
|
+
my-api/
|
|
62
|
+
src/
|
|
63
|
+
server.ts
|
|
64
|
+
modules/
|
|
65
|
+
# generated by default
|
|
66
|
+
health/
|
|
67
|
+
health.controller.ts
|
|
68
|
+
health.payload.ts
|
|
69
|
+
health.route.ts
|
|
70
|
+
health.service.ts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Scripts (generated project)
|
|
74
|
+
```bash
|
|
75
|
+
npm run dev
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
ISC
|
|
80
|
+
by Abdul Salam
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, promises as fs } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { dirname, join, relative } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
async function main() {
|
|
8
|
+
const args = parseArgs(process.argv.slice(2));
|
|
9
|
+
if (args.cmd === "help") {
|
|
10
|
+
printHelp();
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
if (args.cmd === "version") {
|
|
14
|
+
console.log(getVersion());
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
if (args.cmd === "init") {
|
|
18
|
+
await initProject(args.projectName);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (args.cmd === "generate") {
|
|
22
|
+
await generateModule(args.name);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function parseArgs(argv) {
|
|
27
|
+
// Supported:
|
|
28
|
+
// npx facile-js init my-app
|
|
29
|
+
// npx facile-js my-app (default = init)
|
|
30
|
+
// npx facile-js -g users
|
|
31
|
+
// npx facile-js --generate users
|
|
32
|
+
if (argv.length === 0)
|
|
33
|
+
return { cmd: "help" };
|
|
34
|
+
const first = argv[0];
|
|
35
|
+
if (first === "-h" || first === "--help")
|
|
36
|
+
return { cmd: "help" };
|
|
37
|
+
if (first === "-v" || first === "--version")
|
|
38
|
+
return { cmd: "version" };
|
|
39
|
+
if (first === "init") {
|
|
40
|
+
const projectName = argv[1];
|
|
41
|
+
if (!projectName)
|
|
42
|
+
return { cmd: "help" };
|
|
43
|
+
return { cmd: "init", projectName };
|
|
44
|
+
}
|
|
45
|
+
for (let i = 0; i < argv.length; i++) {
|
|
46
|
+
const a = argv[i];
|
|
47
|
+
if (a === "-g" || a === "--generate") {
|
|
48
|
+
const name = argv[i + 1];
|
|
49
|
+
if (!name) {
|
|
50
|
+
return { cmd: "help" };
|
|
51
|
+
}
|
|
52
|
+
return { cmd: "generate", name };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!first) {
|
|
56
|
+
return { cmd: "help" };
|
|
57
|
+
}
|
|
58
|
+
// default shorthand: `npx facile-js my-app`
|
|
59
|
+
if (!first.startsWith("-")) {
|
|
60
|
+
return { cmd: "init", projectName: first };
|
|
61
|
+
}
|
|
62
|
+
return { cmd: "help" };
|
|
63
|
+
}
|
|
64
|
+
function printHelp() {
|
|
65
|
+
console.log(`
|
|
66
|
+
facile-js CLI
|
|
67
|
+
|
|
68
|
+
Usage:
|
|
69
|
+
npx facile-js init <project-name>
|
|
70
|
+
npx facile-js <project-name> (shorthand init)
|
|
71
|
+
npx facile-js -g <module-name>
|
|
72
|
+
npx facile-js --version
|
|
73
|
+
|
|
74
|
+
Examples:
|
|
75
|
+
npx facile-js init my-api
|
|
76
|
+
npx facile-js my-api
|
|
77
|
+
cd my-api && npx facile-js -g users
|
|
78
|
+
`.trim());
|
|
79
|
+
}
|
|
80
|
+
/* ---------------- INIT PROJECT ---------------- */
|
|
81
|
+
async function initProject(projectNameRaw) {
|
|
82
|
+
const projectName = normalizeName(projectNameRaw);
|
|
83
|
+
const root = join(process.cwd(), projectName);
|
|
84
|
+
await ensureDir(root);
|
|
85
|
+
await ensureDir(join(root, "src"));
|
|
86
|
+
await ensureDir(join(root, "src", "modules"));
|
|
87
|
+
await ensureDir(join(root, "src", "modules", "health"));
|
|
88
|
+
// starter files
|
|
89
|
+
await writeFromTemplate("starter.package.json.txt", join(root, "package.json"), {
|
|
90
|
+
__project__: projectName
|
|
91
|
+
});
|
|
92
|
+
await writeFromTemplate("starter.tsconfig.json.txt", join(root, "tsconfig.json"), {});
|
|
93
|
+
await writeFromTemplate("starter.server.ts.txt", join(root, "src", "server.ts"), {});
|
|
94
|
+
// health module
|
|
95
|
+
await writeFromTemplate("health.route.ts.txt", join(root, "src", "modules", "health", "health.route.ts"), {});
|
|
96
|
+
await writeFromTemplate("health.controller.ts.txt", join(root, "src", "modules", "health", "health.controller.ts"), {});
|
|
97
|
+
await writeFromTemplate("health.service.ts.txt", join(root, "src", "modules", "health", "health.service.ts"), {});
|
|
98
|
+
await writeFromTemplate("health.payload.ts.txt", join(root, "src", "modules", "health", "health.payload.ts"), {});
|
|
99
|
+
console.log(`\nDone. Project created: ${relFromCwd(root)}`);
|
|
100
|
+
console.log(`\nNext:\n cd ${projectName}\n npm i\n npm run dev\n`);
|
|
101
|
+
}
|
|
102
|
+
/* ---------------- GENERATE MODULE ---------------- */
|
|
103
|
+
async function generateModule(rawName) {
|
|
104
|
+
const name = normalizeName(rawName.trim());
|
|
105
|
+
const pascal = toPascalCase(name);
|
|
106
|
+
const baseDir = join(process.cwd(), "src", "modules", name);
|
|
107
|
+
await ensureDir(baseDir);
|
|
108
|
+
await writeFromTemplate("module.route.ts.txt", join(baseDir, `${name}.route.ts`), {
|
|
109
|
+
__name__: name,
|
|
110
|
+
__Pascal__: pascal
|
|
111
|
+
});
|
|
112
|
+
await writeFromTemplate("module.controller.ts.txt", join(baseDir, `${name}.controller.ts`), {
|
|
113
|
+
__name__: name,
|
|
114
|
+
__Pascal__: pascal
|
|
115
|
+
});
|
|
116
|
+
await writeFromTemplate("module.service.ts.txt", join(baseDir, `${name}.service.ts`), {
|
|
117
|
+
__name__: name,
|
|
118
|
+
__Pascal__: pascal
|
|
119
|
+
});
|
|
120
|
+
await writeFromTemplate("module.payload.ts.txt", join(baseDir, `${name}.payload.ts`), {
|
|
121
|
+
__name__: name,
|
|
122
|
+
__Pascal__: pascal
|
|
123
|
+
});
|
|
124
|
+
console.log(`\nDone. Module created at: ${relFromCwd(baseDir)}`);
|
|
125
|
+
}
|
|
126
|
+
/* ---------------- Template Loader ---------------- */
|
|
127
|
+
function templatesDirPath() {
|
|
128
|
+
// IMPORTANT:
|
|
129
|
+
// When compiled, dist/cli/index.js should live next to dist/cli/templates/*
|
|
130
|
+
const cliDir = dirname(fileURLToPath(import.meta.url));
|
|
131
|
+
// 1) packaged mode: dist/cli/templates
|
|
132
|
+
const packaged = join(cliDir, "templates");
|
|
133
|
+
if (existsSync(packaged))
|
|
134
|
+
return packaged;
|
|
135
|
+
// 2) dev mode (running TS directly): src/cli/templates
|
|
136
|
+
const dev = join(process.cwd(), "src", "cli", "templates");
|
|
137
|
+
if (existsSync(dev))
|
|
138
|
+
return dev;
|
|
139
|
+
throw new Error("Unable to locate CLI templates. Did you run the build step?");
|
|
140
|
+
}
|
|
141
|
+
async function writeFromTemplate(templateFile, outPath, vars) {
|
|
142
|
+
const tplPath = join(templatesDirPath(), templateFile);
|
|
143
|
+
// Don’t overwrite
|
|
144
|
+
if (await fileExists(outPath)) {
|
|
145
|
+
console.log(`skip: ${relFromCwd(outPath)} (already exists)`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const tpl = await fs.readFile(tplPath, "utf8");
|
|
149
|
+
const rendered = render(tpl, vars);
|
|
150
|
+
await ensureDir(join(outPath, ".."));
|
|
151
|
+
await fs.writeFile(outPath, rendered, "utf8");
|
|
152
|
+
console.log(`create: ${relFromCwd(outPath)}`);
|
|
153
|
+
}
|
|
154
|
+
function render(tpl, vars) {
|
|
155
|
+
let out = tpl;
|
|
156
|
+
for (const [k, v] of Object.entries(vars))
|
|
157
|
+
out = out.replaceAll(k, v);
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
/* ---------------- Utils ---------------- */
|
|
161
|
+
function normalizeName(input) {
|
|
162
|
+
return input
|
|
163
|
+
.trim()
|
|
164
|
+
.toLowerCase()
|
|
165
|
+
.replace(/[^a-z0-9\-_.]/g, "-")
|
|
166
|
+
.replace(/-+/g, "-")
|
|
167
|
+
.replace(/^-|-$/g, "");
|
|
168
|
+
}
|
|
169
|
+
function toPascalCase(name) {
|
|
170
|
+
return name
|
|
171
|
+
.replace(/[_\-.]+/g, " ")
|
|
172
|
+
.split(" ")
|
|
173
|
+
.filter(Boolean)
|
|
174
|
+
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
175
|
+
.join("");
|
|
176
|
+
}
|
|
177
|
+
async function ensureDir(p) {
|
|
178
|
+
await fs.mkdir(p, { recursive: true });
|
|
179
|
+
}
|
|
180
|
+
async function fileExists(p) {
|
|
181
|
+
try {
|
|
182
|
+
await fs.access(p);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function relFromCwd(p) {
|
|
190
|
+
return relative(process.cwd(), p);
|
|
191
|
+
}
|
|
192
|
+
function getVersion() {
|
|
193
|
+
try {
|
|
194
|
+
const require = createRequire(import.meta.url);
|
|
195
|
+
const pkg = require("../../package.json");
|
|
196
|
+
return pkg.version ?? "unknown";
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return "unknown";
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
main().catch((err) => {
|
|
203
|
+
console.error("CLI error:", err);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
});
|
|
206
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Req, Res } from "facile-js";
|
|
2
|
+
import { __Pascal__Service } from "./__name__.service";
|
|
3
|
+
import {
|
|
4
|
+
parseCreatePayload,
|
|
5
|
+
parseReplacePayload,
|
|
6
|
+
parseUpdatePayload
|
|
7
|
+
} from "./__name__.payload";
|
|
8
|
+
|
|
9
|
+
export class __Pascal__Controller {
|
|
10
|
+
static async list(req: Req, res: Res) {
|
|
11
|
+
const data = await __Pascal__Service.list();
|
|
12
|
+
return res.json({ data });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static async getById(req: Req, res: Res) {
|
|
16
|
+
const item = await __Pascal__Service.getById(req.params.id);
|
|
17
|
+
if (!item) return res.status(404).json({ message: "__Pascal__ not found" });
|
|
18
|
+
return res.json({ data: item });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static async create(req: Req, res: Res) {
|
|
22
|
+
const payload = parseCreatePayload(req.body);
|
|
23
|
+
const created = await __Pascal__Service.create(payload);
|
|
24
|
+
return res.status(201).json({ data: created });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static async replace(req: Req, res: Res) {
|
|
28
|
+
const payload = parseReplacePayload(req.body);
|
|
29
|
+
const updated = await __Pascal__Service.replace(req.params.id, payload);
|
|
30
|
+
if (!updated) return res.status(404).json({ message: "__Pascal__ not found" });
|
|
31
|
+
return res.json({ data: updated });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static async update(req: Req, res: Res) {
|
|
35
|
+
const payload = parseUpdatePayload(req.body);
|
|
36
|
+
const updated = await __Pascal__Service.update(req.params.id, payload);
|
|
37
|
+
if (!updated) return res.status(404).json({ message: "__Pascal__ not found" });
|
|
38
|
+
return res.json({ data: updated });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static async remove(req: Req, res: Res) {
|
|
42
|
+
const ok = await __Pascal__Service.remove(req.params.id);
|
|
43
|
+
if (!ok) return res.status(404).json({ message: "__Pascal__ not found" });
|
|
44
|
+
return res.status(204).send();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type CreatePayload = {
|
|
2
|
+
// TODO: define fields
|
|
3
|
+
// example:
|
|
4
|
+
// name: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type ReplacePayload = {
|
|
8
|
+
// PUT: typically full replace.
|
|
9
|
+
// Define required fields here.
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type UpdatePayload = Partial<ReplacePayload>; // PATCH: partial update
|
|
13
|
+
|
|
14
|
+
function isObject(v: unknown): v is Record<string, unknown> {
|
|
15
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function parseCreatePayload(body: unknown): CreatePayload {
|
|
19
|
+
if (!isObject(body)) throw badReq("Body must be a JSON object");
|
|
20
|
+
// TODO: validate required fields
|
|
21
|
+
return body as CreatePayload;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function parseReplacePayload(body: unknown): ReplacePayload {
|
|
25
|
+
if (!isObject(body)) throw badReq("Body must be a JSON object");
|
|
26
|
+
// TODO: validate required fields for PUT
|
|
27
|
+
return body as ReplacePayload;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function parseUpdatePayload(body: unknown): UpdatePayload {
|
|
31
|
+
if (!isObject(body)) throw badReq("Body must be a JSON object");
|
|
32
|
+
return body as UpdatePayload;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function badReq(message: string) {
|
|
36
|
+
const err = new Error(message);
|
|
37
|
+
(err as any).status = 400;
|
|
38
|
+
return err;
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Router } from "facile-js";
|
|
2
|
+
import { __Pascal__Controller } from "./__name__.controller";
|
|
3
|
+
|
|
4
|
+
export const __name__Router = Router();
|
|
5
|
+
|
|
6
|
+
// Base: /__name__
|
|
7
|
+
__name__Router.get("/__name__", __Pascal__Controller.list);
|
|
8
|
+
__name__Router.get("/__name__/:id", __Pascal__Controller.getById);
|
|
9
|
+
|
|
10
|
+
__name__Router.post("/__name__", __Pascal__Controller.create);
|
|
11
|
+
|
|
12
|
+
__name__Router.put("/__name__/:id", __Pascal__Controller.replace);
|
|
13
|
+
__name__Router.patch("/__name__/:id", __Pascal__Controller.update);
|
|
14
|
+
|
|
15
|
+
__name__Router.delete("/__name__/:id", __Pascal__Controller.remove);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { CreatePayload, ReplacePayload, UpdatePayload } from "./__name__.payload";
|
|
2
|
+
|
|
3
|
+
export type __Pascal__Entity = {
|
|
4
|
+
id: string;
|
|
5
|
+
createdAt: string;
|
|
6
|
+
updatedAt: string;
|
|
7
|
+
} & Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
// In-memory store (replace with DB later)
|
|
10
|
+
const db: __Pascal__Entity[] = [];
|
|
11
|
+
|
|
12
|
+
function nowISO() {
|
|
13
|
+
return new Date().toISOString();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function newId() {
|
|
17
|
+
return String(Date.now()) + Math.random().toString(16).slice(2);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class __Pascal__Service {
|
|
21
|
+
static async list() {
|
|
22
|
+
return db;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static async getById(id: string) {
|
|
26
|
+
return db.find(x => x.id === id) ?? null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static async create(payload: CreatePayload) {
|
|
30
|
+
const t = nowISO();
|
|
31
|
+
const item: __Pascal__Entity = {
|
|
32
|
+
id: newId(),
|
|
33
|
+
createdAt: t,
|
|
34
|
+
updatedAt: t,
|
|
35
|
+
...payload
|
|
36
|
+
};
|
|
37
|
+
db.push(item);
|
|
38
|
+
|
|
39
|
+
return item;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static async replace(id: string, payload: ReplacePayload) {
|
|
43
|
+
const idx = db.findIndex(x => x.id === id);
|
|
44
|
+
if (idx === -1) return null;
|
|
45
|
+
|
|
46
|
+
const t = nowISO();
|
|
47
|
+
const prev = db[idx];
|
|
48
|
+
|
|
49
|
+
const next: __Pascal__Entity = {
|
|
50
|
+
...prev,
|
|
51
|
+
...payload,
|
|
52
|
+
id,
|
|
53
|
+
updatedAt: t
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
db[idx] = next;
|
|
57
|
+
return next;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static async update(id: string, payload: UpdatePayload) {
|
|
61
|
+
const idx = db.findIndex(x => x.id === id);
|
|
62
|
+
if (idx === -1) return null;
|
|
63
|
+
|
|
64
|
+
const t = nowISO();
|
|
65
|
+
const prev = db[idx];
|
|
66
|
+
|
|
67
|
+
const next: __Pascal__Entity = {
|
|
68
|
+
...prev,
|
|
69
|
+
...payload,
|
|
70
|
+
id,
|
|
71
|
+
updatedAt: t
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
db[idx] = next;
|
|
75
|
+
return next;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static async remove(id: string) {
|
|
79
|
+
const before = db.length;
|
|
80
|
+
const after = db.filter(x => x.id !== id);
|
|
81
|
+
|
|
82
|
+
db.length = 0;
|
|
83
|
+
db.push(...after);
|
|
84
|
+
|
|
85
|
+
return after.length !== before;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__project__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "tsx watch src/server.ts",
|
|
7
|
+
"start": "tsx src/server.ts",
|
|
8
|
+
"typecheck": "tsc --noEmit"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"facile-js": "^0.0.1"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^22.0.0",
|
|
15
|
+
"typescript": "^5.0.0",
|
|
16
|
+
"tsx": "^4.0.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createApp, json } from "facile-js";
|
|
2
|
+
import { healthRouter } from "./modules/health/health.route";
|
|
3
|
+
|
|
4
|
+
const app = createApp();
|
|
5
|
+
|
|
6
|
+
app.use(json());
|
|
7
|
+
app.use(healthRouter);
|
|
8
|
+
|
|
9
|
+
app.listen(3000, () => {
|
|
10
|
+
console.log("Server running on http://localhost:3000");
|
|
11
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { type Middleware, type ErrorMiddleware } from "./compose";
|
|
3
|
+
import { type FacileRouter } from "../router/router";
|
|
4
|
+
export type App = {
|
|
5
|
+
use(path: string, fn: Middleware | ErrorMiddleware | FacileRouter): App;
|
|
6
|
+
use(fn: Middleware | ErrorMiddleware | FacileRouter): App;
|
|
7
|
+
get(path: string, ...h: Middleware[]): App;
|
|
8
|
+
post(path: string, ...h: Middleware[]): App;
|
|
9
|
+
put(path: string, ...h: Middleware[]): App;
|
|
10
|
+
patch(path: string, ...h: Middleware[]): App;
|
|
11
|
+
delete(path: string, ...h: Middleware[]): App;
|
|
12
|
+
router: FacileRouter;
|
|
13
|
+
listen(port: number, cb?: () => void): http.Server;
|
|
14
|
+
};
|
|
15
|
+
export declare function createApp(): App;
|
|
16
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAW,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAG3E,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAM7D,MAAM,MAAM,GAAG,GAAG;IACd,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,eAAe,GAAG,YAAY,GAAG,GAAG,CAAC;IACxE,GAAG,CAAC,EAAE,EAAE,UAAU,GAAG,eAAe,GAAG,YAAY,GAAG,GAAG,CAAC;IAE1D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAC5C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAC3C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAC7C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAE9C,MAAM,EAAE,YAAY,CAAC;IAErB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;CACtD,CAAC;AAEF,wBAAgB,SAAS,IAAI,GAAG,CA+F/B"}
|
package/dist/core/app.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import { compose } from "./compose";
|
|
3
|
+
import { enhanceResponse } from "./response";
|
|
4
|
+
import { Router } from "../router/router";
|
|
5
|
+
export function createApp() {
|
|
6
|
+
const layers = [];
|
|
7
|
+
const router = Router();
|
|
8
|
+
let routerMounted = false;
|
|
9
|
+
const addLayer = (path, fn) => {
|
|
10
|
+
layers.push({
|
|
11
|
+
path,
|
|
12
|
+
fn,
|
|
13
|
+
isErrorHandler: fn.length === 4
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
const app = {
|
|
17
|
+
use(arg1, arg2) {
|
|
18
|
+
// app.use(fn)
|
|
19
|
+
if (typeof arg1 === "function" || (arg1 && typeof arg1.handle === "function")) {
|
|
20
|
+
const fnOrRouter = arg1;
|
|
21
|
+
// mount router
|
|
22
|
+
if (fnOrRouter && typeof fnOrRouter.handle === "function") {
|
|
23
|
+
routerMounted = true;
|
|
24
|
+
addLayer("", (req, res, next) => fnOrRouter.handle(req, res, next));
|
|
25
|
+
return app;
|
|
26
|
+
}
|
|
27
|
+
addLayer("", fnOrRouter);
|
|
28
|
+
return app;
|
|
29
|
+
}
|
|
30
|
+
// app.use("/prefix", fnOrRouter)
|
|
31
|
+
const prefix = String(arg1 || "");
|
|
32
|
+
const fnOrRouter = arg2;
|
|
33
|
+
if (fnOrRouter && typeof fnOrRouter.handle === "function") {
|
|
34
|
+
routerMounted = true;
|
|
35
|
+
addLayer(prefix, (req, res, next) => fnOrRouter.handle(req, res, next));
|
|
36
|
+
return app;
|
|
37
|
+
}
|
|
38
|
+
addLayer(prefix, fnOrRouter);
|
|
39
|
+
return app;
|
|
40
|
+
},
|
|
41
|
+
get(path, ...h) { router.get(path, ...h); return app; },
|
|
42
|
+
post(path, ...h) { router.post(path, ...h); return app; },
|
|
43
|
+
put(path, ...h) { router.put(path, ...h); return app; },
|
|
44
|
+
patch(path, ...h) { router.patch(path, ...h); return app; },
|
|
45
|
+
delete(path, ...h) { router.delete(path, ...h); return app; },
|
|
46
|
+
router,
|
|
47
|
+
listen(port, cb) {
|
|
48
|
+
// If user used app.get/post/etc, mount internal router automatically (last)
|
|
49
|
+
if (!routerMounted) {
|
|
50
|
+
addLayer("", (req, res, next) => router.handle(req, res, next));
|
|
51
|
+
}
|
|
52
|
+
// default 404 (after everything)
|
|
53
|
+
addLayer("", ((req, res) => {
|
|
54
|
+
if (!res.writableEnded)
|
|
55
|
+
res.status(404).json({ message: "Not Found" });
|
|
56
|
+
}));
|
|
57
|
+
const run = compose(layers);
|
|
58
|
+
const server = http.createServer((rawReq, rawRes) => {
|
|
59
|
+
const req = rawReq;
|
|
60
|
+
const res = enhanceResponse(rawRes);
|
|
61
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
62
|
+
req.path = url.pathname;
|
|
63
|
+
req.query = Object.fromEntries(url.searchParams.entries());
|
|
64
|
+
req.params = {};
|
|
65
|
+
req.body = undefined;
|
|
66
|
+
run(req, res, (err) => {
|
|
67
|
+
if (!err)
|
|
68
|
+
return;
|
|
69
|
+
// respect status if thrown error includes status
|
|
70
|
+
const status = typeof err?.status === "number" ? err.status : 500;
|
|
71
|
+
if (!res.writableEnded) {
|
|
72
|
+
res.status(status).json({
|
|
73
|
+
message: status === 500 ? "Internal Server Error" : "Error",
|
|
74
|
+
error: err?.message ?? String(err)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
return server.listen(port, cb);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return app;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/core/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Next, Req, Res } from "../types";
|
|
2
|
+
export type Middleware = (req: Req, res: Res, next: Next) => void | Promise<void>;
|
|
3
|
+
export type ErrorMiddleware = (err: unknown, req: Req, res: Res, next: Next) => void | Promise<void>;
|
|
4
|
+
type Layer = {
|
|
5
|
+
path?: string;
|
|
6
|
+
fn: Middleware;
|
|
7
|
+
isErrorHandler: false;
|
|
8
|
+
} | {
|
|
9
|
+
path?: string;
|
|
10
|
+
fn: ErrorMiddleware;
|
|
11
|
+
isErrorHandler: true;
|
|
12
|
+
};
|
|
13
|
+
export declare function compose(layers: Layer[]): (req: Req, res: Res, out?: Next) => void;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAErG,KAAK,KAAK,GACJ;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,UAAU,CAAC;IAAC,cAAc,EAAE,KAAK,CAAA;CAAE,GACxD;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,eAAe,CAAC;IAAC,cAAc,EAAE,IAAI,CAAA;CAAE,CAAC;AAEnE,wBAAgB,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,IACf,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,IAAI,UA0CrD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function compose(layers) {
|
|
2
|
+
return function run(req, res, out) {
|
|
3
|
+
let idx = -1;
|
|
4
|
+
const dispatch = (i, err) => {
|
|
5
|
+
if (i <= idx)
|
|
6
|
+
return out?.(new Error("next() called multiple times"));
|
|
7
|
+
idx = i;
|
|
8
|
+
if (i >= layers.length)
|
|
9
|
+
return out?.(err);
|
|
10
|
+
const layer = layers[i];
|
|
11
|
+
// path prefix check
|
|
12
|
+
if (!layer) {
|
|
13
|
+
return dispatch(i + 1, err);
|
|
14
|
+
}
|
|
15
|
+
if (layer.path && !req.path.startsWith(layer.path)) {
|
|
16
|
+
return dispatch(i + 1, err);
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
if (err) {
|
|
20
|
+
// only error handlers should run
|
|
21
|
+
if (layer.isErrorHandler) {
|
|
22
|
+
const ret = layer.fn(err, req, res, (e) => dispatch(i + 1, e));
|
|
23
|
+
if (ret && typeof ret.then === "function")
|
|
24
|
+
ret.catch((e) => dispatch(i + 1, e));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
return dispatch(i + 1, err);
|
|
28
|
+
}
|
|
29
|
+
// normal handlers only
|
|
30
|
+
if (layer.isErrorHandler)
|
|
31
|
+
return dispatch(i + 1);
|
|
32
|
+
const ret = layer.fn(req, res, (e) => dispatch(i + 1, e));
|
|
33
|
+
if (ret && typeof ret.then === "function")
|
|
34
|
+
ret.catch((e) => dispatch(i + 1, e));
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
dispatch(i + 1, e);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
dispatch(0);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/core/compose.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,OAAO,CAAC,MAAe;IACnC,OAAO,SAAS,GAAG,CAAC,GAAQ,EAAE,GAAQ,EAAE,GAAU;QAC9C,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;QAEb,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,GAAa,EAAE,EAAE;YAC1C,IAAI,CAAC,IAAI,GAAG;gBAAE,OAAO,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACtE,GAAG,GAAG,CAAC,CAAC;YAER,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAExB,oBAAoB;YACpB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YAChC,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YAChC,CAAC;YAED,IAAI,CAAC;gBACD,IAAI,GAAG,EAAE,CAAC;oBACN,iCAAiC;oBACjC,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;wBACvB,MAAM,GAAG,GAAI,KAAK,CAAC,EAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBACpF,IAAI,GAAG,IAAI,OAAQ,GAAW,CAAC,IAAI,KAAK,UAAU;4BAAG,GAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wBAC5G,OAAO;oBACX,CAAC;oBACD,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAChC,CAAC;gBAED,uBAAuB;gBACvB,IAAI,KAAK,CAAC,cAAc;oBAAE,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAEjD,MAAM,GAAG,GAAI,KAAK,CAAC,EAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC1E,IAAI,GAAG,IAAI,OAAQ,GAAW,CAAC,IAAI,KAAK,UAAU;oBAAG,GAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAChH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACvB,CAAC;QACL,CAAC,CAAC;QAEF,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CA6C7C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function enhanceResponse(res) {
|
|
2
|
+
res.status = function status(code) {
|
|
3
|
+
res.statusCode = code;
|
|
4
|
+
return res;
|
|
5
|
+
};
|
|
6
|
+
res.set = function set(name, value) {
|
|
7
|
+
res.setHeader(name, value);
|
|
8
|
+
return res;
|
|
9
|
+
};
|
|
10
|
+
res.send = function send(data) {
|
|
11
|
+
if (data == null) {
|
|
12
|
+
res.end();
|
|
13
|
+
return res;
|
|
14
|
+
}
|
|
15
|
+
// Buffer
|
|
16
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
17
|
+
if (!res.getHeader("Content-Type")) {
|
|
18
|
+
res.setHeader("Content-Type", "application/octet-stream");
|
|
19
|
+
}
|
|
20
|
+
res.end(data);
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
// Object => JSON
|
|
24
|
+
if (typeof data === "object")
|
|
25
|
+
return res.json(data);
|
|
26
|
+
// String/number/boolean
|
|
27
|
+
if (!res.getHeader("Content-Type")) {
|
|
28
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
29
|
+
}
|
|
30
|
+
res.end(String(data));
|
|
31
|
+
return res;
|
|
32
|
+
};
|
|
33
|
+
res.json = function json(obj) {
|
|
34
|
+
const body = JSON.stringify(obj);
|
|
35
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
36
|
+
res.end(body);
|
|
37
|
+
return res;
|
|
38
|
+
};
|
|
39
|
+
return res;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sourceRoot":"","sources":["../../src/core/response.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,GAAQ;IACpC,GAAG,CAAC,MAAM,GAAG,SAAS,MAAM,CAAC,IAAY;QACrC,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;QACtB,OAAO,GAAG,CAAC;IACf,CAAC,CAAC;IAEF,GAAG,CAAC,GAAG,GAAG,SAAS,GAAG,CAAC,IAAY,EAAE,KAAa;QAC9C,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC;IACf,CAAC,CAAC;IAEF,GAAG,CAAC,IAAI,GAAG,SAAS,IAAI,CAAC,IAAc;QACnC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACf,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO,GAAG,CAAC;QACf,CAAC;QAED,SAAS;QACT,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;gBACjC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;YAC9D,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACd,OAAO,GAAG,CAAC;QACf,CAAC;QAED,iBAAiB;QACjB,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEpD,wBAAwB;QACxB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YACjC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;QAC/D,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACtB,OAAO,GAAG,CAAC;IACf,CAAC,CAAC;IAEF,GAAG,CAAC,IAAI,GAAG,SAAS,IAAI,CAAC,GAAY;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAC;QACjE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,GAAG,CAAC;IACf,CAAC,CAAC;IAEF,OAAO,GAAG,CAAC;AACf,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/middlewares/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,wBAAgB,IAAI,CAAC,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAwCnE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function json(opts = {}) {
|
|
2
|
+
const limitBytes = opts.limitBytes ?? 1_000_000;
|
|
3
|
+
return (req, res, next) => {
|
|
4
|
+
const type = String(req.headers["content-type"] || "");
|
|
5
|
+
const isJson = type.includes("application/json");
|
|
6
|
+
if (!isJson)
|
|
7
|
+
return next();
|
|
8
|
+
if (req.method === "GET" || req.method === "HEAD")
|
|
9
|
+
return next();
|
|
10
|
+
let size = 0;
|
|
11
|
+
let raw = "";
|
|
12
|
+
req.setEncoding("utf8");
|
|
13
|
+
req.on("data", (chunk) => {
|
|
14
|
+
size += chunk.length;
|
|
15
|
+
if (size > limitBytes) {
|
|
16
|
+
res.status(413).json({ message: "Payload Too Large" });
|
|
17
|
+
req.destroy();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
raw += chunk;
|
|
21
|
+
});
|
|
22
|
+
req.on("end", () => {
|
|
23
|
+
if (!raw) {
|
|
24
|
+
req.body = {};
|
|
25
|
+
return next();
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
req.body = JSON.parse(raw);
|
|
29
|
+
next();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
res.status(400).json({ message: "Invalid JSON" });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
req.on("error", next);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/middlewares/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,IAAI,CAAC,OAAgC,EAAE;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC;IAEhD,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,EAAE,CAAC;QAEjE,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,GAAG,GAAG,EAAE,CAAC;QAEb,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAExB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACrB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC;gBACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBACvD,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO;YACX,CAAC;YACD,GAAG,IAAI,KAAK,CAAC;QACjB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACf,IAAI,CAAC,GAAG,EAAE,CAAC;gBACP,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;gBACd,OAAO,IAAI,EAAE,CAAC;YAClB,CAAC;YACD,IAAI,CAAC;gBACD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC3B,IAAI,EAAE,CAAC;YACX,CAAC;YAAC,MAAM,CAAC;gBACL,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YACtD,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../src/router/match.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;;YACgC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;;YAK7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;EAkBrG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function matchPath(pattern, path) {
|
|
2
|
+
if (pattern === "*" || pattern === path)
|
|
3
|
+
return { ok: true, params: {} };
|
|
4
|
+
const pSeg = trim(pattern).split("/");
|
|
5
|
+
const aSeg = trim(path).split("/");
|
|
6
|
+
if (pSeg.length !== aSeg.length)
|
|
7
|
+
return { ok: false, params: {} };
|
|
8
|
+
const params = {};
|
|
9
|
+
for (let i = 0; i < pSeg.length; i++) {
|
|
10
|
+
const p = pSeg[i];
|
|
11
|
+
const a = aSeg[i];
|
|
12
|
+
if (!p || !a) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (p.startsWith(":")) {
|
|
16
|
+
params[p.slice(1)] = decodeURIComponent(a);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (p !== a)
|
|
20
|
+
return { ok: false, params: {} };
|
|
21
|
+
}
|
|
22
|
+
return { ok: true, params };
|
|
23
|
+
}
|
|
24
|
+
function trim(s) {
|
|
25
|
+
return s.replace(/^\/+|\/+$/g, "");
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match.js","sourceRoot":"","sources":["../../src/router/match.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IACnD,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,MAAM,EAAE,EAA4B,EAAE,CAAC;IAE5G,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,MAAM,EAAE,EAA4B,EAAE,CAAC;IAErG,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAElB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACX,SAAS;QACb,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;YAC3C,SAAS;QACb,CAAC;QACD,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,MAAM,EAAE,EAA4B,EAAE,CAAC;IACrF,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,IAAI,CAAC,CAAS;IACnB,OAAO,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Middleware, ErrorMiddleware } from "../core/compose";
|
|
2
|
+
import type { Next, Req, Res } from "../types";
|
|
3
|
+
type Handler = Middleware | ErrorMiddleware;
|
|
4
|
+
export type FacileRouter = {
|
|
5
|
+
use(path: string, ...handlers: Handler[]): FacileRouter;
|
|
6
|
+
use(...handlers: Handler[]): FacileRouter;
|
|
7
|
+
get(path: string, ...handlers: Handler[]): FacileRouter;
|
|
8
|
+
post(path: string, ...handlers: Handler[]): FacileRouter;
|
|
9
|
+
put(path: string, ...handlers: Handler[]): FacileRouter;
|
|
10
|
+
patch(path: string, ...handlers: Handler[]): FacileRouter;
|
|
11
|
+
delete(path: string, ...handlers: Handler[]): FacileRouter;
|
|
12
|
+
handle(req: Req, res: Res, next: Next): void;
|
|
13
|
+
};
|
|
14
|
+
export declare function Router(): FacileRouter;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAG/C,KAAK,OAAO,GAAG,UAAU,GAAG,eAAe,CAAC;AAQ5C,MAAM,MAAM,YAAY,GAAG;IACvB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IACxD,GAAG,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IAE1C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IACzD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IAC1D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IAE3D,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CAChD,CAAC;AAEF,wBAAgB,MAAM,IAAI,YAAY,CAoDrC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { matchPath } from "./match";
|
|
2
|
+
export function Router() {
|
|
3
|
+
const routes = [];
|
|
4
|
+
const add = (method, path, handlers) => {
|
|
5
|
+
routes.push({ method, path, handlers });
|
|
6
|
+
};
|
|
7
|
+
const router = {
|
|
8
|
+
use(arg1, ...rest) {
|
|
9
|
+
if (typeof arg1 === "string")
|
|
10
|
+
add("USE", arg1, rest);
|
|
11
|
+
else
|
|
12
|
+
add("USE", "", [arg1, ...rest]);
|
|
13
|
+
return router;
|
|
14
|
+
},
|
|
15
|
+
get(path, ...handlers) { add("GET", path, handlers); return router; },
|
|
16
|
+
post(path, ...handlers) { add("POST", path, handlers); return router; },
|
|
17
|
+
put(path, ...handlers) { add("PUT", path, handlers); return router; },
|
|
18
|
+
patch(path, ...handlers) { add("PATCH", path, handlers); return router; },
|
|
19
|
+
delete(path, ...handlers) { add("DELETE", path, handlers); return router; },
|
|
20
|
+
handle(req, res, next) {
|
|
21
|
+
let i = 0;
|
|
22
|
+
const runRoute = (err) => {
|
|
23
|
+
if (err)
|
|
24
|
+
return next(err);
|
|
25
|
+
if (i >= routes.length)
|
|
26
|
+
return next();
|
|
27
|
+
const r = routes[i++];
|
|
28
|
+
if (!r)
|
|
29
|
+
return runRoute();
|
|
30
|
+
const isUse = r.method === "USE";
|
|
31
|
+
if (isUse) {
|
|
32
|
+
// prefix match
|
|
33
|
+
if (r.path && !req.path.startsWith(r.path))
|
|
34
|
+
return runRoute();
|
|
35
|
+
return runHandlers(r.handlers, req, res, runRoute);
|
|
36
|
+
}
|
|
37
|
+
if (r.method !== (req.method || "GET"))
|
|
38
|
+
return runRoute();
|
|
39
|
+
const m = matchPath(r.path, req.path);
|
|
40
|
+
if (!m.ok)
|
|
41
|
+
return runRoute();
|
|
42
|
+
req.params = m.params;
|
|
43
|
+
return runHandlers(r.handlers, req, res, runRoute);
|
|
44
|
+
};
|
|
45
|
+
runRoute();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return router;
|
|
49
|
+
}
|
|
50
|
+
function runHandlers(handlers, req, res, next) {
|
|
51
|
+
let idx = 0;
|
|
52
|
+
const step = (err) => {
|
|
53
|
+
if (err)
|
|
54
|
+
return next(err);
|
|
55
|
+
if (idx >= handlers.length)
|
|
56
|
+
return next();
|
|
57
|
+
const fn = handlers[idx++];
|
|
58
|
+
try {
|
|
59
|
+
// ignore error-handlers in normal chain
|
|
60
|
+
if (fn.length === 4)
|
|
61
|
+
return step();
|
|
62
|
+
const ret = fn(req, res, step);
|
|
63
|
+
if (ret && typeof ret.then === "function")
|
|
64
|
+
ret.catch(step);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
step(e);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
step();
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
export type Next = (err?: unknown) => void;
|
|
3
|
+
export type Req = IncomingMessage & {
|
|
4
|
+
path: string;
|
|
5
|
+
query: Record<string, string>;
|
|
6
|
+
params: Record<string, string>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
};
|
|
9
|
+
export type Res = ServerResponse & {
|
|
10
|
+
status(code: number): Res;
|
|
11
|
+
set(name: string, value: string): Res;
|
|
12
|
+
send(data?: unknown): Res;
|
|
13
|
+
json(obj: unknown): Res;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE3C,MAAM,MAAM,GAAG,GAAG,eAAe,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,cAAc,GAAG;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;IACtC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,GAAG,CAAC;IAC1B,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,CAAC;CAC3B,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "as-facile-js",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Minimalistic API Framework with Strong Schema",
|
|
5
|
+
"type": "module",
|
|
6
|
+
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./cli": {
|
|
16
|
+
"import": "./dist/cli/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
"bin": {
|
|
21
|
+
"facile-js": "dist/cli/index.js",
|
|
22
|
+
"facile": "dist/cli/index.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.json && tsc -p tsconfig.cli.json && node ./scripts/copy-templates.mjs",
|
|
26
|
+
"dev:cli": "node --enable-source-maps dist/cli/index.js",
|
|
27
|
+
"test": "npm run test"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"framework",
|
|
34
|
+
"api",
|
|
35
|
+
"js"
|
|
36
|
+
],
|
|
37
|
+
"author": "@abdulsalam01",
|
|
38
|
+
"license": "ISC",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^25.0.3",
|
|
41
|
+
"typescript": "^5.9.3"
|
|
42
|
+
}
|
|
43
|
+
}
|