ノードヘルプ

eventemitter2 NPM (開発者のための仕組み)

公開済み 2024年10月24日
共有:

イントロダクション

今日のペースの速い開発環境では、応答性が高く、複雑なワークフローを効率的に管理できるアプリケーションを作成することが不可欠です。 そのためには、効果的な文書管理システムとイベント駆動型アーキテクチャが不可欠です。 強力なツールであるEventEmitter2とIronPDFを組み合わせることで、開発者は高度なPDF操作機能を備えたダイナミックなイベントドリブンアプリを構築することができます。

通常の EventEmitter クラスの機能は、Node.js 用の拡張イベント・エミッター・ライブラリである EventEmitter2 によって拡張され、複数のリスナー、イベント・ネームスペース、ワイルドカード、正規表現イベントなどの機能が追加されています。 これらの改善により、複雑なイベントドリブンワークフローがよりシンプルになり、アプリケーションが幅広い非同期タスクを簡単に実行できることを保証します。

この記事ではNode.jsアプリケーションでEventEmitter2とIronPDFを統合する方法を見ていきます。 両方のツールのインストールとセットアップ方法、イベントの処理方法とダイナミックPDFの作成方法の例を説明し、高度な使用例と推奨されるプラクティスについて話します。 この記事を読めば、PDFを簡単に処理できる複雑なイベント駆動型システムを構築するために、これらの強力な技術をどのように使うかについて、しっかりと把握できるはずです。

EventEmitter2 NPMとは何ですか?

でネイティブのEventEmitterクラスの機能を拡張します。イベントエミッター2Node.jsのための強力なイベント処理モジュール。 複雑なイベント駆動構造をより効果的に処理するために、多くの強力な機能を提供しています。 ワイルドカードイベントと正規表現イベントは、パターンに基づくより柔軟なイベントトリガーと、名前空間を使用した多数の関連イベントのグループ化と処理を可能にする2つの重要な機能です。 同じイベントによってプロンプトされる異なるアクションを処理するリスナーの優先順位付けは、1つのイベントに対して複数のリスナーを持つEventEmitter2の機能によって可能になります。

eventemitter2 NPM(開発者向けの仕組み):図1 - EventEmitter2

また、イベントの整理と分類に役立つイベント名前空間を提供し、複雑なシステム管理とデバッグを容易にします。 Node.jsアプリケーションでノンブロッキング・アクションを管理するために不可欠な非同期リスナーは、イベント・エミッター・メソッド・ライブラリでもサポートされています。 これらの特徴から、EventEmitter2は、信頼性の高いイベント管理を必要とする大規模なオンラインアプリケーション、ゲーム、リアルタイムシステムにとって特に有益です。 通常のEventEmitterクラスの拡張であるEventEmitter2は、プログラマに、よりスケーラブルで保守性の高いコードを書くための強力な機能を提供します。

Node.jsの組み込みEventEmitterクラスは、堅牢なイベント処理パッケージEventEmitter2で強化されています。以下は、EventEmitter2 を際立たせる主な特徴です:

ワイルドカードイベント

イベントを指定したワイルドカードパターンの使用を許可し、関連する複数のイベントを処理し、グループ化します。 これは、より階層的で構造化されたイベント管理に役立ちます。

正規表現イベント

正規表現パターンに従ってイベントをトリガーできるようにし、イベント管理に柔軟性を持たせました。

複数のリスナー

1つのイベントに複数のリスナーをアタッチできます。 各リスナーに優先順位を持たせることで、記述されたイベントの上でリスナーが実行される順序をより正確に制御することができます。

イベントの名前空間

イベントの整理と分類のための名前空間の使用を容易にすることで、複雑なシステムの管理とデバッグを簡素化します。

非同期リスナー

非同期イベントリスナーをサポートすることで、高性能アプリケーションに不可欠なノンブロッキングアクションを可能にします。

リスナーの操作

リスナーを追加、削除、管理する効果的な方法を提供します。

イベント放出制御

イベントのリスナー数を制御し、イベントがリッスンされる回数を制限できるようにすることで、長いプログラムのメモリリークを防ぎます。

イベントバブリング

