@effected/workspaces 0.9.0 → 0.9.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.
@@ -292,6 +292,11 @@ var PackageManagerDetector = class PackageManagerDetector extends Context.Servic
292
292
  * reads as a legitimate "no manager here" answer, so a consumer would branch
293
293
  * on it and proceed, never learning that the test simply forgot to stub.
294
294
  *
295
+ * The defect is also not absorbed by `Effect.catch` or any typed-error
296
+ * handler — deliberately, so code under test with a best-effort `catch`
297
+ * around detection cannot make the mandatory stub look optional; the
298
+ * unstubbed call still fails the test.
299
+ *
295
300
  * @param overrides - Members to supply; anything omitted dies on use.
296
301
  *
297
302
  * @example
package/Publishability.js CHANGED
@@ -137,8 +137,15 @@ var PublishabilityDetector = class extends Context.Service()("@effected/workspac
137
137
  * silence — `Layer.mergeAll(myDetector, Workspaces.layer())` resolved to the
138
138
  * default, because `mergeAll` is last-wins. For a service that decides
139
139
  * whether a package publishes and to which registry, that silent revert was
140
- * the worst available failure. The requirement now sits in `R`, so the
141
- * choice is made once, explicitly, and unmade wiring does not compile.
140
+ * the worst available failure.
141
+ *
142
+ * The composites do not *require* a detector either — nothing inside them
143
+ * asks a publishability question, so their `R` stays `FileSystem | Path`.
144
+ * The requirement instead surfaces in the `R` of each operation that asks
145
+ * (`VersioningStrategy.detect`, e.g.): a program that asks and never wires
146
+ * a detector fails to compile where that operation's `R` must close — which
147
+ * can be far from the layer-wiring site — and a program that never asks
148
+ * never supplies a publish policy at all.
142
149
  */
143
150
  static layerNpm = Layer.succeed(this, this.npm);
144
151
  /**
package/README.md CHANGED
@@ -232,7 +232,9 @@ A name miss in the derived `getPackage` fails with the service's own typed `Pack
232
232
  - `WorkspaceCatalogs` — pnpm catalog assembly and `catalog:` resolution, on pnpm's own catalog packages; `releaseAgeGate()` assembles the effective `@effected/npm` `ReleaseAgeGate` from inline `pnpm-workspace.yaml` release-age keys and replayed hook contributions, strictest-wins, in the same pass as the catalogs.
233
233
  - `LockfileReader` — locate and parse the workspace's lockfile through `@effected/lockfiles`.
234
234
  - `ChangeDetector` — git-range change detection over `@effected/git`'s `Git` service; swap the layer to mock it with no repository.
235
- - `PublishabilityDetector` — whether a package publishes and to where, as a `PublishTarget` (registry, directory, access, provenance). The default layer implements npm's semantics; swap the layer if yours differ.
235
+ - `PublishabilityDetector` — whether a package publishes and to where, as a `PublishTarget` (registry, directory, access, provenance). No composite provides one: pick `PublishabilityDetector.layerNpm` (standard npm semantics) or `.layerNone` (nothing publishes) and provide it explicitly.
236
+ - `ReleaseTag` / `TrackingTag` — release-tag formatting (`ReleaseTag.single` / `.scoped`, strict SemVer by default with no `v` prefix) and the floating major/minor alias derivation GitHub Actions-style consumers expect (`v1`, `v1.2`), plus `classifyTag` to tell a release tag from a tracking alias.
237
+ - `VersioningStrategy` — classify a workspace as `single`, `fixed-group` or `independent` from package names and fixed groups, or detect it live against `PublishabilityDetector`, and produce the release tags for a batch with `tagsFor`.
236
238
  - `findWorkspaceRootSync` / `getWorkspacePackagesSync` — the synchronous escape hatch for config-time callers that cannot await, over file and path operations you supply.
237
239
  - `@effected/workspaces/node-sync` — a second entry point holding the Node bindings for those operations (`nodeFileSystem`, `nodePath` and the `nodeSyncOps` bag), kept off the main entry so `node:*` never reaches a consumer that supplies its own.
238
240
 
@@ -326,7 +326,10 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
326
326
  * (a fabricated root path would leak into consumer path logic), so an
327
327
  * unstubbed `info()` call is a test-wiring mistake and fails loudly as a
328
328
  * defect rather than succeeding with a lie or failing with a dishonest
329
- * typed error.
329
+ * typed error. A defect is not absorbed by `Effect.catch` or any
330
+ * typed-error handler — deliberately, so code under test with a
331
+ * best-effort `catch` cannot make the mandatory stub look optional; the
332
+ * unstubbed call still fails the test.
330
333
  *
331
334
  * @example
332
335
  * ```ts
@@ -175,7 +175,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends Context.Service()("@ef
175
175
  return {
176
176
  at: Effect.fn("WorkspaceSnapshots.at")(function* (ref) {
177
177
  const root = yield* Effect.suspend(() => roots.find(options?.cwd ?? process.cwd()));
178
- const key = `${root}${ref}`;
178
+ const key = `${root}\0${ref}`;
179
179
  let memo = atCaches.get(key);
180
180
  if (memo === void 0) {
181
181
  const [resolveOnce, invalidate] = yield* Effect.cachedInvalidateWithTTL(computeAt(root, ref), Duration.infinity);
@@ -233,6 +233,13 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends Context.Service()("@ef
233
233
  * test-wiring mistake fails loudly as a defect rather than succeeding with a
234
234
  * lie.
235
235
  *
236
+ * **A defect is not absorbed by `Effect.catch` or any typed-error handler**,
237
+ * and that is the point: code under test with a best-effort `catch` around
238
+ * its snapshot reads cannot make a mandatory stub look optional — the
239
+ * unstubbed call still fails the test instead of quietly taking the catch
240
+ * branch. Only defect-level combinators (`Effect.catchDefect`,
241
+ * `Effect.exit`) would see it.
242
+ *
236
243
  * @example
237
244
  * ```ts
238
245
  * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
package/Workspaces.js CHANGED
@@ -42,11 +42,12 @@ const localExecLayer = (options) => Layer.effect(LocalExec, Effect.gen(function*
42
42
  cause
43
43
  })));
44
44
  if (Option.isNone(detected)) return Option.none();
45
- const { prefix, dlxPrefix } = LocalExec.prefixes(detected.value.name);
45
+ const { prefix, dlxPrefix, scriptPrefix } = LocalExec.prefixes(detected.value.name);
46
46
  return Option.some(ExecContext.make({
47
47
  label: detected.value.name,
48
48
  prefix,
49
49
  dlxPrefix,
50
+ scriptPrefix,
50
51
  directory: root.value
51
52
  }));
52
53
  }) };
@@ -60,13 +61,23 @@ var Workspaces = class {
60
61
  constructor() {}
61
62
  /**
62
63
  * Every service that needs only a filesystem: root, package-manager
63
- * detection, discovery, lockfile reading, catalogs and publishability.
64
+ * detection, discovery, lockfile reading and catalogs.
64
65
  *
65
66
  * @remarks
66
67
  * Requires core `FileSystem` and `Path`, which the consumer provides at the
67
68
  * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
68
69
  * `FileSystem.layerNoop`).
69
70
  *
71
+ * **`PublishabilityDetector` is neither provided nor required here.** The
72
+ * composite used to bake in npm semantics, which a naively-ordered override
73
+ * silently lost to; now it supplies no default, and — because nothing inside
74
+ * the composite asks a publishability question — it does not require one in
75
+ * `R` either. The requirement surfaces in the `R` of each operation that
76
+ * asks (`VersioningStrategy.detect`, e.g.), so a program that asks and never
77
+ * wires a detector fails to compile at that operation, and a program that
78
+ * never asks never supplies a publish policy. Wire one explicitly where
79
+ * needed: `Layer.mergeAll(Workspaces.layer(), PublishabilityDetector.layerNpm)`.
80
+ *
70
81
  * **Bind the result to a `const`.** This is a parameterized factory and
71
82
  * layers memoize by reference, so calling it twice builds everything twice.
72
83
  *
@@ -122,7 +133,8 @@ var Workspaces = class {
122
133
  * it. So `commands` declares the narrow contract and we ship the layer.
123
134
  *
124
135
  * **The argv knowledge is not duplicated.** `LocalExec.prefixes(name)` is
125
- * the one home of the four managers' `exec`/`dlx` prefixes; this layer
136
+ * the one home of the four managers' `exec`/`dlx`/script-runner prefixes;
137
+ * this layer
126
138
  * detects *which* manager owns the directory and asks `commands` what that
127
139
  * manager's argv looks like. Neither package reimplements the other's
128
140
  * half.
package/index.d.ts CHANGED
@@ -607,7 +607,10 @@ declare class WorkspaceDiscovery extends WorkspaceDiscovery_base {
607
607
  * (a fabricated root path would leak into consumer path logic), so an
608
608
  * unstubbed `info()` call is a test-wiring mistake and fails loudly as a
609
609
  * defect rather than succeeding with a lie or failing with a dishonest
610
- * typed error.
610
+ * typed error. A defect is not absorbed by `Effect.catch` or any
611
+ * typed-error handler — deliberately, so code under test with a
612
+ * best-effort `catch` cannot make the mandatory stub look optional; the
613
+ * unstubbed call still fails the test.
611
614
  *
612
615
  * @example
613
616
  * ```ts
@@ -1126,6 +1129,11 @@ declare class PackageManagerDetector extends PackageManagerDetector_base {
1126
1129
  * reads as a legitimate "no manager here" answer, so a consumer would branch
1127
1130
  * on it and proceed, never learning that the test simply forgot to stub.
1128
1131
  *
1132
+ * The defect is also not absorbed by `Effect.catch` or any typed-error
1133
+ * handler — deliberately, so code under test with a best-effort `catch`
1134
+ * around detection cannot make the mandatory stub look optional; the
1135
+ * unstubbed call still fails the test.
1136
+ *
1129
1137
  * @param overrides - Members to supply; anything omitted dies on use.
1130
1138
  *
1131
1139
  * @example
@@ -1474,8 +1482,15 @@ declare class PublishabilityDetector extends PublishabilityDetector_base {
1474
1482
  * silence — `Layer.mergeAll(myDetector, Workspaces.layer())` resolved to the
1475
1483
  * default, because `mergeAll` is last-wins. For a service that decides
1476
1484
  * whether a package publishes and to which registry, that silent revert was
1477
- * the worst available failure. The requirement now sits in `R`, so the
1478
- * choice is made once, explicitly, and unmade wiring does not compile.
1485
+ * the worst available failure.
1486
+ *
1487
+ * The composites do not *require* a detector either — nothing inside them
1488
+ * asks a publishability question, so their `R` stays `FileSystem | Path`.
1489
+ * The requirement instead surfaces in the `R` of each operation that asks
1490
+ * (`VersioningStrategy.detect`, e.g.): a program that asks and never wires
1491
+ * a detector fails to compile where that operation's `R` must close — which
1492
+ * can be far from the layer-wiring site — and a program that never asks
1493
+ * never supplies a publish policy at all.
1479
1494
  */
1480
1495
  static readonly layerNpm: Layer.Layer<PublishabilityDetector>;
1481
1496
  /**
@@ -2427,6 +2442,13 @@ declare class WorkspaceSnapshots extends WorkspaceSnapshots_base {
2427
2442
  * test-wiring mistake fails loudly as a defect rather than succeeding with a
2428
2443
  * lie.
2429
2444
  *
2445
+ * **A defect is not absorbed by `Effect.catch` or any typed-error handler**,
2446
+ * and that is the point: code under test with a best-effort `catch` around
2447
+ * its snapshot reads cannot make a mandatory stub look optional — the
2448
+ * unstubbed call still fails the test instead of quietly taking the catch
2449
+ * branch. Only defect-level combinators (`Effect.catchDefect`,
2450
+ * `Effect.exit`) would see it.
2451
+ *
2430
2452
  * @example
2431
2453
  * ```ts
2432
2454
  * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
@@ -2502,13 +2524,23 @@ declare class Workspaces {
2502
2524
  private constructor();
2503
2525
  /**
2504
2526
  * Every service that needs only a filesystem: root, package-manager
2505
- * detection, discovery, lockfile reading, catalogs and publishability.
2527
+ * detection, discovery, lockfile reading and catalogs.
2506
2528
  *
2507
2529
  * @remarks
2508
2530
  * Requires core `FileSystem` and `Path`, which the consumer provides at the
2509
2531
  * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
2510
2532
  * `FileSystem.layerNoop`).
2511
2533
  *
2534
+ * **`PublishabilityDetector` is neither provided nor required here.** The
2535
+ * composite used to bake in npm semantics, which a naively-ordered override
2536
+ * silently lost to; now it supplies no default, and — because nothing inside
2537
+ * the composite asks a publishability question — it does not require one in
2538
+ * `R` either. The requirement surfaces in the `R` of each operation that
2539
+ * asks (`VersioningStrategy.detect`, e.g.), so a program that asks and never
2540
+ * wires a detector fails to compile at that operation, and a program that
2541
+ * never asks never supplies a publish policy. Wire one explicitly where
2542
+ * needed: `Layer.mergeAll(Workspaces.layer(), PublishabilityDetector.layerNpm)`.
2543
+ *
2512
2544
  * **Bind the result to a `const`.** This is a parameterized factory and
2513
2545
  * layers memoize by reference, so calling it twice builds everything twice.
2514
2546
  *
@@ -2564,7 +2596,8 @@ declare class Workspaces {
2564
2596
  * it. So `commands` declares the narrow contract and we ship the layer.
2565
2597
  *
2566
2598
  * **The argv knowledge is not duplicated.** `LocalExec.prefixes(name)` is
2567
- * the one home of the four managers' `exec`/`dlx` prefixes; this layer
2599
+ * the one home of the four managers' `exec`/`dlx`/script-runner prefixes;
2600
+ * this layer
2568
2601
  * detects *which* manager owns the directory and asks `commands` what that
2569
2602
  * manager's argv looks like. Neither package reimplements the other's
2570
2603
  * half.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/workspaces",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "private": false,
5
5
  "description": "Monorepo workspace tooling as Effect services — root discovery, package enumeration, the dependency graph, package-manager detection, pnpm catalog resolution, lockfile IO and git-based change detection.",
6
6
  "keywords": [
@@ -46,12 +46,12 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@effected/commands": "~0.1.0",
49
+ "@effected/commands": "~0.2.0",
50
50
  "@effected/git": "~0.5.1",
51
51
  "@effected/glob": "~0.2.1",
52
- "@effected/lockfiles": "~0.2.1",
53
- "@effected/npm": "~0.5.0",
54
- "@effected/package-json": "~0.6.0",
52
+ "@effected/lockfiles": "~0.2.2",
53
+ "@effected/npm": "~0.6.0",
54
+ "@effected/package-json": "~0.6.1",
55
55
  "@effected/semver": "~0.2.1",
56
56
  "@effected/walker": "~0.3.3",
57
57
  "@effected/yaml": "~0.6.0",