@codefast/cli 0.9.0 → 0.11.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 (279) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +345 -151
  3. package/dist/arrange/command.d.ts +7 -0
  4. package/dist/arrange/command.js +96 -132
  5. package/dist/arrange/domain/ast/ast-node.d.ts +394 -0
  6. package/dist/arrange/domain/ast/collectors-cn.d.ts +26 -0
  7. package/dist/arrange/domain/ast/collectors-jsx.d.ts +8 -0
  8. package/dist/arrange/domain/ast/collectors-tv.d.ts +34 -0
  9. package/dist/arrange/domain/ast/helpers.d.ts +36 -0
  10. package/dist/arrange/domain/ast/helpers.js +1 -0
  11. package/dist/arrange/domain/ast/simplify-targets.d.ts +22 -0
  12. package/dist/arrange/domain/ast/simplify-targets.js +18 -23
  13. package/dist/arrange/domain/ast/targets.d.ts +20 -0
  14. package/dist/arrange/domain/ast/translator.d.ts +32 -0
  15. package/dist/arrange/{typescript-ast-translator.js → domain/ast/translator.js} +19 -22
  16. package/dist/arrange/domain/constants.d.ts +111 -0
  17. package/dist/arrange/domain/grouping-service.d.ts +100 -0
  18. package/dist/arrange/domain/grouping.d.ts +21 -0
  19. package/dist/arrange/domain/imports.d.ts +14 -0
  20. package/dist/arrange/domain/source-text-formatters.d.ts +33 -0
  21. package/dist/arrange/domain/tailwind-token.d.ts +24 -0
  22. package/dist/arrange/domain/token-classifier.d.ts +47 -0
  23. package/dist/arrange/domain/types.d.ts +208 -0
  24. package/dist/arrange/group/cli-result.d.ts +7 -0
  25. package/dist/arrange/group/cli-result.js +12 -0
  26. package/dist/arrange/group/cli-schema.d.ts +17 -0
  27. package/dist/arrange/group/cli-schema.js +13 -0
  28. package/dist/arrange/group/output.d.ts +7 -0
  29. package/dist/arrange/group/output.js +10 -0
  30. package/dist/arrange/group/suggest.d.ts +8 -0
  31. package/dist/arrange/inspect/cli-result.d.ts +7 -0
  32. package/dist/arrange/inspect/cli-result.js +8 -0
  33. package/dist/arrange/inspect/cli-schema.d.ts +15 -0
  34. package/dist/arrange/inspect/cli-schema.js +9 -0
  35. package/dist/arrange/inspect/domain/analyze-service.d.ts +18 -0
  36. package/dist/arrange/inspect/output.d.ts +7 -0
  37. package/dist/arrange/inspect/output.js +42 -0
  38. package/dist/arrange/inspect/run.d.ts +10 -0
  39. package/dist/arrange/{analyze.js → inspect/run.js} +2 -2
  40. package/dist/arrange/prepare.d.ts +13 -0
  41. package/dist/arrange/{workspace.js → prepare.js} +5 -8
  42. package/dist/arrange/regroup/cli-result.d.ts +13 -0
  43. package/dist/arrange/regroup/cli-result.js +23 -0
  44. package/dist/arrange/regroup/cli-schema.d.ts +20 -0
  45. package/dist/arrange/regroup/cli-schema.js +14 -0
  46. package/dist/arrange/regroup/output.d.ts +14 -0
  47. package/dist/arrange/regroup/output.js +72 -0
  48. package/dist/arrange/regroup/process-file.d.ts +11 -0
  49. package/dist/arrange/regroup/run.d.ts +11 -0
  50. package/dist/arrange/{sync.js → regroup/run.js} +2 -2
  51. package/dist/arrange/resolve-target.d.ts +10 -0
  52. package/dist/arrange/resolve-target.js +3 -16
  53. package/dist/arrange/scan-target.d.ts +7 -0
  54. package/dist/arrange/simplify/cli-result.d.ts +7 -0
  55. package/dist/arrange/simplify/cli-result.js +8 -0
  56. package/dist/arrange/simplify/cli-schema.d.ts +17 -0
  57. package/dist/arrange/simplify/cli-schema.js +11 -0
  58. package/dist/arrange/simplify/fold-targets.d.ts +13 -0
  59. package/dist/arrange/simplify/fold-targets.js +139 -0
  60. package/dist/arrange/simplify/output.d.ts +7 -0
  61. package/dist/arrange/simplify/output.js +15 -0
  62. package/dist/arrange/simplify/process-file.d.ts +13 -0
  63. package/dist/arrange/simplify/process-file.js +49 -0
  64. package/dist/arrange/simplify/run.d.ts +14 -0
  65. package/dist/arrange/simplify/run.js +38 -0
  66. package/dist/arrange/simplify/variant-classname-probe.d.ts +35 -0
  67. package/dist/arrange/simplify/variant-classname-probe.js +95 -0
  68. package/dist/arrange/source-parse.d.ts +7 -0
  69. package/dist/arrange/source-parse.js +1 -1
  70. package/dist/audit/command.d.ts +8 -0
  71. package/dist/audit/command.js +134 -211
  72. package/dist/audit/comments/cli-result.d.ts +13 -0
  73. package/dist/audit/comments/cli-result.js +22 -0
  74. package/dist/audit/comments/cli-schema.d.ts +19 -0
  75. package/dist/audit/comments/cli-schema.js +13 -0
  76. package/dist/audit/comments/domain/comment-content.d.ts +26 -0
  77. package/dist/audit/comments/domain/comment-dividers.d.ts +62 -0
  78. package/dist/audit/comments/domain/link-references.d.ts +40 -0
  79. package/dist/audit/comments/domain/since-versions.d.ts +26 -0
  80. package/dist/audit/comments/domain/tsdoc-syntax.d.ts +20 -0
  81. package/dist/audit/comments/output.d.ts +7 -0
  82. package/dist/audit/comments/output.js +27 -0
  83. package/dist/audit/comments/prepare.d.ts +16 -0
  84. package/dist/audit/comments/prepare.js +12 -0
  85. package/dist/audit/comments/run.d.ts +17 -0
  86. package/dist/audit/{run-comments.js → comments/run.js} +5 -5
  87. package/dist/audit/display-names/cli-result.d.ts +13 -0
  88. package/dist/audit/display-names/cli-result.js +22 -0
  89. package/dist/audit/display-names/cli-schema.d.ts +18 -0
  90. package/dist/audit/display-names/cli-schema.js +12 -0
  91. package/dist/audit/display-names/domain/display-names.d.ts +11 -0
  92. package/dist/audit/display-names/output.d.ts +7 -0
  93. package/dist/audit/display-names/output.js +21 -0
  94. package/dist/audit/display-names/prepare.d.ts +16 -0
  95. package/dist/audit/display-names/prepare.js +12 -0
  96. package/dist/audit/display-names/run.d.ts +14 -0
  97. package/dist/audit/{run-display-names.js → display-names/run.js} +1 -1
  98. package/dist/audit/domain/types.d.ts +171 -0
  99. package/dist/audit/imports/cli-result.d.ts +13 -0
  100. package/dist/audit/imports/cli-result.js +22 -0
  101. package/dist/audit/imports/cli-schema.d.ts +18 -0
  102. package/dist/audit/imports/cli-schema.js +12 -0
  103. package/dist/audit/imports/domain/import-policy.d.ts +34 -0
  104. package/dist/audit/imports/domain/import-policy.js +140 -0
  105. package/dist/audit/imports/output.d.ts +7 -0
  106. package/dist/audit/imports/output.js +21 -0
  107. package/dist/audit/imports/prepare.d.ts +16 -0
  108. package/dist/audit/imports/prepare.js +12 -0
  109. package/dist/audit/imports/run.d.ts +14 -0
  110. package/dist/audit/{run-react.js → imports/run.js} +15 -5
  111. package/dist/audit/links/cli-result.d.ts +13 -0
  112. package/dist/audit/links/cli-result.js +22 -0
  113. package/dist/audit/links/cli-schema.d.ts +18 -0
  114. package/dist/audit/links/cli-schema.js +12 -0
  115. package/dist/audit/links/domain/markdown-links.d.ts +44 -0
  116. package/dist/audit/links/output.d.ts +7 -0
  117. package/dist/audit/links/output.js +21 -0
  118. package/dist/audit/links/prepare.d.ts +16 -0
  119. package/dist/audit/links/prepare.js +12 -0
  120. package/dist/audit/links/run.d.ts +14 -0
  121. package/dist/audit/{run-links.js → links/run.js} +1 -1
  122. package/dist/audit/prepare.d.ts +31 -0
  123. package/dist/audit/prepare.js +11 -134
  124. package/dist/audit/rtl/cli-result.d.ts +13 -0
  125. package/dist/audit/rtl/cli-result.js +22 -0
  126. package/dist/audit/rtl/cli-schema.d.ts +18 -0
  127. package/dist/audit/rtl/cli-schema.js +12 -0
  128. package/dist/audit/rtl/domain/audit-file.d.ts +7 -0
  129. package/dist/audit/{domain → rtl/domain}/audit-file.js +2 -2
  130. package/dist/audit/rtl/domain/mappings.d.ts +45 -0
  131. package/dist/audit/rtl/domain/tokenize.d.ts +14 -0
  132. package/dist/audit/rtl/output.d.ts +7 -0
  133. package/dist/audit/rtl/output.js +21 -0
  134. package/dist/audit/rtl/prepare.d.ts +13 -0
  135. package/dist/audit/rtl/prepare.js +41 -0
  136. package/dist/audit/rtl/run.d.ts +14 -0
  137. package/dist/audit/{run.js → rtl/run.js} +1 -1
  138. package/dist/bin.d.ts +2 -0
  139. package/dist/cli.d.ts +6 -0
  140. package/dist/core/cli/command-pipeline.d.ts +91 -0
  141. package/dist/core/cli/command-pipeline.js +83 -0
  142. package/dist/core/cli/format-error.d.ts +7 -0
  143. package/dist/core/cli/global-options.d.ts +15 -0
  144. package/dist/core/cli/global-options.js +1 -1
  145. package/dist/core/cli/positional.d.ts +6 -0
  146. package/dist/core/cli/resolve-root.d.ts +9 -0
  147. package/dist/core/cli/resolve-root.js +16 -0
  148. package/dist/core/cli/result-handle.d.ts +13 -0
  149. package/dist/core/cli/result-handle.js +0 -13
  150. package/dist/core/config/define-config.d.ts +7 -0
  151. package/dist/core/config/define-config.js +8 -0
  152. package/dist/core/config/loader.d.ts +18 -0
  153. package/dist/core/config/loader.js +2 -7
  154. package/dist/core/config/schema.d.ts +99 -0
  155. package/dist/core/config/schema.js +8 -86
  156. package/dist/core/config/warnings.d.ts +6 -0
  157. package/dist/core/config.d.ts +12 -0
  158. package/dist/core/errors.d.ts +25 -0
  159. package/dist/core/exit-codes.d.ts +18 -0
  160. package/dist/core/filesystem/filesystem.d.ts +44 -0
  161. package/dist/core/filesystem/node.d.ts +7 -0
  162. package/dist/core/filesystem/node.js +2 -1
  163. package/dist/core/glob.d.ts +19 -0
  164. package/dist/core/logger.d.ts +9 -0
  165. package/dist/core/result.d.ts +30 -0
  166. package/dist/core/schema-parse.d.ts +9 -0
  167. package/dist/core/source-text-edit.d.ts +47 -0
  168. package/dist/core/source-text-edit.js +22 -0
  169. package/dist/core/verbose-diagnostics.d.ts +6 -0
  170. package/dist/core/workspace/ancestor-directories.d.ts +12 -0
  171. package/dist/core/workspace/ancestor-directories.js +30 -0
  172. package/dist/core/workspace/markdown-walk.d.ts +7 -0
  173. package/dist/core/workspace/markdown-walk.js +2 -20
  174. package/dist/core/workspace/package-version.d.ts +9 -0
  175. package/dist/core/workspace/package-version.js +8 -12
  176. package/dist/core/workspace/resolver.d.ts +39 -0
  177. package/dist/core/workspace/resolver.js +58 -75
  178. package/dist/core/workspace/skip-directories.d.ts +6 -0
  179. package/dist/core/workspace/source-walk.d.ts +16 -0
  180. package/dist/core/workspace/source-walk.js +2 -19
  181. package/dist/core/workspace/typescript-walk.d.ts +7 -0
  182. package/dist/core/workspace/typescript-walk.js +2 -23
  183. package/dist/core/workspace/walk-files.d.ts +7 -0
  184. package/dist/core/workspace/walk-files.js +27 -0
  185. package/dist/core/workspace/well-known-files.d.ts +18 -0
  186. package/dist/core/workspace/well-known-files.js +18 -0
  187. package/dist/index.d.ts +6 -0
  188. package/dist/index.js +5 -0
  189. package/dist/mirror/cli-result.d.ts +13 -0
  190. package/dist/mirror/cli-schema.d.ts +8 -0
  191. package/dist/mirror/cli-schema.js +1 -1
  192. package/dist/mirror/command.d.ts +7 -0
  193. package/dist/mirror/command.js +31 -60
  194. package/dist/mirror/dist-filesystem-node.d.ts +8 -0
  195. package/dist/mirror/{dist-filesystem-impl.js → dist-filesystem-node.js} +1 -1
  196. package/dist/mirror/domain/constants.d.ts +18 -0
  197. package/dist/mirror/domain/constants.js +0 -12
  198. package/dist/mirror/domain/dirent-guard.d.ts +10 -0
  199. package/dist/mirror/domain/dist-filesystem.d.ts +9 -0
  200. package/dist/mirror/domain/errors.d.ts +24 -0
  201. package/dist/mirror/domain/exports.d.ts +36 -0
  202. package/dist/mirror/domain/package-display-name.d.ts +8 -0
  203. package/dist/mirror/domain/path-normalizer.d.ts +6 -0
  204. package/dist/mirror/domain/types.d.ts +188 -0
  205. package/dist/mirror/output.d.ts +21 -0
  206. package/dist/mirror/output.js +126 -1
  207. package/dist/mirror/package-path.d.ts +19 -0
  208. package/dist/mirror/prepare.d.ts +15 -0
  209. package/dist/mirror/prepare.js +6 -10
  210. package/dist/mirror/run.d.ts +12 -0
  211. package/dist/mirror/{sync.js → run.js} +5 -3
  212. package/dist/mirror/supplement-exports.d.ts +27 -0
  213. package/dist/mirror/supplement-exports.js +2 -2
  214. package/dist/mirror/sync-workspace-package.d.ts +9 -0
  215. package/dist/mirror/sync-workspace-package.js +4 -4
  216. package/dist/mirror/write-exports.d.ts +15 -0
  217. package/dist/pack-slim/cli-result.d.ts +13 -0
  218. package/dist/pack-slim/cli-schema.d.ts +17 -0
  219. package/dist/pack-slim/cli-schema.js +1 -1
  220. package/dist/pack-slim/command.d.ts +7 -0
  221. package/dist/pack-slim/command.js +31 -66
  222. package/dist/pack-slim/domain/transform.d.ts +69 -0
  223. package/dist/pack-slim/domain/types.d.ts +46 -0
  224. package/dist/pack-slim/output.d.ts +15 -0
  225. package/dist/pack-slim/prepare.d.ts +21 -0
  226. package/dist/pack-slim/prepare.js +14 -0
  227. package/dist/pack-slim/run.d.ts +23 -0
  228. package/dist/pack-slim/{sync.js → run.js} +4 -4
  229. package/dist/pack-slim/working-tree.d.ts +20 -0
  230. package/dist/tag/cli-result.d.ts +13 -0
  231. package/dist/tag/cli-result.js +14 -1
  232. package/dist/tag/cli-schema.d.ts +8 -0
  233. package/dist/tag/cli-schema.js +3 -4
  234. package/dist/tag/command.d.ts +7 -0
  235. package/dist/tag/command.js +33 -60
  236. package/dist/tag/domain/skip-filter.d.ts +13 -0
  237. package/dist/tag/domain/skip-filter.js +29 -0
  238. package/dist/tag/domain/types.d.ts +131 -0
  239. package/dist/tag/domain/version-summary.d.ts +13 -0
  240. package/dist/tag/domain/version-summary.js +24 -0
  241. package/dist/tag/output.d.ts +17 -0
  242. package/dist/tag/output.js +6 -9
  243. package/dist/tag/prepare.d.ts +13 -0
  244. package/dist/tag/prepare.js +4 -4
  245. package/dist/tag/run.d.ts +10 -0
  246. package/dist/tag/{sync.js → run.js} +20 -50
  247. package/dist/tag/target/candidates.d.ts +8 -0
  248. package/dist/tag/{target-candidates.js → target/candidates.js} +2 -2
  249. package/dist/tag/target/resolve-path.d.ts +10 -0
  250. package/dist/tag/target/runner.d.ts +8 -0
  251. package/dist/tag/{target-runner.js → target/runner.js} +2 -2
  252. package/dist/tag/writer/since-writer.d.ts +32 -0
  253. package/dist/tag/writer/version-resolver.d.ts +7 -0
  254. package/package.json +21 -2
  255. package/dist/arrange/cli-schema.js +0 -34
  256. package/dist/arrange/output.js +0 -127
  257. package/dist/arrange/simplify-process-file.js +0 -30
  258. package/dist/arrange/simplify-sync.js +0 -30
  259. package/dist/audit/cli-schema.js +0 -66
  260. package/dist/audit/domain/react-imports.js +0 -91
  261. package/dist/audit/output.js +0 -213
  262. package/dist/mirror/sync-reporter.js +0 -124
  263. package/dist/mirror/sync-types.js +0 -1
  264. /package/dist/arrange/{suggest.js → group/suggest.js} +0 -0
  265. /package/dist/arrange/{domain → inspect/domain}/analyze-service.js +0 -0
  266. /package/dist/arrange/{process-file.js → regroup/process-file.js} +0 -0
  267. /package/dist/audit/{domain → comments/domain}/comment-content.js +0 -0
  268. /package/dist/audit/{domain → comments/domain}/comment-dividers.js +0 -0
  269. /package/dist/audit/{domain → comments/domain}/link-references.js +0 -0
  270. /package/dist/audit/{domain → comments/domain}/since-versions.js +0 -0
  271. /package/dist/audit/{domain → comments/domain}/tsdoc-syntax.js +0 -0
  272. /package/dist/audit/{domain → display-names/domain}/display-names.js +0 -0
  273. /package/dist/audit/{domain → links/domain}/markdown-links.js +0 -0
  274. /package/dist/audit/{domain → rtl/domain}/mappings.js +0 -0
  275. /package/dist/audit/{domain → rtl/domain}/tokenize.js +0 -0
  276. /package/dist/core/filesystem/{port.js → filesystem.js} +0 -0
  277. /package/dist/tag/{resolve-target-path.js → target/resolve-path.js} +0 -0
  278. /package/dist/tag/{since-writer.js → writer/since-writer.js} +0 -0
  279. /package/dist/tag/{version-resolver.js → writer/version-resolver.js} +0 -0