ウェブブラウザのDOMでイベントがバブル化するのと同じように、イベントのバブリングをサポートすることで、イベントが階層上に広がることを可能にします。

パフォーマンス最適化

パフォーマンスに最適化されているため、迅速かつ効果的なイベント処理が必要な、トラフィックの多いアプリケーションに適しています。

冗長なメモリリーク警告

1つのイベントに多くのリスナーが追加された場合、メモリリークの可能性を警告することで、開発者がアプリケーションを健全に保つことができます。

EventEmitter2 Node.js の作成と設定

Node.jsアプリケーションでEventEmitter2を作成し設定するのは簡単です。 EventEmitter2の設定と使用に関する詳細なチュートリアルです。

EventEmitter2をインストールする

npmを使用してEventEmitter2パッケージをインストールすることが最初のステップです。開いているターミナルを使って、以下のコマンドを入力する:

npm install eventemitter2
npm install eventemitter2
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'npm install eventemitter2
VB   C#

EventEmitter2のインポートと設定

その後、あなたのNode.jsプログラムにEventEmitter2をインポートし、あなたの要求に合うように修正してください。 これは、単純なイベント・エミッターの2つの設定の例です:

const EventEmitter2 = require('eventemitter2').EventEmitter2;
const eventEmitter = new EventEmitter2({
  wildcard: true,         // Allows use of wildcards.
  delimiter: '.',         // The delimiter used to segment namespaces.
  newListener: false,     // If true, the `newListener` event is emitted when new listeners are added.
  maxListeners: 20,       // Maximum number of listeners per event.
  verboseMemoryLeak: true // Show warnings if potential memory leaks are detected.
});
// Example: Define a listener for a wildcard event.
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
});
const EventEmitter2 = require('eventemitter2').EventEmitter2;
const eventEmitter = new EventEmitter2({
  wildcard: true,         // Allows use of wildcards.
  delimiter: '.',         // The delimiter used to segment namespaces.
  newListener: false,     // If true, the `newListener` event is emitted when new listeners are added.
  maxListeners: 20,       // Maximum number of listeners per event.
  verboseMemoryLeak: true // Show warnings if potential memory leaks are detected.
});
// Example: Define a listener for a wildcard event.
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
});
const EventEmitter2 = require( 'eventemitter2').EventEmitter2;
const eventEmitter = New EventEmitter2({
	wildcard:= True,
	delimiter:= "."c,
	newListener:= False,
	maxListeners:= 20,
	verboseMemoryLeak:= True
})
' Example: Define a listener for a wildcard event.
eventEmitter.on( 'user.*', (data) =>
If True Then
	console.log( 'User event:', data);
End If
)
VB   C#

イベント

イベント・エミッターを設定した後、イベントの送信を開始し、受信者の反応を観察することができます。 イベントを発信するには、以下の手順に従ってください:

// Emit a user login event.
eventEmitter.emit('user.login', { username: 'john_doe' });
// Emit a user logout event.
eventEmitter.emit('user.logout', { username: 'john_doe' });
// Emit a user login event.
eventEmitter.emit('user.login', { username: 'john_doe' });
// Emit a user logout event.
eventEmitter.emit('user.logout', { username: 'john_doe' });
' Emit a user login event.
eventEmitter.emit( 'user.login', { username: 'john_doe' });
' Emit a user logout event.
eventEmitter.emit( 'user.logout', { username: 'john_doe' });
VB   C#

リスナーの追加と削除

同じイベントで、必要に応じてリスナーを追加したり削除したりすることができます。 こうしてください:

// Define a specific listener.
const loginListener = (data) => {
  console.log('User logged in:', data);
};
// Add the login listener to the user.login event.
eventEmitter.on('user.login', loginListener);
// Emit the login event.
eventEmitter.emit('user.login', { username: 'jane_doe' });
// Remove the login listener.
eventEmitter.off('user.login', loginListener);
// Emit the login event again to show that the listener has been removed.
eventEmitter.emit('user.login', { username: 'jane_doe' });
// Define a specific listener.
const loginListener = (data) => {
  console.log('User logged in:', data);
};
// Add the login listener to the user.login event.
eventEmitter.on('user.login', loginListener);
// Emit the login event.
eventEmitter.emit('user.login', { username: 'jane_doe' });
// Remove the login listener.
eventEmitter.off('user.login', loginListener);
// Emit the login event again to show that the listener has been removed.
eventEmitter.emit('user.login', { username: 'jane_doe' });
' Define a specific listener.
'INSTANT VB TODO TASK: Lambda expressions and anonymous methods are not converted by Instant VB if local variables of the outer method are referenced within the anonymous method:
const loginListener = (data) =>
If True Then
  console.log( 'User logged in:', data);
