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.
Files changed (45) hide show
  1. package/README.md +115 -1
  2. package/dist/cli/args.d.ts +15 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +53 -0
  5. package/dist/cli/help.d.ts +2 -0
  6. package/dist/cli/help.d.ts.map +1 -0
  7. package/dist/cli/help.js +40 -0
  8. package/dist/commands/generate.d.ts +2 -0
  9. package/dist/commands/generate.d.ts.map +1 -0
  10. package/dist/commands/generate.js +73 -0
  11. package/dist/commands/init.d.ts +4 -0
  12. package/dist/commands/init.d.ts.map +1 -0
  13. package/dist/commands/init.js +66 -0
  14. package/dist/commands/serve.d.ts +5 -0
  15. package/dist/commands/serve.d.ts.map +1 -0
  16. package/dist/commands/serve.js +56 -0
  17. package/dist/config/generated-spec.d.ts +3 -0
  18. package/dist/config/generated-spec.d.ts.map +1 -0
  19. package/dist/config/generated-spec.js +26 -0
  20. package/dist/config/runtime-config.d.ts +3 -0
  21. package/dist/config/runtime-config.d.ts.map +1 -0
  22. package/dist/config/runtime-config.js +97 -0
  23. package/dist/config/schema-definitions.d.ts +3 -0
  24. package/dist/config/schema-definitions.d.ts.map +1 -0
  25. package/dist/config/schema-definitions.js +90 -0
  26. package/dist/constants.d.ts +2 -0
  27. package/dist/constants.d.ts.map +1 -0
  28. package/dist/constants.js +4 -0
  29. package/dist/index.js +23 -386
  30. package/dist/project/detect.d.ts +4 -0
  31. package/dist/project/detect.d.ts.map +1 -0
  32. package/dist/project/detect.js +113 -0
  33. package/dist/project/paths.d.ts +3 -0
  34. package/dist/project/paths.d.ts.map +1 -0
  35. package/dist/project/paths.js +28 -0
  36. package/dist/server.d.ts +4 -1
  37. package/dist/server.d.ts.map +1 -1
  38. package/dist/server.js +119 -40
  39. package/dist/types/config.d.ts +20 -0
  40. package/dist/types/config.d.ts.map +1 -0
  41. package/dist/types/config.js +2 -0
  42. package/dist/types/project.d.ts +7 -0
  43. package/dist/types/project.d.ts.map +1 -0
  44. package/dist/types/project.js +2 -0
  45. package/package.json +53 -51
package/README.md CHANGED
@@ -3,15 +3,129 @@
3
3
  Frontend Experience API - Mock API generation CLI tool for local development and testing.
4
4
 
5
5
  ## Installation
6
+
6
7
  ```bash
7
8
  npm install -g fexapi
8
9
  ```
9
10
 
10
11
  ## Usage
12
+
11
13
  ```bash
12
14
  fexapi [options]
13
15
  ```
14
16
 
