@fedify/init 2.0.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +93 -0
- package/dist/action/configs.mjs +89 -0
- package/dist/action/const.mjs +7 -0
- package/dist/action/deps.mjs +50 -0
- package/dist/action/dir.mjs +13 -0
- package/dist/action/env.mjs +10 -0
- package/dist/action/install.mjs +17 -0
- package/dist/action/mod.d.mts +23 -0
- package/dist/action/mod.mjs +38 -0
- package/dist/action/notice.mjs +52 -0
- package/dist/action/patch.mjs +143 -0
- package/dist/action/precommand.mjs +25 -0
- package/dist/action/recommend.mjs +21 -0
- package/dist/action/set.mjs +28 -0
- package/dist/action/templates.mjs +55 -0
- package/dist/action/utils.mjs +47 -0
- package/dist/ask/dir.mjs +79 -0
- package/dist/ask/kv.mjs +41 -0
- package/dist/ask/mod.mjs +13 -0
- package/dist/ask/mq.mjs +43 -0
- package/dist/ask/pm.mjs +49 -0
- package/dist/ask/wf.mjs +26 -0
- package/dist/command.d.mts +41 -0
- package/dist/command.mjs +44 -0
- package/dist/const.d.mts +4 -0
- package/dist/const.mjs +34 -0
- package/dist/deno.mjs +5 -0
- package/dist/json/biome.json +14 -0
- package/dist/json/biome.mjs +14 -0
- package/dist/json/db-to-check.json +17 -0
- package/dist/json/db-to-check.mjs +21 -0
- package/dist/json/kv.json +39 -0
- package/dist/json/kv.mjs +47 -0
- package/dist/json/mq.json +95 -0
- package/dist/json/mq.mjs +65 -0
- package/dist/json/pm.json +47 -0
- package/dist/json/pm.mjs +36 -0
- package/dist/json/rt.json +42 -0
- package/dist/json/rt.mjs +31 -0
- package/dist/json/vscode-settings-for-deno.json +43 -0
- package/dist/json/vscode-settings-for-deno.mjs +39 -0
- package/dist/json/vscode-settings.json +41 -0
- package/dist/json/vscode-settings.mjs +37 -0
- package/dist/lib.mjs +129 -0
- package/dist/mod.d.mts +3 -0
- package/dist/mod.mjs +4 -0
- package/dist/templates/defaults/eslint.config.ts.tpl +3 -0
- package/dist/templates/defaults/federation.ts.tpl +24 -0
- package/dist/templates/defaults/logging.ts.tpl +23 -0
- package/dist/templates/elysia/index/bun.ts.tpl +13 -0
- package/dist/templates/elysia/index/deno.ts.tpl +19 -0
- package/dist/templates/elysia/index/node.ts.tpl +14 -0
- package/dist/templates/express/app.ts.tpl +16 -0
- package/dist/templates/express/index.ts.tpl +6 -0
- package/dist/templates/hono/app.tsx.tpl +14 -0
- package/dist/templates/hono/index/bun.ts.tpl +10 -0
- package/dist/templates/hono/index/deno.ts.tpl +13 -0
- package/dist/templates/hono/index/node.ts.tpl +14 -0
- package/dist/templates/next/middleware.ts.tpl +45 -0
- package/dist/templates/nitro/.env.test.tpl +1 -0
- package/dist/templates/nitro/nitro.config.ts.tpl +14 -0
- package/dist/templates/nitro/server/error.ts.tpl +3 -0
- package/dist/templates/nitro/server/middleware/federation.ts.tpl +8 -0
- package/dist/test/action.mjs +15 -0
- package/dist/test/create.mjs +92 -0
- package/dist/test/db.mjs +42 -0
- package/dist/test/fill.mjs +29 -0
- package/dist/test/lookup.mjs +183 -0
- package/dist/test/mod.d.mts +1 -0
- package/dist/test/mod.mjs +16 -0
- package/dist/test/run.mjs +22 -0
- package/dist/test/utils.mjs +15 -0
- package/dist/types.d.mts +50 -0
- package/dist/utils.d.mts +9 -0
- package/dist/utils.mjs +102 -0
- package/dist/webframeworks.mjs +220 -0
- package/package.json +66 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { replace } from "../utils.mjs";
|
|
2
|
+
import { readTemplate } from "../lib.mjs";
|
|
3
|
+
import { entries, join, map, pipe } from "@fxts/core";
|
|
4
|
+
import { toMerged } from "es-toolkit";
|
|
5
|
+
|
|
6
|
+
//#region src/action/templates.ts
|
|
7
|
+
/**
|
|
8
|
+
* Loads the federation configuration file content from template.
|
|
9
|
+
* Reads the default federation template and replaces placeholders with actual configuration values.
|
|
10
|
+
*
|
|
11
|
+
* @param param0 - Configuration object containing imports, project name, KV store, message queue, and package manager
|
|
12
|
+
* @returns The complete federation configuration file content as a string
|
|
13
|
+
*/
|
|
14
|
+
const loadFederation = ({ imports, projectName, kv, mq, packageManager }) => pipe("defaults/federation.ts", readTemplate, replace(/\/\* imports \*\//, imports), replace(/\/\* logger \*\//, JSON.stringify(projectName)), replace(/\/\* kv \*\//, convertEnv(kv.object, packageManager)), replace(/\/\* queue \*\//, convertEnv(mq.object, packageManager)));
|
|
15
|
+
/**
|
|
16
|
+
* Loads the logging configuration file content from template.
|
|
17
|
+
* Reads the default logging template and replaces the project name placeholder.
|
|
18
|
+
*
|
|
19
|
+
* @param param0 - Destructured object containing the project name
|
|
20
|
+
* @returns The complete logging configuration file content as a string
|
|
21
|
+
*/
|
|
22
|
+
const loadLogging = ({ projectName }) => pipe("defaults/logging.ts", readTemplate, replace(/\/\* project name \*\//, JSON.stringify(projectName)));
|
|
23
|
+
/**
|
|
24
|
+
* Generates import statements for KV store and message queue dependencies.
|
|
25
|
+
* Merges imports from both KV and MQ configurations and creates proper ES module import syntax.
|
|
26
|
+
*
|
|
27
|
+
* @param param0 - Destructured object containing kv and mq configurations
|
|
28
|
+
* @returns A multi-line string containing all necessary import statements
|
|
29
|
+
*/
|
|
30
|
+
const getImports = ({ kv, mq }) => pipe(toMerged(kv.imports, mq.imports), entries, map(([module, { "default": defaultImport = "", ...imports }]) => [
|
|
31
|
+
module,
|
|
32
|
+
defaultImport,
|
|
33
|
+
getAlias(imports)
|
|
34
|
+
]), map(([module, defaultImport, namedImports]) => `import ${[defaultImport, namedImports.length > 0 ? `{ ${namedImports} }` : ""].filter((x) => x.length > 0).join(", ")} from ${JSON.stringify(module)};`), join("\n"));
|
|
35
|
+
/**
|
|
36
|
+
* Converts import mappings to named import string with aliases.
|
|
37
|
+
* Creates proper ES module named import syntax, using aliases when the import name differs from the local name.
|
|
38
|
+
*
|
|
39
|
+
* @param imports - A record mapping import names to their local aliases
|
|
40
|
+
* @returns A comma-separated string of named imports with aliases where needed
|
|
41
|
+
*/
|
|
42
|
+
const getAlias = (imports) => pipe(imports, entries, map(([name, alias]) => name === alias ? name : `${name} as ${alias}`), join(", "));
|
|
43
|
+
const ENV_REG_EXP = /process\.env\.(\w+)/g;
|
|
44
|
+
/**
|
|
45
|
+
* Converts Node.js environment variable access to Deno-compatible syntax when needed.
|
|
46
|
+
* Transforms `process.env.VAR_NAME` to `Deno.env.get("VAR_NAME")` for Deno projects.
|
|
47
|
+
*
|
|
48
|
+
* @param obj - The object string containing potential environment variable references
|
|
49
|
+
* @param pm - The package manager (runtime) being used
|
|
50
|
+
* @returns The converted object string with appropriate environment variable access syntax
|
|
51
|
+
*/
|
|
52
|
+
const convertEnv = (obj, pm) => pm === "deno" && ENV_REG_EXP.test(obj) ? obj.replaceAll(ENV_REG_EXP, (_, g1) => `Deno.env.get("${g1}")`) : obj;
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { getImports, loadFederation, loadLogging };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
|
|
3
|
+
//#region src/action/utils.ts
|
|
4
|
+
const isDry = ({ dryRun }) => dryRun;
|
|
5
|
+
const hasCommand = (data) => !!data.initializer.command;
|
|
6
|
+
const isDeno = ({ packageManager }) => packageManager === "deno";
|
|
7
|
+
const joinDir = (dir) => ([filename, content]) => [join(dir, ...filename.split("/")), content];
|
|
8
|
+
/**
|
|
9
|
+
* Stringify an object into a valid `.env` file format.
|
|
10
|
+
* From `@std/dotenv/stringify`.
|
|
11
|
+
*
|
|
12
|
+
* @example Usage
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { stringifyEnvs } from "./utils.ts";
|
|
15
|
+
* import { assertEquals } from "@std/assert";
|
|
16
|
+
*
|
|
17
|
+
* const object = { GREETING: "hello world" };
|
|
18
|
+
* assertEquals(stringifyEnvs(object), "GREETING='hello world'");
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @param object object to be stringified
|
|
22
|
+
* @returns string of object
|
|
23
|
+
*/
|
|
24
|
+
function stringifyEnvs(object) {
|
|
25
|
+
const lines = [];
|
|
26
|
+
for (const [key, value] of Object.entries(object)) {
|
|
27
|
+
let quote;
|
|
28
|
+
let escapedValue = value ?? "";
|
|
29
|
+
if (key.startsWith("#")) {
|
|
30
|
+
console.warn(`key starts with a '#' indicates a comment and is ignored: '${key}'`);
|
|
31
|
+
continue;
|
|
32
|
+
} else if (escapedValue.includes("\n") || escapedValue.includes("'")) {
|
|
33
|
+
escapedValue = escapedValue.replaceAll("\n", "\\n");
|
|
34
|
+
quote = `"`;
|
|
35
|
+
} else if (escapedValue.match(/\W/)) quote = "'";
|
|
36
|
+
if (quote) {
|
|
37
|
+
escapedValue = escapedValue.replaceAll(quote, `\\${quote}`);
|
|
38
|
+
escapedValue = `${quote}${escapedValue}${quote}`;
|
|
39
|
+
}
|
|
40
|
+
const line = `${key}=${escapedValue}`;
|
|
41
|
+
lines.push(line);
|
|
42
|
+
}
|
|
43
|
+
return lines.join("\n");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { hasCommand, isDeno, isDry, joinDir, stringifyEnvs };
|
package/dist/ask/dir.mjs
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { getCwd, getOsType, runSubCommand } from "../utils.mjs";
|
|
2
|
+
import { isDirectoryEmpty, logger } from "../lib.mjs";
|
|
3
|
+
import { identity, pipe, when } from "@fxts/core";
|
|
4
|
+
import { input } from "@inquirer/prompts";
|
|
5
|
+
import { message } from "@optique/core/message";
|
|
6
|
+
import { printError } from "@optique/run";
|
|
7
|
+
import toggle from "inquirer-toggle";
|
|
8
|
+
|
|
9
|
+
//#region src/ask/dir.ts
|
|
10
|
+
/**
|
|
11
|
+
* Fills in the project directory by prompting the user if not provided.
|
|
12
|
+
* If the directory is not empty, asks the user whether to use it anyway.
|
|
13
|
+
* If the user agrees, offers to move existing contents to trash.
|
|
14
|
+
* Else, recursively prompts for a new directory until a valid one is provided.
|
|
15
|
+
*
|
|
16
|
+
* @param options - Initialization options possibly containing a directory
|
|
17
|
+
* @returns A promise resolving to options with a guaranteed directory
|
|
18
|
+
*/
|
|
19
|
+
const fillDir = async (options) => {
|
|
20
|
+
const dir = options.dir ?? await askDir(getCwd());
|
|
21
|
+
return await askIfNonEmpty(dir) ? {
|
|
22
|
+
...options,
|
|
23
|
+
dir
|
|
24
|
+
} : await fillDir(options);
|
|
25
|
+
};
|
|
26
|
+
var dir_default = fillDir;
|
|
27
|
+
const askDir = (cwd) => input({
|
|
28
|
+
message: "Project directory:",
|
|
29
|
+
default: cwd
|
|
30
|
+
});
|
|
31
|
+
const askIfNonEmpty = async (dir) => {
|
|
32
|
+
if (await isDirectoryEmpty(dir)) return true;
|
|
33
|
+
if (await askNonEmpty(dir)) return await moveDirToTrash(dir);
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
const askNonEmpty = (dir) => toggle.default({
|
|
37
|
+
message: `Directory "${dir}" is not empty.
|
|
38
|
+
Do you want to use it anyway?`,
|
|
39
|
+
default: false
|
|
40
|
+
});
|
|
41
|
+
const moveDirToTrash = (dir) => pipe(dir, askMoveToTrash, when(identity, moveToTrash(dir)));
|
|
42
|
+
const askMoveToTrash = (dir) => toggle.default({
|
|
43
|
+
message: `Do you want to move the contents of "${dir}" to the trash?
|
|
44
|
+
If you choose "No", you should choose another directory.`,
|
|
45
|
+
default: false
|
|
46
|
+
});
|
|
47
|
+
const moveToTrash = (dir) => () => pipe(getOsType(), getTrashCommand, (fn) => fn(dir), (cmd) => runSubCommand(cmd, { stdio: "ignore" }), () => true).catch((e) => {
|
|
48
|
+
logger.error(e);
|
|
49
|
+
printError(message`Failed to move ${dir} to trash.
|
|
50
|
+
Please move it manually.`);
|
|
51
|
+
return false;
|
|
52
|
+
});
|
|
53
|
+
const getTrashCommand = (os) => trashCommands[os] ?? trashCommands.linux;
|
|
54
|
+
const trashCommands = {
|
|
55
|
+
darwin: (dir) => ["trash", dir],
|
|
56
|
+
win32: (dir) => [
|
|
57
|
+
"powershell",
|
|
58
|
+
"-Command",
|
|
59
|
+
getPowershellTrashCommand(dir)
|
|
60
|
+
],
|
|
61
|
+
linux: (dir) => [
|
|
62
|
+
"rm",
|
|
63
|
+
"-rf",
|
|
64
|
+
dir
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
const getPowershellTrashCommand = (dir) => [
|
|
68
|
+
"Add-Type",
|
|
69
|
+
"-AssemblyName",
|
|
70
|
+
"Microsoft.VisualBasic;",
|
|
71
|
+
"[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory('",
|
|
72
|
+
dir,
|
|
73
|
+
"',",
|
|
74
|
+
"'OnlyErrorDialogs',",
|
|
75
|
+
"'SendToRecycleBin')"
|
|
76
|
+
].join(" ");
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { dir_default as default };
|
package/dist/ask/kv.mjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { printErrorMessage } from "../utils.mjs";
|
|
2
|
+
import { isTest, kvStores } from "../lib.mjs";
|
|
3
|
+
import { KV_STORE } from "../const.mjs";
|
|
4
|
+
import { select } from "@inquirer/prompts";
|
|
5
|
+
import { pipe, tap, throwError, unless, when } from "@fxts/core/index.js";
|
|
6
|
+
|
|
7
|
+
//#region src/ask/kv.ts
|
|
8
|
+
/**
|
|
9
|
+
* Fills in the key-value store by prompting the user if not provided.
|
|
10
|
+
* Ensures the selected KV store is compatible with the chosen package manager.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Initialization options possibly containing a kvStore and packageManager
|
|
13
|
+
* @returns A promise resolving to options with a guaranteed kvStore
|
|
14
|
+
*/
|
|
15
|
+
const fillKvStore = (options) => pipe(options, when(isKvStoreEmpty, askKvStore), unless(isKvSupportsPm, (opt) => pipe(opt, when(isTest, throwError(unmatchedWhileTesting)), tap(noticeUnmatched), fillKvStore)));
|
|
16
|
+
var kv_default = fillKvStore;
|
|
17
|
+
const isKvStoreEmpty = (options) => !options.kvStore;
|
|
18
|
+
const askKvStore = async (data) => ({
|
|
19
|
+
...data,
|
|
20
|
+
kvStore: await select({
|
|
21
|
+
message: "Choose the key-value store to use",
|
|
22
|
+
choices: KV_STORE.map(choiceKvStore(data.packageManager))
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
const unmatchedWhileTesting = ({ kvStore: kv, packageManager: pm }) => /* @__PURE__ */ new Error(`Key-value store '${kv}' is not compatible with package manager '${pm}'`);
|
|
26
|
+
const noticeUnmatched = ({ kvStore: kv, packageManager: pm }) => printErrorMessage`Error: Key-value store '${kv}' is not compatible with package manager '${pm}'`;
|
|
27
|
+
const choiceKvStore = (pm) => (kv) => ({
|
|
28
|
+
name: isKvSupportsPm({
|
|
29
|
+
kvStore: kv,
|
|
30
|
+
packageManager: pm
|
|
31
|
+
}) ? kv : `${kv} (not supported with ${pm})`,
|
|
32
|
+
value: kv,
|
|
33
|
+
disabled: !isKvSupportsPm({
|
|
34
|
+
kvStore: kv,
|
|
35
|
+
packageManager: pm
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
const isKvSupportsPm = ({ kvStore, packageManager }) => kvStores[kvStore].packageManagers.includes(packageManager);
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { kv_default as default };
|
package/dist/ask/mod.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import dir_default from "./dir.mjs";
|
|
2
|
+
import kv_default from "./kv.mjs";
|
|
3
|
+
import mq_default from "./mq.mjs";
|
|
4
|
+
import pm_default from "./pm.mjs";
|
|
5
|
+
import wf_default from "./wf.mjs";
|
|
6
|
+
import { pipe } from "@fxts/core";
|
|
7
|
+
|
|
8
|
+
//#region src/ask/mod.ts
|
|
9
|
+
const askOptions = (options) => pipe(options, dir_default, wf_default, pm_default, mq_default, kv_default);
|
|
10
|
+
var ask_default = askOptions;
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ask_default as default };
|
package/dist/ask/mq.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { printErrorMessage } from "../utils.mjs";
|
|
2
|
+
import { isTest, messageQueues } from "../lib.mjs";
|
|
3
|
+
import { MESSAGE_QUEUE } from "../const.mjs";
|
|
4
|
+
import { select } from "@inquirer/prompts";
|
|
5
|
+
import { pipe, tap, throwError, unless, when } from "@fxts/core/index.js";
|
|
6
|
+
|
|
7
|
+
//#region src/ask/mq.ts
|
|
8
|
+
/**
|
|
9
|
+
* Fills in the message queue by prompting the user if not provided.
|
|
10
|
+
* Ensures the selected message queue is compatible with the chosen package manager.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Initialization options possibly containing a messageQueue and packageManager
|
|
13
|
+
* @returns A promise resolving to options with a guaranteed messageQueue
|
|
14
|
+
*/
|
|
15
|
+
const fillMessageQueue = (options) => pipe(options, when(isMessageQueueEmpty, askMessageQueue), unless(isMqSupportsPm, (opt) => pipe(opt, when(isTest, throwError(unmatchedWhileTesting)), tap(noticeUnmatched), fillMessageQueue)));
|
|
16
|
+
var mq_default = fillMessageQueue;
|
|
17
|
+
const isMessageQueueEmpty = (options) => !options.messageQueue;
|
|
18
|
+
const askMessageQueue = async (data) => ({
|
|
19
|
+
...data,
|
|
20
|
+
messageQueue: await select({
|
|
21
|
+
message: "Choose the message queue to use",
|
|
22
|
+
choices: MESSAGE_QUEUE.map(choiceMessageQueue(data.packageManager))
|
|
23
|
+
})
|
|
24
|
+
});
|
|
25
|
+
const unmatchedWhileTesting = ({ messageQueue: mq, packageManager: pm }) => /* @__PURE__ */ new Error(`Message queue '${mq}' is not compatible with package manager '${pm}'`);
|
|
26
|
+
const noticeUnmatched = ({ messageQueue: mq, packageManager: pm }) => {
|
|
27
|
+
printErrorMessage`Error: Message queue '${mq}' is not compatible with package manager '${pm}'`;
|
|
28
|
+
};
|
|
29
|
+
const choiceMessageQueue = (packageManager) => (messageQueue) => ({
|
|
30
|
+
name: isMqSupportsPm({
|
|
31
|
+
messageQueue,
|
|
32
|
+
packageManager
|
|
33
|
+
}) ? messageQueue : `${messageQueue} (not supported with ${packageManager})`,
|
|
34
|
+
value: messageQueue,
|
|
35
|
+
disabled: !isMqSupportsPm({
|
|
36
|
+
messageQueue,
|
|
37
|
+
packageManager
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
const isMqSupportsPm = ({ messageQueue, packageManager }) => messageQueues[messageQueue].packageManagers.includes(packageManager);
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { mq_default as default };
|
package/dist/ask/pm.mjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getInstallUrl, isPackageManagerAvailable, kvStores, messageQueues, packageManagers, runtimes } from "../lib.mjs";
|
|
2
|
+
import { PACKAGE_MANAGER } from "../const.mjs";
|
|
3
|
+
import webframeworks_default from "../webframeworks.mjs";
|
|
4
|
+
import { pipe, when } from "@fxts/core";
|
|
5
|
+
import { select } from "@inquirer/prompts";
|
|
6
|
+
import { message } from "@optique/core/message";
|
|
7
|
+
import { print } from "@optique/run";
|
|
8
|
+
|
|
9
|
+
//#region src/ask/pm.ts
|
|
10
|
+
/**
|
|
11
|
+
* Fills in the package manager by prompting the user if not provided.
|
|
12
|
+
* Ensures the selected package manager is compatible with the chosen web framework.
|
|
13
|
+
* If the selected package manager is not installed, informs the user and prompts again.
|
|
14
|
+
*
|
|
15
|
+
* @param options - Initialization options possibly containing a packageManager and webFramework
|
|
16
|
+
* @returns A promise resolving to options with a guaranteed packageManager
|
|
17
|
+
*/
|
|
18
|
+
const fillPackageManager = async ({ packageManager, ...options }) => {
|
|
19
|
+
const pm = packageManager ?? await askPackageManager(options.webFramework);
|
|
20
|
+
if (await isPackageManagerAvailable(pm)) return {
|
|
21
|
+
...options,
|
|
22
|
+
packageManager: pm
|
|
23
|
+
};
|
|
24
|
+
noticeInstallUrl(pm);
|
|
25
|
+
return await fillPackageManager(options);
|
|
26
|
+
};
|
|
27
|
+
var pm_default = fillPackageManager;
|
|
28
|
+
const askPackageManager = (wf) => select({
|
|
29
|
+
message: "Choose the package manager to use",
|
|
30
|
+
choices: PACKAGE_MANAGER.map(choicePackageManager(wf))
|
|
31
|
+
});
|
|
32
|
+
const choicePackageManager = (wf) => (value) => ({
|
|
33
|
+
name: isWfSupportsPm(wf, value) ? value : `${value} (not supported with ${webframeworks_default[wf].label})`,
|
|
34
|
+
value,
|
|
35
|
+
disabled: !isWfSupportsPm(wf, value)
|
|
36
|
+
});
|
|
37
|
+
const isWfSupportsPm = (wf, pm) => webframeworks_default[wf].packageManagers.includes(pm);
|
|
38
|
+
const noticeInstallUrl = (pm) => {
|
|
39
|
+
const label = getLabel(pm);
|
|
40
|
+
const url = getInstallUrl(pm);
|
|
41
|
+
print(message` Package manager ${label} is not installed.`);
|
|
42
|
+
print(message` You can install it from following link: ${url}`);
|
|
43
|
+
print(message` or choose another package manager:`);
|
|
44
|
+
};
|
|
45
|
+
const getLabel = (name) => pipe(name, whenHasLabel(webframeworks_default), whenHasLabel(packageManagers), whenHasLabel(messageQueues), whenHasLabel(kvStores), whenHasLabel(runtimes));
|
|
46
|
+
const whenHasLabel = (desc) => when((name) => name in desc, (name) => desc[name].label);
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { pm_default as default };
|
package/dist/ask/wf.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { WEB_FRAMEWORK } from "../const.mjs";
|
|
2
|
+
import webframeworks_default from "../webframeworks.mjs";
|
|
3
|
+
import { select } from "@inquirer/prompts";
|
|
4
|
+
|
|
5
|
+
//#region src/ask/wf.ts
|
|
6
|
+
/**
|
|
7
|
+
* Fills in the web framework by prompting the user if not provided.
|
|
8
|
+
*
|
|
9
|
+
* @param options - Initialization options possibly containing a webFramework
|
|
10
|
+
* @returns A promise resolving to options with a guaranteed webFramework
|
|
11
|
+
*/
|
|
12
|
+
const fillWebFramework = async (options) => ({
|
|
13
|
+
...options,
|
|
14
|
+
webFramework: options.webFramework ?? await askWebFramework()
|
|
15
|
+
});
|
|
16
|
+
var wf_default = fillWebFramework;
|
|
17
|
+
const askWebFramework = () => select({
|
|
18
|
+
message: "Choose the web framework to use",
|
|
19
|
+
choices: WEB_FRAMEWORK.map((value) => ({
|
|
20
|
+
name: webframeworks_default[value].label,
|
|
21
|
+
value
|
|
22
|
+
}))
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { wf_default as default };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as _optique_core0 from "@optique/core";
|
|
2
|
+
import { InferValue } from "@optique/core";
|
|
3
|
+
|
|
4
|
+
//#region src/command.d.ts
|
|
5
|
+
declare const initOptions: _optique_core0.Parser<"sync", {
|
|
6
|
+
readonly dir: string;
|
|
7
|
+
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "express";
|
|
8
|
+
readonly packageManager: "deno" | "pnpm" | "bun" | "yarn" | "npm";
|
|
9
|
+
readonly kvStore: "denokv" | "redis" | "postgres";
|
|
10
|
+
readonly messageQueue: "denokv" | "redis" | "postgres" | "amqp";
|
|
11
|
+
readonly dryRun: boolean;
|
|
12
|
+
readonly debugOption: {
|
|
13
|
+
readonly debug: boolean;
|
|
14
|
+
};
|
|
15
|
+
}, {
|
|
16
|
+
readonly dir: [_optique_core0.ValueParserResult<string>];
|
|
17
|
+
readonly webFramework: [_optique_core0.ValueParserResult<"hono" | "nitro" | "next" | "elysia" | "express">];
|
|
18
|
+
readonly packageManager: [_optique_core0.ValueParserResult<"deno" | "pnpm" | "bun" | "yarn" | "npm">];
|
|
19
|
+
readonly kvStore: [_optique_core0.ValueParserResult<"denokv" | "redis" | "postgres">];
|
|
20
|
+
readonly messageQueue: [_optique_core0.ValueParserResult<"denokv" | "redis" | "postgres" | "amqp">];
|
|
21
|
+
readonly dryRun: _optique_core0.ValueParserResult<boolean>;
|
|
22
|
+
readonly debugOption: {
|
|
23
|
+
readonly debug: _optique_core0.ValueParserResult<boolean>;
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
26
|
+
declare const initCommand: _optique_core0.Parser<"sync", {
|
|
27
|
+
readonly dir: string;
|
|
28
|
+
readonly webFramework: "hono" | "nitro" | "next" | "elysia" | "express";
|
|
29
|
+
readonly packageManager: "deno" | "pnpm" | "bun" | "yarn" | "npm";
|
|
30
|
+
readonly kvStore: "denokv" | "redis" | "postgres";
|
|
31
|
+
readonly messageQueue: "denokv" | "redis" | "postgres" | "amqp";
|
|
32
|
+
readonly dryRun: boolean;
|
|
33
|
+
readonly debugOption: {
|
|
34
|
+
readonly debug: boolean;
|
|
35
|
+
};
|
|
36
|
+
} & {
|
|
37
|
+
readonly command: "init";
|
|
38
|
+
}, ["matched", string] | ["parsing", Record<string | symbol, unknown>]>;
|
|
39
|
+
type InitCommand = InferValue<typeof initCommand>;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { InitCommand, initCommand, initOptions };
|
package/dist/command.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { KV_STORE, MESSAGE_QUEUE, PACKAGE_MANAGER, WEB_FRAMEWORK } from "./const.mjs";
|
|
2
|
+
import { path } from "@optique/run";
|
|
3
|
+
import { argument, choice, command, constant, merge, message, multiple, object, option, optionNames, optional, or } from "@optique/core";
|
|
4
|
+
|
|
5
|
+
//#region src/command.ts
|
|
6
|
+
const webFramework = optional(option("-w", "--web-framework", choice(WEB_FRAMEWORK, { metavar: "WEB_FRAMEWORK" }), { description: message`The web framework to integrate Fedify with.` }));
|
|
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
|
+
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
|
+
const messageQueue = optional(option("-m", "--message-queue", choice(MESSAGE_QUEUE, { metavar: "MESSAGE_QUEUE" }), { description: message`The message queue to use for background tasks.` }));
|
|
10
|
+
const debugOption = object("Global options", { debug: option("-d", "--debug", { description: message`Enable debug mode.` }) });
|
|
11
|
+
const initOptions = object("Initialization options", {
|
|
12
|
+
dir: optional(argument(path({ metavar: "DIR" }), { description: message`The project directory to initialize. If a specified directory does not exist, it will be created.` })),
|
|
13
|
+
webFramework,
|
|
14
|
+
packageManager,
|
|
15
|
+
kvStore,
|
|
16
|
+
messageQueue,
|
|
17
|
+
dryRun: option("--dry-run", { description: message`Perform a trial run with no changes made.` }),
|
|
18
|
+
debugOption
|
|
19
|
+
});
|
|
20
|
+
const initCommand = command("init", merge(initOptions, object({ command: constant("init") })), {
|
|
21
|
+
brief: message`Initialize a new Fedify project directory.`,
|
|
22
|
+
description: message`Initialize a new Fedify project directory.
|
|
23
|
+
|
|
24
|
+
By default, it initializes the current directory. You can specify a different directory as an argument.
|
|
25
|
+
|
|
26
|
+
Unless you specify all options (${optionNames(["-w", "--web-framework"])}, ${optionNames(["-p", "--package-manager"])}, ${optionNames(["-k", "--kv-store"])}, and ${optionNames(["-m", "--message-queue"])}), it will prompt you to select the options interactively.`
|
|
27
|
+
});
|
|
28
|
+
const noHydRun = object({ noHydRun: option("--no-hyd-run", { description: message`Log outputs without creating files.` }) });
|
|
29
|
+
const noDryRun = object({ noDryRun: option("--no-dry-run", { description: message`Test with files creations and installations.` }) });
|
|
30
|
+
const testInitCommand = command("test-init", merge(object("Initialization options", {
|
|
31
|
+
webFramework: multiple(webFramework),
|
|
32
|
+
packageManager: multiple(packageManager),
|
|
33
|
+
kvStore: multiple(kvStore),
|
|
34
|
+
messageQueue: multiple(messageQueue),
|
|
35
|
+
debugOption
|
|
36
|
+
}), optional(or(noHydRun, noDryRun))), {
|
|
37
|
+
brief: message`Test an initializing command .`,
|
|
38
|
+
description: message`Test an initializing command on temporary directories.
|
|
39
|
+
|
|
40
|
+
Unless you specify all options (${optionNames(["-w", "--web-framework"])}, ${optionNames(["-p", "--package-manager"])}, ${optionNames(["-k", "--kv-store"])}, and ${optionNames(["-m", "--message-queue"])}), it will test all combinations of the options.`
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { initCommand, initOptions, testInitCommand };
|
package/dist/const.d.mts
ADDED
package/dist/const.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/const.ts
|
|
2
|
+
const PACKAGE_MANAGER = [
|
|
3
|
+
"deno",
|
|
4
|
+
"pnpm",
|
|
5
|
+
"bun",
|
|
6
|
+
"yarn",
|
|
7
|
+
"npm"
|
|
8
|
+
];
|
|
9
|
+
const WEB_FRAMEWORK = [
|
|
10
|
+
"hono",
|
|
11
|
+
"nitro",
|
|
12
|
+
"next",
|
|
13
|
+
"elysia",
|
|
14
|
+
"express"
|
|
15
|
+
];
|
|
16
|
+
const MESSAGE_QUEUE = [
|
|
17
|
+
"denokv",
|
|
18
|
+
"redis",
|
|
19
|
+
"postgres",
|
|
20
|
+
"amqp"
|
|
21
|
+
];
|
|
22
|
+
const KV_STORE = [
|
|
23
|
+
"denokv",
|
|
24
|
+
"redis",
|
|
25
|
+
"postgres"
|
|
26
|
+
];
|
|
27
|
+
const DB_TO_CHECK = [
|
|
28
|
+
"redis",
|
|
29
|
+
"postgres",
|
|
30
|
+
"amqp"
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { DB_TO_CHECK, KV_STORE, MESSAGE_QUEUE, PACKAGE_MANAGER, WEB_FRAMEWORK };
|
package/dist/deno.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/json/biome.json
|
|
2
|
+
var biome_default = {
|
|
3
|
+
$schema: "https://biomejs.dev/schemas/1.8.3/schema.json",
|
|
4
|
+
organizeImports: { "enabled": true },
|
|
5
|
+
formatter: {
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"indentStyle": "space",
|
|
8
|
+
"indentWidth": 2
|
|
9
|
+
},
|
|
10
|
+
linter: { "enabled": false }
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { biome_default as default };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"redis": {
|
|
3
|
+
"name": "Redis",
|
|
4
|
+
"defaultPort": 6379,
|
|
5
|
+
"documentation": "https://redis.io/docs/latest/operate/oss_and_stack/install/archive/install-redis/"
|
|
6
|
+
},
|
|
7
|
+
"postgres": {
|
|
8
|
+
"name": "PostgreSQL",
|
|
9
|
+
"defaultPort": 5432,
|
|
10
|
+
"documentation": "https://www.postgresql.org/download/"
|
|
11
|
+
},
|
|
12
|
+
"amqp": {
|
|
13
|
+
"name": "RabbitMQ",
|
|
14
|
+
"defaultPort": 5672,
|
|
15
|
+
"documentation": "https://www.rabbitmq.com/docs/download"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/json/db-to-check.json
|
|
2
|
+
var db_to_check_default = {
|
|
3
|
+
redis: {
|
|
4
|
+
"name": "Redis",
|
|
5
|
+
"defaultPort": 6379,
|
|
6
|
+
"documentation": "https://redis.io/docs/latest/operate/oss_and_stack/install/archive/install-redis/"
|
|
7
|
+
},
|
|
8
|
+
postgres: {
|
|
9
|
+
"name": "PostgreSQL",
|
|
10
|
+
"defaultPort": 5432,
|
|
11
|
+
"documentation": "https://www.postgresql.org/download/"
|
|
12
|
+
},
|
|
13
|
+
amqp: {
|
|
14
|
+
"name": "RabbitMQ",
|
|
15
|
+
"defaultPort": 5672,
|
|
16
|
+
"documentation": "https://www.rabbitmq.com/docs/download"
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { db_to_check_default as default };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"redis": {
|
|
3
|
+
"label": "Redis",
|
|
4
|
+
"packageManagers": ["deno", "bun", "npm", "yarn", "pnpm"],
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"npm:ioredis": "^5.4.1"
|
|
7
|
+
},
|
|
8
|
+
"imports": {
|
|
9
|
+
"@fedify/redis": { "RedisKvStore": "RedisKvStore" },
|
|
10
|
+
"ioredis": { "Redis": "Redis" }
|
|
11
|
+
},
|
|
12
|
+
"object": "new RedisKvStore(new Redis(process.env.REDIS_URL))",
|
|
13
|
+
"env": {
|
|
14
|
+
"REDIS_URL": "redis://localhost:6379"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"postgres": {
|
|
18
|
+
"label": "PostgreSQL",
|
|
19
|
+
"packageManagers": ["deno", "bun", "npm", "yarn", "pnpm"],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"npm:postgres": "^3.4.5"
|
|
22
|
+
},
|
|
23
|
+
"imports": {
|
|
24
|
+
"@fedify/postgres": { "PostgresKvStore": "PostgresKvStore" },
|
|
25
|
+
"postgres": { "default": "postgres" }
|
|
26
|
+
},
|
|
27
|
+
"object": "new PostgresKvStore(postgres(process.env.POSTGRES_URL))",
|
|
28
|
+
"env": {
|
|
29
|
+
"POSTGRES_URL": "postgres://postgres@localhost:5432/postgres"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"denokv": {
|
|
33
|
+
"label": "Deno KV",
|
|
34
|
+
"packageManagers": ["deno"],
|
|
35
|
+
"imports": { "@fedify/denokv": { "DenoKvStore": "DenoKvStore" } },
|
|
36
|
+
"object": "new DenoKvStore(await Deno.openKv())",
|
|
37
|
+
"denoUnstable": ["kv"]
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/json/kv.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/json/kv.json
|
|
2
|
+
var kv_default = {
|
|
3
|
+
redis: {
|
|
4
|
+
"label": "Redis",
|
|
5
|
+
"packageManagers": [
|
|
6
|
+
"deno",
|
|
7
|
+
"bun",
|
|
8
|
+
"npm",
|
|
9
|
+
"yarn",
|
|
10
|
+
"pnpm"
|
|
11
|
+
],
|
|
12
|
+
"dependencies": { "npm:ioredis": "^5.4.1" },
|
|
13
|
+
"imports": {
|
|
14
|
+
"@fedify/redis": { "RedisKvStore": "RedisKvStore" },
|
|
15
|
+
"ioredis": { "Redis": "Redis" }
|
|
16
|
+
},
|
|
17
|
+
"object": "new RedisKvStore(new Redis(process.env.REDIS_URL))",
|
|
18
|
+
"env": { "REDIS_URL": "redis://localhost:6379" }
|
|
19
|
+
},
|
|
20
|
+
postgres: {
|
|
21
|
+
"label": "PostgreSQL",
|
|
22
|
+
"packageManagers": [
|
|
23
|
+
"deno",
|
|
24
|
+
"bun",
|
|
25
|
+
"npm",
|
|
26
|
+
"yarn",
|
|
27
|
+
"pnpm"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": { "npm:postgres": "^3.4.5" },
|
|
30
|
+
"imports": {
|
|
31
|
+
"@fedify/postgres": { "PostgresKvStore": "PostgresKvStore" },
|
|
32
|
+
"postgres": { "default": "postgres" }
|
|
33
|
+
},
|
|
34
|
+
"object": "new PostgresKvStore(postgres(process.env.POSTGRES_URL))",
|
|
35
|
+
"env": { "POSTGRES_URL": "postgres://postgres@localhost:5432/postgres" }
|
|
36
|
+
},
|
|
37
|
+
denokv: {
|
|
38
|
+
"label": "Deno KV",
|
|
39
|
+
"packageManagers": ["deno"],
|
|
40
|
+
"imports": { "@fedify/denokv": { "DenoKvStore": "DenoKvStore" } },
|
|
41
|
+
"object": "new DenoKvStore(await Deno.openKv())",
|
|
42
|
+
"denoUnstable": ["kv"]
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { kv_default as default };
|