@effected/package-json 0.1.0 → 0.2.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/Package.js CHANGED
@@ -5,7 +5,7 @@ import { renderJson } from "./internal/format.js";
5
5
  import { PackageManager } from "./PackageManager.js";
6
6
  import { InvalidPackageNameError, PackageName } from "./PackageName.js";
7
7
  import { Person } from "./Person.js";
8
- import { CatalogResolver, WorkspaceResolver } from "@effected/npm";
8
+ import { CatalogResolver, DependencySpecifier, WorkspaceResolver } from "@effected/npm";
9
9
  import { Effect, Function, HashMap, Option, Pipeable, Schema, SchemaTransformation } from "effect";
10
10
  import { SemVer } from "@effected/semver";
11
11
 
@@ -106,23 +106,12 @@ const makeWire = (Class) => {
106
106
  encode: (encoded) => {
107
107
  const { rest, ...known } = encoded;
108
108
  return {
109
- ...known,
110
- ...rest ?? {}
109
+ ...rest ?? {},
110
+ ...known
111
111
  };
112
112
  }
113
113
  })));
114
114
  };
115
- const applyWorkspaceModifier = (specifier, version) => {
116
- const modifier = specifier.slice(10);
117
- if (modifier === "*" || modifier === "") return version;
118
- if (modifier === "^") return `^${version}`;
119
- if (modifier === "~") return `~${version}`;
120
- return modifier;
121
- };
122
- const catalogName = (specifier) => {
123
- const name = specifier.slice(8);
124
- return name.length === 0 ? Option.none() : Option.some(name);
125
- };
126
115
  /**
127
116
  * A package.json document as a rich `Schema.Class`: typed known fields, a
128
117
  * `rest` catch-all preserving unknown top-level fields across a read/edit/write
@@ -290,20 +279,33 @@ var Package = class Package extends Schema.Class("Package")({
290
279
  static removeScript = Function.dual(2, (pkg, name) => pkg.copyWith({ scripts: HashMap.remove(pkg.scripts, name) }));
291
280
  /**
292
281
  * Resolve `catalog:` and `workspace:` specifiers across all four dependency
293
- * maps using the `CatalogResolver` and `WorkspaceResolver` from context.
294
- * Specifiers the resolvers return `None` for are left unchanged. This is the
295
- * explicit resolution step `PackageJsonFile.write` never resolves.
282
+ * maps using the `CatalogResolver` and `WorkspaceResolver` from context,
283
+ * classifying and projecting through `@effected/npm`'s `DependencySpecifier`
284
+ * statics (`workspace:` uses the pnpm publish-time projection; the alias
285
+ * form `workspace:<name>@<range>` resolves the TARGET package's version and
286
+ * becomes the published `npm:<name>@<range>` alias). Specifiers the
287
+ * resolvers return `None` for are left unchanged — resolution still
288
+ * succeeds. A `CatalogResolver` whose catalog assembly failed surfaces
289
+ * typed as `@effected/npm`'s `CatalogAssemblyError`, alongside the
290
+ * contracts' `DependencyResolutionError`. This is the explicit resolution
291
+ * step — `PackageJsonFile.write` never resolves.
292
+ *
293
+ * @remarks
294
+ * Leaves unresolvable specifiers unchanged. For fail-typed manifest
295
+ * resolution over the tolerant model, see `@effected/npm`'s
296
+ * `Manifest#resolve`.
296
297
  */