17
+ ## Prisma-like Flow (Dynamic)
18
+
19
+ ### 1) Initialize
20
+
21
+ ```bash
22
+ pnpm dlx fexapi init
23
+ ```
24
+
25
+ Creates:
26
+
27
+ - `fexapi/schema.fexapi`
28
+ - `fexapi.config.json`
29
+
30
+ ### 2) Edit schema file
31
+
32
+ `fexapi/schema.fexapi` uses a simple DSL with only `:` and `,` (no semicolons):
33
+
34
+ ```txt
35
+ # Server
36
+ port: 4100
37
+
38
+ # Routes
39
+ GET /users: id:uuid,name:name,email:email,age:number,phone:phone,pic:url,courseName:string
40
+ GET /courses: id:uuid,courseName:string,mentor:name
41
+ ```
42
+
43
+ ### 3) Generate artifacts (like migrations)
44
+
45
+ ```bash
46
+ npx fexapi generate
47
+ ```
48
+
49
+ Generates:
50
+
51
+ - `fexapi/generated.api.json`
52
+ - `fexapi/migrations/*.json`
53
+
54
+ ### 4) Start server
55
+
56
+ ```bash
57
+ npx fexapi run
58
+ # or
59
+ npx fexapi serve
60
+ # or (inside local workspace package)
61
+ npm run serve
62
+ ```
63
+
64
+ Server port is read from `schema.fexapi` unless overridden by CLI `--port`.
65
+
66
+ ## Configuration File Support
67
+
68
+ Create a `fexapi.config.js` in your project root:
69
+
70
+ ```js
71
+ // fexapi.config.js
72
+ module.exports = {
73
+ port: 3000,
74
+ routes: {
75
+ "/users": { count: 50, schema: "user" },
76
+ "/posts": { count: 100, schema: "post" },
77
+ },
78
+ cors: true,
79
+ delay: 200,
80
+ };
81
+ ```
82
+
83
+ Then run:
84
+
85
+ ```bash
86
+ fexapi serve
87
+ ```
88
+
89
+ Notes:
90
+
91
+ - `port` sets the default server port (CLI `--port` still has priority).
92
+ - `routes` maps endpoint paths to generated payload settings.
93
+ - `schema` maps to files under `schemas/` (for example `schema: "user"` -> `schemas/user.yaml`); unknown names fall back to a generic record.
94
+ - `cors: true` enables CORS headers and OPTIONS preflight handling.
95
+ - `delay` adds response latency in milliseconds.
96
+
97
+ ## Custom Schema Definitions
98
+
99
+ You can define custom schemas in YAML files under `schemas/`.
100
+
101
+ ```yaml
102
+ # schemas/user.yaml
103
+ name:
104
+ type: string
105
+ faker: person.fullName
106
+ email:
107
+ type: string
108
+ faker: internet.email
109
+ age:
110
+ type: number
111
+ min: 18
112
+ max: 80
113
+ ```
114
+
115
+ Then reference it in `fexapi.config.js`:
116
+
117
+ ```js
118
+ routes: {
119
+ "/users": { count: 50, schema: "user" }
120
+ }
121
+ ```
122
+
123
+ Notes:
124
+
125
+ - Supported file extensions: `.yaml`, `.yml`
126
+ - Schema name is taken from filename (for example `schemas/user.yaml` -> `schema: "user"`)
127
+ - `faker` values map to Faker paths like `person.fullName`, `internet.email`
128
+
15
129
  ## Features
16
130
 
17
131
  - Schema-based mock API generation
@@ -21,4 +135,4 @@ fexapi [options]
21
135
 
22
136
  ## License
23
137
 
