rulebookguard 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -36,9 +36,12 @@ testGlobs: # required: files scanned for @rule tags
36
36
  - 'src/**/*.test.ts'
37
37
  - 'tests/**/test_*.py'
38
38
  contextBudget: 30 # default: 30; lint warns when a context holds more rules
39
+ language: es # default: en; language of the text that rulebookguard generates
39
40
  ```
40
41
 
41
- `schema` and `testGlobs` are required (`testGlobs: []` is valid but finds no tags). Unknown fields are rejected. The JSON Schemas ship with the package under `rulebookguard/schemas/v1/`.
42
+ `schema` and `testGlobs` are required (`testGlobs: []` is valid but finds no tags). Unknown fields are rejected.
43
+
44
+ `language` (`en` or `es`) sets the language of the text rulebookguard writes for you, such as the template of `new`. Rule content is free text and is never checked for language, so rules can be written in any language whatever this setting says. `language` needs rulebookguard 0.1.1 or later; older versions reject it as an unknown field. The JSON Schemas ship with the package under `rulebookguard/schemas/v1/`.
42
45
 
43
46
  Inside a git work tree, files are listed with `git ls-files --cached --others --exclude-standard`, so anything in `.gitignore` (`dist/`, `coverage/`, caches) is never matched by anchors or test globs; files inside submodules are listed too. A submodule path that is a symlink, or that resolves outside the rulebook root, is skipped. A test file that is a symlink is scanned for `@rule` tags only when its target lies inside the rulebook root. If one submodule cannot be listed, commands print `warning: could not list files of submodule "<path>" (<reason>); skipping it.` and keep the rest of the git listing. Outside git, or when the rulebook root itself is git-ignored, the whole tree is walked, skipping only `.git` and `node_modules`. If git fails (for example, git is missing from `PATH` or the repository has dubious ownership), commands print one warning on stderr and walk the tree instead.
44
47
 
@@ -224,7 +227,7 @@ Exits 1 for an unknown id.
224
227
 
225
228
  ### `new <context>`
226
229
 
227
- Scaffolds the next free id of a context as a `proposed` rule and prints its path. Ids are never reused, and an existing file is never overwritten.
230
+ Scaffolds the next free id of a context as a `proposed` rule and prints its path. Ids are never reused, and an existing file is never overwritten. The placeholder text of the new rule follows `language` in the config.
228
231
 
229
232
  ```sh
230
233
  $ rulebookguard new clients
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { M as FormatError, N as formatIssue, _ as expandGlobs, a as CliError, c as openCatalog, d as scanTestTags, h as rulesForPath, l as writeJson, o as findRule, r as lintCommand, s as gitFallbackWarning, u as writeLines, y as toRepoPath } from "./lint-V-Uw5ueZ.mjs";
2
+ import { M as FormatError, N as formatIssue, _ as expandGlobs, a as CliError, c as openCatalog, d as scanTestTags, h as rulesForPath, l as writeJson, o as findRule, r as lintCommand, s as gitFallbackWarning, u as writeLines, y as toRepoPath } from "./lint-DtD_Ekei.mjs";
3
3
  import { readdir, writeFile } from "node:fs/promises";
4
4
  import { isAbsolute, join, relative, resolve } from "node:path";
5
5
  import { parseArgs } from "node:util";
@@ -17,32 +17,51 @@ async function newCommand(catalog, io, name) {
17
17
  const id = `R-${context.prefix}-${String(last + 1).padStart(3, "0")}`;
18
18
  const file = `${directory}/${id}.md`;
19
19
  try {
20
- await writeFile(join(catalog.root, file), template(id, context.context), { flag: "wx" });
20
+ await writeFile(join(catalog.root, file), template(id, context.context, catalog.config.language ?? "en"), { flag: "wx" });
21
21
  } catch (error) {
22
22
  if (error.code === "EEXIST") throw new CliError(`${file} already exists; nothing was written.`);
23
23
  throw error;
24
24
  }
25
25
  writeLines(io, [file]);
26
26
  }
