@effected/workspaces 0.5.1 → 0.6.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.
@@ -39,17 +39,45 @@ const seedToConfig = (seed) => {
39
39
  else catalogs[name] = { ...entries };
40
40
  return {
41
41
  catalog,
42
- catalogs
42
+ catalogs,
43
+ minimumReleaseAge: void 0,
44
+ minimumReleaseAgeExclude: void 0
43
45
  };
44
46
  };
45
- /** Read the catalog slice back out of whatever a hook returned, falling back to the prior config. */
47
+ /** A finite number if `value` is one, else the prior threaded value a garbage age is dropped, not fatal. */
48
+ const finiteNumberOr = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
49
+ /** A string array if `value` is one, else the prior threaded value — a malformed exclude is dropped, not fatal. */
50
+ const stringArrayOr = (value, fallback) => Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : fallback;
51
+ /**
52
+ * Read the catalog slice and the release-age keys back out of whatever a hook
53
+ * returned, threading the prior config as the fallback.
54
+ *
55
+ * @remarks
56
+ * Tolerant by design, matching this seam's discipline: a hook's returned *data*
57
+ * is normalized, never a typed failure (only a load/replay *mechanism* failure
58
+ * raises `CatalogAssemblyError`). A hook that omits a key, or returns a
59
+ * malformed value for it, leaves the prior threaded value in place; a hook that
60
+ * sets a well-formed key rewrites it — so across hooks the **last well-formed
61
+ * write wins**, exactly as pnpm's single mutable config object behaves.
62
+ */
46
63
  const configOf = (value, fallback) => {
47
64
  if (!isObject(value)) return fallback;
48
65
  return {
49
66
  catalog: isObject(value.catalog) ? value.catalog : fallback.catalog,
50
- catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs
67
+ catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs,
68
+ minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
69
+ minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude)
51
70
  };
52
71
  };
72
+ /**
73
+ * Project the threaded config's release-age keys into a partial gate
74
+ * contribution, omitting a key the hooks never set (never an explicit
75
+ * `undefined` — the fields are `optionalKey`).
76
+ */
77
+ const releaseAgeOf = (config) => ({
78
+ ...config.minimumReleaseAge !== void 0 ? { ageMinutes: config.minimumReleaseAge } : {},
79
+ ...config.minimumReleaseAgeExclude !== void 0 ? { exclude: config.minimumReleaseAgeExclude } : {}
80
+ });
53
81
  /** Fold the hook config back into the normalized `catalog name → dependency → range` record. */
54
82
  const configToEntries = (config) => {
55
83
  const raw = { ...config.catalogs };
@@ -89,7 +117,10 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends Context.Service(
89
117
  * config dependency. The default {@link WorkspaceCatalogs} layer wires this, so
90
118
  * the default catalog path provably executes no config-dependency code.
91
119
  */
92
- static layerNoop = Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed) => Effect.succeed(seed) });
120
+ static layerNoop = Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed) => Effect.succeed({
121
+ catalogs: seed,
122
+ releaseAge: {}
123
+ }) });
93
124
  /**
94
125
  * The live layer: dynamically imports each config dependency's `pnpmfile.cjs`
95
126
  * (in process, no subprocess) and replays its `updateConfig` hook over the
@@ -108,7 +139,10 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends Context.Service(
108
139
  */
109
140
  static layerLive = Layer.succeed(ConfigDependencyHooks, { inject: (root, configDependencies, seed) => Effect.gen(function* () {
110
141
  const names = Object.keys(configDependencies);
111
- if (names.length === 0) return seed;
142
+ if (names.length === 0) return {
143
+ catalogs: seed,
144
+ releaseAge: {}
145
+ };
112
146
  let config = seedToConfig(seed);
113
147
  for (const name of names) {
114
148
  if (hasTraversalSegment(name)) return yield* Effect.fail(new CatalogAssemblyError({
@@ -149,7 +183,10 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends Context.Service(
149
183
  })
150
184
  });
151
185
  }
152
- return configToEntries(config);
186
+ return {
187
+ catalogs: configToEntries(config),
188
+ releaseAge: releaseAgeOf(config)
189
+ };
153
190
  }) });
