@fedify/init 2.4.0-dev.1805 → 2.4.0-dev.1832
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/action/patch.js +3 -1
- package/dist/action/templates.js +14 -2
- package/dist/deno.js +1 -1
- package/dist/templates/defaults/smoke.test.ts.tpl +170 -0
- package/dist/types.d.ts +2 -0
- package/dist/webframeworks/astro.js +8 -3
- package/dist/webframeworks/bare-bones.js +6 -2
- package/dist/webframeworks/elysia.js +6 -2
- package/dist/webframeworks/express.js +6 -2
- package/dist/webframeworks/hono.js +6 -2
- package/dist/webframeworks/next.js +8 -3
- package/dist/webframeworks/nitro.js +10 -3
- package/dist/webframeworks/nuxt.js +8 -3
- package/dist/webframeworks/solidstart.js +8 -3
- package/dist/webframeworks/sveltekit.js +8 -3
- package/dist/webframeworks/utils.js +15 -1
- package/package.json +1 -1
package/dist/action/patch.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createFile, throwUnlessNotExists } from "../lib.js";
|
|
|
3
3
|
import { displayFile, noticeFilesToCreate, noticeFilesToInsert } from "./notice.js";
|
|
4
4
|
import { joinDir, stringifyEnvs } from "./utils.js";
|
|
5
5
|
import { devToolConfigs, loadDenoConfig, loadOxfmtConfig, loadOxlintConfig, loadPackageJson, loadTsConfig, loadVscodeExtensions, loadVscodeSettings } from "./configs.js";
|
|
6
|
-
import { getImports, loadFederation, loadLogging } from "./templates.js";
|
|
6
|
+
import { getImports, loadFederation, loadLogging, loadTest } from "./templates.js";
|
|
7
7
|
import { always, apply, entries, map, pipe, pipeLazy, tap } from "@fxts/core";
|
|
8
8
|
import { toMerged } from "es-toolkit";
|
|
9
9
|
import { access, readFile } from "node:fs/promises";
|
|
@@ -80,6 +80,7 @@ const getFiles = async (data) => ({
|
|
|
80
80
|
...data
|
|
81
81
|
}),
|
|
82
82
|
[data.initializer.loggingFile]: await loadLogging(data),
|
|
83
|
+
[data.initializer.testFile]: await loadTest(data),
|
|
83
84
|
".env": stringifyEnvs(data.env),
|
|
84
85
|
...data.initializer.files
|
|
85
86
|
});
|
|
@@ -119,6 +120,7 @@ const getJsons = (data) => {
|
|
|
119
120
|
const getGeneratedFilePaths = (data) => [
|
|
120
121
|
data.initializer.federationFile,
|
|
121
122
|
data.initializer.loggingFile,
|
|
123
|
+
data.initializer.testFile,
|
|
122
124
|
".env",
|
|
123
125
|
...Object.keys(data.initializer.files ?? {}),
|
|
124
126
|
...Object.keys(getJsons(data)),
|
package/dist/action/templates.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { replace } from "../utils.js";
|
|
2
|
-
import { readTemplate } from "../lib.js";
|
|
2
|
+
import { getDevCommand, readTemplate } from "../lib.js";
|
|
3
3
|
import { needsDenoDotenv } from "./utils.js";
|
|
4
4
|
import { concat, entries, join, map, pipe, when } from "@fxts/core";
|
|
5
5
|
import { toMerged } from "es-toolkit";
|
|
@@ -30,6 +30,18 @@ const getFederationTemplate = (packageManager) => packageManager === "deno" ? "d
|
|
|
30
30
|
*/
|
|
31
31
|
const loadLogging = async ({ projectName, initializer }) => pipe(await readTemplate(initializer.loggingTemplate ?? "defaults/logging.ts"), replace(/\/\* project name \*\//, JSON.stringify(projectName)));
|
|
32
32
|
/**
|
|
33
|
+
* Loads the smoke-test script content for the initializer.
|
|
34
|
+
*
|
|
35
|
+
* Every framework shares the same *defaults/smoke.test.ts* template, so unlike
|
|
36
|
+
* {@link loadLogging} there is no per-framework template override. The
|
|
37
|
+
* template spawns the project's own dev server, so it needs the dev command
|
|
38
|
+
* for the chosen package manager baked in at generation time.
|
|
39
|
+
*
|
|
40
|
+
* @param param0 - {@link InitCommandData} containing `packageManager`
|
|
41
|
+
* @returns The complete smoke-test script content as a string
|
|
42
|
+
*/
|
|
43
|
+
const loadTest = async ({ packageManager }) => pipe(await readTemplate("defaults/smoke.test.ts"), replace(/\/\* dev command \*\//, JSON.stringify(getDevCommand(packageManager).split(" ")).replaceAll(",", ", ")));
|
|
44
|
+
/**
|
|
33
45
|
* Generates import statements for KV store and message queue dependencies.
|
|
34
46
|
* Merges imports from both KV and MQ configurations and creates proper
|
|
35
47
|
* ES module import syntax.
|
|
@@ -75,4 +87,4 @@ const ENV_REG_EXP = /process\.env\.(\w+)/g;
|
|
|
75
87
|
*/
|
|
76
88
|
const convertEnv = (obj, pm) => pm === "deno" && ENV_REG_EXP.test(obj) ? obj.replaceAll(ENV_REG_EXP, (_, g1) => `Deno.env.get("${g1}")`) : obj;
|
|
77
89
|
//#endregion
|
|
78
|
-
export { convertEnv, getAlias, getImports, loadFederation, loadLogging };
|
|
90
|
+
export { convertEnv, getAlias, getImports, loadFederation, loadLogging, loadTest };
|
package/dist/deno.js
CHANGED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { getDocumentLoader } from "@fedify/fedify";
|
|
2
|
+
import { type Actor, isActor, lookupObject } from "@fedify/vocab";
|
|
3
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
4
|
+
import type { Readable } from "node:stream";
|
|
5
|
+
|
|
6
|
+
const DEV_COMMAND: string[] = /* dev command */;
|
|
7
|
+
const HANDLE = "john";
|
|
8
|
+
const STARTUP_TIMEOUT = 15_000;
|
|
9
|
+
const IS_WINDOWS = process.platform === "win32";
|
|
10
|
+
|
|
11
|
+
async function main(): Promise<void> {
|
|
12
|
+
const [command, ...args] = DEV_COMMAND;
|
|
13
|
+
const server = spawn(command, args, {
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
15
|
+
shell: IS_WINDOWS,
|
|
16
|
+
windowsHide: true,
|
|
17
|
+
detached: !IS_WINDOWS,
|
|
18
|
+
});
|
|
19
|
+
server.on("error", () => {});
|
|
20
|
+
|
|
21
|
+
const exitOnSignal = () => {
|
|
22
|
+
stopServer(server);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
};
|
|
25
|
+
process.once("SIGINT", exitOnSignal);
|
|
26
|
+
process.once("SIGTERM", exitOnSignal);
|
|
27
|
+
|
|
28
|
+
let output = "";
|
|
29
|
+
const collectOutput = (stream: Readable | null) => {
|
|
30
|
+
const decoder = new TextDecoder();
|
|
31
|
+
stream?.on("data", (chunk: Buffer) => {
|
|
32
|
+
output += decoder.decode(chunk, { stream: true });
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
collectOutput(server.stdout);
|
|
36
|
+
collectOutput(server.stderr);
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const port = await determinePort(server);
|
|
40
|
+
const target = `http://localhost:${port}/users/${HANDLE}`;
|
|
41
|
+
await waitForServer(target);
|
|
42
|
+
console.log(`Server is up at http://localhost:${port}.`);
|
|
43
|
+
const actor = await checkActor(target);
|
|
44
|
+
console.log(actor);
|
|
45
|
+
console.log(`Smoke test passed: ${target} resolved to an actor.`);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error("Smoke test failed:", error instanceof Error ? error.message : error);
|
|
48
|
+
if (output.trim() !== "") {
|
|
49
|
+
console.error(`\nDev server output:\n${output}`);
|
|
50
|
+
}
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
} finally {
|
|
53
|
+
stopServer(server);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function stripEscape(text: string): string {
|
|
58
|
+
return text.replace(new RegExp("\\u001B\\[[0-9;]*[A-Za-z]", "g"), "");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function determinePort(server: ReturnType<typeof spawn>): Promise<number> {
|
|
62
|
+
const portPatterns = [
|
|
63
|
+
/listening on.*:(\d+)/i,
|
|
64
|
+
/server.*:(\d+)/i,
|
|
65
|
+
/https?:\/\/localhost:(\d+)/i,
|
|
66
|
+
/https?:\/\/0\.0\.0\.0:(\d+)/i,
|
|
67
|
+
/https?:\/\/127\.0\.0\.1:(\d+)/i,
|
|
68
|
+
/https?:\/\/[^:]+:(\d+)/i,
|
|
69
|
+
];
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const timeout = setTimeout(() => {
|
|
72
|
+
reject(
|
|
73
|
+
new Error(
|
|
74
|
+
`Timeout: Could not determine port from server output within ${STARTUP_TIMEOUT}ms.`,
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
}, STARTUP_TIMEOUT);
|
|
78
|
+
|
|
79
|
+
const findPort = (text: string) => {
|
|
80
|
+
for (const pattern of portPatterns) {
|
|
81
|
+
const match = text.match(pattern);
|
|
82
|
+
if (match && match[1]) {
|
|
83
|
+
const port = Number.parseInt(match[1], 10);
|
|
84
|
+
if (port > 0 && port < 65536) return port;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const scan = (stream: Readable | null) => {
|
|
91
|
+
const decoder = new TextDecoder();
|
|
92
|
+
let text = "";
|
|
93
|
+
stream?.on("data", (chunk: Buffer) => {
|
|
94
|
+
text += decoder.decode(chunk, { stream: true });
|
|
95
|
+
const port = findPort(stripEscape(text));
|
|
96
|
+
if (port != null) {
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
resolve(port);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
scan(server.stdout);
|
|
104
|
+
scan(server.stderr);
|
|
105
|
+
server.once("exit", (code) => {
|
|
106
|
+
clearTimeout(timeout);
|
|
107
|
+
reject(new Error(`The dev server exited early with code ${String(code)}.`));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function waitForServer(url: string): Promise<void> {
|
|
113
|
+
const startTime = Date.now();
|
|
114
|
+
let lastStatus: number | undefined;
|
|
115
|
+
|
|
116
|
+
while (Date.now() - startTime < STARTUP_TIMEOUT) {
|
|
117
|
+
try {
|
|
118
|
+
const response = await fetch(url, {
|
|
119
|
+
headers: { Accept: "application/activity+json" },
|
|
120
|
+
signal: AbortSignal.timeout(1000),
|
|
121
|
+
});
|
|
122
|
+
await response.body?.cancel();
|
|
123
|
+
if (response.ok) return;
|
|
124
|
+
lastStatus = response.status;
|
|
125
|
+
} catch {
|
|
126
|
+
// Server not ready yet, continue waiting
|
|
127
|
+
}
|
|
128
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
129
|
+
}
|
|
130
|
+
throw new Error(
|
|
131
|
+
`The server did not become ready within ${STARTUP_TIMEOUT}ms.` +
|
|
132
|
+
(lastStatus == null ? "" : ` Last response status: ${lastStatus}.`),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function checkActor(url: string): Promise<Actor> {
|
|
137
|
+
const object = await lookupObject(url, {
|
|
138
|
+
documentLoader: getDocumentLoader({ allowPrivateAddress: true }),
|
|
139
|
+
});
|
|
140
|
+
if (object == null) {
|
|
141
|
+
throw new Error(`Could not resolve an actor at ${url}.`);
|
|
142
|
+
}
|
|
143
|
+
if (!isActor(object)) {
|
|
144
|
+
throw new Error(`Expected an actor at ${url}, but got a non-actor object.`);
|
|
145
|
+
}
|
|
146
|
+
return object;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function stopServer(server: ReturnType<typeof spawn>): void {
|
|
150
|
+
if (server.pid == null) return;
|
|
151
|
+
if (IS_WINDOWS) {
|
|
152
|
+
spawnSync("taskkill", ["/pid", String(server.pid), "/T", "/F"], {
|
|
153
|
+
stdio: "ignore",
|
|
154
|
+
windowsHide: true,
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
process.kill(-server.pid, "SIGKILL");
|
|
160
|
+
} catch {
|
|
161
|
+
// Process group already exited.
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
server.kill("SIGKILL");
|
|
165
|
+
} catch {
|
|
166
|
+
// Process already exited.
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
await main();
|
package/dist/types.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ interface WebFrameworkInitializer {
|
|
|
30
30
|
federationFile: string;
|
|
31
31
|
/** Relative path where the logging configuration file will be created. */
|
|
32
32
|
loggingFile: string;
|
|
33
|
+
/** Relative path where the smoke-test script file will be created. */
|
|
34
|
+
testFile: string;
|
|
33
35
|
/** Optional template path for the logging configuration file. */
|
|
34
36
|
loggingTemplate?: string;
|
|
35
37
|
/**
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "@logtape/logtape" as _logtape_logtape, "npm:@astrojs/node" as npm__astrojs_node, "npm:@deno/astro-adapter" as npm__deno_astro_adapter, "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@types/node@22" as npm__types_node_22, "npm:astro" as npm_astro, "npm:create-astro" as npm_create_astro, "npm:oxlint" as npm_oxlint, "npm:prettier" as npm_prettier, "npm:prettier-plugin-astro" as npm_prettier_plugin_astro, "npm:typescript" as npm_typescript } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestDependencies, getTestTask, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/astro.ts
|
|
7
7
|
const astroNodeBunDevDependencies = {
|
|
8
8
|
"@fedify/lint": PACKAGE_VERSION,
|
|
@@ -55,10 +55,12 @@ const astroDescription = {
|
|
|
55
55
|
...pm !== "deno" ? {
|
|
56
56
|
typescript: npm_typescript,
|
|
57
57
|
"@types/node": npm__types_node_22
|
|
58
|
-
} : {}
|
|
58
|
+
} : {},
|
|
59
|
+
...getTestDependencies(pm)
|
|
59
60
|
},
|
|
60
61
|
federationFile: "src/federation.ts",
|
|
61
62
|
loggingFile: "src/logging.ts",
|
|
63
|
+
testFile: "scripts/smoke.test.ts",
|
|
62
64
|
format: pm === "deno" ? void 0 : { tool: "prettier" },
|
|
63
65
|
files: {
|
|
64
66
|
"astro.config.ts": await readTemplate(`astro/astro.config.${pmToRt(pm)}.ts`),
|
|
@@ -107,18 +109,21 @@ const TASKS = {
|
|
|
107
109
|
"deno": {
|
|
108
110
|
dev: `${astroDenoCommand} dev`,
|
|
109
111
|
build: `${astroDenoCommand} build`,
|
|
110
|
-
preview: `${astroDenoCommand} preview
|
|
112
|
+
preview: `${astroDenoCommand} preview`,
|
|
113
|
+
test: getTestTask("deno")
|
|
111
114
|
},
|
|
112
115
|
"bun": {
|
|
113
116
|
dev: "bunx --bun astro dev",
|
|
114
117
|
build: "bunx --bun astro build",
|
|
115
118
|
preview: "bun ./dist/server/entry.mjs",
|
|
119
|
+
test: getTestTask("bun"),
|
|
116
120
|
...astroNodeBunDevToolTasks
|
|
117
121
|
},
|
|
118
122
|
"node": {
|
|
119
123
|
dev: "dotenvx run -- astro dev",
|
|
120
124
|
build: "dotenvx run -- astro build",
|
|
121
125
|
preview: "dotenvx run -- astro preview",
|
|
126
|
+
test: getTestTask("npm"),
|
|
122
127
|
...astroNodeBunDevToolTasks
|
|
123
128
|
}
|
|
124
129
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { readTemplate } from "../lib.js";
|
|
3
3
|
import { "@hongminhee/x-forwarded-fetch" as _hongminhee_x_forwarded_fetch, "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@hono/node-server" as npm__hono_node_server, "npm:@types/bun" as npm__types_bun, "npm:@types/node@25" as npm__types_node_25, "npm:tsx" as npm_tsx, "npm:x-forwarded-fetch" as npm_x_forwarded_fetch } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/bare-bones.ts
|
|
7
7
|
const bareBonesDescription = {
|
|
8
8
|
label: "Bare-bones",
|
|
@@ -16,6 +16,7 @@ const bareBonesDescription = {
|
|
|
16
16
|
},
|
|
17
17
|
federationFile: "src/federation.ts",
|
|
18
18
|
loggingFile: "src/logging.ts",
|
|
19
|
+
testFile: "scripts/smoke.test.ts",
|
|
19
20
|
files: { "src/main.ts": await readTemplate(`bare-bones/main/${pmToRt(pm)}.ts`) },
|
|
20
21
|
compilerOptions: pm === "deno" ? {
|
|
21
22
|
"jsx": "precompile",
|
|
@@ -46,16 +47,19 @@ const getDependencies = (pm) => pm === "deno" ? {
|
|
|
46
47
|
const TASKS = {
|
|
47
48
|
deno: {
|
|
48
49
|
dev: "deno run -A --watch ./src/main.ts",
|
|
49
|
-
prod: "deno run -A ./src/main.ts"
|
|
50
|
+
prod: "deno run -A ./src/main.ts",
|
|
51
|
+
test: getTestTask("deno")
|
|
50
52
|
},
|
|
51
53
|
bun: {
|
|
52
54
|
dev: "bun run --hot ./src/main.ts",
|
|
53
55
|
prod: "bun run ./src/main.ts",
|
|
56
|
+
test: getTestTask("bun"),
|
|
54
57
|
...nodeBunDevToolTasks
|
|
55
58
|
},
|
|
56
59
|
node: {
|
|
57
60
|
dev: "dotenvx run -- tsx watch ./src/main.ts",
|
|
58
61
|
prod: "dotenvx run -- node --import tsx ./src/main.ts",
|
|
62
|
+
test: getTestTask("npm"),
|
|
59
63
|
...nodeBunDevToolTasks
|
|
60
64
|
}
|
|
61
65
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@elysiajs/node" as npm__elysiajs_node, "npm:@sinclair/typebox" as npm__sinclair_typebox, "npm:@types/bun" as npm__types_bun, "npm:@types/node@25" as npm__types_node_25, "npm:elysia" as npm_elysia, "npm:openapi-types" as npm_openapi_types, "npm:tsx" as npm_tsx, "npm:typescript" as npm_typescript } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/elysia.ts
|
|
7
7
|
const elysiaDescription = {
|
|
8
8
|
label: "Elysia",
|
|
@@ -36,6 +36,7 @@ const elysiaDescription = {
|
|
|
36
36
|
},
|
|
37
37
|
federationFile: "src/federation.ts",
|
|
38
38
|
loggingFile: "src/logging.ts",
|
|
39
|
+
testFile: "scripts/smoke.test.ts",
|
|
39
40
|
files: { "src/index.ts": (await readTemplate(`elysia/index/${pmToRt(pm)}.ts`)).replace(/\/\* logger \*\//, projectName) },
|
|
40
41
|
compilerOptions: pm === "deno" || pm === "bun" ? void 0 : {
|
|
41
42
|
"lib": ["ESNext", "DOM"],
|
|
@@ -54,17 +55,20 @@ const elysiaDescription = {
|
|
|
54
55
|
const TASKS = {
|
|
55
56
|
deno: {
|
|
56
57
|
dev: "deno serve --allow-read --allow-env --allow-net --watch ./src/index.ts",
|
|
57
|
-
prod: "deno serve --allow-read --allow-env --allow-net ./src/index.ts"
|
|
58
|
+
prod: "deno serve --allow-read --allow-env --allow-net ./src/index.ts",
|
|
59
|
+
test: getTestTask("deno")
|
|
58
60
|
},
|
|
59
61
|
bun: {
|
|
60
62
|
dev: "bun run --hot ./src/index.ts",
|
|
61
63
|
prod: "bun run ./src/index.ts",
|
|
64
|
+
test: getTestTask("bun"),
|
|
62
65
|
...nodeBunDevToolTasks
|
|
63
66
|
},
|
|
64
67
|
node: {
|
|
65
68
|
dev: "dotenvx run -- tsx watch src/index.ts",
|
|
66
69
|
build: "tsc src/index.ts --outDir dist",
|
|
67
70
|
start: "NODE_ENV=production dotenvx run -- node dist/index.js",
|
|
71
|
+
test: getTestTask("npm"),
|
|
68
72
|
...nodeBunDevToolTasks
|
|
69
73
|
}
|
|
70
74
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@types/bun" as npm__types_bun, "npm:@types/express" as npm__types_express, "npm:express" as npm_express, "npm:tsx" as npm_tsx } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/express.ts
|
|
7
7
|
const expressDescription = {
|
|
8
8
|
label: "Express",
|
|
@@ -25,6 +25,7 @@ const expressDescription = {
|
|
|
25
25
|
},
|
|
26
26
|
federationFile: "src/federation.ts",
|
|
27
27
|
loggingFile: "src/logging.ts",
|
|
28
|
+
testFile: "scripts/smoke.test.ts",
|
|
28
29
|
files: {
|
|
29
30
|
"src/app.ts": (await readTemplate("express/app.ts")).replace(/\/\* logger \*\//, projectName),
|
|
30
31
|
"src/index.ts": await readTemplate("express/index.ts")
|
|
@@ -46,16 +47,19 @@ const expressDescription = {
|
|
|
46
47
|
const TASKS = {
|
|
47
48
|
deno: {
|
|
48
49
|
dev: "deno run --allow-read --allow-net --allow-env --allow-sys --watch ./src/index.ts",
|
|
49
|
-
prod: "deno run --allow-read --allow-net --allow-env --allow-sys ./src/index.ts"
|
|
50
|
+
prod: "deno run --allow-read --allow-net --allow-env --allow-sys ./src/index.ts",
|
|
51
|
+
test: getTestTask("deno")
|
|
50
52
|
},
|
|
51
53
|
bun: {
|
|
52
54
|
dev: "bun run --hot ./src/index.ts",
|
|
53
55
|
prod: "bun run ./src/index.ts",
|
|
56
|
+
test: getTestTask("bun"),
|
|
54
57
|
...nodeBunDevToolTasks
|
|
55
58
|
},
|
|
56
59
|
node: {
|
|
57
60
|
dev: "dotenvx run -- tsx watch ./src/index.ts",
|
|
58
61
|
prod: "dotenvx run -- node --import tsx ./src/index.ts",
|
|
62
|
+
test: getTestTask("npm"),
|
|
59
63
|
...nodeBunDevToolTasks
|
|
60
64
|
}
|
|
61
65
|
};
|
|
@@ -3,7 +3,7 @@ import { replace } from "../utils.js";
|
|
|
3
3
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
4
4
|
import { "@hongminhee/x-forwarded-fetch" as _hongminhee_x_forwarded_fetch, "@hono/hono" as _hono_hono, "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@hono/node-server" as npm__hono_node_server, "npm:@types/bun" as npm__types_bun, "npm:hono" as npm_hono, "npm:tsx" as npm_tsx, "npm:x-forwarded-fetch" as npm_x_forwarded_fetch } from "../json/deps.js";
|
|
5
5
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
6
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
|
+
import { getInstruction, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
7
7
|
import { pipe } from "@fxts/core";
|
|
8
8
|
//#region src/webframeworks/hono.ts
|
|
9
9
|
const honoDescription = {
|
|
@@ -18,6 +18,7 @@ const honoDescription = {
|
|
|
18
18
|
},
|
|
19
19
|
federationFile: "src/federation.ts",
|
|
20
20
|
loggingFile: "src/logging.ts",
|
|
21
|
+
testFile: "scripts/smoke.test.ts",
|
|
21
22
|
files: {
|
|
22
23
|
"src/app.tsx": pipe(await readTemplate("hono/app.tsx"), replace(/\/\* hono \*\//, pm === "deno" ? "@hono/hono" : "hono"), replace(/\/\* logger \*\//, projectName)),
|
|
23
24
|
"src/index.ts": await readTemplate(`hono/index/${pmToRt(pm)}.ts`)
|
|
@@ -58,16 +59,19 @@ const getDependencies = (pm) => pm === "deno" ? {
|
|
|
58
59
|
const TASKS = {
|
|
59
60
|
deno: {
|
|
60
61
|
dev: "deno run -A --watch ./src/index.ts",
|
|
61
|
-
prod: "deno run -A ./src/index.ts"
|
|
62
|
+
prod: "deno run -A ./src/index.ts",
|
|
63
|
+
test: getTestTask("deno")
|
|
62
64
|
},
|
|
63
65
|
bun: {
|
|
64
66
|
dev: "bun run --hot ./src/index.ts",
|
|
65
67
|
prod: "bun run ./src/index.ts",
|
|
68
|
+
test: getTestTask("bun"),
|
|
66
69
|
...nodeBunDevToolTasks
|
|
67
70
|
},
|
|
68
71
|
node: {
|
|
69
72
|
dev: "dotenvx run -- tsx watch ./src/index.ts",
|
|
70
73
|
prod: "dotenvx run -- node --import tsx ./src/index.ts",
|
|
74
|
+
test: getTestTask("npm"),
|
|
71
75
|
...nodeBunDevToolTasks
|
|
72
76
|
}
|
|
73
77
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@types/node@20" as npm__types_node_20 } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, getNodeBunDevToolTasks } from "./utils.js";
|
|
5
|
+
import { getInstruction, getNodeBunDevToolTasks, getTestDependencies, getTestTask } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/next.ts
|
|
7
7
|
const nextDescription = {
|
|
8
8
|
label: "Next.js",
|
|
@@ -21,16 +21,21 @@ const nextDescription = {
|
|
|
21
21
|
},
|
|
22
22
|
devDependencies: {
|
|
23
23
|
"@types/node": npm__types_node_20,
|
|
24
|
-
...defaultDevDependencies
|
|
24
|
+
...defaultDevDependencies,
|
|
25
|
+
...getTestDependencies(pm)
|
|
25
26
|
},
|
|
26
27
|
federationFile: "federation/index.ts",
|
|
27
28
|
loggingFile: "logging.ts",
|
|
29
|
+
testFile: "scripts/smoke.test.ts",
|
|
28
30
|
format: { ignorePatterns: [".next/**"] },
|
|
29
31
|
files: {
|
|
30
32
|
"instrumentation.ts": await readTemplate("next/instrumentation.ts"),
|
|
31
33
|
"middleware.ts": await readTemplate("next/middleware.ts")
|
|
32
34
|
},
|
|
33
|
-
tasks:
|
|
35
|
+
tasks: {
|
|
36
|
+
...getNodeBunDevToolTasks(pm),
|
|
37
|
+
test: getTestTask(pm)
|
|
38
|
+
},
|
|
34
39
|
instruction: getInstruction(pm, 3e3)
|
|
35
40
|
})
|
|
36
41
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PACKAGE_MANAGER } from "../const.js";
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
4
|
-
import { getInstruction, getNodeBunDevToolTasks } from "./utils.js";
|
|
4
|
+
import { getInstruction, getNodeBunDevToolTasks, getTestDependencies, getTestTask } from "./utils.js";
|
|
5
5
|
//#region src/webframeworks/nitro.ts
|
|
6
6
|
const nitroDescription = {
|
|
7
7
|
label: "Nitro",
|
|
@@ -19,9 +19,13 @@ const nitroDescription = {
|
|
|
19
19
|
"@fedify/h3": PACKAGE_VERSION,
|
|
20
20
|
...pm === "deno" && defaultDenoDependencies
|
|
21
21
|
},
|
|
22
|
-
devDependencies:
|
|
22
|
+
devDependencies: {
|
|
23
|
+
...defaultDevDependencies,
|
|
24
|
+
...getTestDependencies(pm)
|
|
25
|
+
},
|
|
23
26
|
federationFile: "server/federation.ts",
|
|
24
27
|
loggingFile: "server/logging.ts",
|
|
28
|
+
testFile: "scripts/smoke.test.ts",
|
|
25
29
|
format: { ignorePatterns: [".output/**"] },
|
|
26
30
|
env: testMode ? { HOST: "127.0.0.1" } : {},
|
|
27
31
|
files: {
|
|
@@ -51,7 +55,10 @@ const nitroDescription = {
|
|
|
51
55
|
lib: ["ESNext", "DOM"],
|
|
52
56
|
baseUrl: "."
|
|
53
57
|
},
|
|
54
|
-
tasks:
|
|
58
|
+
tasks: {
|
|
59
|
+
...getNodeBunDevToolTasks(pm),
|
|
60
|
+
test: getTestTask(pm)
|
|
61
|
+
},
|
|
55
62
|
instruction: getInstruction(pm, 3e3)
|
|
56
63
|
})
|
|
57
64
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@types/node@25" as npm__types_node_25, "npm:typescript" as npm_typescript } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, getNodeBunDevToolTasks } from "./utils.js";
|
|
5
|
+
import { getInstruction, getNodeBunDevToolTasks, getTestDependencies, getTestTask } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/nuxt.ts
|
|
7
7
|
const nuxtDescription = {
|
|
8
8
|
label: "Nuxt",
|
|
@@ -14,18 +14,23 @@ const nuxtDescription = {
|
|
|
14
14
|
devDependencies: {
|
|
15
15
|
...defaultDevDependencies,
|
|
16
16
|
"typescript": npm_typescript,
|
|
17
|
-
"@types/node": npm__types_node_25
|
|
17
|
+
"@types/node": npm__types_node_25,
|
|
18
|
+
...getTestDependencies(pm)
|
|
18
19
|
},
|
|
19
20
|
federationFile: "server/federation.ts",
|
|
20
21
|
loggingFile: "server/logging.ts",
|
|
21
22
|
loggingTemplate: "nuxt/server/logging.ts",
|
|
23
|
+
testFile: "scripts/smoke.test.ts",
|
|
22
24
|
format: { ignorePatterns: [".output/**"] },
|
|
23
25
|
env: testMode ? { HOST: "127.0.0.1" } : {},
|
|
24
26
|
files: {
|
|
25
27
|
"nuxt.config.ts": await readTemplate("nuxt/nuxt.config.ts"),
|
|
26
28
|
"server/plugins/logging.ts": await readTemplate("nuxt/server/plugins/logging.ts")
|
|
27
29
|
},
|
|
28
|
-
tasks:
|
|
30
|
+
tasks: {
|
|
31
|
+
...getNodeBunDevToolTasks(pm),
|
|
32
|
+
test: getTestTask(pm)
|
|
33
|
+
},
|
|
29
34
|
instruction: getInstruction(pm, 3e3)
|
|
30
35
|
})
|
|
31
36
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@solidjs/router" as npm__solidjs_router, "npm:@solidjs/start" as npm__solidjs_start, "npm:@types/node@22" as npm__types_node_22, "npm:solid-js" as npm_solid_js, "npm:typescript" as npm_typescript, "npm:vinxi" as npm_vinxi } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestDependencies, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/solidstart.ts
|
|
7
7
|
const NPM_SOLIDSTART = `npm:@solidjs/start@${npm__solidjs_start}`;
|
|
8
8
|
const solidstartDescription = {
|
|
@@ -14,10 +14,12 @@ const solidstartDescription = {
|
|
|
14
14
|
devDependencies: {
|
|
15
15
|
...defaultDevDependencies,
|
|
16
16
|
typescript: npm_typescript,
|
|
17
|
-
"@types/node": npm__types_node_22
|
|
17
|
+
"@types/node": npm__types_node_22,
|
|
18
|
+
...getTestDependencies(pm)
|
|
18
19
|
},
|
|
19
20
|
federationFile: "src/federation.ts",
|
|
20
21
|
loggingFile: "src/logging.ts",
|
|
22
|
+
testFile: "scripts/smoke.test.ts",
|
|
21
23
|
format: { ignorePatterns: [".solid/**", ".vinxi/**"] },
|
|
22
24
|
files: {
|
|
23
25
|
"app.config.ts": (await readTemplate("solidstart/app.config.ts")).replace(/\/\* preset \*\//, pm === "deno" ? "deno-server" : "node-server"),
|
|
@@ -70,18 +72,21 @@ const TASKS = {
|
|
|
70
72
|
deno: {
|
|
71
73
|
dev: "deno run -A npm:vinxi dev",
|
|
72
74
|
build: "deno run -A npm:vinxi build",
|
|
73
|
-
start: "deno run -A npm:vinxi start"
|
|
75
|
+
start: "deno run -A npm:vinxi start",
|
|
76
|
+
test: getTestTask("deno")
|
|
74
77
|
},
|
|
75
78
|
bun: {
|
|
76
79
|
dev: "bunx vinxi dev",
|
|
77
80
|
build: "bunx vinxi build",
|
|
78
81
|
start: "bunx vinxi start",
|
|
82
|
+
test: getTestTask("bun"),
|
|
79
83
|
...nodeBunDevToolTasks
|
|
80
84
|
},
|
|
81
85
|
node: {
|
|
82
86
|
dev: "vinxi dev",
|
|
83
87
|
build: "vinxi build",
|
|
84
88
|
start: "dotenvx run -- vinxi start",
|
|
89
|
+
test: getTestTask("npm"),
|
|
85
90
|
...nodeBunDevToolTasks
|
|
86
91
|
}
|
|
87
92
|
};
|
|
@@ -2,7 +2,7 @@ import { PACKAGE_MANAGER } from "../const.js";
|
|
|
2
2
|
import { PACKAGE_VERSION, readTemplate } from "../lib.js";
|
|
3
3
|
import { "npm:@dotenvx/dotenvx" as npm__dotenvx_dotenvx, "npm:@types/node@25" as npm__types_node_25, "npm:typescript" as npm_typescript } from "../json/deps.js";
|
|
4
4
|
import { defaultDenoDependencies, defaultDevDependencies } from "./const.js";
|
|
5
|
-
import { getInstruction, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
5
|
+
import { getInstruction, getTestDependencies, getTestTask, nodeBunDevToolTasks, pmToRt } from "./utils.js";
|
|
6
6
|
//#region src/webframeworks/sveltekit.ts
|
|
7
7
|
const sveltekitDescription = {
|
|
8
8
|
label: "SvelteKit",
|
|
@@ -18,13 +18,18 @@ const sveltekitDescription = {
|
|
|
18
18
|
...defaultDevDependencies,
|
|
19
19
|
"typescript": npm_typescript,
|
|
20
20
|
"@types/node": npm__types_node_25,
|
|
21
|
-
...pmToRt(pm) === "deno" ? {} : { "@dotenvx/dotenvx": npm__dotenvx_dotenvx }
|
|
21
|
+
...pmToRt(pm) === "deno" ? {} : { "@dotenvx/dotenvx": npm__dotenvx_dotenvx },
|
|
22
|
+
...getTestDependencies(pm)
|
|
22
23
|
},
|
|
23
24
|
federationFile: "src/lib/federation.ts",
|
|
24
25
|
loggingFile: "src/lib/logging.ts",
|
|
26
|
+
testFile: "scripts/smoke.test.ts",
|
|
25
27
|
env: testMode ? { HOST: "127.0.0.1" } : {},
|
|
26
28
|
files: { "src/hooks.server.ts": await readTemplate("sveltekit/hooks.server.ts") },
|
|
27
|
-
tasks: pmToRt(pm) === "deno" ? {} : {
|
|
29
|
+
tasks: pmToRt(pm) === "deno" ? { test: getTestTask("deno") } : {
|
|
30
|
+
...TASKS,
|
|
31
|
+
test: getTestTask(pm)
|
|
32
|
+
},
|
|
28
33
|
instruction: getInstruction(pm, 5173)
|
|
29
34
|
})
|
|
30
35
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDevCommand } from "../lib.js";
|
|
2
|
+
import { "npm:tsx" as npm_tsx } from "../json/deps.js";
|
|
2
3
|
import { commandLine, message } from "@optique/core/message";
|
|
3
4
|
//#region src/webframeworks/utils.ts
|
|
4
5
|
const nodeBunDevToolTasks = {
|
|
@@ -7,6 +8,19 @@ const nodeBunDevToolTasks = {
|
|
|
7
8
|
lint: "oxlint ."
|
|
8
9
|
};
|
|
9
10
|
const getNodeBunDevToolTasks = (pm) => pm === "deno" ? {} : nodeBunDevToolTasks;
|
|
11
|
+
const SMOKE_TEST_FILE = "scripts/smoke.test.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Returns the `test` task command that runs the generated smoke-test
|
|
14
|
+
* script (`WebFrameworkInitializer.testFile`) with the runtime matching the
|
|
15
|
+
* given package manager.
|
|
16
|
+
*/
|
|
17
|
+
const getTestTask = (pm) => pmToRt(pm) === "deno" ? `deno run -A ${SMOKE_TEST_FILE}` : pmToRt(pm) === "bun" ? `bun run ${SMOKE_TEST_FILE}` : `tsx ${SMOKE_TEST_FILE}`;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the dev dependencies the `test` task needs beyond what the
|
|
20
|
+
* framework already declares. Node.js runs the smoke-test script through
|
|
21
|
+
* `tsx`; Deno and Bun execute TypeScript natively.
|
|
22
|
+
*/
|
|
23
|
+
const getTestDependencies = (pm) => pmToRt(pm) === "node" ? { tsx: npm_tsx } : {};
|
|
10
24
|
/**
|
|
11
25
|
* Generates the post-initialization instruction message that shows
|
|
12
26
|
* the user how to start the dev server and look up an actor.
|
|
@@ -32,4 +46,4 @@ Then, try to look up an actor from your server:
|
|
|
32
46
|
*/
|
|
33
47
|
const pmToRt = (pm) => pm !== "deno" && pm !== "bun" ? "node" : pm;
|
|
34
48
|
//#endregion
|
|
35
|
-
export { getInstruction, getNodeBunDevToolTasks, nodeBunDevToolTasks, pmToRt };
|
|
49
|
+
export { getInstruction, getNodeBunDevToolTasks, getTestDependencies, getTestTask, nodeBunDevToolTasks, pmToRt };
|