From e4d89041bb64be2989abd7ca777cf1ba8576caff Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Sun, 3 Sep 2023 01:04:41 +0900 Subject: [PATCH 1/9] Add: getUrlAddress --- src/lib/getUrlAddress.test.ts | 43 +++++++++++++++++++++++++++++++++++ src/lib/getUrlAddress.ts | 10 ++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/lib/getUrlAddress.test.ts create mode 100644 src/lib/getUrlAddress.ts diff --git a/src/lib/getUrlAddress.test.ts b/src/lib/getUrlAddress.test.ts new file mode 100644 index 0000000..1b3af97 --- /dev/null +++ b/src/lib/getUrlAddress.test.ts @@ -0,0 +1,43 @@ +import { AddressInfo } from "net"; +import { getUrlAddress } from "./getUrlAddress"; + + +describe("getUrlAddress", () => { + describe("when null is passed", () => { + it("returns null", () => { + const url = getUrlAddress(null); + expect(url).toBeNull(); + }); + }); + + describe("when string is passed", () => { + it("returns null", () => { + const url = getUrlAddress("foobar"); + expect(url).toBeNull(); + }); + }); + + describe("when IPv4 is passed", () => { + it("returns correct url", () => { + const address: AddressInfo = { + address: "0.0.0.0", + family: "IPv4", + port: 8888, + } + const url = getUrlAddress(address); + expect(url).toEqual(`http://${address.address}:${address.port}`); + }); + }); + + describe("when IPv6 is passed", () => { + it("returns correct url", () => { + const address: AddressInfo = { + address: "::", + family: "IPv6", + port: 8888, + } + const url = getUrlAddress(address); + expect(url).toEqual(`http://[${address.address}]:${address.port}`); + }); + }); +}); \ No newline at end of file diff --git a/src/lib/getUrlAddress.ts b/src/lib/getUrlAddress.ts new file mode 100644 index 0000000..6d4fd57 --- /dev/null +++ b/src/lib/getUrlAddress.ts @@ -0,0 +1,10 @@ +import { AddressInfo } from "net"; + + +export const getUrlAddress = (address: string | AddressInfo | null) => { + if (!address || typeof address === "string") return null; + + if (["IPv4", "IPv6"].indexOf(address.family) === -1) throw new Error("Unknown address family"); + + return `http://${address.family === "IPv4" ? address.address : `[${address.address}]`}:${address.port}`; +} \ No newline at end of file From 790e4c38e56d498254f5e65a914eb25213cd7c7d Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Sun, 3 Sep 2023 01:07:50 +0900 Subject: [PATCH 2/9] Update: Address --- src/commands/preview.ts | 7 +++++-- src/server/app.ts | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/commands/preview.ts b/src/commands/preview.ts index 14ab2c0..a85868e 100644 --- a/src/commands/preview.ts +++ b/src/commands/preview.ts @@ -1,6 +1,7 @@ import { config } from "../lib/config"; import { getFileSystemRepo } from "../lib/get-file-system-repo"; import { getQiitaApiInstance } from "../lib/get-qiita-api-instance"; +import { getUrlAddress } from "../lib/getUrlAddress"; import { syncArticlesFromQiita } from "../lib/sync-articles-from-qiita"; import { startLocalChangeWatcher, startServer } from "../server/app"; @@ -13,9 +14,11 @@ export const preview = async () => { const server = await startServer(); const address = server.address(); - if (address && typeof address !== "string") { + const url = getUrlAddress(address); + + if (url) { const open = (await import("open")).default; - await open(`http://localhost:${address.port}`); + await open(url); } startLocalChangeWatcher({ diff --git a/src/server/app.ts b/src/server/app.ts index 9f2de35..869894f 100644 --- a/src/server/app.ts +++ b/src/server/app.ts @@ -10,6 +10,7 @@ import { EmojiRouter } from "./api/emoji"; import { ItemsRouter } from "./api/items"; import { ReadmeRouter } from "./api/readme"; import { config } from "../lib/config"; +import { getUrlAddress } from "../lib/getUrlAddress"; export async function startServer() { const app = express(); @@ -39,7 +40,11 @@ export async function startServer() { server .listen(port, host) .once("listening", () => { - console.log(`Preview: http://${host}:${port}`); + const address = server.address(); + const url = getUrlAddress(address); + if (url) { + console.log(`Preview: ${url}`) + } resolve(server); }) From 56451df6c60e06a959f6c22e1f7c83394fcfd0a3 Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Sun, 3 Sep 2023 01:15:05 +0900 Subject: [PATCH 3/9] Add: docker-file --- src/commands/init.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/commands/init.ts b/src/commands/init.ts index 1137770..5f6b339 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -45,6 +45,31 @@ const gitignoreFileContent = `.remote node_modules `; +const dockerfilePath = path.join(rootDir, "Dockerfile"); +const dockerfileContent = `FROM node:20-alpine3.17 + +WORKDIR /qiita + +EXPOSE 8888 +`; + +const dockerComposeFilePath = path.join(rootDir, "docker-compose.yml"); +const dockerComposeFileContent = `version: "3" +services: + qiita: + container_name: qiita + build: + context: . + dockerfile: ./Dockerfile + ports: + - 8888:8888 + tty: true + volumes: + - ./:/qiita + environment: + TZ: Asia/Tokyo +`; + export const init = async () => { console.log("設定ファイルを生成します。\n"); @@ -54,6 +79,10 @@ export const init = async () => { writeFile(publishWorkflowFilePath, publishWorkflowFileContent); writeFile(gitignoreFilePath, gitignoreFileContent); + //docker + writeFile(dockerfilePath, dockerfileContent); + writeFile(dockerComposeFilePath, dockerComposeFileContent); + const userConfigFilePath = config.getUserConfigFilePath(); const userConfigDir = config.getUserConfigDir(); if (!fs.existsSync(userConfigFilePath)) { From 79283e65f0be65b2ddbfc217166943f48487db40 Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Sun, 3 Sep 2023 01:18:42 +0900 Subject: [PATCH 4/9] Update: config --- src/lib/config.test.ts | 8 +++++++- src/lib/config.ts | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/config.test.ts b/src/lib/config.test.ts index dbc5443..3ccbb1b 100644 --- a/src/lib/config.test.ts +++ b/src/lib/config.test.ts @@ -55,7 +55,7 @@ jest.mock("node:fs/promises", () => { writeFile: jest.fn((filePath: string, text: string) => { setFile(filePath, text); }), - mkdir: jest.fn(() => {}), + mkdir: jest.fn(() => { }), }; }); jest.mock("node:fs", () => { @@ -224,6 +224,8 @@ describe("config", () => { beforeEach(() => { const userConfigData = { includePrivate: true, + address: "localhost", + family: "IPv4", port: 9999, }; resetFiles(); @@ -234,6 +236,8 @@ describe("config", () => { const userConfig = await config.getUserConfig(); expect(userConfig).toStrictEqual({ includePrivate: true, + address: "localhost", + family: "IPv4", port: 9999, }); }); @@ -248,6 +252,8 @@ describe("config", () => { const userConfig = await config.getUserConfig(); expect(userConfig).toStrictEqual({ includePrivate: false, + address: "localhost", + family: "IPv4", port: 8888, }); }); diff --git a/src/lib/config.ts b/src/lib/config.ts index a6ba2cf..e0872e4 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -14,6 +14,8 @@ interface Options { type UserConfig = { includePrivate: boolean; + address: string; + family: string; port: number; }; @@ -107,6 +109,8 @@ class Config { async getUserConfig() { const defaultConfig = { includePrivate: false, + address: "localhost", + family: "IPv4", port: 8888, } as UserConfig; From 5f94b3b223fcc697408354201254baebafcf105a Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Sun, 3 Sep 2023 01:45:45 +0900 Subject: [PATCH 5/9] Update: Readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index e24c83c..9521126 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Qiita の Markdown 記法については[Markdown 記法 チートシート](htt Qiita CLI を使うには `Node.js 18.0.0` 以上が必要です。Node.js をはじめて使う場合はインストールする必要があります。 +>`Docker`で利用するには`Docker`がインストールされている必要があります。 + ### 2. Qiita CLI をインストールする Qiita のコンテンツを管理したいディレクトリで、以下のコマンドを実行します。 @@ -30,6 +32,12 @@ Qiita のコンテンツを管理したいディレクトリで、以下のコ npm install @qiita/qiita-cli --save-dev ``` +>`Docker`で環境を構築する場合は次のコマンドで実行できます。 +> +>```console +>docker run --rm -v $(pwd):/opt -w /opt node:20-alpine3.17 sh -c "npm install @qiita/qiita-cli --save-dev && npx qiita init" +>``` + 以下のコマンドでバージョンが表示されればインストール完了です。 ```console @@ -51,6 +59,8 @@ npm install @qiita/qiita-cli@latest 以下のコマンドを実行することで、 - .gitignore +- Dockerfile +- docker-compose.yml - GitHub Actions のワークフローファイル - 「GitHub で記事を管理する」の項目を参照 - ユーザー設定ファイル(qiita.config.json) @@ -58,6 +68,12 @@ npm install @qiita/qiita-cli@latest が生成されます。 +>`Docker`で環境を構築する場合はコンテナを起動してから実行してください。 +> +>```console +>docker-compose up -d && docker-compose exec qiita sh +>``` + ```console npx qiita init ``` From c9392c65d5392de56407de436ca812b397ba3601 Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Mon, 4 Sep 2023 22:11:39 +0900 Subject: [PATCH 6/9] Fix: prettier --- README.md | 18 +++++++++--------- src/lib/config.test.ts | 2 +- src/lib/getUrlAddress.test.ts | 7 +++---- src/lib/getUrlAddress.ts | 10 ++++++---- src/server/app.ts | 2 +- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9521126..f4d7bdf 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Qiita の Markdown 記法については[Markdown 記法 チートシート](htt Qiita CLI を使うには `Node.js 18.0.0` 以上が必要です。Node.js をはじめて使う場合はインストールする必要があります。 ->`Docker`で利用するには`Docker`がインストールされている必要があります。 +> `Docker`で利用するには`Docker`がインストールされている必要があります。 ### 2. Qiita CLI をインストールする @@ -32,11 +32,11 @@ Qiita のコンテンツを管理したいディレクトリで、以下のコ npm install @qiita/qiita-cli --save-dev ``` ->`Docker`で環境を構築する場合は次のコマンドで実行できます。 +> `Docker`で環境を構築する場合は次のコマンドで実行できます。 > ->```console ->docker run --rm -v $(pwd):/opt -w /opt node:20-alpine3.17 sh -c "npm install @qiita/qiita-cli --save-dev && npx qiita init" ->``` +> ```console +> docker run --rm -v $(pwd):/opt -w /opt node:20-alpine3.17 sh -c "npm install @qiita/qiita-cli --save-dev && npx qiita init" +> ``` 以下のコマンドでバージョンが表示されればインストール完了です。 @@ -68,11 +68,11 @@ npm install @qiita/qiita-cli@latest が生成されます。 ->`Docker`で環境を構築する場合はコンテナを起動してから実行してください。 +> `Docker`で環境を構築する場合はコンテナを起動してから実行してください。 > ->```console ->docker-compose up -d && docker-compose exec qiita sh ->``` +> ```console +> docker-compose up -d && docker-compose exec qiita sh +> ``` ```console npx qiita init diff --git a/src/lib/config.test.ts b/src/lib/config.test.ts index 3ccbb1b..280d6a5 100644 --- a/src/lib/config.test.ts +++ b/src/lib/config.test.ts @@ -55,7 +55,7 @@ jest.mock("node:fs/promises", () => { writeFile: jest.fn((filePath: string, text: string) => { setFile(filePath, text); }), - mkdir: jest.fn(() => { }), + mkdir: jest.fn(() => {}), }; }); jest.mock("node:fs", () => { diff --git a/src/lib/getUrlAddress.test.ts b/src/lib/getUrlAddress.test.ts index 1b3af97..1a569dd 100644 --- a/src/lib/getUrlAddress.test.ts +++ b/src/lib/getUrlAddress.test.ts @@ -1,7 +1,6 @@ import { AddressInfo } from "net"; import { getUrlAddress } from "./getUrlAddress"; - describe("getUrlAddress", () => { describe("when null is passed", () => { it("returns null", () => { @@ -23,7 +22,7 @@ describe("getUrlAddress", () => { address: "0.0.0.0", family: "IPv4", port: 8888, - } + }; const url = getUrlAddress(address); expect(url).toEqual(`http://${address.address}:${address.port}`); }); @@ -35,9 +34,9 @@ describe("getUrlAddress", () => { address: "::", family: "IPv6", port: 8888, - } + }; const url = getUrlAddress(address); expect(url).toEqual(`http://[${address.address}]:${address.port}`); }); }); -}); \ No newline at end of file +}); diff --git a/src/lib/getUrlAddress.ts b/src/lib/getUrlAddress.ts index 6d4fd57..f56442e 100644 --- a/src/lib/getUrlAddress.ts +++ b/src/lib/getUrlAddress.ts @@ -1,10 +1,12 @@ import { AddressInfo } from "net"; - export const getUrlAddress = (address: string | AddressInfo | null) => { if (!address || typeof address === "string") return null; - if (["IPv4", "IPv6"].indexOf(address.family) === -1) throw new Error("Unknown address family"); + if (["IPv4", "IPv6"].indexOf(address.family) === -1) + throw new Error("Unknown address family"); - return `http://${address.family === "IPv4" ? address.address : `[${address.address}]`}:${address.port}`; -} \ No newline at end of file + return `http://${ + address.family === "IPv4" ? address.address : `[${address.address}]` + }:${address.port}`; +}; diff --git a/src/server/app.ts b/src/server/app.ts index 869894f..0a3e094 100644 --- a/src/server/app.ts +++ b/src/server/app.ts @@ -43,7 +43,7 @@ export async function startServer() { const address = server.address(); const url = getUrlAddress(address); if (url) { - console.log(`Preview: ${url}`) + console.log(`Preview: ${url}`); } resolve(server); From f3bc0101cdd924ac278ed6dfe68713e82109d2ca Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Tue, 5 Sep 2023 12:41:13 +0900 Subject: [PATCH 7/9] Remove: about docker --- README.md | 16 ---------------- src/commands/init.ts | 29 ----------------------------- 2 files changed, 45 deletions(-) diff --git a/README.md b/README.md index f4d7bdf..e24c83c 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,6 @@ Qiita の Markdown 記法については[Markdown 記法 チートシート](htt Qiita CLI を使うには `Node.js 18.0.0` 以上が必要です。Node.js をはじめて使う場合はインストールする必要があります。 -> `Docker`で利用するには`Docker`がインストールされている必要があります。 - ### 2. Qiita CLI をインストールする Qiita のコンテンツを管理したいディレクトリで、以下のコマンドを実行します。 @@ -32,12 +30,6 @@ Qiita のコンテンツを管理したいディレクトリで、以下のコ npm install @qiita/qiita-cli --save-dev ``` -> `Docker`で環境を構築する場合は次のコマンドで実行できます。 -> -> ```console -> docker run --rm -v $(pwd):/opt -w /opt node:20-alpine3.17 sh -c "npm install @qiita/qiita-cli --save-dev && npx qiita init" -> ``` - 以下のコマンドでバージョンが表示されればインストール完了です。 ```console @@ -59,8 +51,6 @@ npm install @qiita/qiita-cli@latest 以下のコマンドを実行することで、 - .gitignore -- Dockerfile -- docker-compose.yml - GitHub Actions のワークフローファイル - 「GitHub で記事を管理する」の項目を参照 - ユーザー設定ファイル(qiita.config.json) @@ -68,12 +58,6 @@ npm install @qiita/qiita-cli@latest が生成されます。 -> `Docker`で環境を構築する場合はコンテナを起動してから実行してください。 -> -> ```console -> docker-compose up -d && docker-compose exec qiita sh -> ``` - ```console npx qiita init ``` diff --git a/src/commands/init.ts b/src/commands/init.ts index 5f6b339..1137770 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -45,31 +45,6 @@ const gitignoreFileContent = `.remote node_modules `; -const dockerfilePath = path.join(rootDir, "Dockerfile"); -const dockerfileContent = `FROM node:20-alpine3.17 - -WORKDIR /qiita - -EXPOSE 8888 -`; - -const dockerComposeFilePath = path.join(rootDir, "docker-compose.yml"); -const dockerComposeFileContent = `version: "3" -services: - qiita: - container_name: qiita - build: - context: . - dockerfile: ./Dockerfile - ports: - - 8888:8888 - tty: true - volumes: - - ./:/qiita - environment: - TZ: Asia/Tokyo -`; - export const init = async () => { console.log("設定ファイルを生成します。\n"); @@ -79,10 +54,6 @@ export const init = async () => { writeFile(publishWorkflowFilePath, publishWorkflowFileContent); writeFile(gitignoreFilePath, gitignoreFileContent); - //docker - writeFile(dockerfilePath, dockerfileContent); - writeFile(dockerComposeFilePath, dockerComposeFileContent); - const userConfigFilePath = config.getUserConfigFilePath(); const userConfigDir = config.getUserConfigDir(); if (!fs.existsSync(userConfigFilePath)) { From d74b3aec3271d9d14e8ff3161852fb4740846ffc Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Tue, 5 Sep 2023 18:20:56 +0900 Subject: [PATCH 8/9] change from `address` to `host` --- src/lib/config.test.ts | 9 +++------ src/lib/config.ts | 6 ++---- src/server/app.ts | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/lib/config.test.ts b/src/lib/config.test.ts index 280d6a5..81ac679 100644 --- a/src/lib/config.test.ts +++ b/src/lib/config.test.ts @@ -224,8 +224,7 @@ describe("config", () => { beforeEach(() => { const userConfigData = { includePrivate: true, - address: "localhost", - family: "IPv4", + host: "localhost", port: 9999, }; resetFiles(); @@ -236,8 +235,7 @@ describe("config", () => { const userConfig = await config.getUserConfig(); expect(userConfig).toStrictEqual({ includePrivate: true, - address: "localhost", - family: "IPv4", + host: "localhost", port: 9999, }); }); @@ -252,8 +250,7 @@ describe("config", () => { const userConfig = await config.getUserConfig(); expect(userConfig).toStrictEqual({ includePrivate: false, - address: "localhost", - family: "IPv4", + host: "localhost", port: 8888, }); }); diff --git a/src/lib/config.ts b/src/lib/config.ts index e0872e4..873b99b 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -14,8 +14,7 @@ interface Options { type UserConfig = { includePrivate: boolean; - address: string; - family: string; + host: string; port: number; }; @@ -109,8 +108,7 @@ class Config { async getUserConfig() { const defaultConfig = { includePrivate: false, - address: "localhost", - family: "IPv4", + host: "localhost", port: 8888, } as UserConfig; diff --git a/src/server/app.ts b/src/server/app.ts index 0a3e094..5b9168e 100644 --- a/src/server/app.ts +++ b/src/server/app.ts @@ -34,7 +34,7 @@ export async function startServer() { const server = createServer(app); const userConfig = await config.getUserConfig(); const port = userConfig.port; - const host = "localhost"; + const host = userConfig.host; return new Promise((resolve, reject) => { server From 13bb561e0f447f05a03fde2170ed27a403a942b0 Mon Sep 17 00:00:00 2001 From: ikepu-tp Date: Tue, 5 Sep 2023 18:23:59 +0900 Subject: [PATCH 9/9] Add: description of `host` on Readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e24c83c..56b56ee 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,7 @@ npx qiita version 設定できるオプションは以下の通りです。 - includePrivate: 限定共有記事を含めるかどうかを選べます。デフォルトは`false`です。 +- host: `qiita preview`コマンドで利用するホストを指定できます。デフォルトは`localhost`です。 - port: `qiita preview`コマンドで利用するポートを指定できます。デフォルトは`8888`です。 ## オプション