Skip to content

Commit

Permalink
Synced implementation with Java implementation version 10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cowwoc committed Aug 29, 2024
1 parent 20859b1 commit f4f04e4
Show file tree
Hide file tree
Showing 192 changed files with 15,882 additions and 14,291 deletions.
59 changes: 0 additions & 59 deletions .eslintrc.mjs

This file was deleted.

20 changes: 6 additions & 14 deletions .mocharc.cjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
module.exports = {
// https://github.com/mochajs/mocha/issues/4726#issuecomment-903213780
loader: ["ts-node/esm"],
require: ["ts-node/register", "source-map-support/register.js"],
// https://stackoverflow.com/a/78098005/14731
"node-option": ["import=tsx"],
require: ["source-map-support/register.js"],
reporter: "spec",
extensions:
[
".mts"
],
include:
[
"**/*.mts"
],
exclude: [
"**/*.d.mts"
]
extension: ["mts"],
include: ["**/*.mts"],
exclude: ["**/*.d.mts"]
};
45 changes: 23 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
[![npm version](https://badge.fury.io/js/%40cowwoc%2Frequirements.svg)](https://badge.fury.io/js/%40cowwoc%2Frequirements)
[![build-status](https://github.com/cowwoc/requirements.js/workflows/Build/badge.svg)](https://github.com/cowwoc/requirements.js/actions?query=workflow%3ABuild)

# <img src="https://raw.githubusercontent.com/cowwoc/requirements.js/release-3.4.0/docs/checklist.svg?sanitize=true" width=64 height=64 alt="checklist"> Fluent API for Design Contracts
# <img src="https://raw.githubusercontent.com/cowwoc/requirements.js/release-4.0.0/docs/checklist.svg?sanitize=true" width=64 height=64 alt="checklist"> Fluent API for Design Contracts

[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/)
[![Changelog](https://img.shields.io/badge/changelog-A345D5.svg)](wiki/Changelog.md)
[![API](https://img.shields.io/badge/api_docs-5B45D5.svg)](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/)
[![Changelog](https://img.shields.io/badge/changelog-A345D5.svg)](docs/Changelog.md)
[![java](https://img.shields.io/badge/other%20languages-java-457FD5.svg)](../../../requirements.java)

A [fluent API](https://en.wikipedia.org/wiki/Fluent_interface) for enforcing
[design contracts](https://en.wikipedia.org/wiki/Design_by_contract) with [automatic message generation](#usage).
[design contracts](https://en.wikipedia.org/wiki/Design_by_contract)
with [automatic message generation](#usage).

✔️ Easy to use
✔️ Fast
Expand All @@ -17,17 +18,15 @@ A [fluent API](https://en.wikipedia.org/wiki/Fluent_interface) for enforcing
To get started, add this dependency:

```shell
npm install --save @cowwoc/requirements@3.4.0
npm install --save @cowwoc/requirements@4.0.0
```

or [pnpm](https://pnpm.io/):

```shell
pnpm add @cowwoc/requirements@3.4.0
pnpm add @cowwoc/requirements@4.0.0
```

The contents of the API classes depend on which [modules](wiki/Supported_Libraries.md) are enabled.

## Sample Code

```typescript
Expand All @@ -47,9 +46,9 @@ class PublicAPI
requireThat(age as unknown, "age").isNumber().isBetween(18, 30);

// Methods that conduct runtime type-checks, such as isString() or isNotNull(), update the
// compile-time type returned by getActual().
const nameIsString: string = requireThat(name as unknown, "name").isString().getActual();
const address: Address = requireThat(address as unknown, "address").isInstance(Address).getActual();
// compile-time type returned by getValue().
const nameIsString: string = requireThat(name as unknown, "name").isString().getValue();
const address: Address = requireThat(address as unknown, "address").isInstance(Address).getValue();
}
}

Expand Down Expand Up @@ -79,31 +78,33 @@ Actual: 15

## Features

* [Automatic message generation](wiki/Features.md#automatic-message-generation)
* [Diffs provided whenever possible](wiki/Features.md#diffs-provided-whenever-possible)
* [Assertion support](wiki/Features.md#assertion-support)
* [Grouping nested requirements](wiki/Features.md#grouping-nested-requirements)
* [String diff](wiki/Features.md#string-diff)
* [Automatic message generation](docs/Features.md#automatic-message-generation)
* [Diffs provided whenever possible](docs/Features.md#diffs-provided-whenever-possible)
* [Assertion support](docs/Features.md#assertion-support)
* [Grouping nested requirements](docs/Features.md#grouping-nested-requirements)
* [String diff](docs/Features.md#string-diff)

## Getting Started

The best way to learn about the API is using your IDE's auto-complete engine.
There are six entry points you can navigate from:

* [requireThat(value, name)](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-DefaultRequirements.html#~requireThat)
* [validateThat(value, name)](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-DefaultRequirements.html#~validateThat)
* [assertThat(Function)](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-DefaultRequirements.html#~assertThat)
* [assertThatAndReturn(Function)](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-DefaultRequirements.html#~assertThatAndReturn)
* [requireThat(value, name)](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-DefaultRequirements.html#~requireThat)
* [validateThat(value, name)](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-DefaultRequirements.html#~validateThat)
* [assertThat(Function)](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-DefaultRequirements.html#~assertThat)
* [assertThatAndReturn(Function)](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-DefaultRequirements.html#~assertThatAndReturn)

* [Requirements](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-Requirements-Requirements.html)
* [GlobalRequirements](https://cowwoc.github.io/requirements.js/3.4.0/docs/api/module-GlobalRequirements-GlobalRequirements.html)
* [Requirements](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-Requirements-Requirements.html)
* [GlobalRequirements](https://cowwoc.github.io/requirements.js/4.0.0/docs/api/module-GlobalRequirements-GlobalRequirements.html)

## Best practices

* Use `requireThat()` to verify pre-conditions of public APIs.
* Use `assertThat()` to verify object invariants and method post-conditions.
This results in excellent performance when assertions are disabled.
Have your cake and eat it too!
* Don't bother validating any constraints that are already enforced by the Typescript compiler (such as the
type of a variable) unless it will result in silent failures or security vulnerabilities when violated.

## Related Projects

Expand Down
2 changes: 1 addition & 1 deletion build/LogFactory.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const BgRed = "\x1b[41m";
class LogFactory
{
/**
* @param name the name of the logger
* @param name - the name of the logger
*/
public static getLogger(name: string): Logger
{
Expand Down
54 changes: 42 additions & 12 deletions build/Project.mts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import {minify} from "terser";
import {spawn} from "child_process";
import {LogFactory} from "./LogFactory.mjs";
import {default as chokidar} from "chokidar";
import eslintConfig from "../.eslintrc.mjs";
import eslintConfig from "../eslint.config.mjs";
import {Logger} from "winston";
import {mode} from "./mode.mjs";
import parseArgs from "minimist";
import _ from "lodash";
import debounce from "lodash.debounce";


class Project
Expand All @@ -47,19 +47,19 @@ class Project
console.time("lintTypescript");
const eslint = new ESLint({
baseConfig: eslintConfig,
cache: true,
"overrideConfig": {
parserOptions: {
debugLevel: false
}
}
cache: true
});
let results;
try
{
results = await eslint.lintFiles(sources);
const resultsMeta: ESLint.LintResultData =
{
cwd: process.cwd(),
rulesMeta: eslint.getRulesMetaForResults(results)
};
const formatter = await eslint.loadFormatter("stylish");
const resultText = await formatter.format(results);
const resultText = await formatter.format(results, resultsMeta);
if (resultText)
this.log.info(resultText);
}
Expand Down Expand Up @@ -151,7 +151,8 @@ class Project
console.time("bundleForBrowser");

// Need to cast plugins to Function due to bug in type definitions.
// WORKAROUND: https://github.com/algolia/algoliasearch-client-javascript/issues/1431#issuecomment-1568529321
// WORKAROUND:
// https://github.com/algolia/algoliasearch-client-javascript/issues/1431#issuecomment-1568529321
const plugins: Plugin[] = [
rollupCommonjs,
(rollupTypescript as unknown as Function)({
Expand Down Expand Up @@ -305,7 +306,7 @@ class Project
const promise = new Promise(function(resolve, reject)
{
// https://stackoverflow.com/a/14231570/14731
const process = spawn(c8Path, [mochaPath, "./test/**/*.mts", "--mode=" + mode],
const process = spawn(c8Path, [mochaPath, "--parallel", "./test/**/*.mts", "--mode=" + mode],
{
shell: true,
stdio: "inherit"
Expand Down Expand Up @@ -350,6 +351,22 @@ class Project
console.timeEnd("build");
}

public async clean()
{
console.time("clean");
const typescriptFiles = await this.getTypescriptFiles();
for (const file of typescriptFiles)
{
let basePath = path.posix.basename(file);
basePath = basePath.substring(0, basePath.lastIndexOf("."));
if (fs.existsSync(basePath + ".mjs"))
await fs.promises.unlink(basePath + ".mjs");
if (fs.existsSync(basePath + ".mjs.map"))
await fs.promises.unlink(basePath + ".mjs.map");
}
console.timeEnd("clean");
}

/**
* @param paths the paths to watch
* @param callback the callback to notify after a path is updated.
Expand Down Expand Up @@ -378,7 +395,7 @@ class Project
await callback(posixPaths);
}

const queueUpdate = _.debounce(processUpdate, 500);
const queueUpdate = debounce(processUpdate, 500);
const onUpdate = async (changed: string, stats: fs.Stats) =>
{
changes.add(changed);
Expand Down Expand Up @@ -427,10 +444,23 @@ switch (command._[0])
await project.build();
break;
}
case "clean":
{
await project.clean();
break;
}
case "watch":
{
await project.watch();
break;
}
default:
{
// Use POSIX paths across all platforms
const posixPath = url.fileURLToPath(import.meta.url).split(path.sep).join(path.posix.sep);
const __filename = path.posix.basename(posixPath);
const log = LogFactory.getLogger(__filename);
log.error(`Unknown command: ${command._[0]}`);
}
}
console.timeEnd("Time elapsed");
2 changes: 1 addition & 1 deletion build/TestCompiler.mts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class TestCompiler
* Compiles a code snippet.
*
* @param snippet - the code to compile
* @return the compiler warnings and errors
* @returns the compiler warnings and errors
*/
public compile(snippet: string)
{
Expand Down
2 changes: 1 addition & 1 deletion build/mode.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import parseArgs from "minimist";

const env = parseArgs(process.argv.slice(2));
let mode = env.mode;
if (typeof (mode) === "undefined")
if (mode === undefined)
mode = "DEBUG";

export {mode};
Loading

0 comments on commit f4f04e4

Please sign in to comment.