154
191
  };
155
192
 
package/README.md CHANGED
@@ -215,7 +215,7 @@ A name miss in the derived `getPackage` fails with the service's own typed `Pack
215
215
  - `WorkspacePackage` — a deliberately tolerant manifest model, so one member with an odd version cannot fail discovery for the whole repo. `manifestRecord` keeps the as-read `package.json` for tolerant access to fields outside the typed slice without a second read; `WorkspacePackage.manifest(pkg)` re-reads and is the opt-in bridge to `@effected/package-json`'s strict `Package`.
216
216
  - `DependencyGraph` — a value class over discovered packages: `levels()` for parallel build tiers, the flattened topological order, and `CyclicDependencyError` when there isn't one.
217
217
  - `PackageManagerDetector` — npm, pnpm, yarn or bun from lockfiles and the `packageManager` field.
218
- - `WorkspaceCatalogs` — pnpm catalog assembly and `catalog:` resolution, on pnpm's own catalog packages.
218
+ - `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.
219
219
  - `LockfileReader` — locate and parse the workspace's lockfile through `@effected/lockfiles`.
220
220
  - `ChangeDetector` — git-range change detection over `@effected/git`'s `Git` service; swap the layer to mock it with no repository.
221
221
  - `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.
@@ -3,7 +3,7 @@ import { inlineCatalogs, merge, normalize, rangeOf } from "./internal/catalogs.j
3
3
  import { ConfigDependencyHooks } from "./ConfigDependencyHooks.js";
4
4
  import { LockfileReader } from "./LockfileReader.js";
5
5
  import { Context, Duration, Effect, Exit, FileSystem, Layer, Option, Path, PlatformError, Schema } from "effect";
6
- import { CatalogAssemblyError, CatalogResolver, DependencyResolutionError } from "@effected/npm";
6
+ import { CatalogAssemblyError, CatalogResolver, DependencyResolutionError, PartialReleaseAgeGate, ReleaseAgeGate } from "@effected/npm";
7
7
  import { Yaml } from "@effected/yaml";
8
8
 
9
9
  //#region src/WorkspaceCatalogs.ts
@@ -179,6 +179,37 @@ const configDependenciesOf = (document) => {
179
179
  for (const [name, spec] of Object.entries(document.configDependencies)) if (typeof spec === "string") out[name] = spec;
180
180
  return out;
181
181
  };
182
+ /**
183
+ * The inline release-age gate contribution of a parsed `pnpm-workspace.yaml`
184
+ * document — pnpm's top-level `minimumReleaseAge` (minutes) and
185
+ * `minimumReleaseAgeExclude` (name patterns) keys, mapped onto
186
+ * `@effected/npm`'s `PartialReleaseAgeGate` field names
187
+ * (`ageMinutes` / `exclude`).
188
+ *
189
+ * @remarks
190
+ * **Hard-fail by design**, the same posture as the live catalog-block reader:
191
+ * a present-but-malformed value (a non-numeric `minimumReleaseAge`, a
192
+ * `minimumReleaseAgeExclude` that is not a string array) fails typed as a
193
+ * `CatalogAssemblyError` rather than being silently dropped, because a
194
+ * silently-ignored gate is the "install refuses a too-young version the
195
+ * resolver already picked" bug this vocabulary exists to prevent. An absent or
196
+ * explicitly `null` key contributes nothing; the permissive
197
+ * `PartialReleaseAgeGate` accepts any finite `ageMinutes` (negatives and
198
+ * fractions included) — `ReleaseAgeGate.combine` is the single clamping
199
+ * authority, exactly as on the hook path.
200
+ */
201
+ const inlineReleaseAge = (document) => {
202
+ if (!isObject(document)) return Effect.succeed({});
203
+ const raw = {};
204
+ if (document.minimumReleaseAge !== void 0 && document.minimumReleaseAge !== null) raw.ageMinutes = document.minimumReleaseAge;
205
+ if (document.minimumReleaseAgeExclude !== void 0 && document.minimumReleaseAgeExclude !== null) raw.exclude = document.minimumReleaseAgeExclude;
206
+ if (Object.keys(raw).length === 0) return Effect.succeed({});
207
+ return Schema.decodeUnknownEffect(PartialReleaseAgeGate)(raw).pipe(Effect.catchTag("SchemaError", (cause) => new CatalogAssemblyError({
208
+ source: "manifest",
209
+ path: "pnpm-workspace.yaml",
210
+ cause
211
+ })));
212
+ };
182
213
  /** A hard-fail catalog-assembly failure naming the malformed part of a `workspaces` field. */
