@deployanyway/excuse-js 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +17 -0
- package/bin/cli.js +26 -4
- package/package.json +1 -1
- package/src/index.js +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-10-08
|
|
4
|
+
|
|
5
|
+
- Meeting preparation mode: Generate 1–20 excuses with `excuseBatch(category, { count, seed })`. A batch cycles through the category without repeats until its pool is exhausted. Seeds keep the starting point repeatable. CLI `--json` returns a string or array.
|
|
6
|
+
- Add npm and CI badges to the published README.
|
|
7
|
+
|
|
3
8
|
## 0.1.1 — 2026-10-08
|
|
4
9
|
|
|
5
10
|
- Correct npm installation and npx documentation after the initial publication.
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# excuse-js
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@deployanyway/excuse-js)
|
|
4
|
+
[](https://github.com/DeployAnyway/excuse-js/actions/workflows/ci.yml)
|
|
5
|
+
|
|
3
6
|
A seeded developer excuse generator for bugs, builds, and deployments. Finally, a dependency that takes the blame.
|
|
4
7
|
|
|
5
8
|
```text
|
|
@@ -109,3 +112,17 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). Useful first, funny second.
|
|
|
109
112
|
- [doggo-log](https://github.com/DeployAnyway/doggo-log)
|
|
110
113
|
- [ship-it-meter](https://github.com/DeployAnyway/ship-it-meter)
|
|
111
114
|
- [bro-say](https://github.com/DeployAnyway/bro-say)
|
|
115
|
+
|
|
116
|
+
## Meeting preparation mode
|
|
117
|
+
|
|
118
|
+
Generate 1–20 excuses with `excuseBatch(category, { count, seed })`. A batch cycles through the category without repeats until its pool is exhausted. Seeds keep the starting point repeatable. CLI `--json` returns a string or array.
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
npx @deployanyway/excuse-js deployment --count 3 --seed demo
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
API (import the named functions from this package):
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
excuseBatch("deployment", { count: 3, seed: "demo" });
|
|
128
|
+
```
|
package/bin/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { parseArgs } from "node:util";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { URL } from "node:url";
|
|
5
|
-
import { excuse, categories } from "../src/index.js";
|
|
5
|
+
import { excuse, categories, excuseBatch } from "../src/index.js";
|
|
6
6
|
|
|
7
7
|
try {
|
|
8
8
|
const { values, positionals } = parseArgs({
|
|
@@ -12,11 +12,13 @@ try {
|
|
|
12
12
|
version: { type: "boolean", short: "v" },
|
|
13
13
|
seed: { type: "string" },
|
|
14
14
|
list: { type: "boolean" },
|
|
15
|
+
count: { type: "string" },
|
|
16
|
+
json: { type: "boolean" },
|
|
15
17
|
},
|
|
16
18
|
});
|
|
17
19
|
if (values.help) {
|
|
18
20
|
console.log(
|
|
19
|
-
"Usage: excuse-js [category] [--seed text]\n\nDefault category: deployment\n\nOptions:\n --seed text Repeatable selection (always a string seed)\n --list List categories\n -h, --help Show help\n -v, --version Show version\n\nExample: excuse-js deployment --seed demo\nExit codes: 0 success; 2 invalid arguments.",
|
|
21
|
+
"Usage: excuse-js [category] [--seed text] [--count 3] [--json]\n\nDefault category: deployment\n\nOptions:\n --seed text Repeatable selection (always a string seed)\n --count 1..20 Prepare a batch for the meeting\n --json Structured string or batch\n --list List categories\n -h, --help Show help\n -v, --version Show version\n\nExample: excuse-js deployment --seed demo\nExit codes: 0 success; 2 invalid arguments.",
|
|
20
22
|
);
|
|
21
23
|
} else if (values.version) {
|
|
22
24
|
console.log(
|
|
@@ -25,13 +27,33 @@ try {
|
|
|
25
27
|
).version,
|
|
26
28
|
);
|
|
27
29
|
} else if (values.list) {
|
|
28
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
positionals.length ||
|
|
32
|
+
values.seed !== undefined ||
|
|
33
|
+
values.count !== undefined ||
|
|
34
|
+
values.json
|
|
35
|
+
)
|
|
29
36
|
throw new TypeError("--list does not accept a category or seed.");
|
|
30
37
|
console.log(categories().join("\n"));
|
|
31
38
|
} else {
|
|
32
39
|
if (positionals.length > 1)
|
|
33
40
|
throw new TypeError("Provide only one category.");
|
|
34
|
-
|
|
41
|
+
if (values.count !== undefined && !/^[0-9]+$/.test(values.count))
|
|
42
|
+
throw new TypeError("count must be an integer.");
|
|
43
|
+
const result =
|
|
44
|
+
values.count === undefined
|
|
45
|
+
? excuse(positionals[0], { seed: values.seed })
|
|
46
|
+
: excuseBatch(positionals[0], {
|
|
47
|
+
seed: values.seed,
|
|
48
|
+
count: Number(values.count),
|
|
49
|
+
});
|
|
50
|
+
console.log(
|
|
51
|
+
values.json
|
|
52
|
+
? JSON.stringify(result)
|
|
53
|
+
: Array.isArray(result)
|
|
54
|
+
? result.map((line, i) => `${i + 1}. ${line}`).join("\n")
|
|
55
|
+
: result,
|
|
56
|
+
);
|
|
35
57
|
}
|
|
36
58
|
} catch (error) {
|
|
37
59
|
console.error(`excuse-js: ${error.message}\nRun with --help for usage.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deployanyway/excuse-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A seeded developer excuse generator for bugs, builds, and deployments. Finally, a dependency that takes the blame.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./src/index.js",
|
package/src/index.js
CHANGED
|
@@ -42,3 +42,19 @@ export function excuse(category = "deployment", options = {}) {
|
|
|
42
42
|
}
|
|
43
43
|
return phrases[key][index];
|
|
44
44
|
}
|
|
45
|
+
|
|
46
|
+
/** Generate a batch without repeats until the category pool is exhausted. */
|
|
47
|
+
export function excuseBatch(category = "deployment", options = {}) {
|
|
48
|
+
if (!options || typeof options !== "object" || Array.isArray(options))
|
|
49
|
+
throw new TypeError("Options must be an object.");
|
|
50
|
+
const count = options.count ?? 3;
|
|
51
|
+
if (!Number.isSafeInteger(count) || count < 1 || count > 20)
|
|
52
|
+
throw new RangeError("count must be an integer between 1 and 20.");
|
|
53
|
+
const first = excuse(category, { seed: options.seed });
|
|
54
|
+
const pool = phrases[category.trim().toLowerCase()];
|
|
55
|
+
const start = pool.indexOf(first);
|
|
56
|
+
return Array.from(
|
|
57
|
+
{ length: count },
|
|
58
|
+
(_, i) => pool[(start + i) % pool.length],
|
|
59
|
+
);
|
|
60
|
+
}
|