Skip to content

Include docs and semver dependencies in published packages#24

Merged
gentamura merged 3 commits intomainfrom
chore/include-readmes
Oct 23, 2025
Merged

Include docs and semver dependencies in published packages#24
gentamura merged 3 commits intomainfrom
chore/include-readmes

Conversation

@gentamura
Copy link
Member

@gentamura gentamura commented Oct 23, 2025

Summary

  • add README and LICENSE to the published files list for each package
  • replace workspace/catalog references with semver ranges during dist manifest generation
  • ensure @Listee packages resolve via the root catalog when published to npm

Testing

  • bun run build (verifies dist/package.json contains semver ranges)

Summary by CodeRabbit

  • Chores

    • Added MIT license files across packages and included README and LICENSE in published package manifests.
    • Added three internal packages to the project catalog to standardize package references.
  • Refactor

    • Improved manifest generation to resolve and substitute internal package references with concrete versions when producing release manifests.

@coderabbitai
Copy link

coderabbitai bot commented Oct 23, 2025

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Include docs and semver dependencies in published packages" directly relates to the main changes in the changeset. The PR adds README.md and LICENSE files to the published files list across multiple packages (addressing the "docs" aspect) and modifies the dist manifest generation script to replace workspace/catalog references with semver ranges during publication (addressing the "semver dependencies" aspect). The title is concise, specific, and clearly conveys the primary purpose of the changes without being vague or overly broad.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/include-readmes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gentamura gentamura self-assigned this Oct 23, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
scripts/write-dist-manifest.mjs (2)

54-74: Add warning when workspace root is not found.

The function correctly walks up the directory tree to find the workspace root. However, if no workspace root is found (returns null), the rootCatalog will be an empty object, and catalog references won't be resolved. This would result in invalid dist/package.json files containing "catalog:" references that npm cannot resolve.

Consider adding a warning or error when the workspace root is not found:

 const workspaceInfo = await resolveWorkspaceRoot();
+if (!workspaceInfo) {
+  console.warn(
+    `⚠️  No workspace root found for ${packageRoot}. Catalog references will not be resolved.`
+  );
+}
 const rootCatalog = workspaceInfo?.manifest?.catalog ?? {};

76-93: Add warning for unresolved catalog references.

The function correctly handles catalog reference resolution. However, when a catalog entry is not found (line 90 returns the original range), it leaves "catalog:" references in the output, which will cause npm publishing to fail.

Consider logging a warning when catalog entries are missing:

       if (typeof range === "string" && range.startsWith("catalog:")) {
         const catalogKey = range === "catalog:" ? name : range.slice("catalog:".length);
         const resolved = catalog?.[catalogKey];
         if (typeof resolved === "string" && resolved.length > 0) {
           return [name, resolved];
+        } else {
+          console.warn(
+            `⚠️  Catalog entry "${catalogKey}" not found for dependency "${name}". Leaving as "${range}".`
+          );
         }
       }
       return [name, range];
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39b0a0f and f000235.

📒 Files selected for processing (10)
  • package.json (1 hunks)
  • packages/api/LICENSE (1 hunks)
  • packages/api/package.json (2 hunks)
  • packages/auth/LICENSE (1 hunks)
  • packages/auth/package.json (2 hunks)
  • packages/db/LICENSE (1 hunks)
  • packages/db/package.json (1 hunks)
  • packages/types/LICENSE (1 hunks)
  • packages/types/package.json (2 hunks)
  • scripts/write-dist-manifest.mjs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
packages/*/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Reference shared dependencies via the "catalog:" protocol in package manifests

Files:

  • packages/api/package.json
  • packages/types/package.json
  • packages/db/package.json
  • packages/auth/package.json
package.json

📄 CodeRabbit inference engine (AGENTS.md)

package.json: Pin shared dependency versions in the root package.json catalog
Add new shared dependencies to the root catalog before consuming them in packages

Files:

  • package.json
🧠 Learnings (2)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
PR: listee-dev/listee-libs#0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/*/package.json : Reference shared dependencies via the "catalog:" protocol in package manifests

Applied to files:

  • packages/api/package.json
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
PR: listee-dev/listee-libs#0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to package.json : Add new shared dependencies to the root catalog before consuming them in packages

