fexapi 0.1.0 → 0.1.1
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 +115 -1
- package/dist/cli/args.d.ts +15 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +53 -0
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +40 -0
- package/dist/commands/generate.d.ts +2 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +73 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +66 -0
- package/dist/commands/serve.d.ts +5 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +56 -0
- package/dist/config/generated-spec.d.ts +3 -0
- package/dist/config/generated-spec.d.ts.map +1 -0
- package/dist/config/generated-spec.js +26 -0
- package/dist/config/runtime-config.d.ts +3 -0
- package/dist/config/runtime-config.d.ts.map +1 -0
- package/dist/config/runtime-config.js +97 -0
- package/dist/config/schema-definitions.d.ts +3 -0
- package/dist/config/schema-definitions.d.ts.map +1 -0
- package/dist/config/schema-definitions.js +90 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +4 -0
- package/dist/index.js +23 -386
- package/dist/project/detect.d.ts +4 -0
- package/dist/project/detect.d.ts.map +1 -0
- package/dist/project/detect.js +113 -0
- package/dist/project/paths.d.ts +3 -0
- package/dist/project/paths.d.ts.map +1 -0
- package/dist/project/paths.js +28 -0
- package/dist/server.d.ts +4 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +119 -40
- package/dist/types/config.d.ts +20 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/project.d.ts +7 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +2 -0
- package/package.json +53 -51
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/project/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,GACjC,gBAAgB,MAAM,KACrB,MAAM,GAAG,SAgBX,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,MAAM,GAAG,SAO9C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveProjectRoot = exports.findClosestPackageJson = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const findClosestPackageJson = (startDirectory) => {
|
|
7
|
+
let currentDirectory = startDirectory;
|
|
8
|
+
while (true) {
|
|
9
|
+
const candidate = (0, node_path_1.join)(currentDirectory, "package.json");
|
|
10
|
+
if ((0, node_fs_1.existsSync)(candidate)) {
|
|
11
|
+
return candidate;
|
|
12
|
+
}
|
|
13
|
+
const parentDirectory = (0, node_path_1.dirname)(currentDirectory);
|
|
14
|
+
if (parentDirectory === currentDirectory) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
currentDirectory = parentDirectory;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
exports.findClosestPackageJson = findClosestPackageJson;
|
|
21
|
+
const resolveProjectRoot = () => {
|
|
22
|
+
const packageJsonPath = (0, exports.findClosestPackageJson)(process.cwd());
|
|
23
|
+
if (!packageJsonPath) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
return (0, node_path_1.dirname)(packageJsonPath);
|
|
27
|
+
};
|
|
28
|
+
exports.resolveProjectRoot = resolveProjectRoot;
|
package/dist/server.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { ServerResponse } from "node:http";
|
|
2
2
|
import type { FexapiRoute } from "./schema";
|
|
3
|
+
import type { FexapiRuntimeConfig, FexapiSchemaDefinitions } from "./types/config";
|
|
3
4
|
export type ServerOptions = {
|
|
4
5
|
host?: string;
|
|
5
6
|
port?: number;
|
|
6
7
|
apiSpec?: GeneratedApiSpec;
|
|
8
|
+
runtimeConfig?: FexapiRuntimeConfig;
|
|
9
|
+
schemaDefinitions?: FexapiSchemaDefinitions;
|
|
7
10
|
};
|
|
8
11
|
export type GeneratedApiSpec = {
|
|
9
12
|
port: number;
|
|
10
13
|
routes: FexapiRoute[];
|
|
11
14
|
};
|
|
12
|
-
export declare const startServer: ({ host, port, apiSpec, }?: ServerOptions) => import("http").Server<typeof import("http").IncomingMessage, typeof ServerResponse>;
|
|
15
|
+
export declare const startServer: ({ host, port, apiSpec, runtimeConfig, schemaDefinitions, }?: ServerOptions) => import("http").Server<typeof import("http").IncomingMessage, typeof ServerResponse>;
|
|
13
16
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EAExB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAAC;AAyLF,eAAO,MAAM,WAAW,GAAI,6DAMzB,aAAkB,wFAqGpB,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -5,9 +5,25 @@ const faker_1 = require("@faker-js/faker");
|
|
|
5
5
|
const node_http_1 = require("node:http");
|
|
6
6
|
const DEFAULT_HOST = "127.0.0.1";
|
|
7
7
|
const DEFAULT_PORT = 4000;
|
|
8
|
-
const sendJson = (response, statusCode, payload) => {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const sendJson = (response, statusCode, payload, options) => {
|
|
9
|
+
const send = () => {
|
|
10
|
+
const headers = {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
};
|
|
13
|
+
if (options.cors) {
|
|
14
|
+
headers["Access-Control-Allow-Origin"] = "*";
|
|
15
|
+
headers["Access-Control-Allow-Methods"] =
|
|
16
|
+
"GET,POST,PUT,PATCH,DELETE,OPTIONS";
|
|
17
|
+
headers["Access-Control-Allow-Headers"] = "Content-Type,Authorization";
|
|
18
|
+
}
|
|
19
|
+
response.writeHead(statusCode, headers);
|
|
20
|
+
response.end(JSON.stringify(payload));
|
|
21
|
+
};
|
|
22
|
+
if (options.delay > 0) {
|
|
23
|
+
setTimeout(send, options.delay);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
send();
|
|
11
27
|
};
|
|
12
28
|
const createValueFromField = (field) => {
|
|
13
29
|
switch (field.type) {
|
|
@@ -39,6 +55,62 @@ const createRecordFromRoute = (route) => {
|
|
|
39
55
|
return record;
|
|
40
56
|
}, {});
|
|
41
57
|
};
|
|
58
|
+
const resolveFakerMethod = (path) => {
|
|
59
|
+
const pathParts = path.split(".").filter(Boolean);
|
|
60
|
+
let current = faker_1.faker;
|
|
61
|
+
for (const pathPart of pathParts) {
|
|
62
|
+
if (typeof current !== "object" || current === null) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
current = current[pathPart];
|
|
66
|
+
}
|
|
67
|
+
if (typeof current !== "function") {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
return current;
|
|
71
|
+
};
|
|
72
|
+
const createValueFromSchemaFieldDefinition = (fieldDefinition) => {
|
|
73
|
+
if (fieldDefinition.faker) {
|
|
74
|
+
const fakerMethod = resolveFakerMethod(fieldDefinition.faker);
|
|
75
|
+
if (fakerMethod) {
|
|
76
|
+
return fakerMethod();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
switch (fieldDefinition.type) {
|
|
80
|
+
case "number": {
|
|
81
|
+
const min = typeof fieldDefinition.min === "number" ? fieldDefinition.min : 1;
|
|
82
|
+
const max = typeof fieldDefinition.max === "number" ? fieldDefinition.max : 10000;
|
|
83
|
+
return faker_1.faker.number.int({
|
|
84
|
+
min: Math.min(min, max),
|
|
85
|
+
max: Math.max(min, max),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
case "boolean":
|
|
89
|
+
return faker_1.faker.datatype.boolean();
|
|
90
|
+
case "date":
|
|
91
|
+
return faker_1.faker.date.recent({ days: 30 }).toISOString();
|
|
92
|
+
case "uuid":
|
|
93
|
+
return faker_1.faker.string.uuid();
|
|
94
|
+
case "email":
|
|
95
|
+
return faker_1.faker.internet.email();
|
|
96
|
+
case "url":
|
|
97
|
+
return faker_1.faker.internet.url();
|
|
98
|
+
case "name":
|
|
99
|
+
return faker_1.faker.person.fullName();
|
|
100
|
+
case "phone":
|
|
101
|
+
return faker_1.faker.phone.number();
|
|
102
|
+
case "string":
|
|
103
|
+
default:
|
|
104
|
+
return faker_1.faker.lorem.words({ min: 1, max: 4 });
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const createRecordFromSchemaDefinition = (schemaDefinition) => {
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const [fieldName, fieldDefinition] of Object.entries(schemaDefinition)) {
|
|
110
|
+
result[fieldName] = createValueFromSchemaFieldDefinition(fieldDefinition);
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
42
114
|
const toCollectionKey = (routePath) => {
|
|
43
115
|
const segments = routePath.split("/").filter(Boolean);
|
|
44
116
|
const lastSegment = segments[segments.length - 1];
|
|
@@ -47,21 +119,17 @@ const toCollectionKey = (routePath) => {
|
|
|
47
119
|
}
|
|
48
120
|
return lastSegment.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
49
121
|
};
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
avatarUrl: faker_1.faker.image.avatar(),
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
const createMockPost = () => {
|
|
122
|
+
const createRecordFromSchemaName = (schemaName, schemaDefinitions) => {
|
|
123
|
+
const normalizedSchemaName = schemaName.trim().toLowerCase();
|
|
124
|
+
const customSchemaDefinition = schemaDefinitions[normalizedSchemaName];
|
|
125
|
+
if (customSchemaDefinition) {
|
|
126
|
+
return createRecordFromSchemaDefinition(customSchemaDefinition);
|
|
127
|
+
}
|
|
60
128
|
return {
|
|
61
129
|
id: faker_1.faker.string.uuid(),
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
createdAt: faker_1.faker.date.recent({ days:
|
|
130
|
+
type: normalizedSchemaName || "record",
|
|
131
|
+
value: faker_1.faker.lorem.words({ min: 1, max: 4 }),
|
|
132
|
+
createdAt: faker_1.faker.date.recent({ days: 7 }).toISOString(),
|
|
65
133
|
};
|
|
66
134
|
};
|
|
67
135
|
const getCountFromUrl = (urlText, fallback = 5) => {
|
|
@@ -75,16 +143,46 @@ const getCountFromUrl = (urlText, fallback = 5) => {
|
|
|
75
143
|
}
|
|
76
144
|
return Math.min(Math.max(Math.floor(rawCount), 1), 50);
|
|
77
145
|
};
|
|
78
|
-
const startServer = ({ host = DEFAULT_HOST, port = DEFAULT_PORT, apiSpec, } = {}) => {
|
|
146
|
+
const startServer = ({ host = DEFAULT_HOST, port = DEFAULT_PORT, apiSpec, runtimeConfig, schemaDefinitions = {}, } = {}) => {
|
|
147
|
+
const corsEnabled = runtimeConfig?.cors ?? false;
|
|
148
|
+
const responseDelay = runtimeConfig?.delay ?? 0;
|
|
149
|
+
const configuredRoutes = runtimeConfig?.routes ?? {};
|
|
150
|
+
const availableConfiguredRoutes = Object.keys(configuredRoutes).map((path) => `GET ${path}`);
|
|
151
|
+
const availableSchemaRoutes = apiSpec
|
|
152
|
+
? apiSpec.routes.map((route) => `${route.method} ${route.path}`)
|
|
153
|
+
: [];
|
|
154
|
+
const availableRoutes = [
|
|
155
|
+
"GET /health",
|
|
156
|
+
...new Set([...availableConfiguredRoutes, ...availableSchemaRoutes]),
|
|
157
|
+
];
|
|
79
158
|
const server = (0, node_http_1.createServer)((request, response) => {
|
|
80
159
|
const pathname = new URL(request.url ?? "/", "http://localhost").pathname;
|
|
160
|
+
if (corsEnabled && request.method === "OPTIONS") {
|
|
161
|
+
response.writeHead(204, {
|
|
162
|
+
"Access-Control-Allow-Origin": "*",
|
|
163
|
+
"Access-Control-Allow-Methods": "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
164
|
+
"Access-Control-Allow-Headers": "Content-Type,Authorization",
|
|
165
|
+
});
|
|
166
|
+
response.end();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
81
169
|
if (request.method === "GET" && pathname === "/health") {
|
|
82
170
|
sendJson(response, 200, {
|
|
83
171
|
ok: true,
|
|
84
172
|
timestamp: new Date().toISOString(),
|
|
85
|
-
});
|
|
173
|
+
}, { cors: corsEnabled, delay: responseDelay });
|
|
86
174
|
return;
|
|
87
175
|
}
|
|
176
|
+
if (request.method === "GET") {
|
|
177
|
+
const configuredRoute = configuredRoutes[pathname];
|
|
178
|
+
if (configuredRoute) {
|
|
179
|
+
const payloadKey = toCollectionKey(pathname);
|
|
180
|
+
sendJson(response, 200, {
|
|
181
|
+
[payloadKey]: Array.from({ length: configuredRoute.count }, () => createRecordFromSchemaName(configuredRoute.schema, schemaDefinitions)),
|
|
182
|
+
}, { cors: corsEnabled, delay: responseDelay });
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
88
186
|
if (apiSpec) {
|
|
89
187
|
const matchedRoute = apiSpec.routes.find((route) => route.method === request.method && route.path === pathname);
|
|
90
188
|
if (matchedRoute) {
|
|
@@ -92,33 +190,14 @@ const startServer = ({ host = DEFAULT_HOST, port = DEFAULT_PORT, apiSpec, } = {}
|
|
|
92
190
|
const payloadKey = toCollectionKey(matchedRoute.path);
|
|
93
191
|
sendJson(response, 200, {
|
|
94
192
|
[payloadKey]: Array.from({ length: count }, () => createRecordFromRoute(matchedRoute)),
|
|
95
|
-
});
|
|
193
|
+
}, { cors: corsEnabled, delay: responseDelay });
|
|
96
194
|
return;
|
|
97
195
|
}
|
|
98
196
|
}
|
|
99
|
-
if (request.method === "GET" && pathname === "/users") {
|
|
100
|
-
const count = getCountFromUrl(request.url, 8);
|
|
101
|
-
sendJson(response, 200, {
|
|
102
|
-
users: Array.from({ length: count }, createMockUser),
|
|
103
|
-
});
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
if (request.method === "GET" && pathname === "/posts") {
|
|
107
|
-
const count = getCountFromUrl(request.url, 5);
|
|
108
|
-
sendJson(response, 200, {
|
|
109
|
-
posts: Array.from({ length: count }, createMockPost),
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
197
|
sendJson(response, 404, {
|
|
114
198
|
message: "Route not found",
|
|
115
|
-
availableRoutes
|
|
116
|
-
|
|
117
|
-
"GET /health",
|
|
118
|
-
...apiSpec.routes.map((route) => `${route.method} ${route.path}`),
|
|
119
|
-
]
|
|
120
|
-
: ["GET /health", "GET /users?count=10", "GET /posts?count=5"],
|
|
121
|
-
});
|
|
199
|
+
availableRoutes,
|
|
200
|
+
}, { cors: corsEnabled, delay: responseDelay });
|
|
122
201
|
});
|
|
123
202
|
server.listen(port, host, () => {
|
|
124
203
|
console.log(`Mock API running at http://${host}:${port}`);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type FexapiRouteConfig = {
|
|
2
|
+
count: number;
|
|
3
|
+
schema: string;
|
|
4
|
+
};
|
|
5
|
+
export type FexapiFieldValueType = "number" | "string" | "boolean" | "date" | "uuid" | "email" | "url" | "name" | "phone";
|
|
6
|
+
export type FexapiSchemaFieldDefinition = {
|
|
7
|
+
type: FexapiFieldValueType;
|
|
8
|
+
faker?: string;
|
|
9
|
+
min?: number;
|
|
10
|
+
max?: number;
|
|
11
|
+
};
|
|
12
|
+
export type FexapiSchemaDefinition = Record<string, FexapiSchemaFieldDefinition>;
|
|
13
|
+
export type FexapiSchemaDefinitions = Record<string, FexapiSchemaDefinition>;
|
|
14
|
+
export type FexapiRuntimeConfig = {
|
|
15
|
+
port?: number;
|
|
16
|
+
routes?: Record<string, FexapiRouteConfig>;
|
|
17
|
+
cors?: boolean;
|
|
18
|
+
delay?: number;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,MAAM,GACN,MAAM,GACN,OAAO,GACP,KAAK,GACL,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,MAAM,CACzC,MAAM,EACN,2BAA2B,CAC5B,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;AAE7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type SupportedFramework = "nextjs" | "reactjs" | "vue" | "nuxt" | "svelte" | "sveltekit" | "angular" | "solid" | "remix" | "astro" | "unknown";
|
|
2
|
+
export type DetectedProject = {
|
|
3
|
+
primaryFramework: SupportedFramework;
|
|
4
|
+
frameworks: SupportedFramework[];
|
|
5
|
+
tooling: string[];
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/types/project.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,SAAS,GACT,KAAK,GACL,MAAM,GACN,QAAQ,GACR,WAAW,GACX,SAAS,GACT,OAAO,GACP,OAAO,GACP,OAAO,GACP,SAAS,CAAC;AAEd,MAAM,MAAM,eAAe,GAAG;IAC5B,gBAAgB,EAAE,kBAAkB,CAAC;IACrC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,51 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "fexapi",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Mock API generation CLI tool for local development and testing",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"types": "./dist/index.d.ts",
|
|
7
|
-
"bin": {
|
|
8
|
-
"fexapi": "dist/index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"README.md"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsc -p tsconfig.json",
|
|
16
|
-
"check-types": "tsc --noEmit",
|
|
17
|
-
"start": "node dist/index.js",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "fexapi",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Mock API generation CLI tool for local development and testing",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"fexapi": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p tsconfig.json",
|
|
16
|
+
"check-types": "tsc --noEmit",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"serve": "node dist/index.js serve",
|
|
19
|
+
"dev": "tsc -w -p tsconfig.json",
|
|
20
|
+
"prepublishOnly": "pnpm build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mock",
|
|
24
|
+
"api",
|
|
25
|
+
"cli",
|
|
26
|
+
"testing",
|
|
27
|
+
"development",
|
|
28
|
+
"faker",
|
|
29
|
+
"mock-server"
|
|
30
|
+
],
|
|
31
|
+
"author": "Shreeteja Mutukundu smutukundu2006@gmail.com",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/shreeteja172/fexapi.git",
|
|
36
|
+
"directory": "apps/cli"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/shreeteja172/fexapi/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/shreeteja172/fexapi#readme",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.15.3",
|
|
44
|
+
"typescript": "5.9.2"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@faker-js/faker": "^10.3.0",
|
|
48
|
+
"yaml": "^2.8.3"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=18.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|