End If
' Add the login listener to the user.login event.
eventEmitter.on( 'user.login', loginListener);
' Emit the login event.
eventEmitter.emit( 'user.login', { username: 'jane_doe' });
' Remove the login listener.
eventEmitter.off( 'user.login', loginListener);
' Emit the login event again to show that the listener has been removed.
eventEmitter.emit( 'user.login', { username: 'jane_doe' });
VB   C#

非同期リスナーの使用

非同期リスナーはEventEmitter2でサポートされており、I/O集約的な操作やその他の非同期処理を管理する場合に有利です:

// Define an asynchronous listener.
eventEmitter.on('file.upload', async (data) => {
  await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate async operation.
  console.log('File uploaded:', data);
});
// Emit the file upload event.
eventEmitter.emit('file.upload', { filename: 'example.txt' });
// Define an asynchronous listener.
eventEmitter.on('file.upload', async (data) => {
  await new Promise((resolve) => setTimeout(resolve, 2000)); // Simulate async operation.
  console.log('File uploaded:', data);
});
// Emit the file upload event.
eventEmitter.emit('file.upload', { filename: 'example.txt' });
' Define an asynchronous listener.
eventEmitter.on( 'file.upload', async(data) =>
If True Then
	Await New Promise(Sub(resolve) setTimeout(resolve, 2000))
	console.log( 'File uploaded:', data);
End If
)
' Emit the file upload event.
eventEmitter.emit( 'file.upload', { filename: 'example.txt' });
VB   C#

エラー処理

エラーイベント処理中に発生する可能性のあるエラーに対処する必要があります。 間違いに細心の注意を払ってください:

eventEmitter.on('error', (err) => {
  console.error('An error occurred:', err);
});
// Emit an error event.
eventEmitter.emit('error', new Error('Something went wrong!'));
eventEmitter.on('error', (err) => {
  console.error('An error occurred:', err);
});
// Emit an error event.
eventEmitter.emit('error', new Error('Something went wrong!'));
eventEmitter.on( '@error', (err) =>
If True Then
	console.error( 'An @error occurred:', err);
End If
)
' Emit an error event.
eventEmitter.emit( '@error', New @Error('Something went wrong!'));
VB   C#

すべてをまとめる

以下に、前述の各ステップに従った包括的な例を示します:

const EventEmitter2 = require('eventemitter2').EventEmitter2;
const eventEmitter = new EventEmitter2({
  wildcard: true,
  delimiter: '.',
  newListener: false,
  maxListeners: 20,
  verboseMemoryLeak: true
});
// Add listeners
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
});
const loginListener = (data) => {
  console.log('User logged in:', data);
};
eventEmitter.on('user.login', loginListener);
eventEmitter.on('file.upload', async (data) => {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  console.log('File uploaded:', data);
});
eventEmitter.on('error', (err) => {
  console.error('An error occurred:', err);
});
// Emit events
eventEmitter.emit('user.login', { username: 'john_doe' });
eventEmitter.emit('user.logout', { username: 'john_doe' });
eventEmitter.emit('file.upload', { filename: 'example.txt' });
//first event data argument error
eventEmitter.emit('error', new Error('Something went wrong!'));
// Remove listeners
eventEmitter.off('user.login', loginListener);
eventEmitter.emit('user.login', { username: 'jane_doe' });
const EventEmitter2 = require('eventemitter2').EventEmitter2;
const eventEmitter = new EventEmitter2({
  wildcard: true,
  delimiter: '.',
  newListener: false,
  maxListeners: 20,
  verboseMemoryLeak: true
});
// Add listeners
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
});
const loginListener = (data) => {
  console.log('User logged in:', data);
};
eventEmitter.on('user.login', loginListener);
eventEmitter.on('file.upload', async (data) => {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  console.log('File uploaded:', data);
});
eventEmitter.on('error', (err) => {
  console.error('An error occurred:', err);
});
// Emit events
eventEmitter.emit('user.login', { username: 'john_doe' });
eventEmitter.emit('user.logout', { username: 'john_doe' });
eventEmitter.emit('file.upload', { filename: 'example.txt' });
//first event data argument error
eventEmitter.emit('error', new Error('Something went wrong!'));
// Remove listeners
eventEmitter.off('user.login', loginListener);
eventEmitter.emit('user.login', { username: 'jane_doe' });
const EventEmitter2 = require( 'eventemitter2').EventEmitter2;
const eventEmitter = New EventEmitter2({
	wildcard:= True,
	delimiter:= "."c,
	newListener:= False,
	maxListeners:= 20,
	verboseMemoryLeak:= True
})
' Add listeners
eventEmitter.on( 'user.*', (data) =>
If True Then
	console.log( 'User event:', data);
End If
)
'INSTANT VB TODO TASK: Lambda expressions and anonymous methods are not converted by Instant VB if local variables of the outer method are referenced within the anonymous method:
const loginListener = (data) =>
If True Then
  console.log( 'User logged in:', data);
