@savvy-web/silk 2.0.0 → 2.1.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 (155) hide show
  1. package/README.md +7 -5
  2. package/changesets-changelog.cjs +10 -4
  3. package/changesets-changelog.js +54057 -1
  4. package/changesets-markdownlint.cjs +10 -4
  5. package/changesets-markdownlint.js +54057 -1
  6. package/package.json +5 -4
  7. package/tsconfig/node/dist/tsconfig.tsbuildinfo +1 -1
  8. package/_virtual/_rolldown/runtime.cjs +0 -45
  9. package/_virtual/_rolldown/runtime.js +0 -45
  10. package/packages/silk-effects/dist/dev/pkg/_virtual/_rolldown/runtime.cjs +0 -15
  11. package/packages/silk-effects/dist/dev/pkg/_virtual/_rolldown/runtime.js +0 -14
  12. package/packages/silk-effects/dist/dev/pkg/changesets/api/categories.cjs +0 -247
  13. package/packages/silk-effects/dist/dev/pkg/changesets/api/categories.js +0 -247
  14. package/packages/silk-effects/dist/dev/pkg/changesets/api/changelog.cjs +0 -134
  15. package/packages/silk-effects/dist/dev/pkg/changesets/api/changelog.js +0 -134
  16. package/packages/silk-effects/dist/dev/pkg/changesets/api/dependency-table.cjs +0 -163
  17. package/packages/silk-effects/dist/dev/pkg/changesets/api/dependency-table.js +0 -163
  18. package/packages/silk-effects/dist/dev/pkg/changesets/api/linter.cjs +0 -170
  19. package/packages/silk-effects/dist/dev/pkg/changesets/api/linter.js +0 -170
  20. package/packages/silk-effects/dist/dev/pkg/changesets/api/transformer.cjs +0 -134
  21. package/packages/silk-effects/dist/dev/pkg/changesets/api/transformer.js +0 -134
  22. package/packages/silk-effects/dist/dev/pkg/changesets/categories/index.cjs +0 -317
  23. package/packages/silk-effects/dist/dev/pkg/changesets/categories/index.js +0 -299
  24. package/packages/silk-effects/dist/dev/pkg/changesets/categories/types.cjs +0 -65
  25. package/packages/silk-effects/dist/dev/pkg/changesets/categories/types.js +0 -65
  26. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/formatting.cjs +0 -114
  27. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/formatting.js +0 -113
  28. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getDependencyReleaseLine.cjs +0 -118
  29. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getDependencyReleaseLine.js +0 -118
  30. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getReleaseLine.cjs +0 -122
  31. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getReleaseLine.js +0 -122
  32. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/index.cjs +0 -97
  33. package/packages/silk-effects/dist/dev/pkg/changesets/changelog/index.js +0 -97
  34. package/packages/silk-effects/dist/dev/pkg/changesets/constants.cjs +0 -43
  35. package/packages/silk-effects/dist/dev/pkg/changesets/constants.js +0 -42
  36. package/packages/silk-effects/dist/dev/pkg/changesets/errors.cjs +0 -386
  37. package/packages/silk-effects/dist/dev/pkg/changesets/errors.js +0 -371
  38. package/packages/silk-effects/dist/dev/pkg/changesets/index.cjs +0 -300
  39. package/packages/silk-effects/dist/dev/pkg/changesets/index.js +0 -179
  40. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/index.cjs +0 -34
  41. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/index.js +0 -29
  42. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/content-structure.cjs +0 -98
  43. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/content-structure.js +0 -98
  44. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/dependency-table-format.cjs +0 -170
  45. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/dependency-table-format.js +0 -170
  46. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/heading-hierarchy.cjs +0 -61
  47. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/heading-hierarchy.js +0 -61
  48. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/required-sections.cjs +0 -54
  49. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/required-sections.js +0 -54
  50. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/uncategorized-content.cjs +0 -54
  51. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/uncategorized-content.js +0 -54
  52. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/utils.cjs +0 -31
  53. package/packages/silk-effects/dist/dev/pkg/changesets/markdownlint/rules/utils.js +0 -30
  54. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/aggregate-dependency-tables.cjs +0 -47
  55. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/aggregate-dependency-tables.js +0 -47
  56. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/contributor-footnotes.cjs +0 -123
  57. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/contributor-footnotes.js +0 -123
  58. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/deduplicate-items.cjs +0 -32
  59. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/deduplicate-items.js +0 -32
  60. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/issue-link-refs.cjs +0 -59
  61. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/issue-link-refs.js +0 -59
  62. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/maintenance-note.cjs +0 -61
  63. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/maintenance-note.js +0 -61
  64. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/merge-sections.cjs +0 -43
  65. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/merge-sections.js +0 -43
  66. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/normalize-format.cjs +0 -47
  67. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/normalize-format.js +0 -47
  68. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/reorder-sections.cjs +0 -34
  69. package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/reorder-sections.js +0 -34
  70. package/packages/silk-effects/dist/dev/pkg/changesets/remark/presets.cjs +0 -120
  71. package/packages/silk-effects/dist/dev/pkg/changesets/remark/presets.js +0 -119
  72. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/content-structure.cjs +0 -22
  73. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/content-structure.js +0 -22
  74. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/dependency-table-format.cjs +0 -40
  75. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/dependency-table-format.js +0 -40
  76. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/heading-hierarchy.cjs +0 -19
  77. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/heading-hierarchy.js +0 -19
  78. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/required-sections.cjs +0 -17
  79. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/required-sections.js +0 -17
  80. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/uncategorized-content.cjs +0 -31
  81. package/packages/silk-effects/dist/dev/pkg/changesets/remark/rules/uncategorized-content.js +0 -31
  82. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/changeset.cjs +0 -148
  83. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/changeset.js +0 -145
  84. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.cjs +0 -203
  85. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.js +0 -198
  86. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/git.cjs +0 -69
  87. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/git.js +0 -68
  88. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/github.cjs +0 -177
  89. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/github.js +0 -174
  90. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/options.cjs +0 -183
  91. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/options.js +0 -181
  92. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/package-scope.cjs +0 -129
  93. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/package-scope.js +0 -127
  94. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/primitives.cjs +0 -72
  95. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/primitives.js +0 -71
  96. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/release-plan.cjs +0 -62
  97. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/release-plan.js +0 -56
  98. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/version-files.cjs +0 -154
  99. package/packages/silk-effects/dist/dev/pkg/changesets/schemas/version-files.js +0 -150
  100. package/packages/silk-effects/dist/dev/pkg/changesets/services/branch-analyzer.cjs +0 -300
  101. package/packages/silk-effects/dist/dev/pkg/changesets/services/branch-analyzer.js +0 -294
  102. package/packages/silk-effects/dist/dev/pkg/changesets/services/changelog.cjs +0 -50
  103. package/packages/silk-effects/dist/dev/pkg/changesets/services/changelog.js +0 -49
  104. package/packages/silk-effects/dist/dev/pkg/changesets/services/config-inspector.cjs +0 -489
  105. package/packages/silk-effects/dist/dev/pkg/changesets/services/config-inspector.js +0 -481
  106. package/packages/silk-effects/dist/dev/pkg/changesets/services/deps-regen.cjs +0 -375
  107. package/packages/silk-effects/dist/dev/pkg/changesets/services/deps-regen.js +0 -371
  108. package/packages/silk-effects/dist/dev/pkg/changesets/services/github.cjs +0 -160
  109. package/packages/silk-effects/dist/dev/pkg/changesets/services/github.js +0 -157
  110. package/packages/silk-effects/dist/dev/pkg/changesets/services/maintenance-reason.cjs +0 -68
  111. package/packages/silk-effects/dist/dev/pkg/changesets/services/maintenance-reason.js +0 -66
  112. package/packages/silk-effects/dist/dev/pkg/changesets/services/markdown.cjs +0 -87
  113. package/packages/silk-effects/dist/dev/pkg/changesets/services/markdown.js +0 -85
  114. package/packages/silk-effects/dist/dev/pkg/changesets/services/release-planner.cjs +0 -352
  115. package/packages/silk-effects/dist/dev/pkg/changesets/services/release-planner.js +0 -348
  116. package/packages/silk-effects/dist/dev/pkg/changesets/utils/commit-parser.cjs +0 -81
  117. package/packages/silk-effects/dist/dev/pkg/changesets/utils/commit-parser.js +0 -80
  118. package/packages/silk-effects/dist/dev/pkg/changesets/utils/dep-diff.cjs +0 -111
  119. package/packages/silk-effects/dist/dev/pkg/changesets/utils/dep-diff.js +0 -111
  120. package/packages/silk-effects/dist/dev/pkg/changesets/utils/dependency-table.cjs +0 -351
  121. package/packages/silk-effects/dist/dev/pkg/changesets/utils/dependency-table.js +0 -347
  122. package/packages/silk-effects/dist/dev/pkg/changesets/utils/git.cjs +0 -51
  123. package/packages/silk-effects/dist/dev/pkg/changesets/utils/git.js +0 -51
  124. package/packages/silk-effects/dist/dev/pkg/changesets/utils/issue-refs.cjs +0 -102
  125. package/packages/silk-effects/dist/dev/pkg/changesets/utils/issue-refs.js +0 -101
  126. package/packages/silk-effects/dist/dev/pkg/changesets/utils/jsonpath.cjs +0 -178
  127. package/packages/silk-effects/dist/dev/pkg/changesets/utils/jsonpath.js +0 -175
  128. package/packages/silk-effects/dist/dev/pkg/changesets/utils/logger.cjs +0 -51
  129. package/packages/silk-effects/dist/dev/pkg/changesets/utils/logger.js +0 -50
  130. package/packages/silk-effects/dist/dev/pkg/changesets/utils/markdown-link.cjs +0 -59
  131. package/packages/silk-effects/dist/dev/pkg/changesets/utils/markdown-link.js +0 -57
  132. package/packages/silk-effects/dist/dev/pkg/changesets/utils/publishability.cjs +0 -50
  133. package/packages/silk-effects/dist/dev/pkg/changesets/utils/publishability.js +0 -50
  134. package/packages/silk-effects/dist/dev/pkg/changesets/utils/remark-pipeline.cjs +0 -81
  135. package/packages/silk-effects/dist/dev/pkg/changesets/utils/remark-pipeline.js +0 -79
  136. package/packages/silk-effects/dist/dev/pkg/changesets/utils/section-parser.cjs +0 -94
  137. package/packages/silk-effects/dist/dev/pkg/changesets/utils/section-parser.js +0 -94
  138. package/packages/silk-effects/dist/dev/pkg/changesets/utils/strip-frontmatter.cjs +0 -47
  139. package/packages/silk-effects/dist/dev/pkg/changesets/utils/strip-frontmatter.js +0 -46
  140. package/packages/silk-effects/dist/dev/pkg/changesets/utils/version-blocks.cjs +0 -110
  141. package/packages/silk-effects/dist/dev/pkg/changesets/utils/version-blocks.js +0 -108
  142. package/packages/silk-effects/dist/dev/pkg/changesets/utils/version-files.cjs +0 -336
  143. package/packages/silk-effects/dist/dev/pkg/changesets/utils/version-files.js +0 -336
  144. package/packages/silk-effects/dist/dev/pkg/changesets/vendor/github-info.cjs +0 -77
  145. package/packages/silk-effects/dist/dev/pkg/changesets/vendor/github-info.js +0 -77
  146. package/packages/silk-effects/dist/dev/pkg/errors/ChangesetConfigError.cjs +0 -21
  147. package/packages/silk-effects/dist/dev/pkg/errors/ChangesetConfigError.js +0 -21
  148. package/packages/silk-effects/dist/dev/pkg/schemas/VersioningSchemas.cjs +0 -101
  149. package/packages/silk-effects/dist/dev/pkg/schemas/VersioningSchemas.js +0 -99
  150. package/packages/silk-effects/dist/dev/pkg/services/ChangesetConfig.cjs +0 -81
  151. package/packages/silk-effects/dist/dev/pkg/services/ChangesetConfig.js +0 -80
  152. package/packages/silk-effects/dist/dev/pkg/services/ChangesetConfigReader.cjs +0 -109
  153. package/packages/silk-effects/dist/dev/pkg/services/ChangesetConfigReader.js +0 -108
  154. package/packages/silk-effects/dist/dev/pkg/services/SilkPublishability.cjs +0 -238
  155. package/packages/silk-effects/dist/dev/pkg/services/SilkPublishability.js +0 -236