27
- function template(id, context) {
27
+ const TEMPLATE_TEXT = {
28
+ en: {
29
+ summary: "TODO: one-line summary of the rule.",
30
+ title: "TODO: rule title",
31
+ intro: "TODO: state the rule in full, then add examples as Gherkin scenarios or tables.",
32
+ scenario: `Scenario: TODO
33
+ Given TODO
34
+ When TODO
35
+ Then TODO`
36
+ },
37
+ es: {
38
+ summary: "TODO: resumen de la regla en una línea.",
39
+ title: "TODO: título de la regla",
40
+ intro: "TODO: describe la regla completa y agrega ejemplos como escenarios Gherkin o tablas.",
41
+ scenario: `# language: es
42
+ Escenario: TODO
43
+ Dado TODO
44
+ Cuando TODO
45
+ Entonces TODO`
46
+ }
47
+ };
48
+ function template(id, context, language) {
49
+ const text = TEMPLATE_TEXT[language];
28
50
  return `---
29
51
  id: ${id}
30
52
  context: ${context}
31
53
  entities: []
32
54
  status: proposed
33
55
  anchors: []
34
- summary: 'TODO: one-line summary of the rule.'
56
+ summary: '${text.summary}'
35
57
  ---
36
58
 
37
- # TODO: rule title
59
+ # ${text.title}
38
60
 
39
- TODO: state the rule in full, then add examples as Gherkin scenarios or tables.
61
+ ${text.intro}
40
62
 
41
63
  \`\`\`gherkin
42
- Scenario: TODO
43
- Given TODO
44
- When TODO
45
- Then TODO
64
+ ${text.scenario}
46
65
  \`\`\`
47
66
  `;
48
67
  }
package/dist/index.d.mts CHANGED
@@ -1,9 +1,12 @@
1
1
  type RuleStatus = "proposed" | "active" | "deprecated";
2
+ type RuleLanguage = "en" | "es";
2
3
  interface RulebookConfig {
3
4
  schema: 1;
4
5
  rulesDir: string;
5
6
  testGlobs: string[];
6
7
  contextBudget: number;
8
+ /** Language the generated rule text is written in; `en` when unset. */
9
+ language?: RuleLanguage;
7
10
  }
8
11
  interface ContextFrontmatter {
9
12
  context: string;
@@ -146,4 +149,4 @@ interface LintOptions {
146
149
  export declare function lintCatalog(catalog: Catalog, tags?: TagIndex, onGitFallback?: GitFallbackListener): Promise<LintFinding[]>;
147
150
  export declare function pendingImplementation(catalog: Catalog, tags: TagIndex, base: string, changed: string[]): LintFinding[];
148
151
  export declare function formatFinding(finding: LintFinding): string;
149
- export type { Catalog, CatalogIssue, CatalogIssueCode, ContextDoc, ContextFrontmatter, ContextsJson, ForJson, FormatIssue, Frontmatter, GitFallbackListener, ImpactJson, LintFinding, LintJson, LintOptions, LintSeverity, ListJson, RuleDoc, RuleFrontmatter, RuleStatus, RuleSummaryJson, RuleTag, RulebookConfig, ShowJson, TagIndex, TagLocation };
152
+ export type { Catalog, CatalogIssue, CatalogIssueCode, ContextDoc, ContextFrontmatter, ContextsJson, ForJson, FormatIssue, Frontmatter, GitFallbackListener, ImpactJson, LintFinding, LintJson, LintOptions, LintSeverity, ListJson, RuleDoc, RuleFrontmatter, RuleLanguage, RuleStatus, RuleSummaryJson, RuleTag, RulebookConfig, ShowJson, TagIndex, TagLocation };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export { k as CONFIG_FILE_NAME, T as CONTEXT_FILE_NAME, M as FormatError, b as RULE_TAG_PATTERN, g as createGlobMatcher, _ as expandGlobs, x as findRuleTags, f as findRulebookRoot, t as formatFinding, N as formatIssue, S as isRuleId, n as lintCatalog, v as listRepoFiles, p as loadCatalog, A as loadConfig, E as loadContext, C as loadRule, j as parseConfig, D as parseContext, w as parseRule, i as pendingImplementation, m as relativeToRoot, h as rulesForPath, d as scanTestTags, O as splitFrontmatter, y as toRepoPath } from "./lint-V-Uw5ueZ.mjs";
1
+ export { k as CONFIG_FILE_NAME, T as CONTEXT_FILE_NAME, M as FormatError, b as RULE_TAG_PATTERN, g as createGlobMatcher, _ as expandGlobs, x as findRuleTags, f as findRulebookRoot, t as formatFinding, N as formatIssue, S as isRuleId, n as lintCatalog, v as listRepoFiles, p as loadCatalog, A as loadConfig, E as loadContext, C as loadRule, j as parseConfig, D as parseContext, w as parseRule, i as pendingImplementation, m as relativeToRoot, h as rulesForPath, d as scanTestTags, O as splitFrontmatter, y as toRepoPath } from "./lint-DtD_Ekei.mjs";
@@ -52,7 +52,8 @@ var config_schema_default = {
52
52
  "type": "integer",
53
53
  "minimum": 1,
54
54
  "default": 30
55
- }
55
+ },
56
+ "language": { "enum": ["en", "es"] }
56
57
  },
57
58
  required: ["schema", "testGlobs"],
58
59
  additionalProperties: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulebookguard",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Keep business rules as the single source of truth, bound to code and tests.",
5
5
  "homepage": "https://github.com/JuanCJR/rulebookguard#readme",
6
6
  "bugs": {
@@ -7,7 +7,8 @@
7
7
  "schema": { "const": 1 },
8
8
  "rulesDir": { "type": "string", "minLength": 1, "default": "docs/rules" },
9
9
  "testGlobs": { "type": "array", "items": { "type": "string", "minLength": 1 } },
10
- "contextBudget": { "type": "integer", "minimum": 1, "default": 30 }
10
+ "contextBudget": { "type": "integer", "minimum": 1, "default": 30 },
11
+ "language": { "enum": ["en", "es"] }
11
12
  },
12
13
  "required": ["schema", "testGlobs"],
13
14
  "additionalProperties": false