Skip to content

Use memfs other#1586

Merged
ShinobuTakahashi merged 17 commits intouse-memfs-for-commonsfrom
use-memfs-other
Feb 4, 2026
Merged

Use memfs other#1586
ShinobuTakahashi merged 17 commits intouse-memfs-for-commonsfrom
use-memfs-other

Conversation

@ShinobuTakahashi
Copy link
Copy Markdown
Contributor

@ShinobuTakahashi ShinobuTakahashi commented Aug 20, 2025

概要

#1561 の browserify -> rollup 変更に伴うテスト周りの修正。

  • commons 以外の mock-fs を memfs へ変更。
  • memfs で対応できない箇所は、実ファイルでテストを実施。

備考
#1576 へマージします。この PR で CI が通る事を確認。
ローカルでテスト後に実ファイルが残らない事を確認。

export function prepareFsContent(def: FsContentDefinition, baseDir: string): PrepareFsContentResult {
const dir = fs.mkdtempSync(baseDir);
export function prepareFsContent(def: FsContentDefinition, baseDir: string, useDirPath?: string): PrepareFsContentResult {
const dir = useDirPath ? useDirPath : fs.mkdtempSync(baseDir);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

テストで同ディレクトリに対しファイルの追加があるため、引数 useDirPath があった場合にはそのディレクトリパスを使用するようにしました。

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

うーん、第二第三引数はほとんど意味が重複しているのは抵抗があります。mkdtemp() を呼び出し元の責任にしませんか。

通常:

prepareFsContent(def, fs.mkdtempSync(baseDir));

今回必要なパス:

prepareFsContent(def, path.join(fixtureContents.path, "somedir", "node_modules"));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。mkdtemp() を呼び出し元の責務にするよう修正しました。

Comment on lines -118 to +126
.then(() => promiseInstall({ moduleNames: ["dummy2@1.0.1"], cwd: "./somedir", plugin: 12, logger: logger, debugNpm: dummyNpm }))
.then(() => cmn.FileSystem.readJSON<cmn.GameConfiguration>("./somedir/game.json"))
.then(() => promiseInstall({ moduleNames: ["dummy2"], cwd: somedir, plugin: 12, logger: logger, debugNpm: dummyNpm }))
.then(() => cmn.FileSystem.readJSON<cmn.GameConfiguration>(path.join(somedir, "game.json")))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

モジュール名の "@x.x.x" は rollup で解決できないため削除

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

バージョンを指定しての akashic install ができなくなるということでしょうか?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moduleName@x.x.x で install できるよう修正しました。

const moduleMainScripts = NodeModules.listModuleMainScripts(packageJsonFiles);

// CI の windows 用にファイルパスを unix 形式に変換して比較
for(const [key, value] of Object.entries(moduleMainScripts)) moduleMainScripts[key] = toUnixPath(value);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

listModuleMainScripts() の戻り値 (game.json にそのまま書く) は常に unix path ではないかと思いますが、この処理必要でしょうか?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

仰る通りです。この処理削除しました。

const moduleMainPaths = NodeModules.listModuleMainPaths(packageJsonFiles);

// CI の windows 用にファイルパスを unix 形式に変換して比較
for(const [key, value] of Object.entries(moduleMainPaths)) moduleMainPaths[key] = toUnixPath(value);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここも。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらも削除しました

export function prepareFsContent(def: FsContentDefinition, baseDir: string): PrepareFsContentResult {
const dir = fs.mkdtempSync(baseDir);
export function prepareFsContent(def: FsContentDefinition, baseDir: string, useDirPath?: string): PrepareFsContentResult {
const dir = useDirPath ? useDirPath : fs.mkdtempSync(baseDir);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

うーん、第二第三引数はほとんど意味が重複しているのは抵抗があります。mkdtemp() を呼び出し元の責任にしませんか。

通常:

prepareFsContent(def, fs.mkdtempSync(baseDir));

今回必要なパス:

prepareFsContent(def, path.join(fixtureContents.path, "somedir", "node_modules"));

Comment on lines +56 to +57
const mockFsContent = {
"source": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

インデントと空白見直したいです。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。修正しました。

Comment on lines +407 to +408
const rmPath = path.join(fixtureContents.path, "testdir", "foo", "node_modules", name);
fs.rmSync(rmPath, {recursive: true});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DummyNpm は実ファイルを触らずに npm の動作を模擬するものだったように見えるのですが、ここで実ファイルを削除する必要があるんでしょうか。(だとするとこれまでなぜ動いていたのか不思議なような?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

仰る通り、ここで実ファイルを削除せずとも問題ありませんでした。修正しました。

Comment on lines -118 to +126
.then(() => promiseInstall({ moduleNames: ["dummy2@1.0.1"], cwd: "./somedir", plugin: 12, logger: logger, debugNpm: dummyNpm }))
.then(() => cmn.FileSystem.readJSON<cmn.GameConfiguration>("./somedir/game.json"))
.then(() => promiseInstall({ moduleNames: ["dummy2"], cwd: somedir, plugin: 12, logger: logger, debugNpm: dummyNpm }))
.then(() => cmn.FileSystem.readJSON<cmn.GameConfiguration>(path.join(somedir, "game.json")))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

バージョンを指定しての akashic install ができなくなるということでしょうか?

Comment on lines +107 to +110
.then(async () => {
const ret = await cmn.FileSystem.readJSON<cmn.GameConfiguration>(path.join(somedir, "game.json"))
return ret;
})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promise 返すだけなので async も await も変数もいらなくてこれでいいような?

.then(() => cmn.FileSystem.readJSON<cmn.GameConfiguration>(path.join(somedir, "game.json")))

Copy link
Copy Markdown
Contributor Author

@ShinobuTakahashi ShinobuTakahashi Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

デバッグ時に確認のため修正したままでした。await 等削除し戻しました。

import { readJSON, writeJSON } from "@akashic/akashic-cli-commons/lib/FileSystem.js";

vi.mock("node:fs", async () => {
const memfs: { fs: typeof fs } = await vi.importActual("memfs")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

行末の ; が抜けていそうです。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。修正しました。

import { Util } from "..";
import * as testUtil from "./helpers/TestUtil.js";

const toUnixPath = (p: string) => p.replace(/^\//, "").replace(/\\/g, "/");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 文字目の "/" を削るのは toUnixPath() という名前にそぐわないので、 toGameJsonPath() とかにしておくのはどうでしょう。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。toGameJsonPath() へ修正しました。

Comment on lines +200 to +203
expect(content.moduleMainScripts).toEqual({
"dummy": "node_modules/dummy/index2.js",
"dummyChild": "node_modules/dummy/node_modules/dummyChild/main.js"
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この辺り期待動作が変化しているのはなぜでしょう?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントアウトした箇所の影響で、dummy モジュールは初回インストールした内容のため修正しました。

expect(globalScripts.indexOf("node_modules/dummy/foo.js")).toBe(-1);
expect(globalScripts.indexOf("node_modules/dummy/node_modules/dummyChild/main.js")).toBe(-1);
expect(globalScripts.indexOf("node_modules/dummy/index2.js")).not.toBe(-1);
expect(globalScripts.indexOf("node_modules/dummy/sub2.js")).not.toBe(-1);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このあたりもばっさり削られていますが、そうすると上の // dummyモジュールの定義を書き換えて反映されるか確認する の部分の意味がなくなっていませんか。もしこのあたりをテストする意味がないなら書き換え部分も削除されるべきに思えます。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

別途ご相談させてきただき、rollup で変更したpackage.json が認識できないため、このブロックをコメントアウトとしました。

Copy link
Copy Markdown
Member

@xnv xnv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントつけていますが approved.

})
/*
// Rollup は一度読み込んだ package.json が変更された場合、packag.json の main フィールドが変わっても検知できない。
// そのため、下記の dummy モジュールの中身が変更されて反映できているかのブロックをコメントアウトとする。
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

厳密には --watch 中に node_modules 以下の package.json 書き換えを検知できなくなっているので、デグレである。ただ回避手段が見当たらないこと、現実的にほぼないユースケースであるため妥協する という点も書いておきたいです。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。コメント追加しました。

@ShinobuTakahashi ShinobuTakahashi merged commit 0b0002c into use-memfs-for-commons Feb 4, 2026
@ShinobuTakahashi ShinobuTakahashi deleted the use-memfs-other branch February 4, 2026 07:55
This was referenced Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants