fexapi 0.2.2 → 0.2.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,YAgErB,CAAC"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,YA8DrB,CAAC"}
package/dist/cli/help.js CHANGED
@@ -23,7 +23,7 @@ const printHelp = () => {
23
23
  console.log(` ${(0, ui_1.formatCommand)("fexapi dev --watch")}`);
24
24
  console.log(` ${(0, ui_1.formatCommand)("fexapi dev --watch --log")}`);
25
25
  console.log(` ${(0, ui_1.formatCommand)("fexapi serve --log")}`);
26
- console.log(` ${(0, ui_1.formatCommand)("fexapi serve --host 127.0.0.1 --port 5000")}`);
26
+ console.log(` ${(0, ui_1.formatCommand)("fexapi serve --host localhost --port 5000")}`);
27
27
  console.log(` ${(0, ui_1.formatCommand)("fexapi --port 4000")}`);
28
28
  (0, ui_1.printSpacer)();
29
29
  console.log(ui_1.ui.bold("Package Manager Usage"));
@@ -32,13 +32,12 @@ const printHelp = () => {
32
32
  console.log(` ${(0, ui_1.formatCommand)("yarn dlx fexapi init")}`);
33
33
  (0, ui_1.printSpacer)();
34
34
  console.log(ui_1.ui.bold("fexapi init creates"));
35
- console.log(` ${ui_1.ui.dim("fexapi.config.json")}`);
36
35
  console.log(` ${ui_1.ui.dim("fexapi.config.js")}`);
37
36
  console.log(` ${ui_1.ui.dim("fexapi/schema.fexapi")}`);
38
37
  console.log(` ${ui_1.ui.dim("fexapi/schemas/*.yaml (optional, via wizard)")}`);
39
38
  (0, ui_1.printSpacer)();
40
39
  console.log(ui_1.ui.bold("Init wizard asks"));
41
- console.log(` ${ui_1.ui.dim("What port? (default: 3000)")}`);
40
+ console.log(` ${ui_1.ui.dim("What port? (default: 4000)")}`);
42
41
  console.log(` ${ui_1.ui.dim("Enable CORS? (Y/n)")}`);
43
42
  console.log(` ${ui_1.ui.dim("Generate sample schemas? (Y/n)")}`);
44
43
  (0, ui_1.printSpacer)();
@@ -49,6 +48,5 @@ const printHelp = () => {
49
48
  (0, ui_1.printSpacer)();
50
49
  console.log(ui_1.ui.bold("Generate output"));
51
50
  console.log(` ${ui_1.ui.dim("fexapi/generated.api.json")}`);
52
- console.log(` ${ui_1.ui.dim("fexapi/migrations/schema.json")}`);
53
51
  };
54
52
  exports.printHelp = printHelp;
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,EAAE;iBACA,MAAM,KAAG,MAAM;gBAChB,MAAM,KAAG,MAAM;iBACd,MAAM,KAAG,MAAM;oBACZ,MAAM,KAAG,MAAM;iBAClB,MAAM,KAAG,MAAM;kBACd,MAAM,KAAG,MAAM;mBACd,MAAM,KAAG,MAAM;gBAClB,MAAM,KAAG,MAAM;iBACd,MAAM,KAAG,MAAM;kBACd,MAAM,KAAG,MAAM;CAC9B,CAAC;AA4DF,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,KAAG,iBA0ClD,CAAC;AAEF,eAAO,MAAM,KAAK,QAAO,MAAoB,CAAC;AAE9C,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAQhD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,EACb,MAAM,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,KAC5C,IAqDF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,IAQhD,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAO9B,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,IAE1C,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAE/C,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,EAAE;iBACA,MAAM,KAAG,MAAM;gBAChB,MAAM,KAAG,MAAM;iBACd,MAAM,KAAG,MAAM;oBACZ,MAAM,KAAG,MAAM;iBAClB,MAAM,KAAG,MAAM;kBACd,MAAM,KAAG,MAAM;mBACd,MAAM,KAAG,MAAM;gBAClB,MAAM,KAAG,MAAM;iBACd,MAAM,KAAG,MAAM;kBACd,MAAM,KAAG,MAAM;CAC9B,CAAC;AA4DF,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,KAAG,iBA0ClD,CAAC;AAEF,eAAO,MAAM,KAAK,QAAO,MAAoB,CAAC;AAE9C,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,MAQhD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,EACb,MAAM,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,KAC5C,IAgEF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,IAkBhD,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAO9B,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,IAE5C,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,IAE1C,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,IAEzC,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAE/C,CAAC"}
package/dist/cli/ui.js CHANGED
@@ -120,48 +120,57 @@ const printSummaryCard = (title, rows) => {
120
120
  const terminalWidth = getTerminalWidth();
121
121
  const compactMode = terminalWidth < 64;
122
122
  if (compactMode) {
123
- console.log(exports.ui.gray(`--- ${title} ---`));
123
+ console.log(exports.ui.gray(`+-- ${title} --+`));
124
124
  for (const row of rows) {
125
- console.log(`${exports.ui.dim(row.label)}: ${row.value}`);
125
+ console.log(`${exports.ui.dim(row.label)} ${exports.ui.gray("::")} ${styleCardValue(row.value)}`);
126
126
  }
127
- console.log(exports.ui.gray("---------------"));
127
+ console.log(exports.ui.gray("+----------------+"));
128
128
  return;
129
129
  }
130
130
  const safeRows = rows.map((row) => ({
131
131
  label: row.label,
132
132
  value: row.value,
133
133
  }));
134
- const cardWidth = terminalWidth - 2;
134
+ const maxCardWidth = 96;
135
+ const naturalInnerWidth = Math.max(36, visibleLength(title) + 2, ...safeRows.map((row) => visibleLength(row.label) + visibleLength(row.value) + 7));
136
+ const cardWidth = Math.max(40, Math.min(maxCardWidth, terminalWidth - 2, naturalInnerWidth + 2));
135
137
  const innerWidth = cardWidth - 2;
136
138
  const labelWidth = Math.min(20, Math.max(10, ...safeRows.map((row) => visibleLength(row.label))));
137
- const valueSpace = Math.max(8, innerWidth - 3 - labelWidth - 3);
139
+ const valueSpace = Math.max(8, innerWidth - 7 - labelWidth);
140
+ const renderBoxLine = (content) => {
141
+ const remaining = Math.max(0, innerWidth - 2 - visibleLength(content));
142
+ return `│ ${content}${" ".repeat(remaining)} │`;
143
+ };
138
144
  const topBorder = `┌${"─".repeat(innerWidth)}┐`;
139
145
  const divider = `├${"─".repeat(innerWidth)}┤`;
140
146
  const bottomBorder = `└${"─".repeat(innerWidth)}┘`;
141
147
  console.log(exports.ui.gray(topBorder));
142
148
  const renderedTitle = truncateText(title, innerWidth - 2);
143
- const titlePadding = " ".repeat(Math.max(0, innerWidth - 2 - visibleLength(renderedTitle)));
144
- console.log(`│ ${exports.ui.bold(exports.ui.cyan(renderedTitle))}${titlePadding} │`);
149
+ console.log(renderBoxLine(exports.ui.bold(exports.ui.cyan(renderedTitle))));
145
150
  console.log(exports.ui.gray(divider));
146
151
  for (const row of safeRows) {
147
152
  const rawValue = stripAnsi(row.value);
148
153
  const value = truncateText(rawValue, valueSpace);
149
154
  const label = row.label.padEnd(labelWidth, " ");
150
155
  const styledValue = styleCardValue(value);
151
- const spaces = " ".repeat(Math.max(1, innerWidth - 3 - visibleLength(label) - 3 - visibleLength(value)));
152
- console.log(`│ ${exports.ui.dim(label)} ${exports.ui.gray("::")} ${styledValue}${spaces}│`);
156
+ console.log(renderBoxLine(`${exports.ui.dim(label)} ${exports.ui.gray("::")} ${styledValue}`));
153
157
  }
154
158
  console.log(exports.ui.gray(bottomBorder));
155
159
  };
156
160
  exports.printSummaryCard = printSummaryCard;
157
161
  const printGroupHeader = (title) => {
158
162
  const terminalWidth = getTerminalWidth();
159
- const marker = exports.ui.gray("──");
160
- const text = ` ${exports.ui.bold(title)} `;
161
- const lineLength = Math.max(0, terminalWidth - visibleLength(title) - 4);
162
- const left = marker;
163
- const right = exports.ui.gray("─".repeat(Math.max(0, lineLength - 2)));
164
- console.log(`${left}${text}${right}`);
163
+ const compactMode = terminalWidth < 64;
164
+ if (compactMode) {
165
+ console.log(exports.ui.gray(`-- ${title} --`));
166
+ return;
167
+ }
168
+ const innerWidth = terminalWidth - 2;
169
+ const renderedTitle = truncateText(title, Math.max(1, innerWidth - 6));
170
+ const rawPrefix = `── ${renderedTitle} `;
171
+ const fill = Math.max(0, innerWidth - visibleLength(rawPrefix));
172
+ const prefix = `${exports.ui.gray("── ")}${exports.ui.bold(exports.ui.cyan(renderedTitle))} `;
173
+ console.log(`${exports.ui.gray("┌")}${prefix}${exports.ui.gray("─".repeat(fill))}${exports.ui.gray("┐")}`);
165
174
  };
166
175
  exports.printGroupHeader = printGroupHeader;
167
176
  const printBanner = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,aAAa,GAAI,2CAK3B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB,KAAG,MAmHH,CAAC"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,aAAa,GAAI,2CAK3B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB,KAAG,MAmHH,CAAC"}
@@ -12,8 +12,7 @@ const normalizePath = (pathValue) => {
12
12
  };
13
13
  const isWatchedPath = (projectRoot, changedPath) => {
14
14
  const relativePath = normalizePath((0, node_path_1.relative)(projectRoot, changedPath));
15
- if (relativePath === "fexapi.config.js" ||
16
- relativePath === "fexapi.config.json") {
15
+ if (relativePath === "fexapi.config.js") {
17
16
  return true;
18
17
  }
19
18
  if (relativePath.startsWith("fexapi/")) {
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,kBAAkB,QAAO,MA6KrC,CAAC"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,kBAAkB,QAAO,MA8GrC,CAAC"}
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateFromSchema = void 0;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const node_path_1 = require("node:path");
6
- const constants_1 = require("../constants");
7
6
  const ui_1 = require("../cli/ui");
8
7
  const paths_1 = require("../project/paths");
9
8
  const schema_1 = require("../schema");
@@ -22,8 +21,6 @@ const generateFromSchema = () => {
22
21
  }
23
22
  const schemaPath = (0, node_path_1.join)(projectRoot, "fexapi", "schema.fexapi");
24
23
  const generatedPath = (0, node_path_1.join)(projectRoot, "fexapi", "generated.api.json");
25
- const migrationsDirectoryPath = (0, node_path_1.join)(projectRoot, "fexapi", "migrations");
26
- const configPath = (0, node_path_1.join)(projectRoot, "fexapi.config.json");
27
24
  if (!(0, node_fs_1.existsSync)(schemaPath)) {
28
25
  (0, ui_1.logError)(`Schema file not found: ${schemaPath}`);
29
26
  (0, ui_1.logError)("Run `fexapi init` first.");
@@ -67,52 +64,12 @@ const generateFromSchema = () => {
67
64
  port: parsed.schema.port,
68
65
  routes: parsed.schema.routes,
69
66
  };
70
- (0, node_fs_1.mkdirSync)(migrationsDirectoryPath, { recursive: true });
71
- const migrationPath = (0, node_path_1.join)(migrationsDirectoryPath, "schema.json");
72
- const migration = {
73
- migrationId: new Date().toISOString().replace(/[.:]/g, "-"),
74
- sourceSchema: "fexapi/schema.fexapi",
75
- createdAt: generated.generatedAt,
76
- port: parsed.schema.port,
77
- routes: parsed.schema.routes,
78
- };
79
67
  let generatedStatus = "cached";
80
- let migrationStatus = "cached";
81
68
  if (schemaChanged || !(0, node_fs_1.existsSync)(generatedPath)) {
82
69
  generationSpinner.update("Writing generated API spec");
83
70
  (0, node_fs_1.writeFileSync)(generatedPath, `${JSON.stringify(generated, null, 2)}\n`, "utf-8");
84
71
  generatedStatus = "changed";
85
72
  }
86
- if (schemaChanged || !(0, node_fs_1.existsSync)(migrationPath)) {
87
- generationSpinner.update("Updating migration snapshot");
88
- (0, node_fs_1.writeFileSync)(migrationPath, `${JSON.stringify(migration, null, 2)}\n`, "utf-8");
89
- migrationStatus = "changed";
90
- }
91
- let existingConfig = {};
92
- if ((0, node_fs_1.existsSync)(configPath)) {
93
- try {
94
- existingConfig = JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf-8"));
95
- }
96
- catch {
97
- existingConfig = {};
98
- }
99
- }
100
- const updatedConfig = {
101
- ...existingConfig,
102
- schemaPath: "fexapi/schema.fexapi",
103
- generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
104
- ...(schemaChanged ? { lastGeneratedAt: new Date().toISOString() } : {}),
105
- };
106
- generationSpinner.update("Syncing project config");
107
- const nextConfigText = `${JSON.stringify(updatedConfig, null, 2)}\n`;
108
- const previousConfigText = (0, node_fs_1.existsSync)(configPath)
109
- ? (0, node_fs_1.readFileSync)(configPath, "utf-8")
110
- : undefined;
111
- let configStatus = "cached";
112
- if (previousConfigText !== nextConfigText) {
113
- (0, node_fs_1.writeFileSync)(configPath, nextConfigText, "utf-8");
114
- configStatus = "changed";
115
- }
116
73
  generationSpinner.succeed(`Generate complete (${schemaChanged ? "changed" : "cached"})`);
117
74
  (0, ui_1.printSpacer)();
118
75
  (0, ui_1.printGroupHeader)("Summary");
@@ -133,14 +90,6 @@ const generateFromSchema = () => {
133
90
  label: "generated.api.json",
134
91
  value: generatedStatus,
135
92
  },
136
- {
137
- label: "migration",
138
- value: migrationStatus,
139
- },
140
- {
141
- label: "config",
142
- value: configStatus,
143
- },
144
93
  {
145
94
  label: "time",
146
95
  value: (0, ui_1.formatDuration)(startedAtMs),
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAuMA,eAAO,MAAM,iBAAiB,GAAU,YAErC;IACD,KAAK,EAAE,OAAO,CAAC;CAChB,KAAG,OAAO,CAAC,MAAM,CA2MjB,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA4OA,eAAO,MAAM,iBAAiB,GAAU,YAErC;IACD,KAAK,EAAE,OAAO,CAAC;CAChB,KAAG,OAAO,CAAC,MAAM,CA+KjB,CAAC"}
@@ -5,7 +5,6 @@ const node_fs_1 = require("node:fs");
5
5
  const node_path_1 = require("node:path");
6
6
  const promises_1 = require("node:readline/promises");
7
7
  const node_process_1 = require("node:process");
8
- const constants_1 = require("../constants");
9
8
  const ui_1 = require("../cli/ui");
10
9
  const detect_1 = require("../project/detect");
11
10
  const paths_1 = require("../project/paths");
@@ -32,10 +31,18 @@ const askInitWizardQuestions = async () => {
32
31
  };
33
32
  }
34
33
  const questionInterface = (0, promises_1.createInterface)({ input: node_process_1.stdin, output: node_process_1.stdout });
34
+ const totalSteps = 3;
35
+ const formatWizardPrompt = (step, question, hint, defaultValue) => {
36
+ return `${ui_1.ui.cyan("?")} ${ui_1.ui.bold(`[${step}/${totalSteps}]`)} ${ui_1.ui.white(question)} ${ui_1.ui.gray(`(${hint})`)} ${ui_1.ui.dim(`default: ${defaultValue}`)} ${ui_1.ui.gray("› ")}`;
37
+ };
35
38
  try {
39
+ (0, ui_1.printSpacer)();
40
+ (0, ui_1.printGroupHeader)("Setup Wizard");
41
+ console.log(ui_1.ui.dim("Press Enter to accept defaults."));
42
+ (0, ui_1.printSpacer)();
36
43
  let port = DEFAULT_INIT_PORT;
37
44
  while (true) {
38
- const answer = await questionInterface.question(`What port? (default: ${DEFAULT_INIT_PORT}) `);
45
+ const answer = await questionInterface.question(formatWizardPrompt(1, "What port should FexAPI use?", "1-65535", String(DEFAULT_INIT_PORT)));
39
46
  if (!answer.trim()) {
40
47
  break;
41
48
  }
@@ -46,29 +53,35 @@ const askInitWizardQuestions = async () => {
46
53
  port = parsedPort;
47
54
  break;
48
55
  }
49
- console.log("Please enter a valid port (1-65535).\n");
56
+ console.log(`${ui_1.ui.red("✕")} ${ui_1.ui.white("Please enter a valid port between 1 and 65535.")}`);
57
+ (0, ui_1.printSpacer)();
50
58
  }
59
+ console.log(`${ui_1.ui.green("✓")} ${ui_1.ui.dim("Port")}: ${ui_1.ui.bold(String(port))}`);
51
60
  let cors = true;
52
61
  while (true) {
53
- const answer = await questionInterface.question("Enable CORS? (Y/n) ");
62
+ const answer = await questionInterface.question(formatWizardPrompt(2, "Enable CORS?", "Y/n", "Y"));
54
63
  const parsed = parseYesNo(answer, true);
55
64
  if (parsed !== undefined) {
56
65
  cors = parsed;
57
66
  break;
58
67
  }
59
- console.log("Please answer with Y/Yes or N/No.\n");
68
+ console.log(`${ui_1.ui.red("✕")} ${ui_1.ui.white("Please answer with Y/Yes or N/No.")}`);
69
+ (0, ui_1.printSpacer)();
60
70
  }
71
+ console.log(`${ui_1.ui.green("✓")} ${ui_1.ui.dim("CORS")}: ${cors ? ui_1.ui.green("enabled") : ui_1.ui.gray("disabled")}`);
61
72
  let generateSampleSchemas = true;
62
73
  while (true) {
63
- const answer = await questionInterface.question("Generate sample schemas? (Y/n) ");
74
+ const answer = await questionInterface.question(formatWizardPrompt(3, "Generate sample schemas?", "Y/n", "Y"));
64
75
  const parsed = parseYesNo(answer, true);
65
76
  if (parsed !== undefined) {
66
77
  generateSampleSchemas = parsed;
67
78
  break;
68
79
  }
69
- console.log("Please answer with Y/Yes or N/No.\n");
80
+ console.log(`${ui_1.ui.red("✕")} ${ui_1.ui.white("Please answer with Y/Yes or N/No.")}`);
81
+ (0, ui_1.printSpacer)();
70
82
  }
71
- console.log("");
83
+ console.log(`${ui_1.ui.green("")} ${ui_1.ui.dim("Sample schemas")}: ${generateSampleSchemas ? ui_1.ui.green("enabled") : ui_1.ui.gray("disabled")}`);
84
+ (0, ui_1.printSpacer)();
72
85
  return {
73
86
  port,
74
87
  cors,
@@ -151,7 +164,6 @@ const initializeProject = async ({ force, }) => {
151
164
  const detectedProject = (0, detect_1.detectProject)(packageJsonPath, projectRoot);
152
165
  const fexapiDirectoryPath = (0, node_path_1.join)(projectRoot, "fexapi");
153
166
  const schemaPath = (0, node_path_1.join)(fexapiDirectoryPath, "schema.fexapi");
154
- const configPath = (0, node_path_1.join)(projectRoot, "fexapi.config.json");
155
167
  const runtimeConfigPath = (0, node_path_1.join)(projectRoot, "fexapi.config.js");
156
168
  const schemasDirectoryPath = (0, node_path_1.join)(projectRoot, "fexapi", "schemas");
157
169
  const userSchemaPath = (0, node_path_1.join)(schemasDirectoryPath, "user.yaml");
@@ -160,23 +172,7 @@ const initializeProject = async ({ force, }) => {
160
172
  (0, ui_1.printGroupHeader)("Init");
161
173
  const initSpinner = (0, ui_1.startSpinner)("Scaffolding fexapi project files");
162
174
  (0, node_fs_1.mkdirSync)(fexapiDirectoryPath, { recursive: true });
163
- const configExists = (0, node_fs_1.existsSync)(configPath);
164
175
  const schemaExists = (0, node_fs_1.existsSync)(schemaPath);
165
- const config = {
166
- framework: detectedProject.primaryFramework,
167
- frameworks: detectedProject.frameworks,
168
- tooling: detectedProject.tooling,
169
- schemaPath: "fexapi/schema.fexapi",
170
- generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
171
- defaultPort: wizardAnswers.port,
172
- corsEnabled: wizardAnswers.cors,
173
- sampleSchemasGenerated: wizardAnswers.generateSampleSchemas,
174
- createdAt: new Date().toISOString(),
175
- };
176
- if (!configExists || force) {
177
- initSpinner.update("Writing fexapi.config.json");
178
- (0, node_fs_1.writeFileSync)(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
179
- }
180
176
  if (!schemaExists || force) {
181
177
  initSpinner.update("Writing fexapi/schema.fexapi");
182
178
  (0, node_fs_1.writeFileSync)(schemaPath, `${(0, detect_1.getSchemaTemplate)(detectedProject.primaryFramework, wizardAnswers.port)}\n`, "utf-8");
@@ -222,15 +218,6 @@ const initializeProject = async ({ force, }) => {
222
218
  }
223
219
  (0, ui_1.printSpacer)();
224
220
  (0, ui_1.printGroupHeader)("Files");
225
- if (configExists && !force) {
226
- (0, ui_1.logWarn)(`Exists ${configPath}`);
227
- }
228
- else if (configExists && force) {
229
- (0, ui_1.logSuccess)(`Overwritten ${configPath}`);
230
- }
231
- else {
232
- (0, ui_1.logSuccess)(`Created ${configPath}`);
233
- }
234
221
  if (schemaExists && !force) {
235
222
  (0, ui_1.logWarn)(`Exists ${schemaPath}`);
236
223
  }
@@ -273,12 +260,11 @@ const initializeProject = async ({ force, }) => {
273
260
  (0, ui_1.logWarn)("Sample schemas were skipped.");
274
261
  }
275
262
  if (detectedProject.primaryFramework === "unknown") {
276
- (0, ui_1.logWarn)("No known framework dependency found. Update fexapi.config.json and schema.fexapi if needed.");
263
+ (0, ui_1.logWarn)("No known framework dependency found. Update fexapi.config.js and schema.fexapi if needed.");
277
264
  }
278
265
  (0, ui_1.printSpacer)();
279
266
  (0, ui_1.printGroupHeader)("Summary");
280
267
  const createdFiles = [
281
- !configExists || force,
282
268
  !schemaExists || force,
283
269
  !runtimeConfigExists || force,
284
270
  userSchemaStatus === "created" || userSchemaStatus === "overwritten",
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AASxC,eAAO,MAAM,mBAAmB,GAAI,6BAIjC;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,KAAG,MAAM,GAAG,SA2DZ,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,6BAI1B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,KAAG,MAsBH,CAAC"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AASxC,eAAO,MAAM,mBAAmB,GAAI,6BAIjC;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,KAAG,MAAM,GAAG,SA+EZ,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,6BAI1B;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,KAAG,MAsBH,CAAC"}
@@ -24,9 +24,19 @@ const createProjectServer = ({ host, port, logEnabled = false, }) => {
24
24
  ? (0, generated_spec_1.loadGeneratedApiSpec)(projectRoot)
25
25
  : undefined;
26
26
  const effectivePort = port ?? runtimeConfig?.port ?? generatedSpec?.port ?? 4000;
27
+ const configuredRoutePaths = Object.keys(runtimeConfig?.routes ?? {});
28
+ const generatedRoutePaths = new Set((generatedSpec?.routes ?? []).map((route) => route.path));
29
+ const overlappingPaths = configuredRoutePaths.filter((path) => generatedRoutePaths.has(path));
27
30
  if (runtimeConfig?.routes && Object.keys(runtimeConfig.routes).length > 0) {
28
31
  (0, ui_1.logInfo)(`Using routes from fexapi.config.js (${Object.keys(runtimeConfig.routes).length})`);
29
32
  }
33
+ if (overlappingPaths.length > 0) {
34
+ const sample = overlappingPaths.slice(0, 5).join(", ");
35
+ const more = overlappingPaths.length > 5
36
+ ? ` (+${overlappingPaths.length - 5} more)`
37
+ : "";
38
+ (0, ui_1.logWarn)(`Config routes override generated schema routes for: ${sample}${more}. Remove or edit fexapi.config.js routes if you want schema.fexapi changes to appear.`);
39
+ }
30
40
  if (Object.keys(schemaDefinitions).length > 0) {
31
41
  (0, ui_1.logInfo)(`Loaded custom schemas from fexapi/schemas (${Object.keys(schemaDefinitions).length})`);
32
42
  }
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ const main = async () => {
35
35
  (0, ui_1.printBanner)();
36
36
  (0, ui_1.printSpacer)();
37
37
  (0, ui_1.logInfo)(`Usage: ${(0, ui_1.formatCommand)("fexapi generate")}`);
38
- console.log("Reads fexapi/schema.fexapi and updates generated API artifacts + migration.");
38
+ console.log("Reads fexapi/schema.fexapi and updates generated API artifacts.");
39
39
  process.exit(0);
40
40
  }
41
41
  const generateOptions = (0, args_1.parseGenerateOptions)(restArgs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fexapi",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Mock API generation CLI tool for local development and testing",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",