@heroiclands/package-build 20.0.0 → 20.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.
@@ -14,6 +14,41 @@
14
14
  * {@link CONFIG_FILENAMES}.
15
15
  */
16
16
  export function findConfigFile(from: string): string | undefined;
17
+ /**
18
+ * Which configuration file a build launched here should read, and what each
19
+ * walk found.
20
+ *
21
+ * Kept separate from {@link loadPackConfig} because the *choice* is worth being
22
+ * able to ask about without loading anything: the two walks disagreeing is the
23
+ * observable form of #364, and a caller that wants to report it — or a test
24
+ * that wants to describe it — should not have to reproduce the resolution and
25
+ * risk disagreeing with the loader about it. It performs I/O, and is named for
26
+ * it, like the {@link findConfigFile} it calls twice.
27
+ *
28
+ * `PACKAGE_BUILD_CONFIG` is deliberately not consulted here. An explicit name
29
+ * is not a search result: {@link loadPackConfig} short-circuits on it before it
30
+ * ever asks, so there is no walk to report and nothing to disagree with.
31
+ *
32
+ * @param {object} [from] - Where to walk up from; both default to the real
33
+ * thing, and are parameters only so a caller can describe a tree it is not
34
+ * standing in.
35
+ * @param {string} [from.cwd] - The directory the build was launched in.
36
+ * @param {string} [from.moduleDir] - The directory this module sits in.
37
+ * @returns {{path: string|undefined, fromCwd: string|undefined, fromModule: string|undefined}}
38
+ * The file to read, and each walk's own answer — the same file in an ordinary
39
+ * build, different ones in a worktree resolving the toolchain out of its
40
+ * parent checkout.
41
+ * @throws {Error} As {@link findConfigFile}, when one directory holds more than
42
+ * one configuration.
43
+ */
44
+ export function resolveConfigFile({ cwd, moduleDir }?: {
45
+ cwd?: string | undefined;
46
+ moduleDir?: string | undefined;
47
+ }): {
48
+ path: string | undefined;
49
+ fromCwd: string | undefined;
50
+ fromModule: string | undefined;
51
+ };
17
52
  /**
18
53
  * Attach the position of the key a configuration error names.
19
54
  *
@@ -9,6 +9,47 @@
9
9
  * `overrides`: passing that inline is what silently did nothing (#76).
10
10
  */
11
11
  export function sharedPrettierOptionsFor(file: string): object;
12
+ /**
13
+ * Where a resolved Prettier configuration disagrees with the shared one.
14
+ *
15
+ * The runner resolves each file's options as *either* the consumer's own config
16
+ * or {@link sharedPrettierOptionsFor}, never a merge. That is what bare Prettier
17
+ * does and it is the contract — but it means the conventions this package exists
18
+ * to publish hold by convention alone, and they lapse in two opposite directions
19
+ * (#133). A consumer that declares any config of its own gets whatever that
20
+ * config says: spread {@link PRETTIER_BASE} without the markdown override and
21
+ * every note reindents at 4, the reindentation the override was added to prevent
22
+ * (#76); write a partial `.prettierrc` such as `{"tabWidth": 2}` and
23
+ * `printWidth`, `trailingComma`, `experimentalTernaries` and the rest fall back
24
+ * to Prettier's own defaults. A consumer that declares *nothing* formats one way
25
+ * under this command and another under a bare `npx prettier`.
26
+ *
27
+ * This is the comparison that makes either absence visible. It is a **report,
28
+ * not a merge**: what a consumer declared still wins, and a deliberate local
29
+ * choice stays possible — it stops being silent, and nothing here fails a build
30
+ * over it.
31
+ *
32
+ * Every shared value is a primitive, so `!==` is the whole comparison. An option
33
+ * holding an object would need a deeper one, and the shared set has none —
34
+ * `overrides` is not compared, because `resolveConfig` has already applied and
35
+ * removed it by the time a configuration reaches this.
36
+ *
37
+ * @param {object|null|undefined} resolved - What `prettier.resolveConfig`
38
+ * returned for `file`, with the consumer's own `overrides` already applied.
39
+ * `null` — no configuration at all — reports every shared key as absent.
40
+ * @param {string} file - Path the options were resolved for. Decides whether
41
+ * {@link PRETTIER_MARKDOWN} is part of what is expected.
42
+ * @returns {Array<{key: string, shared: unknown, local: unknown}>} One entry per
43
+ * shared key the resolved configuration does not carry the value of, in the
44
+ * order {@link PRETTIER_BASE} declares them. `local` is `undefined` where the
45
+ * key is absent entirely, which is not the same finding as a key set to
46
+ * something else and is reported differently.
47
+ */
48
+ export function sharedPrettierDivergence(resolved: object | null | undefined, file: string): Array<{
49
+ key: string;
50
+ shared: unknown;
51
+ local: unknown;
52
+ }>;
12
53
  /**
13
54
  * The prose conventions every content repository writes to — one Prettier
14
55
  * configuration and one markdownlint rule set, declared here so a note
@@ -35,6 +35,42 @@ export function checkFormatting(root: string, opts?: {
35
35
  checked: number;
36
36
  written: string[];
37
37
  }>;
38
+ /**
39
+ * Report where a repository's own Prettier configuration parts from the shared
40
+ * one — or that it has none at all (#133).
41
+ *
42
+ * **Warnings, every one of them.** A consumer's config wins by design and this
43
+ * does not change that; it only refuses to let the divergence be silent, which
44
+ * is the whole of what the issue asks for. Turning any of this into an error
45
+ * would make the shared conventions mandatory, and they are a default.
46
+ *
47
+ * The no-configuration case is the sharper one and is reported even though the
48
+ * command itself behaves correctly there: with no config file the shared
49
+ * conventions reach `content-build format` and reach *nothing else*, so an
50
+ * editor's format-on-save and a bare `npx prettier --check .` apply Prettier's
51
+ * own defaults to the same tree, and the two take turns rewriting the same
52
+ * lines. That is not hypothetical — it is what the config files in
53
+ * `sohl-thalorna` and `sohl-kethira-basic` were added to stop.
54
+ *
55
+ * @param {string} root - Repository to ask about.
56
+ * @param {object} [opts]
57
+ * @param {object} [opts.prettier] - The Prettier module, for tests.
58
+ * @returns {Promise<{findings: Array<{file?: string, severity: string,
59
+ * message: string}>, configFile: string|null}>} The findings and the config
60
+ * file they are about, which is `null` when the repository declares none. A
61
+ * finding about a missing file carries no `file`: #17's rule is to drop a
62
+ * field rather than invent one.
63
+ */
64
+ export function checkPrettierConventions(root: string, opts?: {
65
+ prettier?: object | undefined;
66
+ }): Promise<{
67
+ findings: Array<{
68
+ file?: string;
69
+ severity: string;
70
+ message: string;
71
+ }>;
72
+ configFile: string | null;
73
+ }>;
38
74
  /**
39
75
  * Lint a repository's markdown against the shared rule set.
40
76
  *