Applied to files:

  • scripts/write-dist-manifest.mjs
🔇 Additional comments (15)
packages/db/LICENSE (1)

1-21: LGTM! Standard MIT license.

The MIT license text is correct and appropriate for the package.

packages/auth/LICENSE (1)

1-21: LGTM! Consistent MIT licensing.

The license is identical to other packages, ensuring consistent licensing across the monorepo.

packages/types/package.json (2)

27-29: LGTM! Catalog reference aligns with guidelines.

The change from workspace:^ to catalog: follows the coding guidelines and enables semver resolution during the build process.

Based on coding guidelines


13-17: No action required. README.md exists in packages/types/ and is correctly listed in the package.json files array. The package will publish successfully.

packages/types/LICENSE (1)

1-21: LGTM! Consistent licensing.

packages/db/package.json (1)

13-17: LGTM! Adds documentation and license to published artifacts.

The changes correctly include README.md and LICENSE in the published package. Ensure README.md exists (see verification script in packages/types/package.json review).

scripts/write-dist-manifest.mjs (2)

3-3: LGTM! Import needed for workspace resolution.

The dirname import is required for the new resolveWorkspaceRoot function.


113-114: LGTM! Catalog resolution properly integrated.

The catalog resolution is correctly integrated into the manifest generation flow. All dependency types (dependencies, devDependencies, peerDependencies, optionalDependencies) are processed, ensuring comprehensive catalog reference substitution.

Also applies to: 139-154

packages/api/LICENSE (1)

1-21: LGTM! Consistent licensing.

packages/api/package.json (2)

13-17: LGTM! Documentation and license included in published artifacts.

Ensure README.md exists (see verification script in packages/types/package.json review).


27-32: LGTM! Internal dependencies now use catalog references.

The change from workspace:^ to catalog: for internal @listee packages aligns with the coding guidelines and enables proper semver resolution during the build process.

Based on coding guidelines

package.json (2)

10-13: Ensure jose version is consistent across all usages.

Jose is now defined in the root catalog at ^5.2.3 and should be referenced via "catalog:" in all packages. Verify that packages/auth/package.json (and all other packages) consistently use this catalog entry rather than direct version specifications.

The catalog entries are properly pinned with semver ranges. This aligns with the PR objective to establish catalog-based dependency resolution. Ensure the build process successfully substitutes these catalog references to absolute versions in published dist manifests.


10-13: Version alignment and catalog entries verified successfully.

All internal packages (auth, db, types) are correctly pinned to version ^0.2.0 in the root catalog, matching their respective package.json files. Packages that depend on internal @Listee packages properly use the "catalog:" protocol for dependency resolution.

packages/auth/package.json (2)

13-17: Both required files are present in packages/auth/.

README.md and LICENSE files exist in the package directory and will be included in the npm package correctly.


28-30: Catalog reference substitution is correctly implemented.

The verification confirms:

  • packages/auth/package.json properly uses the "catalog:" protocol for all dependencies
  • Root package.json contains a complete catalog with semver versions for @listee/db, @listee/types, and jose
  • scripts/write-dist-manifest.mjs postbuild script correctly implements catalog reference replacement by resolving the workspace root, extracting the catalog, and substituting "catalog:" strings with their corresponding semver versions in the dist/package.json during build

The implementation aligns with the coding guideline requirement to reference shared dependencies via the "catalog:" protocol in package manifests.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f000235 and ddda56a.

📒 Files selected for processing (4)
  • packages/api/package.json (2 hunks)
  • packages/auth/package.json (1 hunks)
  • packages/types/package.json (1 hunks)
  • scripts/write-dist-manifest.mjs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/auth/package.json
  • packages/types/package.json
  • packages/api/package.json
🔇 Additional comments (5)
scripts/write-dist-manifest.mjs (5)

2-3: LGTM!

The added imports (readdir, dirname) are correctly used by the new workspace resolution functions.


54-74: LGTM!

The workspace root resolution correctly climbs the directory tree and stops at the filesystem root. The logic handles errors gracefully and returns the appropriate result.


137-146: LGTM!