End If
eventEmitter.on( 'user.login', loginListener);
eventEmitter.on( 'file.upload', async(data) =>
If True Then
	Await New Promise(Sub(resolve) setTimeout(resolve, 2000))
	console.log( 'File uploaded:', data);
End If
)
eventEmitter.on( '@error', (err) =>
If True Then
	console.error( 'An @error occurred:', err);
End If
)
' Emit events
eventEmitter.emit( 'user.login', { username: 'john_doe' });
eventEmitter.emit( 'user.logout', { username: 'john_doe' });
eventEmitter.emit( 'file.upload', { filename: 'example.txt' });
'first event data argument error
eventEmitter.emit( '@error', New @Error('Something went wrong!'));
' Remove listeners
eventEmitter.off( 'user.login', loginListener);
eventEmitter.emit( 'user.login', { username: 'jane_doe' });
VB   C#

リスナー・コンフィギュレーション、イベント・エミッション、エラー・ハンドリング、非同期オペレーション管理など、Node.js アプリケーションにおける EventEmitter2 の作成とコンフィギュレーションに関する広範な概要がこのガイドに記載されています。

eventemitter2 NPM(開発者向けの仕組み):図2 - EventEmitter2

はじめに

開発者はEventEmitter2とIronPDFをNode.jsアプリケーションに組み合わせることで、パワフルなPDF作成・操作機能を持つダイナミックなイベント駆動型アプリケーションを構築することができます。 このガイドの助けを借りて、Node.jsプロジェクトにこれら2つのツールをセットアップし、統合することができます。

IronPDFとは何ですか?

HTMLテキストから非常に高品質のPDFページを生成することを目的とした強力なNode.jsライブラリは、次のとおりです。IronPDF. 元のウェブコンテンツを犠牲にすることなく、HTML、CSS、その他のJavaScriptファイルを正しくフォーマットされたPDFに変換するプロセスを迅速化します。 レポート、請求書、認証書のような動的で印刷可能な書類を生成する必要があるウェブアプリケーションにとって、これは非常に役立つツールです。

カスタマイズ可能なページ設定、ヘッダー、フッター、フォントや画像の追加機能は、IronPDFの機能のほんの一部です。 複雑なスタイルやレイアウトにも対応し、すべてのテスト出力PDFが必要なレイアウトに忠実であることを保証します。 さらに、IronPDFはHTML内のJavaScriptの実行を管理し、ダイナミックでインタラクティブな情報の正確なレンダリングを可能にします。

eventemitter2 NPM(開発者向けの仕組み):図3 - IronPDF

IronPDFの機能

HTMLからのPDF生成

JavaScript、HTML、CSSをPDFに変換。 IronPDFはメディアクエリとレスポンシブデザインをサポートしています。 PDFのレポート、請求書、ドキュメントをHTMLとCSSで動的に装飾するのに便利です。

**PDF編集