@@ -1,481 +0,0 @@
1
- import { ChangesetConfigReader } from "../../services/ChangesetConfigReader.js";
2
- import { WorkspaceDiscovery } from "../../../../../../../node_modules/.pnpm/workspaces-effect@2.0.1_@effect_platform@0.96.2_effect@3.21.4__effect@3.21.4/node_modules/workspaces-effect/services/WorkspaceDiscovery.js";
3
- import { SilkPublishability, readTargetsBinding } from "../../services/SilkPublishability.js";
4
- import { ConfigurationError } from "../errors.js";
5
- import { ChangesetOptionsSchema } from "../schemas/options.js";
6
- import { globSync } from "../../../../../../../node_modules/.pnpm/tinyglobby@0.2.17/node_modules/tinyglobby/dist/index.js";
7
- import { Context, Effect, Layer, Schema } from "effect";
8
- import { FileSystem } from "@effect/platform";
9
- import { isAbsolute, join, relative, resolve } from "node:path";
10
-
11
- //#region ../silk-effects/dist/dev/pkg/changesets/services/config-inspector.js
12
- /**
13
- * `ConfigInspector` service — surface the project's `.changeset/config.json`
14
- * in a structured, validated form that agents and tooling can consume.
15
- *
16
- * @remarks
17
- * The inspector handles three responsibilities that the schemas alone cannot:
18
- *
19
- * 1. **Legacy normalization.** Configs from 0.8.x still use the flat
20
- * top-level `versionFiles[]` array. When that field is populated, the
21
- * inspector emits a one-line deprecation warning to stderr (naming the
22
- * config path and the required edit) and folds each legacy entry into
23
- * the equivalent `packages[entry.package].versionFiles` shape for
24
- * downstream consumers. Removed in 1.0.0.
25
- * 2. **Resolution against the workspace.** Each `packages` key must resolve
26
- * to a known workspace package via `WorkspaceDiscovery`. Unknown keys
27
- * surface as a {@link ConfigurationError}. The inspector returns the
28
- * package's absolute workspace directory alongside the resolved scope.
29
- * 3. **Overlap detection.** Cross-package validation rules that the schemas
30
- * cannot enforce:
31
- * - `additionalScopes` of two different packages must not overlap.
32
- * - `additionalScopes` of one package must not shadow another package's
33
- * workspace directory.
34
- * - Two `versionFiles` entries (within or across packages) must not
35
- * resolve to the same `(file, $.path)` tuple.
36
- *
37
- * Validation is performed eagerly on the first {@link ConfigInspectorShape.inspect}
38
- * call. The resolved state is cached internally per `cwd` so subsequent
39
- * {@link ConfigInspectorShape.classify} calls reuse it.
40
- *
41
- * @see {@link ConfigInspector} for the Effect service tag
42
- * @see {@link ConfigInspectorLive} for the production layer
43
- *
44
- */
45
- /** A `versionFiles` entry expanded to its absolute target paths. @public */
46
- const ResolvedVersionFileSchema = Schema.Struct({
47
- glob: Schema.String,
48
- paths: Schema.Array(Schema.String).annotations({ description: "JSONPath expressions to update (defaults to [\"$.version\"])." }),
49
- matchedFiles: Schema.Array(Schema.String)
50
- }).annotations({ identifier: "ResolvedVersionFile" });
51
- /** A package's resolved release surface. @public */
52
- const ResolvedPackageScopeSchema = Schema.Struct({
53
- name: Schema.String,
54
- workspaceDir: Schema.String,
55
- version: Schema.String,
56
- additionalScopes: Schema.Array(Schema.String),
57
- additionalScopeFiles: Schema.Array(Schema.String),
58
- versionFiles: Schema.Array(ResolvedVersionFileSchema)
59
- }).annotations({ identifier: "ResolvedPackageScope" });
60
- /** Structured representation of a resolved `.changeset/config.json`. @public */
61
- const InspectedConfigSchema = Schema.Struct({
62
- configPath: Schema.String,
63
- projectDir: Schema.String.annotations({ description: "Absolute project root (the directory containing .changeset/)." }),
64
- changelog: Schema.NullOr(Schema.String),
65
- baseBranch: Schema.String,
66
- access: Schema.Literal("public", "restricted"),
67
- ignore: Schema.Array(Schema.String),
68
- packages: Schema.Array(ResolvedPackageScopeSchema),
69
- legacyVersionFilesUsed: Schema.Boolean
70
- }).annotations({ identifier: "InspectedConfig" });
71
- /** Reason a path was attributed to a package (or left unmapped). @public */
72
- const ClassificationReasonSchema = Schema.Union(Schema.Literal("workspace"), Schema.Struct({
73
- kind: Schema.Literal("additionalScope"),
74
- glob: Schema.String
75
- }), Schema.Struct({
76
- kind: Schema.Literal("versionFile"),
77
- glob: Schema.String
78
- }), Schema.Null).annotations({ identifier: "ClassificationReason" });
79
- /** The result of classifying a single path against a resolved config. @public */
80
- const ClassificationSchema = Schema.Struct({
81
- path: Schema.String,
82
- package: Schema.NullOr(Schema.String),
83
- reason: ClassificationReasonSchema
84
- }).annotations({ identifier: "Classification" });
85
- /**
86
- * Base class for {@link ConfigInspector}.
87
- *
88
- * @privateRemarks
89
- * Effect's `Context.Tag` creates an anonymous base class that api-extractor
90
- * cannot follow without an explicit export. Do not delete.
91
- *
92
- * @internal
93
- */
94
- const ConfigInspectorBase = Context.Tag("ConfigInspector")();
95
- /**
96
- * Effect service tag for {@link ConfigInspectorShape}.
97
- *
98
- * @example
99
- * ```typescript
100
- * import { Effect } from "effect";
101
- * import { ConfigInspector, ConfigInspectorLive } from "@savvy-web/changesets";
102
- *
103
- * const program = Effect.gen(function* () {
104
- * const inspector = yield* ConfigInspector;
105
- * const config = yield* inspector.inspect(process.cwd());
106
- * return config.packages.map((p) => p.name);
107
- * });
108
- *
109
- * Effect.runPromise(program.pipe(Effect.provide(ConfigInspectorLive)));
110
- * ```
111
- *
112
- * @public
113
- */
114
- var ConfigInspector = class extends ConfigInspectorBase {};
115
- /**
116
- * Pull the changelog formatter ID and its options object out of the raw
117
- * `.changeset/config.json` shape (where `changelog` may be a tuple, a string,
118
- * or absent).
119
- */
120
- function extractChangelogOptions(config) {
121
- const { changelog } = config;
122
- if (Array.isArray(changelog)) return {
123
- changelogId: typeof changelog[0] === "string" ? changelog[0] : null,
124
- options: changelog[1] ?? {}
125
- };
126
- if (typeof changelog === "string") return {
127
- changelogId: changelog,
128
- options: {}
129
- };
130
- return {
131
- changelogId: null,
132
- options: {}
133
- };
134
- }
135
- /**
136
- * Normalize the deprecated top-level `versionFiles[]` array into the
137
- * equivalent `packages[entry.package].versionFiles` shape. Mutates a fresh
138
- * copy of the options; never the input.
139
- *
140
- * Returns the normalized options and a flag indicating whether normalization
141
- * happened (so the caller can emit a deprecation warning once per inspect).
142
- */
143
- function normalizeLegacyOptions(options, configPath) {
144
- const legacy = options.versionFiles;
145
- if (!Array.isArray(legacy) || legacy.length === 0) return {
146
- normalized: options,
147
- legacyUsed: false
148
- };
149
- console.warn(`[changesets] DEPRECATION: ${configPath} uses the top-level \`versionFiles\` array. Migrate to \`changelog[1].packages[<name>].versionFiles\`. Removed in 1.0.0.`);
150
- const existing = options.packages ?? {};
151
- const next = {};
152
- for (const [k, v] of Object.entries(existing)) next[k] = { ...v };
153
- for (const entry of legacy) {
154
- const ownerName = typeof entry.package === "string" ? entry.package : void 0;
155
- if (!ownerName) throw new ConfigurationError({
156
- field: "versionFiles",
157
- reason: `Legacy versionFiles entry { glob: ${JSON.stringify(entry.glob)} } in ${configPath} has no \`package\` field. Path-based owner inference is removed during the 0.9.0 migration — add an explicit \`package\` field, or migrate the entry to \`packages[<name>].versionFiles\`.`
158
- });
159
- if (!next[ownerName]) next[ownerName] = {};
160
- const slot = next[ownerName];
161
- const arr = Array.isArray(slot.versionFiles) ? slot.versionFiles.slice() : [];
162
- const cleaned = { glob: entry.glob };
163
- if (Array.isArray(entry.paths)) cleaned.paths = entry.paths;
164
- arr.push(cleaned);
165
- slot.versionFiles = arr;
166
- }
167
- const normalized = {
168
- ...options,
169
- packages: next
170
- };
171
- delete normalized.versionFiles;
172
- return {
173
- normalized,
174
- legacyUsed: true
175
- };
176
- }
177
- /**
178
- * Materialize a glob against `cwd` and return the matched file paths as
179
- * repo-relative strings. Honors negation patterns and ignores `node_modules`.
180
- */
181
- function materializeGlob(glob, cwd) {
182
- return globSync(glob, {
183
- cwd,
184
- ignore: ["**/node_modules/**"],
185
- dot: true
186
- });
187
- }
188
- /**
189
- * Determine whether `child` is the same directory as `parent` or sits inside
190
- * it. Both paths must be absolute.
191
- */
192
- function isInside(parent, child) {
193
- const rel = relative(parent, child);
194
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
195
- }
196
- /**
197
- * Build per-package resolved scopes by intersecting the (possibly normalized)
198
- * options with workspace info.
199
- */
200
- function buildResolvedScopes(params) {
201
- const { options, workspaces, projectDir, configPath } = params;
202
- const packages = options.packages ?? {};
203
- const workspacesByName = new Map(workspaces.map((w) => [w.name, w]));
204
- const scopes = [];
205
- for (const [pkgName, scope] of Object.entries(packages)) {
206
- const ws = workspacesByName.get(pkgName);
207
- if (!ws) throw new ConfigurationError({
208
- field: `packages["${pkgName}"]`,
209
- reason: `Unknown package "${pkgName}" in ${configPath}. Known workspace packages: ${workspaces.map((w) => w.name).join(", ") || "(none)"}.`
210
- });
211
- const additionalScopes = scope.additionalScopes ?? [];
212
- const additionalScopeFiles = additionalScopes.flatMap((g) => materializeGlob(g, projectDir));
213
- const resolvedVersionFiles = (scope.versionFiles ?? []).map((entry) => ({
214
- glob: entry.glob,
215
- paths: entry.paths ?? ["$.version"],
216
- matchedFiles: materializeGlob(entry.glob, projectDir).map((rel) => join(projectDir, rel))
217
- }));
218
- scopes.push({
219
- name: pkgName,
220
- workspaceDir: ws.path,
221
- version: ws.version,
222
- additionalScopes,
223
- additionalScopeFiles: additionalScopeFiles.map((rel) => join(projectDir, rel)),
224
- versionFiles: resolvedVersionFiles
225
- });
226
- }
227
- return scopes;
228
- }
229
- /**
230
- * Read a workspace package's raw package.json. A genuinely missing manifest
231
- * resolves to `null` so the caller can skip that package — a workspace
232
- * directory without a `package.json` is not a release surface. Any OTHER
233
- * failure (unreadable file, malformed JSON) is surfaced as a
234
- * {@link ConfigurationError} carrying the package path, rather than silently
235
- * dropping the package, which would cascade into wrong attribution.
236
- */
237
- function readRawPackageJson(fs, pkgDir) {
238
- const pkgJsonPath = join(pkgDir, "package.json");
239
- return fs.readFileString(pkgJsonPath).pipe(Effect.flatMap((content) => Effect.try(() => JSON.parse(content))), Effect.catchAll((err) => {
240
- if (err.reason === "NotFound") return Effect.succeed(null);
241
- return Effect.fail(new ConfigurationError({
242
- field: "workspace",
243
- reason: `Failed to read or parse ${pkgJsonPath}: ${err instanceof Error ? err.message : String(err)}`
244
- }));
245
- }));
246
- }
247
- /**
248
- * Build resolved scopes from the discovered workspace packages, keeping only
249
- * those that are a release surface (declare publishConfig that yields at least
250
- * one publish target). Used both when `.changeset/config.json` declares no
251
- * explicit `packages` record AND to augment an explicit record with the
252
- * remaining workspace packages it does not list (so the record annotates the
253
- * listed packages without shrinking the release surface). The changeset
254
- * `ignore` list is intentionally NOT consulted here — an ignored package still
255
- * declares publishConfig and remains a valid changeset target.
256
- */
257
- function buildFallbackScopes(fs, workspaces) {
258
- return Effect.forEach(workspaces, (ws) => Effect.gen(function* () {
259
- const raw = yield* readRawPackageJson(fs, ws.path);
260
- if (raw === null) return [];
261
- const binding = yield* readTargetsBinding(fs, ws.path);
262
- if (SilkPublishability.detect(ws.name, raw, binding).length === 0) return [];
263
- return [{
264
- name: ws.name,
265
- workspaceDir: ws.path,
266
- version: ws.version,
267
- additionalScopes: [],
268
- additionalScopeFiles: [],
269
- versionFiles: []
270
- }];
271
- })).pipe(Effect.map((nested) => nested.flat()));
272
- }
273
- /**
274
- * Cross-package validation: no overlap in `additionalScopes`, no shadowing
275
- * of another workspace package's directory (regardless of whether that
276
- * package is itself declared in `config.packages`), and no duplicate
277
- * `(file, JSONPath)` tuples in `versionFiles`.
278
- */
279
- function checkConflicts(scopes, allWorkspaces, projectDir, configPath) {
280
- const scopeOwner = /* @__PURE__ */ new Map();
281
- for (const s of scopes) for (const f of s.additionalScopeFiles) {
282
- const prev = scopeOwner.get(f);
283
- if (prev && prev !== s.name) throw new ConfigurationError({
284
- field: `packages["${s.name}"].additionalScopes`,
285
- reason: `Overlap in ${configPath}: file ${JSON.stringify(f)} is matched by both "${prev}" and "${s.name}". additionalScopes must not overlap between packages.`
286
- });
287
- scopeOwner.set(f, s.name);
288
- }
289
- for (const s of scopes) for (const f of s.additionalScopeFiles) for (const ws of allWorkspaces) {
290
- if (ws.name === s.name) continue;
291
- if (ws.path === projectDir) continue;
292
- if (isInside(ws.path, f)) throw new ConfigurationError({
293
- field: `packages["${s.name}"].additionalScopes`,
294
- reason: `Shadowing in ${configPath}: "${s.name}" claims ${JSON.stringify(f)} via additionalScopes, but that path is inside "${ws.name}"'s workspace directory (${ws.path}). A package's additionalScopes must not include another package's workspace files.`
295
- });
296
- }
297
- const seen = /* @__PURE__ */ new Map();
298
- for (const s of scopes) for (const vf of s.versionFiles) for (const file of vf.matchedFiles) for (const path of vf.paths) {
299
- const key = `${file}::${path}`;
300
- const prev = seen.get(key);
301
- if (prev && (prev.pkg !== s.name || prev.glob !== vf.glob)) throw new ConfigurationError({
302
- field: `packages["${s.name}"].versionFiles`,
303
- reason: `Conflict in ${configPath}: target (${JSON.stringify(file)}, ${path}) is claimed by both "${prev.pkg}" (glob ${JSON.stringify(prev.glob)}) and "${s.name}" (glob ${JSON.stringify(vf.glob)}). Two versionFiles entries must not resolve to the same (file, JSONPath) tuple.`
304
- });
305
- seen.set(key, {
306
- pkg: s.name,
307
- glob: vf.glob
308
- });
309
- }
310
- }
311
- /**
312
- * Build a `ConfigurationError` from a Schema `ParseError`. Captures the
313
- * original message verbatim so the user sees exactly what the schema
314
- * complained about.
315
- */
316
- function configErrorFromParseError(parseError, configPath) {
317
- return new ConfigurationError({
318
- field: "options",
319
- reason: `Invalid options in ${configPath}: ${String(parseError)}`
320
- });
321
- }
322
- /**
323
- * Build a {@link ConfigInspectorShape} that closes over already-resolved
324
- * service implementations. This keeps the public `inspect`/`classify`
325
- * signatures requirement-free (`R = never`) while still allowing the
326
- * implementation to use `ChangesetConfigReader` and `WorkspaceDiscovery`.
327
- *
328
- * Each shape carries a private cache keyed by absolute project dir so
329
- * repeat `inspect`/`classify` calls reuse the materialized state.
330
- */
331
- function makeShape(reader, discovery, fs) {
332
- const cache = /* @__PURE__ */ new Map();
333
- const inspect = (cwd) => Effect.gen(function* () {
334
- const projectDir = resolve(cwd);
335
- const cached = cache.get(projectDir);
336
- if (cached) return cached;
337
- const config = yield* reader.read(projectDir).pipe(Effect.mapError((err) => new ConfigurationError({
338
- field: "configFile",
339
- reason: err.message
340
- })));
341
- const configPath = join(projectDir, ".changeset", "config.json");
342
- const { changelogId, options: rawOptions } = extractChangelogOptions(config);
343
- const optionsRecord = typeof rawOptions === "object" && rawOptions !== null ? rawOptions : {};
344
- if (Array.isArray(optionsRecord.versionFiles) && typeof optionsRecord.packages === "object" && optionsRecord.packages !== null) return yield* Effect.fail(new ConfigurationError({
345
- field: "options",
346
- reason: `Configuration in ${configPath} declares both \`packages\` and the deprecated top-level \`versionFiles\` array. Migrate the legacy entries into \`packages[<name>].versionFiles\` and remove the top-level field.`
347
- }));
348
- let normalized;
349
- let legacyUsed;
350
- try {
351
- const result = normalizeLegacyOptions(optionsRecord, configPath);
352
- normalized = result.normalized;
353
- legacyUsed = result.legacyUsed;
354
- } catch (e) {
355
- if (e instanceof ConfigurationError) return yield* Effect.fail(e);
356
- throw e;
357
- }
358
- const decodedOptions = yield* Schema.decodeUnknown(ChangesetOptionsSchema)(normalized).pipe(Effect.mapError((parseError) => configErrorFromParseError(parseError, configPath)));
359
- const workspaces = (yield* discovery.listPackages(projectDir).pipe(Effect.mapError((err) => new ConfigurationError({
360
- field: "workspace",
361
- reason: `Workspace discovery failed for ${projectDir}: ${err.message}`
362
- })))).map((w) => ({
363
- name: w.name,
364
- path: w.path,
365
- version: w.version
366
- }));
367
- const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
368
- let scopes;
369
- if (hasExplicitPackages) {
370
- let explicitScopes;
371
- try {
372
- explicitScopes = buildResolvedScopes({
373
- options: decodedOptions,
374
- workspaces,
375
- projectDir,
376
- configPath
377
- });
378
- checkConflicts(explicitScopes, workspaces, projectDir, configPath);
379
- } catch (e) {
380
- if (e instanceof ConfigurationError) return yield* Effect.fail(e);
381
- throw e;
382
- }
383
- const explicitNames = new Set(explicitScopes.map((s) => s.name));
384
- const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
385
- scopes = [...explicitScopes, ...discoveredScopes];
386
- } else scopes = yield* buildFallbackScopes(fs, workspaces);
387
- const inspected = {
388
- configPath,
389
- projectDir,
390
- changelog: changelogId,
391
- baseBranch: config.baseBranch ?? "main",
392
- access: config.access ?? "restricted",
393
- ignore: config.ignore ?? [],
394
- packages: scopes,
395
- legacyVersionFilesUsed: legacyUsed
396
- };
397
- cache.set(projectDir, inspected);
398
- return inspected;
399
- });
400
- const classify = (cwd, paths) => Effect.gen(function* () {
401
- const inspected = yield* inspect(cwd);
402
- return paths.map((p) => classifyOne(inspected, p));
403
- });
404
- return {
405
- inspect,
406
- classify
407
- };
408
- }
409
- /**
410
- * Classify a single path against an inspected config.
411
- */
412
- function classifyOne(inspected, path) {
413
- const abs = resolve(inspected.projectDir, path);
414
- let bestWorkspace = null;
415
- for (const s of inspected.packages) if (isInside(s.workspaceDir, abs)) {
416
- const depth = s.workspaceDir.length;
417
- if (!bestWorkspace || depth > bestWorkspace.depth) bestWorkspace = {
418
- pkg: s.name,
419
- depth
420
- };
421
- }
422
- if (bestWorkspace) return {
423
- path,
424
- package: bestWorkspace.pkg,
425
- reason: "workspace"
426
- };
427
- for (const s of inspected.packages) if (s.additionalScopeFiles.includes(abs)) {
428
- const glob = s.additionalScopes.find((g) => materializeGlob(g, inspected.projectDir).map((rel) => join(inspected.projectDir, rel)).includes(abs));
429
- return {
430
- path,
431
- package: s.name,
432
- reason: {
433
- kind: "additionalScope",
434
- glob: glob ?? s.additionalScopes[0] ?? ""
435
- }
436
- };
437
- }
438
- for (const s of inspected.packages) for (const vf of s.versionFiles) if (vf.matchedFiles.includes(abs)) return {
439
- path,
440
- package: s.name,
441
- reason: {
442
- kind: "versionFile",
443
- glob: vf.glob
444
- }
445
- };
446
- return {
447
- path,
448
- package: null,
449
- reason: null
450
- };
451
- }
452
- /**
453
- * Live layer for {@link ConfigInspector}.
454
- *
455
- * Requires {@link ChangesetConfigReader} and `WorkspaceDiscovery`
456
- * in the environment.
457
- *
458
- * @public
459
- */
460
- const ConfigInspectorLive = Layer.effect(ConfigInspector, Effect.gen(function* () {
461
- return makeShape(yield* ChangesetConfigReader, yield* WorkspaceDiscovery, yield* FileSystem.FileSystem);
462
- }));
463
- /**
464
- * Test factory — build a {@link ConfigInspector} that returns a fixed
465
- * {@link InspectedConfig} without touching the filesystem.
466
- *
467
- * Tests that need to exercise the inspect/classify logic against real files
468
- * should compose `ConfigInspectorLive` with test layers for
469
- * `ChangesetConfigReader` and `WorkspaceDiscovery` instead.
470
- *
471
- * @public
472
- */
473
- function makeConfigInspectorTest(fixed) {
474
- return Layer.succeed(ConfigInspector, {
475
- inspect: () => Effect.succeed(fixed),
476
- classify: (_cwd, paths) => Effect.succeed(paths.map((p) => classifyOne(fixed, p)))
477
- });
478
- }
479
-
480
- //#endregion
481
- export { ClassificationReasonSchema, ClassificationSchema, ConfigInspector, ConfigInspectorBase, ConfigInspectorLive, InspectedConfigSchema, ResolvedPackageScopeSchema, ResolvedVersionFileSchema, makeConfigInspectorTest };