183
214
  const malformed = (source, path, detail) => new CatalogAssemblyError({
184
215
  source,
@@ -299,6 +330,8 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
299
330
  const hasPnpmWorkspace = yield* probeExists(workspaceYaml);
300
331
  let inline;
301
332
  let injected;
333
+ let inlineGate = {};
334
+ let hookGate = {};
302
335
  if (hasPnpmWorkspace) {
303
336
  const text = yield* fs.readFileString(workspaceYaml).pipe(Effect.mapError((cause) => new CatalogAssemblyError({
304
337
  source: "manifest",
@@ -312,11 +345,16 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
312
345
  })));
313
346
  yield* validatePnpmWorkspaceCatalogs(document);
314
347
  inline = CatalogSet.fromCatalogs(inlineCatalogs(catalogBlocksOf(document)));
315
- const injectedEntries = yield* hooks.inject(root, configDependenciesOf(document), inline.entries);
316
- injected = CatalogSet.fromCatalogs(injectedEntries);
348
+ inlineGate = yield* inlineReleaseAge(document);
349
+ const injection = yield* hooks.inject(root, configDependenciesOf(document), inline.entries);
350
+ injected = CatalogSet.fromCatalogs(injection.catalogs);
351
+ hookGate = injection.releaseAge;
317
352
  } else {
318
353
  const manifestPath = path.join(root, "package.json");
319
- if (!(yield* probeExists(manifestPath))) return fromLockfile;
354
+ if (!(yield* probeExists(manifestPath))) return {
355
+ catalogs: fromLockfile,
356
+ releaseAgeGate: ReleaseAgeGate.combine()
357
+ };
320
358
  const text = yield* fs.readFileString(manifestPath).pipe(Effect.mapError((cause) => new CatalogAssemblyError({
321
359
  source: "manifest",
322
360
  path: manifestPath,
@@ -326,20 +364,28 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
326
364
  injected = CatalogSet.empty();
327
365
  }
328
366
  const assembled = CatalogSet.merge(fromLockfile, inline, injected);
367
+ const releaseAgeGate = ReleaseAgeGate.combine(inlineGate, hookGate);
329
368
  yield* Effect.logDebug("Catalogs assembled").pipe(Effect.annotateLogs({
330
369
  "workspace.root": root,
331
- "workspace.catalogs": Object.keys(assembled.entries).join(",")
370
+ "workspace.catalogs": Object.keys(assembled.entries).join(","),
371
+ "workspace.releaseAgeMinutes": releaseAgeGate.ageMinutes
332
372
  }));
333
- return assembled;
373
+ return {
374
+ catalogs: assembled,
375
+ releaseAgeGate
376
+ };
334
377
  });
335
378
  const [resolveOnce, invalidate] = yield* Effect.cachedInvalidateWithTTL(assemble, Duration.infinity);
336
379
  const memo = Effect.onExit(resolveOnce, (exit) => Exit.isSuccess(exit) ? Effect.void : invalidate);
337
380
  return {
338
381
  set: Effect.fn("WorkspaceCatalogs.set")(function* () {
339
- return yield* memo;
382
+ return (yield* memo).catalogs;
340
383
  }),
341
384
  resolveSpecifier: Effect.fn("WorkspaceCatalogs.resolveSpecifier")(function* (dependency, specifier) {
342
- return (yield* memo).resolveSpecifier(dependency, specifier);
385
+ return (yield* memo).catalogs.resolveSpecifier(dependency, specifier);
386
+ }),
387
+ releaseAgeGate: Effect.fn("WorkspaceCatalogs.releaseAgeGate")(function* () {
388
+ return (yield* memo).releaseAgeGate;
343
389
  })
344
390
  };
345
391
  });
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Git, GitCommandError, NotARepositoryError, UnknownRefError } from "@effected/git";
2
2
  import { Context, Effect, FileSystem, Layer, Option, Path, Schema } from "effect";
3
- import { CatalogAssemblyError, CatalogResolver, DependencyResolutionError, Manifest, UnresolvedDependencyError, WorkspaceResolver } from "@effected/npm";
3
+ import { CatalogAssemblyError, CatalogResolver, DependencyResolutionError, Manifest, PartialReleaseAgeGate, ReleaseAgeGate, UnresolvedDependencyError, WorkspaceResolver } from "@effected/npm";
4
4
  import { GlobPattern } from "@effected/glob";
5
5
  import { Lockfile, LockfileFramingError, LockfileIntegrity, LockfileParseError, ResolvedPackage, WorkspaceManifest } from "@effected/lockfiles";
6
6
  import { Package } from "@effected/package-json";
@@ -793,22 +793,56 @@ declare class ChangeDetector extends ChangeDetector_base {
793
793
  }
794
794
  //#endregion
795
795
  //#region src/ConfigDependencyHooks.d.ts
796
+ /**
797
+ * The result of replaying a workspace's `configDependencies` hooks: the catalogs
798
+ * the hooks yield, and the release-age gate contribution they leave on the
799
+ * config (pnpm's `minimumReleaseAge` / `minimumReleaseAgeExclude`).
800
+ *
801
+ * @remarks
802
+ * `releaseAge` is a `PartialReleaseAgeGate` — the age, the exclude list,
803
+ * both, or neither, depending on what the replayed hooks set. It is deliberately
804
+ * a *partial* contribution: a consumer folds it into an effective gate with
805
+ * `ReleaseAgeGate.combine` alongside inline `pnpm-workspace.yaml` values. Hooks
806
+ * that set no release-age keys contribute an empty gate (`{}`).
807
+ *
808
+ * @public
809
+ */
810
+ interface HookInjection {
811
+ /** The catalogs the replayed hooks yield, as `catalog name → dependency → range`. */
812
+ readonly catalogs: Readonly<Record<string, Readonly<Record<string, string>>>>;
813
+ /** The release-age gate contribution the replayed hooks leave on the config. */
814
+ readonly releaseAge: PartialReleaseAgeGate;
815
+ }
796
816
  /**
797
817
  * The {@link ConfigDependencyHooks} service shape.
798
818
  *
799
819
  * @remarks
800
820
  * `inject` is given the workspace root, the manifest's `configDependencies`
801
821
  * (name → version+integrity), and the inline-catalog seed as a plain
802
- * `catalog name → dependency name → range` record, and produces the catalogs the
803
- * replayed hooks yield. The default (no-op) implementation returns the seed
804
- * unchanged and loads nothing.
822
+ * `catalog name → dependency name → range` record, and produces a
823
+ * {@link HookInjection}: the catalogs the replayed hooks yield **and** the
824
+ * release-age gate contribution they leave on the config. The default (no-op)
825
+ * implementation returns the seed catalogs unchanged, contributes an empty
826
+ * release-age gate, and loads nothing.
805
827
  *
806
828
  * @public
807
829
  */
808
830
  interface ConfigDependencyHooksShape {
809
831
  /**
810
832
  * Replay each config dependency's `updateConfig` hook over `seed`, in
811
- * declaration order, and return the resulting catalogs.
833
+ * declaration order, and return both the resulting catalogs and the
834
+ * release-age gate contribution the hooks leave behind.
835
+ *
836
+ * @remarks
837
+ * The hooks are replayed once over a single threaded config object, exactly
838
+ * as pnpm does — so catalogs and the release-age keys
839
+ * (`minimumReleaseAge` / `minimumReleaseAgeExclude`) are both read off that
840
+ * one final object, and the config-dependency code executes only once. When
841
+ * two hooks both set a release-age key the **later hook wins** (it rewrites
842
+ * the threaded value); a hook that returns a malformed value for a key leaves
843
+ * the prior threaded value in place (tolerant threading, matching the catalog
844
+ * slice). A hook failing to load or replay fails typed with a
845
+ * `hooks`-source `CatalogAssemblyError`, never a silent skip.
812
846
  *
813
847
  * @param root - The workspace root; config dependencies resolve under
814
848
  * `<root>/node_modules/.pnpm-config/<name>`.
@@ -816,7 +850,7 @@ interface ConfigDependencyHooksShape {
816
850
  * version+integrity) declared in `pnpm-workspace.yaml`.
817
851
  * @param seed - The inline catalogs, as `catalog name → dependency → range`.
818
852
  */
819
- readonly inject: (root: string, configDependencies: Readonly<Record<string, string>>, seed: Readonly<Record<string, Readonly<Record<string, string>>>>) => Effect.Effect<Readonly<Record<string, Readonly<Record<string, string>>>>, CatalogAssemblyError>;
853
+ readonly inject: (root: string, configDependencies: Readonly<Record<string, string>>, seed: Readonly<Record<string, Readonly<Record<string, string>>>>) => Effect.Effect<HookInjection, CatalogAssemblyError>;
820
854
  }
821
855
  declare const ConfigDependencyHooks_base: Context.ServiceClass<ConfigDependencyHooks, "@effected/workspaces/ConfigDependencyHooks", ConfigDependencyHooksShape>;
822
856
  /**
@@ -1407,6 +1441,20 @@ interface WorkspaceCatalogsShape {
1407
1441
  readonly set: () => Effect.Effect<CatalogSet, CatalogAssemblyFailure>;
1408
1442
  /** Resolve one `catalog:` specifier; `Option.none()` when it names nothing. */
1409
1443
  readonly resolveSpecifier: (dependency: string, specifier: string) => Effect.Effect<Option.Option<string>, CatalogAssemblyFailure>;
1444
+ /**
1445
+ * The effective pnpm release-age gate for the workspace, combined
1446
+ * strictest-wins from the inline `pnpm-workspace.yaml` keys
1447
+ * (`minimumReleaseAge` / `minimumReleaseAgeExclude`) and the replayed
1448
+ * config-dependency hooks. Assembled from the same single read and hook
1449
+ * replay as `set`, and memoized with it.
1450
+ *
1451
+ * @remarks
1452
+ * Under the default layer (no-op hooks) only inline values contribute; under
1453
+ * {@link WorkspaceCatalogs.layerWithConfigDependencies} the replayed hooks
1454
+ * contribute too. A workspace with no pnpm-workspace.yaml (a bun/npm
1455
+ * workspace) has no release-age keys, so the gate is the inert zero gate.
1456
+ */
1457
+ readonly releaseAgeGate: () => Effect.Effect<ReleaseAgeGate, CatalogAssemblyFailure>;
1410
1458
  }
