@savvy-web/silk-effects 0.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.
package/index.d.ts ADDED
@@ -0,0 +1,1045 @@
1
+ /**
2
+ * `@savvy-web/silk-effects` — shared Effect library for Silk Suite conventions.
3
+ *
4
+ * @remarks
5
+ * Platform-agnostic Effect services for publishability detection, versioning strategy,
6
+ * tag strategy, managed sections, config discovery, and Biome schema synchronization.
7
+ * Consumers provide their platform layer (NodeContext, BunContext, etc.).
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+
12
+ import { Context } from 'effect';
13
+ import { Effect } from 'effect';
14
+ import { FileSystem } from '@effect/platform';
15
+ import { Layer } from 'effect';
16
+ import { Schema } from 'effect';
17
+ import { VoidIfEmpty } from 'effect/Types';
18
+ import { YieldableError } from 'effect/Cause';
19
+
20
+ /**
21
+ * Authentication strategy used to obtain publish credentials.
22
+ *
23
+ * @remarks
24
+ * `"oidc"` relies on GitHub Actions OIDC provenance tokens (no explicit secret needed).
25
+ * `"token"` reads a long-lived token from an environment variable.
26
+ *
27
+ * @since 0.1.0
28
+ */
29
+ export declare const AuthStrategy: Schema.Literal<["oidc", "token"]>;
30
+
31
+ /** @since 0.1.0 */
32
+ export declare type AuthStrategy = typeof AuthStrategy.Type;
33
+
34
+ /**
35
+ * Service that keeps the `$schema` URL in Biome config files in sync with a target version.
36
+ *
37
+ * @remarks
38
+ * Locates `biome.json` and `biome.jsonc` files in the working directory, then compares
39
+ * each file's `$schema` field against the expected `biomejs.dev` URL for the given version.
40
+ * `sync` writes updates in-place; `check` returns the same result without modifying files.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const result = await Effect.runPromise(
45
+ * Effect.gen(function* () {
46
+ * const syncer = yield* BiomeSchemaSync;
47
+ * return yield* syncer.sync("^1.9.3");
48
+ * }).pipe(
49
+ * Effect.provide(BiomeSchemaSyncLive),
50
+ * Effect.provide(NodeContext.layer),
51
+ * )
52
+ * );
53
+ * ```
54
+ *
55
+ * @since 0.1.0
56
+ */
57
+ export declare class BiomeSchemaSync extends BiomeSchemaSync_base {
58
+ }
59
+
60
+ declare const BiomeSchemaSync_base: Context.TagClass<BiomeSchemaSync, "@savvy-web/silk-effects/BiomeSchemaSync", {
61
+ /**
62
+ * Update the `$schema` URL in all located Biome config files to match `version`.
63
+ *
64
+ * @param version - Target Biome version (range operators are stripped automatically).
65
+ * @param options - Optional `cwd` and `gitignore` overrides.
66
+ * @returns An `Effect` that succeeds with a {@link BiomeSyncResult} or fails with {@link BiomeSyncError}.
67
+ *
68
+ * @since 0.1.0
69
+ */
70
+ readonly sync: (version: string, options?: {
71
+ cwd?: string;
72
+ gitignore?: boolean;
73
+ }) => Effect.Effect<BiomeSyncResult, BiomeSyncError>;
74
+ /**
75
+ * Check whether the `$schema` URL in Biome config files is current, without writing any changes.
76
+ *
77
+ * @param version - Target Biome version (range operators are stripped automatically).
78
+ * @param options - Optional `cwd` and `gitignore` overrides.
79
+ * @returns An `Effect` that succeeds with a {@link BiomeSyncResult} or fails with {@link BiomeSyncError}.
80
+ * Files that would be updated appear in `updated`; no disk writes occur.
81
+ *
82
+ * @since 0.1.0
83
+ */
84
+ readonly check: (version: string, options?: {
85
+ cwd?: string;
86
+ gitignore?: boolean;
87
+ }) => Effect.Effect<BiomeSyncResult, BiomeSyncError>;
88
+ }>;
89
+
90
+ /**
91
+ * Live implementation of {@link BiomeSchemaSync}.
92
+ *
93
+ * @remarks
94
+ * Requires `FileSystem` from `@effect/platform`. Provide `NodeContext.layer` or
95
+ * `BunContext.layer` to satisfy this dependency.
96
+ *
97
+ * @since 0.1.0
98
+ */
99
+ export declare const BiomeSchemaSyncLive: Layer.Layer<BiomeSchemaSync, never, FileSystem.FileSystem>;
100
+
101
+ /**
102
+ * Raised when a Biome config file cannot be read or its `$schema` URL cannot be updated.
103
+ *
104
+ * @remarks
105
+ * Returned by {@link BiomeSchemaSync.sync} and {@link BiomeSchemaSync.check} when
106
+ * a `biome.json` or `biome.jsonc` file exists but cannot be read, contains invalid JSON,
107
+ * or cannot be written back to disk.
108
+ *
109
+ * @since 0.1.0
110
+ */
111
+ export declare class BiomeSyncError extends BiomeSyncError_base<{
112
+ readonly path: string;
113
+ readonly reason: string;
114
+ }> {
115
+ get message(): string;
116
+ }
117
+
118
+ declare const BiomeSyncError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
119
+ readonly _tag: "BiomeSyncError";
120
+ } & Readonly<A>;
121
+
122
+ /**
123
+ * Options for {@link BiomeSchemaSync} operations.
124
+ *
125
+ * @remarks
126
+ * `cwd` overrides the working directory used to locate `biome.json` / `biome.jsonc`.
127
+ * `gitignore` is reserved for future use to skip gitignored config files (defaults to `true`).
128
+ *
129
+ * @since 0.1.0
130
+ */
131
+ export declare const BiomeSyncOptions: Schema.Struct<{
132
+ cwd: Schema.optional<typeof Schema.String>;
133
+ gitignore: Schema.optionalWith<typeof Schema.Boolean, {
134
+ default: () => true;
135
+ }>;
136
+ }>;
137
+
138
+ /** @since 0.1.0 */
139
+ export declare type BiomeSyncOptions = typeof BiomeSyncOptions.Type;
140
+
141
+ /**
142
+ * Result of a Biome schema URL sync or check operation.
143
+ *
144
+ * @remarks
145
+ * - `updated` — paths of config files whose `$schema` URL was changed (or would be changed on `check`).
146
+ * - `skipped` — paths of config files with no `$schema` field or a non-biomejs.dev URL.
147
+ * - `current` — paths of config files already pointing to the expected schema URL.
148
+ *
149
+ * @since 0.1.0
150
+ */
151
+ export declare const BiomeSyncResult: Schema.Struct<{
152
+ updated: Schema.Array$<typeof Schema.String>;
153
+ skipped: Schema.Array$<typeof Schema.String>;
154
+ current: Schema.Array$<typeof Schema.String>;
155
+ }>;
156
+
157
+ /** @since 0.1.0 */
158
+ export declare type BiomeSyncResult = typeof BiomeSyncResult.Type;
159
+
160
+ /**
161
+ * Standard changesets configuration matching the `@changesets/types` upstream spec.
162
+ *
163
+ * @remarks
164
+ * Represents the parsed `.changeset/config.json` file. All fields are optional
165
+ * to allow partial configs. Use {@link SilkChangesetConfig} when the Silk changelog
166
+ * adapter is detected.
167
+ *
168
+ * @since 0.1.0
169
+ */
170
+ export declare const ChangesetConfig: Schema.Struct<{
171
+ changelog: Schema.optional<Schema.Union<[typeof Schema.String, Schema.Array$<typeof Schema.Unknown>]>>;
172
+ commit: Schema.optional<typeof Schema.Boolean>;
173
+ fixed: Schema.optional<Schema.Array$<Schema.Array$<typeof Schema.String>>>;
174
+ linked: Schema.optional<Schema.Array$<Schema.Array$<typeof Schema.String>>>;
175
+ access: Schema.optional<Schema.Literal<["public", "restricted"]>>;
176
+ baseBranch: Schema.optional<typeof Schema.String>;
177
+ updateInternalDependencies: Schema.optional<Schema.Literal<["patch", "minor", "major"]>>;
178
+ ignore: Schema.optional<Schema.Array$<typeof Schema.String>>;
179
+ }>;
180
+
181
+ /** @since 0.1.0 */
182
+ export declare type ChangesetConfig = typeof ChangesetConfig.Type;
183
+
184
+ /**
185
+ * Raised when the `.changeset/config.json` file cannot be read or decoded.
186
+ *
187
+ * @remarks
188
+ * Returned by {@link ChangesetConfigReader.read} when the file is missing,
189
+ * contains invalid JSON, or fails Effect Schema validation.
190
+ *
191
+ * @since 0.1.0
192
+ */
193
+ export declare class ChangesetConfigError extends ChangesetConfigError_base<{
194
+ readonly path: string;
195
+ readonly reason: string;
196
+ }> {
197
+ get message(): string;
198
+ }
199
+
200
+ declare const ChangesetConfigError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
201
+ readonly _tag: "ChangesetConfigError";
202
+ } & Readonly<A>;
203
+
204
+ /**
205
+ * Service that reads and decodes the `.changeset/config.json` for a given workspace root.
206
+ *
207
+ * @remarks
208
+ * Automatically detects whether the config uses the Silk changelog adapter
209
+ * (`@savvy-web/changesets`) and decodes as {@link SilkChangesetConfig} or the
210
+ * standard {@link ChangesetConfig} accordingly.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const result = await Effect.runPromise(
215
+ * Effect.gen(function* () {
216
+ * const reader = yield* ChangesetConfigReader;
217
+ * return yield* reader.read(process.cwd());
218
+ * }).pipe(
219
+ * Effect.provide(ChangesetConfigReaderLive),
220
+ * Effect.provide(NodeContext.layer),
221
+ * )
222
+ * );
223
+ * ```
224
+ *
225
+ * @since 0.1.0
226
+ */
227
+ export declare class ChangesetConfigReader extends ChangesetConfigReader_base {
228
+ }
229
+
230
+ declare const ChangesetConfigReader_base: Context.TagClass<ChangesetConfigReader, "@savvy-web/silk-effects/ChangesetConfigReader", {
231
+ /**
232
+ * Read and decode `.changeset/config.json` from the given workspace root.
233
+ *
234
+ * @param root - Absolute path to the workspace root containing the `.changeset/` directory.
235
+ * @returns An `Effect` that succeeds with the decoded config or fails with {@link ChangesetConfigError}.
236
+ *
237
+ * @since 0.1.0
238
+ */
239
+ readonly read: (root: string) => Effect.Effect<ChangesetConfig | SilkChangesetConfig, ChangesetConfigError>;
240
+ }>;
241
+
242
+ /**
243
+ * Live implementation of {@link ChangesetConfigReader}.
244
+ *
245
+ * @remarks
246
+ * Requires `FileSystem` from `@effect/platform`. Provide `NodeContext.layer` or
247
+ * `BunContext.layer` to satisfy this dependency.
248
+ *
249
+ * @since 0.1.0
250
+ */
251
+ export declare const ChangesetConfigReaderLive: Layer.Layer<ChangesetConfigReader, never, FileSystem.FileSystem>;
252
+
253
+ /**
254
+ * Comment syntax used to write managed section markers.
255
+ *
256
+ * @remarks
257
+ * - `"#"` — shell/YAML style, suitable for hook scripts and `.env` files.
258
+ * - `"//"` — C-style, suitable for JavaScript/TypeScript files.
259
+ *
260
+ * @since 0.1.0
261
+ */
262
+ export declare const CommentStyle: Schema.Literal<["#", "//"]>;
263
+
264
+ /** @since 0.1.0 */
265
+ export declare type CommentStyle = typeof CommentStyle.Type;
266
+
267
+ /**
268
+ * Service that locates named config files within a workspace using priority-ordered search paths.
269
+ *
270
+ * @remarks
271
+ * Search priority (highest to lowest):
272
+ * 1. `lib/configs/{name}` — shared config provided by a dependency package.
273
+ * 2. `{cwd}/{name}` — local override at the workspace root.
274
+ *
275
+ * Missing files are silently skipped; only files that actually exist are returned.
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * const result = await Effect.runPromise(
280
+ * Effect.gen(function* () {
281
+ * const discovery = yield* ConfigDiscovery;
282
+ * return yield* discovery.find("biome.json");
283
+ * }).pipe(
284
+ * Effect.provide(ConfigDiscoveryLive),
285
+ * Effect.provide(NodeContext.layer),
286
+ * )
287
+ * );
288
+ * ```
289
+ *
290
+ * @since 0.1.0
291
+ */
292
+ export declare class ConfigDiscovery extends ConfigDiscovery_base {
293
+ }
294
+
295
+ declare const ConfigDiscovery_base: Context.TagClass<ConfigDiscovery, "@savvy-web/silk-effects/ConfigDiscovery", {
296
+ /**
297
+ * Return the highest-priority {@link ConfigLocation} for the given config file name,
298
+ * or `null` when none of the candidate paths exist.
299
+ *
300
+ * @param name - Config file name (e.g. `"biome.json"`).
301
+ * @param options - Optional `cwd` override for path resolution.
302
+ * @returns An `Effect` that always succeeds with a {@link ConfigLocation} or `null`.
303
+ *
304
+ * @since 0.1.0
305
+ */
306
+ readonly find: (name: string, options?: {
307
+ cwd?: string;
308
+ }) => Effect.Effect<ConfigLocation | null>;
309
+ /**
310
+ * Return all existing {@link ConfigLocation} entries for the given config file name,
311
+ * ordered from highest to lowest priority.
312
+ *
313
+ * @param name - Config file name (e.g. `"biome.json"`).
314
+ * @param options - Optional `cwd` override for path resolution.
315
+ * @returns An `Effect` that always succeeds with an array of {@link ConfigLocation} records.
316
+ *
317
+ * @since 0.1.0
318
+ */
319
+ readonly findAll: (name: string, options?: {
320
+ cwd?: string;
321
+ }) => Effect.Effect<ReadonlyArray<ConfigLocation>>;
322
+ }>;
323
+
324
+ /**
325
+ * Live implementation of {@link ConfigDiscovery}.
326
+ *
327
+ * @remarks
328
+ * Requires `FileSystem` from `@effect/platform`. Provide `NodeContext.layer` or
329
+ * `BunContext.layer` to satisfy this dependency.
330
+ *
331
+ * @since 0.1.0
332
+ */
333
+ export declare const ConfigDiscoveryLive: Layer.Layer<ConfigDiscovery, never, FileSystem.FileSystem>;
334
+
335
+ /**
336
+ * Options passed to config discovery methods.
337
+ *
338
+ * @remarks
339
+ * `cwd` overrides the working directory for path resolution (defaults to `process.cwd()`).
340
+ * `tool` is reserved for future use as a tool-specific discovery hint.
341
+ *
342
+ * @since 0.1.0
343
+ */
344
+ export declare const ConfigDiscoveryOptions: Schema.Struct<{
345
+ cwd: Schema.optional<typeof Schema.String>;
346
+ tool: Schema.optional<typeof Schema.String>;
347
+ }>;
348
+
349
+ /** @since 0.1.0 */
350
+ export declare type ConfigDiscoveryOptions = typeof ConfigDiscoveryOptions.Type;
351
+
352
+ /**
353
+ * The resolved location of a discovered config file.
354
+ *
355
+ * @remarks
356
+ * Produced by {@link ConfigDiscovery.find} and {@link ConfigDiscovery.findAll}.
357
+ * `path` is the absolute file path; `source` indicates how it was discovered.
358
+ *
359
+ * @since 0.1.0
360
+ */
361
+ export declare const ConfigLocation: Schema.Struct<{
362
+ path: typeof Schema.String;
363
+ source: Schema.Literal<["lib", "root", "cosmiconfig"]>;
364
+ }>;
365
+
366
+ /** @since 0.1.0 */
367
+ export declare type ConfigLocation = typeof ConfigLocation.Type;
368
+
369
+ /**
370
+ * Raised when a config file cannot be located in any of the expected locations.
371
+ *
372
+ * @remarks
373
+ * Returned by consumers that require a config file to exist. {@link ConfigDiscovery.find}
374
+ * itself returns `null` instead of failing — callers that need a hard failure should
375
+ * map `null` to this error.
376
+ *
377
+ * @since 0.1.0
378
+ */
379
+ export declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
380
+ readonly name: string;
381
+ readonly searchedPaths: ReadonlyArray<string>;
382
+ }> {
383
+ get message(): string;
384
+ }
385
+
386
+ declare const ConfigNotFoundError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
387
+ readonly _tag: "ConfigNotFoundError";
388
+ } & Readonly<A>;
389
+
390
+ /**
391
+ * The discovery strategy used to locate a config file.
392
+ *
393
+ * @remarks
394
+ * - `"lib"` — found under `lib/configs/{name}` relative to the workspace root.
395
+ * - `"root"` — found directly in the workspace root as `{name}`.
396
+ * - `"cosmiconfig"` — reserved for future cosmiconfig-based discovery.
397
+ *
398
+ * @since 0.1.0
399
+ */
400
+ export declare const ConfigSource: Schema.Literal<["lib", "root", "cosmiconfig"]>;
401
+
402
+ /** @since 0.1.0 */
403
+ export declare type ConfigSource = typeof ConfigSource.Type;
404
+
405
+ /**
406
+ * Service providing managed section operations for tool-owned regions
407
+ * within user-editable files (e.g. husky hooks).
408
+ *
409
+ * @remarks
410
+ * A managed section is a delimited block in a file bounded by BEGIN/END marker comments.
411
+ * The markers embed the tool name so multiple tools can manage independent sections in
412
+ * the same file. User content outside the markers is always preserved.
413
+ *
414
+ * @example
415
+ * ```typescript
416
+ * const result = await Effect.runPromise(
417
+ * Effect.gen(function* () {
418
+ * const section = yield* ManagedSection;
419
+ * yield* section.write(".husky/pre-commit", "silk", "\nnpx lint-staged\n");
420
+ * return yield* section.read(".husky/pre-commit", "silk");
421
+ * }).pipe(
422
+ * Effect.provide(ManagedSectionLive),
423
+ * Effect.provide(NodeContext.layer),
424
+ * )
425
+ * );
426
+ * ```
427
+ *
428
+ * @since 0.1.0
429
+ */
430
+ export declare class ManagedSection extends ManagedSection_base {
431
+ }
432
+
433
+ declare const ManagedSection_base: Context.TagClass<ManagedSection, "@savvy-web/silk-effects/ManagedSection", {
434
+ /**
435
+ * Read and parse the managed section from a file.
436
+ *
437
+ * @param path - Absolute path to the file.
438
+ * @param toolName - Tool identifier embedded in the section markers.
439
+ * @param commentStyle - Comment prefix to use (`"#"` or `"//"`, defaults to `"#"`).
440
+ * @returns An `Effect` that succeeds with a {@link ManagedSectionResult} when markers
441
+ * are found, `null` when the file has no markers, or fails with
442
+ * {@link ManagedSectionParseError} on I/O errors.
443
+ *
444
+ * @since 0.1.0
445
+ */
446
+ readonly read: (path: string, toolName: string, commentStyle?: string) => Effect.Effect<ManagedSectionResult | null, ManagedSectionParseError>;
447
+ /**
448
+ * Write managed content to a file.
449
+ *
450
+ * @remarks
451
+ * - Replaces the existing managed section when markers are already present.
452
+ * - Appends a new managed section when the file exists but has no markers.
453
+ * - Creates the file when it does not exist.
454
+ *
455
+ * @param path - Absolute path to the file.
456
+ * @param toolName - Tool identifier embedded in the section markers.
457
+ * @param content - Content to place inside the managed section (between markers).
458
+ * @param commentStyle - Comment prefix to use (`"#"` or `"//"`, defaults to `"#"`).
459
+ * @returns An `Effect` that succeeds with `void` or fails with {@link ManagedSectionWriteError}.
460
+ *
461
+ * @since 0.1.0
462
+ */
463
+ readonly write: (path: string, toolName: string, content: string, commentStyle?: string) => Effect.Effect<void, ManagedSectionWriteError>;
464
+ /**
465
+ * Read-then-write convenience method that replaces managed content while
466
+ * preserving surrounding user content.
467
+ *
468
+ * @param path - Absolute path to the file.
469
+ * @param toolName - Tool identifier embedded in the section markers.
470
+ * @param content - Replacement content for the managed section.
471
+ * @param commentStyle - Comment prefix to use (`"#"` or `"//"`, defaults to `"#"`).
472
+ * @returns An `Effect` that succeeds with `void` or fails with {@link ManagedSectionWriteError}.
473
+ *
474
+ * @since 0.1.0
475
+ */
476
+ readonly update: (path: string, toolName: string, content: string, commentStyle?: string) => Effect.Effect<void, ManagedSectionWriteError>;
477
+ /**
478
+ * Return `true` when the file contains both BEGIN and END markers for the given tool.
479
+ *
480
+ * @param path - Absolute path to the file.
481
+ * @param toolName - Tool identifier to search for in the markers.
482
+ * @param commentStyle - Comment prefix to match (`"#"` or `"//"`, defaults to `"#"`).
483
+ * @returns An `Effect` that always succeeds with a boolean.
484
+ *
485
+ * @since 0.1.0
486
+ */
487
+ readonly isManaged: (path: string, toolName: string, commentStyle?: string) => Effect.Effect<boolean>;
488
+ }>;
489
+
490
+ /**
491
+ * Live implementation of {@link ManagedSection} backed by `@effect/platform` FileSystem.
492
+ *
493
+ * @remarks
494
+ * Requires `FileSystem` from `@effect/platform`. Provide `NodeContext.layer` or
495
+ * `BunContext.layer` to satisfy this dependency.
496
+ *
497
+ * @since 0.1.0
498
+ */
499
+ export declare const ManagedSectionLive: Layer.Layer<ManagedSection, never, FileSystem.FileSystem>;
500
+
501
+ /**
502
+ * Options controlling how managed sections are identified in a file.
503
+ *
504
+ * @remarks
505
+ * `toolName` is embedded in the BEGIN/END markers so multiple tools can coexist
506
+ * in the same file without collision. `commentStyle` defaults to `"#"`.
507
+ *
508
+ * @since 0.1.0
509
+ */
510
+ export declare const ManagedSectionOptions: Schema.Struct<{
511
+ toolName: typeof Schema.String;
512
+ commentStyle: Schema.optionalWith<Schema.Literal<["#", "//"]>, {
513
+ default: () => "#";
514
+ }>;
515
+ }>;
516
+
517
+ /** @since 0.1.0 */
518
+ export declare type ManagedSectionOptions = typeof ManagedSectionOptions.Type;
519
+
520
+ /**
521
+ * Raised when a managed section cannot be parsed from a file.
522
+ *
523
+ * @remarks
524
+ * Returned by {@link ManagedSection.read} when the file exists but its content
525
+ * cannot be read (e.g. a filesystem permission error).
526
+ *
527
+ * @since 0.1.0
528
+ */
529
+ export declare class ManagedSectionParseError extends ManagedSectionParseError_base<{
530
+ readonly path: string;
531
+ readonly reason: string;
532
+ }> {
533
+ get message(): string;
534
+ }
535
+
536
+ declare const ManagedSectionParseError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
537
+ readonly _tag: "ManagedSectionParseError";
538
+ } & Readonly<A>;
539
+
540
+ /**
541
+ * Parsed result of reading a managed section from a file.
542
+ *
543
+ * @remarks
544
+ * Produced by {@link ManagedSection.read}. The `before` and `after` strings
545
+ * contain the file content surrounding the managed block; `managed` holds the
546
+ * content between the BEGIN and END markers (excluding the markers themselves).
547
+ *
548
+ * @since 0.1.0
549
+ */
550
+ export declare const ManagedSectionResult: Schema.Struct<{
551
+ before: typeof Schema.String;
552
+ managed: typeof Schema.String;
553
+ after: typeof Schema.String;
554
+ }>;
555
+
556
+ /** @since 0.1.0 */
557
+ export declare type ManagedSectionResult = typeof ManagedSectionResult.Type;
558
+
559
+ /**
560
+ * Raised when a managed section cannot be written to a file.
561
+ *
562
+ * @remarks
563
+ * Returned by {@link ManagedSection.write} and {@link ManagedSection.update} when
564
+ * the file cannot be read for content replacement or when the write itself fails.
565
+ *
566
+ * @since 0.1.0
567
+ */
568
+ export declare class ManagedSectionWriteError extends ManagedSectionWriteError_base<{
569
+ readonly path: string;
570
+ readonly reason: string;
571
+ }> {
572
+ get message(): string;
573
+ }
574
+
575
+ declare const ManagedSectionWriteError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
576
+ readonly _tag: "ManagedSectionWriteError";
577
+ } & Readonly<A>;
578
+
579
+ /**
580
+ * Raised when the `publishConfig` field in a `package.json` is present but invalid.
581
+ *
582
+ * @remarks
583
+ * Returned by {@link SilkPublishabilityPlugin.detect} when `publishConfig` exists
584
+ * but cannot be mapped to a valid set of publish targets.
585
+ *
586
+ * @since 0.1.0
587
+ */
588
+ export declare class PublishConfigError extends PublishConfigError_base<{
589
+ readonly packageName: string;
590
+ readonly reason: string;
591
+ }> {
592
+ get message(): string;
593
+ }
594
+
595
+ declare const PublishConfigError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
596
+ readonly _tag: "PublishConfigError";
597
+ } & Readonly<A>;
598
+
599
+ /**
600
+ * The publish protocol used when pushing a package to a registry.
601
+ *
602
+ * @remarks
603
+ * `"npm"` covers all npm-compatible registries (npmjs.org, GitHub Packages, custom).
604
+ * `"jsr"` targets the JSR registry via its own publish tool.
605
+ *
606
+ * @since 0.1.0
607
+ */
608
+ export declare const PublishProtocol: Schema.Literal<["npm", "jsr"]>;
609
+
610
+ /** @since 0.1.0 */
611
+ export declare type PublishProtocol = typeof PublishProtocol.Type;
612
+
613
+ /**
614
+ * Union of all accepted publish-target representations.
615
+ *
616
+ * @remarks
617
+ * Accepts a {@link PublishTargetShorthand} string (`"npm"`, `"github"`, `"jsr"`),
618
+ * an `https://` URL pointing to a custom npm-compatible registry, or a full
619
+ * {@link PublishTargetObject} with explicit field overrides.
620
+ *
621
+ * @since 0.1.0
622
+ */
623
+ export declare const PublishTarget: Schema.Union<[Schema.Literal<["npm", "github", "jsr"]>, Schema.filter<typeof Schema.String>, Schema.Struct<{
624
+ protocol: Schema.optionalWith<Schema.Literal<["npm", "jsr"]>, {
625
+ default: () => "npm";
626
+ }>;
627
+ registry: Schema.optional<typeof Schema.String>;
628
+ directory: Schema.optional<typeof Schema.String>;
629
+ access: Schema.optional<Schema.Literal<["public", "restricted"]>>;
630
+ provenance: Schema.optional<typeof Schema.Boolean>;
631
+ tag: Schema.optional<typeof Schema.String>;
632
+ }>]>;
633
+
634
+ /** @since 0.1.0 */
635
+ export declare type PublishTarget = typeof PublishTarget.Type;
636
+
637
+ /**
638
+ * Full publish-target configuration expressed as a structured object.
639
+ *
640
+ * @remarks
641
+ * All fields are optional and fall back to sensible defaults when omitted.
642
+ * `protocol` defaults to `"npm"`. `access` defaults to the registry default.
643
+ *
644
+ * @since 0.1.0
645
+ */
646
+ export declare const PublishTargetObject: Schema.Struct<{
647
+ protocol: Schema.optionalWith<Schema.Literal<["npm", "jsr"]>, {
648
+ default: () => "npm";
649
+ }>;
650
+ registry: Schema.optional<typeof Schema.String>;
651
+ directory: Schema.optional<typeof Schema.String>;
652
+ access: Schema.optional<Schema.Literal<["public", "restricted"]>>;
653
+ provenance: Schema.optional<typeof Schema.Boolean>;
654
+ tag: Schema.optional<typeof Schema.String>;
655
+ }>;
656
+
657
+ /** @since 0.1.0 */
658
+ export declare type PublishTargetObject = typeof PublishTargetObject.Type;
659
+
660
+ /**
661
+ * Shorthand string identifiers for common publish destinations.
662
+ *
663
+ * @remarks
664
+ * - `"npm"` — the public npm registry, authenticated via OIDC.
665
+ * - `"github"` — GitHub Packages, authenticated via `GITHUB_TOKEN`.
666
+ * - `"jsr"` — the JSR registry, authenticated via OIDC.
667
+ *
668
+ * @since 0.1.0
669
+ */
670
+ export declare const PublishTargetShorthand: Schema.Literal<["npm", "github", "jsr"]>;
671
+
672
+ /** @since 0.1.0 */
673
+ export declare type PublishTargetShorthand = typeof PublishTargetShorthand.Type;
674
+
675
+ /**
676
+ * Fully resolved publish target with all fields populated and defaults applied.
677
+ *
678
+ * @remarks
679
+ * Produced by {@link TargetResolver.resolve} from any {@link PublishTarget} input.
680
+ * All optional fields from {@link PublishTargetObject} become required here,
681
+ * and `auth` / `tokenEnv` are derived from the registry URL.
682
+ *
683
+ * @since 0.1.0
684
+ */
685
+ export declare const ResolvedTarget: Schema.Struct<{
686
+ protocol: Schema.Literal<["npm", "jsr"]>;
687
+ registry: Schema.NullOr<typeof Schema.String>;
688
+ directory: typeof Schema.String;
689
+ access: Schema.Literal<["public", "restricted"]>;
690
+ provenance: typeof Schema.Boolean;
691
+ tag: typeof Schema.String;
692
+ auth: Schema.Literal<["oidc", "token"]>;
693
+ tokenEnv: Schema.NullOr<typeof Schema.String>;
694
+ }>;
695
+
696
+ /** @since 0.1.0 */
697
+ export declare type ResolvedTarget = typeof ResolvedTarget.Type;
698
+
699
+ /**
700
+ * Extended changeset config for repos using the `@savvy-web/changesets` changelog adapter.
701
+ *
702
+ * @remarks
703
+ * Extends {@link ChangesetConfig} with a `_isSilk` marker flag that is automatically
704
+ * set to `true`. Detected by {@link ChangesetConfigReader} when the `changelog` field
705
+ * references `@savvy-web/changesets`.
706
+ *
707
+ * @since 0.1.0
708
+ */
709
+ export declare const SilkChangesetConfig: Schema.extend<Schema.Struct<{
710
+ changelog: Schema.optional<Schema.Union<[typeof Schema.String, Schema.Array$<typeof Schema.Unknown>]>>;
711
+ commit: Schema.optional<typeof Schema.Boolean>;
712
+ fixed: Schema.optional<Schema.Array$<Schema.Array$<typeof Schema.String>>>;
713
+ linked: Schema.optional<Schema.Array$<Schema.Array$<typeof Schema.String>>>;
714
+ access: Schema.optional<Schema.Literal<["public", "restricted"]>>;
715
+ baseBranch: Schema.optional<typeof Schema.String>;
716
+ updateInternalDependencies: Schema.optional<Schema.Literal<["patch", "minor", "major"]>>;
717
+ ignore: Schema.optional<Schema.Array$<typeof Schema.String>>;
718
+ }>, Schema.Struct<{
719
+ _isSilk: Schema.optionalWith<typeof Schema.Boolean, {
720
+ default: () => true;
721
+ }>;
722
+ }>>;
723
+
724
+ /** @since 0.1.0 */
725
+ export declare type SilkChangesetConfig = typeof SilkChangesetConfig.Type;
726
+
727
+ /**
728
+ * Service that determines whether a package is publishable and resolves its targets.
729
+ *
730
+ * @remarks
731
+ * Inspects the `package.json` object using the Silk publishability rules:
732
+ * - `private: true` with no `publishConfig` → not publishable (empty array).
733
+ * - `publishConfig` without `access` or `targets` → not publishable.
734
+ * - `publishConfig.targets` (array) → resolved via {@link TargetResolver}.
735
+ * - `publishConfig.registry` → resolved as a single registry target.
736
+ * - Default → resolved as `"npm"`.
737
+ *
738
+ * @example
739
+ * ```typescript
740
+ * const result = await Effect.runPromise(
741
+ * Effect.gen(function* () {
742
+ * const plugin = yield* SilkPublishabilityPlugin;
743
+ * return yield* plugin.detect({ publishConfig: { access: "public" } });
744
+ * }).pipe(
745
+ * Effect.provide(SilkPublishabilityPluginLive),
746
+ * Effect.provide(TargetResolverLive),
747
+ * )
748
+ * );
749
+ * ```
750
+ *
751
+ * @since 0.1.0
752
+ */
753
+ export declare class SilkPublishabilityPlugin extends SilkPublishabilityPlugin_base {
754
+ }
755
+
756
+ declare const SilkPublishabilityPlugin_base: Context.TagClass<SilkPublishabilityPlugin, "@savvy-web/silk-effects/SilkPublishabilityPlugin", {
757
+ /**
758
+ * Inspect a parsed `package.json` object and return the resolved publish targets.
759
+ *
760
+ * @param pkgJson - The parsed `package.json` contents.
761
+ * @returns An `Effect` that succeeds with an array of {@link ResolvedTarget} records
762
+ * (empty when the package is not publishable), or fails with {@link TargetResolutionError}.
763
+ *
764
+ * @since 0.1.0
765
+ */
766
+ readonly detect: (pkgJson: Record<string, unknown>) => Effect.Effect<ReadonlyArray<ResolvedTarget>, TargetResolutionError>;
767
+ }>;
768
+
769
+ /**
770
+ * Live implementation of {@link SilkPublishabilityPlugin}.
771
+ *
772
+ * @remarks
773
+ * Requires {@link TargetResolver} to resolve target strings and objects.
774
+ *
775
+ * @since 0.1.0
776
+ */
777
+ export declare const SilkPublishabilityPluginLive: Layer.Layer<SilkPublishabilityPlugin, never, TargetResolver>;
778
+
779
+ /**
780
+ * Raised when a git tag string cannot be formatted for the given package name and version.
781
+ *
782
+ * @remarks
783
+ * Returned by {@link TagStrategy.formatTag} when the `version` argument is an empty string
784
+ * or another invariant prevents tag construction.
785
+ *
786
+ * @since 0.1.0
787
+ */
788
+ export declare class TagFormatError extends TagFormatError_base<{
789
+ readonly name: string;
790
+ readonly version: string;
791
+ readonly reason: string;
792
+ }> {
793
+ get message(): string;
794
+ }
795
+
796
+ declare const TagFormatError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
797
+ readonly _tag: "TagFormatError";
798
+ } & Readonly<A>;
799
+
800
+ /**
801
+ * Service that determines and applies the git-tag naming strategy for a release.
802
+ *
803
+ * @remarks
804
+ * Consumes a {@link VersioningStrategyResult} to pick between `"single"` and `"scoped"`
805
+ * tag formats, then formats tag strings accordingly. Independent versioning always
806
+ * produces scoped tags; single and fixed-group versioning produces a single shared tag.
807
+ *
808
+ * @example
809
+ * ```typescript
810
+ * const result = await Effect.runPromise(
811
+ * Effect.gen(function* () {
812
+ * const tags = yield* TagStrategy;
813
+ * const strategyType = yield* tags.determine({ type: "independent", fixedGroups: [], publishablePackages: [] });
814
+ * return yield* tags.formatTag("@my-org/pkg", "1.2.3", strategyType);
815
+ * }).pipe(Effect.provide(TagStrategyLive))
816
+ * );
817
+ * // => "@my-org/pkg@1.2.3"
818
+ * ```
819
+ *
820
+ * @since 0.1.0
821
+ */
822
+ export declare class TagStrategy extends TagStrategy_base {
823
+ }
824
+
825
+ declare const TagStrategy_base: Context.TagClass<TagStrategy, "@savvy-web/silk-effects/TagStrategy", {
826
+ /**
827
+ * Determine the appropriate tag strategy type from a versioning strategy result.
828
+ *
829
+ * @param versioningResult - The result of {@link VersioningStrategy.detect}.
830
+ * @returns An `Effect` that always succeeds with a {@link TagStrategyType}.
831
+ *
832
+ * @since 0.1.0
833
+ */
834
+ readonly determine: (versioningResult: VersioningStrategyResult) => Effect.Effect<TagStrategyType>;
835
+ /**
836
+ * Format a git tag string for a given package name, version, and strategy.
837
+ *
838
+ * @param name - The package name (e.g. `"@my-org/pkg"` or `"my-pkg"`).
839
+ * @param version - The semver version string (e.g. `"1.2.3"`). Must not be empty.
840
+ * @param strategy - The {@link TagStrategyType} to apply.
841
+ * @returns An `Effect` that resolves to the formatted tag string, or fails with
842
+ * {@link TagFormatError} when `version` is empty.
843
+ *
844
+ * @since 0.1.0
845
+ */
846
+ readonly formatTag: (name: string, version: string, strategy: TagStrategyType) => Effect.Effect<string, TagFormatError>;
847
+ }>;
848
+
849
+ /**
850
+ * Live implementation of {@link TagStrategy} with no external dependencies.
851
+ *
852
+ * @remarks
853
+ * All logic is pure: strategy determination and tag formatting involve no I/O.
854
+ *
855
+ * @since 0.1.0
856
+ */
857
+ export declare const TagStrategyLive: Layer.Layer<TagStrategy>;
858
+
859
+ /**
860
+ * Git tag naming strategy for a workspace.
861
+ *
862
+ * @remarks
863
+ * - `"single"` — one shared tag for the entire release (e.g. `1.2.3`).
864
+ * - `"scoped"` — a per-package tag that includes the package name (e.g. `@my-org/pkg@1.2.3`).
865
+ *
866
+ * Determined by {@link TagStrategy.determine} based on the {@link VersioningStrategyResult}.
867
+ *
868
+ * @since 0.1.0
869
+ */
870
+ export declare const TagStrategyType: Schema.Literal<["single", "scoped"]>;
871
+
872
+ /** @since 0.1.0 */
873
+ export declare type TagStrategyType = typeof TagStrategyType.Type;
874
+
875
+ /**
876
+ * Raised when a publish target value cannot be resolved into a {@link ResolvedTarget}.
877
+ *
878
+ * @remarks
879
+ * Returned by {@link TargetResolver.resolve} when the input is not a recognised shorthand,
880
+ * a valid `https://` URL, or a well-formed object target.
881
+ *
882
+ * @since 0.1.0
883
+ */
884
+ export declare class TargetResolutionError extends TargetResolutionError_base<{
885
+ readonly target: unknown;
886
+ readonly reason: string;
887
+ }> {
888
+ get message(): string;
889
+ }
890
+
891
+ declare const TargetResolutionError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
892
+ readonly _tag: "TargetResolutionError";
893
+ } & Readonly<A>;
894
+
895
+ /**
896
+ * Service that resolves raw publish-target values into fully-normalised {@link ResolvedTarget} records.
897
+ *
898
+ * @remarks
899
+ * Accepts a single target or an array of targets. Each item may be a
900
+ * {@link PublishTargetShorthand} string, an `https://` registry URL, or a
901
+ * {@link PublishTargetObject}. Unknown values produce a {@link TargetResolutionError}.
902
+ *
903
+ * @example
904
+ * ```typescript
905
+ * const result = await Effect.runPromise(
906
+ * Effect.gen(function* () {
907
+ * const resolver = yield* TargetResolver;
908
+ * return yield* resolver.resolve("npm");
909
+ * }).pipe(Effect.provide(TargetResolverLive))
910
+ * );
911
+ * ```
912
+ *
913
+ * @since 0.1.0
914
+ */
915
+ export declare class TargetResolver extends TargetResolver_base {
916
+ }
917
+
918
+ declare const TargetResolver_base: Context.TagClass<TargetResolver, "@savvy-web/silk-effects/TargetResolver", {
919
+ /**
920
+ * Resolve one target (or an array of targets) into an array of {@link ResolvedTarget} records.
921
+ *
922
+ * @param target - A single publish-target value or an array of them.
923
+ * @returns An `Effect` that succeeds with the resolved targets or fails with {@link TargetResolutionError}.
924
+ *
925
+ * @since 0.1.0
926
+ */
927
+ readonly resolve: (target: unknown) => Effect.Effect<ReadonlyArray<ResolvedTarget>, TargetResolutionError>;
928
+ }>;
929
+
930
+ /**
931
+ * Live implementation of {@link TargetResolver} with no external dependencies.
932
+ *
933
+ * @remarks
934
+ * All resolution logic is pure: shorthand strings, `https://` URLs, and object targets
935
+ * are mapped to {@link ResolvedTarget} records without any I/O.
936
+ *
937
+ * @since 0.1.0
938
+ */
939
+ export declare const TargetResolverLive: Layer.Layer<TargetResolver, never, never>;
940
+
941
+ /**
942
+ * Raised when the versioning strategy cannot be determined from the workspace state.
943
+ *
944
+ * @remarks
945
+ * Returned by {@link VersioningStrategy.detect} when an unexpected condition
946
+ * prevents strategy classification.
947
+ *
948
+ * @since 0.1.0
949
+ */
950
+ export declare class VersioningDetectionError extends VersioningDetectionError_base<{
951
+ readonly reason: string;
952
+ }> {
953
+ get message(): string;
954
+ }
955
+
956
+ declare const VersioningDetectionError_base: new <A extends Record<string, any> = {}>(args: VoidIfEmpty< { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => YieldableError & {
957
+ readonly _tag: "VersioningDetectionError";
958
+ } & Readonly<A>;
959
+
960
+ /**
961
+ * Service that classifies the versioning strategy used by a workspace.
962
+ *
963
+ * @remarks
964
+ * Reads the changesets config to inspect `fixed` groups, then determines whether
965
+ * the workspace uses a single-package, fixed-group, or independent versioning strategy.
966
+ * Falls back to safe defaults when the changeset config is unavailable.
967
+ *
968
+ * @example
969
+ * ```typescript
970
+ * const result = await Effect.runPromise(
971
+ * Effect.gen(function* () {
972
+ * const strategy = yield* VersioningStrategy;
973
+ * return yield* strategy.detect(["@my-org/pkg-a", "@my-org/pkg-b"]);
974
+ * }).pipe(
975
+ * Effect.provide(VersioningStrategyLive),
976
+ * Effect.provide(ChangesetConfigReaderLive),
977
+ * Effect.provide(NodeContext.layer),
978
+ * )
979
+ * );
980
+ * ```
981
+ *
982
+ * @since 0.1.0
983
+ */
984
+ export declare class VersioningStrategy extends VersioningStrategy_base {
985
+ }
986
+
987
+ declare const VersioningStrategy_base: Context.TagClass<VersioningStrategy, "@savvy-web/silk-effects/VersioningStrategy", {
988
+ /**
989
+ * Classify the versioning strategy for a list of publishable package names.
990
+ *
991
+ * @param publishablePackages - Package names (e.g. `"@my-org/pkg"`) that will be published.
992
+ * @param root - Workspace root directory to read changeset config from.
993
+ * @returns An `Effect` resolving to a {@link VersioningStrategyResult}, or failing with
994
+ * {@link VersioningDetectionError} on unexpected errors.
995
+ *
996
+ * @since 0.1.0
997
+ */
998
+ readonly detect: (publishablePackages: ReadonlyArray<string>, root: string) => Effect.Effect<VersioningStrategyResult, VersioningDetectionError>;
999
+ }>;
1000
+
1001
+ /**
1002
+ * Live implementation of {@link VersioningStrategy}.
1003
+ *
1004
+ * @remarks
1005
+ * Requires {@link ChangesetConfigReader} to read the workspace changeset configuration.
1006
+ * If the config file is absent, an empty `fixed` groups array is assumed.
1007
+ *
1008
+ * @since 0.1.0
1009
+ */
1010
+ export declare const VersioningStrategyLive: Layer.Layer<VersioningStrategy, never, ChangesetConfigReader>;
1011
+
1012
+ /**
1013
+ * Output of the versioning strategy detection, combining the strategy type with group metadata.
1014
+ *
1015
+ * @remarks
1016
+ * Produced by {@link VersioningStrategy.detect} and consumed by {@link TagStrategy.determine}
1017
+ * to decide on the appropriate git-tag format.
1018
+ *
1019
+ * @since 0.1.0
1020
+ */
1021
+ export declare const VersioningStrategyResult: Schema.Struct<{
1022
+ type: Schema.Literal<["single", "fixed-group", "independent"]>;
1023
+ fixedGroups: Schema.Array$<Schema.Array$<typeof Schema.String>>;
1024
+ publishablePackages: Schema.Array$<typeof Schema.String>;
1025
+ }>;
1026
+
1027
+ /** @since 0.1.0 */
1028
+ export declare type VersioningStrategyResult = typeof VersioningStrategyResult.Type;
1029
+
1030
+ /**
1031
+ * Versioning strategy classification for a workspace.
1032
+ *
1033
+ * @remarks
1034
+ * - `"single"` — one publishable package; a single version tag is used.
1035
+ * - `"fixed-group"` — all publishable packages are in the same changesets fixed group.
1036
+ * - `"independent"` — multiple publishable packages with independent version bumps.
1037
+ *
1038
+ * @since 0.1.0
1039
+ */
1040
+ export declare const VersioningStrategyType: Schema.Literal<["single", "fixed-group", "independent"]>;
1041
+
1042
+ /** @since 0.1.0 */
1043
+ export declare type VersioningStrategyType = typeof VersioningStrategyType.Type;
1044
+
1045
+ export { }