297
298
  static resolve = Effect.fn("Package.resolve")(function* (pkg) {
298
299
  const workspace = yield* WorkspaceResolver;
299
300
  const catalog = yield* CatalogResolver;
300
301
  const resolveMap = Effect.fn("Package.resolve.map")(function* (map) {
301
302
  let next = map;
302
- for (const [name, specifier] of HashMap.entries(map)) if (specifier.startsWith("workspace:")) {
303
- const version = yield* workspace.versionOf(name);
304
- if (Option.isSome(version)) next = HashMap.set(next, name, applyWorkspaceModifier(specifier, version.value));
305
- } else if (specifier.startsWith("catalog:")) {
306
- const range = yield* catalog.rangeOf(name, catalogName(specifier));
303
+ for (const [name, specifier] of HashMap.entries(map)) if (DependencySpecifier.isWorkspace(specifier)) {
304
+ const target = Option.getOrElse(DependencySpecifier.workspaceTargetOf(specifier), () => name);
305
+ const version = yield* workspace.versionOf(target);
306
+ if (Option.isSome(version)) next = HashMap.set(next, name, DependencySpecifier.resolveWorkspace(specifier, version.value));
307
+ } else if (DependencySpecifier.isCatalog(specifier)) {
308
+ const range = yield* catalog.rangeOf(name, DependencySpecifier.catalogNameOf(specifier));
307
309
  if (Option.isSome(range)) next = HashMap.set(next, name, range.value);
308
310
  }
309
311
  return next;
package/README.md CHANGED
@@ -180,7 +180,7 @@ console.log(Effect.runSync(program));
180
180
  // => ["^4.0.0", "^1.4.0"]
181
181
  ```
182
182
 
183
- The `workspace:` range modifier is honored: `workspace:*` takes the bare version, `workspace:^` and `workspace:~` prefix it, and an explicit modifier is used as-is.
183
+ The `workspace:` range modifier is honored: `workspace:*` takes the bare version, `workspace:^` and `workspace:~` prefix it, and an explicit modifier is used as-is. The projection is `@effected/npm`'s `DependencySpecifier` statics with full pnpm publish semantics: the alias form `workspace:<name>@<range>` resolves the *target* package's version and becomes the `npm:<name>@<range>` alias pnpm publishes, and a blank catalog name selects the default catalog. A failed catalog assembly surfaces typed as `@effected/npm`'s `CatalogAssemblyError`, alongside the contracts' `DependencyResolutionError`.
184
184
 
185
185
  ## Errors
186
186
 
@@ -206,7 +206,7 @@ Every failure is a `Schema.TaggedErrorClass` routed with `Effect.catchTag`. Caus
206
206
  - `Package.schema` / `Package.wireFor` — the open-JSON ↔ class wire codec, and the factory that builds one for a `.extend()`ed subclass so its custom fields decode as typed members instead of falling into `rest`.
207
207
  - `PackageJsonFile` — the IO surface: `read` and `write` over core `FileSystem` / `Path`, with the platform implementation supplied at the edge.
208
208
  - `PackageValidator` — rule-based validation aggregating every failure, with the default rule set, a parameterized `layerRules` factory, and the publish-gate rules `noUnresolvedDepsRule` and `noLocalDepsRule`.
209
- - `Package.resolve` — `catalog:` and `workspace:` expansion over the `@effected/npm` contracts, as an explicit step that `write` never performs for you.
209
+ - `Package.resolve` — `catalog:` and `workspace:` expansion over the `@effected/npm` contracts with pnpm's publish-time projection (alias form included), as an explicit step that `write` never performs for you.
210
210
  - `PackageName`, `DependencySpecifier`, `Dependency`, `SpdxLicense`, `PackageManager`, `Person`, `DevEngine` — the leaf concepts, each owning its own statics, brand and error, usable independently of `Package`.
211
211
  - Field schemas (`DependencyMapField`, `BinField`, `ExportsField`, `RepositoryField`, `PublishConfigField`, `PeerDependenciesMetaField`, `StringMapField`) exported for subclasses that extend the model.
212
212
 
package/index.d.ts CHANGED
@@ -525,11 +525,23 @@ declare class Package extends Package_base {
525
525
  };
526
526
  /**
527
527
  * Resolve `catalog:` and `workspace:` specifiers across all four dependency
528
- * maps using the `CatalogResolver` and `WorkspaceResolver` from context.
529
- * Specifiers the resolvers return `None` for are left unchanged. This is the
530
- * explicit resolution step `PackageJsonFile.write` never resolves.
528
+ * maps using the `CatalogResolver` and `WorkspaceResolver` from context,
529
+ * classifying and projecting through `@effected/npm`'s `DependencySpecifier`
530
+ * statics (`workspace:` uses the pnpm publish-time projection; the alias
531
+ * form `workspace:<name>@<range>` resolves the TARGET package's version and
532
+ * becomes the published `npm:<name>@<range>` alias). Specifiers the
533
+ * resolvers return `None` for are left unchanged — resolution still
534
+ * succeeds. A `CatalogResolver` whose catalog assembly failed surfaces
535
+ * typed as `@effected/npm`'s `CatalogAssemblyError`, alongside the
536
+ * contracts' `DependencyResolutionError`. This is the explicit resolution
537
+ * step — `PackageJsonFile.write` never resolves.
538
+ *
539
+ * @remarks
540
+ * Leaves unresolvable specifiers unchanged. For fail-typed manifest
541
+ * resolution over the tolerant model, see `@effected/npm`'s
542
+ * `Manifest#resolve`.
531
543
  */
532
- static readonly resolve: (pkg: Package) => Effect.Effect<Package, import("@effected/npm").DependencyResolutionError, CatalogResolver | WorkspaceResolver>;
544
+ static readonly resolve: (pkg: Package) => Effect.Effect<Package, import("@effected/npm").CatalogAssemblyError | import("@effected/npm").DependencyResolutionError, CatalogResolver | WorkspaceResolver>;
533
545
  /**
534
546
  * Serialize to a formatted package.json string: encode through the wire
535
547
  * codec (flattening `rest`), then apply the canonical key order, dependency
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/package-json",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "description": "package.json parsing, editing, validation and file IO as Effect schemas.",
6
6
  "keywords": [
@@ -37,7 +37,7 @@
37
37
  "./package.json": "./package.json"
38
38
  },
39
39
  "dependencies": {
40
- "@effected/npm": "0.1.0",
40
+ "@effected/npm": "0.2.0",
41
41
  "@effected/semver": "0.1.0",
42
42
  "spdx-expression-parse": "^4.0.0"
43
43
  },