diff --git a/changelog.md b/changelog.md index d58dc6e..c5a2498 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2024-10-21 - 1.2.0 - feat(core) +Enhance package publication workflow with dependency handling and CLI improvements. + +- Updated package description and keywords in package.json and npmextra.json. +- Integrated dependency extraction from root package.json into sub-package tspublish.json during initialization. +- Added build and publish script executions for each submodule. +- Improved CLI documentation and usage guidance in readme.md. + ## 2024-10-21 - 1.1.0 - feat(core) Add runCli function to execute TsPublish process diff --git a/npmextra.json b/npmextra.json index e5e219f..939f5b8 100644 --- a/npmextra.json +++ b/npmextra.json @@ -5,10 +5,22 @@ "githost": "code.foss.global", "gitscope": "git.zone", "gitrepo": "tspublish", - "description": "publish multiple, concise and small packages from monorepos", + "description": "A tool to publish multiple, concise, and small packages from monorepos, specifically for TypeScript projects within a git environment.", "npmPackagename": "@git.zone/tspublish", "license": "MIT", - "projectDomain": "git.zone" + "projectDomain": "git.zone", + "keywords": [ + "typescript", + "monorepo", + "package", + "publish", + "npm", + "automation", + "git", + "modularity", + "module-management", + "developer-tools" + ] } }, "npmci": { diff --git a/package.json b/package.json index 3711bf2..517ee7f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@git.zone/tspublish", "version": "1.1.0", "private": false, - "description": "publish multiple, concise and small packages from monorepos", + "description": "A tool to publish multiple, concise, and small packages from monorepos, specifically for TypeScript projects within a git environment.", "main": "dist_ts/index.js", "typings": "dist_ts/index.d.ts", "type": "module", @@ -49,6 +49,19 @@ "@push.rocks/smartfile": "^11.0.21", "@push.rocks/smartlog": "^3.0.7", "@push.rocks/smartnpm": "^2.0.4", - "@push.rocks/smartpath": "^5.0.18" - } -} + "@push.rocks/smartpath": "^5.0.18", + "@push.rocks/smartshell": "^3.0.6" + }, + "keywords": [ + "typescript", + "monorepo", + "package", + "publish", + "npm", + "automation", + "git", + "modularity", + "module-management", + "developer-tools" + ] +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 840ed51..e0f3da1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@push.rocks/smartpath': specifier: ^5.0.18 version: 5.0.18 + '@push.rocks/smartshell': + specifier: ^3.0.6 + version: 3.0.6 devDependencies: '@git.zone/tsbuild': specifier: ^2.1.25 diff --git a/readme.md b/readme.md index ac0d23d..cdb1d84 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,190 @@ publish multiple, concise and small packages from monorepos -## How to create the docs +## Install -To create docs run gitzone aidoc. +To install `@git.zone/tspublish`, you can use npm. To use the latest stable version, run: + +```bash +npm install @git.zone/tspublish +``` + +Alternatively, if you are using yarn, the equivalent command would be: + +```bash +yarn add @git.zone/tspublish +``` + +These commands will add `@git.zone/tspublish` as a dependency in your `package.json` file and install the package into your `node_modules` directory. + +## Usage + +`@git.zone/tspublish` is designed to manage the publishing of multiple, small-scale packages within monorepos. The following sections will guide you through its usage, from setting up your environment to effectively publishing packages. + +### Getting Started with TypeScript and Module Setup + +`@git.zone/tspublish` works with monorepos that are organized using TypeScript. The package structure should follow a convention where each submodule intended for publishing is located in a directory prefixed with `ts`, for example, `tsModuleName`. Each submodule directory should contain a `tspublish.json` file to correctly configure the package to be published separately. This file is critical for the `tspublish` process to identify valid package directories and should also include necessary metadata for the package. + +Your monorepo structure might resemble: + +``` +my-monorepo/ +├── ts-package1/ +│ ├── src/ +│ ├── tspublish.json +├── ts-package2/ +│ ├── src/ +│ ├── tspublish.json +``` + +### Configuring `tspublish.json` + +Each submodule must include a `tspublish.json` within its directory. This JSON file should include essential details for your publishable package, including its dependencies. Here's a basic example of what `tspublish.json` could look like: + +```json +{ + "name": "@myorg/ts-package1", + "dependencies": { + "some-dependency": "^1.0.0" + } +} +``` + +### Running the CLI + +`@git.zone/tspublish` includes a CLI that simplifies the publishing process. Begin by importing the CLI runner in a script within your project: + +```typescript +import { runCli } from '@git.zone/tspublish'; + +runCli(); +``` + +This function call orchestrates the publishing operation. It reads each directory prefixed with `ts`, looks for a `tspublish.json`, and creates an individual package based on the gathered data. + +### Core Features + +#### Publishing Modules + +The core functionality provided by `@git.zone/tspublish` involves processing directories to check for valid submodules that are ready to be published. This occurs via the `publish` method in `TsPublish` class. This method does the following: + +- **Reads all directories** within the specified monorepo path. +- **Identifies directories** that start with `ts` and validates the presence of `tspublish.json`. +- **Logs** information about found packages for user awareness and debugging. +- **Checks for collisions** with existing versions on the npm registry to prevent overriding published versions. + +```typescript +import { TsPublish } from '@git.zone/tspublish'; + +const tspublish = new TsPublish(); +await tspublish.publish('/path/to/your/monorepo'); +``` + +#### Package Initialization + +Once valid submodules are identified, the `init` method in the `PublishModule` class initializes the publish module. This includes: + +- Parsing `tspublish.json` for metadata. +- Constructing full paths for necessary operations. +- Verifying package existence to avoid duplication. + +```typescript +import { PublishModule } from '@git.zone/tspublish'; + +const publishModule = new PublishModule({ + monoRepoDir: '/path/to/monorepo', + packageSubFolder: 'ts-package1', +}); + +await publishModule.init(); +``` + +#### Creating `package.json` + +Part of the publishing process involves automatically creating a `package.json` tailored to each submodule. This dynamically generated JSON will incorporate dependencies from `tspublish.json` and associate them with the latest version of `tsbuild` from the registry: + +```typescript +await publishModule.createPackageJson(); +``` + +This creates a structured `package.json` which includes scripts to build your TypeScript files before publishing. + +#### Constructing Publish-ready Directory + +After all configurations are verified and the `package.json` is created, the submodule is ready to be published. This step involves setting up a `dist_publish_` directory specific to each module: + +```typescript +await publishModule.createPublishModuleDir(); +``` + +The above method ensures that each module's source files are copied and prepared under a dedicated directory meant for packaging and distribution. + +### Logging and Debugging + +The package includes a structured logging mechanism using `smartlog` which provides insights into the publishing process, helping in runtime debugging and status tracking of operations: + +```typescript +import { logger } from '@git.zone/tspublish/logging'; + +logger.log('info', 'Publishing process initialized'); +``` + +This powerful logging helps in tracking the status of each step and understanding potential issues during the operations. + +### Testing with tapbundle + +To ensure that your publishing workflow is functioning correctly, you can utilize the test suite set up with `tapbundle`. This library facilitates behavior-driven testing for your monorepo. Below is a basic test setup to verify the import and initial function accessibility of `@git.zone/tspublish`: + +```typescript +import { expect, tap } from '@push.rocks/tapbundle'; +import * as tspublish from '@git.zone/tspublish'; + +tap.test('Should run the CLI without errors', async () => { + await tspublish.runCli(); + expect(tspublish).toBeTruthy(); +}); + +tap.start(); +``` + +### Comprehensive usage example + +Let's combine all the steps into a complete example where you prepare a monorepo, configure each module, and execute the publishing workflow. + +Suppose you have a project structure as follows: + +```plaintext +my-monorepo/ +├── ts-package1/ +│ ├── src/ +│ ├── tspublish.json +├── ts-package2/ +│ ├── src/ +│ ├── tspublish.json +``` + +Follow these steps: + +1. Ensure each package has `tspublish.json` properly configured with necessary metadata. +2. Create a CLI script such as `publish.js`: + +```typescript +import { runCli } from '@git.zone/tspublish'; + +runCli().then(() => { + console.log('Publishing completed successfully'); +}).catch((error) => { + console.error('Error during publishing:', error); +}); +``` + +3. Execute your CLI script: + +```bash +node publish.js +``` + +Your script will call `runCli`, which will traverse each `ts-package`, verify their publish readiness, and handle individual publishing processes. + +By following these comprehensive guidelines and utilizing the structured approach provided by `@git.zone/tspublish`, you can efficiently manage and publish multiple sub-packages from within a monorepo, facilitating organized, modular package management in projects of any scale. +undefined \ No newline at end of file diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 989dbed..efebe99 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tspublish', - version: '1.1.0', - description: 'publish multiple, concise and small packages from monorepos' + version: '1.2.0', + description: 'A tool to publish multiple, concise, and small packages from monorepos, specifically for TypeScript projects within a git environment.' } diff --git a/ts/classes.publishmodule.ts b/ts/classes.publishmodule.ts index 60d5d43..29afe86 100644 --- a/ts/classes.publishmodule.ts +++ b/ts/classes.publishmodule.ts @@ -31,15 +31,21 @@ export class PublishModule { const jsonData = plugins.smartfile.fs.toObjectSync( plugins.path.join(this.options.packageSubFolderFullPath, 'tspublish.json') ); - this.options.dependencies = this.options.dependencies || {}; + const monoRepoPackageJson = JSON.parse( + plugins.smartfile.fs.toStringSync(plugins.path.join(this.options.monoRepoDir, 'package.json')) + ) this.options.dependencies = { ...this.options.dependencies, - ...jsonData.dependencies, + ...(() => { + const resultDependencies = {}; + for (const dependency of jsonData.dependencies) { + resultDependencies[dependency] = monoRepoPackageJson.dependencies[dependency]; + } + return resultDependencies; + })() }; this.options.name = this.options.name || jsonData.name; - this.options.version = plugins.smartfile.fs.toObjectSync( - plugins.path.join(this.options.monoRepoDir, 'package.json') - ).version; + this.options.version = monoRepoPackageJson.version; // now that we have a name and version, lets check if there is already a package under the same name and version. const smartnpmInstance = new plugins.smartnpm.NpmRegistry({}); // TODO: pass in options @@ -102,4 +108,18 @@ export class PublishModule { // ts folder await plugins.smartfile.fs.copy(this.options.packageSubFolderFullPath, plugins.path.join(this.options.publishModDirFullPath, this.options.packageSubFolder)) } + + public async build() { + const smartshellInstance = new plugins.smartshell.Smartshell({ + executor: 'bash', + }) + await smartshellInstance.exec(`cd ${this.options.publishModDirFullPath} && pnpm run build`); + } + + public async publish() { + const smartshellInstance = new plugins.smartshell.Smartshell({ + executor: 'bash', + }) + await smartshellInstance.exec(`cd ${this.options.publishModDirFullPath} && pnpm publish`); + } } diff --git a/ts/classes.tspublish.ts b/ts/classes.tspublish.ts index e67da3c..5f1c732 100644 --- a/ts/classes.tspublish.ts +++ b/ts/classes.tspublish.ts @@ -14,6 +14,9 @@ export class TsPublish { packageSubFolder: publishModule, }); await publishModuleInstance.init(); + await publishModuleInstance.createPublishModuleDir(); + await publishModuleInstance.build(); + await publishModuleInstance.publish(); } } diff --git a/ts/plugins.ts b/ts/plugins.ts index 2b7eeaa..221c179 100644 --- a/ts/plugins.ts +++ b/ts/plugins.ts @@ -10,5 +10,6 @@ import * as smartcli from '@push.rocks/smartcli'; import * as smartlog from '@push.rocks/smartlog'; import * as smartnpm from '@push.rocks/smartnpm'; import * as smartpath from '@push.rocks/smartpath'; +import * as smartshell from '@push.rocks/smartshell'; -export { smartfile, smartcli, smartlog, smartnpm, smartpath, }; +export { smartfile, smartcli, smartlog, smartnpm, smartpath, smartshell };