@fedify/init 2.1.0-dev.421 → 2.1.0-dev.444
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/configs.js +20 -52
- package/dist/action/const.js +4 -0
- package/dist/action/deps.js +1 -1
- package/dist/action/env.js +5 -0
- package/dist/action/install.js +4 -0
- package/dist/action/notice.js +21 -0
- package/dist/action/set.js +1 -1
- package/dist/action/utils.js +7 -0
- package/dist/ask/mod.js +6 -0
- package/dist/ask/pm.js +1 -1
- package/dist/ask/wf.js +1 -1
- package/dist/command.d.ts +16 -3
- package/dist/command.js +11 -0
- package/dist/const.d.ts +3 -0
- package/dist/const.js +9 -0
- package/dist/deno.js +1 -1
- package/dist/json/kv.js +18 -0
- package/dist/json/kv.json +15 -0
- package/dist/lib.js +50 -50
- package/dist/templates/astro/astro.config.deno.ts.tpl +10 -0
- package/dist/templates/astro/astro.config.node.ts.tpl +10 -0
- package/dist/templates/astro/src/middleware.ts.tpl +4 -0
- package/dist/test/create.js +5 -2
- package/dist/test/lookup.js +2 -2
- package/dist/test/utils.js +1 -1
- package/dist/types.d.ts +61 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +60 -0
- package/dist/webframeworks/astro.js +83 -0
- package/dist/webframeworks/const.js +11 -0
- package/dist/webframeworks/elysia.js +66 -0
- package/dist/webframeworks/express.js +54 -0
- package/dist/webframeworks/hono.js +66 -0
- package/dist/webframeworks/mod.js +27 -0
- package/dist/webframeworks/next.js +56 -0
- package/dist/webframeworks/nitro.js +53 -0
- package/dist/webframeworks/utils.js +31 -0
- package/package.json +1 -1
- package/dist/webframeworks.js +0 -220
package/dist/action/configs.js
CHANGED
|
@@ -4,12 +4,11 @@ import vscode_settings_for_deno_default from "../json/vscode-settings-for-deno.j
|
|
|
4
4
|
import vscode_settings_default from "../json/vscode-settings.js";
|
|
5
5
|
import { PACKAGES_PATH } from "./const.js";
|
|
6
6
|
import { getDependencies, getDevDependencies, joinDepsReg } from "./deps.js";
|
|
7
|
-
import { uniq } from "es-toolkit";
|
|
8
7
|
import { execFileSync } from "node:child_process";
|
|
9
8
|
import { getLogger } from "@logtape/logtape";
|
|
10
9
|
import { realpathSync } from "node:fs";
|
|
11
10
|
import { join, relative } from "node:path";
|
|
12
|
-
import { concat, filter, keys, map, pick, pipe, toArray } from "@fxts/core/index.js";
|
|
11
|
+
import { always, cases, concat, filter, head, isArray, isEmpty, isNull, isString, keys, map, pick, pipe, prop, toArray, uniq, unless, when, zip } from "@fxts/core/index.js";
|
|
13
12
|
|
|
14
13
|
//#region src/action/configs.ts
|
|
15
14
|
const logger = getLogger([
|
|
@@ -25,36 +24,27 @@ const logger = getLogger([
|
|
|
25
24
|
* @param param0 - Destructured initialization data containing KV, MQ, initializer, and directory
|
|
26
25
|
* @returns Configuration object with path and Deno-specific settings
|
|
27
26
|
*/
|
|
28
|
-
const loadDenoConfig = (data) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
const getUnstable = ({ kv: { denoUnstable: kv = [] }, mq: { denoUnstable: mq = [] } }) => pipe(needsUnstableTemporal() ? ["temporal"] : [], concat(kv), concat(mq), toArray, uniq);
|
|
27
|
+
const loadDenoConfig = (data) => ({
|
|
28
|
+
path: "deno.json",
|
|
29
|
+
data: {
|
|
30
|
+
...pick(["compilerOptions", "tasks"], data.initializer),
|
|
31
|
+
...getUnstable(data),
|
|
32
|
+
nodeModulesDir: "auto",
|
|
33
|
+
imports: joinDepsReg("deno")(getDependencies(data)),
|
|
34
|
+
lint: { plugins: ["jsr:@fedify/lint"] },
|
|
35
|
+
...data.testMode && !data.dryRun ? { links: getLinks(data) } : {}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const getUnstable = ({ kv: { denoUnstable: kv = [] }, mq: { denoUnstable: mq = [] } }) => pipe(needsUnstableTemporal() ? ["temporal"] : [], concat(kv), concat(mq), uniq, toArray, cases(isEmpty, always({}), (unstable) => ({ unstable })));
|
|
43
39
|
const TEMPORAL_STABLE_FROM = [
|
|
44
40
|
2,
|
|
45
41
|
7,
|
|
46
42
|
0
|
|
47
43
|
];
|
|
48
|
-
const needsUnstableTemporal = () =>
|
|
49
|
-
|
|
50
|
-
if (version == null) return true;
|
|
51
|
-
return compareVersions(version, TEMPORAL_STABLE_FROM) < 0;
|
|
52
|
-
};
|
|
53
|
-
const getInstalledDenoVersion = () => {
|
|
54
|
-
const deno = getDenoVersionFromRuntime();
|
|
55
|
-
if (deno != null) return deno;
|
|
44
|
+
const needsUnstableTemporal = () => pipe(getDenoVersionFromRuntime(), when(isNull, getDenoVersionFromCommand), when(isString, parseVersion), cases(isArray, isLaterOrEqualThan(TEMPORAL_STABLE_FROM), always(true)));
|
|
45
|
+
const getDenoVersionFromCommand = () => {
|
|
56
46
|
try {
|
|
57
|
-
|
|
47
|
+
return execFileSync("deno", ["--version"], {
|
|
58
48
|
encoding: "utf8",
|
|
59
49
|
stdio: [
|
|
60
50
|
"ignore",
|
|
@@ -62,37 +52,15 @@ const getInstalledDenoVersion = () => {
|
|
|
62
52
|
"ignore"
|
|
63
53
|
]
|
|
64
54
|
});
|
|
65
|
-
const version = output.match(/^deno\s+(\d+)\.(\d+)\.(\d+)/m);
|
|
66
|
-
if (version == null) return null;
|
|
67
|
-
return [
|
|
68
|
-
Number(version[1]),
|
|
69
|
-
Number(version[2]),
|
|
70
|
-
Number(version[3])
|
|
71
|
-
];
|
|
72
55
|
} catch (error) {
|
|
73
56
|
logger.debug("Failed to get Deno version by executing `deno --version`: {error}", { error });
|
|
74
57
|
return null;
|
|
75
58
|
}
|
|
76
59
|
};
|
|
77
|
-
const getDenoVersionFromRuntime = () =>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (version == null) return null;
|
|
82
|
-
return [
|
|
83
|
-
Number(version[1]),
|
|
84
|
-
Number(version[2]),
|
|
85
|
-
Number(version[3])
|
|
86
|
-
];
|
|
87
|
-
};
|
|
88
|
-
const compareVersions = (a, b) => {
|
|
89
|
-
for (let i = 0; i < a.length; i++) {
|
|
90
|
-
if (a[i] < b[i]) return -1;
|
|
91
|
-
if (a[i] > b[i]) return 1;
|
|
92
|
-
}
|
|
93
|
-
return 0;
|
|
94
|
-
};
|
|
95
|
-
const getLinks = ({ kv, mq, initializer, dir }) => pipe({ "@fedify/fedify": "" }, merge(initializer.dependencies), merge(kv.dependencies), merge(mq.dependencies), keys, filter((dep) => dep.includes("@fedify/")), map((dep) => dep.replace("@fedify/", "")), map((dep) => join(PACKAGES_PATH, dep)), map((absolutePath) => realpathSync(absolutePath)), map((realAbsolutePath) => relative(realpathSync(dir), realAbsolutePath)), toArray);
|
|
60
|
+
const getDenoVersionFromRuntime = () => pipe(globalThis, prop("Deno"), prop("version"), prop("deno"));
|
|
61
|
+
const parseVersion = (deno) => pipe(deno.match(/^(\d+)\.(\d+)\.(\d+)/), unless(isNull, (arr) => arr.map(Number)));
|
|
62
|
+
const isLaterOrEqualThan = (basis) => (target) => pipe(zip(basis, target), filter(([b, t]) => t !== b), head, (a) => a ? a[0] < a[1] : true);
|
|
63
|
+
const getLinks = ({ kv, mq, initializer, dir }) => pipe({ "@fedify/fedify": "" }, merge(initializer.dependencies), merge(kv.dependencies), merge(mq.dependencies), keys, filter((dep) => dep.includes("@fedify/")), map((dep) => dep.replace("@fedify/", "")), map((dep) => join(PACKAGES_PATH, dep)), map(realpathSync), map((realAbsolutePath) => relative(realpathSync(dir), realAbsolutePath)), toArray);
|
|
96
64
|
/**
|
|
97
65
|
* Loads TypeScript configuration object for Node.js/Bun projects.
|
|
98
66
|
* Uses compiler options from the framework initializer.
|
package/dist/action/const.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
|
|
3
3
|
//#region src/action/const.ts
|
|
4
|
+
/**
|
|
5
|
+
* Absolute path to the monorepo *packages/* directory.
|
|
6
|
+
* Used in test mode to resolve local `@fedify/*` package paths.
|
|
7
|
+
*/
|
|
4
8
|
const PACKAGES_PATH = join(import.meta.dirname, "..", "..", "..");
|
|
5
9
|
|
|
6
10
|
//#endregion
|
package/dist/action/deps.js
CHANGED
|
@@ -30,7 +30,7 @@ const convertFedifyToLocal = (name) => pipe(name, replace("@fedify/", ""), (pkg)
|
|
|
30
30
|
* and message queue descriptions
|
|
31
31
|
* @returns A record of devDependencies with their versions
|
|
32
32
|
*/
|
|
33
|
-
const getDevDependencies = ({ initializer, kv, mq, packageManager }) => pipe({ "@biomejs/biome": "^2.2.4" }, merge(initializer.devDependencies), merge(kv.devDependencies), merge(mq.devDependencies), normalizePackageNames(packageManager));
|
|
33
|
+
const getDevDependencies = ({ initializer, kv, mq, packageManager, testMode }) => pipe({ "@biomejs/biome": "^2.2.4" }, merge(initializer.devDependencies), merge(kv.devDependencies), merge(mq.devDependencies), when(always(testMode), isDeno({ packageManager }) ? removeFedifyDeps : addLocalFedifyDeps), normalizePackageNames(packageManager));
|
|
34
34
|
/**
|
|
35
35
|
* Joins package names with their versions for installation dependencies.
|
|
36
36
|
* For Deno, it prefixes packages with 'jsr:'
|
package/dist/action/env.js
CHANGED
|
@@ -3,6 +3,11 @@ import { noticeConfigEnv, noticeEnvKeyValue } from "./notice.js";
|
|
|
3
3
|
import { entries, forEach, pipeLazy, tap, toArray, when } from "@fxts/core";
|
|
4
4
|
|
|
5
5
|
//#region src/action/env.ts
|
|
6
|
+
/**
|
|
7
|
+
* Displays environment variable recommendations to the user.
|
|
8
|
+
* Lists the `.env` key-value pairs from the combined KV store and message
|
|
9
|
+
* queue configurations, so the user knows what to configure.
|
|
10
|
+
*/
|
|
6
11
|
const recommendConfigEnv = pipeLazy((data) => data.env, entries, toArray, when(notEmpty, tap(noticeConfigEnv)), forEach(noticeEnvKeyValue));
|
|
7
12
|
var env_default = recommendConfigEnv;
|
|
8
13
|
|
package/dist/action/install.js
CHANGED
|
@@ -2,6 +2,10 @@ import { CommandError, runSubCommand } from "../utils.js";
|
|
|
2
2
|
import { apply, pipe } from "@fxts/core";
|
|
3
3
|
|
|
4
4
|
//#region src/action/install.ts
|
|
5
|
+
/**
|
|
6
|
+
* Runs `<packageManager> install` in the project directory to install all
|
|
7
|
+
* dependencies. Logs an error message if the installation fails.
|
|
8
|
+
*/
|
|
5
9
|
const installDependencies = (data) => pipe(data, ({ packageManager, dir }) => [[packageManager, "install"], { cwd: dir }], apply(runSubCommand)).catch((e) => {
|
|
6
10
|
if (e instanceof CommandError) {
|
|
7
11
|
console.error(`Failed to install dependencies using ${data.packageManager}.`);
|
package/dist/action/notice.js
CHANGED
|
@@ -3,6 +3,7 @@ import { text } from "@optique/core";
|
|
|
3
3
|
import { flow } from "es-toolkit";
|
|
4
4
|
|
|
5
5
|
//#region src/action/notice.ts
|
|
6
|
+
/** Prints the Feddy ASCII art banner to stderr. */
|
|
6
7
|
function drawDinosaur() {
|
|
7
8
|
const d = flow(colors.bgBlue, colors.black);
|
|
8
9
|
const f = colors.blue;
|
|
@@ -15,33 +16,53 @@ ${d(" <__.|_|-|_| ")} ${f("|_| \\___|\\__,_|_|_| \\__, |")}
|
|
|
15
16
|
${d(" ")} ${f(" |___/")}
|
|
16
17
|
`);
|
|
17
18
|
}
|
|
19
|
+
/** Prints the user's selected initialization options to stdout. */
|
|
18
20
|
const noticeOptions = ({ packageManager, webFramework, kvStore, messageQueue }) => printMessage`
|
|
19
21
|
Package manager: ${packageManager};
|
|
20
22
|
Web framework: ${webFramework};
|
|
21
23
|
Key–value store: ${kvStore};
|
|
22
24
|
Message queue: ${messageQueue};
|
|
23
25
|
`;
|
|
26
|
+
/**
|
|
27
|
+
* Prints the precommand that would be run in dry-run mode,
|
|
28
|
+
* showing the directory and command to execute.
|
|
29
|
+
*/
|
|
24
30
|
function noticePrecommand({ initializer: { command: command$1 }, dir }) {
|
|
25
31
|
printMessage`📦 Would run command:`;
|
|
26
32
|
printMessage` cd ${dir}`;
|
|
27
33
|
printMessage` ${command$1.join(" ")}\n`;
|
|
28
34
|
}
|
|
35
|
+
/** Prints a header indicating that text files would be created. */
|
|
29
36
|
const noticeFilesToCreate = () => printMessage`📄 Would create files:\n`;
|
|
37
|
+
/** Prints a header indicating that JSON files would be created or updated. */
|
|
30
38
|
const noticeFilesToInsert = () => printMessage`Would create/update JSON files:\n`;
|
|
39
|
+
/** Prints a header indicating that dependencies would be installed. */
|
|
31
40
|
const noticeDepsIfExist = () => printMessage`📦 Would install dependencies:`;
|
|
41
|
+
/** Prints a header indicating that dev dependencies would be installed. */
|
|
32
42
|
const noticeDevDepsIfExist = () => printMessage`📦 Would install dev dependencies:`;
|
|
43
|
+
/** Prints a single dependency name and version. */
|
|
33
44
|
const noticeDeps = ([name, version]) => printMessage`${name}@${version}`;
|
|
45
|
+
/**
|
|
46
|
+
* Displays a file's path and content with a horizontal rule separator,
|
|
47
|
+
* used in dry-run mode to preview generated files.
|
|
48
|
+
*/
|
|
34
49
|
function displayFile(path, content, emoji = "📄") {
|
|
35
50
|
printMessage`${emoji} ${path}`;
|
|
36
51
|
printMessage`${"─".repeat(60)}`;
|
|
37
52
|
printMessage`${content}`;
|
|
38
53
|
printMessage`${"─".repeat(60)}\n`;
|
|
39
54
|
}
|
|
55
|
+
/** Prints a notice recommending the user edit the `.env` file. */
|
|
40
56
|
const noticeConfigEnv = () => printMessage`Note that you probably want to edit the ${".env"} file.
|
|
41
57
|
It currently contains the following values:\n`;
|
|
58
|
+
/** Prints a single environment variable key-value pair. */
|
|
42
59
|
const noticeEnvKeyValue = ([key, value]) => {
|
|
43
60
|
printMessage`${text(` ${key}='${value}'`)}`;
|
|
44
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* Prints the post-initialization instructions, showing how to start
|
|
64
|
+
* the dev server and where to edit the federation configuration.
|
|
65
|
+
*/
|
|
45
66
|
const noticeHowToRun = ({ initializer: { instruction, federationFile } }) => printMessage`
|
|
46
67
|
${instruction}
|
|
47
68
|
|
package/dist/action/set.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { merge, set } from "../utils.js";
|
|
2
2
|
import { kvStores, messageQueues } from "../lib.js";
|
|
3
|
-
import webframeworks_default from "../webframeworks.js";
|
|
3
|
+
import webframeworks_default from "../webframeworks/mod.js";
|
|
4
4
|
import { pipe } from "@fxts/core";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { realpath } from "node:fs/promises";
|
package/dist/action/utils.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
|
|
3
3
|
//#region src/action/utils.ts
|
|
4
|
+
/** Returns `true` if the current run is in dry-run mode. */
|
|
4
5
|
const isDry = ({ dryRun }) => dryRun;
|
|
6
|
+
/** Returns `true` if the framework initializer has a precommand to execute. */
|
|
5
7
|
const hasCommand = (data) => !!data.initializer.command;
|
|
8
|
+
/** Returns `true` if the selected package manager is Deno. */
|
|
6
9
|
const isDeno = ({ packageManager }) => packageManager === "deno";
|
|
10
|
+
/**
|
|
11
|
+
* Returns a function that prepends the project directory to a
|
|
12
|
+
* `[filename, content]` tuple, resolving the filename into an absolute path.
|
|
13
|
+
*/
|
|
7
14
|
const joinDir = (dir) => ([filename, content]) => [join(dir, ...filename.split("/")), content];
|
|
8
15
|
/**
|
|
9
16
|
* Stringify an object into a valid `.env` file format.
|
package/dist/ask/mod.js
CHANGED
|
@@ -6,6 +6,12 @@ import wf_default from "./wf.js";
|
|
|
6
6
|
import { pipe } from "@fxts/core";
|
|
7
7
|
|
|
8
8
|
//#region src/ask/mod.ts
|
|
9
|
+
/**
|
|
10
|
+
* Orchestrates all interactive prompts to fill in missing initialization options.
|
|
11
|
+
* Prompts the user in sequence for: project directory, web framework,
|
|
12
|
+
* package manager, message queue, and key-value store.
|
|
13
|
+
* Returns a fully resolved {@link InitCommandOptions} with all fields guaranteed.
|
|
14
|
+
*/
|
|
9
15
|
const askOptions = (options) => pipe(options, dir_default, wf_default, pm_default, mq_default, kv_default);
|
|
10
16
|
var ask_default = askOptions;
|
|
11
17
|
|
package/dist/ask/pm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getInstallUrl, isPackageManagerAvailable, kvStores, messageQueues, packageManagers, runtimes } from "../lib.js";
|
|
2
2
|
import { PACKAGE_MANAGER } from "../const.js";
|
|
3
|
-
import webframeworks_default from "../webframeworks.js";
|
|
3
|
+
import webframeworks_default from "../webframeworks/mod.js";
|
|
4
4
|
import { pipe, when } from "@fxts/core";
|
|
5
5
|
import { select } from "@inquirer/prompts";
|
|
6
6
|
import { message } from "@optique/core/message";
|
package/dist/ask/wf.js
CHANGED
package/dist/command.d.ts
CHANGED
|
@@ -2,24 +2,33 @@ import * as _optique_core0 from "@optique/core";
|
|
|
2
2
|
import { InferValue } from "@optique/core";
|
|
3
3
|
|
|
4
4
|
//#region src/command.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The `@optique/core` option schema for the `fedify init` command.
|
|
8
|
+
* Defines `dir`, `webFramework`, `packageManager`, `kvStore`, `messageQueue`,
|
|
9
|
+
* and `dryRun` options that the CLI parser will accept.
|
|
10
|
+
*/
|
|
5
11
|
declare const initOptions: _optique_core0.Parser<"sync", {
|
|
6
12
|
readonly dir: string;
|
|
7
|
-
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "express";
|
|
13
|
+
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "astro" | "express";
|
|
8
14
|
readonly packageManager: "deno" | "pnpm" | "bun" | "yarn" | "npm";
|
|
9
15
|
readonly kvStore: "denokv" | "redis" | "postgres";
|
|
10
16
|
readonly messageQueue: "denokv" | "redis" | "postgres" | "amqp";
|
|
11
17
|
readonly dryRun: boolean;
|
|
12
18
|
}, {
|
|
13
19
|
readonly dir: [_optique_core0.ValueParserResult<string>];
|
|
14
|
-
readonly webFramework: [_optique_core0.ValueParserResult<"hono" | "nitro" | "next" | "elysia" | "express">];
|
|
20
|
+
readonly webFramework: [_optique_core0.ValueParserResult<"hono" | "nitro" | "next" | "elysia" | "astro" | "express">];
|
|
15
21
|
readonly packageManager: [_optique_core0.ValueParserResult<"deno" | "pnpm" | "bun" | "yarn" | "npm">];
|
|
16
22
|
readonly kvStore: [_optique_core0.ValueParserResult<"denokv" | "redis" | "postgres">];
|
|
17
23
|
readonly messageQueue: [_optique_core0.ValueParserResult<"denokv" | "redis" | "postgres" | "amqp">];
|
|
18
24
|
readonly dryRun: _optique_core0.ValueParserResult<boolean>;
|
|
19
25
|
}>;
|
|
26
|
+
/**
|
|
27
|
+
* The `fedify init` CLI command parser.
|
|
28
|
+
*/
|
|
20
29
|
declare const initCommand: _optique_core0.Parser<"sync", {
|
|
21
30
|
readonly dir: string;
|
|
22
|
-
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "express";
|
|
31
|
+
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "astro" | "express";
|
|
23
32
|
readonly packageManager: "deno" | "pnpm" | "bun" | "yarn" | "npm";
|
|
24
33
|
readonly kvStore: "denokv" | "redis" | "postgres";
|
|
25
34
|
readonly messageQueue: "denokv" | "redis" | "postgres" | "amqp";
|
|
@@ -27,6 +36,10 @@ declare const initCommand: _optique_core0.Parser<"sync", {
|
|
|
27
36
|
} & {
|
|
28
37
|
readonly command: "init";
|
|
29
38
|
}, ["matched", string] | ["parsing", Record<string | symbol, unknown>]>;
|
|
39
|
+
/** The inferred value type produced by parsing the `fedify init` command. */
|
|
30
40
|
type InitCommand = InferValue<typeof initCommand>;
|
|
41
|
+
/**
|
|
42
|
+
* The `test-init` CLI command parser.
|
|
43
|
+
*/
|
|
31
44
|
//#endregion
|
|
32
45
|
export { InitCommand, initCommand, initOptions };
|
package/dist/command.js
CHANGED
|
@@ -7,6 +7,11 @@ const webFramework = optional(option("-w", "--web-framework", choice(WEB_FRAMEWO
|
|
|
7
7
|
const packageManager = optional(option("-p", "--package-manager", choice(PACKAGE_MANAGER, { metavar: "PACKAGE_MANAGER" }), { description: message`The package manager to use for installing dependencies.` }));
|
|
8
8
|
const kvStore = optional(option("-k", "--kv-store", choice(KV_STORE, { metavar: "KV_STORE" }), { description: message`The key-value store to use for caching and some other features.` }));
|
|
9
9
|
const messageQueue = optional(option("-m", "--message-queue", choice(MESSAGE_QUEUE, { metavar: "MESSAGE_QUEUE" }), { description: message`The message queue to use for background tasks.` }));
|
|
10
|
+
/**
|
|
11
|
+
* The `@optique/core` option schema for the `fedify init` command.
|
|
12
|
+
* Defines `dir`, `webFramework`, `packageManager`, `kvStore`, `messageQueue`,
|
|
13
|
+
* and `dryRun` options that the CLI parser will accept.
|
|
14
|
+
*/
|
|
10
15
|
const initOptions = object("Initialization options", {
|
|
11
16
|
dir: optional(argument(path({ metavar: "DIR" }), { description: message`The project directory to initialize. If a specified directory does not exist, it will be created.` })),
|
|
12
17
|
webFramework,
|
|
@@ -15,6 +20,9 @@ const initOptions = object("Initialization options", {
|
|
|
15
20
|
messageQueue,
|
|
16
21
|
dryRun: option("--dry-run", { description: message`Perform a trial run with no changes made.` })
|
|
17
22
|
});
|
|
23
|
+
/**
|
|
24
|
+
* The `fedify init` CLI command parser.
|
|
25
|
+
*/
|
|
18
26
|
const initCommand = command("init", merge(initOptions, object({ command: constant("init") })), {
|
|
19
27
|
brief: message`Initialize a new Fedify project directory.`,
|
|
20
28
|
description: message`Initialize a new Fedify project directory.
|
|
@@ -25,6 +33,9 @@ Unless you specify all options (${optionNames(["-w", "--web-framework"])}, ${opt
|
|
|
25
33
|
});
|
|
26
34
|
const noHydRun = object({ noHydRun: option("--no-hyd-run", { description: message`Log outputs without creating files.` }) });
|
|
27
35
|
const noDryRun = object({ noDryRun: option("--no-dry-run", { description: message`Test with files creations and installations.` }) });
|
|
36
|
+
/**
|
|
37
|
+
* The `test-init` CLI command parser.
|
|
38
|
+
*/
|
|
28
39
|
const testInitCommand = command("test-init", merge(object("Initialization options", {
|
|
29
40
|
webFramework: multiple(webFramework),
|
|
30
41
|
packageManager: multiple(packageManager),
|
package/dist/const.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
//#region src/const.d.ts
|
|
2
|
+
/** All supported package manager identifiers, in display order. */
|
|
2
3
|
declare const PACKAGE_MANAGER: readonly ["deno", "pnpm", "bun", "yarn", "npm"];
|
|
4
|
+
/** All supported web framework identifiers, in display order. */
|
|
5
|
+
|
|
3
6
|
//#endregion
|
|
4
7
|
export { PACKAGE_MANAGER };
|
package/dist/const.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/const.ts
|
|
2
|
+
/** All supported package manager identifiers, in display order. */
|
|
2
3
|
const PACKAGE_MANAGER = [
|
|
3
4
|
"deno",
|
|
4
5
|
"pnpm",
|
|
@@ -6,24 +7,32 @@ const PACKAGE_MANAGER = [
|
|
|
6
7
|
"yarn",
|
|
7
8
|
"npm"
|
|
8
9
|
];
|
|
10
|
+
/** All supported web framework identifiers, in display order. */
|
|
9
11
|
const WEB_FRAMEWORK = [
|
|
10
12
|
"hono",
|
|
11
13
|
"nitro",
|
|
12
14
|
"next",
|
|
13
15
|
"elysia",
|
|
16
|
+
"astro",
|
|
14
17
|
"express"
|
|
15
18
|
];
|
|
19
|
+
/** All supported message queue backend identifiers. */
|
|
16
20
|
const MESSAGE_QUEUE = [
|
|
17
21
|
"denokv",
|
|
18
22
|
"redis",
|
|
19
23
|
"postgres",
|
|
20
24
|
"amqp"
|
|
21
25
|
];
|
|
26
|
+
/** All supported key-value store backend identifiers. */
|
|
22
27
|
const KV_STORE = [
|
|
23
28
|
"denokv",
|
|
24
29
|
"redis",
|
|
25
30
|
"postgres"
|
|
26
31
|
];
|
|
32
|
+
/**
|
|
33
|
+
* External database services that need to be running for integration tests.
|
|
34
|
+
* Used by the test suite to check service availability before running tests.
|
|
35
|
+
*/
|
|
27
36
|
const DB_TO_CHECK = [
|
|
28
37
|
"redis",
|
|
29
38
|
"postgres",
|
package/dist/deno.js
CHANGED
package/dist/json/kv.js
CHANGED
|
@@ -33,6 +33,23 @@ var postgres = {
|
|
|
33
33
|
"object": "new PostgresKvStore(postgres(process.env.POSTGRES_URL))",
|
|
34
34
|
"env": { "POSTGRES_URL": "postgres://postgres@localhost:5432/postgres" }
|
|
35
35
|
};
|
|
36
|
+
var mysql = {
|
|
37
|
+
"label": "MySQL/MariaDB",
|
|
38
|
+
"packageManagers": [
|
|
39
|
+
"deno",
|
|
40
|
+
"bun",
|
|
41
|
+
"npm",
|
|
42
|
+
"yarn",
|
|
43
|
+
"pnpm"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": { "npm:mysql2": "^3.18.0" },
|
|
46
|
+
"imports": {
|
|
47
|
+
"@fedify/mysql": { "MysqlKvStore": "MysqlKvStore" },
|
|
48
|
+
"mysql2/promise": { "default": "mysql" }
|
|
49
|
+
},
|
|
50
|
+
"object": "new MysqlKvStore(mysql.createPool(process.env.MYSQL_URL))",
|
|
51
|
+
"env": { "MYSQL_URL": "mysql://root@localhost/fedify" }
|
|
52
|
+
};
|
|
36
53
|
var denokv = {
|
|
37
54
|
"label": "Deno KV",
|
|
38
55
|
"packageManagers": ["deno"],
|
|
@@ -43,6 +60,7 @@ var denokv = {
|
|
|
43
60
|
var kv_default = {
|
|
44
61
|
redis,
|
|
45
62
|
postgres,
|
|
63
|
+
mysql,
|
|
46
64
|
denokv
|
|
47
65
|
};
|
|
48
66
|
|
package/dist/json/kv.json
CHANGED
|
@@ -29,6 +29,21 @@
|
|
|
29
29
|
"POSTGRES_URL": "postgres://postgres@localhost:5432/postgres"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
+
"mysql": {
|
|
33
|
+
"label": "MySQL/MariaDB",
|
|
34
|
+
"packageManagers": ["deno", "bun", "npm", "yarn", "pnpm"],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"npm:mysql2": "^3.18.0"
|
|
37
|
+
},
|
|
38
|
+
"imports": {
|
|
39
|
+
"@fedify/mysql": { "MysqlKvStore": "MysqlKvStore" },
|
|
40
|
+
"mysql2/promise": { "default": "mysql" }
|
|
41
|
+
},
|
|
42
|
+
"object": "new MysqlKvStore(mysql.createPool(process.env.MYSQL_URL))",
|
|
43
|
+
"env": {
|
|
44
|
+
"MYSQL_URL": "mysql://root@localhost/fedify"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
32
47
|
"denokv": {
|
|
33
48
|
"label": "Deno KV",
|
|
34
49
|
"packageManagers": ["deno"],
|
package/dist/lib.js
CHANGED
|
@@ -6,7 +6,6 @@ import pm_default from "./json/pm.js";
|
|
|
6
6
|
import rt_default from "./json/rt.js";
|
|
7
7
|
import { entries, evolve, fromEntries, isObject, map, negate, pipe, throwIf } from "@fxts/core";
|
|
8
8
|
import process from "node:process";
|
|
9
|
-
import { commandLine, message } from "@optique/core/message";
|
|
10
9
|
import { toMerged } from "es-toolkit";
|
|
11
10
|
import { getLogger } from "@logtape/logtape";
|
|
12
11
|
import { readFileSync } from "node:fs";
|
|
@@ -14,20 +13,44 @@ import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
|
14
13
|
import { dirname, join as join$1 } from "node:path";
|
|
15
14
|
|
|
16
15
|
//#region src/lib.ts
|
|
16
|
+
/** The current `@fedify/init` package version, read from *deno.json*. */
|
|
17
17
|
const PACKAGE_VERSION = deno_default.version;
|
|
18
|
+
/** Logger instance for the `fedify init` command, scoped to `["fedify", "cli", "init"]`. */
|
|
18
19
|
const logger = getLogger([
|
|
19
20
|
"fedify",
|
|
20
21
|
"cli",
|
|
21
22
|
"init"
|
|
22
23
|
]);
|
|
23
24
|
const addFedifyDeps = (json) => Object.fromEntries(Object.entries(json).map(([key, value]) => [key, toMerged(value, { dependencies: { [`@fedify/${key}`]: PACKAGE_VERSION } })]));
|
|
25
|
+
/**
|
|
26
|
+
* KV store descriptions loaded from *json/kv.json*, enriched with the
|
|
27
|
+
* appropriate `@fedify/*` dependency at the current package version.
|
|
28
|
+
*/
|
|
24
29
|
const kvStores = addFedifyDeps(kv_default);
|
|
30
|
+
/**
|
|
31
|
+
* Message queue descriptions loaded from *json/mq.json*, enriched with the
|
|
32
|
+
* appropriate `@fedify/*` dependency at the current package version.
|
|
33
|
+
*/
|
|
25
34
|
const messageQueues = addFedifyDeps(mq_default);
|
|
26
35
|
const toRegExp = (str) => new RegExp(str);
|
|
27
36
|
const convertPattern = (obj) => pipe(obj, entries, map(([key, value]) => [key, evolve({ outputPattern: toRegExp })(value)]), fromEntries);
|
|
37
|
+
/**
|
|
38
|
+
* Package manager descriptions loaded from *json/pm.json*, with
|
|
39
|
+
* `outputPattern` strings converted to `RegExp` instances.
|
|
40
|
+
*/
|
|
28
41
|
const packageManagers = convertPattern(pm_default);
|
|
42
|
+
/**
|
|
43
|
+
* Runtime descriptions loaded from *json/rt.json*, with `outputPattern`
|
|
44
|
+
* strings converted to `RegExp` instances.
|
|
45
|
+
*/
|
|
29
46
|
const runtimes = convertPattern(rt_default);
|
|
47
|
+
/** Returns the installation URL for the given package manager. */
|
|
30
48
|
const getInstallUrl = (pm) => packageManagers[pm].installUrl;
|
|
49
|
+
/**
|
|
50
|
+
* Checks whether a package manager is installed and available on the system.
|
|
51
|
+
* Runs the package manager's check command and verifies its output.
|
|
52
|
+
* On Windows, also tries the `.cmd` variant of the command.
|
|
53
|
+
*/
|
|
31
54
|
async function isPackageManagerAvailable(pm) {
|
|
32
55
|
if (await isCommandAvailable(packageManagers[pm])) return true;
|
|
33
56
|
if (process.platform !== "win32") return false;
|
|
@@ -38,17 +61,19 @@ async function isPackageManagerAvailable(pm) {
|
|
|
38
61
|
})) return true;
|
|
39
62
|
return false;
|
|
40
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Reads a template file from the *templates/* directory and returns its content.
|
|
66
|
+
* Appends `.tpl` to the given path before reading.
|
|
67
|
+
*
|
|
68
|
+
* @param templatePath - Relative path within the templates directory
|
|
69
|
+
* (e.g., `"defaults/federation.ts"`)
|
|
70
|
+
* @returns The template file content as a string
|
|
71
|
+
*/
|
|
41
72
|
const readTemplate = (templatePath) => readFileSync(join$1(import.meta.dirname, "templates", ...(templatePath + ".tpl").split("/")), "utf8");
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Then, try look up an actor from your server:
|
|
48
|
-
|
|
49
|
-
${commandLine(`fedify lookup http://localhost:${port}/users/john`)}
|
|
50
|
-
|
|
51
|
-
`;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the shell command string to start the dev server for the given
|
|
75
|
+
* package manager (e.g., `"deno task dev"`, `"bun dev"`, `"npm run dev"`).
|
|
76
|
+
*/
|
|
52
77
|
const getDevCommand = (pm) => pm === "deno" ? "deno task dev" : pm === "bun" ? "bun dev" : `${pm} run dev`;
|
|
53
78
|
async function isCommandAvailable({ checkCommand, outputPattern }) {
|
|
54
79
|
try {
|
|
@@ -71,12 +96,24 @@ async function isCommandAvailable({ checkCommand, outputPattern }) {
|
|
|
71
96
|
throw error;
|
|
72
97
|
}
|
|
73
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a file at the given path with the given content, creating
|
|
101
|
+
* any necessary parent directories along the way.
|
|
102
|
+
*/
|
|
74
103
|
async function createFile(path, content) {
|
|
75
104
|
await mkdir(dirname(path), { recursive: true });
|
|
76
105
|
await writeFile(path, content);
|
|
77
106
|
}
|
|
78
107
|
const isNotExistsError = (e) => isObject(e) && "code" in e && e.code === "ENOENT";
|
|
108
|
+
/**
|
|
109
|
+
* Throws the given error unless it is an `ENOENT` (file not found) error.
|
|
110
|
+
* Used to silently handle missing files while re-throwing other errors.
|
|
111
|
+
*/
|
|
79
112
|
const throwUnlessNotExists = throwIf(negate(isNotExistsError));
|
|
113
|
+
/**
|
|
114
|
+
* Checks whether a directory is empty or does not exist.
|
|
115
|
+
* Returns `true` if the directory has no entries or does not exist yet.
|
|
116
|
+
*/
|
|
80
117
|
const isDirectoryEmpty = async (path) => {
|
|
81
118
|
try {
|
|
82
119
|
const files = await readdir(path);
|
|
@@ -86,45 +123,8 @@ const isDirectoryEmpty = async (path) => {
|
|
|
86
123
|
return true;
|
|
87
124
|
}
|
|
88
125
|
};
|
|
89
|
-
/**
|
|
90
|
-
* Converts a package manager to its corresponding runtime.
|
|
91
|
-
* @param pm - The package manager (deno, bun, npm, yarn, pnpm)
|
|
92
|
-
* @returns The runtime name (deno, bun, or node)
|
|
93
|
-
*/
|
|
94
|
-
const packageManagerToRuntime = (pm) => pm === "deno" ? "deno" : pm === "bun" ? "bun" : "node";
|
|
95
|
-
const getNextInitCommand = (pm) => [
|
|
96
|
-
...createNextAppCommand(pm),
|
|
97
|
-
".",
|
|
98
|
-
"--yes"
|
|
99
|
-
];
|
|
100
|
-
const createNextAppCommand = (pm) => pm === "deno" ? [
|
|
101
|
-
"deno",
|
|
102
|
-
"-Ar",
|
|
103
|
-
"npm:create-next-app@latest"
|
|
104
|
-
] : pm === "bun" ? [
|
|
105
|
-
"bun",
|
|
106
|
-
"create",
|
|
107
|
-
"next-app"
|
|
108
|
-
] : pm === "npm" ? ["npx", "create-next-app"] : [
|
|
109
|
-
pm,
|
|
110
|
-
"dlx",
|
|
111
|
-
"create-next-app"
|
|
112
|
-
];
|
|
113
|
-
const getNitroInitCommand = (pm) => [
|
|
114
|
-
...createNitroAppCommand(pm),
|
|
115
|
-
pm === "deno" ? "npm:giget@latest" : "giget@latest",
|
|
116
|
-
"nitro",
|
|
117
|
-
".",
|
|
118
|
-
"&&",
|
|
119
|
-
"rm",
|
|
120
|
-
"nitro.config.ts"
|
|
121
|
-
];
|
|
122
|
-
const createNitroAppCommand = (pm) => pm === "deno" ? [
|
|
123
|
-
"deno",
|
|
124
|
-
"run",
|
|
125
|
-
"-A"
|
|
126
|
-
] : pm === "bun" ? ["bunx"] : pm === "npm" ? ["npx"] : [pm, "dlx"];
|
|
126
|
+
/** Returns `true` if the current run is in test mode. */
|
|
127
127
|
const isTest = ({ testMode }) => testMode;
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
|
-
export { PACKAGE_VERSION, createFile, getDevCommand, getInstallUrl,
|
|
130
|
+
export { PACKAGE_VERSION, createFile, getDevCommand, getInstallUrl, isDirectoryEmpty, isPackageManagerAvailable, isTest, kvStores, logger, messageQueues, packageManagers, readTemplate, runtimes, throwUnlessNotExists };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import deno from "@deno/astro-adapter";
|
|
2
|
+
import { fedifyIntegration } from "@fedify/astro";
|
|
3
|
+
import { defineConfig } from "astro/config";
|
|
4
|
+
|
|
5
|
+
// https://astro.build/config
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
integrations: [fedifyIntegration()],
|
|
8
|
+
output: "server",
|
|
9
|
+
adapter: deno(),
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import node from "@astrojs/node";
|
|
2
|
+
import { fedifyIntegration } from "@fedify/astro";
|
|
3
|
+
import { defineConfig } from "astro/config";
|
|
4
|
+
|
|
5
|
+
// https://astro.build/config
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
integrations: [fedifyIntegration()],
|
|
8
|
+
output: "server",
|
|
9
|
+
adapter: node({ mode: "standalone" }),
|
|
10
|
+
});
|