Creates exportable package manifests by resolving workspace dependencies for pnpm publishing workflow
npx @tessl/cli install tessl/npm-pnpm--exportable-manifest@1000.1.0@pnpm/exportable-manifest creates exportable package manifests by resolving workspace dependencies for pnpm's publishing workflow. It transforms package.json files to prepare them for publishing by resolving workspace protocol dependencies, catalog protocol dependencies, and JSR protocol dependencies to their concrete versions.
pnpm add @pnpm/exportable-manifestimport {
createExportableManifest,
overridePublishConfig,
type MakePublishManifestOptions,
type PublishDependencyConverter
} from "@pnpm/exportable-manifest";For CommonJS:
const { createExportableManifest, overridePublishConfig } = require("@pnpm/exportable-manifest");import { createExportableManifest } from "@pnpm/exportable-manifest";
import { type ProjectManifest } from "@pnpm/types";
import { type Catalogs } from "@pnpm/catalogs.types";
// Basic manifest transformation
const originalManifest: ProjectManifest = {
name: "my-package",
version: "1.0.0",
dependencies: {
"workspace-dep": "workspace:^",
"catalog-dep": "catalog:",
"jsr-dep": "jsr:@scope/package@1.0.0"
},
pnpm: {
overrides: {
"some-dep": "2.0.0"
}
},
scripts: {
prepublishOnly: "npm run build",
test: "jest"
}
};
const catalogs: Catalogs = {
default: {
"catalog-dep": "^2.1.0"
}
};
const exportableManifest = await createExportableManifest(
"/path/to/package",
originalManifest,
{ catalogs }
);
// Result will have workspace:, catalog:, and jsr: protocols resolved
// pnpm-specific fields removed, and publish scripts removed@pnpm/exportable-manifest is built around several key transformation components:
Creates publication-ready manifests by resolving all protocol dependencies and cleaning pnpm-specific fields.
/**
* Creates an exportable manifest from a workspace package manifest
* @param dir - Directory path of the package
* @param originalManifest - Original package.json manifest
* @param opts - Options for manifest creation
* @returns Promise resolving to transformed ProjectManifest ready for publishing
*/
async function createExportableManifest(
dir: string,
originalManifest: ProjectManifest,
opts: MakePublishManifestOptions
): Promise<ProjectManifest>;
interface MakePublishManifestOptions {
/** Catalog configurations for resolving catalog protocol dependencies */
catalogs: Catalogs;
/** Optional path to node_modules directory */
modulesDir?: string;
/** Optional readme file content to add to manifest */
readmeFile?: string;
}Applies publishConfig overrides to the main manifest fields and removes processed fields.
/**
* Overrides manifest fields with publishConfig values and cleans up publishConfig
* @param publishManifest - Manifest to process publishConfig overrides for
*/
function overridePublishConfig(publishManifest: ProjectManifest): void;Resolves workspace: dependencies to their concrete versions:
workspace:* → 1.2.3 (exact version)workspace:^ → ^1.2.3 (caret range)workspace:~ → ~1.2.3 (tilde range)workspace:./path → 1.2.3 (relative path resolution)workspace:@scope/alias@* → npm:@scope/alias@1.2.3 (aliased packages)Resolves catalog: dependencies using provided catalogs:
catalog: → Uses default catalog entry for the dependency namecatalog:named → Uses named catalog entryConverts JSR (JavaScript Registry) dependencies to npm equivalents:
jsr:@scope/name@1.0.0 → npm:@jsr/scope__name@1.0.0jsr:@scope/name → npm:@jsr/scope__nameThe following fields are removed from the exported manifest:
pnpm - pnpm-specific configurationpackageManager - Package manager specificationprepublishOnly, prepack, prepare, postpack, publish, postpublishThe following publishConfig fields are automatically copied to the main manifest by createExportableManifest:
main, module, types, typings, exports, browser, esnext, es2015, unpkg, umd:mainos, cpu, libctypesVersionsbin, type, importsThe package throws PnpmError with code CANNOT_RESOLVE_WORKSPACE_PROTOCOL when:
import { createExportableManifest } from "@pnpm/exportable-manifest";
const manifest = {
name: "my-workspace-package",
version: "1.0.0",
dependencies: {
"peer-dep": "workspace:^",
"alias-dep": "workspace:@other/name@*",
"relative-dep": "workspace:../other-package"
},
peerDependencies: {
"peer-workspace": "workspace:>=1.0.0 || ^2.0.0"
},
publishConfig: {
main: "dist/index.js",
types: "dist/index.d.ts"
},
scripts: {
prepublishOnly: "npm run build",
test: "jest"
}
};
const result = await createExportableManifest("/workspace/my-package", manifest, {
catalogs: {}
});
// Result:
// {
// name: "my-workspace-package",
// version: "1.0.0",
// main: "dist/index.js",
// types: "dist/index.d.ts",
// dependencies: {
// "peer-dep": "^1.2.3",
// "alias-dep": "npm:@other/name@1.0.0",
// "relative-dep": "2.1.0"
// },
// peerDependencies: {
// "peer-workspace": ">=1.2.3 || ^2.0.0"
// },
// scripts: {
// test: "jest"
// }
// }import { createExportableManifest } from "@pnpm/exportable-manifest";
const manifest = {
name: "catalog-example",
version: "1.0.0",
dependencies: {
"default-catalog": "catalog:",
"named-catalog": "catalog:react"
}
};
const catalogs = {
default: {
"default-catalog": "^3.1.0"
},
react: {
"named-catalog": "^18.0.0"
}
};
const result = await createExportableManifest("/path", manifest, { catalogs });
// Result dependencies:
// {
// "default-catalog": "^3.1.0",
// "named-catalog": "^18.0.0"
// }import { overridePublishConfig } from "@pnpm/exportable-manifest";
const manifest = {
name: "example-package",
version: "1.0.0",
main: "src/index.js",
types: "src/index.d.ts",
publishConfig: {
main: "dist/index.js",
types: "dist/index.d.ts",
registry: "https://registry.npmjs.org/"
}
};
// Apply publishConfig overrides
overridePublishConfig(manifest);
// Result:
// {
// name: "example-package",
// version: "1.0.0",
// main: "dist/index.js", // overridden from publishConfig
// types: "dist/index.d.ts", // overridden from publishConfig
// publishConfig: {
// registry: "https://registry.npmjs.org/" // non-whitelisted fields remain
// }
// }// Re-exported from @pnpm/types
interface ProjectManifest {
name?: string;
version?: string;
dependencies?: Dependencies;
devDependencies?: Dependencies;
optionalDependencies?: Dependencies;
peerDependencies?: Dependencies;
scripts?: Record<string, string>;
publishConfig?: PublishConfig;
[key: string]: any;
}
interface Dependencies {
[name: string]: string;
}
interface Catalogs {
[catalogName: string]: {
[packageName: string]: string;
};
}
interface PublishConfig {
[key: string]: any;
}
/**
* Function type for converting dependency specifications during publishing
*/
type PublishDependencyConverter = (
depName: string,
depSpec: string,
dir: string,
modulesDir?: string
) => Promise<string> | string;