The workspace reference handling correctly preserves ^ and ~ prefixes while defaulting to exact versions for workspace:* and workspace: (empty). This covers the common workspace specifier patterns.


171-173: LGTM!

The workspace resolution and dependency substitution is correctly integrated into the manifest generation flow. All dependency types (dependencies, devDependencies, peerDependencies, optionalDependencies) are properly handled.

Also applies to: 198-217


92-94: All workspace patterns in the codebase end with /*.

Verification confirms that the workspace configuration uses only glob patterns, so the code at lines 92-94 correctly processes all patterns. No changes needed.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
scripts/write-dist-manifest.mjs (1)

231-237: Add a final manifest scan to catch any leaked catalog:/workspace: ranges.

You collect unresolved during substitution (good), but a defensive final scan of distManifest guarantees no protocol ranges slip through (e.g., via nested catalog values or future edits). This aligns with the earlier review suggestion.

Apply below just before writing the file:

   distManifest.optionalDependencies = replaceSpecialReferences(
     distManifest.optionalDependencies,
     rootCatalog,
     workspaceVersions,
     unresolvedReferences,
   );
 
-  if (unresolvedReferences.length > 0) {
+  if (unresolvedReferences.length > 0) {
     console.error("❌ Unresolved workspace/catalog references detected:");
     for (const { name, range, type } of unresolvedReferences) {
       console.error(`  ${name}: ${range} (${type})`);
     }
     process.exit(1);
   }
+
+  // Defensive validation: ensure no protocol ranges remain in the final manifest
+  const sections = [
+    ["dependencies", distManifest.dependencies],
+    ["devDependencies", distManifest.devDependencies],
+    ["peerDependencies", distManifest.peerDependencies],
+    ["optionalDependencies", distManifest.optionalDependencies],
+  ];
+  const leaked = sections
+    .flatMap(([section, obj]) =>
+      Object.entries(obj || {}).map(([dep, r]) => [section, dep, r]),
+    )
+    .filter(([, , r]) => typeof r === "string" && (r.startsWith("catalog:") || r.startsWith("workspace:")));
+  if (leaked.length > 0) {
+    console.error("❌ Unresolved references found in dist manifest:");
+    for (const [section, dep, r] of leaked) {
+      console.error(`  ${section}.${dep}: ${r}`);
+    }
+    process.exit(1);
+  }
🧹 Nitpick comments (2)
scripts/write-dist-manifest.mjs (2)

76-120: Workspace pattern handling is limited; warn or support non-trivial globs.

Current logic only handles patterns ending with "/" and silently skips others, missing valid configs like "packages//examples/" or a plain directory without "". Add minimal warnings and handle the “no star” directory case to avoid silent drops. Based on learnings.

Apply this diff inside resolveWorkspacePackages:

-  for (const pattern of patterns) {
-    if (!pattern.endsWith("/*")) {
-      continue;
-    }
-    const base = resolve(workspaceRoot.rootDir, pattern.slice(0, -2));
+  for (const pattern of patterns) {
+    // Skip complex nested globs but warn so it's visible in CI
+    const firstStar = pattern.indexOf("*");
+    if (firstStar !== -1 && pattern.slice(firstStar + 1).includes("*")) {
+      console.warn(`⚠️  Nested workspace pattern not supported by write-dist-manifest: "${pattern}". Skipping.`);
+      continue;
+    }
+
+    let base;
+    if (pattern.endsWith("/*")) {
+      base = resolve(workspaceRoot.rootDir, pattern.slice(0, -2));
+    } else if (!pattern.includes("*")) {
+      // Allow a concrete directory (e.g., "packages")
+      base = resolve(workspaceRoot.rootDir, pattern);
+    } else {
+      console.warn(`⚠️  Unsupported workspace pattern: "${pattern}". Expected "<dir>/*" or a concrete directory. Skipping.`);
+      continue;
+    }

121-159: Broaden workspace: specifier support and guard against nested protocol values.

  • Handle workspace:^1.2.3 and workspace:~1.2.3 by normalizing to prefix of the actual workspace version.
  • Treat workspace:* and empty specifier explicitly.
  • If a catalog value itself contains catalog:/workspace:, treat as unresolved to avoid leaking protocols into the published manifest.
  • Optionally emit a warning when pushing to unresolved (helps debugging). Based on learnings.
-        if (range.startsWith("catalog:")) {
+        if (range.startsWith("catalog:")) {
           const catalogKey = range === "catalog:" ? name : range.slice("catalog:".length);
           const resolved = catalog?.[catalogKey];
-          if (typeof resolved === "string" && resolved.length > 0) {
-            return [name, resolved];
-          }
-          unresolved.push({ name, range, type: "catalog" });
+          if (typeof resolved === "string" && resolved.length > 0) {
+            // Guard against nested protocols in catalog values
+            if (resolved.startsWith("catalog:") || resolved.startsWith("workspace:")) {
+              unresolved.push({ name, range: resolved, type: "catalog-nested" });
+            } else {
+              return [name, resolved];
+            }
+          } else {
+            unresolved.push({ name, range, type: "catalog" });
+          }
         }
 
-        if (range.startsWith("workspace:")) {
+        if (range.startsWith("workspace:")) {
           const specifier = range.slice("workspace:".length);
           const version = workspaceVersions.get(name);
           if (typeof version === "string" && version.length > 0) {
-            if (specifier === "^" || specifier === "~") {
-              return [name, `${specifier}${version}`];
-            }
-            return [name, version];
+            // Normalize common forms
+            if (specifier === "^" || specifier.startsWith("^")) {
+              return [name, `^${version}`];
+            }
+            if (specifier === "~" || specifier.startsWith("~")) {
+              return [name, `~${version}`];
+            }
+            if (specifier === "*" || specifier === "") {
+              return [name, version];
+            }
+            // Fallback: use the workspace version
+            return [name, version];
           }
-          unresolved.push({ name, range, type: "workspace" });
+          unresolved.push({ name, range, type: "workspace" });
         }
       }
       return [name, range];
     }),
   );

Optionally add warnings when recording unresolved:

-          unresolved.push({ name, range, type: "catalog" });
+          unresolved.push({ name, range, type: "catalog" });
+          console.warn(`⚠️  Could not resolve catalog reference: ${name}@${range}`);
...
-          unresolved.push({ name, range, type: "workspace" });
+          unresolved.push({ name, range, type: "workspace" });
+          console.warn(`⚠️  Could not resolve workspace reference: ${name}@${range}`);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ddda56a and d75ef5e.

📒 Files selected for processing (1)
  • scripts/write-dist-manifest.mjs (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-02T12:40:33.718Z
Learnt from: CR
PR: listee-dev/listee-libs#0
File: AGENTS.md:0-0
Timestamp: 2025-10-02T12:40:33.718Z
Learning: Applies to packages/*/package.json : Reference shared dependencies via the "catalog:" protocol in package manifests

