@fedify/cli 2.0.0-pr.474.1879 → 2.0.0-pr.479.1902
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/deno.json +1 -1
- package/dist/deno.js +1 -1
- package/dist/imagerenderer.js +1 -1
- package/dist/inbox.js +2 -5
- package/dist/init/action/configs.js +22 -13
- package/dist/init/action/const.js +10 -0
- package/dist/init/action/deps.js +26 -28
- package/dist/init/action/install.js +11 -13
- package/dist/init/action/mod.js +1 -1
- package/dist/init/action/notice.js +12 -19
- package/dist/init/action/patch.js +33 -27
- package/dist/init/action/precommand.js +7 -2
- package/dist/init/action/recommend.js +1 -1
- package/dist/init/action/set.js +1 -1
- package/dist/init/action/templates.js +2 -1
- package/dist/init/ask/kv.js +24 -13
- package/dist/init/ask/mq.js +26 -13
- package/dist/init/command.js +20 -3
- package/dist/init/lib.js +20 -13
- package/dist/init/mod.js +2 -1
- package/dist/init/templates/nitro/.env.test.tpl +1 -0
- package/dist/init/templates/nitro/nitro.config.ts.tpl +12 -3
- package/dist/init/test/action.js +15 -0
- package/dist/init/test/create.js +100 -0
- package/dist/init/test/fill.js +26 -0
- package/dist/init/test/lookup.js +189 -0
- package/dist/init/test/run.js +26 -0
- package/dist/init/test/utils.js +17 -0
- package/dist/init/webframeworks.js +31 -28
- package/dist/mod.js +4 -2
- package/dist/nodeinfo.js +6 -6
- package/dist/utils.js +75 -8
- package/package.json +5 -5
- package/src/inbox.tsx +1 -15
- package/src/init/action/configs.ts +56 -13
- package/src/init/action/const.ts +9 -0
- package/src/init/action/deps.ts +98 -30
- package/src/init/action/install.ts +17 -52
- package/src/init/action/notice.ts +16 -14
- package/src/init/action/patch.ts +48 -27
- package/src/init/action/precommand.ts +9 -2
- package/src/init/action/set.ts +2 -15
- package/src/init/action/templates.ts +3 -2
- package/src/init/action/utils.ts +1 -1
- package/src/init/ask/kv.ts +64 -21
- package/src/init/ask/mq.ts +69 -20
- package/src/init/command.ts +39 -1
- package/src/init/lib.ts +31 -28
- package/src/init/mod.ts +2 -1
- package/src/init/templates/nitro/.env.test.tpl +1 -0
- package/src/init/templates/nitro/nitro.config.ts.tpl +12 -3
- package/src/init/test/action.ts +25 -0
- package/src/init/test/create.ts +137 -0
- package/src/init/test/fill.ts +61 -0
- package/src/init/test/lookup.ts +253 -0
- package/src/init/test/run.ts +42 -0
- package/src/init/test/types.ts +34 -0
- package/src/init/test/utils.ts +21 -0
- package/src/init/types.ts +4 -3
- package/src/init/webframeworks.ts +35 -18
- package/src/mod.ts +10 -1
- package/src/nodeinfo.ts +2 -1
- package/src/utils.ts +128 -10
package/deno.json
CHANGED
package/dist/deno.js
CHANGED
package/dist/imagerenderer.js
CHANGED
|
@@ -5,8 +5,8 @@ import { Jimp } from "./nodeinfo.js";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
7
|
import process from "node:process";
|
|
8
|
-
import { encodeBase64 } from "byte-encodings/base64";
|
|
9
8
|
import os from "node:os";
|
|
9
|
+
import { encodeBase64 } from "byte-encodings/base64";
|
|
10
10
|
|
|
11
11
|
//#region src/imagerenderer.ts
|
|
12
12
|
const KITTY_IDENTIFIERS = [
|
package/dist/inbox.js
CHANGED
|
@@ -30,8 +30,7 @@ const inboxCommand = command("inbox", merge(object("Inbox options", {
|
|
|
30
30
|
acceptFollow: optional(multiple(option("-a", "--accept-follow", string({ metavar: "URI" }), { description: message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.` }))),
|
|
31
31
|
noTunnel: option("-T", "--no-tunnel", { description: message`Do not tunnel the ephemeral ActivityPub server to the public Internet.` }),
|
|
32
32
|
actorName: withDefault(option("--actor-name", string({ metavar: "NAME" }), { description: message`Customize the actor display name.` }), "Fedify Ephemeral Inbox"),
|
|
33
|
-
actorSummary: withDefault(option("--actor-summary", string({ metavar: "SUMMARY" }), { description: message`Customize the actor description.` }), "An ephemeral ActivityPub inbox for testing purposes.")
|
|
34
|
-
authorizedFetch: option("-A", "--authorized-fetch", { description: message`Require HTTP Signatures for all incoming requests. Returns 401 for unsigned requests.` })
|
|
33
|
+
actorSummary: withDefault(option("--actor-summary", string({ metavar: "SUMMARY" }), { description: message`Customize the actor description.` }), "An ephemeral ActivityPub inbox for testing purposes.")
|
|
35
34
|
}), debugOption), {
|
|
36
35
|
brief: message`Run an ephemeral ActivityPub inbox server.`,
|
|
37
36
|
description: message`Spins up an ephemeral server that serves the ActivityPub inbox with an one-time actor, through a short-lived public DNS with HTTPS. You can monitor the incoming activities in real-time.`
|
|
@@ -39,8 +38,7 @@ const inboxCommand = command("inbox", merge(object("Inbox options", {
|
|
|
39
38
|
async function runInbox(command$1) {
|
|
40
39
|
const fetch = createFetchHandler({
|
|
41
40
|
actorName: command$1.actorName,
|
|
42
|
-
actorSummary: command$1.actorSummary
|
|
43
|
-
requireHttpSignature: command$1.authorizedFetch
|
|
41
|
+
actorSummary: command$1.actorSummary
|
|
44
42
|
});
|
|
45
43
|
const sendDeleteToPeers = createSendDeleteToPeers({
|
|
46
44
|
actorName: command$1.actorName,
|
|
@@ -302,7 +300,6 @@ function createFetchHandler(actorOptions) {
|
|
|
302
300
|
actorName: actorOptions.actorName,
|
|
303
301
|
actorSummary: actorOptions.actorSummary
|
|
304
302
|
},
|
|
305
|
-
requireHttpSignature: actorOptions.requireHttpSignature,
|
|
306
303
|
onNotAcceptable: app.fetch.bind(app),
|
|
307
304
|
onNotFound: app.fetch.bind(app),
|
|
308
305
|
onUnauthorized: app.fetch.bind(app)
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
+
import { merge } from "../../utils.js";
|
|
4
5
|
import biome_default from "../json/biome.js";
|
|
5
6
|
import vscode_settings_for_deno_default from "../json/vscode-settings-for-deno.js";
|
|
6
7
|
import vscode_settings_default from "../json/vscode-settings.js";
|
|
7
|
-
import {
|
|
8
|
+
import { PACKAGES_PATH } from "./const.js";
|
|
9
|
+
import { getDependencies, getDevDependencies, joinDepsReg } from "./deps.js";
|
|
10
|
+
import { join, relative } from "node:path";
|
|
11
|
+
import { uniq } from "es-toolkit";
|
|
12
|
+
import { concat, filter, keys, map, pick, pipe, toArray } from "@fxts/core/index.js";
|
|
8
13
|
|
|
9
14
|
//#region src/init/action/configs.ts
|
|
10
15
|
/**
|
|
@@ -14,16 +19,18 @@ import { join } from "node:path";
|
|
|
14
19
|
* @param param0 - Destructured initialization data containing KV, MQ, initializer, and directory
|
|
15
20
|
* @returns Configuration object with path and Deno-specific settings
|
|
16
21
|
*/
|
|
17
|
-
const loadDenoConfig = (
|
|
18
|
-
path:
|
|
19
|
-
data: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const loadDenoConfig = (data) => ({
|
|
23
|
+
path: "deno.json",
|
|
24
|
+
data: {
|
|
25
|
+
...pick(["compilerOptions", "tasks"], data.initializer),
|
|
26
|
+
unstable: getUnstable(data),
|
|
27
|
+
nodeModulesDir: "auto",
|
|
28
|
+
imports: joinDepsReg("deno")(getDependencies(data)),
|
|
29
|
+
...data.testMode ? { links: getLinks(data) } : {}
|
|
30
|
+
}
|
|
26
31
|
});
|
|
32
|
+
const getUnstable = ({ kv: { denoUnstable: kv = [] }, mq: { denoUnstable: mq = [] } }) => pipe(["temporal"], concat(kv), concat(mq), toArray, uniq);
|
|
33
|
+
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) => relative(dir, absolutePath)), toArray);
|
|
27
34
|
/**
|
|
28
35
|
* Loads TypeScript configuration object for Node.js/Bun projects.
|
|
29
36
|
* Uses compiler options from the framework initializer.
|
|
@@ -42,11 +49,13 @@ const loadTsConfig = ({ initializer, dir }) => ({
|
|
|
42
49
|
* @param param0 - Destructured initialization data containing initializer and directory
|
|
43
50
|
* @returns Configuration object with path and package.json settings
|
|
44
51
|
*/
|
|
45
|
-
const loadPackageJson = (
|
|
46
|
-
path:
|
|
52
|
+
const loadPackageJson = (data) => ({
|
|
53
|
+
path: "package.json",
|
|
47
54
|
data: {
|
|
48
55
|
type: "module",
|
|
49
|
-
scripts: initializer.tasks
|
|
56
|
+
scripts: data.initializer.tasks,
|
|
57
|
+
dependencies: getDependencies(data),
|
|
58
|
+
devDependencies: getDevDependencies(data)
|
|
50
59
|
}
|
|
51
60
|
});
|
|
52
61
|
/**
|
package/dist/init/action/deps.js
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
-
import { merge } from "../../utils.js";
|
|
4
|
+
import { merge, replace } from "../../utils.js";
|
|
5
5
|
import { PACKAGE_VERSION } from "../lib.js";
|
|
6
|
-
import {
|
|
6
|
+
import { PACKAGES_PATH } from "./const.js";
|
|
7
|
+
import { isDeno } from "./utils.js";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { always, entries, filter, fromEntries, map, pipe, when } from "@fxts/core";
|
|
7
10
|
|
|
8
11
|
//#region src/init/action/deps.ts
|
|
9
12
|
/**
|
|
10
13
|
* Gathers all dependencies required for the project based on the initializer,
|
|
11
14
|
* key-value store, and message queue configurations.
|
|
12
15
|
*
|
|
13
|
-
* @param data - Web Framework initializer, key-value store and
|
|
16
|
+
* @param data - Web Framework initializer, key-value store and
|
|
17
|
+
* message queue descriptions
|
|
14
18
|
* @returns A record of dependencies with their versions
|
|
15
19
|
*/
|
|
16
|
-
const getDependencies = ({ initializer, kv, mq }) => pipe({
|
|
20
|
+
const getDependencies = ({ initializer, kv, mq, testMode, packageManager }) => pipe({
|
|
17
21
|
"@fedify/fedify": PACKAGE_VERSION,
|
|
18
22
|
"@logtape/logtape": "^1.1.0"
|
|
19
|
-
}, merge(initializer.dependencies), merge(kv.dependencies), merge(mq.dependencies));
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
}, merge(initializer.dependencies), merge(kv.dependencies), merge(mq.dependencies), when(always(testMode), isDeno({ packageManager }) ? removeFedifyDeps : addLocalFedifyDeps), normalizePackageNames(packageManager));
|
|
24
|
+
const removeFedifyDeps = (deps) => pipe(deps, entries, filter(([name]) => !name.includes("@fedify")), fromEntries);
|
|
25
|
+
const addLocalFedifyDeps = (deps) => pipe(deps, entries, map(when(([name]) => name.includes("@fedify/"), ([name, _version]) => [name, convertFedifyToLocal(name)])), fromEntries);
|
|
26
|
+
const convertFedifyToLocal = (name) => pipe(name, replace("@fedify/", ""), (pkg) => join(PACKAGES_PATH, pkg));
|
|
27
|
+
/** Gathers all devDependencies required for the project based on the
|
|
28
|
+
* initializer, key-value store, and message queue configurations,
|
|
29
|
+
* including Biome for linting/formatting.
|
|
22
30
|
*
|
|
23
|
-
* @param data - Web Framework initializer, key-value store
|
|
31
|
+
* @param data - Web Framework initializer, key-value store
|
|
32
|
+
* and message queue descriptions
|
|
24
33
|
* @returns A record of devDependencies with their versions
|
|
25
34
|
*/
|
|
26
|
-
const getDevDependencies = ({ initializer, kv, mq }) => pipe({ "@biomejs/biome": "^2.2.4" }, merge(initializer.devDependencies), merge(kv.devDependencies), merge(mq.devDependencies));
|
|
35
|
+
const getDevDependencies = ({ initializer, kv, mq, packageManager }) => pipe({ "@biomejs/biome": "^2.2.4" }, merge(initializer.devDependencies), merge(kv.devDependencies), merge(mq.devDependencies), normalizePackageNames(packageManager));
|
|
27
36
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* @param param0 - Object containing the package manager and a boolean indicating if dev dependencies are to be added
|
|
33
|
-
* @yields The command-line arguments as strings
|
|
34
|
-
*/
|
|
35
|
-
function* getAddDepsArgs({ packageManager, dev = false }) {
|
|
36
|
-
yield packageManager;
|
|
37
|
-
yield "add";
|
|
38
|
-
if (dev) yield "-D";
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Joins package names with their versions for installation commands.
|
|
42
|
-
* For Deno, it prefixes packages with 'jsr:' unless they already start with 'npm:'.
|
|
37
|
+
* Joins package names with their versions for installation dependencies.
|
|
38
|
+
* For Deno, it prefixes packages with 'jsr:'
|
|
39
|
+
* unless they already start with 'npm:' or 'jsr:'.
|
|
43
40
|
*
|
|
44
41
|
* @param data - Package manager and dependencies to be joined with versions
|
|
45
|
-
* @returns `${registry}:${package}@${version}`
|
|
42
|
+
* @returns \{ name: `${registry}:${package}@${version}` } for deno
|
|
46
43
|
*/
|
|
47
|
-
const
|
|
48
|
-
const getPackageName = (pm, name) => pm !== "deno" ? name : name.startsWith("npm:") ? name.substring(4) : !name.startsWith("npm:") ? `jsr:${name}` : name;
|
|
44
|
+
const joinDepsReg = (pm) => (dependencies) => pipe(dependencies, entries, map(([name, version]) => [name.substring(4), `${name}@${getPackageVersion(pm, version)}`]), fromEntries);
|
|
49
45
|
const getPackageVersion = (pm, version) => pm !== "deno" && version.includes("+") ? version.substring(0, version.indexOf("+")) : version;
|
|
46
|
+
const normalizePackageNames = (pm) => (deps) => pipe(deps, entries, map(([name, version]) => [getPackageName(pm, name), version]), fromEntries);
|
|
47
|
+
const getPackageName = (pm, name) => pm !== "deno" ? name.startsWith("npm:") ? name.replace("npm:", "") : name : name.startsWith("npm:") ? name : `jsr:${name}`;
|
|
50
48
|
|
|
51
49
|
//#endregion
|
|
52
|
-
export {
|
|
50
|
+
export { getDependencies, getDevDependencies, joinDepsReg };
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { getAddDepsArgs, getDependencies, getDevDependencies, joinDepsVer } from "./deps.js";
|
|
7
|
-
import { isDeno } from "./utils.js";
|
|
8
|
-
import { always, concat, pipe, tap, toArray, unless, when } from "@fxts/core";
|
|
4
|
+
import { CommandError, runSubCommand } from "../../utils.js";
|
|
5
|
+
import { apply, pipe } from "@fxts/core";
|
|
9
6
|
|
|
10
7
|
//#region src/init/action/install.ts
|
|
11
|
-
const installDependencies = (data) => pipe(data,
|
|
8
|
+
const installDependencies = (data) => pipe(data, ({ packageManager, dir }) => [[packageManager, "install"], { cwd: dir }], apply(runSubCommand)).catch((e) => {
|
|
9
|
+
if (e instanceof CommandError) {
|
|
10
|
+
console.error(`Failed to install dependencies using ${data.packageManager}.`);
|
|
11
|
+
console.error("Command:", e.commandLine);
|
|
12
|
+
if (e.stderr) console.error("Error:", e.stderr);
|
|
13
|
+
throw e;
|
|
14
|
+
}
|
|
15
|
+
throw e;
|
|
16
|
+
});
|
|
12
17
|
var install_default = installDependencies;
|
|
13
|
-
const installDeps = (data) => pipe(data, set("dependencies", getDependencies), getAddDepsCommand, when(notEmpty, runAddDeps(data)));
|
|
14
|
-
const installDevDeps = (data) => pipe(data, set("dependencies", getDevDependencies), set("dev", always(true)), getAddDepsCommand, when(notEmpty, runAddDeps(data)));
|
|
15
|
-
const getAddDepsCommand = (data) => pipe(data, joinDepsVer, when(notEmpty, concat(getAddDepsArgs(data))), toArray);
|
|
16
|
-
const runAddDeps = ({ dir }) => (command) => runSubCommand(command, {
|
|
17
|
-
cwd: dir,
|
|
18
|
-
stdio: "inherit"
|
|
19
|
-
}).catch(noticeErrorWhileAddDeps(command));
|
|
20
18
|
|
|
21
19
|
//#endregion
|
|
22
20
|
export { install_default as default };
|
package/dist/init/action/mod.js
CHANGED
|
@@ -5,8 +5,8 @@ import ask_default from "../ask/mod.js";
|
|
|
5
5
|
import { makeDirIfHyd } from "./dir.js";
|
|
6
6
|
import { drawDinosaur, noticeHowToRun, noticeOptions, noticePrecommand } from "./notice.js";
|
|
7
7
|
import env_default from "./env.js";
|
|
8
|
-
import { hasCommand, isDry } from "./utils.js";
|
|
9
8
|
import install_default from "./install.js";
|
|
9
|
+
import { hasCommand, isDry } from "./utils.js";
|
|
10
10
|
import { patchFiles, recommendPatchFiles } from "./patch.js";
|
|
11
11
|
import precommand_default from "./precommand.js";
|
|
12
12
|
import recommend_default from "./recommend.js";
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
-
import { colors } from "../../utils.js";
|
|
5
|
-
import {
|
|
6
|
-
import { print, printError } from "@optique/run";
|
|
4
|
+
import { colors, printMessage } from "../../utils.js";
|
|
5
|
+
import { text } from "@optique/core";
|
|
7
6
|
import { flow } from "es-toolkit";
|
|
8
7
|
|
|
9
8
|
//#region src/init/action/notice.ts
|
|
10
|
-
const printMessage = flow(message, print);
|
|
11
|
-
const printErrorMessage = flow(message, printError);
|
|
12
9
|
function drawDinosaur() {
|
|
13
10
|
const d = flow(colors.bgBlue, colors.black);
|
|
14
11
|
const f = colors.blue;
|
|
@@ -37,26 +34,22 @@ const noticeFilesToInsert = () => printMessage`Would create/update JSON files:\n
|
|
|
37
34
|
const noticeDepsIfExist = () => printMessage`📦 Would install dependencies:`;
|
|
38
35
|
const noticeDevDepsIfExist = () => printMessage`📦 Would install dev dependencies:`;
|
|
39
36
|
const noticeDeps = ([name, version]) => printMessage`${name}@${version}`;
|
|
40
|
-
function displayFile(path
|
|
41
|
-
printMessage`${emoji} ${path
|
|
37
|
+
function displayFile(path, content, emoji = "📄") {
|
|
38
|
+
printMessage`${emoji} ${path}`;
|
|
42
39
|
printMessage`${"─".repeat(60)}`;
|
|
43
40
|
printMessage`${content}`;
|
|
44
41
|
printMessage`${"─".repeat(60)}\n`;
|
|
45
42
|
}
|
|
46
43
|
const noticeConfigEnv = () => printMessage`Note that you probably want to edit the ${".env"} file.
|
|
47
44
|
It currently contains the following values:\n`;
|
|
48
|
-
const noticeEnvKeyValue = ([key, value]) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const noticeEnvKeyValue = ([key, value]) => {
|
|
46
|
+
printMessage`${text(` ${key}='${value}'`)}`;
|
|
47
|
+
};
|
|
48
|
+
const noticeHowToRun = ({ initializer: { instruction, federationFile } }) => printMessage`
|
|
49
|
+
${instruction}
|
|
50
|
+
|
|
51
|
+
Start by editing the ${text(federationFile)} file to define your federation!
|
|
52
52
|
`;
|
|
53
|
-
}
|
|
54
|
-
function noticeErrorWhileAddDeps(command$1) {
|
|
55
|
-
return (error) => {
|
|
56
|
-
printErrorMessage`The command ${command$1.join(" ")} failed with the error: ${String(error)}`;
|
|
57
|
-
throw new Error("Failed to add dependencies.");
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
53
|
|
|
61
54
|
//#endregion
|
|
62
|
-
export { displayFile, drawDinosaur, noticeConfigEnv, noticeDeps, noticeDepsIfExist, noticeDevDepsIfExist, noticeEnvKeyValue,
|
|
55
|
+
export { displayFile, drawDinosaur, noticeConfigEnv, noticeDeps, noticeDepsIfExist, noticeDevDepsIfExist, noticeEnvKeyValue, noticeFilesToCreate, noticeFilesToInsert, noticeHowToRun, noticeOptions, noticePrecommand };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
-
import { formatJson, merge, set } from "../../utils.js";
|
|
4
|
+
import { formatJson, merge, replaceAll, set } from "../../utils.js";
|
|
5
5
|
import { createFile, throwUnlessNotExists } from "../lib.js";
|
|
6
6
|
import { displayFile, noticeFilesToCreate, noticeFilesToInsert } from "./notice.js";
|
|
7
7
|
import { joinDir, stringifyEnvs } from "./utils.js";
|
|
8
8
|
import { devToolConfigs, loadDenoConfig, loadPackageJson, loadTsConfig } from "./configs.js";
|
|
9
9
|
import { getImports, loadFederation, loadLogging } from "./templates.js";
|
|
10
10
|
import { readFile } from "node:fs/promises";
|
|
11
|
-
import { apply, entries,
|
|
11
|
+
import { always, apply, entries, map, pipe, pipeLazy, tap } from "@fxts/core";
|
|
12
12
|
import { toMerged } from "es-toolkit";
|
|
13
13
|
|
|
14
14
|
//#region src/init/action/patch.ts
|
|
@@ -17,15 +17,17 @@ import { toMerged } from "es-toolkit";
|
|
|
17
17
|
* Handles both dry-run mode (recommending files) and actual file creation.
|
|
18
18
|
* Orchestrates the entire file generation and writing process.
|
|
19
19
|
*
|
|
20
|
-
* @param data - The initialization command data containing project
|
|
20
|
+
* @param data - The initialization command data containing project
|
|
21
|
+
* configuration
|
|
21
22
|
* @returns A processed data object with files and JSONs ready for creation
|
|
22
23
|
*/
|
|
23
24
|
const patchFiles = (data) => pipe(data, set("files", getFiles), set("jsons", getJsons), createFiles);
|
|
24
25
|
const recommendPatchFiles = (data) => pipe(data, set("files", getFiles), set("jsons", getJsons), recommendFiles);
|
|
25
26
|
/**
|
|
26
27
|
* Generates text-based files (TypeScript, environment files) for the project.
|
|
27
|
-
* Creates federation configuration, logging setup, environment variables, and
|
|
28
|
-
* by processing templates and combining them with
|
|
28
|
+
* Creates federation configuration, logging setup, environment variables, and
|
|
29
|
+
* framework-specific files by processing templates and combining them with
|
|
30
|
+
* project-specific data.
|
|
29
31
|
*
|
|
30
32
|
* @param data - The initialization command data
|
|
31
33
|
* @returns A record of file paths to their string content
|
|
@@ -41,8 +43,9 @@ const getFiles = (data) => ({
|
|
|
41
43
|
});
|
|
42
44
|
/**
|
|
43
45
|
* Generates JSON configuration files based on the package manager type.
|
|
44
|
-
* Creates different sets of configuration files for Deno vs
|
|
45
|
-
* including compiler configs, package manifests, and development
|
|
46
|
+
* Creates different sets of configuration files for Deno vs other environments,
|
|
47
|
+
* including compiler configs, package manifests, and development
|
|
48
|
+
* tool configurations.
|
|
46
49
|
*
|
|
47
50
|
* @param data - The initialization command data
|
|
48
51
|
* @returns A record of file paths to their JSON object content
|
|
@@ -52,23 +55,24 @@ const getJsons = (data) => data.packageManager === "deno" ? {
|
|
|
52
55
|
[devToolConfigs["vscSetDeno"].path]: devToolConfigs["vscSetDeno"].data,
|
|
53
56
|
[devToolConfigs["vscExtDeno"].path]: devToolConfigs["vscExtDeno"].data
|
|
54
57
|
} : {
|
|
55
|
-
"tsconfig.json": loadTsConfig(data).data,
|
|
58
|
+
...data.initializer.compilerOptions ? { "tsconfig.json": loadTsConfig(data).data } : {},
|
|
56
59
|
"package.json": loadPackageJson(data).data,
|
|
57
60
|
[devToolConfigs["biome"].path]: devToolConfigs["biome"].data,
|
|
58
61
|
[devToolConfigs["vscSet"].path]: devToolConfigs["vscSet"].data,
|
|
59
62
|
[devToolConfigs["vscExt"].path]: devToolConfigs["vscExt"].data
|
|
60
63
|
};
|
|
61
64
|
/**
|
|
62
|
-
* Handles dry-run mode by recommending files to be created without actually
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
+
* Handles dry-run mode by recommending files to be created without actually
|
|
66
|
+
* creating them.
|
|
67
|
+
* Displays what files would be created and shows their content for user review,
|
|
68
|
+
* so users can preview the initialization process before committing to it.
|
|
65
69
|
*
|
|
66
70
|
* @param data - The initialization command data with files and JSONs prepared
|
|
67
71
|
* @returns The processed data with recommendations displayed
|
|
68
72
|
*/
|
|
69
73
|
const recommendFiles = (data) => pipe(data, tap(noticeFilesToCreate), tap(processAllFiles(displayFile)), tap(noticeFilesToInsert), set("files", ({ jsons }) => jsons), tap(processAllFiles(displayFile)));
|
|
70
74
|
/**
|
|
71
|
-
* Actually creates files on the filesystem during normal
|
|
75
|
+
* Actually creates files on the filesystem during normal execution.
|
|
72
76
|
* Merges text files and JSON files together and writes them to disk.
|
|
73
77
|
* This performs the actual file system operations to initialize the project.
|
|
74
78
|
*
|
|
@@ -77,18 +81,18 @@ const recommendFiles = (data) => pipe(data, tap(noticeFilesToCreate), tap(proces
|
|
|
77
81
|
*/
|
|
78
82
|
const createFiles = (data) => pipe(data, set("files", ({ jsons, files }) => toMerged(files, jsons)), tap(processAllFiles(createFile)));
|
|
79
83
|
/**
|
|
80
|
-
*
|
|
81
|
-
* Takes a
|
|
84
|
+
* Processes all files with a given processing function.
|
|
85
|
+
* Takes a processor (either display or create) and applies it to all files
|
|
82
86
|
* in the target directory, handling path resolution and content patching.
|
|
83
87
|
*
|
|
84
88
|
* @param process - Function to process each file (either display or create)
|
|
85
89
|
* @returns A function that processes all files in the given directory with the provided processor
|
|
86
90
|
*/
|
|
87
|
-
const processAllFiles = (process) => ({ dir, files }) => pipe(files, entries,
|
|
91
|
+
const processAllFiles = (process) => ({ dir, files }) => pipe(files, entries, map(pipeLazy(joinDir(dir), apply(patchContent), apply(process))), Array.fromAsync);
|
|
88
92
|
/**
|
|
89
|
-
* Patches file content by either merging JSON
|
|
90
|
-
* Handles existing files by reading their current content and intelligently
|
|
91
|
-
* it with new content based on the content type (JSON vs text).
|
|
93
|
+
* Patches file content by either merging JSON or appending text content.
|
|
94
|
+
* Handles existing files by reading their current content and intelligently
|
|
95
|
+
* combining it with new content based on the content type (JSON vs text).
|
|
92
96
|
*
|
|
93
97
|
* @param path - The file path to patch
|
|
94
98
|
* @param content - The new content (either string or object)
|
|
@@ -103,12 +107,21 @@ async function patchContent(path, content) {
|
|
|
103
107
|
* Merges new JSON data with existing JSON content and formats the result.
|
|
104
108
|
* Parses existing JSON content (if any) and deep merges it with new data,
|
|
105
109
|
* then formats the result for consistent output.
|
|
110
|
+
* Supports JSONC (JSON with Comments) by removing comments before parsing.
|
|
106
111
|
*
|
|
107
112
|
* @param prev - The previous JSON content as string
|
|
108
113
|
* @param data - The new data object to merge
|
|
109
114
|
* @returns Formatted JSON string with merged content
|
|
110
115
|
*/
|
|
111
|
-
const mergeJson = (prev, data) => pipe(prev ? JSON.parse(prev) : {}, merge(data), formatJson);
|
|
116
|
+
const mergeJson = (prev, data) => pipe(prev ? JSON.parse(removeJsonComments(prev)) : {}, merge(data), formatJson);
|
|
117
|
+
/**
|
|
118
|
+
* Removes single-line (//) and multi-line (/* *\/) comments from JSON string.
|
|
119
|
+
* This allows parsing JSONC (JSON with Comments) files.
|
|
120
|
+
*
|
|
121
|
+
* @param jsonString - The JSON string potentially containing comments
|
|
122
|
+
* @returns JSON string with comments removed
|
|
123
|
+
*/
|
|
124
|
+
const removeJsonComments = (jsonString) => pipe(jsonString, replaceAll(/\/\/.*$/gm, ""), replaceAll(/\/\*[\s\S]*?\*\//g, ""));
|
|
112
125
|
/**
|
|
113
126
|
* Appends new text content to existing text content line by line.
|
|
114
127
|
* Concatenates new content lines with existing content lines,
|
|
@@ -128,14 +141,7 @@ const appendText = (prev, data) => prev ? `${prev}\n${data}` : data;
|
|
|
128
141
|
* @returns The file content as string, or empty string if file doesn't exist
|
|
129
142
|
* @throws Error if file access fails for reasons other than file not existing
|
|
130
143
|
*/
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
return await readFile(path, "utf8");
|
|
134
|
-
} catch (e) {
|
|
135
|
-
throwUnlessNotExists(e);
|
|
136
|
-
return "";
|
|
137
|
-
}
|
|
138
|
-
}
|
|
144
|
+
const readFileIfExists = (path) => readFile(path, "utf8").catch(pipeLazy(tap(throwUnlessNotExists), always("")));
|
|
139
145
|
|
|
140
146
|
//#endregion
|
|
141
147
|
export { patchFiles, recommendPatchFiles };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
-
import { exit, runSubCommand } from "../../utils.js";
|
|
4
|
+
import { CommandError, exit, runSubCommand } from "../../utils.js";
|
|
5
5
|
|
|
6
6
|
//#region src/init/action/precommand.ts
|
|
7
7
|
/**
|
|
@@ -14,7 +14,12 @@ const runPrecommand = ({ initializer: { command }, dir }) => runSubCommand(comma
|
|
|
14
14
|
cwd: dir,
|
|
15
15
|
stdio: "inherit"
|
|
16
16
|
}).catch((e) => {
|
|
17
|
-
|
|
17
|
+
if (e instanceof CommandError) {
|
|
18
|
+
console.error("Failed to run the precommand.");
|
|
19
|
+
console.error("Command:", e.commandLine);
|
|
20
|
+
if (e.stderr) console.error("Error:", e.stderr);
|
|
21
|
+
if (e.stdout) console.error("Output:", e.stdout);
|
|
22
|
+
} else console.error("Failed to run the precommand:", e);
|
|
18
23
|
exit(1);
|
|
19
24
|
});
|
|
20
25
|
var precommand_default = runPrecommand;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import { notEmpty } from "../../utils.js";
|
|
5
5
|
import { noticeDeps, noticeDepsIfExist, noticeDevDepsIfExist } from "./notice.js";
|
|
6
|
-
import { getDependencies, getDevDependencies } from "./deps.js";
|
|
7
6
|
import { isDeno } from "./utils.js";
|
|
7
|
+
import { getDependencies, getDevDependencies } from "./deps.js";
|
|
8
8
|
import { map, peek, pipeLazy, tap, unless, when } from "@fxts/core";
|
|
9
9
|
|
|
10
10
|
//#region src/init/action/recommend.ts
|
package/dist/init/action/set.js
CHANGED
|
@@ -22,7 +22,7 @@ import { existsSync } from "node:fs";
|
|
|
22
22
|
const setData = (data) => pipe(data, setProjectName, setInitializer, setKv, setMq, setEnv);
|
|
23
23
|
var set_default = setData;
|
|
24
24
|
const setProjectName = set("projectName", async ({ dir }) => basename(existsSync(dir) ? await realpath(dir) : normalize(dir)));
|
|
25
|
-
const setInitializer = set("initializer", (
|
|
25
|
+
const setInitializer = set("initializer", (data) => webframeworks_default[data.webFramework].init(data));
|
|
26
26
|
const setKv = set("kv", ({ kvStore }) => kvStores[kvStore]);
|
|
27
27
|
const setMq = set("mq", ({ messageQueue }) => messageQueues[messageQueue]);
|
|
28
28
|
const setEnv = set("env", ({ kv, mq }) => merge(kv.env)(mq.env));
|
|
@@ -43,6 +43,7 @@ const getImports = ({ kv, mq }) => pipe(toMerged(kv.imports, mq.imports), entrie
|
|
|
43
43
|
* @returns A comma-separated string of named imports with aliases where needed
|
|
44
44
|
*/
|
|
45
45
|
const getAlias = (imports) => pipe(imports, entries, map(([name, alias]) => name === alias ? name : `${name} as ${alias}`), join(", "));
|
|
46
|
+
const ENV_REG_EXP = /process\.env\.(\w+)/g;
|
|
46
47
|
/**
|
|
47
48
|
* Converts Node.js environment variable access to Deno-compatible syntax when needed.
|
|
48
49
|
* Transforms `process.env.VAR_NAME` to `Deno.env.get("VAR_NAME")` for Deno projects.
|
|
@@ -51,7 +52,7 @@ const getAlias = (imports) => pipe(imports, entries, map(([name, alias]) => name
|
|
|
51
52
|
* @param pm - The package manager (runtime) being used
|
|
52
53
|
* @returns The converted object string with appropriate environment variable access syntax
|
|
53
54
|
*/
|
|
54
|
-
const convertEnv = (obj, pm) => pm === "deno" &&
|
|
55
|
+
const convertEnv = (obj, pm) => pm === "deno" && ENV_REG_EXP.test(obj) ? obj.replaceAll(ENV_REG_EXP, (_, g1) => `Deno.env.get("${g1}")`) : obj;
|
|
55
56
|
|
|
56
57
|
//#endregion
|
|
57
58
|
export { getImports, loadFederation, loadLogging };
|
package/dist/init/ask/kv.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
+
import { printErrorMessage } from "../../utils.js";
|
|
4
5
|
import { KV_STORE } from "../const.js";
|
|
5
|
-
import { kvStores } from "../lib.js";
|
|
6
|
+
import { isTest, kvStores } from "../lib.js";
|
|
6
7
|
import { select } from "@inquirer/prompts";
|
|
8
|
+
import { pipe, tap, throwError, unless, when } from "@fxts/core/index.js";
|
|
7
9
|
|
|
8
10
|
//#region src/init/ask/kv.ts
|
|
9
11
|
/**
|
|
@@ -13,21 +15,30 @@ import { select } from "@inquirer/prompts";
|
|
|
13
15
|
* @param options - Initialization options possibly containing a kvStore and packageManager
|
|
14
16
|
* @returns A promise resolving to options with a guaranteed kvStore
|
|
15
17
|
*/
|
|
16
|
-
const fillKvStore =
|
|
17
|
-
...options,
|
|
18
|
-
kvStore: options.kvStore ?? await askKvStore(options.packageManager)
|
|
19
|
-
});
|
|
18
|
+
const fillKvStore = (options) => pipe(options, when(isKvStoreEmpty, askKvStore), unless(isKvSupportsPm, (opt) => pipe(opt, when(isTest, throwError(unmatchedWhileTesting)), tap(noticeUnmatched), fillKvStore)));
|
|
20
19
|
var kv_default = fillKvStore;
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const isKvStoreEmpty = (options) => !options.kvStore;
|
|
21
|
+
const askKvStore = async (data) => ({
|
|
22
|
+
...data,
|
|
23
|
+
kvStore: await select({
|
|
24
|
+
message: "Choose the key-value store to use",
|
|
25
|
+
choices: KV_STORE.map(choiceKvStore(data.packageManager))
|
|
26
|
+
})
|
|
24
27
|
});
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const unmatchedWhileTesting = ({ kvStore: kv, packageManager: pm }) => /* @__PURE__ */ new Error(`Key-value store '${kv}' is not compatible with package manager '${pm}'`);
|
|
29
|
+
const noticeUnmatched = ({ kvStore: kv, packageManager: pm }) => printErrorMessage`Error: Key-value store '${kv}' is not compatible with package manager '${pm}'`;
|
|
30
|
+
const choiceKvStore = (pm) => (kv) => ({
|
|
31
|
+
name: isKvSupportsPm({
|
|
32
|
+
kvStore: kv,
|
|
33
|
+
packageManager: pm
|
|
34
|
+
}) ? kv : `${kv} (not supported with ${pm})`,
|
|
35
|
+
value: kv,
|
|
36
|
+
disabled: !isKvSupportsPm({
|
|
37
|
+
kvStore: kv,
|
|
38
|
+
packageManager: pm
|
|
39
|
+
})
|
|
29
40
|
});
|
|
30
|
-
const isKvSupportsPm = (
|
|
41
|
+
const isKvSupportsPm = ({ kvStore, packageManager }) => kvStores[kvStore].packageManagers.includes(packageManager);
|
|
31
42
|
|
|
32
43
|
//#endregion
|
|
33
44
|
export { kv_default as default };
|
package/dist/init/ask/mq.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
|
|
4
|
+
import { printErrorMessage } from "../../utils.js";
|
|
4
5
|
import { MESSAGE_QUEUE } from "../const.js";
|
|
5
|
-
import { messageQueues } from "../lib.js";
|
|
6
|
+
import { isTest, messageQueues } from "../lib.js";
|
|
6
7
|
import { select } from "@inquirer/prompts";
|
|
8
|
+
import { pipe, tap, throwError, unless, when } from "@fxts/core/index.js";
|
|
7
9
|
|
|
8
10
|
//#region src/init/ask/mq.ts
|
|
9
11
|
/**
|
|
@@ -13,21 +15,32 @@ import { select } from "@inquirer/prompts";
|
|
|
13
15
|
* @param options - Initialization options possibly containing a messageQueue and packageManager
|
|
14
16
|
* @returns A promise resolving to options with a guaranteed messageQueue
|
|
15
17
|
*/
|
|
16
|
-
const fillMessageQueue =
|
|
17
|
-
...options,
|
|
18
|
-
messageQueue: options.messageQueue ?? await askMessageQueue(options.packageManager)
|
|
19
|
-
});
|
|
18
|
+
const fillMessageQueue = (options) => pipe(options, when(isMessageQueueEmpty, askMessageQueue), unless(isMqSupportsPm, (opt) => pipe(opt, when(isTest, throwError(unmatchedWhileTesting)), tap(noticeUnmatched), fillMessageQueue)));
|
|
20
19
|
var mq_default = fillMessageQueue;
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const isMessageQueueEmpty = (options) => !options.messageQueue;
|
|
21
|
+
const askMessageQueue = async (data) => ({
|
|
22
|
+
...data,
|
|
23
|
+
messageQueue: await select({
|
|
24
|
+
message: "Choose the message queue to use",
|
|
25
|
+
choices: MESSAGE_QUEUE.map(choiceMessageQueue(data.packageManager))
|
|
26
|
+
})
|
|
24
27
|
});
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const unmatchedWhileTesting = ({ messageQueue: mq, packageManager: pm }) => /* @__PURE__ */ new Error(`Message queue '${mq}' is not compatible with package manager '${pm}'`);
|
|
29
|
+
const noticeUnmatched = ({ messageQueue: mq, packageManager: pm }) => {
|
|
30
|
+
printErrorMessage`Error: Message queue '${mq}' is not compatible with package manager '${pm}'`;
|
|
31
|
+
};
|
|
32
|
+
const choiceMessageQueue = (packageManager) => (messageQueue) => ({
|
|
33
|
+
name: isMqSupportsPm({
|
|
34
|
+
messageQueue,
|
|
35
|
+
packageManager
|
|
36
|
+
}) ? messageQueue : `${messageQueue} (not supported with ${packageManager})`,
|
|
37
|
+
value: messageQueue,
|
|
38
|
+
disabled: !isMqSupportsPm({
|
|
39
|
+
messageQueue,
|
|
40
|
+
packageManager
|
|
41
|
+
})
|
|
29
42
|
});
|
|
30
|
-
const isMqSupportsPm = (
|
|
43
|
+
const isMqSupportsPm = ({ messageQueue, packageManager }) => messageQueues[messageQueue].packageManagers.includes(packageManager);
|
|
31
44
|
|
|
32
45
|
//#endregion
|
|
33
46
|
export { mq_default as default };
|