@ploaness/cli 1.0.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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +161 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/checks/assets.d.ts +30 -0
  8. package/dist/checks/assets.d.ts.map +1 -0
  9. package/dist/checks/assets.js +169 -0
  10. package/dist/checks/assets.js.map +1 -0
  11. package/dist/checks/containers.d.ts +9 -0
  12. package/dist/checks/containers.d.ts.map +1 -0
  13. package/dist/checks/containers.js +194 -0
  14. package/dist/checks/containers.js.map +1 -0
  15. package/dist/checks/conventions.d.ts +8 -0
  16. package/dist/checks/conventions.d.ts.map +1 -0
  17. package/dist/checks/conventions.js +77 -0
  18. package/dist/checks/conventions.js.map +1 -0
  19. package/dist/checks/dependencies.d.ts +11 -0
  20. package/dist/checks/dependencies.d.ts.map +1 -0
  21. package/dist/checks/dependencies.js +389 -0
  22. package/dist/checks/dependencies.js.map +1 -0
  23. package/dist/checks/editorconfig.d.ts +5 -0
  24. package/dist/checks/editorconfig.d.ts.map +1 -0
  25. package/dist/checks/editorconfig.js +38 -0
  26. package/dist/checks/editorconfig.js.map +1 -0
  27. package/dist/checks/generated.d.ts +10 -0
  28. package/dist/checks/generated.d.ts.map +1 -0
  29. package/dist/checks/generated.js +65 -0
  30. package/dist/checks/generated.js.map +1 -0
  31. package/dist/checks/history.d.ts +19 -0
  32. package/dist/checks/history.d.ts.map +1 -0
  33. package/dist/checks/history.js +71 -0
  34. package/dist/checks/history.js.map +1 -0
  35. package/dist/checks/images.d.ts +14 -0
  36. package/dist/checks/images.d.ts.map +1 -0
  37. package/dist/checks/images.js +100 -0
  38. package/dist/checks/images.js.map +1 -0
  39. package/dist/checks/install.d.ts +5 -0
  40. package/dist/checks/install.d.ts.map +1 -0
  41. package/dist/checks/install.js +21 -0
  42. package/dist/checks/install.js.map +1 -0
  43. package/dist/checks/integrity.d.ts +11 -0
  44. package/dist/checks/integrity.d.ts.map +1 -0
  45. package/dist/checks/integrity.js +66 -0
  46. package/dist/checks/integrity.js.map +1 -0
  47. package/dist/checks/payload.d.ts +7 -0
  48. package/dist/checks/payload.d.ts.map +1 -0
  49. package/dist/checks/payload.js +81 -0
  50. package/dist/checks/payload.js.map +1 -0
  51. package/dist/checks/preflight.d.ts +5 -0
  52. package/dist/checks/preflight.d.ts.map +1 -0
  53. package/dist/checks/preflight.js +48 -0
  54. package/dist/checks/preflight.js.map +1 -0
  55. package/dist/checks/references.d.ts +18 -0
  56. package/dist/checks/references.d.ts.map +1 -0
  57. package/dist/checks/references.js +100 -0
  58. package/dist/checks/references.js.map +1 -0
  59. package/dist/checks/suppressions.d.ts +5 -0
  60. package/dist/checks/suppressions.d.ts.map +1 -0
  61. package/dist/checks/suppressions.js +50 -0
  62. package/dist/checks/suppressions.js.map +1 -0
  63. package/dist/checks/tailwind.d.ts +5 -0
  64. package/dist/checks/tailwind.d.ts.map +1 -0
  65. package/dist/checks/tailwind.js +29 -0
  66. package/dist/checks/tailwind.js.map +1 -0
  67. package/dist/checks/tests.d.ts +8 -0
  68. package/dist/checks/tests.d.ts.map +1 -0
  69. package/dist/checks/tests.js +123 -0
  70. package/dist/checks/tests.js.map +1 -0
  71. package/dist/checks/toolchain.d.ts +25 -0
  72. package/dist/checks/toolchain.d.ts.map +1 -0
  73. package/dist/checks/toolchain.js +165 -0
  74. package/dist/checks/toolchain.js.map +1 -0
  75. package/dist/checks/tree.d.ts +6 -0
  76. package/dist/checks/tree.d.ts.map +1 -0
  77. package/dist/checks/tree.js +52 -0
  78. package/dist/checks/tree.js.map +1 -0
  79. package/dist/checks/wiring.d.ts +5 -0
  80. package/dist/checks/wiring.d.ts.map +1 -0
  81. package/dist/checks/wiring.js +163 -0
  82. package/dist/checks/wiring.js.map +1 -0
  83. package/dist/commands/commit-message.d.ts +11 -0
  84. package/dist/commands/commit-message.d.ts.map +1 -0
  85. package/dist/commands/commit-message.js +57 -0
  86. package/dist/commands/commit-message.js.map +1 -0
  87. package/dist/commands/format.d.ts +4 -0
  88. package/dist/commands/format.d.ts.map +1 -0
  89. package/dist/commands/format.js +35 -0
  90. package/dist/commands/format.js.map +1 -0
  91. package/dist/commands/hooks.d.ts +9 -0
  92. package/dist/commands/hooks.d.ts.map +1 -0
  93. package/dist/commands/hooks.js +57 -0
  94. package/dist/commands/hooks.js.map +1 -0
  95. package/dist/commands/init.d.ts +4 -0
  96. package/dist/commands/init.d.ts.map +1 -0
  97. package/dist/commands/init.js +92 -0
  98. package/dist/commands/init.js.map +1 -0
  99. package/dist/commands/sync.d.ts +4 -0
  100. package/dist/commands/sync.d.ts.map +1 -0
  101. package/dist/commands/sync.js +30 -0
  102. package/dist/commands/sync.js.map +1 -0
  103. package/dist/commands/verify.d.ts +18 -0
  104. package/dist/commands/verify.d.ts.map +1 -0
  105. package/dist/commands/verify.js +96 -0
  106. package/dist/commands/verify.js.map +1 -0
  107. package/dist/context.d.ts +157 -0
  108. package/dist/context.d.ts.map +1 -0
  109. package/dist/context.js +345 -0
  110. package/dist/context.js.map +1 -0
  111. package/dist/exec.d.ts +80 -0
  112. package/dist/exec.d.ts.map +1 -0
  113. package/dist/exec.js +117 -0
  114. package/dist/exec.js.map +1 -0
  115. package/dist/gates.d.ts +61 -0
  116. package/dist/gates.d.ts.map +1 -0
  117. package/dist/gates.js +298 -0
  118. package/dist/gates.js.map +1 -0
  119. package/dist/index.d.ts +10 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +12 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/report.d.ts +40 -0
  124. package/dist/report.d.ts.map +1 -0
  125. package/dist/report.js +224 -0
  126. package/dist/report.js.map +1 -0
  127. package/package.json +60 -0
