@rtorcato/js-tooling 2.19.2 → 2.20.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.
@@ -807,6 +807,23 @@ async function checkCodeowners(dir) {
807
807
  hint: 'Run `npx @rtorcato/js-tooling fix codeowners` to scaffold .github/CODEOWNERS',
808
808
  };
809
809
  }
810
+ async function checkCommunityHealth(dir) {
811
+ const anchors = ['CONTRIBUTING.md', 'SECURITY.md'];
812
+ const present = await Promise.all(anchors.map((f) => fs.pathExists(path.join(dir, f))));
813
+ if (present.every(Boolean)) {
814
+ return {
815
+ check: 'Community health',
816
+ status: 'ok',
817
+ detail: 'CONTRIBUTING.md and SECURITY.md found',
818
+ };
819
+ }
820
+ return {
821
+ check: 'Community health',
822
+ status: 'optional-missing',
823
+ detail: 'missing community-health files (CONTRIBUTING/SECURITY/templates)',
824
+ hint: 'Run `npx @rtorcato/js-tooling fix community-health` to scaffold them',
825
+ };
826
+ }
810
827
  async function checkGitLabCI(dir) {
811
828
  for (const candidate of ['.gitlab-ci.yml', '.gitlab-ci.yaml']) {
812
829
  if (await fs.pathExists(path.join(dir, candidate))) {
@@ -850,6 +867,7 @@ export async function runDoctor(dir) {
850
867
  results.push(await checkCodeQL(targetDir));
851
868
  results.push(await checkGitLabCI(targetDir));
852
869
  results.push(await checkCodeowners(targetDir));
870
+ results.push(await checkCommunityHealth(targetDir));
853
871
  results.push(await checkTypedoc(targetDir, pkg));
854
872
  results.push(await checkAreTheTypesWrong(targetDir, pkg));
855
873
  results.push(await checkTreeshakeSetup(targetDir, pkg));
@@ -6,6 +6,7 @@ import fs from 'fs-extra';
6
6
  import inquirer from 'inquirer';
7
7
  import { installAgentRules } from '../generators/agent-rules.js';
8
8
  import { generateSemanticReleaseConfig } from '../generators/build.js';
9
+ import { generateCommunityHealth } from '../generators/community-health.js';
9
10
  import { generateCommitlintConfig, generateHuskyConfig, generatePrePushHook, } from '../generators/git.js';
10
11
  import { generateGitHubActions } from '../generators/github-actions.js';
11
12
  import { generateGitLabCI } from '../generators/gitlab-ci.js';
@@ -299,6 +300,24 @@ const FIXERS = [
299
300
  return { filesWritten: [written] };
300
301
  },
301
302
  },
303
+ {
304
+ target: 'community-health',
305
+ description: 'Scaffold CONTRIBUTING.md, SECURITY.md, PR + issue templates',
306
+ appliesTo: ['Community health'],
307
+ outputs: [
308
+ 'CONTRIBUTING.md',
309
+ 'SECURITY.md',
310
+ '.github/PULL_REQUEST_TEMPLATE.md',
311
+ '.github/ISSUE_TEMPLATE/bug_report.md',
312
+ '.github/ISSUE_TEMPLATE/feature_request.md',
313
+ ],
314
+ riskLevel: 'safe-add',
315
+ canFixDrift: false,
316
+ async run({ targetDir }) {
317
+ const filesWritten = await generateCommunityHealth(targetDir);
318
+ return { filesWritten };
319
+ },
320
+ },
302
321
  {
303
322
  target: 'gitlab-ci',
304
323
  description: 'Scaffold .gitlab-ci.yml (lint/typecheck/test/build mirrored from GitHub Actions)',
@@ -0,0 +1,145 @@
1
+ import path from 'node:path';
2
+ import fs from 'fs-extra';
3
+ const CONTRIBUTING = `# Contributing
4
+
5
+ Thanks for your interest in contributing!
6
+
7
+ ## Local setup
8
+
9
+ \`\`\`bash
10
+ pnpm install
11
+ pnpm build
12
+ pnpm test
13
+ \`\`\`
14
+
15
+ ## Commit messages
16
+
17
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/).
18
+ Format: \`type(scope): summary\` — e.g. \`fix(api): handle empty payload\`.
19
+ Common types: \`feat\`, \`fix\`, \`docs\`, \`refactor\`, \`test\`, \`chore\`.
20
+ If commitizen is set up, run \`pnpm commit\` to be guided through it.
21
+
22
+ ## Pull requests
23
+
24
+ - Keep PRs focused and small where possible.
25
+ - Make sure \`pnpm test\` and \`pnpm check\` (lint) pass.
26
+ - Add tests for new behaviour.
27
+ - Describe what changed and why in the PR description.
28
+ `;
29
+ // Relative advisory link works from a repo-root SECURITY.md on GitHub, so the
30
+ // template stays repo-agnostic (no hardcoded owner/name). Fill in the contact.
31
+ const SECURITY = `# Security Policy
32
+
33
+ ## Supported versions
34
+
35
+ Only the latest major version receives security fixes.
36
+
37
+ ## Reporting a vulnerability
38
+
39
+ Do **not** open a public GitHub issue for security vulnerabilities.
40
+
41
+ Instead, use [GitHub's private vulnerability reporting](../../security/advisories/new)
42
+ or email **<security-contact@example.com>** with:
43
+
44
+ - A description of the vulnerability
45
+ - Steps to reproduce
46
+ - Potential impact
47
+
48
+ You'll receive a response within 5 business days.
49
+ `;
50
+ const PULL_REQUEST_TEMPLATE = `## Summary
51
+
52
+ <!-- 1-3 bullet points describing what changed and why -->
53
+ -
54
+
55
+ ## Type of change
56
+
57
+ - [ ] Bug fix
58
+ - [ ] New feature
59
+ - [ ] Refactor / cleanup
60
+ - [ ] Documentation
61
+ - [ ] CI / tooling
62
+
63
+ ## Test plan
64
+
65
+ - [ ] Existing tests pass (\`pnpm test\`)
66
+ - [ ] New tests added for new behaviour
67
+
68
+ ## Checklist
69
+
70
+ - [ ] No debug logging left in production code
71
+ - [ ] No breaking changes (or BREAKING CHANGE footer added to commit)
72
+ - [ ] Lint passes (\`pnpm check\` / \`pnpm lint\`)
73
+ `;
74
+ const BUG_REPORT = `---
75
+ name: Bug report
76
+ about: Something isn't working as expected
77
+ labels: bug
78
+ ---
79
+
80
+ ## Describe the bug
81
+
82
+ <!-- A clear and concise description of what the bug is -->
83
+
84
+ ## Steps to reproduce
85
+
86
+ 1.
87
+ 2.
88
+ 3.
89
+
90
+ ## Expected behaviour
91
+
92
+ ## Actual behaviour
93
+
94
+ <!-- Paste any error output here -->
95
+
96
+ \`\`\`
97
+ \`\`\`
98
+
99
+ ## Environment
100
+
101
+ - Package version:
102
+ - Node version (\`node -v\`):
103
+ - Package manager + version:
104
+ - OS:
105
+ `;
106
+ const FEATURE_REQUEST = `---
107
+ name: Feature request
108
+ about: Suggest an idea or improvement
109
+ labels: enhancement
110
+ ---
111
+
112
+ ## Problem
113
+
114
+ <!-- What are you trying to do that you can't do today? -->
115
+
116
+ ## Proposed solution
117
+
118
+ ## Alternatives considered
119
+
120
+ ## Additional context
121
+ `;
122
+ const FILES = [
123
+ { rel: 'CONTRIBUTING.md', content: CONTRIBUTING },
124
+ { rel: 'SECURITY.md', content: SECURITY },
125
+ { rel: '.github/PULL_REQUEST_TEMPLATE.md', content: PULL_REQUEST_TEMPLATE },
126
+ { rel: '.github/ISSUE_TEMPLATE/bug_report.md', content: BUG_REPORT },
127
+ { rel: '.github/ISSUE_TEMPLATE/feature_request.md', content: FEATURE_REQUEST },
128
+ ];
129
+ /**
130
+ * Scaffold GitHub community-health files. Safe-add: existing files are left
131
+ * untouched (the user owns them once written). Returns the list of files
132
+ * actually created.
133
+ */
134
+ export async function generateCommunityHealth(targetDir) {
135
+ const written = [];
136
+ for (const { rel, content } of FILES) {
137
+ const filepath = path.join(targetDir, rel);
138
+ if (await fs.pathExists(filepath))
139
+ continue;
140
+ await fs.ensureDir(path.dirname(filepath));
141
+ await fs.writeFile(filepath, content);
142
+ written.push(rel);
143
+ }
144
+ return written;
145
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtorcato/js-tooling",
3
- "version": "2.19.2",
3
+ "version": "2.20.0",
4
4
  "description": "JavaScript and TypeScript tooling for Node.js, React, Next.js, and Vitest.",
5
5
  "type": "module",
6
6
  "keywords": [