Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ Version 2.0.6

To be released.

### @fedify/init

- Fixed `fedify init` crashing when `@fedify/cli` or `@fedify/init` is
executed through the JSR/Deno distribution. `import.meta.dirname` is
`undefined` for remote JSR modules, so the template loading and
repository-relative path logic has been made safe for published JSR
execution. [[#624], [#633]]

[#624]: https://github.com/fedify-dev/fedify/issues/624
[#633]: https://github.com/fedify-dev/fedify/pull/633

### @fedify/vocab-runtime

- Added `http://joinmastodon.org/ns` to preloaded JSON-LD contexts.
Expand Down
4 changes: 2 additions & 2 deletions packages/init/src/action/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import vscodeSettings from "../json/vscode-settings.json" with {
};
import type { InitCommandData } from "../types.ts";
import { merge } from "../utils.ts";
import { PACKAGES_PATH } from "./const.ts";
import { getPackagesPath } from "./const.ts";
import { getDependencies, getDevDependencies, joinDepsReg } from "./deps.ts";

/**
Expand Down Expand Up @@ -66,7 +66,7 @@ const getLinks = <
keys as (obj: object) => Iterable<string>,
filter((dep) => dep.includes("@fedify/")),
map((dep) => dep.replace("@fedify/", "")),
map((dep) => joinPath(PACKAGES_PATH, dep)),
map((dep) => joinPath(getPackagesPath(), dep)),
map((absolutePath) => realpathSync(absolutePath)),
map((realAbsolutePath) => relative(realpathSync(dir), realAbsolutePath)),
toArray,
Expand Down
13 changes: 7 additions & 6 deletions packages/init/src/action/const.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { join as joinPath } from "node:path";

export const PACKAGES_PATH = joinPath(
import.meta.dirname!, // action
"..", // src
"..", // init
"..", // packages
);
export const getPackagesPath = (): string =>
joinPath(
import.meta.dirname!, // action
"..", // src
"..", // init
"..", // packages
);
4 changes: 2 additions & 2 deletions packages/init/src/action/deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { join as joinPath } from "node:path";
import { merge, replace } from "../utils.ts";
import { PACKAGE_VERSION } from "../lib.ts";
import type { InitCommandData, PackageManager } from "../types.ts";
import { PACKAGES_PATH } from "./const.ts";
import { getPackagesPath } from "./const.ts";
import { isDeno } from "./utils.ts";

type Deps = Record<string, string>;
Expand Down Expand Up @@ -71,7 +71,7 @@ const convertFedifyToLocal = (name: string): string =>
pipe(
name,
replace("@fedify/", ""),
(pkg) => joinPath(PACKAGES_PATH, pkg),
(pkg) => joinPath(getPackagesPath(), pkg),
);

/** Gathers all devDependencies required for the project based on the
Expand Down
6 changes: 3 additions & 3 deletions packages/init/src/action/patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ export const recommendPatchFiles = (data: InitCommandData) =>
* @param data - The initialization command data
* @returns A record of file paths to their string content
*/
const getFiles = <
const getFiles = async <
T extends InitCommandData,
>(data: T) => ({
[data.initializer.federationFile]: loadFederation({
[data.initializer.federationFile]: await loadFederation({
imports: getImports(data),
...data,
}),
[data.initializer.loggingFile]: loadLogging(data),
[data.initializer.loggingFile]: await loadLogging(data),
".env": stringifyEnvs(data.env),
...data.initializer.files,
});
Expand Down
29 changes: 19 additions & 10 deletions packages/init/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,26 @@ export async function isPackageManagerAvailable(
return false;
}

export const readTemplate: (templatePath: string) => string = (
templatePath,
) =>
readFileSync(
joinPath(
import.meta.dirname!,
"templates",
...(templatePath + ".tpl").split("/"),
),
"utf8",
export const readTemplate = async (
templatePath: string,
): Promise<string> => {
const segments = (templatePath + ".tpl").split("/");
if (import.meta.dirname) {
return readFileSync(
joinPath(import.meta.dirname, "templates", ...segments),
"utf8",
);
}
const url = new URL(
["templates", ...segments].join("/"),
import.meta.url,
);
const resp = await fetch(url);
if (!resp.ok) {
throw new Error(`Failed to fetch template: ${url}`);
}
return resp.text();
};

export const getInstruction: (
packageManager: PackageManager,
Expand Down
2 changes: 1 addition & 1 deletion packages/init/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface WebFrameworkDescription {
defaultPort: number;
init(
data: InitCommandOptions & { projectName: string; testMode: boolean },
): WebFrameworkInitializer;
): WebFrameworkInitializer | Promise<WebFrameworkInitializer>;
}

export interface MessageQueueDescription {
Expand Down
55 changes: 32 additions & 23 deletions packages/init/src/webframeworks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const webFrameworks: WebFrameworks = {
hono: {
label: "Hono",
packageManagers: PACKAGE_MANAGER,
init: ({ projectName, packageManager: pm }) => ({
init: async ({ projectName, packageManager: pm }) => ({
dependencies: pm === "deno"
? {
...defaultDenoDependencies,
Expand Down Expand Up @@ -46,16 +46,17 @@ const webFrameworks: WebFrameworks = {
loggingFile: "src/logging.ts",
files: {
"src/app.tsx": pipe(
"hono/app.tsx",
readTemplate,
await readTemplate("hono/app.tsx"),
replace(/\/\* hono \*\//, pm === "deno" ? "@hono/hono" : "hono"),
replace(/\/\* logger \*\//, projectName),
),
"src/index.ts": readTemplate(
"src/index.ts": await readTemplate(
`hono/index/${packageManagerToRuntime(pm)}.ts`,
),
...(pm !== "deno"
? { "eslint.config.ts": readTemplate("defaults/eslint.config.ts") }
? {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}
: {}),
},
compilerOptions: pm === "deno" ? undefined : {
Expand Down Expand Up @@ -90,7 +91,7 @@ const webFrameworks: WebFrameworks = {
elysia: {
label: "ElysiaJS",
packageManagers: PACKAGE_MANAGER,
init: ({ projectName, packageManager: pm }) => ({
init: async ({ projectName, packageManager: pm }) => ({
dependencies: pm === "deno"
? {
...defaultDenoDependencies,
Expand Down Expand Up @@ -124,11 +125,13 @@ const webFrameworks: WebFrameworks = {
federationFile: "src/federation.ts",
loggingFile: "src/logging.ts",
files: {
"src/index.ts": readTemplate(
"src/index.ts": (await readTemplate(
`elysia/index/${packageManagerToRuntime(pm)}.ts`,
).replace(/\/\* logger \*\//, projectName),
)).replace(/\/\* logger \*\//, projectName),
...(pm !== "deno"
? { "eslint.config.ts": readTemplate("defaults/eslint.config.ts") }
? {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}
: {}),
},
compilerOptions: pm === "deno" || pm === "bun" ? undefined : {
Expand Down Expand Up @@ -164,7 +167,7 @@ const webFrameworks: WebFrameworks = {
express: {
label: "Express",
packageManagers: PACKAGE_MANAGER,
init: ({ projectName, packageManager: pm }) => ({
init: async ({ projectName, packageManager: pm }) => ({
dependencies: {
"npm:express": "^4.19.2",
"@fedify/express": PACKAGE_VERSION,
Expand All @@ -181,11 +184,13 @@ const webFrameworks: WebFrameworks = {
federationFile: "src/federation.ts",
loggingFile: "src/logging.ts",
files: {
"src/app.ts": readTemplate("express/app.ts")
"src/app.ts": (await readTemplate("express/app.ts"))
.replace(/\/\* logger \*\//, projectName),
"src/index.ts": readTemplate("express/index.ts"),
"src/index.ts": await readTemplate("express/index.ts"),
...(pm !== "deno"
? { "eslint.config.ts": readTemplate("defaults/eslint.config.ts") }
? {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}
: {}),
},
compilerOptions: pm === "deno" ? undefined : {
Expand Down Expand Up @@ -218,7 +223,7 @@ const webFrameworks: WebFrameworks = {
nitro: {
label: "Nitro",
packageManagers: PACKAGE_MANAGER,
init: ({ packageManager: pm, testMode }) => ({
init: async ({ packageManager: pm, testMode }) => ({
command: getNitroInitCommand(pm),
dependencies: {
"@fedify/h3": PACKAGE_VERSION,
Expand All @@ -228,16 +233,18 @@ const webFrameworks: WebFrameworks = {
federationFile: "server/federation.ts",
loggingFile: "server/logging.ts",
files: {
"server/middleware/federation.ts": readTemplate(
"server/middleware/federation.ts": await readTemplate(
"nitro/server/middleware/federation.ts",
),
"server/error.ts": readTemplate("nitro/server/error.ts"),
"nitro.config.ts": readTemplate("nitro/nitro.config.ts"),
"server/error.ts": await readTemplate("nitro/server/error.ts"),
"nitro.config.ts": await readTemplate("nitro/nitro.config.ts"),
...(
testMode ? { ".env": readTemplate("nitro/.env.test") } : {}
testMode ? { ".env": await readTemplate("nitro/.env.test") } : {}
),
...(pm !== "deno"
? { "eslint.config.ts": readTemplate("defaults/eslint.config.ts") }
? {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}
: {}),
},
tasks: {
Expand All @@ -250,7 +257,7 @@ const webFrameworks: WebFrameworks = {
next: {
label: "Next.js",
packageManagers: PACKAGE_MANAGER,
init: ({ packageManager: pm }) => ({
init: async ({ packageManager: pm }) => ({
label: "Next.js",
command: getNextInitCommand(pm),
dependencies: {
Expand All @@ -264,9 +271,11 @@ const webFrameworks: WebFrameworks = {
federationFile: "federation/index.ts",
loggingFile: "logging.ts",
files: {
"middleware.ts": readTemplate("next/middleware.ts"),
"middleware.ts": await readTemplate("next/middleware.ts"),
...(pm !== "deno"
? { "eslint.config.ts": readTemplate("defaults/eslint.config.ts") }
? {
"eslint.config.ts": await readTemplate("defaults/eslint.config.ts"),
}
: {}),
},
tasks: {
Expand All @@ -276,7 +285,7 @@ const webFrameworks: WebFrameworks = {
}),
defaultPort: 3000,
},
} as const;
};
export default webFrameworks;

const defaultDevDependencies = {
Expand Down
Loading