create-nexwire 4.2.4 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -8
- package/express/.env +1 -1
- package/express/.vscode/extensions.json +6 -0
- package/express/.vscode/settings.json +37 -26
- package/express/biome.json +99 -66
- package/express/package.json +31 -29
- package/express/src/config/database.ts +48 -29
- package/express/src/config/index.ts +83 -83
- package/express/src/config/openapi.ts +6 -24
- package/express/src/config/queue.ts +30 -30
- package/express/src/config/validate.ts +50 -40
- package/express/src/database/migrations/sqlite/0000_init.sql +47 -47
- package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
- package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
- package/express/src/database/schema.ts +2 -2
- package/express/src/framework/cache/cache.ts +40 -8
- package/express/src/framework/circuit-breaker/cb.ts +88 -60
- package/express/src/framework/database/connection.ts +52 -27
- package/express/src/framework/events/dispatcher.ts +61 -49
- package/express/src/framework/facade.ts +46 -3
- package/express/src/framework/http/app.ts +28 -22
- package/express/src/framework/http/logger.ts +27 -16
- package/express/src/framework/http/openapi.ts +9 -11
- package/express/src/framework/modules/routes.ts +26 -21
- package/express/src/framework/notification/channels/broadcast.ts +15 -0
- package/express/src/framework/notification/channels/mail.ts +40 -0
- package/express/src/framework/notification/contracts.ts +29 -0
- package/express/src/framework/notification/index.ts +19 -94
- package/express/src/framework/notification/registry.ts +15 -0
- package/express/src/framework/providers/adapter.ts +27 -17
- package/express/src/framework/queue/queue.ts +43 -44
- package/express/src/framework/realtime/broadcast.ts +29 -5
- package/express/src/framework/realtime/socket.ts +149 -119
- package/express/src/framework/redis/client.ts +148 -151
- package/express/src/framework/runtime/server-adapter.ts +39 -34
- package/express/src/framework/scheduler/lock.ts +128 -116
- package/express/src/framework/server.ts +33 -49
- package/express/src/framework/session/session.ts +69 -14
- package/express/src/framework/storage/storage.ts +744 -785
- package/express/src/framework/support/mail.ts +15 -7
- package/express/src/providers/notification.ts +4 -0
- package/express/src/resources/src/components/Checkbox.vue +32 -29
- package/express/src/resources/src/components/Input.vue +243 -223
- package/express/src/resources/src/components/InputGroup.vue +147 -145
- package/express/src/resources/src/components/InputPasswordToggle.vue +229 -213
- package/express/src/resources/src/components/Modal.vue +71 -55
- package/express/src/resources/src/components/Refresh.vue +19 -0
- package/express/src/resources/src/helpers/assets.ts +51 -0
- package/express/src/resources/src/layouts/Layout/Header.vue +124 -105
- package/express/src/resources/src/main.ts +3 -1
- package/express/src/resources/src/plugins/gum.ts +1 -1
- package/express/src/resources/src/plugins/pulse.ts +157 -147
- package/express/src/resources/src/stores/auth.ts +184 -164
- package/express/src/resources/vite.config.ts +54 -36
- package/express/src/storage/database/nexwire.sqlite +0 -0
- package/express/src/storage/logs/app.log +0 -0
- package/express/src/storage/logs/fatal.log +0 -0
- package/express/src/types/global.d.ts +32 -26
- package/hono/.env +1 -1
- package/hono/.vscode/extensions.json +6 -0
- package/hono/.vscode/settings.json +37 -26
- package/hono/biome.json +25 -2
- package/hono/package.json +25 -23
- package/hono/src/config/database.ts +48 -29
- package/hono/src/config/index.ts +83 -83
- package/hono/src/config/openapi.ts +6 -24
- package/hono/src/config/queue.ts +30 -30
- package/hono/src/config/validate.ts +50 -40
- package/hono/src/database/migrations/sqlite/0000_init.sql +47 -47
- package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
- package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
- package/hono/src/database/schema.ts +2 -2
- package/hono/src/framework/cache/cache.ts +40 -8
- package/hono/src/framework/circuit-breaker/cb.ts +88 -60
- package/hono/src/framework/database/connection.ts +52 -27
- package/hono/src/framework/events/dispatcher.ts +61 -49
- package/hono/src/framework/facade.ts +38 -1
- package/hono/src/framework/http/openapi.ts +7 -9
- package/hono/src/framework/notification/channels/broadcast.ts +15 -0
- package/hono/src/framework/notification/channels/mail.ts +40 -0
- package/hono/src/framework/notification/contracts.ts +29 -0
- package/hono/src/framework/notification/index.ts +19 -94
- package/hono/src/framework/notification/registry.ts +15 -0
- package/hono/src/framework/providers/adapter.ts +27 -17
- package/hono/src/framework/queue/queue.ts +43 -44
- package/hono/src/framework/realtime/broadcast.ts +29 -5
- package/hono/src/framework/realtime/socket.ts +217 -196
- package/hono/src/framework/redis/client.ts +148 -151
- package/hono/src/framework/scheduler/lock.ts +128 -116
- package/hono/src/framework/server.ts +27 -29
- package/hono/src/framework/session/session.ts +62 -14
- package/hono/src/framework/storage/storage.ts +744 -785
- package/hono/src/framework/support/mail.ts +56 -48
- package/hono/src/providers/notification.ts +4 -0
- package/hono/src/resources/src/components/Checkbox.vue +32 -29
- package/hono/src/resources/src/components/Input.vue +243 -234
- package/hono/src/resources/src/components/InputGroup.vue +147 -149
- package/hono/src/resources/src/components/InputPasswordToggle.vue +229 -222
- package/hono/src/resources/src/components/Modal.vue +71 -55
- package/hono/src/resources/src/components/Refresh.vue +19 -0
- package/hono/src/resources/src/helpers/assets.ts +51 -0
- package/hono/src/resources/src/layouts/Layout/Header.vue +124 -105
- package/hono/src/resources/src/main.ts +3 -1
- package/hono/src/resources/src/plugins/gum.ts +1 -1
- package/hono/src/resources/src/plugins/pulse.ts +157 -147
- package/hono/src/resources/src/stores/auth.ts +184 -164
- package/hono/src/resources/vite.config.ts +54 -36
- package/hono/src/storage/database/nexwire.sqlite +0 -0
- package/hono/src/storage/logs/app.log +0 -0
- package/hono/src/storage/logs/fatal.log +0 -0
- package/hono/src/types/global.d.ts +32 -26
- package/package.json +2 -2
- package/src/index.js +139 -14
package/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { readFileSync, existsSync, cpSync, mkdirSync, writeFileSync, renameSync, readdirSync, rmSync } from "node:fs";
|
|
4
4
|
import { join, dirname, basename } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { createInterface } from "node:readline";
|
|
6
|
+
import { createInterface, emitKeypressEvents } from "node:readline";
|
|
7
7
|
import { gunzipSync } from "node:zlib";
|
|
8
8
|
import https from "node:https";
|
|
9
9
|
|
|
@@ -18,6 +18,104 @@ function ask(query) {
|
|
|
18
18
|
return new Promise((resolve) => rl.question(query, (a) => { rl.close(); resolve(a.trim()); }));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// Keep this in sync with the packages/ directories shipped in the tarball and
|
|
22
|
+
// with ENGINE_PREFIXES below. A future frontend adds its own list here and its
|
|
23
|
+
// own prefix inside extractTarGz.
|
|
24
|
+
const BACKENDS = [
|
|
25
|
+
{ value: "hono", label: "Hono", hint: "Hono-based HTTP layer and OpenAPI" },
|
|
26
|
+
{ value: "express", label: "Express", hint: "Express-based HTTP layer and OpenAPI" }
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const BACKEND_NAMES = BACKENDS.map((b) => b.value);
|
|
30
|
+
|
|
31
|
+
function backendIndex(value) {
|
|
32
|
+
return BACKENDS.findIndex((b) => b.value === String(value).toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const useColor = Boolean(process.stdout.isTTY && !process.env.NO_COLOR);
|
|
36
|
+
const paint = (code, text) => (useColor ? `\x1b[${code}m${text}\x1b[0m` : text);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Render an arrow-key list picker. Falls back to the default choice when
|
|
40
|
+
* stdin is not a TTY (CI, piped input) so `npm create nexwire@latest .`
|
|
41
|
+
* keeps working in scripts without hanging on a prompt.
|
|
42
|
+
*/
|
|
43
|
+
async function selectOption(title, options, defaultIndex = 0) {
|
|
44
|
+
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
45
|
+
return options[defaultIndex].value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const stdin = process.stdin;
|
|
49
|
+
const out = process.stdout;
|
|
50
|
+
let index = defaultIndex;
|
|
51
|
+
const lines = options.length + 2; // title + options + trailing help line
|
|
52
|
+
|
|
53
|
+
emitKeypressEvents(stdin);
|
|
54
|
+
stdin.setRawMode(true);
|
|
55
|
+
stdin.resume();
|
|
56
|
+
out.write("\x1b[?25l"); // hide the cursor while the list is live
|
|
57
|
+
|
|
58
|
+
const render = (first) => {
|
|
59
|
+
if (!first) out.write(`\x1b[${lines}A`);
|
|
60
|
+
out.write(`${paint(1, title)}\n`);
|
|
61
|
+
options.forEach((option, i) => {
|
|
62
|
+
const active = i === index;
|
|
63
|
+
const marker = active ? paint(32, "\u276F") : " ";
|
|
64
|
+
const label = paint(active ? 1 : 0, option.label);
|
|
65
|
+
const hint = option.hint ? ` ${paint(2, option.hint)}` : "";
|
|
66
|
+
out.write(`${marker} ${label}${hint}\x1b[K\n`);
|
|
67
|
+
});
|
|
68
|
+
out.write(`${paint(2, "Arrow keys choose, 1-2 jump, Enter confirm")}\n`);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
render(true);
|
|
72
|
+
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
const cleanup = () => {
|
|
75
|
+
stdin.setRawMode(false);
|
|
76
|
+
stdin.removeListener("keypress", onKeypress);
|
|
77
|
+
stdin.pause();
|
|
78
|
+
out.write("\x1b[?25h"); // restore the cursor
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const onKeypress = (str, key = {}) => {
|
|
82
|
+
if (key.ctrl && key.name === "c") {
|
|
83
|
+
cleanup();
|
|
84
|
+
out.write("\n");
|
|
85
|
+
process.exit(130);
|
|
86
|
+
}
|
|
87
|
+
if (key.name === "escape") {
|
|
88
|
+
cleanup();
|
|
89
|
+
out.write("\n");
|
|
90
|
+
process.exit(130);
|
|
91
|
+
}
|
|
92
|
+
if (key.name === "up" || key.name === "k") {
|
|
93
|
+
index = (index - 1 + options.length) % options.length;
|
|
94
|
+
render(false);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (key.name === "down" || key.name === "j") {
|
|
98
|
+
index = (index + 1) % options.length;
|
|
99
|
+
render(false);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (key.name === "return" || key.name === "enter") {
|
|
103
|
+
cleanup();
|
|
104
|
+
out.write("\n");
|
|
105
|
+
resolve(options[index].value);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const digit = Number(str);
|
|
109
|
+
if (Number.isInteger(digit) && digit >= 1 && digit <= options.length) {
|
|
110
|
+
index = digit - 1;
|
|
111
|
+
render(false);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
stdin.on("keypress", onKeypress);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
21
119
|
function detectPackageManager() {
|
|
22
120
|
if (typeof process !== "undefined" && process.isBun) return "bun";
|
|
23
121
|
const ua = process.env.npm_config_user_agent || "";
|
|
@@ -116,26 +214,26 @@ function fetchTarball(pkgName, pkgVersion) {
|
|
|
116
214
|
|
|
117
215
|
async function main() {
|
|
118
216
|
const args = process.argv.slice(2);
|
|
119
|
-
|
|
120
|
-
|
|
217
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
121
218
|
const engineArg = args.find((a) => a.startsWith("--engine="));
|
|
122
|
-
let
|
|
123
|
-
|
|
124
|
-
if (!ENGINE_PREFIXES[engine]) {
|
|
125
|
-
console.error(`Error: Unknown engine "${engine}". Supported engines: hono, express.`);
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
219
|
+
let projectName = args.find((a) => !a.startsWith("--"));
|
|
128
220
|
|
|
221
|
+
// --help works even with --engine set, and before any prompt or network call.
|
|
129
222
|
if (args.includes("--help") || args.includes("-h")) {
|
|
130
223
|
console.log(`create-nexwire v${version}`);
|
|
131
224
|
console.log();
|
|
132
225
|
console.log("Usage:");
|
|
133
|
-
console.log(" npm create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
134
|
-
console.log(" pnpm create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
135
|
-
console.log(" bun create nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
136
|
-
console.log(" npx create-nexwire@latest <project-name|.> [--engine=<hono|express>]");
|
|
226
|
+
console.log(" npm create nexwire@latest <project-name|.> [--engine=<hono|express>] [--yes]");
|
|
227
|
+
console.log(" pnpm create nexwire@latest <project-name|.> [--engine=<hono|express>] [--yes]");
|
|
228
|
+
console.log(" bun create nexwire@latest <project-name|.> [--engine=<hono|express>] [--yes]");
|
|
229
|
+
console.log(" npx create-nexwire@latest <project-name|.> [--engine=<hono|express>] [--yes]");
|
|
137
230
|
console.log();
|
|
138
|
-
console.log("
|
|
231
|
+
console.log("Options:");
|
|
232
|
+
console.log(" --engine=<hono|express> Backend to scaffold. Asked interactively when omitted.");
|
|
233
|
+
console.log(" -y, --yes Skip prompts and accept the defaults (requires a project name).");
|
|
234
|
+
console.log(" -h, --help Show this help.");
|
|
235
|
+
console.log();
|
|
236
|
+
console.log("Backends:");
|
|
139
237
|
console.log(" hono (default) Hono-based HTTP layer and OpenAPI");
|
|
140
238
|
console.log(" express Express-based HTTP layer and OpenAPI");
|
|
141
239
|
console.log();
|
|
@@ -144,7 +242,25 @@ async function main() {
|
|
|
144
242
|
process.exit(0);
|
|
145
243
|
}
|
|
146
244
|
|
|
245
|
+
if (engineArg === undefined && args.includes("--engine")) {
|
|
246
|
+
console.error('Error: Missing value for --engine. Use --engine=hono or --engine=express.');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (engineArg) {
|
|
251
|
+
const engine = engineArg.split("=")[1].toLowerCase();
|
|
252
|
+
if (backendIndex(engine) === -1) {
|
|
253
|
+
console.error(`Error: Unknown engine "${engine}". Supported backends: ${BACKEND_NAMES.join(", ")}.`);
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
147
258
|
if (!projectName) {
|
|
259
|
+
if (!process.stdin.isTTY || yes) {
|
|
260
|
+
console.error("Error: Please provide a project name or '.' to scaffold into the current directory.");
|
|
261
|
+
console.error(" A project name is required when the CLI runs without an interactive terminal.");
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
148
264
|
projectName = await ask("Project name or '.' for the current directory: ");
|
|
149
265
|
}
|
|
150
266
|
|
|
@@ -158,6 +274,15 @@ async function main() {
|
|
|
158
274
|
process.exit(1);
|
|
159
275
|
}
|
|
160
276
|
|
|
277
|
+
let engine = engineArg ? engineArg.split("=")[1].toLowerCase() : null;
|
|
278
|
+
if (!engine) {
|
|
279
|
+
if (yes) {
|
|
280
|
+
engine = "hono";
|
|
281
|
+
} else {
|
|
282
|
+
engine = await selectOption("Choose a backend:", BACKENDS, 0);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
161
286
|
const targetDir = resolveTargetDir(projectName);
|
|
162
287
|
const isCurrentDir = targetDir === process.cwd();
|
|
163
288
|
|