@@ -0,0 +1,17 @@
1
+ import type { CommentAuditResult } from "#/audit/domain/types";
2
+ import { AppError } from "#/core/errors";
3
+ import type { Filesystem } from "#/core/filesystem/filesystem";
4
+ import type { Result } from "#/core/result";
5
+ /**
6
+ * Reports every comment off the repo's conventions: divider form (which `fix` rewrites), banned
7
+ * content — document pointers, JSDoc types, tag misuse — `{@link}` targets nothing declares, and
8
+ * every diagnostic the official TSDoc parser raises against a doc block's grammar.
9
+ *
10
+ * @since 0.6.0
11
+ */
12
+ export declare function runCommentAudit(fs: Filesystem, args: {
13
+ readonly rootDir: string;
14
+ readonly targetPath: string;
15
+ readonly allowlist: ReadonlyArray<string>;
16
+ readonly fix: boolean;
17
+ }): Result<CommentAuditResult, AppError>;
@@ -1,9 +1,9 @@
1
1
  import path from "node:path";
2
- import { scanCommentContent } from "#/audit/domain/comment-content";
3
- import { applyCommentDividerFixes, DIVIDER_COLUMN, scanCommentDividers } from "#/audit/domain/comment-dividers";
4
- import { countHeadMentions, isPathLinkTarget, linkTargetHead, scanLinkReferences, } from "#/audit/domain/link-references";
5
- import { scanImpossibleSinceTags } from "#/audit/domain/since-versions";
6
- import { scanTsdocSyntax } from "#/audit/domain/tsdoc-syntax";
2
+ import { scanCommentContent } from "#/audit/comments/domain/comment-content";
3
+ import { applyCommentDividerFixes, DIVIDER_COLUMN, scanCommentDividers, } from "#/audit/comments/domain/comment-dividers";
4
+ import { countHeadMentions, isPathLinkTarget, linkTargetHead, scanLinkReferences, } from "#/audit/comments/domain/link-references";
5
+ import { scanImpossibleSinceTags } from "#/audit/comments/domain/since-versions";
6
+ import { scanTsdocSyntax } from "#/audit/comments/domain/tsdoc-syntax";
7
7
  import { AppError, messageFrom } from "#/core/errors";