1411
1459
  /**
1412
1460
  * Options for the {@link WorkspaceCatalogs} layer.
@@ -1931,5 +1979,5 @@ interface GetWorkspacePackagesSyncOptions extends WorkspacesSyncOptions {
1931
1979
  */
1932
1980
  declare const getWorkspacePackagesSync: (root: string, options: GetWorkspacePackagesSyncOptions) => ReadonlyArray<WorkspacePackage>;
1933
1981
  //#endregion
1934
- export { type CatalogAssemblyFailure, CatalogSet, ChangeDetectionError, type ChangeDetectionFailure, ChangeDetectionOptions, ChangeDetector, type ChangeDetectorShape, ConfigDependencyHooks, type ConfigDependencyHooksShape, CyclicDependencyError, type DependencyDiff, DependencyGraph, DetectedPackageManager, type FindWorkspaceRootOptions, type GetWorkspacePackagesSyncOptions, LockfileReadError, type LockfileReadFailure, LockfileReader, type LockfileReaderOptions, type LockfileReaderShape, PackageManagerDetectionError, type PackageManagerDetectionFailure, PackageManagerDetector, PackageManagerName, PackageNotFoundError, PackageStateSnapshot, PublishConfig, PublishTarget, PublishabilityDetector, type PublishabilityDetectorShape, type SyncFileSystem, type SyncPath, WORKSPACE_MARKERS, WorkspaceCatalogs, type WorkspaceCatalogsOptions, type WorkspaceCatalogsShape, WorkspaceDiscovery, WorkspaceDiscoveryError, type WorkspaceDiscoveryFailure, type WorkspaceDiscoveryOptions, type WorkspaceDiscoveryShape, WorkspaceInfo, type WorkspaceLookupFailure, WorkspaceManifestError, WorkspacePackage, WorkspacePatternError, WorkspaceRoot, WorkspaceRootNotFoundError, type WorkspaceRootShape, type WorkspaceSnapshotAtFailure, type WorkspaceSnapshotWorktreeFailure, WorkspaceSnapshots, type WorkspaceSnapshotsOptions, type WorkspaceSnapshotsShape, WorkspaceStateSnapshot, Workspaces, type WorkspacesOptions, type WorkspacesServices, type WorkspacesSyncOptions, findWorkspaceRootSync, getWorkspacePackagesSync };
1982
+ export { type CatalogAssemblyFailure, CatalogSet, ChangeDetectionError, type ChangeDetectionFailure, ChangeDetectionOptions, ChangeDetector, type ChangeDetectorShape, ConfigDependencyHooks, type ConfigDependencyHooksShape, CyclicDependencyError, type DependencyDiff, DependencyGraph, DetectedPackageManager, type FindWorkspaceRootOptions, type GetWorkspacePackagesSyncOptions, type HookInjection, LockfileReadError, type LockfileReadFailure, LockfileReader, type LockfileReaderOptions, type LockfileReaderShape, PackageManagerDetectionError, type PackageManagerDetectionFailure, PackageManagerDetector, PackageManagerName, PackageNotFoundError, PackageStateSnapshot, PublishConfig, PublishTarget, PublishabilityDetector, type PublishabilityDetectorShape, type SyncFileSystem, type SyncPath, WORKSPACE_MARKERS, WorkspaceCatalogs, type WorkspaceCatalogsOptions, type WorkspaceCatalogsShape, WorkspaceDiscovery, WorkspaceDiscoveryError, type WorkspaceDiscoveryFailure, type WorkspaceDiscoveryOptions, type WorkspaceDiscoveryShape, WorkspaceInfo, type WorkspaceLookupFailure, WorkspaceManifestError, WorkspacePackage, WorkspacePatternError, WorkspaceRoot, WorkspaceRootNotFoundError, type WorkspaceRootShape, type WorkspaceSnapshotAtFailure, type WorkspaceSnapshotWorktreeFailure, WorkspaceSnapshots, type WorkspaceSnapshotsOptions, type WorkspaceSnapshotsShape, WorkspaceStateSnapshot, Workspaces, type WorkspacesOptions, type WorkspacesServices, type WorkspacesSyncOptions, findWorkspaceRootSync, getWorkspacePackagesSync };
1935
1983
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/workspaces",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
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,14 +46,14 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@effected/git": "0.4.1",
50
- "@effected/glob": "0.2.0",
51
- "@effected/lockfiles": "0.1.7",
52
- "@effected/npm": "0.2.2",
53
- "@effected/package-json": "0.4.0",
54
- "@effected/semver": "0.2.0",
55
- "@effected/walker": "0.3.0",
56
- "@effected/yaml": "0.5.0",
49
+ "@effected/git": "~0.4.1",
50
+ "@effected/glob": "~0.2.0",
51
+ "@effected/lockfiles": "~0.1.9",
52
+ "@effected/npm": "~0.3.0",
53
+ "@effected/package-json": "~0.4.2",
54
+ "@effected/semver": "~0.2.0",
55
+ "@effected/walker": "~0.3.1",
56
+ "@effected/yaml": "~0.5.0",
57
57
  "@pnpm/catalogs.config": "^1100.0.0",
58
58
  "@pnpm/catalogs.protocol-parser": "^1100.0.0",
59
59
  "@pnpm/catalogs.resolver": "^1100.0.0",