24
- MIT
138
+ MIT
@@ -0,0 +1,15 @@
1
+ export declare const parseInitOptions: (initArgs: string[]) => {
2
+ force: boolean;
3
+ } | {
4
+ error: string;
5
+ };
6
+ export declare const parseGenerateOptions: (generateArgs: string[]) => {
7
+ error?: string;
8
+ };
9
+ export declare const parseServeOptions: (serveArgs: string[]) => {
10
+ host: string;
11
+ port?: number;
12
+ } | {
13
+ error: string;
14
+ };
15
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAAE,KACjB;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAWtC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,cAAc,MAAM,EAAE,KACrB;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAQlB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EAAE,KAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CA+CnD,CAAC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseServeOptions = exports.parseGenerateOptions = exports.parseInitOptions = void 0;
4
+ const parseInitOptions = (initArgs) => {
5
+ const validFlags = new Set(["--force"]);
6
+ const invalidFlags = initArgs.filter((value) => value.startsWith("-") && !validFlags.has(value));
7
+ if (invalidFlags.length > 0) {
8
+ return { error: `Unknown option(s): ${invalidFlags.join(", ")}` };
9
+ }
10
+ return { force: initArgs.includes("--force") };
11
+ };
12
+ exports.parseInitOptions = parseInitOptions;
13
+ const parseGenerateOptions = (generateArgs) => {
14
+ const invalidFlags = generateArgs.filter((value) => value.startsWith("-"));
15
+ if (invalidFlags.length > 0) {
16
+ return { error: `Unknown option(s): ${invalidFlags.join(", ")}` };
17
+ }
18
+ return {};
19
+ };
20
+ exports.parseGenerateOptions = parseGenerateOptions;
21
+ const parseServeOptions = (serveArgs) => {
22
+ const getFlagValue = (flagName) => {
23
+ const index = serveArgs.indexOf(flagName);
24
+ if (index === -1) {
25
+ return undefined;
26
+ }
27
+ const value = serveArgs[index + 1];
28
+ if (!value || value.startsWith("-")) {
29
+ return { error: `Missing value for ${flagName}` };
30
+ }
31
+ return value;
32
+ };
33
+ const unknownFlags = serveArgs.filter((value) => value.startsWith("-") && value !== "--host" && value !== "--port");
34
+ if (unknownFlags.length > 0) {
35
+ return { error: `Unknown option(s): ${unknownFlags.join(", ")}` };
36
+ }
37
+ const hostValue = getFlagValue("--host");
38
+ if (hostValue && typeof hostValue !== "string") {
39
+ return hostValue;
40
+ }
41
+ const portValue = getFlagValue("--port");
42
+ if (portValue && typeof portValue !== "string") {
43
+ return portValue;
44
+ }
45
+ const host = hostValue ?? "127.0.0.1";
46
+ const port = portValue ? Number(portValue) : undefined;
47
+ if (port !== undefined &&
48
+ (!Number.isInteger(port) || port < 1 || port > 65535)) {
49
+ return { error: `Invalid port: ${portValue ?? ""}`.trim() };
50
+ }
51
+ return { host, port };
52
+ };
53
+ exports.parseServeOptions = parseServeOptions;
@@ -0,0 +1,2 @@
1
+ export declare const printHelp: () => void;
2
+ //# sourceMappingURL=help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,YAmCrB,CAAC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.printHelp = void 0;
4
+ const printHelp = () => {
5
+ console.log("fexapi-cli");
6
+ console.log("");
7
+ console.log("Usage:");
8
+ console.log(" fexapi init [--force]");
9
+ console.log(" fexapi generate");
10
+ console.log(" fexapi serve [--host <host>] [--port <number>]");
11
+ console.log(" fexapi run [--host <host>] [--port <number>]");
12
+ console.log(" fexapi [--host <host>] [--port <number>]");
13
+ console.log(" fexapi --help");
14
+ console.log("");
15
+ console.log("Examples:");
16
+ console.log(" fexapi init");
17
+ console.log(" fexapi init --force");
18
+ console.log(" fexapi generate");
19
+ console.log(" fexapi serve --host 127.0.0.1 --port 5000");
20
+ console.log(" fexapi --port 4000");
21
+ console.log("");
22
+ console.log("Package manager usage:");
23
+ console.log(" npx fexapi init");
24
+ console.log(" pnpm dlx fexapi init");
25
+ console.log(" yarn dlx fexapi init");
26
+ console.log("");
27
+ console.log("`fexapi init` creates:");
28
+ console.log(" fexapi.config.json");
29
+ console.log(" fexapi/schema.fexapi");
30
+ console.log("");
31
+ console.log("Then run:");
32
+ console.log(" # edit fexapi/schema.fexapi");
33
+ console.log(" fexapi generate");
34
+ console.log(" fexapi run");
35
+ console.log("");
36
+ console.log("Generate output:");
37
+ console.log(" fexapi/generated.api.json");
38
+ console.log(" fexapi/migrations/*.json");
39
+ };
40
+ exports.printHelp = printHelp;
@@ -0,0 +1,2 @@
1
+ export declare const generateFromSchema: () => number;
2
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,kBAAkB,QAAO,MAkGrC,CAAC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateFromSchema = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const constants_1 = require("../constants");
7
+ const paths_1 = require("../project/paths");
8
+ const schema_1 = require("../schema");
9
+ const generateFromSchema = () => {
10
+ const projectRoot = (0, paths_1.resolveProjectRoot)();
11
+ if (!projectRoot) {
12
+ console.error("Could not find package.json in this directory or parent directories.");
13
+ return 1;
14
+ }
15
+ const schemaPath = (0, node_path_1.join)(projectRoot, "fexapi", "schema.fexapi");
16
+ const generatedPath = (0, node_path_1.join)(projectRoot, "fexapi", "generated.api.json");
17
+ const migrationsDirectoryPath = (0, node_path_1.join)(projectRoot, "fexapi", "migrations");
18
+ const configPath = (0, node_path_1.join)(projectRoot, "fexapi.config.json");
19
+ if (!(0, node_fs_1.existsSync)(schemaPath)) {
20
+ console.error(`Schema file not found: ${schemaPath}`);
21
+ console.error("Run `fexapi init` first.");
22
+ return 1;
23
+ }
24
+ const schemaText = (0, node_fs_1.readFileSync)(schemaPath, "utf-8");
25
+ const parsed = (0, schema_1.parseFexapiSchema)(schemaText);
26
+ if (parsed.errors.length > 0 || !parsed.schema) {
27
+ console.error("Failed to generate API from schema.fexapi");
28
+ for (const error of parsed.errors) {
29
+ console.error(`- ${error}`);
30
+ }
31
+ return 1;
32
+ }
33
+ const generated = {
34
+ schemaVersion: 1,
35
+ generatedAt: new Date().toISOString(),
36
+ port: parsed.schema.port,
37
+ routes: parsed.schema.routes,
38
+ };
39
+ (0, node_fs_1.mkdirSync)(migrationsDirectoryPath, { recursive: true });
40
+ const migrationId = new Date().toISOString().replace(/[.:]/g, "-");
41
+ const migrationPath = (0, node_path_1.join)(migrationsDirectoryPath, `${migrationId}_schema.json`);
42
+ const migration = {
43
+ migrationId,
44
+ sourceSchema: "fexapi/schema.fexapi",
45
+ createdAt: generated.generatedAt,
46
+ port: parsed.schema.port,
47
+ routes: parsed.schema.routes,
48
+ };
49
+ (0, node_fs_1.writeFileSync)(generatedPath, `${JSON.stringify(generated, null, 2)}\n`, "utf-8");
50
+ (0, node_fs_1.writeFileSync)(migrationPath, `${JSON.stringify(migration, null, 2)}\n`, "utf-8");
51
+ let existingConfig = {};
52
+ if ((0, node_fs_1.existsSync)(configPath)) {
53
+ try {
54
+ existingConfig = JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf-8"));
55
+ }
56
+ catch {
57
+ existingConfig = {};
58
+ }
59
+ }
60
+ const updatedConfig = {
61
+ ...existingConfig,
62
+ schemaPath: "fexapi/schema.fexapi",
63
+ generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
64
+ lastGeneratedAt: new Date().toISOString(),
65
+ };
66
+ (0, node_fs_1.writeFileSync)(configPath, `${JSON.stringify(updatedConfig, null, 2)}\n`, "utf-8");
67
+ console.log(`Generated API spec at ${generatedPath}`);
68
+ console.log(`Migration created at ${migrationPath}`);
69
+ console.log(`Routes generated: ${parsed.schema.routes.length}`);
70
+ console.log(`Configured server port: ${parsed.schema.port}`);
71
+ return 0;
72
+ };
73
+ exports.generateFromSchema = generateFromSchema;
@@ -0,0 +1,4 @@
1
+ export declare const initializeProject: ({ force }: {
2
+ force: boolean;
3
+ }) => number;
4
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,GAAI,WAAW;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,KAAG,MAwEjE,CAAC"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initializeProject = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const constants_1 = require("../constants");
7
+ const detect_1 = require("../project/detect");
8
+ const paths_1 = require("../project/paths");
9
+ const initializeProject = ({ force }) => {
10
+ const packageJsonPath = (0, paths_1.findClosestPackageJson)(process.cwd());
11
+ if (!packageJsonPath) {
12
+ console.error("Could not find package.json in this directory or parent directories.");
13
+ return 1;
14
+ }
15
+ const projectRoot = (0, node_path_1.dirname)(packageJsonPath);
16
+ const detectedProject = (0, detect_1.detectProject)(packageJsonPath, projectRoot);
17
+ const fexapiDirectoryPath = (0, node_path_1.join)(projectRoot, "fexapi");
18
+ const schemaPath = (0, node_path_1.join)(fexapiDirectoryPath, "schema.fexapi");
19
+ const configPath = (0, node_path_1.join)(projectRoot, "fexapi.config.json");
20
+ (0, node_fs_1.mkdirSync)(fexapiDirectoryPath, { recursive: true });
21
+ const configExists = (0, node_fs_1.existsSync)(configPath);
22
+ const schemaExists = (0, node_fs_1.existsSync)(schemaPath);
23
+ const config = {
24
+ framework: detectedProject.primaryFramework,
25
+ frameworks: detectedProject.frameworks,
26
+ tooling: detectedProject.tooling,
27
+ schemaPath: "fexapi/schema.fexapi",
28
+ generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
29
+ createdAt: new Date().toISOString(),
30
+ };
31
+ if (!configExists || force) {
32
+ (0, node_fs_1.writeFileSync)(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
33
+ }
34
+ if (!schemaExists || force) {
35
+ (0, node_fs_1.writeFileSync)(schemaPath, `${(0, detect_1.getSchemaTemplate)(detectedProject.primaryFramework)}\n`, "utf-8");
36
+ }
37
+ console.log(`Initialized Fexapi in ${projectRoot}`);
38
+ console.log(`Detected framework: ${detectedProject.primaryFramework}`);
39
+ console.log(`Detected frameworks: ${detectedProject.frameworks.join(", ")}`);
40
+ if (detectedProject.tooling.length > 0) {
41
+ console.log(`Detected tooling: ${detectedProject.tooling.join(", ")}`);
42
+ }
43
+ if (configExists && !force) {
44
+ console.log(`Exists ${configPath}`);
45
+ }
46
+ else if (configExists && force) {
47
+ console.log(`Overwritten ${configPath}`);
48
+ }
49
+ else {
50
+ console.log(`Created ${configPath}`);
51
+ }
52
+ if (schemaExists && !force) {
53
+ console.log(`Exists ${schemaPath}`);
54
+ }
55
+ else if (schemaExists && force) {
56
+ console.log(`Overwritten ${schemaPath}`);
57
+ }
58
+ else {
59
+ console.log(`Created ${schemaPath}`);
60
+ }
61
+ if (detectedProject.primaryFramework === "unknown") {
62
+ console.log("No known framework dependency found. Update fexapi.config.json and schema.fexapi if needed.");
63
+ }
64
+ return 0;
65
+ };
66
+ exports.initializeProject = initializeProject;
@@ -0,0 +1,5 @@
1
+ export declare const serveProject: ({ host, port, }: {
2
+ host: string;
3
+ port?: number;
4
+ }) => number;
5
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,GAAI,iBAG1B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,KAAG,MAkEH,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serveProject = void 0;
4
+ const constants_1 = require("../constants");
5
+ const generated_spec_1 = require("../config/generated-spec");
6
+ const runtime_config_1 = require("../config/runtime-config");
7
+ const schema_definitions_1 = require("../config/schema-definitions");
8
+ const paths_1 = require("../project/paths");
9
+ const server_1 = require("../server");
10
+ const serveProject = ({ host, port, }) => {
11
+ const projectRoot = (0, paths_1.resolveProjectRoot)();
12
+ const runtimeConfig = projectRoot
13
+ ? (0, runtime_config_1.loadFexapiRuntimeConfig)(projectRoot)
14
+ : undefined;
15
+ const schemaDefinitions = projectRoot
16
+ ? (0, schema_definitions_1.loadSchemaDefinitions)(projectRoot)
17
+ : {};
18
+ const generatedSpec = projectRoot
19
+ ? (0, generated_spec_1.loadGeneratedApiSpec)(projectRoot)
20
+ : undefined;
21
+ const effectivePort = port ?? runtimeConfig?.port ?? generatedSpec?.port ?? 4000;
22
+ if (runtimeConfig?.routes && Object.keys(runtimeConfig.routes).length > 0) {
23
+ console.log(`Using routes from fexapi.config.js (${Object.keys(runtimeConfig.routes).length})`);
24
+ }
25
+ if (Object.keys(schemaDefinitions).length > 0) {
26
+ console.log(`Loaded custom schemas from /schemas (${Object.keys(schemaDefinitions).length})`);
27
+ }
28
+ if (generatedSpec &&
29
+ !(runtimeConfig?.routes && Object.keys(runtimeConfig.routes).length > 0)) {
30
+ console.log(`Using generated schema routes (${generatedSpec.routes.length}) from ${constants_1.GENERATED_SPEC_RELATIVE_PATH}`);
31
+ }
32
+ else if (!runtimeConfig?.routes ||
33
+ Object.keys(runtimeConfig.routes).length === 0) {
34
+ console.log("No generated schema found. Run `fexapi generate` to serve schema-defined endpoints.");
35
+ }
36
+ const server = (0, server_1.startServer)({
37
+ host,
38
+ port: effectivePort,
39
+ apiSpec: generatedSpec,
40
+ runtimeConfig,
41
+ schemaDefinitions,
42
+ });
43
+ const shutdown = () => {
44
+ server.close((error) => {
45
+ if (error) {
46
+ console.error("Error while shutting down server", error);
47
+ process.exit(1);
48
+ }
49
+ process.exit(0);
50
+ });
51
+ };
52
+ process.on("SIGINT", shutdown);
53
+ process.on("SIGTERM", shutdown);
54
+ return 0;
55
+ };
56
+ exports.serveProject = serveProject;
@@ -0,0 +1,3 @@
1
+ import type { GeneratedApiSpec } from "../server";
2
+ export declare const loadGeneratedApiSpec: (projectRoot: string) => GeneratedApiSpec | undefined;
3
+ //# sourceMappingURL=generated-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generated-spec.d.ts","sourceRoot":"","sources":["../../src/config/generated-spec.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,KAClB,gBAAgB,GAAG,SAwBrB,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadGeneratedApiSpec = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const constants_1 = require("../constants");
7
+ const loadGeneratedApiSpec = (projectRoot) => {
8
+ const generatedPath = (0, node_path_1.join)(projectRoot, constants_1.GENERATED_SPEC_RELATIVE_PATH);
9
+ if (!(0, node_fs_1.existsSync)(generatedPath)) {
10
+ return undefined;
11
+ }
12
+ try {
13
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(generatedPath, "utf-8"));
14
+ if (typeof parsed.port !== "number" || !Array.isArray(parsed.routes)) {
15
+ return undefined;
16
+ }
17
+ return {
18
+ port: parsed.port,
19
+ routes: parsed.routes,
20
+ };
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ };
26
+ exports.loadGeneratedApiSpec = loadGeneratedApiSpec;
@@ -0,0 +1,3 @@
1
+ import type { FexapiRuntimeConfig } from "../types/config";
2
+ export declare const loadFexapiRuntimeConfig: (projectRoot: string) => FexapiRuntimeConfig | undefined;
3
+ //# sourceMappingURL=runtime-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-config.d.ts","sourceRoot":"","sources":["../../src/config/runtime-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAU9E,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,KAClB,mBAAmB,GAAG,SA8GxB,CAAC"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadFexapiRuntimeConfig = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const isRecord = (value) => {
7
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8
+ };
9
+ const normalizePath = (value) => {
10
+ return value.startsWith("/") ? value : `/${value}`;
11
+ };
12
+ const loadFexapiRuntimeConfig = (projectRoot) => {
13
+ const configPath = (0, node_path_1.join)(projectRoot, "fexapi.config.js");
14
+ if (!(0, node_fs_1.existsSync)(configPath)) {
15
+ return undefined;
16
+ }
17
+ try {
18
+ const source = (0, node_fs_1.readFileSync)(configPath, "utf-8");
19
+ const moduleShim = { exports: {} };
20
+ const exportsShim = {};
21
+ const executeModule = new Function("module", "exports", source);
22
+ executeModule(moduleShim, exportsShim);
23
+ const rawConfig = moduleShim.exports;
24
+ if (!isRecord(rawConfig)) {
25
+ console.error("Invalid fexapi.config.js: expected an object export.");
26
+ return undefined;
27
+ }
28
+ const normalizedConfig = {};
29
+ if (rawConfig.port !== undefined) {
30
+ if (typeof rawConfig.port !== "number" ||
31
+ !Number.isInteger(rawConfig.port) ||
32
+ rawConfig.port < 1 ||
33
+ rawConfig.port > 65535) {
34
+ console.error("Invalid fexapi.config.js: `port` must be an integer between 1 and 65535.");
35
+ }
36
+ else {
37
+ normalizedConfig.port = rawConfig.port;
38
+ }
39
+ }
40
+ if (rawConfig.cors !== undefined) {
41
+ if (typeof rawConfig.cors !== "boolean") {
42
+ console.error("Invalid fexapi.config.js: `cors` must be true or false.");
43
+ }
44
+ else {
45
+ normalizedConfig.cors = rawConfig.cors;
46
+ }
47
+ }
48
+ if (rawConfig.delay !== undefined) {
49
+ if (typeof rawConfig.delay !== "number" ||
50
+ !Number.isFinite(rawConfig.delay) ||
51
+ rawConfig.delay < 0) {
52
+ console.error("Invalid fexapi.config.js: `delay` must be a non-negative number.");
53
+ }
54
+ else {
55
+ normalizedConfig.delay = Math.floor(rawConfig.delay);
56
+ }
57
+ }
58
+ if (rawConfig.routes !== undefined) {
59
+ if (!isRecord(rawConfig.routes)) {
60
+ console.error("Invalid fexapi.config.js: `routes` must be an object.");
61
+ }
62
+ else {
63
+ const normalizedRoutes = {};
64
+ for (const [pathKey, routeValue] of Object.entries(rawConfig.routes)) {
65
+ if (!isRecord(routeValue)) {
66
+ console.error(`Invalid fexapi.config.js route at ${pathKey}: expected an object with count and schema.`);
67
+ continue;
68
+ }
69
+ const schemaValue = routeValue.schema;
70
+ if (typeof schemaValue !== "string" ||
71
+ schemaValue.trim().length === 0) {
72
+ console.error(`Invalid fexapi.config.js route at ${pathKey}: schema must be a non-empty string.`);
73
+ continue;
74
+ }
75
+ const countValue = routeValue.count;
76
+ const normalizedCount = typeof countValue === "number" &&
77
+ Number.isInteger(countValue) &&
78
+ countValue > 0
79
+ ? countValue
80
+ : 10;
81
+ normalizedRoutes[normalizePath(pathKey)] = {
82
+ count: normalizedCount,
83
+ schema: schemaValue.trim(),
84
+ };
85
+ }
86
+ normalizedConfig.routes = normalizedRoutes;
87
+ }
88
+ }
89
+ return normalizedConfig;
90
+ }
91
+ catch (error) {
92
+ const message = error instanceof Error ? error.message : String(error);
93
+ console.error(`Failed to load fexapi.config.js: ${message}`);
94
+ return undefined;
95
+ }
96
+ };
97
+ exports.loadFexapiRuntimeConfig = loadFexapiRuntimeConfig;
@@ -0,0 +1,3 @@
1
+ import type { FexapiSchemaDefinitions } from "../types/config";
2
+ export declare const loadSchemaDefinitions: (projectRoot: string) => FexapiSchemaDefinitions;
3
+ //# sourceMappingURL=schema-definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-definitions.d.ts","sourceRoot":"","sources":["../../src/config/schema-definitions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,uBAAuB,EACxB,MAAM,iBAAiB,CAAC;AA8EzB,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,KAClB,uBAoCF,CAAC"}