8
8
  import { err, ok } from "#/core/result";
9
9
  import { findNearestPackageVersion } from "#/core/workspace/package-version";
@@ -0,0 +1,13 @@
1
+ import type { DisplayNameAuditResult } from "#/audit/domain/types";
2
+ /**
3
+ * Exit `1` when any non-allowlisted display-name violation remains.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export declare function exitCodeForDisplayNameAuditResult(result: DisplayNameAuditResult): number;
8
+ /**
9
+ * Machine-readable display-name summary for `--json`.
10
+ *
11
+ * @since 0.9.0
12
+ */
13
+ export declare function formatDisplayNameAuditJsonOutput(result: DisplayNameAuditResult, rootDir: string): string;
@@ -0,0 +1,22 @@
1
+ import { CLI_EXIT_GENERAL_ERROR, CLI_EXIT_SUCCESS } from "#/core/exit-codes";
2
+ /**
3
+ * Exit `1` when any non-allowlisted display-name violation remains.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export function exitCodeForDisplayNameAuditResult(result) {
8
+ return result.violationCount > 0 ? CLI_EXIT_GENERAL_ERROR : CLI_EXIT_SUCCESS;
9
+ }
10
+ /**
11
+ * Machine-readable display-name summary for `--json`.
12
+ *
13
+ * @since 0.9.0
14
+ */
15
+ export function formatDisplayNameAuditJsonOutput(result, rootDir) {
16
+ return JSON.stringify({
17
+ schemaVersion: 1,
18
+ ok: result.violationCount === 0,
19
+ cwd: rootDir,
20
+ result,
21
+ });
22
+ }
@@ -0,0 +1,18 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * Resolved request for a single display-name audit run.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export type DisplayNameAuditRunRequest = {
8
+ readonly rootDir: string;
9
+ readonly targetPath: string;
10
+ readonly allowlist?: ReadonlyArray<string> | undefined;
11
+ readonly json: boolean;
12
+ };
13
+ /**
14
+ * Zod schema for {@link DisplayNameAuditRunRequest}.
15
+ *
16
+ * @since 0.9.0
17
+ */
18
+ export declare const displayNameAuditRunRequestSchema: z.ZodType<DisplayNameAuditRunRequest>;
@@ -0,0 +1,12 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * Zod schema for {@link DisplayNameAuditRunRequest}.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export const displayNameAuditRunRequestSchema = z.object({
8
+ rootDir: z.string().min(1),
9
+ targetPath: z.string().min(1),
10
+ allowlist: z.array(z.string()).optional(),
11
+ json: z.boolean(),
12
+ });
@@ -0,0 +1,11 @@
1
+ /** The display-name convention: a name is spelled like the TS symbol it stands for, under its owner's namespace. */
2
+ import type { DisplayNameViolation } from "#/audit/domain/types";
3
+ /**
4
+ * Scans one source or markdown text for `token()`, `tag()` and module display names that break the convention.
5
+ *
6
+ * @remarks Runs on markdown as well as TypeScript because a doc sample is what a reader copies:
7
+ * a convention the docs break is not one the docs teach.
8
+ *
9
+ * @since 0.9.0
10
+ */
11
+ export declare function auditDisplayNames(sourceText: string): Array<DisplayNameViolation>;
@@ -0,0 +1,7 @@
1
+ import type { DisplayNameAuditResult } from "#/audit/domain/types";
2
+ /**
3
+ * Human-readable display-name report.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export declare function presentDisplayNameAuditResult(result: DisplayNameAuditResult): void;
@@ -0,0 +1,21 @@
1
+ import { logger } from "#/core/logger";
2
+ /**
3
+ * Human-readable display-name report.
4
+ *
5
+ * @since 0.9.0
6
+ */
7
+ export function presentDisplayNameAuditResult(result) {
8
+ for (const file of result.files) {
9
+ logger.out(`\n${file.relativePath}`);
10
+ for (const { line, raw, reason } of file.violations) {
11
+ logger.out(` ${line}: ${raw} → ${reason}`);
12
+ }
13
+ }
14
+ const allowlistSuffix = result.allowlistedCount > 0 ? ` (${result.allowlistedCount} allowlisted)` : "";
15
+ if (result.violationCount > 0) {
16
+ logger.out(`\n✖ ${result.violationCount} display name(s) off the convention${allowlistSuffix}`);
17
+ }
18
+ else {
19
+ logger.out(`✓ Every token, tag and module display name follows <namespace>:<Name> across ${result.scannedFileCount} file(s)${allowlistSuffix}`);
20
+ }
21
+ }
@@ -0,0 +1,16 @@
1
+ import type { AuditCommandPrelude } from "#/audit/prepare";
2
+ import type { AppError } from "#/core/errors";
3
+ import type { Filesystem } from "#/core/filesystem/filesystem";
4
+ import type { Result } from "#/core/result";
5
+ /**
6
+ * Loads config and resolves the scan target for `audit display-names`.
7
+ *
8
+ * @remarks Defaults to the repo root: a display name collides across packages, so the convention
9
+ * has to hold across them.
10
+ *
11
+ * @since 0.9.0
12
+ */
13
+ export declare function prepareDisplayNameAudit(fs: Filesystem, args: {
14
+ readonly currentWorkingDirectory: string;
15
+ readonly rawTarget: string | undefined;
16
+ }): Promise<Result<AuditCommandPrelude, AppError>>;
@@ -0,0 +1,12 @@
1
+ import { prepareRepoRootAudit } from "#/audit/prepare";
2
+ /**
3
+ * Loads config and resolves the scan target for `audit display-names`.
4
+ *
5
+ * @remarks Defaults to the repo root: a display name collides across packages, so the convention
6
+ * has to hold across them.
7
+ *
8
+ * @since 0.9.0
9
+ */
10
+ export async function prepareDisplayNameAudit(fs, args) {
11
+ return prepareRepoRootAudit(fs, args, (config) => config.audit?.displayNames?.allowlist ?? []);
12
+ }
@@ -0,0 +1,14 @@
1
+ import type { DisplayNameAuditResult } from "#/audit/domain/types";
2
+ import { AppError } from "#/core/errors";
3
+ import type { Filesystem } from "#/core/filesystem/filesystem";
4
+ import type { Result } from "#/core/result";
5
+ /**
6
+ * Scans a target path for `token()`, `tag()` and module display names that break the convention.
7
+ *
8
+ * @since 0.9.0
9
+ */
10
+ export declare function runDisplayNameAudit(fs: Filesystem, args: {
11
+ readonly rootDir: string;
12
+ readonly targetPath: string;
13
+ readonly allowlist: ReadonlyArray<string>;
14
+ }): Result<DisplayNameAuditResult, AppError>;
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { auditDisplayNames } from "#/audit/domain/display-names";
2
+ import { auditDisplayNames } from "#/audit/display-names/domain/display-names";
3
3
  import { AppError, messageFrom } from "#/core/errors";
