-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
256 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* Provides functions for finding available network ports within a specified range. | ||
* | ||
* @file lib/common/port.ts | ||
* @license MIT | ||
*/ | ||
|
||
import { createServer } from "node:net" | ||
|
||
interface FindFreePortOptions { | ||
/** | ||
* The starting port number to begin the search. | ||
* @default 49152 | ||
*/ | ||
startPort?: number | ||
|
||
/** | ||
* The ending port number (inclusive) for the search. | ||
* @default 65535 | ||
*/ | ||
endPort?: number | ||
} | ||
|
||
/** | ||
* Asynchronously checks if a given port is available. | ||
* | ||
* @param port - The port number to check. | ||
* @returns A promise that resolves to `true` if the port is available, `false` otherwise. | ||
*/ | ||
// deno-lint-ignore require-await | ||
async function isPortAvailable(port: number) { | ||
return new Promise((resolve) => { | ||
const server = createServer() | ||
server.on("error", () => resolve(false)) | ||
server.listen(port, () => { | ||
server.close() | ||
resolve(true) | ||
}) | ||
}) | ||
} | ||
|
||
/** | ||
* Asynchronously finds an available port within a specified range. | ||
* | ||
* @param options - Options for the port search. | ||
* @returns A promise that resolves to the first available free port. | ||
* @throws An error if no free ports are found within the range. | ||
*/ | ||
export async function findFreePort(options: FindFreePortOptions = {}): Promise<number> { | ||
const { startPort = 49152, endPort = 65535 } = options | ||
|
||
for (let port = startPort; port <= endPort; port++) { | ||
if (await isPortAvailable(port)) { | ||
return port | ||
} | ||
} | ||
|
||
throw new Error("No free ports found in the specified range.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/** | ||
* Provides a mechanism for loading or generating properties stored in files, | ||
* ensuring secure file permissions. | ||
* | ||
* @file lib/common/prop.ts | ||
* @license MIT | ||
*/ | ||
|
||
import { exists, readFile, writeFile } from "@cross/fs" | ||
import { DEFAULT_PROP_FILE_PERMISSIONS } from "../core/configuration.ts" | ||
|
||
export type PropGenerator = () => Promise<string> | ||
|
||
export class Prop { | ||
/** | ||
* The file path where the property is stored. | ||
*/ | ||
path: string | ||
|
||
/** | ||
* An in-memory cache of the loaded or generated property. | ||
*/ | ||
cache: string | undefined | ||
|
||
/** | ||
* File permissions to use when creating the property file. | ||
*/ | ||
filePermissions: number | ||
|
||
/** | ||
* Creates a new instance of the Prop class. | ||
* | ||
* @param secretFilePath - The path to the file where the property is stored. | ||
* @param filePermissions - File permissions to use when creating the property file (default: 0o600). | ||
*/ | ||
constructor(secretFilePath: string, filePermissions = DEFAULT_PROP_FILE_PERMISSIONS) { | ||
this.path = secretFilePath | ||
this.filePermissions = filePermissions | ||
} | ||
|
||
/** | ||
* Generates a new property and stores it in the file. | ||
* | ||
* @throws On error | ||
* @returns The newly generated property. | ||
*/ | ||
async generate(generatorFn: PropGenerator): Promise<string> { | ||
const resultString = await generatorFn() | ||
await writeFile(this.path, resultString, { mode: this.filePermissions }) | ||
return resultString | ||
} | ||
|
||
/** | ||
* Loads the property from the file system. | ||
* | ||
* @returns The property from the file. | ||
* @throws If an error occurs while reading the file. | ||
*/ | ||
async load(): Promise<string> { | ||
this.cache = await readFile(this.path, "utf-8") | ||
return this.cache! | ||
} | ||
|
||
/** | ||
* Loads the property from the cache | ||
* | ||
* @returns The property from the file. | ||
* @throws If an error occurs while reading the file. | ||
*/ | ||
fromCache(): string | undefined { | ||
return this.cache | ||
} | ||
|
||
/** | ||
* Loads the property if it exists in the file, or generates a new one if it doesn't. | ||
* The property is cached for subsequent calls. This is the primary method for using the class. | ||
* | ||
* @throws On any error | ||
* @returns The loaded or generated property. | ||
*/ | ||
async loadOrGenerate(generatorFn: PropGenerator): Promise<string> { | ||
if (!this.cache) { | ||
if (await exists(this.path)) { | ||
this.cache = await this.load() | ||
} else { | ||
this.cache = await this.generate(generatorFn) | ||
} | ||
} | ||
return this.cache | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.