Applied to files:

  • scripts/write-dist-manifest.mjs
🔇 Additional comments (2)
scripts/write-dist-manifest.mjs (2)

206-230: Good coverage: all dep sections are normalized.

dependencies, devDependencies, peerDependencies, and optionalDependencies are all processed consistently before write. LGTM.


239-246: Verify publishing strategy before applying docs-copy refactor.

The concern raised is valid but conditional. Current setup publishes from the package root (standard npm behavior), which correctly includes docs via the "files" field. The suggested refactor to copy docs into dist/ would only be necessary if:

  1. Publishing is intended to run from dist/ (configured via publishConfig.directory), or
  2. The dist/ folder is meant to be standalone-publishable

The current publishConfig lacks a "directory" field, so npm publishes from the root per default. The deletion of the "files" field from dist/package.json is appropriate since the normalized manifest in dist/ is not itself published directly—docs are included at the root level.

However, if the PR's intent is to enable future dist/-based publishing, the refactor is appropriate and aligns with the stated objective to "include docs in published packages."

Check the PR description or release strategy to confirm whether docs should be copied into dist/ as part of this change.

@gentamura gentamura merged commit be4eb71 into main Oct 23, 2025
5 checks passed
@gentamura gentamura deleted the chore/include-readmes branch October 23, 2025 12:38
This was referenced Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant