@savvy-web/silk-effects 5.6.0 → 5.7.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/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import { ChildProcessSpawner } from "effect/unstable/process";
4
4
  import { PackageManagerDetector, PublishConfig, PublishTarget, PublishabilityDetector, VersioningStrategy, WorkspaceDiscovery, WorkspaceDiscoveryFailure, WorkspacePackage, WorkspaceSnapshotAtFailure, WorkspaceSnapshotWorktreeFailure, WorkspaceSnapshots, WorkspaceStateSnapshot, WorkspacesOptions } from "@effected/workspaces";
5
5
  import { Git } from "@effected/git";
6
6
  import { GlobExpansionError } from "@effected/walker";
7
+ import { YamlFormattingOptions } from "@effected/yaml";
7
8
  import { Section, SectionId } from "@effected/templates";
8
9
  import { ToolDiscovery } from "@effected/commands";
9
10
  //#endregion
@@ -289,7 +290,7 @@ declare class Categories {
289
290
  static isValidHeading(heading: string): boolean;
290
291
  }
291
292
  //#endregion
292
- //#region ../../node_modules/.pnpm/@changesets+types@7.0.0-next.9/node_modules/@changesets/types/dist/index.d.mts
293
+ //#region ../../node_modules/.pnpm/@changesets+types@7.0.0/node_modules/@changesets/types/dist/index.d.mts
293
294
  //#region src/index.d.ts
294
295
  type MaybePromise<T> = T | Promise<T>;
295
296
  type VersionType$1 = "major" | "minor" | "patch" | "none";