@@ -0,0 +1,194 @@
1
+ // The gates that run their tool inside Docker. A Payload project already needs Docker for its database,
2
+ // so this costs nothing extra and makes the gates behave identically on every machine: no local install
3
+ // of gitleaks, hadolint, or actionlint, and no version skew between developers and CI.
4
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
5
+ import { homedir } from 'node:os';
6
+ import path from 'node:path';
7
+ import { CONTAINER_IMAGES, classifyContainerExit, classifyImageFailure, composeProjectsIn, dockerfilesIn, renderGitleaksConfig, } from '@ploaness/governance';
8
+ import { trackedFiles } from '../context.js';
9
+ import { asFindings, failed, fromRun, passed, run, } from '../exec.js';
10
+ // Pinned by digest in the governance layer, where a spec rejects a mutable reference. These were three
11
+ // `:latest` literals, which let an upstream release change a verdict without the repository changing.
12
+ const GITLEAKS_IMAGE = CONTAINER_IMAGES.gitleaks;
13
+ const HADOLINT_IMAGE = CONTAINER_IMAGES.hadolint;
14
+ const ACTIONLINT_IMAGE = CONTAINER_IMAGES.actionlint;
15
+ const describeFailure = (failure) => failed(failure.summary, failure.remedies);
16
+ // The image is acquired as a step of its own, BEFORE any analyzer runs, and that ordering is the repair
17
+ // rather than an optimisation. It puts "the analyzer could not be obtained" on a command whose output
18
+ // docker wrote in full, so the failure can be read honestly; leaving the pull implicit in `docker run`
19
+ // left one exit code carrying two questions, and a rate-limited pull answered the wrong one - the secret
20
+ // scan reported a secret in the git history because gitleaks had never started.
21
+ //
22
+ // `docker image inspect` is local and costs nothing on a machine that has already pulled, which is every
23
+ // machine after the first run.
24
+ const acquireImage = (context, image, gate) => {
25
+ const present = run('docker', ['image', 'inspect', '--format', '{{.Id}}', image], {
26
+ cwd: context.root,
27
+ });
28
+ if (present.code === 0) {
29
+ return undefined;
30
+ }
31
+ const pulled = run('docker', ['pull', image], { cwd: context.root });
32
+ const failure = classifyImageFailure(gate, pulled);
33
+ return failure === undefined ? undefined : describeFailure(failure);
34
+ };
35
+ // Asked only when a run failed, and answered by docker rather than by the analyzer's output. The reserved
36
+ // exit codes settle it outright; otherwise the question is whether docker is STILL well, which closes the
37
+ // narrow window where the daemon dies between the pull and the run without letting a commit message the
38
+ // scanner quoted decide whether a finding is real.
39
+ const dockerFault = (context, image, gate, result) => {
40
+ if (result.code === 0) {
41
+ return undefined;
42
+ }
43
+ const reserved = classifyContainerExit(gate, result);
44
+ return reserved === undefined ? acquireImage(context, image, gate) : describeFailure(reserved);
45
+ };
46
+ // The scanner's configuration is rendered outside the working tree and mounted read-only. A copy in the
47
+ // tree is a forbidden path, because it could shadow or weaken the tool's own rules; rendering it here
48
+ // means the project supplies data - which fixture credential, and why - while ploaness keeps the rules.
49
+ //
50
+ // Rendered under the home directory rather than the system temporary directory: a macOS Docker daemon
51
+ // shares the home directory and need not share /tmp, and an unshared source mounts as an empty
52
+ // directory rather than as an error. `it/verify.sh` records the same constraint for the same reason.
53
+ const withRenderedConfig = (context, use) => {
54
+ const directory = mkdtempSync(path.join(homedir(), '.ploaness-secrets-'));
55
+ try {
56
+ writeFileSync(path.join(directory, 'gitleaks.toml'), renderGitleaksConfig(context.settings.secretAllowlist));
57
+ return use(directory);
58
+ }
59
+ finally {
60
+ rmSync(directory, { recursive: true, force: true });
61
+ }
62
+ };
63
+ const scanSecrets = (context, configDirectory, target) => run('docker', [
64
+ 'run',
65
+ '--rm',
66
+ '-v',
67
+ `${context.root}:/repo`,
68
+ '-v',
69
+ `${configDirectory}:/ploaness:ro`,
70
+ GITLEAKS_IMAGE,
71
+ target,
72
+ '/repo',
73
+ '--config',
74
+ '/ploaness/gitleaks.toml',
75
+ '--no-banner',
76
+ '--redact',
77
+ ], { cwd: context.root });
78
+ /** Scan the commit history for committed secrets. */
79
+ export const secrets = (context) => acquireImage(context, GITLEAKS_IMAGE, 'the secret scan') ??
80
+ withRenderedConfig(context, (configDirectory) => {
81
+ // `git` mode, not `dir`. The standard asks for the tracked content and the commit history, and
82
+ // history mode covers both: every tracked file's content is in some commit. `dir` mode has no git
83
+ // awareness at all - it reads `node_modules`, the build output, and a local `.env`, none of which
84
+ // the repository tracks or owns. On a real Payload project that was 1.09 GB against 2 MB, sixty
85
+ // times slower, and every finding it added came from a dependency rather than from this project.
86
+ const history = scanSecrets(context, configDirectory, 'git');
87
+ return (dockerFault(context, GITLEAKS_IMAGE, 'the secret scan', history) ??
88
+ fromRun(history, 'no secret found in the git history', 'the scanner found a secret in the git history'));
89
+ });
90
+ // Both kinds are discovered from the tracked tree, by the rules in `governance`. The compose half used to
91
+ // look at the repository root alone, so a project keeping its application - and its compose file - in a
92
+ // member directory had that file validated by nothing, while the Dockerfile beside it was linted.
93
+ const dockerfiles = (context) => dockerfilesIn(trackedFiles(context.root));
94
+ const composeProjects = (context) => composeProjectsIn(trackedFiles(context.root));
95
+ // Compose ships both as a `docker` subcommand and as a standalone binary, and which one a machine has is
96
+ // not a property of the project. Try the modern form first and accept the legacy one, failing only when
97
+ // neither can validate the file.
98
+ //
99
+ // Run from the project's own directory rather than from the repository root, because that is what decides
100
+ // what compose reads: the override files beside it, the `.env` it interpolates from, and the build
101
+ // contexts its relative paths name.
102
+ const validateCompose = (directory) => {
103
+ const modern = run('sh', ['-c', 'docker compose config > /dev/null'], {
104
+ cwd: directory,
105
+ });
106
+ return modern.code === 0
107
+ ? modern
108
+ : run('sh', ['-c', 'docker-compose config > /dev/null'], { cwd: directory });
109
+ };
110
+ const validateComposeProjects = (context, projects) => projects.map((project) => ({
111
+ project,
112
+ result: validateCompose(path.join(context.root, project.directory)),
113
+ }));
114
+ const CONTAINER_GATE = 'the container gate';
115
+ const firstReserved = (results) => {
116
+ const reserved = results
117
+ .map((result) => classifyContainerExit(CONTAINER_GATE, result))
118
+ .find((entry) => entry !== undefined);
119
+ return reserved === undefined ? undefined : describeFailure(reserved);
120
+ };
121
+ const lintResults = (linted) => linted.map((entry) => entry.result);
122
+ // The file is fed on stdin through the argv form rather than through a shell redirection. It used to be
123
+ // interpolated into an `sh -c` string with `JSON.stringify` around it, which is JSON quoting and not
124
+ // shell quoting: inside double quotes `sh` still expands `$`, a backtick, and a backslash, so a tracked
125
+ // file named `Dockerfile.$(...)` ran its own contents on every verification.
126
+ const lintDockerfile = (context, target) => run('docker', ['run', '--rm', '-i', HADOLINT_IMAGE], {
127
+ cwd: context.root,
128
+ input: readFileSync(path.join(context.root, target), 'utf8'),
129
+ });
130
+ // Compose is judged on its exit code alone: it needs no analyzer image, so there is nothing to re-check
131
+ // and its output quotes the project's own YAML. The Dockerfile half asks the further question, once for
132
+ // the whole run rather than once per file - the answer cannot differ between two files linted seconds
133
+ // apart, and asking per file would re-pull an image on every genuine finding.
134
+ const containerFault = (context, linted, validated) => firstReserved([
135
+ ...lintResults(linted),
136
+ ...validated.map((entry) => entry.result),
137
+ ]) ??
138
+ (lintResults(linted).some((result) => result.code !== 0)
139
+ ? acquireImage(context, HADOLINT_IMAGE, CONTAINER_GATE)
140
+ : undefined);
141
+ // What the gate actually looked at, so a pass never claims more than it checked. The summary read
142
+ // "N Dockerfile(s) and the compose file are valid" whether or not a compose file existed.
143
+ const describeTargets = (dockerfileCount, composeCount) => {
144
+ const parts = [
145
+ ...(dockerfileCount > 0 ? [`${String(dockerfileCount)} Dockerfile(s)`] : []),
146
+ ...(composeCount > 0 ? [`${String(composeCount)} compose project(s)`] : []),
147
+ ];
148
+ return parts.length === 0
149
+ ? 'the project ships no container definition'
150
+ : `${parts.join(' and ')} are valid`;
151
+ };
152
+ /** Lint every Dockerfile and validate every compose project. */
153
+ export const containers = (context) => {
154
+ const targets = dockerfiles(context);
155
+ const projects = composeProjects(context);
156
+ // A project whose database comes from compose and whose app is built by Next ships no Dockerfile at
157
+ // all - the common Payload layout. Returning here on that count alone meant its compose file was
158
+ // never validated, and the gate reported a pass having read nothing.
159
+ if (projects.length === 0 && targets.length === 0) {
160
+ return passed('the project ships no container definition');
161
+ }
162
+ const unavailable = targets.length > 0 ? acquireImage(context, HADOLINT_IMAGE, CONTAINER_GATE) : undefined;
163
+ if (unavailable !== undefined) {
164
+ return unavailable;
165
+ }
166
+ // Run every tool first, then judge.
167
+ const linted = targets.map((target) => ({ target, result: lintDockerfile(context, target) }));
168
+ const validated = validateComposeProjects(context, projects);
169
+ const faulted = containerFault(context, linted, validated);
170
+ if (faulted !== undefined) {
171
+ return faulted;
172
+ }
173
+ const findings = [
174
+ ...linted.flatMap((entry) => entry.result.code === 0 ? [] : [`${entry.target}:`, ...asFindings(entry.result.output)]),
175
+ ...validated.flatMap((entry) => entry.result.code === 0 ? [] : [`${entry.project.file}:`, ...asFindings(entry.result.output)]),
176
+ ];
177
+ return findings.length > 0
178
+ ? failed('container definitions have defects', findings)
179
+ : passed(describeTargets(targets.length, projects.length));
180
+ };
181
+ /** Lint the GitHub Actions workflows. */
182
+ export const actions = (context) => {
183
+ if (!existsSync(path.join(context.root, '.github', 'workflows'))) {
184
+ return passed('the project ships no workflows');
185
+ }
186
+ const unavailable = acquireImage(context, ACTIONLINT_IMAGE, 'the workflow gate');
187
+ if (unavailable !== undefined) {
188
+ return unavailable;
189
+ }
190
+ const result = run('docker', ['run', '--rm', '-v', `${context.root}:/repo`, '--workdir', '/repo', ACTIONLINT_IMAGE], { cwd: context.root });
191
+ return (dockerFault(context, ACTIONLINT_IMAGE, 'the workflow gate', result) ??
192
+ fromRun(result, 'workflows pass actionlint', 'a workflow does not pass actionlint'));
193
+ };
194
+ //# sourceMappingURL=containers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containers.js","sourceRoot":"","sources":["../../src/checks/containers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type Context } from '../context.js';
2
+ import { type GateResult } from '../exec.js';
3
+ /**
4
+ * Scan every tracked file for banned typography, stray hand-written JavaScript, and documenting
5
+ * comments left above another comment rather than above what they document.
6
+ */
7
+ export declare const conventions: (context: Context) => GateResult;
8
+ //# sourceMappingURL=conventions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conventions.d.ts","sourceRoot":"","sources":["../../src/checks/conventions.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAU,KAAK,UAAU,EAAU,MAAM,YAAY,CAAA;AAqF5D;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,OAAO,KAAG,UAY9C,CAAA"}
@@ -0,0 +1,77 @@
1
+ // Source conventions: the AI-typography ban and the preference for TypeScript over hand-written
2
+ // JavaScript. Both are scanned across every tracked file rather than a chosen subtree, because the
3
+ // characters a model emits appear in documentation and configuration as readily as in code.
4
+ import { existsSync, readFileSync, statSync } from 'node:fs';
5
+ import path from 'node:path';
6
+ import { DOCUMENTED_EXTENSIONS, findOrphanedDocBlocks, findTypographyViolations, hasExtension, isBinary, matchesRole, } from '@ploaness/governance';
7
+ import { trackedFiles } from '../context.js';
8
+ import { failed, passed } from '../exec.js';
9
+ // The typography ban used to carry an allowlist of ten extensions here, which is the wrong shape for a
10
+ // rule that reaches "every tracked file the repository does not exclude by file role": `.css`, `.adoc`,
11
+ // a shell script, and a Dockerfile all went unscanned, and every new text format arrived unscanned
12
+ // until someone remembered this list. The role predicate is default-safe in the other direction - a
13
+ // binary asset is recognised from its own bytes, and everything else is text that gets scanned.
14
+ const JAVASCRIPT_EXTENSIONS = ['.js', '.mjs', '.cjs'];
15
+ // Regions a tool rewrites byte for byte on every run, so a local edit is reverted rather than kept and
16
+ // the ban has nothing to enforce against. `next dev` upserts its agent-rules block into AGENTS.md
17
+ // whenever it detects an AI agent, em dashes included. Only the span between the markers is skipped;
18
+ // every line the project itself authors in the same file is still scanned.
19
+ const VENDOR_MANAGED_REGIONS = [
20
+ /<!-- BEGIN:nextjs-agent-rules -->.*?<!-- END:nextjs-agent-rules -->/gs,
21
+ ];
22
+ // Blank a managed region to spaces rather than delete it, so the line and column numbers reported for
23
+ // the rest of the file still point at real source positions.
24
+ const blankVendorRegions = (text) => VENDOR_MANAGED_REGIONS.reduce((content, region) => content.replaceAll(region, (match) => match.replaceAll(/[^\n]/g, ' ')), text);
25
+ const typographyFindings = (context, tracked) => tracked
26
+ .filter((file) => !matchesRole(file, context.settings.typographyExclusions))
27
+ .flatMap((file) => {
28
+ const bytes = readFileSync(path.join(context.root, file));
29
+ if (isBinary(bytes)) {
30
+ return [];
31
+ }
32
+ const content = blankVendorRegions(bytes.toString('utf8'));
33
+ return findTypographyViolations(content).map((violation) => `${file}:${String(violation.line)}:${String(violation.column)} ` +
34
+ `banned ${violation.label}; use ${violation.replacement}`);
35
+ });
36
+ const javascriptFindings = (context, tracked) => tracked
37
+ .filter((file) => hasExtension(file, JAVASCRIPT_EXTENSIONS) &&
38
+ !matchesRole(file, context.settings.javascriptAllowlist))
39
+ .map((file) => `${file} hand-written JavaScript is banned; write TypeScript instead`);
40
+ // A documenting comment stranded above another one documents nothing, and the symbol it was written
41
+ // for is left with no doc at all. It is scanned here rather than by the lint pass because
42
+ // eslint-plugin-jsdoc structurally cannot see it: every rule that plugin ships visits the block
43
+ // ATTACHED to a syntax node, and the parser hands a declaration only the LAST block before it.
44
+ //
45
+ // The role exclusions are the ones `isGovernedCode` already reads, which is how the suppressions gate
46
+ // scopes the same question: a generated file carries comments its generator wrote, and a project
47
+ // cannot be asked to repair them.
48
+ const orphanedDocFindings = (context, tracked) => tracked
49
+ .filter((file) => hasExtension(file, DOCUMENTED_EXTENSIONS) &&
50
+ !matchesRole(file, context.settings.typographyExclusions))
51
+ .flatMap((file) => {
52
+ const content = readFileSync(path.join(context.root, file), 'utf8');
53
+ return findOrphanedDocBlocks(content).map((block) => `${file}:${String(block.line)} the doc block ending on line ${String(block.endLine)} ` +
54
+ `is followed by another doc block rather than by what it documents`);
55
+ });
56
+ // A tracked path is not always a regular file. `git ls-files` reports a symlink and a submodule
57
+ // gitlink too, and reading either throws rather than yielding text.
58
+ const isRegularFile = (root, file) => {
59
+ const full = path.join(root, file);
60
+ return existsSync(full) && statSync(full).isFile();
61
+ };
62
+ /**
63
+ * Scan every tracked file for banned typography, stray hand-written JavaScript, and documenting
64
+ * comments left above another comment rather than above what they document.
65
+ */
66
+ export const conventions = (context) => {
67
+ const tracked = trackedFiles(context.root).filter((file) => isRegularFile(context.root, file));
68
+ const findings = [
69
+ ...typographyFindings(context, tracked),
70
+ ...javascriptFindings(context, tracked),
71
+ ...orphanedDocFindings(context, tracked),
72
+ ];
73
+ return findings.length > 0
74
+ ? failed(`${String(findings.length)} convention violation(s)`, findings)
75
+ : passed(`${String(tracked.length)} tracked file(s) follow the source conventions`);
76
+ };
77
+ //# sourceMappingURL=conventions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../src/checks/conventions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type Context } from '../context.js';
2
+ import { type GateResult } from '../exec.js';
3
+ export declare const licenses: (context: Context) => GateResult;
4
+ export declare const dependencyFreshness: (context: Context) => Promise<GateResult>;
5
+ /**
6
+ * Read every package in the resolved set against the public advisory database.
7
+ * @param context the resolved project environment.
8
+ * @returns a failure for any finding at or above the declared severity, or for a stale exception.
9
+ */
10
+ export declare const vulnerabilities: (context: Context) => GateResult;
11
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/checks/dependencies.ts"],"names":[],"mappings":"AAoCA,OAAO,EAAE,KAAK,OAAO,EAA4C,MAAM,eAAe,CAAA;AACtF,OAAO,EAEL,KAAK,UAAU,EAMhB,MAAM,YAAY,CAAA;AAgBnB,eAAO,MAAM,QAAQ,GAAI,SAAS,OAAO,KAAG,UAkC3C,CAAA;AAgVD,eAAO,MAAM,mBAAmB,GAAU,SAAS,OAAO,KAAG,OAAO,CAAC,UAAU,CA+C9E,CAAA;AA6CD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,KAAG,UAiDlD,CAAA"}