4
4
  import { err, ok } from "#/core/result";
5
5
  import { walkMarkdownFiles } from "#/core/workspace/markdown-walk";
@@ -0,0 +1,171 @@
1
+ /**
2
+ * A class token parsed from a source string literal, split into variant, value, and modifier.
3
+ *
4
+ * @since 0.5.0-canary.6
5
+ */
6
+ export type RtlClassToken = {
7
+ readonly raw: string;
8
+ readonly token: string;
9
+ readonly variant: string | null;
10
+ readonly value: string;
11
+ readonly modifier: string | null;
12
+ readonly line: number;
13
+ };
14
+ /**
15
+ * A physical class occurrence the RTL audit flags, with its suggested logical replacement.
16
+ *
17
+ * @since 0.5.0-canary.6
18
+ */
19
+ export type RtlViolation = {
20
+ readonly line: number;
21
+ readonly raw: string;
22
+ readonly suggestion: string;
23
+ };
24
+ /**
25
+ * The RTL violations found in one file.
26
+ *
27
+ * @since 0.5.0-canary.6
28
+ */
29
+ export type RtlFileViolations = {
30
+ readonly relativePath: string;
31
+ readonly violations: Array<RtlViolation>;
32
+ };
33
+ /**
34
+ * Outcome of one `audit rtl` run.
35
+ *
36
+ * @since 0.5.0-canary.6
37
+ */
38
+ export type RtlAuditResult = {
39
+ readonly files: Array<RtlFileViolations>;
40
+ readonly violationCount: number;
41
+ readonly allowlistedCount: number;
42
+ readonly scannedFileCount: number;
43
+ };
44
+ /**
45
+ * An import-policy violation: a banned import form (namespace / default / named), or an implicit
46
+ * UMD-global type reference under a name nothing in the file imports.
47
+ *
48
+ * @since 0.10.0
49
+ */
50
+ export type ImportPolicyViolation = {
51
+ readonly line: number;
52
+ /** The offending source text — the import statement or the qualified type name. */
53
+ readonly raw: string;
54
+ readonly reason: string;
55
+ };
56
+ /**
57
+ * The import-policy violations found in one file.
58
+ *
59
+ * @since 0.10.0
60
+ */
61
+ export type ImportPolicyFileViolations = {
62
+ readonly relativePath: string;
63
+ readonly violations: Array<ImportPolicyViolation>;
64
+ };
65
+ /**
66
+ * Outcome of one `audit imports` run.
67
+ *
68
+ * @since 0.10.0
69
+ */
70
+ export type ImportsAuditResult = {
71
+ readonly files: Array<ImportPolicyFileViolations>;
72
+ readonly violationCount: number;
73
+ readonly allowlistedCount: number;
74
+ readonly scannedFileCount: number;
75
+ };
76
+ /**
77
+ * A `token()`, `tag()` or module display name that breaks the display-name convention.
78
+ *
79
+ * @since 0.9.0
80
+ */
81
+ export type DisplayNameViolation = {
82
+ readonly line: number;
83
+ /** The call as written, through its closing quote. */
84
+ readonly raw: string;
85
+ readonly reason: string;
86
+ };
87
+ /**
88
+ * The display-name violations found in one file.
89
+ *
90
+ * @since 0.9.0
91
+ */
92
+ export type DisplayNameFileViolations = {
93
+ readonly relativePath: string;
94
+ readonly violations: Array<DisplayNameViolation>;
95
+ };
96
+ /**
97
+ * Outcome of one `audit display-names` run.
98
+ *
99
+ * @since 0.9.0
100
+ */
101
+ export type DisplayNameAuditResult = {
102
+ readonly files: Array<DisplayNameFileViolations>;
103
+ readonly violationCount: number;
104
+ readonly allowlistedCount: number;
105
+ readonly scannedFileCount: number;
106
+ };
107
+ /**
108
+ * A broken link or anchor found by the link audit.
109
+ *
110
+ * @since 0.5.0
111
+ */
112
+ export type LinkBreakage = {
113
+ readonly line: number;
114
+ /** The link target as written, fragment included. */
115
+ readonly raw: string;
116
+ readonly reason: string;
117
+ };
118
+ /**
119
+ * The link breakages found in one markdown file.
120
+ *
121
+ * @since 0.5.0
122
+ */
123
+ export type LinkFileBreakages = {
124
+ readonly relativePath: string;
125
+ readonly breakages: Array<LinkBreakage>;
126
+ };
127
+ /**
128
+ * Outcome of one `audit links` run.
129
+ *
130
+ * @since 0.5.0
131
+ */
132
+ export type LinkAuditResult = {
133
+ readonly files: Array<LinkFileBreakages>;
134
+ readonly breakageCount: number;
135
+ readonly allowlistedCount: number;
136
+ readonly linkCount: number;
137
+ readonly scannedFileCount: number;
138
+ };
139
+ /**
140
+ * A section divider that does not match the repo's one allowed form. Always `--fix`-able.
141
+ *
142
+ * @since 0.6.0
143
+ */
144
+ export type DividerBreakage = {
145
+ readonly line: number;
146
+ /** The divider's opening line as written. */
147
+ readonly raw: string;
148
+ readonly reason: string;
149
+ };
150
+ /**
151
+ * @see DividerBreakage
152
+ *
153
+ * @since 0.6.0
154
+ */
155
+ export type DividerFileBreakages = {
156
+ readonly relativePath: string;
157
+ readonly breakages: Array<DividerBreakage>;
158
+ };
159
+ /**
160
+ * Outcome of one `audit comments` run. `fixedCount` stays `0` unless `--fix` was passed.
161
+ *
162
+ * @since 0.6.0
163
+ */
164
+ export type CommentAuditResult = {
165
+ readonly files: Array<DividerFileBreakages>;
166
+ readonly breakageCount: number;
167
+ readonly allowlistedCount: number;
168
+ readonly fixedCount: number;
169
+ readonly dividerCount: number;
170
+ readonly scannedFileCount: number;
171
+ };
@@ -0,0 +1,13 @@
1
+ import type { ImportsAuditResult } from "#/audit/domain/types";
2
+ /**
3
+ * Exit `1` when any non-allowlisted import-policy violation remains.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export declare function exitCodeForImportsAuditResult(result: ImportsAuditResult): number;
8
+ /**
9
+ * Machine-readable import-policy summary for `--json`.
10
+ *
11
+ * @since 0.10.0
12
+ */
13
+ export declare function formatImportsAuditJsonOutput(result: ImportsAuditResult, rootDir: string): string;
@@ -0,0 +1,22 @@
1
+ import { CLI_EXIT_GENERAL_ERROR, CLI_EXIT_SUCCESS } from "#/core/exit-codes";
2
+ /**
3
+ * Exit `1` when any non-allowlisted import-policy violation remains.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export function exitCodeForImportsAuditResult(result) {
8
+ return result.violationCount > 0 ? CLI_EXIT_GENERAL_ERROR : CLI_EXIT_SUCCESS;
9
+ }
10
+ /**
11
+ * Machine-readable import-policy summary for `--json`.
12
+ *
13
+ * @since 0.10.0
14
+ */
15
+ export function formatImportsAuditJsonOutput(result, rootDir) {
16
+ return JSON.stringify({
17
+ schemaVersion: 1,
18
+ ok: result.violationCount === 0,
19
+ cwd: rootDir,
20
+ result,
21
+ });
22
+ }
@@ -0,0 +1,18 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * Resolved request for a single import-policy audit run.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export type ImportsAuditRunRequest = {
8
+ readonly rootDir: string;
9
+ readonly targetPath: string;
10
+ readonly allowlist?: ReadonlyArray<string> | undefined;
11
+ readonly json: boolean;
12
+ };
13
+ /**
14
+ * Zod schema for {@link ImportsAuditRunRequest}.
15
+ *
16
+ * @since 0.10.0
17
+ */
18
+ export declare const importsAuditRunRequestSchema: z.ZodType<ImportsAuditRunRequest>;
@@ -0,0 +1,12 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * Zod schema for {@link ImportsAuditRunRequest}.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export const importsAuditRunRequestSchema = z.object({
8
+ rootDir: z.string().min(1),
9
+ targetPath: z.string().min(1),
10
+ allowlist: z.array(z.string()).optional(),
11
+ json: z.boolean(),
12
+ });
@@ -0,0 +1,34 @@
1
+ import type { ImportPolicyViolation } from "#/audit/domain/types";
2
+ /**
3
+ * One library's import policy: which forms of importing `module` are banned, optionally limited to
4
+ * files whose repo-relative path matches `scope`, plus an optional UMD-global name to flag when the
5
+ * file references `<name>.*` without importing it.
6
+ *
7
+ * @since 0.10.0
8
+ */
9
+ export interface ImportPolicyRule {
10
+ readonly module: string;
11
+ /** Banned forms: `namespace` (`import * as x`), `default` (`import x`), or `named:<name>`. */
12
+ readonly ban: ReadonlyArray<"namespace" | "default" | `named:${string}`>;
13
+ readonly scope?: ReadonlyArray<string> | undefined;
14
+ readonly umdGlobal?: string | undefined;
15
+ readonly message: string;
16
+ }
17
+ /**
18
+ * The import policies enforced across the monorepo: React members by name (never a namespace,
19
+ * default, or implicit `React.*` UMD global), and Zod as a namespace repo-wide — the house form,
20
+ * so a named `import { z }` never pins Zod's full locale set into a package that ships bundled.
21
+ *
22
+ * @since 0.10.0
23
+ */
24
+ export declare const defaultImportPolicyRules: ReadonlyArray<ImportPolicyRule>;
25
+ /**
26
+ * Scans one TypeScript source against the given import-policy rules and returns the violations.
27
+ *
28
+ * @remarks Each rule matches import declarations from its `module` and flags the banned forms;
29
+ * a rule with `umdGlobal` additionally flags implicit `<name>.*` type references when nothing in
30
+ * the file imports that name (the case tsc accepts silently through a UMD `export as namespace`).
31
+ *
32
+ * @since 0.10.0
33
+ */
34
+ export declare function auditImportPolicySource(filePath: string, sourceText: string, rules: ReadonlyArray<ImportPolicyRule>): Array<ImportPolicyViolation>;
@@ -0,0 +1,140 @@
1
+ import { parseSync } from "oxc-parser";
2
+ /**
3
+ * The import policies enforced across the monorepo: React members by name (never a namespace,
4
+ * default, or implicit `React.*` UMD global), and Zod as a namespace repo-wide — the house form,
5
+ * so a named `import { z }` never pins Zod's full locale set into a package that ships bundled.
6
+ *
7
+ * @since 0.10.0
8
+ */
9
+ export const defaultImportPolicyRules = [
10
+ {
11
+ module: "react",
12
+ ban: ["namespace", "default"],
13
+ umdGlobal: "React",
14
+ message: 'import React members by name from "react"',
15
+ },
16
+ {
17
+ module: "zod",
18
+ ban: ["named:z"],
19
+ message: 'import Zod as a namespace: import * as z from "zod" (repo house form; a named import { z } pins Zod\'s full ' +
20
+ "locale set into any bundle that reaches it)",
21
+ },
22
+ ];
23
+ function isOxcNode(value) {
24
+ return typeof value === "object" && value !== null && typeof value.type === "string";
25
+ }
26
+ function isIdentifierNamed(node, name) {
27
+ return isOxcNode(node) && node.type === "Identifier" && node.name === name;
28
+ }
29
+ function importedName(specifier) {
30
+ const imported = specifier.imported;
31
+ return isOxcNode(imported) && typeof imported.name === "string" ? imported.name : undefined;
32
+ }
33
+ /**
34
+ * Scans one TypeScript source against the given import-policy rules and returns the violations.
35
+ *
36
+ * @remarks Each rule matches import declarations from its `module` and flags the banned forms;
37
+ * a rule with `umdGlobal` additionally flags implicit `<name>.*` type references when nothing in
38
+ * the file imports that name (the case tsc accepts silently through a UMD `export as namespace`).
39
+ *
40
+ * @since 0.10.0
41
+ */
42
+ export function auditImportPolicySource(filePath, sourceText, rules) {
43
+ const { program } = parseSync(filePath, sourceText);
44
+ const statements = program.body;
45
+ const violations = [];
46
+ const boundUmdNames = new Set();
47
+ for (const rule of rules) {
48
+ const bannedNamed = new Set();
49
+ let banNamespace = false;
50
+ let banDefault = false;
51
+ for (const form of rule.ban) {
52
+ if (form === "namespace") {
53
+ banNamespace = true;
54
+ }
55
+ else if (form === "default") {
56
+ banDefault = true;
57
+ }
58
+ else {
59
+ bannedNamed.add(form.slice("named:".length));
60
+ }
61
+ }
62
+ for (const statement of statements) {
63
+ if (statement.type !== "ImportDeclaration") {
64
+ continue;
65
+ }
66
+ const source = statement.source;
67
+ if (!isOxcNode(source) || source.value !== rule.module) {
68
+ continue;
69
+ }
70
+ const specifiers = Array.isArray(statement.specifiers) ? statement.specifiers.filter(isOxcNode) : [];
71
+ const umdGlobal = rule.umdGlobal;
72
+ if (umdGlobal !== undefined && specifiers.some((specifier) => isIdentifierNamed(specifier.local, umdGlobal))) {
73
+ boundUmdNames.add(umdGlobal);
74
+ }
75
+ for (const specifier of specifiers) {
76
+ if (banNamespace && specifier.type === "ImportNamespaceSpecifier") {
77
+ violations.push(violationAt(sourceText, statement, `namespace import of "${rule.module}" — ${rule.message}`));
78
+ }
79
+ else if (banDefault && specifier.type === "ImportDefaultSpecifier") {
80
+ violations.push(violationAt(sourceText, statement, `default import of "${rule.module}" — ${rule.message}`));
81
+ }
82
+ else if (specifier.type === "ImportSpecifier") {
83
+ const name = importedName(specifier);
84
+ if (name !== undefined && bannedNamed.has(name)) {
85
+ violations.push(violationAt(sourceText, statement, `named import { ${name} } from "${rule.module}" — ${rule.message}`));
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
91
+ for (const rule of rules) {
92
+ if (rule.umdGlobal !== undefined && !boundUmdNames.has(rule.umdGlobal)) {
93
+ collectUmdGlobalReferences(program, sourceText, rule, violations);
94
+ }
95
+ }
96
+ violations.sort((a, b) => a.line - b.line);
97
+ return violations;
98
+ }
99
+ function violationAt(sourceText, statement, reason) {
100
+ return {
101
+ line: lineOfOffset(sourceText, statement.start),
102
+ raw: firstLineOf(sourceText.slice(statement.start, statement.end)),
103
+ reason,
104
+ };
105
+ }
106
+ function collectUmdGlobalReferences(node, sourceText, rule, violations) {
107
+ if (node.type === "TSQualifiedName" && isIdentifierNamed(node.left, rule.umdGlobal ?? "")) {
108
+ violations.push({
109
+ line: lineOfOffset(sourceText, node.start),
110
+ raw: sourceText.slice(node.start, node.end),
111
+ reason: `implicit ${rule.umdGlobal}.* UMD global — ${rule.message}`,
112
+ });
113
+ return;
114
+ }
115
+ for (const value of Object.values(node)) {
116
+ if (Array.isArray(value)) {
117
+ for (const item of value) {
118
+ if (isOxcNode(item)) {
119
+ collectUmdGlobalReferences(item, sourceText, rule, violations);
120
+ }
121
+ }
122
+ }
123
+ else if (isOxcNode(value)) {
124
+ collectUmdGlobalReferences(value, sourceText, rule, violations);
125
+ }
126
+ }
127
+ }
128
+ function lineOfOffset(sourceText, offset) {
129
+ let line = 1;
130
+ for (let index = 0; index < offset; index++) {
131
+ if (sourceText.charCodeAt(index) === 10) {
132
+ line++;
133
+ }
134
+ }
135
+ return line;
136
+ }
137
+ function firstLineOf(text) {
138
+ const newlineIndex = text.indexOf("\n");
139
+ return newlineIndex === -1 ? text : text.slice(0, newlineIndex);
140
+ }
@@ -0,0 +1,7 @@
1
+ import type { ImportsAuditResult } from "#/audit/domain/types";
2
+ /**
3
+ * Human-readable import-policy report.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export declare function presentImportsAuditResult(result: ImportsAuditResult): void;
@@ -0,0 +1,21 @@
1
+ import { logger } from "#/core/logger";
2
+ /**
3
+ * Human-readable import-policy report.
4
+ *
5
+ * @since 0.10.0
6
+ */
7
+ export function presentImportsAuditResult(result) {
8
+ for (const file of result.files) {
9
+ logger.out(`\n${file.relativePath}`);
10
+ for (const { line, raw, reason } of file.violations) {
11
+ logger.out(` ${line}: ${raw} → ${reason}`);
12
+ }
13
+ }
14
+ const allowlistSuffix = result.allowlistedCount > 0 ? ` (${result.allowlistedCount} allowlisted)` : "";
15
+ if (result.violationCount > 0) {
16
+ logger.out(`\n✖ ${result.violationCount} import-policy violation(s)${allowlistSuffix}`);
17
+ }
18
+ else {
19
+ logger.out(`✓ No import-policy violations across ${result.scannedFileCount} file(s)${allowlistSuffix}`);
20
+ }
21
+ }
@@ -0,0 +1,16 @@
1
+ import type { AuditCommandPrelude } from "#/audit/prepare";
2
+ import type { AppError } from "#/core/errors";
3
+ import type { Filesystem } from "#/core/filesystem/filesystem";
4
+ import type { Result } from "#/core/result";
5
+ /**
6
+ * Loads config and resolves the scan target for `audit imports`.
7
+ *
8
+ * @remarks Defaults to the repo root: the import policy is repo-wide, and generated or vendored
9
+ * trees are already excluded by the shared walk.
10
+ *
11
+ * @since 0.10.0
12
+ */
13
+ export declare function prepareImportsAudit(fs: Filesystem, args: {
14
+ readonly currentWorkingDirectory: string;
15
+ readonly rawTarget: string | undefined;
16
+ }): Promise<Result<AuditCommandPrelude, AppError>>;