@@ -6778,9 +6779,14 @@ interface ShellScriptsOptions extends BaseHandlerOptions {
6778
6779
  */
6779
6780
  interface YamlOptions extends BaseHandlerOptions {
6780
6781
  /**
6781
- * Path to yaml-lint config file (.yaml-lint.json).
6782
+ * Formatting options passed through to `@effected/yaml`.
6783
+ *
6784
+ * @remarks
6785
+ * Defaults to the handler's own `defaultFormatOptions`. There is no
6786
+ * config-file discovery: `@effected/yaml` is a pure tier that loads nothing
6787
+ * from disk, and a consumer's `.prettierrc` is NOT consulted.
6782
6788
  */
6783
- config?: string;
6789
+ format?: YamlFormattingOptions;
6784
6790
  /**
6785
6791
  * Skip YAML formatting.
6786
6792
  * @defaultValue false
@@ -7431,14 +7437,15 @@ declare class TypeScript {
7431
7437
  /**
7432
7438
  * Handler for YAML files.
7433
7439
  *
7434
- * Formats with Prettier and validates with yaml-lint, both as bundled dependencies.
7440
+ * Formats and validates with `@effected/yaml`, a bundled dependency.
7435
7441
  *
7436
7442
  * @remarks
7437
7443
  * Excludes pnpm-lock.yaml and pnpm-workspace.yaml by default.
7438
7444
  * pnpm-workspace.yaml has its own dedicated handler.
7439
7445
  *
7440
- * Uses Prettier for formatting and yaml-lint for validation.
7441
- * Both are bundled dependencies (no CLI spawning required).
7446
+ * Formatting preserves comments and blank lines, and formats every document of
7447
+ * a multi-document stream. Validation covers the WHOLE stream: a file whose
7448
+ * second document is invalid fails, which a single-document parse would miss.
7442
7449
  *
7443
7450
  * @example
7444
7451
  * ```typescript
@@ -7462,50 +7469,71 @@ declare class Yaml {
7462
7469
  * @defaultValue `['pnpm-lock.yaml', 'pnpm-workspace.yaml', '__test__/fixtures']`
7463
7470
  */
7464
7471
  static readonly defaultExcludes: readonly ["pnpm-lock.yaml", "pnpm-workspace.yaml", "__test__/fixtures"];
7472
+ /**
7473
+ * The formatting options applied when a caller supplies none.
7474
+ *
7475
+ * @remarks
7476
+ * `indentSequences` matches the block-sequence indentation an ex-Prettier
7477
+ * repository already has on disk; without it, formatting rewrites every
7478
+ * sequence in the tree. `quoteStyle` only governs scalars the stringifier
7479
+ * creates — it never re-quotes scalars already present in the source — so it
7480
+ * is set for consistency with `PnpmWorkspace`, not to change existing files.
7481
+ */
7482
+ static readonly defaultFormatOptions: YamlFormattingOptions;
7465
7483
  /**
7466
7484
  * Pre-configured handler with default options.
7467
7485
  */
7468
7486
  static readonly handler: LintStagedHandler;
7469
7487
  /**
7470
- * Find the yaml-lint config file.
7488
+ * Check if the YAML engine is available.
7471
7489
  *
7472
- * Paths are anchored to the workspace root (via {@link getWorkspaceRoot}),
7473
- * falling back to `process.cwd()` when not inside a workspace.
7474
- *
7475
- * Searches in order:
7476
- * 1. `{workspaceRoot}/lib/configs/.yaml-lint.json`
7477
- * 2. `{workspaceRoot}/.yaml-lint.json`
7478
- *
7479
- * @returns The config file path, or undefined if not found
7490
+ * @returns Always `true` since `@effected/yaml` is a bundled dependency
7480
7491
  */
7481
- static findConfig(): string | undefined;
7492
+ static isAvailable(): boolean;
7482
7493
  /**
7483
- * Load the yaml-lint schema from a config file.
7494
+ * Format a YAML file in-place.
7484
7495
  *
7485
- * @param filepath - Path to the yaml-lint config file
7486
- * @returns The schema string, or undefined if not found
7496
+ * @remarks
7497
+ * Synchronous by contract: the engine is a pure, IO-free tier, so the only
7498
+ * IO here is this function's own file read and write.
7499
+ *
7500
+ * @param filepath - Path to the YAML file
7501
+ * @param options - Formatting options; defaults to {@link Yaml.defaultFormatOptions}
7487
7502
  */
7488
- static loadConfig(filepath: string): string | undefined;
7503
+ static formatFile(filepath: string, options?: YamlFormattingOptions): void;
7489
7504
  /**
7490
- * Check if yaml-lint is available.
7505
+ * Validate a YAML file.
7491
7506
  *
7492
- * @returns Always `true` since yaml-lint is a bundled dependency
7507
+ * @remarks
7508
+ * Validates every document of the stream, so a multi-document file whose
7509
+ * later documents are invalid is rejected rather than silently accepted.
7510
+ *
7511
+ * @param filepath - Path to the YAML file
7512
+ * @throws Error if the YAML is invalid
7493
7513
  */
7494
- static isAvailable(): boolean;
7514
+ static validateFile(filepath: string): void;
7495
7515
  /**
7496
- * Format a YAML file in-place using Prettier.
7516
+ * Serialize formatting options for the `savvy lint fmt yaml --format` flag.
7497
7517
  *
7498
- * @param filepath - Path to the YAML file
7518
+ * @remarks
7519
+ * The CLI subcommand runs in a separate process, so options set on
7520
+ * {@link fmtCommand} have to cross a shell boundary to reach
7521
+ * {@link formatFile}. Without that hop the two entry points format the same
7522
+ * file differently — the drift this package's shared-static rule exists to
7523
+ * prevent. {@link parseFormatOptions} is the inverse.
7524
+ *
7525
+ * @param options - Formatting options to encode
7526
+ * @returns The options as a JSON string
7499
7527
  */
7500
- static formatFile(filepath: string): Promise<void>;
7528
+ static encodeFormatOptions(options: YamlFormattingOptions): string;
7501
7529
  /**
7502
- * Validate a YAML file using yaml-lint.
7530
+ * Parse formatting options serialized by {@link encodeFormatOptions}.
7503
7531
  *
7504
- * @param filepath - Path to the YAML file
7505
- * @param schema - The YAML schema to validate against
7506
- * @throws Error if the YAML is invalid
7532
+ * @param encoded - JSON produced by {@link encodeFormatOptions}
7533
+ * @returns The decoded options
7534
+ * @throws Error if the JSON is malformed or fails schema validation
7507
7535
  */
7508
- static validateFile(filepath: string, schema?: string): Promise<void>;
7536
+ static parseFormatOptions(encoded: string): YamlFormattingOptions;
7509
7537
  /**
7510
7538
  * Create a handler that returns a CLI command to format YAML files.
7511
7539
  *
@@ -7515,6 +7543,9 @@ declare class Yaml {
7515
7543
  * can detect the modification and auto-stage it.
7516
7544
  * Use this in lint-staged array syntax for sequential execution.
7517
7545
  *
7546
+ * `options.format` is forwarded to the subcommand as `--format`, so this
7547
+ * path and {@link create} produce identical bytes for the same options.
7548
+ *
7518
7549
  * @param options - Configuration options
7519
7550
  * @returns A lint-staged compatible handler function
7520
7551
  */
@@ -1,28 +1,26 @@
1
1
  import { Command } from "../utils/Command.js";
2
2
  import { Filter } from "../utils/Filter.js";
3
- import { getWorkspaceRoot } from "../utils/Workspace.js";
4
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
5
- import { join } from "node:path";
6
- import { format, resolveConfig } from "prettier";
7
- import { lint } from "yaml-lint";
3
+ import { readFileSync, writeFileSync } from "node:fs";
4
+ import { Yaml, YamlFormat, YamlFormattingOptions } from "@effected/yaml";
8
5
 
9
6
  //#region src/lint/handlers/Yaml.ts
10
7
  /**
11
8
  * Handler for YAML files.
12
9
  *
13
- * Formats with Prettier and validates with yaml-lint, both as bundled dependencies.
10
+ * Formats and validates with `@effected/yaml`, a bundled dependency.
14
11
  */
15
12
  /**
16
13
  * Handler for YAML files.
17
14
  *
18
- * Formats with Prettier and validates with yaml-lint, both as bundled dependencies.
15
+ * Formats and validates with `@effected/yaml`, a bundled dependency.
19
16
  *
20
17
  * @remarks
21
18
  * Excludes pnpm-lock.yaml and pnpm-workspace.yaml by default.
22
19
  * pnpm-workspace.yaml has its own dedicated handler.
23
20
  *
24
- * Uses Prettier for formatting and yaml-lint for validation.
25
- * Both are bundled dependencies (no CLI spawning required).
21
+ * Formatting preserves comments and blank lines, and formats every document of
22
+ * a multi-document stream. Validation covers the WHOLE stream: a file whose
23
+ * second document is invalid fails, which a single-document parse would miss.
26
24
  *
27
25
  * @example
28
26
  * ```typescript
@@ -35,7 +33,7 @@ import { lint } from "yaml-lint";
35
33
  * };
36
34
  * ```
37
35
  */
38
- var Yaml = class Yaml {
36
+ var Yaml$1 = class Yaml$1 {
39
37
  /**
40
38
  * Glob pattern for matching YAML files.
41
39
  * @defaultValue `'**\/*.{yml,yaml}'`
@@ -51,75 +49,86 @@ var Yaml = class Yaml {
51
49
  "__test__/fixtures"
52
50
  ];
53
51
  /**
54
- * Pre-configured handler with default options.
55
- */
56
- static handler = Yaml.create();
57
- /**
58
- * Find the yaml-lint config file.
59
- *
60
- * Paths are anchored to the workspace root (via {@link getWorkspaceRoot}),
61
- * falling back to `process.cwd()` when not inside a workspace.
52
+ * The formatting options applied when a caller supplies none.
62
53
  *
63
- * Searches in order:
64
- * 1. `{workspaceRoot}/lib/configs/.yaml-lint.json`
65
- * 2. `{workspaceRoot}/.yaml-lint.json`
66
- *
67
- * @returns The config file path, or undefined if not found
54
+ * @remarks
55
+ * `indentSequences` matches the block-sequence indentation an ex-Prettier
56
+ * repository already has on disk; without it, formatting rewrites every
57
+ * sequence in the tree. `quoteStyle` only governs scalars the stringifier
58
+ * creates it never re-quotes scalars already present in the source — so it
59
+ * is set for consistency with `PnpmWorkspace`, not to change existing files.
68
60
  */
69
- static findConfig() {
70
- const root = getWorkspaceRoot() ?? process.cwd();
71
- const libPath = join(root, "lib/configs/.yaml-lint.json");
72
- if (existsSync(libPath)) return libPath;
73
- const rootPath = join(root, ".yaml-lint.json");
74
- if (existsSync(rootPath)) return rootPath;
75
- }
61
+ static defaultFormatOptions = YamlFormattingOptions.make({
62
+ quoteStyle: "double",
63
+ indentSequences: true
64
+ });
76
65
  /**
77
- * Load the yaml-lint schema from a config file.
78
- *
79
- * @param filepath - Path to the yaml-lint config file
80
- * @returns The schema string, or undefined if not found
66
+ * Pre-configured handler with default options.
81
67
  */
82
- static loadConfig(filepath) {
83
- try {
84
- const content = readFileSync(filepath, "utf-8");
85
- return JSON.parse(content).schema;
86
- } catch {
87
- return;
88
- }
89
- }
68
+ static handler = Yaml$1.create();
90
69
  /**
91
- * Check if yaml-lint is available.
70
+ * Check if the YAML engine is available.
92
71
  *
93
- * @returns Always `true` since yaml-lint is a bundled dependency
72
+ * @returns Always `true` since `@effected/yaml` is a bundled dependency
94
73
  */
95
74
  static isAvailable() {
96
75
  return true;
97
76
  }
98
77
  /**
99
- * Format a YAML file in-place using Prettier.
78
+ * Format a YAML file in-place.
79
+ *
80
+ * @remarks
81
+ * Synchronous by contract: the engine is a pure, IO-free tier, so the only
82
+ * IO here is this function's own file read and write.
100
83
  *
101
84
  * @param filepath - Path to the YAML file
85
+ * @param options - Formatting options; defaults to {@link Yaml.defaultFormatOptions}
102
86
  */
103
- static async formatFile(filepath) {
87
+ static formatFile(filepath, options = Yaml$1.defaultFormatOptions) {
104
88
  const content = readFileSync(filepath, "utf-8");
105
- const prettierConfig = await resolveConfig(filepath);
106
- const formatted = await format(content, {
107
- ...prettierConfig,
108
- filepath,
109
- parser: "yaml"
110
- });
111
- writeFileSync(filepath, formatted, "utf-8");
89
+ const formatted = YamlFormat.formatToString(content, void 0, options);
90
+ if (formatted !== content) writeFileSync(filepath, formatted, "utf-8");
112
91
  }
113
92
  /**
114
- * Validate a YAML file using yaml-lint.
93
+ * Validate a YAML file.
94
+ *
95
+ * @remarks
96
+ * Validates every document of the stream, so a multi-document file whose
97
+ * later documents are invalid is rejected rather than silently accepted.
115
98
  *
116
99
  * @param filepath - Path to the YAML file
117
- * @param schema - The YAML schema to validate against
118
100
  * @throws Error if the YAML is invalid
119
101
  */
120
- static async validateFile(filepath, schema) {
102
+ static validateFile(filepath) {
121
103
  const content = readFileSync(filepath, "utf-8");
122
- await lint(content, schema ? { schema } : void 0);
104
+ const result = Yaml.parseAllResult(content);
105
+ if (!("success" in result)) throw new Error(String(result.failure));
106
+ }
107
+ /**
108
+ * Serialize formatting options for the `savvy lint fmt yaml --format` flag.
109
+ *
110
+ * @remarks
111
+ * The CLI subcommand runs in a separate process, so options set on
112
+ * {@link fmtCommand} have to cross a shell boundary to reach
113
+ * {@link formatFile}. Without that hop the two entry points format the same
114
+ * file differently — the drift this package's shared-static rule exists to
115
+ * prevent. {@link parseFormatOptions} is the inverse.
116
+ *
117
+ * @param options - Formatting options to encode
118
+ * @returns The options as a JSON string
119
+ */
120
+ static encodeFormatOptions(options) {
121
+ return JSON.stringify(options);
122
+ }
123
+ /**
124
+ * Parse formatting options serialized by {@link encodeFormatOptions}.
125
+ *
126
+ * @param encoded - JSON produced by {@link encodeFormatOptions}
127
+ * @returns The decoded options
128
+ * @throws Error if the JSON is malformed or fails schema validation
129
+ */
130
+ static parseFormatOptions(encoded) {
131
+ return YamlFormattingOptions.make(JSON.parse(encoded));
123
132
  }
124
133
  /**
125
134
  * Create a handler that returns a CLI command to format YAML files.
@@ -130,15 +139,19 @@ var Yaml = class Yaml {
130
139
  * can detect the modification and auto-stage it.
131
140
  * Use this in lint-staged array syntax for sequential execution.
132
141
  *
142
+ * `options.format` is forwarded to the subcommand as `--format`, so this
143
+ * path and {@link create} produce identical bytes for the same options.
144
+ *
133
145
  * @param options - Configuration options
134
146
  * @returns A lint-staged compatible handler function
135
147
  */
136
148
  static fmtCommand(options = {}) {
137
- const excludes = options.exclude ?? [...Yaml.defaultExcludes];
149
+ const excludes = options.exclude ?? [...Yaml$1.defaultExcludes];
150
+ const formatOptions = options.format;
138
151
  return (filenames) => {
139
152
  const filtered = Filter.exclude(filenames, excludes);
140
153
  if (filtered.length === 0) return [];
141
- return `${Command.findSavvyLint()} fmt yaml ${Filter.shellEscape(filtered)}`;
154
+ return `${Command.findSavvyLint()} fmt yaml${formatOptions ? ` --format ${Filter.shellEscape([Yaml$1.encodeFormatOptions(formatOptions)])}` : ""} ${Filter.shellEscape(filtered)}`;
142
155
  };
143
156
  }
144
157
  /**
@@ -148,17 +161,16 @@ var Yaml = class Yaml {
148
161
  * @returns A lint-staged compatible handler function
149
162
  */
150
163
  static create(options = {}) {
151
- const excludes = options.exclude ?? [...Yaml.defaultExcludes];
164
+ const excludes = options.exclude ?? [...Yaml$1.defaultExcludes];
152
165
  const skipFormat = options.skipFormat ?? false;
153
166
  const skipValidate = options.skipValidate ?? false;
154
- const configPath = options.config ?? Yaml.findConfig();
155
- const schema = configPath ? Yaml.loadConfig(configPath) : void 0;
156
- return async (filenames) => {
167
+ const formatOptions = options.format ?? Yaml$1.defaultFormatOptions;
168
+ return (filenames) => {
157
169
  const filtered = Filter.exclude(filenames, excludes);
158
170
  if (filtered.length === 0) return [];
159
- if (!skipFormat) for (const filepath of filtered) await Yaml.formatFile(filepath);
171
+ if (!skipFormat) for (const filepath of filtered) Yaml$1.formatFile(filepath, formatOptions);
160
172
  if (!skipValidate) for (const filepath of filtered) try {
161
- await Yaml.validateFile(filepath, schema);
173
+ Yaml$1.validateFile(filepath);
162
174
  } catch (error) {
163
175
  throw new Error(`Invalid YAML in ${filepath}: ${error instanceof Error ? error.message : String(error)}`);
164
176
  }
@@ -168,4 +180,4 @@ var Yaml = class Yaml {
168
180
  };
169
181
 
170
182
  //#endregion
171
- export { Yaml };
183
+ export { Yaml$1 as Yaml };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/silk-effects",
3
- "version": "5.6.0",
3
+ "version": "5.7.1",
4
4
  "private": false,
5
5
  "description": "Shared Effect library for Silk Suite conventions",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/silk-effects",
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@changesets/apply-release-plan": "^8.0.0-next.9",
33
33
  "@changesets/config": "^4.0.0-next.6",
34
- "@changesets/get-github-info": "^1.0.0-next.4",
34
+ "@changesets/get-github-info": "^1.0.0",
35
35
  "@changesets/get-release-plan": "^5.0.0-next.9",
36
36
  "@effected/commands": "^0.4.0",
37
37
  "@effected/git": "^0.7.0",
@@ -40,20 +40,18 @@
40
40
  "@effected/package-json": "^0.8.0",
41
41
  "@effected/templates": "^0.2.0",
42
42
  "@effected/walker": "^0.4.0",
43
- "@effected/workspaces": "^0.11.1",
44
- "@effected/yaml": "^0.7.0",
43
+ "@effected/workspaces": "^0.12.0",
44
+ "@effected/yaml": "^0.8.0",
45
45
  "@manypkg/get-packages": "^3.1.0",
46
46
  "mdast-util-heading-range": "^4.0.0",
47
47
  "mdast-util-to-string": "^4.0.0",
48
- "prettier": "^3.9.6",
49
48
  "remark-gfm": "^4.0.1",
50
49
  "remark-parse": "^11.0.0",
51
50
  "remark-stringify": "^11.0.0",
52
51
  "shell-quote": "^1.10.0",
53
52
  "unified": "^11.0.5",
54
53
  "unified-lint-rule": "^3.0.1",
55
- "unist-util-visit": "^5.1.0",
56
- "yaml-lint": "^1.7.0"
54
+ "unist-util-visit": "^5.1.0"
57
55
  },
58
56
  "peerDependencies": {
59
57
  "effect": "4.0.0-beta.107"