既存のPDFにテキスト、写真、その他のコンテンツを追加することができます。 PDFファイルからテキストや画像を取り出したり、多数のPDFを1つのファイルにまとめたり、PDFファイルを複数の別々の文書に分割したりします。 透かし、注釈、ヘッダー、フッターを含む。

**性能と信頼性

高い性能と信頼性は、産業環境において望まれる設計品質である。 大きな文書セットも簡単に管理。

IronPDF をインストール

Node.jsプロジェクトでPDFを扱うために必要なツールを得るためにIronPDFパッケージをインストールしてください。

npm install @ironsoftware/ironpdf
npm install @ironsoftware/ironpdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'npm install @ironsoftware/ironpdf
VB   C#

EventEmitter2でPDFを生成

新しいファイルを作成し、EventEmitter2 を設定します:

const EventEmitter2 = require('eventemitter2').EventEmitter2;
const IronPdf = require("@ironsoftware/ironpdf");
const document=IronPdf.PdfDocument;
var config=IronPdf.IronPdfGlobalConfig
config.setConfig({licenseKey:''});
// Initialize EventEmitter2
const eventEmitter = new EventEmitter2({
  wildcard: true,
  delimiter: '.',
  newListener: false,
  maxListeners: 20,// show event name in memory leak message when maximum amount of listeners
  verboseMemoryLeak: true,
});
// Function to generate PDF report
const generatePdfReport = async (data) => {
  try {
    const htmlContent = `<h1>Event Report</h1><p>Event: ${data.eventName}</p><p>Data: ${JSON.stringify(data)}</p>`;
    const pdfDoc = await document.fromHtml(htmlContent);
    const filePath = `event_report_${Date.now()}.pdf`;
    await pdfDoc.saveAs(filePath);
    console.log('PDF report generated:', filePath);
  } catch (error) {
    console.error('Error generating PDF report:', error);
  }
};
// Define a listener for a wildcard event
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
  generatePdfReport({ eventName: data.eventName, ...data });
});
// test subscription event listener
eventEmitter.emit('user.login', { eventName: 'user.login', username: 'john_doe' });
eventEmitter.emit('user.logout', { eventName: 'user.logout', username: 'john_doe' });
const EventEmitter2 = require('eventemitter2').EventEmitter2;
const IronPdf = require("@ironsoftware/ironpdf");
const document=IronPdf.PdfDocument;
var config=IronPdf.IronPdfGlobalConfig
config.setConfig({licenseKey:''});
// Initialize EventEmitter2
const eventEmitter = new EventEmitter2({
  wildcard: true,
  delimiter: '.',
  newListener: false,
  maxListeners: 20,// show event name in memory leak message when maximum amount of listeners
  verboseMemoryLeak: true,
});
// Function to generate PDF report
const generatePdfReport = async (data) => {
  try {
    const htmlContent = `<h1>Event Report</h1><p>Event: ${data.eventName}</p><p>Data: ${JSON.stringify(data)}</p>`;
    const pdfDoc = await document.fromHtml(htmlContent);
    const filePath = `event_report_${Date.now()}.pdf`;
    await pdfDoc.saveAs(filePath);
    console.log('PDF report generated:', filePath);
  } catch (error) {
    console.error('Error generating PDF report:', error);
  }
};
// Define a listener for a wildcard event
eventEmitter.on('user.*', (data) => {
  console.log('User event:', data);
  generatePdfReport({ eventName: data.eventName, ...data });
});
// test subscription event listener
eventEmitter.emit('user.login', { eventName: 'user.login', username: 'john_doe' });
eventEmitter.emit('user.logout', { eventName: 'user.logout', username: 'john_doe' });
const EventEmitter2 = require( 'eventemitter2').EventEmitter2;
const IronPdf = require("@ironsoftware/ironpdf")
const document=IronPdf.PdfDocument
Dim config=IronPdf.IronPdfGlobalConfig config.setConfig({licenseKey: ''});
' Initialize EventEmitter2
const eventEmitter = New EventEmitter2({
	wildcard:= True,
	delimiter:= "."c,
	newListener:= False,
	maxListeners:= 20,
	verboseMemoryLeak:= True
})
' Function to generate PDF report
'INSTANT VB TODO TASK: Lambda expressions and anonymous methods are not converted by Instant VB if local variables of the outer method are referenced within the anonymous method:
const generatePdfReport = async(data) =>
If True Then
  Try
	const htmlContent = `(Of h1) [Event] Report</h1>(Of p) [Event]: $
	If True Then
		data.eventName
	End If
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'	</p>(Of p) Data: $
'	{
'		JSON.stringify(data)
'	}
	</p>`
	const pdfDoc = Await document.fromHtml(htmlContent)
