fexapi 0.2.1 → 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.
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +2 -4
- package/dist/cli/ui.d.ts +2 -0
- package/dist/cli/ui.d.ts.map +1 -1
- package/dist/cli/ui.js +99 -26
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +1 -2
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +6 -55
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +30 -43
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +10 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,
|
|
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
|
|
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:
|
|
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;
|
package/dist/cli/ui.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const ui: {
|
|
|
8
8
|
yellow: (text: string) => string;
|
|
9
9
|
red: (text: string) => string;
|
|
10
10
|
gray: (text: string) => string;
|
|
11
|
+
white: (text: string) => string;
|
|
11
12
|
};
|
|
12
13
|
type SpinnerController = {
|
|
13
14
|
update: (text: string) => void;
|
|
@@ -22,6 +23,7 @@ export declare const printSummaryCard: (title: string, rows: Array<{
|
|
|
22
23
|
label: string;
|
|
23
24
|
value: string;
|
|
24
25
|
}>) => void;
|
|
26
|
+
export declare const printGroupHeader: (title: string) => void;
|
|
25
27
|
export declare const printBanner: () => void;
|
|
26
28
|
export declare const printSpacer: () => void;
|
|
27
29
|
export declare const logInfo: (message: string) => void;
|
package/dist/cli/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"
|
|
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
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatCommand = exports.logStep = exports.logError = exports.logWarn = exports.logSuccess = exports.logInfo = exports.printSpacer = exports.printBanner = exports.printSummaryCard = exports.formatDuration = exports.nowMs = exports.startSpinner = exports.ui = void 0;
|
|
3
|
+
exports.formatCommand = exports.logStep = exports.logError = exports.logWarn = exports.logSuccess = exports.logInfo = exports.printSpacer = exports.printBanner = exports.printGroupHeader = exports.printSummaryCard = exports.formatDuration = exports.nowMs = exports.startSpinner = exports.ui = void 0;
|
|
4
4
|
const shouldUseColor = () => {
|
|
5
5
|
return Boolean(process.stdout.isTTY);
|
|
6
6
|
};
|
|
7
7
|
const colorEnabled = shouldUseColor();
|
|
8
8
|
const interactive = Boolean(process.stdout.isTTY);
|
|
9
|
+
const DEFAULT_TERMINAL_WIDTH = 80;
|
|
9
10
|
const paint = (code, text) => {
|
|
10
11
|
if (!colorEnabled) {
|
|
11
12
|
return text;
|
|
@@ -22,8 +23,43 @@ exports.ui = {
|
|
|
22
23
|
yellow: (text) => paint("33", text),
|
|
23
24
|
red: (text) => paint("31", text),
|
|
24
25
|
gray: (text) => paint("90", text),
|
|
26
|
+
white: (text) => paint("97", text),
|
|
27
|
+
};
|
|
28
|
+
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
29
|
+
const ANSI_REGEX = /\u001b\[[0-9;]*m/g;
|
|
30
|
+
const stripAnsi = (text) => text.replace(ANSI_REGEX, "");
|
|
31
|
+
const visibleLength = (text) => stripAnsi(text).length;
|
|
32
|
+
const getTerminalWidth = () => {
|
|
33
|
+
const columns = process.stdout.columns;
|
|
34
|
+
if (!columns || Number.isNaN(columns)) {
|
|
35
|
+
return DEFAULT_TERMINAL_WIDTH;
|
|
36
|
+
}
|
|
37
|
+
return Math.max(40, columns);
|
|
38
|
+
};
|
|
39
|
+
const truncateText = (text, maxLength) => {
|
|
40
|
+
if (text.length <= maxLength) {
|
|
41
|
+
return text;
|
|
42
|
+
}
|
|
43
|
+
if (maxLength <= 1) {
|
|
44
|
+
return text.slice(0, maxLength);
|
|
45
|
+
}
|
|
46
|
+
return `${text.slice(0, maxLength - 1)}…`;
|
|
47
|
+
};
|
|
48
|
+
const styleCardValue = (value) => {
|
|
49
|
+
const normalized = value.trim().toLowerCase();
|
|
50
|
+
if (normalized === "changed" ||
|
|
51
|
+
normalized === "enabled" ||
|
|
52
|
+
normalized === "running") {
|
|
53
|
+
return exports.ui.green(exports.ui.bold(value));
|
|
54
|
+
}
|
|
55
|
+
if (normalized === "cached" || normalized === "disabled") {
|
|
56
|
+
return exports.ui.gray(value);
|
|
57
|
+
}
|
|
58
|
+
if (normalized === "stopped" || normalized === "failed") {
|
|
59
|
+
return exports.ui.red(exports.ui.bold(value));
|
|
60
|
+
}
|
|
61
|
+
return exports.ui.white(exports.ui.bold(value));
|
|
25
62
|
};
|
|
26
|
-
const SPINNER_FRAMES = ["-", "\\", "|", "/"];
|
|
27
63
|
const clearCurrentLine = () => {
|
|
28
64
|
if (!interactive) {
|
|
29
65
|
return;
|
|
@@ -45,7 +81,7 @@ const startSpinner = (initialText) => {
|
|
|
45
81
|
const render = () => {
|
|
46
82
|
const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length] ?? "-";
|
|
47
83
|
frameIndex += 1;
|
|
48
|
-
process.stdout.write(`\r${exports.ui.cyan(frame)} ${exports.ui.bold(text)}`);
|
|
84
|
+
process.stdout.write(`\r${exports.ui.cyan(frame)} ${exports.ui.white(exports.ui.bold(text))}`);
|
|
49
85
|
};
|
|
50
86
|
render();
|
|
51
87
|
const timer = setInterval(render, 80);
|
|
@@ -56,12 +92,12 @@ const startSpinner = (initialText) => {
|
|
|
56
92
|
succeed: (finalText) => {
|
|
57
93
|
clearInterval(timer);
|
|
58
94
|
clearCurrentLine();
|
|
59
|
-
console.log(`${exports.ui.green("
|
|
95
|
+
console.log(`${exports.ui.green("✓")} ${exports.ui.white(finalText)}`);
|
|
60
96
|
},
|
|
61
97
|
fail: (finalText) => {
|
|
62
98
|
clearInterval(timer);
|
|
63
99
|
clearCurrentLine();
|
|
64
|
-
console.log(`${exports.ui.red("
|
|
100
|
+
console.log(`${exports.ui.red("✕")} ${exports.ui.white(finalText)}`);
|
|
65
101
|
},
|
|
66
102
|
stop: () => {
|
|
67
103
|
clearInterval(timer);
|
|
@@ -81,25 +117,62 @@ const formatDuration = (startMs) => {
|
|
|
81
117
|
};
|
|
82
118
|
exports.formatDuration = formatDuration;
|
|
83
119
|
const printSummaryCard = (title, rows) => {
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
120
|
+
const terminalWidth = getTerminalWidth();
|
|
121
|
+
const compactMode = terminalWidth < 64;
|
|
122
|
+
if (compactMode) {
|
|
123
|
+
console.log(exports.ui.gray(`+-- ${title} --+`));
|
|
124
|
+
for (const row of rows) {
|
|
125
|
+
console.log(`${exports.ui.dim(row.label)} ${exports.ui.gray("::")} ${styleCardValue(row.value)}`);
|
|
126
|
+
}
|
|
127
|
+
console.log(exports.ui.gray("+----------------+"));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const safeRows = rows.map((row) => ({
|
|
131
|
+
label: row.label,
|
|
132
|
+
value: row.value,
|
|
133
|
+
}));
|
|
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));
|
|
137
|
+
const innerWidth = cardWidth - 2;
|
|
138
|
+
const labelWidth = Math.min(20, Math.max(10, ...safeRows.map((row) => visibleLength(row.label))));
|
|
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
|
+
};
|
|
144
|
+
const topBorder = `┌${"─".repeat(innerWidth)}┐`;
|
|
145
|
+
const divider = `├${"─".repeat(innerWidth)}┤`;
|
|
146
|
+
const bottomBorder = `└${"─".repeat(innerWidth)}┘`;
|
|
147
|
+
console.log(exports.ui.gray(topBorder));
|
|
148
|
+
const renderedTitle = truncateText(title, innerWidth - 2);
|
|
149
|
+
console.log(renderBoxLine(exports.ui.bold(exports.ui.cyan(renderedTitle))));
|
|
150
|
+
console.log(exports.ui.gray(divider));
|
|
151
|
+
for (const row of safeRows) {
|
|
152
|
+
const rawValue = stripAnsi(row.value);
|
|
153
|
+
const value = truncateText(rawValue, valueSpace);
|
|
154
|
+
const label = row.label.padEnd(labelWidth, " ");
|
|
155
|
+
const styledValue = styleCardValue(value);
|
|
156
|
+
console.log(renderBoxLine(`${exports.ui.dim(label)} ${exports.ui.gray("::")} ${styledValue}`));
|
|
99
157
|
}
|
|
100
|
-
console.log(exports.ui.gray(
|
|
158
|
+
console.log(exports.ui.gray(bottomBorder));
|
|
101
159
|
};
|
|
102
160
|
exports.printSummaryCard = printSummaryCard;
|
|
161
|
+
const printGroupHeader = (title) => {
|
|
162
|
+
const terminalWidth = getTerminalWidth();
|
|
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("┐")}`);
|
|
174
|
+
};
|
|
175
|
+
exports.printGroupHeader = printGroupHeader;
|
|
103
176
|
const printBanner = () => {
|
|
104
177
|
console.log(exports.ui.bold(exports.ui.cyan("fexapi")) +
|
|
105
178
|
exports.ui.gray(" ") +
|
|
@@ -112,23 +185,23 @@ const printSpacer = () => {
|
|
|
112
185
|
};
|
|
113
186
|
exports.printSpacer = printSpacer;
|
|
114
187
|
const logInfo = (message) => {
|
|
115
|
-
console.log(`${exports.ui.blue("info")} ${message}`);
|
|
188
|
+
console.log(`${exports.ui.blue("•")} ${exports.ui.blue("info")} ${exports.ui.white(message)}`);
|
|
116
189
|
};
|
|
117
190
|
exports.logInfo = logInfo;
|
|
118
191
|
const logSuccess = (message) => {
|
|
119
|
-
console.log(`${exports.ui.green("ok ")} ${message}`);
|
|
192
|
+
console.log(`${exports.ui.green("✓")} ${exports.ui.green("ok ")} ${exports.ui.white(message)}`);
|
|
120
193
|
};
|
|
121
194
|
exports.logSuccess = logSuccess;
|
|
122
195
|
const logWarn = (message) => {
|
|
123
|
-
console.log(`${exports.ui.yellow("warn")} ${message}`);
|
|
196
|
+
console.log(`${exports.ui.yellow("!")} ${exports.ui.yellow("warn")} ${exports.ui.white(message)}`);
|
|
124
197
|
};
|
|
125
198
|
exports.logWarn = logWarn;
|
|
126
199
|
const logError = (message) => {
|
|
127
|
-
console.error(`${exports.ui.red("err ")} ${message}`);
|
|
200
|
+
console.error(`${exports.ui.red("✕")} ${exports.ui.red("err ")} ${exports.ui.white(message)}`);
|
|
128
201
|
};
|
|
129
202
|
exports.logError = logError;
|
|
130
203
|
const logStep = (message) => {
|
|
131
|
-
console.log(`${exports.ui.cyan("
|
|
204
|
+
console.log(`${exports.ui.cyan("›")} ${exports.ui.white(message)}`);
|
|
132
205
|
};
|
|
133
206
|
exports.logStep = logStep;
|
|
134
207
|
const formatCommand = (command) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -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":"
|
|
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,13 +21,12 @@ 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.");
|
|
30
27
|
return 1;
|
|
31
28
|
}
|
|
29
|
+
(0, ui_1.printGroupHeader)("Generate");
|
|
32
30
|
const generationSpinner = (0, ui_1.startSpinner)("Reading schema");
|
|
33
31
|
const schemaText = (0, node_fs_1.readFileSync)(schemaPath, "utf-8");
|
|
34
32
|
generationSpinner.update("Parsing schema routes");
|
|
@@ -66,62 +64,23 @@ const generateFromSchema = () => {
|
|
|
66
64
|
port: parsed.schema.port,
|
|
67
65
|
routes: parsed.schema.routes,
|
|
68
66
|
};
|
|
69
|
-
(0, node_fs_1.mkdirSync)(migrationsDirectoryPath, { recursive: true });
|
|
70
|
-
const migrationPath = (0, node_path_1.join)(migrationsDirectoryPath, "schema.json");
|
|
71
|
-
const migration = {
|
|
72
|
-
migrationId: new Date().toISOString().replace(/[.:]/g, "-"),
|
|
73
|
-
sourceSchema: "fexapi/schema.fexapi",
|
|
74
|
-
createdAt: generated.generatedAt,
|
|
75
|
-
port: parsed.schema.port,
|
|
76
|
-
routes: parsed.schema.routes,
|
|
77
|
-
};
|
|
78
67
|
let generatedStatus = "cached";
|
|
79
|
-
let migrationStatus = "cached";
|
|
80
68
|
if (schemaChanged || !(0, node_fs_1.existsSync)(generatedPath)) {
|
|
81
69
|
generationSpinner.update("Writing generated API spec");
|
|
82
70
|
(0, node_fs_1.writeFileSync)(generatedPath, `${JSON.stringify(generated, null, 2)}\n`, "utf-8");
|
|
83
71
|
generatedStatus = "changed";
|
|
84
72
|
}
|
|
85
|
-
if (schemaChanged || !(0, node_fs_1.existsSync)(migrationPath)) {
|
|
86
|
-
generationSpinner.update("Updating migration snapshot");
|
|
87
|
-
(0, node_fs_1.writeFileSync)(migrationPath, `${JSON.stringify(migration, null, 2)}\n`, "utf-8");
|
|
88
|
-
migrationStatus = "changed";
|
|
89
|
-
}
|
|
90
|
-
let existingConfig = {};
|
|
91
|
-
if ((0, node_fs_1.existsSync)(configPath)) {
|
|
92
|
-
try {
|
|
93
|
-
existingConfig = JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf-8"));
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
existingConfig = {};
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const updatedConfig = {
|
|
100
|
-
...existingConfig,
|
|
101
|
-
schemaPath: "fexapi/schema.fexapi",
|
|
102
|
-
generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
|
|
103
|
-
...(schemaChanged ? { lastGeneratedAt: new Date().toISOString() } : {}),
|
|
104
|
-
};
|
|
105
|
-
generationSpinner.update("Syncing project config");
|
|
106
|
-
const nextConfigText = `${JSON.stringify(updatedConfig, null, 2)}\n`;
|
|
107
|
-
const previousConfigText = (0, node_fs_1.existsSync)(configPath)
|
|
108
|
-
? (0, node_fs_1.readFileSync)(configPath, "utf-8")
|
|
109
|
-
: undefined;
|
|
110
|
-
let configStatus = "cached";
|
|
111
|
-
if (previousConfigText !== nextConfigText) {
|
|
112
|
-
(0, node_fs_1.writeFileSync)(configPath, nextConfigText, "utf-8");
|
|
113
|
-
configStatus = "changed";
|
|
114
|
-
}
|
|
115
73
|
generationSpinner.succeed(`Generate complete (${schemaChanged ? "changed" : "cached"})`);
|
|
116
74
|
(0, ui_1.printSpacer)();
|
|
75
|
+
(0, ui_1.printGroupHeader)("Summary");
|
|
117
76
|
(0, ui_1.printSummaryCard)("Generate Summary", [
|
|
118
77
|
{
|
|
119
78
|
label: "routes",
|
|
120
|
-
value:
|
|
79
|
+
value: String(parsed.schema.routes.length),
|
|
121
80
|
},
|
|
122
81
|
{
|
|
123
82
|
label: "port",
|
|
124
|
-
value:
|
|
83
|
+
value: String(parsed.schema.port),
|
|
125
84
|
},
|
|
126
85
|
{
|
|
127
86
|
label: "schema source",
|
|
@@ -129,19 +88,11 @@ const generateFromSchema = () => {
|
|
|
129
88
|
},
|
|
130
89
|
{
|
|
131
90
|
label: "generated.api.json",
|
|
132
|
-
value: generatedStatus
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
label: "migration",
|
|
136
|
-
value: migrationStatus === "changed" ? ui_1.ui.green("changed") : ui_1.ui.gray("cached"),
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
label: "config",
|
|
140
|
-
value: configStatus === "changed" ? ui_1.ui.green("changed") : ui_1.ui.gray("cached"),
|
|
91
|
+
value: generatedStatus,
|
|
141
92
|
},
|
|
142
93
|
{
|
|
143
94
|
label: "time",
|
|
144
|
-
value:
|
|
95
|
+
value: (0, ui_1.formatDuration)(startedAtMs),
|
|
145
96
|
},
|
|
146
97
|
]);
|
|
147
98
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/commands/init.js
CHANGED
|
@@ -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(
|
|
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
|
|
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?
|
|
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
|
|
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?
|
|
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
|
|
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,31 +164,15 @@ 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");
|
|
158
170
|
const postSchemaPath = (0, node_path_1.join)(schemasDirectoryPath, "post.yaml");
|
|
159
171
|
const wizardAnswers = await askInitWizardQuestions();
|
|
172
|
+
(0, ui_1.printGroupHeader)("Init");
|
|
160
173
|
const initSpinner = (0, ui_1.startSpinner)("Scaffolding fexapi project files");
|
|
161
174
|
(0, node_fs_1.mkdirSync)(fexapiDirectoryPath, { recursive: true });
|
|
162
|
-
const configExists = (0, node_fs_1.existsSync)(configPath);
|
|
163
175
|
const schemaExists = (0, node_fs_1.existsSync)(schemaPath);
|
|
164
|
-
const config = {
|
|
165
|
-
framework: detectedProject.primaryFramework,
|
|
166
|
-
frameworks: detectedProject.frameworks,
|
|
167
|
-
tooling: detectedProject.tooling,
|
|
168
|
-
schemaPath: "fexapi/schema.fexapi",
|
|
169
|
-
generatedPath: constants_1.GENERATED_SPEC_RELATIVE_PATH,
|
|
170
|
-
defaultPort: wizardAnswers.port,
|
|
171
|
-
corsEnabled: wizardAnswers.cors,
|
|
172
|
-
sampleSchemasGenerated: wizardAnswers.generateSampleSchemas,
|
|
173
|
-
createdAt: new Date().toISOString(),
|
|
174
|
-
};
|
|
175
|
-
if (!configExists || force) {
|
|
176
|
-
initSpinner.update("Writing fexapi.config.json");
|
|
177
|
-
(0, node_fs_1.writeFileSync)(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
|
|
178
|
-
}
|
|
179
176
|
if (!schemaExists || force) {
|
|
180
177
|
initSpinner.update("Writing fexapi/schema.fexapi");
|
|
181
178
|
(0, node_fs_1.writeFileSync)(schemaPath, `${(0, detect_1.getSchemaTemplate)(detectedProject.primaryFramework, wizardAnswers.port)}\n`, "utf-8");
|
|
@@ -220,15 +217,7 @@ const initializeProject = async ({ force, }) => {
|
|
|
220
217
|
(0, ui_1.logInfo)(`Detected tooling: ${detectedProject.tooling.join(", ")}`);
|
|
221
218
|
}
|
|
222
219
|
(0, ui_1.printSpacer)();
|
|
223
|
-
|
|
224
|
-
(0, ui_1.logWarn)(`Exists ${configPath}`);
|
|
225
|
-
}
|
|
226
|
-
else if (configExists && force) {
|
|
227
|
-
(0, ui_1.logSuccess)(`Overwritten ${configPath}`);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
(0, ui_1.logSuccess)(`Created ${configPath}`);
|
|
231
|
-
}
|
|
220
|
+
(0, ui_1.printGroupHeader)("Files");
|
|
232
221
|
if (schemaExists && !force) {
|
|
233
222
|
(0, ui_1.logWarn)(`Exists ${schemaPath}`);
|
|
234
223
|
}
|
|
@@ -271,11 +260,11 @@ const initializeProject = async ({ force, }) => {
|
|
|
271
260
|
(0, ui_1.logWarn)("Sample schemas were skipped.");
|
|
272
261
|
}
|
|
273
262
|
if (detectedProject.primaryFramework === "unknown") {
|
|
274
|
-
(0, ui_1.logWarn)("No known framework dependency found. Update fexapi.config.
|
|
263
|
+
(0, ui_1.logWarn)("No known framework dependency found. Update fexapi.config.js and schema.fexapi if needed.");
|
|
275
264
|
}
|
|
276
265
|
(0, ui_1.printSpacer)();
|
|
266
|
+
(0, ui_1.printGroupHeader)("Summary");
|
|
277
267
|
const createdFiles = [
|
|
278
|
-
!configExists || force,
|
|
279
268
|
!schemaExists || force,
|
|
280
269
|
!runtimeConfigExists || force,
|
|
281
270
|
userSchemaStatus === "created" || userSchemaStatus === "overwritten",
|
|
@@ -288,25 +277,23 @@ const initializeProject = async ({ force, }) => {
|
|
|
288
277
|
},
|
|
289
278
|
{
|
|
290
279
|
label: "port",
|
|
291
|
-
value:
|
|
280
|
+
value: String(wizardAnswers.port),
|
|
292
281
|
},
|
|
293
282
|
{
|
|
294
283
|
label: "cors",
|
|
295
|
-
value: wizardAnswers.cors ?
|
|
284
|
+
value: wizardAnswers.cors ? "enabled" : "disabled",
|
|
296
285
|
},
|
|
297
286
|
{
|
|
298
287
|
label: "sample schemas",
|
|
299
|
-
value: wizardAnswers.generateSampleSchemas
|
|
300
|
-
? ui_1.ui.green("enabled")
|
|
301
|
-
: ui_1.ui.gray("disabled"),
|
|
288
|
+
value: wizardAnswers.generateSampleSchemas ? "enabled" : "disabled",
|
|
302
289
|
},
|
|
303
290
|
{
|
|
304
291
|
label: "files changed",
|
|
305
|
-
value:
|
|
292
|
+
value: String(createdFiles),
|
|
306
293
|
},
|
|
307
294
|
{
|
|
308
295
|
label: "time",
|
|
309
|
-
value:
|
|
296
|
+
value: (0, ui_1.formatDuration)(initStartedAtMs),
|
|
310
297
|
},
|
|
311
298
|
]);
|
|
312
299
|
(0, ui_1.printSpacer)();
|
|
@@ -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,
|
|
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"}
|
package/dist/commands/serve.js
CHANGED
|
@@ -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
|
|
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);
|