'INSTANT VB TODO TASK: Local functions are not converted by Instant VB:
'	const filePath = `event_report_$
'	{
'		@Date.now()
'	}
	.pdf`
	Await pdfDoc.saveAs(filePath)
	console.log( 'PDF report generated:', filePath);
  Catch e1 As [error]
	console.error( '@Error generating PDF report:', @error);
  End Try
End If
' Define a listener for a wildcard event
eventEmitter.on( 'user.*', (data) =>
If True Then
	console.log( 'User event:', data);
	generatePdfReport({
		eventName:= data.eventName,
		...data
	})
End If
)
' test subscription event listener
eventEmitter.emit( 'user.login', { eventName: 'user.login', username: 'john_doe' });
eventEmitter.emit( 'user.logout', { eventName: 'user.logout', username: 'john_doe' });
VB   C#

IronPDFパッケージのIronPDFクラスとEventemitter2パッケージのEventEmitter2クラスが必要です。 EventEmitter2のインスタンスを起動し、最大リスナー、名前空間の区切り文字、ワイルドカードのサポートなどのパラメータを設定します。 私たちはgeneratePdfReportHTML情報をIronPDFを使ってPDFに変換します。

イベントデータを受け取った後、関数はHTML文字列、PDF文書、ファイルを生成します。エラー処理は、PDFを作成するときに遭遇した問題を記録するために統合されています。

eventemitter2 NPM(開発者向けの仕組み):図4 - IronPDFを使ったEventEmitter2

ワイルドカード(ユーザー)ユーザーイベントのリスナーを設定します。 ユーザーから始まるイベントはすべて、このリスナーをアクティブにします。 イベントがリリースされると、リスナーはそれに関する情報を記録し、generatePdfReport関数を呼び出すためにその中のイベントデータargを使用します。 2つのテストイベント、user.loginとuser.logoutがリリースされました。 すべてのイベントには、ユーザー名とeventNameを含むペイロードがあります。

eventemitter2 NPM(開発者向けの仕組み):図5 - PDF出力

結論

Node.jsアプリケーションは、EventEmitter2とNode-IronPDFを統合することで、強力なPDF作成機能を備えたダイナミックなイベント駆動型システムを作成することができます。 この強力なコンボは、開発者に複雑なワークフローを管理し、詳細なレポートを提供する能力を与えるため、自動レポートとリアルタイムのデータ監視を必要とするアプリケーションに最適なオプションです。

Node-IronPDFの洗練されたPDF作成機能とEventEmitter2のワイルドカードイベントとネームスペースの管理における適応性と組み合わせることで、この統合は様々なユースケースのための強力なソリューションを提供します。 この統合方法だけで、自動レポートシステム、リアルタイム分析ダッシュボード、その他の種類のイベント駆動型アプリケーションのいずれを構築する場合でも、よりスケーラブルで保守性の高いシステムを構築することができます。

OCR、BarCodeスキャン、PDF作成、Excel統合、その他多くの機能が、IronPDFやIron Software通常版はわずか749ドルで、開発者はIronSoftwareの非常に適応性の高いシステムとスイートを使用することで、より多くのウェブアプリケーションや機能をより効率的に作成することができます。

プロジェクトに合わせたライセンスの選択肢を明確にすることで、開発者が理想的なモデルを選択しやすくなります。 これらの機能の助けを借りて、開発者は、簡単、効果的、まとまった形で、さまざまな問題を解決することができます。

< 以前
Koa node js (開発者のための仕組み)
次へ >
browserify NPM (開発者のための仕組み)

準備はできましたか? バージョン: 2024.11 新発売

無料のnpmインストール ライセンスを表示 >