@ls-stack/pkg-manager 0.3.0 → 0.5.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/README.md +56 -4
- package/dist/{config-CG8p1aGY.mjs → config-DAHW5EzY.mjs} +7 -1
- package/dist/config-DAHW5EzY.mjs.map +1 -0
- package/dist/exports.d.mts +2 -1
- package/dist/exports.mjs +1 -1
- package/dist/main.mjs +316 -41
- package/dist/main.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/config-CG8p1aGY.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ pkg-manager init [--force]
|
|
|
46
46
|
Publishes a package with hash-based change detection.
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
pkg-manager publish [package] [--type <
|
|
49
|
+
pkg-manager publish [package] [--type <type>] [--force] [--dry-run] [--skip-confirm]
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
**Arguments:**
|
|
@@ -55,7 +55,7 @@ pkg-manager publish [package] [--type <major|minor|patch>] [--force] [--dry-run]
|
|
|
55
55
|
|
|
56
56
|
**Options:**
|
|
57
57
|
|
|
58
|
-
- `--type <type>` - Version bump type: `
|
|
58
|
+
- `--type <type>` - Version bump type: `patch`, `minor`, `major`, `prerelease`, `release`, `prepatch-alpha`, `preminor-beta`, `premajor-rc`, etc.
|
|
59
59
|
- `--force` - Publish even if no changes detected
|
|
60
60
|
- `--dry-run` - Preview what would happen without making changes
|
|
61
61
|
- `--skip-confirm` - Skip major version confirmation prompt
|
|
@@ -63,7 +63,7 @@ pkg-manager publish [package] [--type <major|minor|patch>] [--force] [--dry-run]
|
|
|
63
63
|
**Workflow:**
|
|
64
64
|
|
|
65
65
|
1. Verifies git working directory is clean
|
|
66
|
-
2. Prompts for version type if not provided
|
|
66
|
+
2. Prompts for version type if not provided (supports prerelease via two-level select)
|
|
67
67
|
3. Confirms major version bumps (configurable)
|
|
68
68
|
4. Builds dependencies first (monorepo, topological order)
|
|
69
69
|
5. Runs pre-publish scripts (required - see [Pre-Publish Scripts](#pre-publish-scripts))
|
|
@@ -71,8 +71,9 @@ pkg-manager publish [package] [--type <major|minor|patch>] [--force] [--dry-run]
|
|
|
71
71
|
7. Checks hash against stored hashes (prevents duplicate publishes)
|
|
72
72
|
8. Bumps version with `pnpm version`
|
|
73
73
|
9. Creates git tag (`packageName@version`)
|
|
74
|
-
10. Publishes with `pnpm publish --access public`
|
|
74
|
+
10. Publishes with `pnpm publish --access public` (uses `--tag <preid>` for prereleases)
|
|
75
75
|
11. Saves hash for future duplicate detection
|
|
76
|
+
12. Runs post-publish scripts (if configured)
|
|
76
77
|
|
|
77
78
|
## Configuration
|
|
78
79
|
|
|
@@ -108,6 +109,9 @@ export default defineConfig({
|
|
|
108
109
|
| `prePublish` | `array` | Uses `pre-publish` script | Scripts to run before publishing |
|
|
109
110
|
| `prePublish[].command` | `string` | Required | Command to execute |
|
|
110
111
|
| `prePublish[].label` | `string` | Required | Display label for the script |
|
|
112
|
+
| `postPublish` | `array` | - | Scripts to run after publishing |
|
|
113
|
+
| `postPublish[].command` | `string` | Required | Command to execute |
|
|
114
|
+
| `postPublish[].label` | `string` | Required | Display label for the script |
|
|
111
115
|
| `monorepo` | `object` | - | Monorepo configuration |
|
|
112
116
|
| `monorepo.packages` | `array` | Required | List of packages |
|
|
113
117
|
| `monorepo.packages[].name` | `string` | Required | Package name (from package.json) |
|
|
@@ -138,6 +142,45 @@ Pre-publish scripts are **required**. They ensure your package is built and vali
|
|
|
138
142
|
|
|
139
143
|
This works without any config file.
|
|
140
144
|
|
|
145
|
+
## Post-Publish Scripts
|
|
146
|
+
|
|
147
|
+
Post-publish scripts are **optional**. They run after a successful publish, hash save, and git commit. Useful for deploy steps, notifications, or cleanup.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
export default defineConfig({
|
|
151
|
+
postPublish: [
|
|
152
|
+
{ command: 'pnpm deploy', label: 'Deploying' },
|
|
153
|
+
{ command: 'node notify.ts', label: 'Sending notification' },
|
|
154
|
+
],
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Prerelease Versions
|
|
159
|
+
|
|
160
|
+
pkg-manager supports publishing prerelease versions (alpha, beta, rc).
|
|
161
|
+
|
|
162
|
+
**Interactive mode** uses a two-level select:
|
|
163
|
+
|
|
164
|
+
- For **stable versions** (e.g., `1.2.3`): the first select shows `patch`, `minor`, `major`, and `prerelease...`. Choosing `prerelease...` opens a second select with all combinations of `prepatch`/`preminor`/`premajor` × `alpha`/`beta`/`rc`.
|
|
165
|
+
- For **prerelease versions** (e.g., `1.2.4-alpha.0`): relevant options are promoted to the top-level select — `prerelease` (bump number), `graduate to beta`/`rc`, and `release` (drop the prerelease suffix).
|
|
166
|
+
|
|
167
|
+
**CLI mode:**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Start a prerelease cycle
|
|
171
|
+
pkg-manager publish --type prepatch-alpha # 1.2.3 → 1.2.4-alpha.0
|
|
172
|
+
pkg-manager publish --type preminor-beta # 1.2.3 → 1.3.0-beta.0
|
|
173
|
+
pkg-manager publish --type premajor-rc # 1.2.3 → 2.0.0-rc.0
|
|
174
|
+
|
|
175
|
+
# Bump existing prerelease
|
|
176
|
+
pkg-manager publish --type prerelease # 1.2.4-alpha.0 → 1.2.4-alpha.1
|
|
177
|
+
|
|
178
|
+
# Release from prerelease
|
|
179
|
+
pkg-manager publish --type release # 1.2.4-alpha.1 → 1.2.4
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Prerelease versions are published with `--tag <preid>` (e.g., `--tag alpha`) so they don't become the `latest` dist-tag on npm.
|
|
183
|
+
|
|
141
184
|
## Hash-Based Change Detection
|
|
142
185
|
|
|
143
186
|
pkg-manager generates a SHA256 hash of the entire `dist/` directory (file paths + contents) before publishing. This hash is stored locally and checked on subsequent publishes to prevent publishing identical builds.
|
|
@@ -182,6 +225,15 @@ pkg-manager publish --force --type patch
|
|
|
182
225
|
|
|
183
226
|
# Publish major version without confirmation
|
|
184
227
|
pkg-manager publish --type major --skip-confirm
|
|
228
|
+
|
|
229
|
+
# Start a prerelease cycle
|
|
230
|
+
pkg-manager publish --type prepatch-alpha
|
|
231
|
+
|
|
232
|
+
# Bump an existing prerelease
|
|
233
|
+
pkg-manager publish --type prerelease
|
|
234
|
+
|
|
235
|
+
# Release from a prerelease version
|
|
236
|
+
pkg-manager publish --type release
|
|
185
237
|
```
|
|
186
238
|
|
|
187
239
|
## License
|
|
@@ -17,6 +17,7 @@ const monorepoPackageSchema = z.object({
|
|
|
17
17
|
});
|
|
18
18
|
const pkgManagerConfigSchema = z.object({
|
|
19
19
|
prePublish: z.array(prePublishScriptSchema).optional(),
|
|
20
|
+
postPublish: z.array(prePublishScriptSchema).optional(),
|
|
20
21
|
monorepo: z.object({ packages: z.array(monorepoPackageSchema) }).optional(),
|
|
21
22
|
hashStorePath: z.string().optional(),
|
|
22
23
|
requireMajorConfirmation: z.boolean().optional()
|
|
@@ -69,6 +70,11 @@ function generateConfigFile(config, cwd = process.cwd()) {
|
|
|
69
70
|
for (const script of config.prePublish) lines.push(` { command: '${script.command}', label: '${script.label}' },`);
|
|
70
71
|
lines.push(" ],");
|
|
71
72
|
}
|
|
73
|
+
if (config.postPublish && config.postPublish.length > 0) {
|
|
74
|
+
lines.push(" postPublish: [");
|
|
75
|
+
for (const script of config.postPublish) lines.push(` { command: '${script.command}', label: '${script.label}' },`);
|
|
76
|
+
lines.push(" ],");
|
|
77
|
+
}
|
|
72
78
|
if (config.monorepo) {
|
|
73
79
|
lines.push(" monorepo: {");
|
|
74
80
|
lines.push(" packages: [");
|
|
@@ -89,4 +95,4 @@ function getHashStorePath(config) {
|
|
|
89
95
|
|
|
90
96
|
//#endregion
|
|
91
97
|
export { loadConfig as a, getHashStorePath as i, defineConfig as n, generateConfigFile as r, configExists as t };
|
|
92
|
-
//# sourceMappingURL=config-
|
|
98
|
+
//# sourceMappingURL=config-DAHW5EzY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-DAHW5EzY.mjs","names":[],"sources":["../src/core/config.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'fs'\nimport { join } from 'path'\nimport { pathToFileURL } from 'url'\nimport { z } from 'zod'\n\nconst CONFIG_FILENAME = 'pkg-manager.config.ts'\nconst DEFAULT_HASH_STORE_PATH = 'node_modules/.pkg-manager/hashes.json'\n\nconst prePublishScriptSchema = z.object({\n command: z.string(),\n label: z.string(),\n})\n\nconst monorepoPackageSchema = z.object({\n name: z.string(),\n path: z.string(),\n dependsOn: z.array(z.string()).optional(),\n})\n\nconst pkgManagerConfigSchema = z.object({\n prePublish: z.array(prePublishScriptSchema).optional(),\n postPublish: z.array(prePublishScriptSchema).optional(),\n monorepo: z\n .object({\n packages: z.array(monorepoPackageSchema),\n })\n .optional(),\n hashStorePath: z.string().optional(),\n requireMajorConfirmation: z.boolean().optional(),\n})\n\nexport type MonorepoPackage = {\n /** Package name (as in package.json) */\n name: string\n /** Relative path to the package directory */\n path: string\n /** Package names this package depends on (for topological ordering) */\n dependsOn?: string[]\n}\n\nexport type PrePublishScript = {\n /** The shell command to execute */\n command: string\n /** Display label shown during execution */\n label: string\n}\n\n/**\n * Configuration for pkg-manager.\n */\nexport type PkgManagerConfig = {\n /** Scripts to run before publishing (e.g., build commands) */\n prePublish?: PrePublishScript[]\n /** Scripts to run after publishing (e.g., deploy, notifications) */\n postPublish?: PrePublishScript[]\n /** Monorepo configuration for multi-package projects */\n monorepo?: {\n /** Array of packages in the monorepo */\n packages: MonorepoPackage[]\n }\n /**\n * Custom path for storing publish hashes.\n * @default \"node_modules/.pkg-manager/hashes.json\"\n */\n hashStorePath?: string\n /**\n * Require confirmation for major version bumps.\n * @default true\n */\n requireMajorConfirmation?: boolean\n}\n\n/**\n * Defines the configuration for pkg-manager.\n *\n * @example\n * ```ts\n * export default defineConfig({\n * requireMajorConfirmation: true,\n * prePublish: [{ command: 'pnpm build', label: 'Building' }],\n * });\n * ```\n */\nexport function defineConfig(config: PkgManagerConfig): PkgManagerConfig {\n return config\n}\n\nexport function getConfigPath(cwd: string = process.cwd()): string {\n return join(cwd, CONFIG_FILENAME)\n}\n\nexport function configExists(cwd: string = process.cwd()): boolean {\n return existsSync(getConfigPath(cwd))\n}\n\nconst defaultConfig: PkgManagerConfig = {\n hashStorePath: DEFAULT_HASH_STORE_PATH,\n requireMajorConfirmation: true,\n}\n\nexport async function loadConfig(\n cwd: string = process.cwd()\n): Promise<PkgManagerConfig> {\n const configPath = getConfigPath(cwd)\n\n if (!existsSync(configPath)) return defaultConfig\n\n const configModule: { default: unknown } = await import(\n pathToFileURL(configPath).href\n )\n const config = pkgManagerConfigSchema.parse(configModule.default)\n\n return {\n ...config,\n hashStorePath: config.hashStorePath ?? DEFAULT_HASH_STORE_PATH,\n requireMajorConfirmation: config.requireMajorConfirmation ?? true,\n }\n}\n\nexport function generateConfigFile(\n config: PkgManagerConfig,\n cwd: string = process.cwd()\n): void {\n const configPath = getConfigPath(cwd)\n\n const lines: string[] = [\n `import { defineConfig } from '@ls-stack/pkg-manager';`,\n '',\n 'export default defineConfig({',\n ]\n\n if (config.requireMajorConfirmation !== undefined) {\n lines.push(\n ` requireMajorConfirmation: ${config.requireMajorConfirmation},`\n )\n }\n\n if (config.prePublish && config.prePublish.length > 0) {\n lines.push(' prePublish: [')\n for (const script of config.prePublish) {\n lines.push(\n ` { command: '${script.command}', label: '${script.label}' },`\n )\n }\n lines.push(' ],')\n }\n\n if (config.postPublish && config.postPublish.length > 0) {\n lines.push(' postPublish: [')\n for (const script of config.postPublish) {\n lines.push(\n ` { command: '${script.command}', label: '${script.label}' },`\n )\n }\n lines.push(' ],')\n }\n\n if (config.monorepo) {\n lines.push(' monorepo: {')\n lines.push(' packages: [')\n for (const pkg of config.monorepo.packages) {\n if (pkg.dependsOn && pkg.dependsOn.length > 0) {\n const depsStr = pkg.dependsOn.map((d) => `'${d}'`).join(', ')\n lines.push(\n ` { name: '${pkg.name}', path: '${pkg.path}', dependsOn: [${depsStr}] },`\n )\n } else {\n lines.push(` { name: '${pkg.name}', path: '${pkg.path}' },`)\n }\n }\n lines.push(' ],')\n lines.push(' },')\n }\n\n lines.push('});')\n lines.push('')\n\n writeFileSync(configPath, lines.join('\\n'))\n}\n\nexport function getHashStorePath(config: PkgManagerConfig): string {\n return config.hashStorePath ?? DEFAULT_HASH_STORE_PATH\n}\n"],"mappings":";;;;;;AAKA,MAAM,kBAAkB;AACxB,MAAM,0BAA0B;AAEhC,MAAM,yBAAyB,EAAE,OAAO;CACtC,SAAS,EAAE,QAAQ;CACnB,OAAO,EAAE,QAAQ;CAClB,CAAC;AAEF,MAAM,wBAAwB,EAAE,OAAO;CACrC,MAAM,EAAE,QAAQ;CAChB,MAAM,EAAE,QAAQ;CAChB,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU;CAC1C,CAAC;AAEF,MAAM,yBAAyB,EAAE,OAAO;CACtC,YAAY,EAAE,MAAM,uBAAuB,CAAC,UAAU;CACtD,aAAa,EAAE,MAAM,uBAAuB,CAAC,UAAU;CACvD,UAAU,EACP,OAAO,EACN,UAAU,EAAE,MAAM,sBAAsB,EACzC,CAAC,CACD,UAAU;CACb,eAAe,EAAE,QAAQ,CAAC,UAAU;CACpC,0BAA0B,EAAE,SAAS,CAAC,UAAU;CACjD,CAAC;;;;;;;;;;;;AAsDF,SAAgB,aAAa,QAA4C;AACvE,QAAO;;AAGT,SAAgB,cAAc,MAAc,QAAQ,KAAK,EAAU;AACjE,QAAO,KAAK,KAAK,gBAAgB;;AAGnC,SAAgB,aAAa,MAAc,QAAQ,KAAK,EAAW;AACjE,QAAO,WAAW,cAAc,IAAI,CAAC;;AAGvC,MAAM,gBAAkC;CACtC,eAAe;CACf,0BAA0B;CAC3B;AAED,eAAsB,WACpB,MAAc,QAAQ,KAAK,EACA;CAC3B,MAAM,aAAa,cAAc,IAAI;AAErC,KAAI,CAAC,WAAW,WAAW,CAAE,QAAO;CAEpC,MAAM,eAAqC,MAAM,OAC/C,cAAc,WAAW,CAAC;CAE5B,MAAM,SAAS,uBAAuB,MAAM,aAAa,QAAQ;AAEjE,QAAO;EACL,GAAG;EACH,eAAe,OAAO,iBAAiB;EACvC,0BAA0B,OAAO,4BAA4B;EAC9D;;AAGH,SAAgB,mBACd,QACA,MAAc,QAAQ,KAAK,EACrB;CACN,MAAM,aAAa,cAAc,IAAI;CAErC,MAAM,QAAkB;EACtB;EACA;EACA;EACD;AAED,KAAI,OAAO,6BAA6B,OACtC,OAAM,KACJ,+BAA+B,OAAO,yBAAyB,GAChE;AAGH,KAAI,OAAO,cAAc,OAAO,WAAW,SAAS,GAAG;AACrD,QAAM,KAAK,kBAAkB;AAC7B,OAAK,MAAM,UAAU,OAAO,WAC1B,OAAM,KACJ,mBAAmB,OAAO,QAAQ,aAAa,OAAO,MAAM,MAC7D;AAEH,QAAM,KAAK,OAAO;;AAGpB,KAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;AACvD,QAAM,KAAK,mBAAmB;AAC9B,OAAK,MAAM,UAAU,OAAO,YAC1B,OAAM,KACJ,mBAAmB,OAAO,QAAQ,aAAa,OAAO,MAAM,MAC7D;AAEH,QAAM,KAAK,OAAO;;AAGpB,KAAI,OAAO,UAAU;AACnB,QAAM,KAAK,gBAAgB;AAC3B,QAAM,KAAK,kBAAkB;AAC7B,OAAK,MAAM,OAAO,OAAO,SAAS,SAChC,KAAI,IAAI,aAAa,IAAI,UAAU,SAAS,GAAG;GAC7C,MAAM,UAAU,IAAI,UAAU,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK;AAC7D,SAAM,KACJ,kBAAkB,IAAI,KAAK,YAAY,IAAI,KAAK,iBAAiB,QAAQ,MAC1E;QAED,OAAM,KAAK,kBAAkB,IAAI,KAAK,YAAY,IAAI,KAAK,MAAM;AAGrE,QAAM,KAAK,SAAS;AACpB,QAAM,KAAK,OAAO;;AAGpB,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;AAEd,eAAc,YAAY,MAAM,KAAK,KAAK,CAAC;;AAG7C,SAAgB,iBAAiB,QAAkC;AACjE,QAAO,OAAO,iBAAiB"}
|
package/dist/exports.d.mts
CHANGED
|
@@ -12,7 +12,8 @@ type PrePublishScript = {
|
|
|
12
12
|
* Configuration for pkg-manager.
|
|
13
13
|
*/
|
|
14
14
|
type PkgManagerConfig = {
|
|
15
|
-
/** Scripts to run before publishing (e.g., build commands) */prePublish?: PrePublishScript[]; /**
|
|
15
|
+
/** Scripts to run before publishing (e.g., build commands) */prePublish?: PrePublishScript[]; /** Scripts to run after publishing (e.g., deploy, notifications) */
|
|
16
|
+
postPublish?: PrePublishScript[]; /** Monorepo configuration for multi-package projects */
|
|
16
17
|
monorepo?: {
|
|
17
18
|
/** Array of packages in the monorepo */packages: MonorepoPackage[];
|
|
18
19
|
};
|
package/dist/exports.mjs
CHANGED
package/dist/main.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as loadConfig, i as getHashStorePath, r as generateConfigFile, t as configExists } from "./config-
|
|
2
|
+
import { a as loadConfig, i as getHashStorePath, r as generateConfigFile, t as configExists } from "./config-DAHW5EzY.mjs";
|
|
3
3
|
import { cliInput, createCLI, createCmd } from "@ls-stack/cli";
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
@@ -7,6 +7,7 @@ import { dirname, join } from "path";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { spawn } from "child_process";
|
|
9
9
|
import clipboardy from "clipboardy";
|
|
10
|
+
import { env } from "node:process";
|
|
10
11
|
import { createHash } from "crypto";
|
|
11
12
|
|
|
12
13
|
//#region src/utils/runCmd.ts
|
|
@@ -316,12 +317,105 @@ function savePackageHash(hashStorePath, packageName, version, hash) {
|
|
|
316
317
|
}
|
|
317
318
|
|
|
318
319
|
//#endregion
|
|
319
|
-
//#region src/
|
|
320
|
-
const
|
|
321
|
-
"
|
|
322
|
-
"
|
|
323
|
-
"
|
|
320
|
+
//#region src/core/semver.ts
|
|
321
|
+
const PRERELEASE_TAGS = [
|
|
322
|
+
"alpha",
|
|
323
|
+
"beta",
|
|
324
|
+
"rc"
|
|
324
325
|
];
|
|
326
|
+
function parseVersion(version) {
|
|
327
|
+
const [core, prereleaseStr] = version.split("-");
|
|
328
|
+
const parts = (core ?? "").split(".").map(Number);
|
|
329
|
+
const major = parts[0] ?? 0;
|
|
330
|
+
const minor = parts[1] ?? 0;
|
|
331
|
+
const patch = parts[2] ?? 0;
|
|
332
|
+
if (prereleaseStr) {
|
|
333
|
+
const lastDotIndex = prereleaseStr.lastIndexOf(".");
|
|
334
|
+
if (lastDotIndex !== -1) return {
|
|
335
|
+
major,
|
|
336
|
+
minor,
|
|
337
|
+
patch,
|
|
338
|
+
prerelease: {
|
|
339
|
+
tag: prereleaseStr.slice(0, lastDotIndex),
|
|
340
|
+
number: Number(prereleaseStr.slice(lastDotIndex + 1))
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
return {
|
|
344
|
+
major,
|
|
345
|
+
minor,
|
|
346
|
+
patch,
|
|
347
|
+
prerelease: {
|
|
348
|
+
tag: prereleaseStr,
|
|
349
|
+
number: 0
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
major,
|
|
355
|
+
minor,
|
|
356
|
+
patch,
|
|
357
|
+
prerelease: void 0
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function isPrerelease(version) {
|
|
361
|
+
return version.includes("-");
|
|
362
|
+
}
|
|
363
|
+
function getPrereleaseTag(version) {
|
|
364
|
+
return parseVersion(version).prerelease?.tag;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Returns prerelease tags that come after the given tag in the progression.
|
|
368
|
+
* alpha → [beta, rc], beta → [rc], rc → []
|
|
369
|
+
* Unknown tags → all PRERELEASE_TAGS
|
|
370
|
+
*/
|
|
371
|
+
function getNextTags(currentTag) {
|
|
372
|
+
const index = PRERELEASE_TAGS.findIndex((t) => t === currentTag);
|
|
373
|
+
if (index === -1) return [...PRERELEASE_TAGS];
|
|
374
|
+
return [...PRERELEASE_TAGS.slice(index + 1)];
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Computes the resulting version string for a given bump operation.
|
|
378
|
+
* Used for displaying hints in the version select UI.
|
|
379
|
+
*/
|
|
380
|
+
function bumpVersionPreview(version, type, preid) {
|
|
381
|
+
const parsed = parseVersion(version);
|
|
382
|
+
switch (type) {
|
|
383
|
+
case "patch":
|
|
384
|
+
if (parsed.prerelease) return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
385
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
|
|
386
|
+
case "minor":
|
|
387
|
+
if (parsed.prerelease && parsed.patch === 0) return `${parsed.major}.${parsed.minor}.0`;
|
|
388
|
+
return `${parsed.major}.${parsed.minor + 1}.0`;
|
|
389
|
+
case "major":
|
|
390
|
+
if (parsed.prerelease && parsed.minor === 0 && parsed.patch === 0) return `${parsed.major}.0.0`;
|
|
391
|
+
return `${parsed.major + 1}.0.0`;
|
|
392
|
+
case "prepatch": {
|
|
393
|
+
const tag = preid ?? "alpha";
|
|
394
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${tag}.0`;
|
|
395
|
+
}
|
|
396
|
+
case "preminor": {
|
|
397
|
+
const tag = preid ?? "alpha";
|
|
398
|
+
return `${parsed.major}.${parsed.minor + 1}.0-${tag}.0`;
|
|
399
|
+
}
|
|
400
|
+
case "premajor": {
|
|
401
|
+
const tag = preid ?? "alpha";
|
|
402
|
+
return `${parsed.major + 1}.0.0-${tag}.0`;
|
|
403
|
+
}
|
|
404
|
+
case "prerelease": {
|
|
405
|
+
if (parsed.prerelease) {
|
|
406
|
+
if (preid && preid !== parsed.prerelease.tag) return `${parsed.major}.${parsed.minor}.${parsed.patch}-${preid}.0`;
|
|
407
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch}-${parsed.prerelease.tag}.${parsed.prerelease.number + 1}`;
|
|
408
|
+
}
|
|
409
|
+
const tag = preid ?? "alpha";
|
|
410
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${tag}.0`;
|
|
411
|
+
}
|
|
412
|
+
case "release": return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
//#endregion
|
|
417
|
+
//#region src/commands/publish.ts
|
|
418
|
+
const PRE_TYPE_REGEX = /^(prepatch|preminor|premajor)-(\w+)$/;
|
|
325
419
|
const packageJsonSchema = z.object({
|
|
326
420
|
name: z.string().optional(),
|
|
327
421
|
version: z.string().optional(),
|
|
@@ -340,8 +434,8 @@ async function publishCommand(args) {
|
|
|
340
434
|
const currentVersion = getPackageVersion(packagePath);
|
|
341
435
|
console.log(styleText(["blue", "bold"], `\nPublishing: ${packageName} (current: ${currentVersion})`));
|
|
342
436
|
if (args.dryRun) console.log(styleText(["yellow"], "(dry-run mode - no changes will be made)\n"));
|
|
343
|
-
const
|
|
344
|
-
if (
|
|
437
|
+
const versionBump = await resolveVersionBump(args.type, currentVersion);
|
|
438
|
+
if (versionBump.isMajor && config.requireMajorConfirmation && !args.skipConfirm) {
|
|
345
439
|
if (!await cliInput.confirm("You are about to publish a MAJOR version. Are you sure?", { initial: false })) {
|
|
346
440
|
console.log("Aborted.");
|
|
347
441
|
process.exit(0);
|
|
@@ -392,14 +486,14 @@ async function publishCommand(args) {
|
|
|
392
486
|
console.warn(styleText(["yellow"], `\nWarning: This build was already published as ${packageName}@${hashCheck.existingVersion}`));
|
|
393
487
|
console.warn("Force flag enabled - proceeding with publish anyway.");
|
|
394
488
|
}
|
|
395
|
-
console.log(styleText(["blue"], `\nBumping version (${
|
|
489
|
+
console.log(styleText(["blue"], `\nBumping version (${versionBump.label})...`));
|
|
396
490
|
if (!args.dryRun) {
|
|
397
491
|
await runCmdOrExit("bump version", [
|
|
398
492
|
"pnpm",
|
|
399
493
|
"version",
|
|
400
|
-
|
|
494
|
+
...versionBump.versionArgs
|
|
401
495
|
], { cwd: packagePath });
|
|
402
|
-
await commitIfDirty(`chore: bump ${packageName}
|
|
496
|
+
await commitIfDirty(`chore: bump ${packageName} version (${versionBump.label})`);
|
|
403
497
|
}
|
|
404
498
|
const newVersion = getPackageVersion(packagePath);
|
|
405
499
|
console.log(styleText(["green"], `New version: ${newVersion}`));
|
|
@@ -415,19 +509,45 @@ async function publishCommand(args) {
|
|
|
415
509
|
}
|
|
416
510
|
console.log(styleText(["blue"], "\nPublishing to npm..."));
|
|
417
511
|
if (!args.dryRun) {
|
|
418
|
-
|
|
512
|
+
const publishArgs = [
|
|
419
513
|
"pnpm",
|
|
420
514
|
"publish",
|
|
421
515
|
"--access",
|
|
422
516
|
"public"
|
|
423
|
-
]
|
|
517
|
+
];
|
|
518
|
+
if (versionBump.distTag) publishArgs.push("--tag", versionBump.distTag);
|
|
519
|
+
await runCmdOrExit("publish", publishArgs, { cwd: packagePath });
|
|
424
520
|
savePackageHash(hashStorePath, packageName, newVersion, currentHash);
|
|
425
521
|
await commitIfDirty(`chore: update publish hashes for ${packageName}@${newVersion}`);
|
|
426
522
|
}
|
|
427
|
-
const installCmd = `pnpm add ${packageName}@${newVersion}`;
|
|
428
|
-
await clipboardy.write(installCmd);
|
|
429
523
|
console.log(styleText(["green", "bold"], `\nSuccessfully published ${packageName}@${newVersion}`));
|
|
430
|
-
|
|
524
|
+
const postPublishScripts = config.postPublish ?? [];
|
|
525
|
+
if (postPublishScripts.length > 0) {
|
|
526
|
+
console.log(styleText(["dim"], "\nRunning post-publish scripts..."));
|
|
527
|
+
for (const script of postPublishScripts) {
|
|
528
|
+
console.log(styleText(["blue"], `\n${script.label}...`));
|
|
529
|
+
if (!args.dryRun) {
|
|
530
|
+
const [cmd, ...cmdArgs] = script.command.split(" ");
|
|
531
|
+
if (!cmd) {
|
|
532
|
+
console.error(styleText(["red"], `Invalid command: ${script.command}`));
|
|
533
|
+
process.exit(1);
|
|
534
|
+
}
|
|
535
|
+
if (config.monorepo) await runCmdOrExit(script.label, [
|
|
536
|
+
"pnpm",
|
|
537
|
+
"--filter",
|
|
538
|
+
packageName,
|
|
539
|
+
...cmdArgs
|
|
540
|
+
], { cwd });
|
|
541
|
+
else await runCmdOrExit(script.label, [cmd, ...cmdArgs], { cwd: packagePath });
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const copyCmdPrefix = env.PKG_MANAGER_COPY_CMD;
|
|
546
|
+
if (copyCmdPrefix) {
|
|
547
|
+
const installCmd = `${copyCmdPrefix} ${packageName}@${newVersion}`;
|
|
548
|
+
await clipboardy.write(installCmd);
|
|
549
|
+
console.log(styleText(["dim"], `Copied to clipboard: ${installCmd}`));
|
|
550
|
+
}
|
|
431
551
|
}
|
|
432
552
|
async function resolveTargetPackage(packageArg, config) {
|
|
433
553
|
if (packageArg) return packageArg;
|
|
@@ -438,45 +558,200 @@ async function resolveTargetPackage(packageArg, config) {
|
|
|
438
558
|
hint: pkg.path
|
|
439
559
|
})) });
|
|
440
560
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
561
|
+
const STABLE_TYPES = [
|
|
562
|
+
"major",
|
|
563
|
+
"minor",
|
|
564
|
+
"patch"
|
|
565
|
+
];
|
|
566
|
+
const VALID_TYPE_ARGS = [
|
|
567
|
+
...STABLE_TYPES,
|
|
568
|
+
"prerelease",
|
|
569
|
+
"release",
|
|
570
|
+
...PRERELEASE_TAGS.flatMap((tag) => [
|
|
571
|
+
"prepatch",
|
|
572
|
+
"preminor",
|
|
573
|
+
"premajor"
|
|
574
|
+
].map((base) => `${base}-${tag}`))
|
|
575
|
+
];
|
|
576
|
+
function parseTypeArg(typeArg, currentVersion) {
|
|
577
|
+
const normalized = typeArg.toLowerCase();
|
|
578
|
+
const stableMatch = STABLE_TYPES.find((t) => t === normalized);
|
|
579
|
+
if (stableMatch) return {
|
|
580
|
+
label: stableMatch,
|
|
581
|
+
versionArgs: [stableMatch],
|
|
582
|
+
isMajor: stableMatch === "major",
|
|
583
|
+
distTag: void 0
|
|
584
|
+
};
|
|
585
|
+
if (normalized === "prerelease") {
|
|
586
|
+
const currentTag = getPrereleaseTag(currentVersion);
|
|
587
|
+
if (!currentTag) {
|
|
588
|
+
console.error(styleText(["red", "bold"], "Cannot use --type=prerelease on a stable version."));
|
|
589
|
+
console.error("Use prepatch-alpha, preminor-alpha, or premajor-alpha instead.");
|
|
459
590
|
process.exit(1);
|
|
460
591
|
}
|
|
461
|
-
return
|
|
592
|
+
return {
|
|
593
|
+
label: "prerelease",
|
|
594
|
+
versionArgs: ["prerelease"],
|
|
595
|
+
isMajor: false,
|
|
596
|
+
distTag: currentTag
|
|
597
|
+
};
|
|
462
598
|
}
|
|
463
|
-
|
|
599
|
+
if (normalized === "release") {
|
|
600
|
+
if (!isPrerelease(currentVersion)) {
|
|
601
|
+
console.error(styleText(["red", "bold"], "Cannot use --type=release on a stable version."));
|
|
602
|
+
process.exit(1);
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
label: "release",
|
|
606
|
+
versionArgs: ["patch"],
|
|
607
|
+
isMajor: false,
|
|
608
|
+
distTag: void 0
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
const preMatch = PRE_TYPE_REGEX.exec(normalized);
|
|
612
|
+
if (preMatch) {
|
|
613
|
+
const baseType = preMatch[1];
|
|
614
|
+
const preid = preMatch[2];
|
|
615
|
+
if (baseType && preid) return {
|
|
616
|
+
label: `${baseType} (${preid})`,
|
|
617
|
+
versionArgs: [baseType, `--preid=${preid}`],
|
|
618
|
+
isMajor: false,
|
|
619
|
+
distTag: preid
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
console.error(styleText(["red", "bold"], `Invalid version type: ${typeArg}`));
|
|
623
|
+
console.error(`Valid types: ${VALID_TYPE_ARGS.join(", ")}`);
|
|
624
|
+
process.exit(1);
|
|
625
|
+
}
|
|
626
|
+
async function resolveVersionBump(typeArg, currentVersion) {
|
|
627
|
+
if (typeArg) return parseTypeArg(typeArg, currentVersion);
|
|
628
|
+
const currentPreTag = getPrereleaseTag(currentVersion);
|
|
629
|
+
if (currentPreTag) return resolveVersionBumpFromPrerelease(currentVersion, currentPreTag);
|
|
630
|
+
return resolveVersionBumpFromStable(currentVersion);
|
|
631
|
+
}
|
|
632
|
+
async function resolveVersionBumpFromStable(currentVersion) {
|
|
633
|
+
const options = [
|
|
464
634
|
{
|
|
465
635
|
value: "patch",
|
|
466
636
|
label: "patch",
|
|
467
|
-
hint: `${currentVersion} → ${
|
|
637
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "patch")}`
|
|
468
638
|
},
|
|
469
639
|
{
|
|
470
640
|
value: "minor",
|
|
471
641
|
label: "minor",
|
|
472
|
-
hint: `${currentVersion} → ${
|
|
642
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "minor")}`
|
|
473
643
|
},
|
|
474
644
|
{
|
|
475
645
|
value: "major",
|
|
476
646
|
label: "major",
|
|
477
|
-
hint: `${currentVersion} → ${
|
|
647
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "major")}`
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
value: "prerelease-menu",
|
|
651
|
+
label: "prerelease..."
|
|
478
652
|
}
|
|
479
|
-
]
|
|
653
|
+
];
|
|
654
|
+
const selection = await cliInput.select("Select version bump type:", { options });
|
|
655
|
+
if (selection === "prerelease-menu") return resolvePrerelaseSubmenu(currentVersion);
|
|
656
|
+
return {
|
|
657
|
+
label: selection,
|
|
658
|
+
versionArgs: [selection],
|
|
659
|
+
isMajor: selection === "major",
|
|
660
|
+
distTag: void 0
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
async function resolvePrerelaseSubmenu(currentVersion) {
|
|
664
|
+
const baseTypes = [
|
|
665
|
+
"prepatch",
|
|
666
|
+
"preminor",
|
|
667
|
+
"premajor"
|
|
668
|
+
];
|
|
669
|
+
const options = [];
|
|
670
|
+
for (const tag of PRERELEASE_TAGS) for (const base of baseTypes) {
|
|
671
|
+
const preview = bumpVersionPreview(currentVersion, base, tag);
|
|
672
|
+
options.push({
|
|
673
|
+
value: `${base}-${tag}`,
|
|
674
|
+
label: `${base} (${tag})`,
|
|
675
|
+
hint: `${currentVersion} → ${preview}`
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
const [baseType, preid] = (await cliInput.select("Select prerelease type:", { options })).split("-");
|
|
679
|
+
if (!baseType || !preid) {
|
|
680
|
+
console.error(styleText(["red", "bold"], "Unexpected selection format."));
|
|
681
|
+
process.exit(1);
|
|
682
|
+
}
|
|
683
|
+
return {
|
|
684
|
+
label: `${baseType} (${preid})`,
|
|
685
|
+
versionArgs: [baseType, `--preid=${preid}`],
|
|
686
|
+
isMajor: false,
|
|
687
|
+
distTag: preid
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
async function resolveVersionBumpFromPrerelease(currentVersion, currentTag) {
|
|
691
|
+
const options = [];
|
|
692
|
+
options.push({
|
|
693
|
+
value: "prerelease",
|
|
694
|
+
label: "prerelease",
|
|
695
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "prerelease")}`
|
|
696
|
+
});
|
|
697
|
+
const nextTags = getNextTags(currentTag);
|
|
698
|
+
for (const tag of nextTags) options.push({
|
|
699
|
+
value: `graduate-${tag}`,
|
|
700
|
+
label: `graduate to ${tag}`,
|
|
701
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "prerelease", tag)}`
|
|
702
|
+
});
|
|
703
|
+
options.push({
|
|
704
|
+
value: "release",
|
|
705
|
+
label: "release",
|
|
706
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "release")}`
|
|
707
|
+
});
|
|
708
|
+
options.push({
|
|
709
|
+
value: "patch",
|
|
710
|
+
label: "patch",
|
|
711
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "patch")}`
|
|
712
|
+
}, {
|
|
713
|
+
value: "minor",
|
|
714
|
+
label: "minor",
|
|
715
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "minor")}`
|
|
716
|
+
}, {
|
|
717
|
+
value: "major",
|
|
718
|
+
label: "major",
|
|
719
|
+
hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, "major")}`
|
|
720
|
+
});
|
|
721
|
+
options.push({
|
|
722
|
+
value: "prerelease-menu",
|
|
723
|
+
label: "prerelease...",
|
|
724
|
+
hint: "start a new prerelease cycle"
|
|
725
|
+
});
|
|
726
|
+
const selection = await cliInput.select("Select version bump type:", { options });
|
|
727
|
+
if (selection === "prerelease-menu") return resolvePrerelaseSubmenu(currentVersion);
|
|
728
|
+
if (selection === "prerelease") return {
|
|
729
|
+
label: "prerelease",
|
|
730
|
+
versionArgs: ["prerelease"],
|
|
731
|
+
isMajor: false,
|
|
732
|
+
distTag: currentTag
|
|
733
|
+
};
|
|
734
|
+
if (selection === "release") return {
|
|
735
|
+
label: "release",
|
|
736
|
+
versionArgs: ["patch"],
|
|
737
|
+
isMajor: false,
|
|
738
|
+
distTag: void 0
|
|
739
|
+
};
|
|
740
|
+
if (selection.startsWith("graduate-")) {
|
|
741
|
+
const targetTag = selection.replace("graduate-", "");
|
|
742
|
+
return {
|
|
743
|
+
label: `graduate to ${targetTag}`,
|
|
744
|
+
versionArgs: ["prerelease", `--preid=${targetTag}`],
|
|
745
|
+
isMajor: false,
|
|
746
|
+
distTag: targetTag
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
return {
|
|
750
|
+
label: selection,
|
|
751
|
+
versionArgs: [selection],
|
|
752
|
+
isMajor: selection === "major",
|
|
753
|
+
distTag: void 0
|
|
754
|
+
};
|
|
480
755
|
}
|
|
481
756
|
function getPackagePath(targetPackage, config, cwd) {
|
|
482
757
|
if (!targetPackage) return cwd;
|
|
@@ -546,7 +821,7 @@ await createCLI({
|
|
|
546
821
|
type: {
|
|
547
822
|
type: "value-string-flag",
|
|
548
823
|
name: "type",
|
|
549
|
-
description: "Version bump type
|
|
824
|
+
description: "Version bump type (e.g., patch, minor, major, prerelease, release, prepatch-alpha)"
|
|
550
825
|
},
|
|
551
826
|
force: {
|
|
552
827
|
type: "flag",
|
package/dist/main.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.mjs","names":["packageJsonSchema"],"sources":["../src/utils/runCmd.ts","../src/core/monorepo.ts","../src/commands/init.ts","../src/core/git.ts","../src/core/hash.ts","../src/commands/publish.ts","../src/main.ts"],"sourcesContent":["import { spawn } from 'child_process';\nimport { styleText } from 'node:util';\n\nexport type RunCmdOptions = {\n cwd?: string;\n silent?: boolean;\n};\n\nexport async function runCmd(\n label: string,\n cmd: string[],\n options: RunCmdOptions = {},\n): Promise<{ ok: true; output: string } | { ok: false; error: string }> {\n const [command, ...args] = cmd;\n\n if (!command) {\n return { ok: false, error: 'No command provided' };\n }\n\n if (!options.silent) {\n console.log(styleText(['dim'], `> ${cmd.join(' ')}`));\n }\n\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n cwd: options.cwd,\n stdio: options.silent ? 'pipe' : 'inherit',\n });\n\n let stdout = '';\n let stderr = '';\n\n if (options.silent) {\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n }\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ ok: true, output: stdout });\n } else {\n resolve({\n ok: false,\n error: stderr || stdout || `Command failed with exit code ${code}`,\n });\n }\n });\n\n proc.on('error', (error) => {\n resolve({ ok: false, error: error.message });\n });\n });\n}\n\nexport async function runCmdOrExit(\n label: string,\n cmd: string[],\n options: RunCmdOptions = {},\n): Promise<string> {\n const result = await runCmd(label, cmd, options);\n\n if (!result.ok) {\n console.error(styleText(['red', 'bold'], `Failed: ${label}`));\n console.error(result.error);\n process.exit(1);\n }\n\n return result.output;\n}\n","import { existsSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { z } from 'zod';\nimport type { MonorepoPackage } from './config.ts';\nimport { runCmdOrExit } from '../utils/runCmd.ts';\n\nexport function detectMonorepo(cwd: string = process.cwd()): boolean {\n return existsSync(join(cwd, 'pnpm-workspace.yaml'));\n}\n\nconst packageJsonSchema = z.object({\n name: z.string().optional(),\n});\n\nexport function scanPackages(cwd: string = process.cwd()): MonorepoPackage[] {\n const workspacePath = join(cwd, 'pnpm-workspace.yaml');\n\n if (!existsSync(workspacePath)) return [];\n\n const packages: MonorepoPackage[] = [];\n const packagesDir = join(cwd, 'packages');\n\n if (!existsSync(packagesDir)) return [];\n\n const items = readdirSync(packagesDir);\n\n for (const item of items) {\n const itemPath = join(packagesDir, item);\n const stat = statSync(itemPath);\n\n if (!stat.isDirectory()) continue;\n\n const packageJsonPath = join(itemPath, 'package.json');\n\n if (!existsSync(packageJsonPath)) continue;\n\n try {\n const content = readFileSync(packageJsonPath, 'utf-8');\n const parsed = JSON.parse(content);\n const packageJson = packageJsonSchema.parse(parsed);\n\n if (packageJson.name) {\n packages.push({\n name: packageJson.name,\n path: `packages/${item}`,\n });\n }\n } catch {\n continue;\n }\n }\n\n return packages;\n}\n\nexport function topologicalSort(packages: MonorepoPackage[]): MonorepoPackage[] {\n const nameToPackage = new Map<string, MonorepoPackage>();\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n\n for (const pkg of packages) {\n nameToPackage.set(pkg.name, pkg);\n inDegree.set(pkg.name, 0);\n dependents.set(pkg.name, []);\n }\n\n for (const pkg of packages) {\n if (pkg.dependsOn) {\n for (const dep of pkg.dependsOn) {\n if (nameToPackage.has(dep)) {\n inDegree.set(pkg.name, (inDegree.get(pkg.name) ?? 0) + 1);\n dependents.get(dep)?.push(pkg.name);\n }\n }\n }\n }\n\n const queue: string[] = [];\n\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n const sorted: MonorepoPackage[] = [];\n\n while (queue.length > 0) {\n const name = queue.shift();\n\n if (!name) continue;\n\n const pkg = nameToPackage.get(name);\n\n if (pkg) {\n sorted.push(pkg);\n }\n\n for (const dependent of dependents.get(name) ?? []) {\n const newDegree = (inDegree.get(dependent) ?? 1) - 1;\n inDegree.set(dependent, newDegree);\n\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n if (sorted.length !== packages.length) {\n throw new Error('Circular dependency detected in package graph');\n }\n\n return sorted;\n}\n\nexport function getDependencyOrder(\n targetPackage: string,\n packages: MonorepoPackage[],\n): MonorepoPackage[] {\n const nameToPackage = new Map<string, MonorepoPackage>();\n\n for (const pkg of packages) {\n nameToPackage.set(pkg.name, pkg);\n }\n\n const target = nameToPackage.get(targetPackage);\n\n if (!target) return [];\n\n const visited = new Set<string>();\n const result: MonorepoPackage[] = [];\n\n function visit(name: string) {\n if (visited.has(name)) return;\n\n visited.add(name);\n\n const pkg = nameToPackage.get(name);\n\n if (!pkg) return;\n\n if (pkg.dependsOn) {\n for (const dep of pkg.dependsOn) {\n visit(dep);\n }\n }\n\n if (name !== targetPackage) {\n result.push(pkg);\n }\n }\n\n visit(targetPackage);\n\n return result;\n}\n\nexport async function buildPackage(\n packageName: string,\n cwd: string = process.cwd(),\n): Promise<void> {\n await runCmdOrExit(`build ${packageName}`, [\n 'pnpm',\n '--filter',\n packageName,\n 'build',\n ], { cwd });\n}\n\nexport async function buildDependencies(\n targetPackage: string,\n packages: MonorepoPackage[],\n cwd: string = process.cwd(),\n): Promise<void> {\n const deps = getDependencyOrder(targetPackage, packages);\n\n for (const dep of deps) {\n console.log(`Building dependency: ${dep.name}`);\n await buildPackage(dep.name, cwd);\n }\n}\n","import { cliInput } from '@ls-stack/cli';\nimport { styleText } from 'node:util';\nimport {\n configExists,\n generateConfigFile,\n type MonorepoPackage,\n type PkgManagerConfig,\n type PrePublishScript,\n} from '../core/config.ts';\nimport { detectMonorepo, scanPackages } from '../core/monorepo.ts';\n\ntype InitArgs = {\n force: boolean;\n};\n\nexport async function initCommand({ force }: InitArgs): Promise<void> {\n if (configExists() && !force) {\n console.error(\n styleText(['red', 'bold'], 'Config file already exists. Use --force to overwrite.'),\n );\n process.exit(1);\n }\n\n console.log(styleText(['blue', 'bold'], 'Initializing pkg-manager config...\\n'));\n\n const isMonorepo = detectMonorepo();\n\n if (isMonorepo) {\n console.log(styleText(['green'], 'Detected monorepo (pnpm-workspace.yaml found)\\n'));\n }\n\n const prePublishScripts = await selectPrePublishScripts();\n let monorepoConfig: { packages: MonorepoPackage[] } | undefined;\n\n if (isMonorepo) {\n const packages = scanPackages();\n\n if (packages.length > 0) {\n console.log(styleText(['blue'], `\\nFound ${packages.length} packages:`));\n\n for (const pkg of packages) {\n console.log(styleText(['dim'], ` - ${pkg.name} (${pkg.path})`));\n }\n\n const configureDeps = await cliInput.confirm(\n '\\nConfigure package dependencies?',\n { initial: true },\n );\n\n if (configureDeps) {\n monorepoConfig = await configureMonorepoDependencies(packages);\n } else {\n monorepoConfig = { packages };\n }\n }\n }\n\n const config: PkgManagerConfig = {\n requireMajorConfirmation: true,\n };\n\n if (prePublishScripts.length > 0) {\n config.prePublish = prePublishScripts;\n }\n\n if (monorepoConfig) {\n config.monorepo = monorepoConfig;\n }\n\n generateConfigFile(config);\n\n console.log(styleText(['green', 'bold'], '\\npkg-manager.config.ts created successfully!'));\n}\n\nasync function selectPrePublishScripts(): Promise<PrePublishScript[]> {\n const scripts: PrePublishScript[] = [];\n\n const selectedScripts = await cliInput.multipleSelect(\n 'Select pre-publish scripts to run:',\n {\n options: [\n {\n value: 'lint',\n label: 'Lint',\n hint: 'Run pnpm lint',\n },\n {\n value: 'test',\n label: 'Test',\n hint: 'Run pnpm test',\n },\n {\n value: 'build',\n label: 'Build',\n hint: 'Run pnpm build',\n },\n ],\n },\n );\n\n for (const script of selectedScripts) {\n switch (script) {\n case 'lint':\n scripts.push({ command: 'pnpm lint', label: 'Linting' });\n break;\n case 'test':\n scripts.push({ command: 'pnpm test', label: 'Testing' });\n break;\n case 'build':\n scripts.push({ command: 'pnpm build', label: 'Building' });\n break;\n }\n }\n\n return scripts;\n}\n\nasync function configureMonorepoDependencies(\n packages: MonorepoPackage[],\n): Promise<{ packages: MonorepoPackage[] }> {\n const configuredPackages: MonorepoPackage[] = [];\n\n for (const pkg of packages) {\n const otherPackages = packages.filter((p) => p.name !== pkg.name);\n\n if (otherPackages.length === 0) {\n configuredPackages.push(pkg);\n continue;\n }\n\n const deps = await cliInput.multipleSelect(\n `Select dependencies for ${pkg.name}:`,\n {\n options: [\n { value: '__none__', label: 'None', hint: 'No dependencies' },\n ...otherPackages.map((p) => ({\n value: p.name,\n label: p.name,\n hint: p.path,\n })),\n ],\n },\n );\n\n const filteredDeps = deps.filter((d) => d !== '__none__');\n\n if (filteredDeps.length > 0) {\n configuredPackages.push({\n ...pkg,\n dependsOn: filteredDeps,\n });\n } else {\n configuredPackages.push(pkg);\n }\n }\n\n return { packages: configuredPackages };\n}\n","import { runCmd, runCmdOrExit } from '../utils/runCmd.ts';\n\nexport async function isGitClean(): Promise<boolean> {\n const result = await runCmd('check git status', ['git', 'status', '--porcelain'], {\n silent: true,\n });\n\n if (!result.ok) return false;\n\n return result.output.trim() === '';\n}\n\nexport async function gitAdd(files: string[] = ['.']): Promise<void> {\n await runCmdOrExit('stage changes', ['git', 'add', ...files]);\n}\n\nexport async function gitCommit(message: string): Promise<void> {\n await runCmdOrExit('commit', ['git', 'commit', '-m', message]);\n}\n\nexport async function commitIfDirty(message: string): Promise<boolean> {\n const clean = await isGitClean();\n\n if (clean) {\n console.log('No changes to commit');\n return false;\n }\n\n await gitAdd();\n await gitCommit(message);\n return true;\n}\n","import { createHash } from 'crypto';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from 'fs';\nimport { dirname, join } from 'path';\nimport { z } from 'zod';\n\nconst packageHashesSchema = z.object({\n versions: z.record(z.string(), z.string()),\n lastVersion: z.string().optional(),\n});\n\nconst hashStoreSchema = z.object({\n packages: z.record(z.string(), packageHashesSchema),\n});\n\nexport function generateDirectoryHash(dirPath: string): string {\n if (!existsSync(dirPath)) {\n throw new Error(`Directory does not exist: ${dirPath}`);\n }\n\n const hash = createHash('sha256');\n const files: string[] = [];\n\n function collectFiles(currentPath: string, relativePath = '') {\n const items = readdirSync(currentPath).sort();\n for (const item of items) {\n const fullPath = join(currentPath, item);\n const itemRelativePath = relativePath ? join(relativePath, item) : item;\n const stat = statSync(fullPath);\n if (stat.isDirectory()) {\n collectFiles(fullPath, itemRelativePath);\n } else {\n files.push(itemRelativePath);\n }\n }\n }\n\n collectFiles(dirPath);\n\n for (const filePath of files) {\n const fullPath = join(dirPath, filePath);\n const content = readFileSync(fullPath);\n hash.update(filePath);\n hash.update(content);\n }\n\n return hash.digest('hex');\n}\n\ntype HashStore = z.infer<typeof hashStoreSchema>;\n\nexport function readHashStore(hashStorePath: string): HashStore {\n if (!existsSync(hashStorePath)) {\n return { packages: {} };\n }\n\n try {\n const content = readFileSync(hashStorePath, 'utf-8');\n const parsed = JSON.parse(content);\n return hashStoreSchema.parse(parsed);\n } catch {\n return { packages: {} };\n }\n}\n\nexport function writeHashStore(hashStorePath: string, store: HashStore): void {\n const dir = dirname(hashStorePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(hashStorePath, `${JSON.stringify(store, null, 2)}\\n`);\n}\n\nexport function checkHashForDuplicate(\n hashStorePath: string,\n packageName: string,\n currentHash: string,\n): { isDuplicate: boolean; existingVersion?: string } {\n const store = readHashStore(hashStorePath);\n const packageHashes = store.packages[packageName];\n\n if (!packageHashes) {\n return { isDuplicate: false };\n }\n\n for (const [version, hash] of Object.entries(packageHashes.versions)) {\n if (hash === currentHash) {\n return { isDuplicate: true, existingVersion: version };\n }\n }\n\n return { isDuplicate: false };\n}\n\nexport function savePackageHash(\n hashStorePath: string,\n packageName: string,\n version: string,\n hash: string,\n): void {\n const store = readHashStore(hashStorePath);\n\n if (!store.packages[packageName]) {\n store.packages[packageName] = { versions: {} };\n }\n\n const pkgStore = store.packages[packageName];\n\n pkgStore.versions[version] = hash;\n pkgStore.lastVersion = version;\n\n writeHashStore(hashStorePath, store);\n}\n","import { cliInput } from '@ls-stack/cli';\nimport clipboardy from 'clipboardy';\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { styleText } from 'node:util';\nimport { z } from 'zod';\nimport {\n getHashStorePath,\n loadConfig,\n type PkgManagerConfig,\n type PrePublishScript,\n} from '../core/config.ts';\nimport { commitIfDirty, isGitClean } from '../core/git.ts';\nimport {\n checkHashForDuplicate,\n generateDirectoryHash,\n savePackageHash,\n} from '../core/hash.ts';\nimport { buildDependencies } from '../core/monorepo.ts';\nimport { runCmdOrExit } from '../utils/runCmd.ts';\n\nconst VERSION_TYPES = ['major', 'minor', 'patch'] as const;\ntype VersionType = (typeof VERSION_TYPES)[number];\n\nconst packageJsonSchema = z.object({\n name: z.string().optional(),\n version: z.string().optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n});\n\ntype PublishArgs = {\n package: string | undefined;\n type: string | undefined;\n force: boolean;\n dryRun: boolean;\n skipConfirm: boolean;\n};\n\nexport async function publishCommand(args: PublishArgs): Promise<void> {\n const config = await loadConfig();\n const cwd = process.cwd();\n\n const isClean = await isGitClean();\n\n if (!isClean) {\n console.error(\n styleText(['red', 'bold'], 'Git working directory is not clean.'),\n );\n console.error('Please commit or stash your changes before publishing.');\n process.exit(1);\n }\n\n const targetPackage = await resolveTargetPackage(args.package, config);\n const packagePath = getPackagePath(targetPackage, config, cwd);\n const packageName = getPackageName(packagePath);\n\n const currentVersion = getPackageVersion(packagePath);\n\n console.log(styleText(['blue', 'bold'], `\\nPublishing: ${packageName} (current: ${currentVersion})`));\n\n if (args.dryRun) {\n console.log(styleText(['yellow'], '(dry-run mode - no changes will be made)\\n'));\n }\n\n const versionType = await resolveVersionType(args.type, currentVersion);\n\n if (versionType === 'major' && config.requireMajorConfirmation && !args.skipConfirm) {\n const confirmed = await cliInput.confirm(\n 'You are about to publish a MAJOR version. Are you sure?',\n { initial: false },\n );\n\n if (!confirmed) {\n console.log('Aborted.');\n process.exit(0);\n }\n }\n\n if (config.monorepo?.packages) {\n console.log(styleText(['dim'], '\\nBuilding dependencies...'));\n if (!args.dryRun) {\n await buildDependencies(packageName, config.monorepo.packages, cwd);\n }\n }\n\n const prePublishScripts = getPrePublishScripts(config, packagePath, packageName);\n\n console.log(styleText(['dim'], '\\nRunning pre-publish scripts...'));\n\n for (const script of prePublishScripts) {\n console.log(styleText(['blue'], `\\n${script.label}...`));\n\n if (!args.dryRun) {\n const [cmd, ...cmdArgs] = script.command.split(' ');\n\n if (!cmd) {\n console.error(styleText(['red'], `Invalid command: ${script.command}`));\n process.exit(1);\n }\n\n if (config.monorepo) {\n await runCmdOrExit(script.label, ['pnpm', '--filter', packageName, ...cmdArgs], {\n cwd,\n });\n } else {\n await runCmdOrExit(script.label, [cmd, ...cmdArgs], { cwd: packagePath });\n }\n }\n }\n\n const distPath = join(packagePath, 'dist');\n\n if (!existsSync(distPath)) {\n console.error(styleText(['red', 'bold'], `dist directory not found at ${distPath}`));\n console.error('Please build your package first.');\n process.exit(1);\n }\n\n console.log(styleText(['dim'], '\\nGenerating build hash...'));\n const currentHash = generateDirectoryHash(distPath);\n console.log(styleText(['dim'], `Hash: ${currentHash.slice(0, 12)}...`));\n\n const hashStorePath = join(cwd, getHashStorePath(config));\n const hashCheck = checkHashForDuplicate(hashStorePath, packageName, currentHash);\n\n if (hashCheck.isDuplicate && !args.force) {\n console.error(\n styleText(\n ['red', 'bold'],\n `\\nThis build has already been published as ${packageName}@${hashCheck.existingVersion}`,\n ),\n );\n console.error('No changes detected in the build output.');\n console.error('Make code changes before attempting to publish.');\n console.error('Or use --force to publish anyway.');\n process.exit(1);\n }\n\n if (hashCheck.isDuplicate && args.force) {\n console.warn(\n styleText(\n ['yellow'],\n `\\nWarning: This build was already published as ${packageName}@${hashCheck.existingVersion}`,\n ),\n );\n console.warn('Force flag enabled - proceeding with publish anyway.');\n }\n\n console.log(styleText(['blue'], `\\nBumping version (${versionType})...`));\n\n if (!args.dryRun) {\n await runCmdOrExit('bump version', ['pnpm', 'version', versionType], {\n cwd: packagePath,\n });\n\n await commitIfDirty(`chore: bump ${packageName} to next ${versionType} version`);\n }\n\n const newVersion = getPackageVersion(packagePath);\n console.log(styleText(['green'], `New version: ${newVersion}`));\n\n console.log(styleText(['blue'], '\\nCreating git tag...'));\n\n if (!args.dryRun) {\n const tagName = `${packageName}@${newVersion}`;\n await runCmdOrExit('create tag', ['git', 'tag', tagName]);\n console.log(styleText(['dim'], `Created tag: ${tagName}`));\n }\n\n console.log(styleText(['blue'], '\\nPublishing to npm...'));\n\n if (!args.dryRun) {\n await runCmdOrExit('publish', ['pnpm', 'publish', '--access', 'public'], {\n cwd: packagePath,\n });\n\n savePackageHash(hashStorePath, packageName, newVersion, currentHash);\n\n await commitIfDirty(`chore: update publish hashes for ${packageName}@${newVersion}`);\n }\n\n const installCmd = `pnpm add ${packageName}@${newVersion}`;\n\n await clipboardy.write(installCmd);\n\n console.log(\n styleText(['green', 'bold'], `\\nSuccessfully published ${packageName}@${newVersion}`),\n );\n console.log(styleText(['dim'], `\\nCopied to clipboard: ${installCmd}`));\n}\n\nasync function resolveTargetPackage(\n packageArg: string | undefined,\n config: PkgManagerConfig,\n): Promise<string | undefined> {\n if (packageArg) return packageArg;\n\n if (!config.monorepo?.packages || config.monorepo.packages.length === 0) {\n return undefined;\n }\n\n const packageName = await cliInput.select('Select package to publish:', {\n options: config.monorepo.packages.map((pkg) => ({\n value: pkg.name,\n label: pkg.name,\n hint: pkg.path,\n })),\n });\n\n return packageName;\n}\n\nfunction bumpVersion(version: string, type: VersionType): string {\n const parts = version.split('.').map(Number);\n const major = parts[0] ?? 0;\n const minor = parts[1] ?? 0;\n const patch = parts[2] ?? 0;\n\n switch (type) {\n case 'major':\n return `${major + 1}.0.0`;\n case 'minor':\n return `${major}.${minor + 1}.0`;\n case 'patch':\n return `${major}.${minor}.${patch + 1}`;\n }\n}\n\nasync function resolveVersionType(\n typeArg: string | undefined,\n currentVersion: string,\n): Promise<VersionType> {\n if (typeArg) {\n const normalizedType = typeArg.toLowerCase();\n const matchingType = VERSION_TYPES.find((t) => t === normalizedType);\n\n if (!matchingType) {\n console.error(\n styleText(['red', 'bold'], `Invalid version type: ${typeArg}`),\n );\n console.error(`Valid types: ${VERSION_TYPES.join(', ')}`);\n process.exit(1);\n }\n return matchingType;\n }\n\n const versionType = await cliInput.select('Select version bump type:', {\n options: [\n { value: 'patch', label: 'patch', hint: `${currentVersion} → ${bumpVersion(currentVersion, 'patch')}` },\n { value: 'minor', label: 'minor', hint: `${currentVersion} → ${bumpVersion(currentVersion, 'minor')}` },\n { value: 'major', label: 'major', hint: `${currentVersion} → ${bumpVersion(currentVersion, 'major')}` },\n ],\n });\n\n return versionType;\n}\n\nfunction getPackagePath(\n targetPackage: string | undefined,\n config: PkgManagerConfig,\n cwd: string,\n): string {\n if (!targetPackage) return cwd;\n\n const pkg = config.monorepo?.packages.find((p) => p.name === targetPackage);\n\n if (pkg) return join(cwd, pkg.path);\n\n return cwd;\n}\n\nfunction readPackageJson(packagePath: string): z.infer<typeof packageJsonSchema> {\n const packageJsonPath = join(packagePath, 'package.json');\n const content = readFileSync(packageJsonPath, 'utf-8');\n const parsed = JSON.parse(content);\n return packageJsonSchema.parse(parsed);\n}\n\nfunction getPackageName(packagePath: string): string {\n const packageJsonPath = join(packagePath, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n console.error(\n styleText(['red', 'bold'], `package.json not found at ${packagePath}`),\n );\n process.exit(1);\n }\n\n const packageJson = readPackageJson(packagePath);\n\n if (!packageJson.name) {\n console.error(\n styleText(['red', 'bold'], 'package.json does not have a name field'),\n );\n process.exit(1);\n }\n\n return packageJson.name;\n}\n\nfunction getPackageVersion(packagePath: string): string {\n const packageJson = readPackageJson(packagePath);\n return packageJson.version ?? '0.0.0';\n}\n\nfunction getPrePublishScripts(\n config: PkgManagerConfig,\n packagePath: string,\n packageName: string,\n): PrePublishScript[] {\n if (config.prePublish && config.prePublish.length > 0) {\n return config.prePublish;\n }\n\n const packageJson = readPackageJson(packagePath);\n const hasPrePublishScript = packageJson.scripts?.['pre-publish'] !== undefined;\n\n if (hasPrePublishScript) {\n return [{ command: 'pnpm pre-publish', label: 'Running pre-publish script' }];\n }\n\n console.error(\n styleText(\n ['red', 'bold'],\n `\\nNo pre-publish scripts configured for ${packageName}`,\n ),\n );\n console.error(\n 'Either add a \"pre-publish\" script to package.json or configure \"prePublish\" in pkg-manager.config.ts',\n );\n process.exit(1);\n}\n","#!/usr/bin/env node\nimport { createCLI, createCmd } from '@ls-stack/cli';\nimport { initCommand } from './commands/init.ts';\nimport { publishCommand } from './commands/publish.ts';\n\nawait createCLI(\n {\n name: 'pkg-manager',\n baseCmd: 'pkg-manager',\n sort: ['publish', 'init'],\n },\n {\n init: createCmd({\n description: 'Initialize pkg-manager configuration',\n args: {\n force: {\n type: 'flag',\n name: 'force',\n description: 'Overwrite existing config file',\n },\n },\n run: async ({ force }) => {\n await initCommand({ force });\n },\n }),\n\n publish: createCmd({\n short: 'p',\n description: 'Publish a package with hash-based change detection',\n args: {\n package: {\n type: 'positional-string',\n name: 'package',\n description: 'Package name to publish (monorepo only)',\n default: '',\n },\n type: {\n type: 'value-string-flag',\n name: 'type',\n description: 'Version bump type: major, minor, or patch',\n },\n force: {\n type: 'flag',\n name: 'force',\n description: 'Force publish even if no changes detected',\n },\n dryRun: {\n type: 'flag',\n name: 'dry-run',\n description: 'Show what would be done without making changes',\n },\n skipConfirm: {\n type: 'flag',\n name: 'skip-confirm',\n description: 'Skip major version confirmation prompt',\n },\n },\n examples: [\n { args: ['--type', 'patch'], description: 'Publish a patch version' },\n { args: ['@my-scope/pkg', '--type', 'minor'], description: 'Publish specific package' },\n { args: ['--dry-run'], description: 'Preview publish without changes' },\n { args: ['--force', '--type', 'patch'], description: 'Force publish even if unchanged' },\n ],\n run: async ({ package: pkg, type, force, dryRun, skipConfirm }) => {\n await publishCommand({\n package: pkg || undefined,\n type,\n force,\n dryRun,\n skipConfirm,\n });\n },\n }),\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.mjs","names":["packageJsonSchema"],"sources":["../src/utils/runCmd.ts","../src/core/monorepo.ts","../src/commands/init.ts","../src/core/git.ts","../src/core/hash.ts","../src/core/semver.ts","../src/commands/publish.ts","../src/main.ts"],"sourcesContent":["import { spawn } from 'child_process';\nimport { styleText } from 'node:util';\n\nexport type RunCmdOptions = {\n cwd?: string;\n silent?: boolean;\n};\n\nexport async function runCmd(\n label: string,\n cmd: string[],\n options: RunCmdOptions = {},\n): Promise<{ ok: true; output: string } | { ok: false; error: string }> {\n const [command, ...args] = cmd;\n\n if (!command) {\n return { ok: false, error: 'No command provided' };\n }\n\n if (!options.silent) {\n console.log(styleText(['dim'], `> ${cmd.join(' ')}`));\n }\n\n return new Promise((resolve) => {\n const proc = spawn(command, args, {\n cwd: options.cwd,\n stdio: options.silent ? 'pipe' : 'inherit',\n });\n\n let stdout = '';\n let stderr = '';\n\n if (options.silent) {\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString();\n });\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n }\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ ok: true, output: stdout });\n } else {\n resolve({\n ok: false,\n error: stderr || stdout || `Command failed with exit code ${code}`,\n });\n }\n });\n\n proc.on('error', (error) => {\n resolve({ ok: false, error: error.message });\n });\n });\n}\n\nexport async function runCmdOrExit(\n label: string,\n cmd: string[],\n options: RunCmdOptions = {},\n): Promise<string> {\n const result = await runCmd(label, cmd, options);\n\n if (!result.ok) {\n console.error(styleText(['red', 'bold'], `Failed: ${label}`));\n console.error(result.error);\n process.exit(1);\n }\n\n return result.output;\n}\n","import { existsSync, readFileSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport { z } from 'zod';\nimport type { MonorepoPackage } from './config.ts';\nimport { runCmdOrExit } from '../utils/runCmd.ts';\n\nexport function detectMonorepo(cwd: string = process.cwd()): boolean {\n return existsSync(join(cwd, 'pnpm-workspace.yaml'));\n}\n\nconst packageJsonSchema = z.object({\n name: z.string().optional(),\n});\n\nexport function scanPackages(cwd: string = process.cwd()): MonorepoPackage[] {\n const workspacePath = join(cwd, 'pnpm-workspace.yaml');\n\n if (!existsSync(workspacePath)) return [];\n\n const packages: MonorepoPackage[] = [];\n const packagesDir = join(cwd, 'packages');\n\n if (!existsSync(packagesDir)) return [];\n\n const items = readdirSync(packagesDir);\n\n for (const item of items) {\n const itemPath = join(packagesDir, item);\n const stat = statSync(itemPath);\n\n if (!stat.isDirectory()) continue;\n\n const packageJsonPath = join(itemPath, 'package.json');\n\n if (!existsSync(packageJsonPath)) continue;\n\n try {\n const content = readFileSync(packageJsonPath, 'utf-8');\n const parsed = JSON.parse(content);\n const packageJson = packageJsonSchema.parse(parsed);\n\n if (packageJson.name) {\n packages.push({\n name: packageJson.name,\n path: `packages/${item}`,\n });\n }\n } catch {\n continue;\n }\n }\n\n return packages;\n}\n\nexport function topologicalSort(packages: MonorepoPackage[]): MonorepoPackage[] {\n const nameToPackage = new Map<string, MonorepoPackage>();\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n\n for (const pkg of packages) {\n nameToPackage.set(pkg.name, pkg);\n inDegree.set(pkg.name, 0);\n dependents.set(pkg.name, []);\n }\n\n for (const pkg of packages) {\n if (pkg.dependsOn) {\n for (const dep of pkg.dependsOn) {\n if (nameToPackage.has(dep)) {\n inDegree.set(pkg.name, (inDegree.get(pkg.name) ?? 0) + 1);\n dependents.get(dep)?.push(pkg.name);\n }\n }\n }\n }\n\n const queue: string[] = [];\n\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n const sorted: MonorepoPackage[] = [];\n\n while (queue.length > 0) {\n const name = queue.shift();\n\n if (!name) continue;\n\n const pkg = nameToPackage.get(name);\n\n if (pkg) {\n sorted.push(pkg);\n }\n\n for (const dependent of dependents.get(name) ?? []) {\n const newDegree = (inDegree.get(dependent) ?? 1) - 1;\n inDegree.set(dependent, newDegree);\n\n if (newDegree === 0) {\n queue.push(dependent);\n }\n }\n }\n\n if (sorted.length !== packages.length) {\n throw new Error('Circular dependency detected in package graph');\n }\n\n return sorted;\n}\n\nexport function getDependencyOrder(\n targetPackage: string,\n packages: MonorepoPackage[],\n): MonorepoPackage[] {\n const nameToPackage = new Map<string, MonorepoPackage>();\n\n for (const pkg of packages) {\n nameToPackage.set(pkg.name, pkg);\n }\n\n const target = nameToPackage.get(targetPackage);\n\n if (!target) return [];\n\n const visited = new Set<string>();\n const result: MonorepoPackage[] = [];\n\n function visit(name: string) {\n if (visited.has(name)) return;\n\n visited.add(name);\n\n const pkg = nameToPackage.get(name);\n\n if (!pkg) return;\n\n if (pkg.dependsOn) {\n for (const dep of pkg.dependsOn) {\n visit(dep);\n }\n }\n\n if (name !== targetPackage) {\n result.push(pkg);\n }\n }\n\n visit(targetPackage);\n\n return result;\n}\n\nexport async function buildPackage(\n packageName: string,\n cwd: string = process.cwd(),\n): Promise<void> {\n await runCmdOrExit(`build ${packageName}`, [\n 'pnpm',\n '--filter',\n packageName,\n 'build',\n ], { cwd });\n}\n\nexport async function buildDependencies(\n targetPackage: string,\n packages: MonorepoPackage[],\n cwd: string = process.cwd(),\n): Promise<void> {\n const deps = getDependencyOrder(targetPackage, packages);\n\n for (const dep of deps) {\n console.log(`Building dependency: ${dep.name}`);\n await buildPackage(dep.name, cwd);\n }\n}\n","import { cliInput } from '@ls-stack/cli';\nimport { styleText } from 'node:util';\nimport {\n configExists,\n generateConfigFile,\n type MonorepoPackage,\n type PkgManagerConfig,\n type PrePublishScript,\n} from '../core/config.ts';\nimport { detectMonorepo, scanPackages } from '../core/monorepo.ts';\n\ntype InitArgs = {\n force: boolean;\n};\n\nexport async function initCommand({ force }: InitArgs): Promise<void> {\n if (configExists() && !force) {\n console.error(\n styleText(['red', 'bold'], 'Config file already exists. Use --force to overwrite.'),\n );\n process.exit(1);\n }\n\n console.log(styleText(['blue', 'bold'], 'Initializing pkg-manager config...\\n'));\n\n const isMonorepo = detectMonorepo();\n\n if (isMonorepo) {\n console.log(styleText(['green'], 'Detected monorepo (pnpm-workspace.yaml found)\\n'));\n }\n\n const prePublishScripts = await selectPrePublishScripts();\n let monorepoConfig: { packages: MonorepoPackage[] } | undefined;\n\n if (isMonorepo) {\n const packages = scanPackages();\n\n if (packages.length > 0) {\n console.log(styleText(['blue'], `\\nFound ${packages.length} packages:`));\n\n for (const pkg of packages) {\n console.log(styleText(['dim'], ` - ${pkg.name} (${pkg.path})`));\n }\n\n const configureDeps = await cliInput.confirm(\n '\\nConfigure package dependencies?',\n { initial: true },\n );\n\n if (configureDeps) {\n monorepoConfig = await configureMonorepoDependencies(packages);\n } else {\n monorepoConfig = { packages };\n }\n }\n }\n\n const config: PkgManagerConfig = {\n requireMajorConfirmation: true,\n };\n\n if (prePublishScripts.length > 0) {\n config.prePublish = prePublishScripts;\n }\n\n if (monorepoConfig) {\n config.monorepo = monorepoConfig;\n }\n\n generateConfigFile(config);\n\n console.log(styleText(['green', 'bold'], '\\npkg-manager.config.ts created successfully!'));\n}\n\nasync function selectPrePublishScripts(): Promise<PrePublishScript[]> {\n const scripts: PrePublishScript[] = [];\n\n const selectedScripts = await cliInput.multipleSelect(\n 'Select pre-publish scripts to run:',\n {\n options: [\n {\n value: 'lint',\n label: 'Lint',\n hint: 'Run pnpm lint',\n },\n {\n value: 'test',\n label: 'Test',\n hint: 'Run pnpm test',\n },\n {\n value: 'build',\n label: 'Build',\n hint: 'Run pnpm build',\n },\n ],\n },\n );\n\n for (const script of selectedScripts) {\n switch (script) {\n case 'lint':\n scripts.push({ command: 'pnpm lint', label: 'Linting' });\n break;\n case 'test':\n scripts.push({ command: 'pnpm test', label: 'Testing' });\n break;\n case 'build':\n scripts.push({ command: 'pnpm build', label: 'Building' });\n break;\n }\n }\n\n return scripts;\n}\n\nasync function configureMonorepoDependencies(\n packages: MonorepoPackage[],\n): Promise<{ packages: MonorepoPackage[] }> {\n const configuredPackages: MonorepoPackage[] = [];\n\n for (const pkg of packages) {\n const otherPackages = packages.filter((p) => p.name !== pkg.name);\n\n if (otherPackages.length === 0) {\n configuredPackages.push(pkg);\n continue;\n }\n\n const deps = await cliInput.multipleSelect(\n `Select dependencies for ${pkg.name}:`,\n {\n options: [\n { value: '__none__', label: 'None', hint: 'No dependencies' },\n ...otherPackages.map((p) => ({\n value: p.name,\n label: p.name,\n hint: p.path,\n })),\n ],\n },\n );\n\n const filteredDeps = deps.filter((d) => d !== '__none__');\n\n if (filteredDeps.length > 0) {\n configuredPackages.push({\n ...pkg,\n dependsOn: filteredDeps,\n });\n } else {\n configuredPackages.push(pkg);\n }\n }\n\n return { packages: configuredPackages };\n}\n","import { runCmd, runCmdOrExit } from '../utils/runCmd.ts';\n\nexport async function isGitClean(): Promise<boolean> {\n const result = await runCmd('check git status', ['git', 'status', '--porcelain'], {\n silent: true,\n });\n\n if (!result.ok) return false;\n\n return result.output.trim() === '';\n}\n\nexport async function gitAdd(files: string[] = ['.']): Promise<void> {\n await runCmdOrExit('stage changes', ['git', 'add', ...files]);\n}\n\nexport async function gitCommit(message: string): Promise<void> {\n await runCmdOrExit('commit', ['git', 'commit', '-m', message]);\n}\n\nexport async function commitIfDirty(message: string): Promise<boolean> {\n const clean = await isGitClean();\n\n if (clean) {\n console.log('No changes to commit');\n return false;\n }\n\n await gitAdd();\n await gitCommit(message);\n return true;\n}\n","import { createHash } from 'crypto';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n} from 'fs';\nimport { dirname, join } from 'path';\nimport { z } from 'zod';\n\nconst packageHashesSchema = z.object({\n versions: z.record(z.string(), z.string()),\n lastVersion: z.string().optional(),\n});\n\nconst hashStoreSchema = z.object({\n packages: z.record(z.string(), packageHashesSchema),\n});\n\nexport function generateDirectoryHash(dirPath: string): string {\n if (!existsSync(dirPath)) {\n throw new Error(`Directory does not exist: ${dirPath}`);\n }\n\n const hash = createHash('sha256');\n const files: string[] = [];\n\n function collectFiles(currentPath: string, relativePath = '') {\n const items = readdirSync(currentPath).sort();\n for (const item of items) {\n const fullPath = join(currentPath, item);\n const itemRelativePath = relativePath ? join(relativePath, item) : item;\n const stat = statSync(fullPath);\n if (stat.isDirectory()) {\n collectFiles(fullPath, itemRelativePath);\n } else {\n files.push(itemRelativePath);\n }\n }\n }\n\n collectFiles(dirPath);\n\n for (const filePath of files) {\n const fullPath = join(dirPath, filePath);\n const content = readFileSync(fullPath);\n hash.update(filePath);\n hash.update(content);\n }\n\n return hash.digest('hex');\n}\n\ntype HashStore = z.infer<typeof hashStoreSchema>;\n\nexport function readHashStore(hashStorePath: string): HashStore {\n if (!existsSync(hashStorePath)) {\n return { packages: {} };\n }\n\n try {\n const content = readFileSync(hashStorePath, 'utf-8');\n const parsed = JSON.parse(content);\n return hashStoreSchema.parse(parsed);\n } catch {\n return { packages: {} };\n }\n}\n\nexport function writeHashStore(hashStorePath: string, store: HashStore): void {\n const dir = dirname(hashStorePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(hashStorePath, `${JSON.stringify(store, null, 2)}\\n`);\n}\n\nexport function checkHashForDuplicate(\n hashStorePath: string,\n packageName: string,\n currentHash: string,\n): { isDuplicate: boolean; existingVersion?: string } {\n const store = readHashStore(hashStorePath);\n const packageHashes = store.packages[packageName];\n\n if (!packageHashes) {\n return { isDuplicate: false };\n }\n\n for (const [version, hash] of Object.entries(packageHashes.versions)) {\n if (hash === currentHash) {\n return { isDuplicate: true, existingVersion: version };\n }\n }\n\n return { isDuplicate: false };\n}\n\nexport function savePackageHash(\n hashStorePath: string,\n packageName: string,\n version: string,\n hash: string,\n): void {\n const store = readHashStore(hashStorePath);\n\n if (!store.packages[packageName]) {\n store.packages[packageName] = { versions: {} };\n }\n\n const pkgStore = store.packages[packageName];\n\n pkgStore.versions[version] = hash;\n pkgStore.lastVersion = version;\n\n writeHashStore(hashStorePath, store);\n}\n","export const PRERELEASE_TAGS = ['alpha', 'beta', 'rc'] as const\nexport type PrereleaseTag = (typeof PRERELEASE_TAGS)[number]\n\nexport type ParsedVersion = {\n major: number\n minor: number\n patch: number\n prerelease: { tag: string; number: number } | undefined\n}\n\nexport function parseVersion(version: string): ParsedVersion {\n const [core, prereleaseStr] = version.split('-')\n\n const parts = (core ?? '').split('.').map(Number)\n const major = parts[0] ?? 0\n const minor = parts[1] ?? 0\n const patch = parts[2] ?? 0\n\n if (prereleaseStr) {\n const lastDotIndex = prereleaseStr.lastIndexOf('.')\n if (lastDotIndex !== -1) {\n const tag = prereleaseStr.slice(0, lastDotIndex)\n const num = Number(prereleaseStr.slice(lastDotIndex + 1))\n return { major, minor, patch, prerelease: { tag, number: num } }\n }\n return { major, minor, patch, prerelease: { tag: prereleaseStr, number: 0 } }\n }\n\n return { major, minor, patch, prerelease: undefined }\n}\n\nexport function formatVersion(parsed: ParsedVersion): string {\n const base = `${parsed.major}.${parsed.minor}.${parsed.patch}`\n if (parsed.prerelease) {\n return `${base}-${parsed.prerelease.tag}.${parsed.prerelease.number}`\n }\n return base\n}\n\nexport function isPrerelease(version: string): boolean {\n return version.includes('-')\n}\n\nexport function getPrereleaseTag(version: string): string | undefined {\n return parseVersion(version).prerelease?.tag\n}\n\n/**\n * Returns prerelease tags that come after the given tag in the progression.\n * alpha → [beta, rc], beta → [rc], rc → []\n * Unknown tags → all PRERELEASE_TAGS\n */\nexport function getNextTags(currentTag: string): PrereleaseTag[] {\n const index = PRERELEASE_TAGS.findIndex((t) => t === currentTag)\n if (index === -1) return [...PRERELEASE_TAGS]\n return [...PRERELEASE_TAGS.slice(index + 1)]\n}\n\n/**\n * Computes the resulting version string for a given bump operation.\n * Used for displaying hints in the version select UI.\n */\nexport function bumpVersionPreview(\n version: string,\n type: 'patch' | 'minor' | 'major' | 'prepatch' | 'preminor' | 'premajor' | 'prerelease' | 'release',\n preid?: string,\n): string {\n const parsed = parseVersion(version)\n\n switch (type) {\n case 'patch': {\n if (parsed.prerelease) {\n return `${parsed.major}.${parsed.minor}.${parsed.patch}`\n }\n return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`\n }\n case 'minor': {\n if (parsed.prerelease && parsed.patch === 0) {\n return `${parsed.major}.${parsed.minor}.0`\n }\n return `${parsed.major}.${parsed.minor + 1}.0`\n }\n case 'major': {\n if (parsed.prerelease && parsed.minor === 0 && parsed.patch === 0) {\n return `${parsed.major}.0.0`\n }\n return `${parsed.major + 1}.0.0`\n }\n case 'prepatch': {\n const tag = preid ?? 'alpha'\n return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${tag}.0`\n }\n case 'preminor': {\n const tag = preid ?? 'alpha'\n return `${parsed.major}.${parsed.minor + 1}.0-${tag}.0`\n }\n case 'premajor': {\n const tag = preid ?? 'alpha'\n return `${parsed.major + 1}.0.0-${tag}.0`\n }\n case 'prerelease': {\n if (parsed.prerelease) {\n if (preid && preid !== parsed.prerelease.tag) {\n return `${parsed.major}.${parsed.minor}.${parsed.patch}-${preid}.0`\n }\n return `${parsed.major}.${parsed.minor}.${parsed.patch}-${parsed.prerelease.tag}.${parsed.prerelease.number + 1}`\n }\n const tag = preid ?? 'alpha'\n return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}-${tag}.0`\n }\n case 'release': {\n return `${parsed.major}.${parsed.minor}.${parsed.patch}`\n }\n }\n}\n","import { cliInput } from '@ls-stack/cli';\nimport clipboardy from 'clipboardy';\nimport { env } from 'node:process';\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { styleText } from 'node:util';\nimport { z } from 'zod';\nimport {\n getHashStorePath,\n loadConfig,\n type PkgManagerConfig,\n type PrePublishScript,\n} from '../core/config.ts';\nimport { commitIfDirty, isGitClean } from '../core/git.ts';\nimport {\n checkHashForDuplicate,\n generateDirectoryHash,\n savePackageHash,\n} from '../core/hash.ts';\nimport { buildDependencies } from '../core/monorepo.ts';\nimport {\n bumpVersionPreview,\n getNextTags,\n getPrereleaseTag,\n isPrerelease,\n PRERELEASE_TAGS,\n type PrereleaseTag,\n} from '../core/semver.ts';\nimport { runCmdOrExit } from '../utils/runCmd.ts';\n\nconst PRE_TYPE_REGEX = /^(prepatch|preminor|premajor)-(\\w+)$/;\n\ntype VersionBumpSpec = {\n label: string;\n versionArgs: string[];\n isMajor: boolean;\n distTag: string | undefined;\n};\n\nconst packageJsonSchema = z.object({\n name: z.string().optional(),\n version: z.string().optional(),\n scripts: z.record(z.string(), z.string()).optional(),\n});\n\ntype PublishArgs = {\n package: string | undefined;\n type: string | undefined;\n force: boolean;\n dryRun: boolean;\n skipConfirm: boolean;\n};\n\nexport async function publishCommand(args: PublishArgs): Promise<void> {\n const config = await loadConfig();\n const cwd = process.cwd();\n\n const isClean = await isGitClean();\n\n if (!isClean) {\n console.error(\n styleText(['red', 'bold'], 'Git working directory is not clean.'),\n );\n console.error('Please commit or stash your changes before publishing.');\n process.exit(1);\n }\n\n const targetPackage = await resolveTargetPackage(args.package, config);\n const packagePath = getPackagePath(targetPackage, config, cwd);\n const packageName = getPackageName(packagePath);\n\n const currentVersion = getPackageVersion(packagePath);\n\n console.log(styleText(['blue', 'bold'], `\\nPublishing: ${packageName} (current: ${currentVersion})`));\n\n if (args.dryRun) {\n console.log(styleText(['yellow'], '(dry-run mode - no changes will be made)\\n'));\n }\n\n const versionBump = await resolveVersionBump(args.type, currentVersion);\n\n if (versionBump.isMajor && config.requireMajorConfirmation && !args.skipConfirm) {\n const confirmed = await cliInput.confirm(\n 'You are about to publish a MAJOR version. Are you sure?',\n { initial: false },\n );\n\n if (!confirmed) {\n console.log('Aborted.');\n process.exit(0);\n }\n }\n\n if (config.monorepo?.packages) {\n console.log(styleText(['dim'], '\\nBuilding dependencies...'));\n if (!args.dryRun) {\n await buildDependencies(packageName, config.monorepo.packages, cwd);\n }\n }\n\n const prePublishScripts = getPrePublishScripts(config, packagePath, packageName);\n\n console.log(styleText(['dim'], '\\nRunning pre-publish scripts...'));\n\n for (const script of prePublishScripts) {\n console.log(styleText(['blue'], `\\n${script.label}...`));\n\n if (!args.dryRun) {\n const [cmd, ...cmdArgs] = script.command.split(' ');\n\n if (!cmd) {\n console.error(styleText(['red'], `Invalid command: ${script.command}`));\n process.exit(1);\n }\n\n if (config.monorepo) {\n await runCmdOrExit(script.label, ['pnpm', '--filter', packageName, ...cmdArgs], {\n cwd,\n });\n } else {\n await runCmdOrExit(script.label, [cmd, ...cmdArgs], { cwd: packagePath });\n }\n }\n }\n\n const distPath = join(packagePath, 'dist');\n\n if (!existsSync(distPath)) {\n console.error(styleText(['red', 'bold'], `dist directory not found at ${distPath}`));\n console.error('Please build your package first.');\n process.exit(1);\n }\n\n console.log(styleText(['dim'], '\\nGenerating build hash...'));\n const currentHash = generateDirectoryHash(distPath);\n console.log(styleText(['dim'], `Hash: ${currentHash.slice(0, 12)}...`));\n\n const hashStorePath = join(cwd, getHashStorePath(config));\n const hashCheck = checkHashForDuplicate(hashStorePath, packageName, currentHash);\n\n if (hashCheck.isDuplicate && !args.force) {\n console.error(\n styleText(\n ['red', 'bold'],\n `\\nThis build has already been published as ${packageName}@${hashCheck.existingVersion}`,\n ),\n );\n console.error('No changes detected in the build output.');\n console.error('Make code changes before attempting to publish.');\n console.error('Or use --force to publish anyway.');\n process.exit(1);\n }\n\n if (hashCheck.isDuplicate && args.force) {\n console.warn(\n styleText(\n ['yellow'],\n `\\nWarning: This build was already published as ${packageName}@${hashCheck.existingVersion}`,\n ),\n );\n console.warn('Force flag enabled - proceeding with publish anyway.');\n }\n\n console.log(styleText(['blue'], `\\nBumping version (${versionBump.label})...`));\n\n if (!args.dryRun) {\n await runCmdOrExit('bump version', ['pnpm', 'version', ...versionBump.versionArgs], {\n cwd: packagePath,\n });\n\n await commitIfDirty(`chore: bump ${packageName} version (${versionBump.label})`);\n }\n\n const newVersion = getPackageVersion(packagePath);\n console.log(styleText(['green'], `New version: ${newVersion}`));\n\n console.log(styleText(['blue'], '\\nCreating git tag...'));\n\n if (!args.dryRun) {\n const tagName = `${packageName}@${newVersion}`;\n await runCmdOrExit('create tag', ['git', 'tag', tagName]);\n console.log(styleText(['dim'], `Created tag: ${tagName}`));\n }\n\n console.log(styleText(['blue'], '\\nPublishing to npm...'));\n\n if (!args.dryRun) {\n const publishArgs = ['pnpm', 'publish', '--access', 'public'];\n\n if (versionBump.distTag) {\n publishArgs.push('--tag', versionBump.distTag);\n }\n\n await runCmdOrExit('publish', publishArgs, {\n cwd: packagePath,\n });\n\n savePackageHash(hashStorePath, packageName, newVersion, currentHash);\n\n await commitIfDirty(`chore: update publish hashes for ${packageName}@${newVersion}`);\n }\n\n console.log(\n styleText(['green', 'bold'], `\\nSuccessfully published ${packageName}@${newVersion}`),\n );\n\n const postPublishScripts = config.postPublish ?? [];\n\n if (postPublishScripts.length > 0) {\n console.log(styleText(['dim'], '\\nRunning post-publish scripts...'));\n\n for (const script of postPublishScripts) {\n console.log(styleText(['blue'], `\\n${script.label}...`));\n\n if (!args.dryRun) {\n const [cmd, ...cmdArgs] = script.command.split(' ');\n\n if (!cmd) {\n console.error(styleText(['red'], `Invalid command: ${script.command}`));\n process.exit(1);\n }\n\n if (config.monorepo) {\n await runCmdOrExit(script.label, ['pnpm', '--filter', packageName, ...cmdArgs], {\n cwd,\n });\n } else {\n await runCmdOrExit(script.label, [cmd, ...cmdArgs], { cwd: packagePath });\n }\n }\n }\n }\n\n const copyCmdPrefix = env.PKG_MANAGER_COPY_CMD;\n\n if (copyCmdPrefix) {\n const installCmd = `${copyCmdPrefix} ${packageName}@${newVersion}`;\n\n await clipboardy.write(installCmd);\n\n console.log(styleText(['dim'], `Copied to clipboard: ${installCmd}`));\n }\n}\n\nasync function resolveTargetPackage(\n packageArg: string | undefined,\n config: PkgManagerConfig,\n): Promise<string | undefined> {\n if (packageArg) return packageArg;\n\n if (!config.monorepo?.packages || config.monorepo.packages.length === 0) {\n return undefined;\n }\n\n const packageName = await cliInput.select('Select package to publish:', {\n options: config.monorepo.packages.map((pkg) => ({\n value: pkg.name,\n label: pkg.name,\n hint: pkg.path,\n })),\n });\n\n return packageName;\n}\n\nconst STABLE_TYPES = ['major', 'minor', 'patch'] as const;\ntype StableType = (typeof STABLE_TYPES)[number];\n\nconst VALID_TYPE_ARGS = [\n ...STABLE_TYPES,\n 'prerelease',\n 'release',\n ...PRERELEASE_TAGS.flatMap((tag) =>\n (['prepatch', 'preminor', 'premajor'] as const).map((base) => `${base}-${tag}`),\n ),\n] as const;\n\nfunction parseTypeArg(\n typeArg: string,\n currentVersion: string,\n): VersionBumpSpec {\n const normalized = typeArg.toLowerCase();\n\n const stableMatch = STABLE_TYPES.find((t) => t === normalized);\n if (stableMatch) {\n return {\n label: stableMatch,\n versionArgs: [stableMatch],\n isMajor: stableMatch === 'major',\n distTag: undefined,\n };\n }\n\n if (normalized === 'prerelease') {\n const currentTag = getPrereleaseTag(currentVersion);\n if (!currentTag) {\n console.error(styleText(['red', 'bold'], 'Cannot use --type=prerelease on a stable version.'));\n console.error('Use prepatch-alpha, preminor-alpha, or premajor-alpha instead.');\n process.exit(1);\n }\n return {\n label: 'prerelease',\n versionArgs: ['prerelease'],\n isMajor: false,\n distTag: currentTag,\n };\n }\n\n if (normalized === 'release') {\n if (!isPrerelease(currentVersion)) {\n console.error(styleText(['red', 'bold'], 'Cannot use --type=release on a stable version.'));\n process.exit(1);\n }\n return {\n label: 'release',\n versionArgs: ['patch'],\n isMajor: false,\n distTag: undefined,\n };\n }\n\n const preMatch = PRE_TYPE_REGEX.exec(normalized);\n if (preMatch) {\n const baseType = preMatch[1];\n const preid = preMatch[2];\n\n if (baseType && preid) {\n return {\n label: `${baseType} (${preid})`,\n versionArgs: [baseType, `--preid=${preid}`],\n isMajor: false,\n distTag: preid,\n };\n }\n }\n\n console.error(styleText(['red', 'bold'], `Invalid version type: ${typeArg}`));\n console.error(`Valid types: ${VALID_TYPE_ARGS.join(', ')}`);\n process.exit(1);\n}\n\nasync function resolveVersionBump(\n typeArg: string | undefined,\n currentVersion: string,\n): Promise<VersionBumpSpec> {\n if (typeArg) {\n return parseTypeArg(typeArg, currentVersion);\n }\n\n const currentPreTag = getPrereleaseTag(currentVersion);\n\n if (currentPreTag) {\n return resolveVersionBumpFromPrerelease(currentVersion, currentPreTag);\n }\n\n return resolveVersionBumpFromStable(currentVersion);\n}\n\nasync function resolveVersionBumpFromStable(\n currentVersion: string,\n): Promise<VersionBumpSpec> {\n type StableOption = StableType | 'prerelease-menu';\n\n const options: Array<{ value: StableOption; label: string; hint?: string }> = [\n { value: 'patch', label: 'patch', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'patch')}` },\n { value: 'minor', label: 'minor', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'minor')}` },\n { value: 'major', label: 'major', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'major')}` },\n { value: 'prerelease-menu', label: 'prerelease...' },\n ];\n\n const selection = await cliInput.select('Select version bump type:', { options });\n\n if (selection === 'prerelease-menu') {\n return resolvePrerelaseSubmenu(currentVersion);\n }\n\n return {\n label: selection,\n versionArgs: [selection],\n isMajor: selection === 'major',\n distTag: undefined,\n };\n}\n\nasync function resolvePrerelaseSubmenu(\n currentVersion: string,\n): Promise<VersionBumpSpec> {\n const baseTypes = ['prepatch', 'preminor', 'premajor'] as const;\n\n const options: Array<{ value: string; label: string; hint: string }> = [];\n\n for (const tag of PRERELEASE_TAGS) {\n for (const base of baseTypes) {\n const preview = bumpVersionPreview(currentVersion, base, tag);\n options.push({\n value: `${base}-${tag}`,\n label: `${base} (${tag})`,\n hint: `${currentVersion} → ${preview}`,\n });\n }\n }\n\n const selection = await cliInput.select('Select prerelease type:', { options });\n\n const [baseType, preid] = selection.split('-');\n\n if (!baseType || !preid) {\n console.error(styleText(['red', 'bold'], 'Unexpected selection format.'));\n process.exit(1);\n }\n\n return {\n label: `${baseType} (${preid})`,\n versionArgs: [baseType, `--preid=${preid}`],\n isMajor: false,\n distTag: preid,\n };\n}\n\ntype PrereleaseOption = 'prerelease' | 'release' | StableType | 'prerelease-menu' | `graduate-${PrereleaseTag}`;\n\nasync function resolveVersionBumpFromPrerelease(\n currentVersion: string,\n currentTag: string,\n): Promise<VersionBumpSpec> {\n const options: Array<{ value: PrereleaseOption; label: string; hint: string }> = [];\n\n options.push({\n value: 'prerelease',\n label: 'prerelease',\n hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'prerelease')}`,\n });\n\n const nextTags = getNextTags(currentTag);\n for (const tag of nextTags) {\n options.push({\n value: `graduate-${tag}`,\n label: `graduate to ${tag}`,\n hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'prerelease', tag)}`,\n });\n }\n\n options.push({\n value: 'release',\n label: 'release',\n hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'release')}`,\n });\n\n options.push(\n { value: 'patch', label: 'patch', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'patch')}` },\n { value: 'minor', label: 'minor', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'minor')}` },\n { value: 'major', label: 'major', hint: `${currentVersion} → ${bumpVersionPreview(currentVersion, 'major')}` },\n );\n\n options.push({\n value: 'prerelease-menu',\n label: 'prerelease...',\n hint: 'start a new prerelease cycle',\n });\n\n const selection = await cliInput.select('Select version bump type:', { options });\n\n if (selection === 'prerelease-menu') {\n return resolvePrerelaseSubmenu(currentVersion);\n }\n\n if (selection === 'prerelease') {\n return {\n label: 'prerelease',\n versionArgs: ['prerelease'],\n isMajor: false,\n distTag: currentTag,\n };\n }\n\n if (selection === 'release') {\n return {\n label: 'release',\n versionArgs: ['patch'],\n isMajor: false,\n distTag: undefined,\n };\n }\n\n if (selection.startsWith('graduate-')) {\n const targetTag = selection.replace('graduate-', '');\n return {\n label: `graduate to ${targetTag}`,\n versionArgs: ['prerelease', `--preid=${targetTag}`],\n isMajor: false,\n distTag: targetTag,\n };\n }\n\n return {\n label: selection,\n versionArgs: [selection],\n isMajor: selection === 'major',\n distTag: undefined,\n };\n}\n\nfunction getPackagePath(\n targetPackage: string | undefined,\n config: PkgManagerConfig,\n cwd: string,\n): string {\n if (!targetPackage) return cwd;\n\n const pkg = config.monorepo?.packages.find((p) => p.name === targetPackage);\n\n if (pkg) return join(cwd, pkg.path);\n\n return cwd;\n}\n\nfunction readPackageJson(packagePath: string): z.infer<typeof packageJsonSchema> {\n const packageJsonPath = join(packagePath, 'package.json');\n const content = readFileSync(packageJsonPath, 'utf-8');\n const parsed = JSON.parse(content);\n return packageJsonSchema.parse(parsed);\n}\n\nfunction getPackageName(packagePath: string): string {\n const packageJsonPath = join(packagePath, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n console.error(\n styleText(['red', 'bold'], `package.json not found at ${packagePath}`),\n );\n process.exit(1);\n }\n\n const packageJson = readPackageJson(packagePath);\n\n if (!packageJson.name) {\n console.error(\n styleText(['red', 'bold'], 'package.json does not have a name field'),\n );\n process.exit(1);\n }\n\n return packageJson.name;\n}\n\nfunction getPackageVersion(packagePath: string): string {\n const packageJson = readPackageJson(packagePath);\n return packageJson.version ?? '0.0.0';\n}\n\nfunction getPrePublishScripts(\n config: PkgManagerConfig,\n packagePath: string,\n packageName: string,\n): PrePublishScript[] {\n if (config.prePublish && config.prePublish.length > 0) {\n return config.prePublish;\n }\n\n const packageJson = readPackageJson(packagePath);\n const hasPrePublishScript = packageJson.scripts?.['pre-publish'] !== undefined;\n\n if (hasPrePublishScript) {\n return [{ command: 'pnpm pre-publish', label: 'Running pre-publish script' }];\n }\n\n console.error(\n styleText(\n ['red', 'bold'],\n `\\nNo pre-publish scripts configured for ${packageName}`,\n ),\n );\n console.error(\n 'Either add a \"pre-publish\" script to package.json or configure \"prePublish\" in pkg-manager.config.ts',\n );\n process.exit(1);\n}\n","#!/usr/bin/env node\nimport { createCLI, createCmd } from '@ls-stack/cli';\nimport { initCommand } from './commands/init.ts';\nimport { publishCommand } from './commands/publish.ts';\n\nawait createCLI(\n {\n name: 'pkg-manager',\n baseCmd: 'pkg-manager',\n sort: ['publish', 'init'],\n },\n {\n init: createCmd({\n description: 'Initialize pkg-manager configuration',\n args: {\n force: {\n type: 'flag',\n name: 'force',\n description: 'Overwrite existing config file',\n },\n },\n run: async ({ force }) => {\n await initCommand({ force });\n },\n }),\n\n publish: createCmd({\n short: 'p',\n description: 'Publish a package with hash-based change detection',\n args: {\n package: {\n type: 'positional-string',\n name: 'package',\n description: 'Package name to publish (monorepo only)',\n default: '',\n },\n type: {\n type: 'value-string-flag',\n name: 'type',\n description: 'Version bump type (e.g., patch, minor, major, prerelease, release, prepatch-alpha)',\n },\n force: {\n type: 'flag',\n name: 'force',\n description: 'Force publish even if no changes detected',\n },\n dryRun: {\n type: 'flag',\n name: 'dry-run',\n description: 'Show what would be done without making changes',\n },\n skipConfirm: {\n type: 'flag',\n name: 'skip-confirm',\n description: 'Skip major version confirmation prompt',\n },\n },\n examples: [\n { args: ['--type', 'patch'], description: 'Publish a patch version' },\n { args: ['@my-scope/pkg', '--type', 'minor'], description: 'Publish specific package' },\n { args: ['--dry-run'], description: 'Preview publish without changes' },\n { args: ['--force', '--type', 'patch'], description: 'Force publish even if unchanged' },\n ],\n run: async ({ package: pkg, type, force, dryRun, skipConfirm }) => {\n await publishCommand({\n package: pkg || undefined,\n type,\n force,\n dryRun,\n skipConfirm,\n });\n },\n }),\n },\n);\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ls-stack/pkg-manager",
|
|
3
3
|
"description": "CLI tool for managing package publishing with hash-based change tracking and monorepo support",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"node": ">=25.0.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@ls-stack/cli": "^0.
|
|
30
|
+
"@ls-stack/cli": "^0.6.0",
|
|
31
31
|
"clipboardy": "^5.3.1",
|
|
32
32
|
"zod": "^4.3.6"
|
|
33
33
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-CG8p1aGY.mjs","names":[],"sources":["../src/core/config.ts"],"sourcesContent":["import { existsSync, writeFileSync } from 'fs'\nimport { join } from 'path'\nimport { pathToFileURL } from 'url'\nimport { z } from 'zod'\n\nconst CONFIG_FILENAME = 'pkg-manager.config.ts'\nconst DEFAULT_HASH_STORE_PATH = 'node_modules/.pkg-manager/hashes.json'\n\nconst prePublishScriptSchema = z.object({\n command: z.string(),\n label: z.string(),\n})\n\nconst monorepoPackageSchema = z.object({\n name: z.string(),\n path: z.string(),\n dependsOn: z.array(z.string()).optional(),\n})\n\nconst pkgManagerConfigSchema = z.object({\n prePublish: z.array(prePublishScriptSchema).optional(),\n monorepo: z\n .object({\n packages: z.array(monorepoPackageSchema),\n })\n .optional(),\n hashStorePath: z.string().optional(),\n requireMajorConfirmation: z.boolean().optional(),\n})\n\nexport type MonorepoPackage = {\n /** Package name (as in package.json) */\n name: string\n /** Relative path to the package directory */\n path: string\n /** Package names this package depends on (for topological ordering) */\n dependsOn?: string[]\n}\n\nexport type PrePublishScript = {\n /** The shell command to execute */\n command: string\n /** Display label shown during execution */\n label: string\n}\n\n/**\n * Configuration for pkg-manager.\n */\nexport type PkgManagerConfig = {\n /** Scripts to run before publishing (e.g., build commands) */\n prePublish?: PrePublishScript[]\n /** Monorepo configuration for multi-package projects */\n monorepo?: {\n /** Array of packages in the monorepo */\n packages: MonorepoPackage[]\n }\n /**\n * Custom path for storing publish hashes.\n * @default \"node_modules/.pkg-manager/hashes.json\"\n */\n hashStorePath?: string\n /**\n * Require confirmation for major version bumps.\n * @default true\n */\n requireMajorConfirmation?: boolean\n}\n\n/**\n * Defines the configuration for pkg-manager.\n *\n * @example\n * ```ts\n * export default defineConfig({\n * requireMajorConfirmation: true,\n * prePublish: [{ command: 'pnpm build', label: 'Building' }],\n * });\n * ```\n */\nexport function defineConfig(config: PkgManagerConfig): PkgManagerConfig {\n return config\n}\n\nexport function getConfigPath(cwd: string = process.cwd()): string {\n return join(cwd, CONFIG_FILENAME)\n}\n\nexport function configExists(cwd: string = process.cwd()): boolean {\n return existsSync(getConfigPath(cwd))\n}\n\nconst defaultConfig: PkgManagerConfig = {\n hashStorePath: DEFAULT_HASH_STORE_PATH,\n requireMajorConfirmation: true,\n}\n\nexport async function loadConfig(\n cwd: string = process.cwd()\n): Promise<PkgManagerConfig> {\n const configPath = getConfigPath(cwd)\n\n if (!existsSync(configPath)) return defaultConfig\n\n const configModule: { default: unknown } = await import(\n pathToFileURL(configPath).href\n )\n const config = pkgManagerConfigSchema.parse(configModule.default)\n\n return {\n ...config,\n hashStorePath: config.hashStorePath ?? DEFAULT_HASH_STORE_PATH,\n requireMajorConfirmation: config.requireMajorConfirmation ?? true,\n }\n}\n\nexport function generateConfigFile(\n config: PkgManagerConfig,\n cwd: string = process.cwd()\n): void {\n const configPath = getConfigPath(cwd)\n\n const lines: string[] = [\n `import { defineConfig } from '@ls-stack/pkg-manager';`,\n '',\n 'export default defineConfig({',\n ]\n\n if (config.requireMajorConfirmation !== undefined) {\n lines.push(\n ` requireMajorConfirmation: ${config.requireMajorConfirmation},`\n )\n }\n\n if (config.prePublish && config.prePublish.length > 0) {\n lines.push(' prePublish: [')\n for (const script of config.prePublish) {\n lines.push(\n ` { command: '${script.command}', label: '${script.label}' },`\n )\n }\n lines.push(' ],')\n }\n\n if (config.monorepo) {\n lines.push(' monorepo: {')\n lines.push(' packages: [')\n for (const pkg of config.monorepo.packages) {\n if (pkg.dependsOn && pkg.dependsOn.length > 0) {\n const depsStr = pkg.dependsOn.map((d) => `'${d}'`).join(', ')\n lines.push(\n ` { name: '${pkg.name}', path: '${pkg.path}', dependsOn: [${depsStr}] },`\n )\n } else {\n lines.push(` { name: '${pkg.name}', path: '${pkg.path}' },`)\n }\n }\n lines.push(' ],')\n lines.push(' },')\n }\n\n lines.push('});')\n lines.push('')\n\n writeFileSync(configPath, lines.join('\\n'))\n}\n\nexport function getHashStorePath(config: PkgManagerConfig): string {\n return config.hashStorePath ?? DEFAULT_HASH_STORE_PATH\n}\n"],"mappings":";;;;;;AAKA,MAAM,kBAAkB;AACxB,MAAM,0BAA0B;AAEhC,MAAM,yBAAyB,EAAE,OAAO;CACtC,SAAS,EAAE,QAAQ;CACnB,OAAO,EAAE,QAAQ;CAClB,CAAC;AAEF,MAAM,wBAAwB,EAAE,OAAO;CACrC,MAAM,EAAE,QAAQ;CAChB,MAAM,EAAE,QAAQ;CAChB,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU;CAC1C,CAAC;AAEF,MAAM,yBAAyB,EAAE,OAAO;CACtC,YAAY,EAAE,MAAM,uBAAuB,CAAC,UAAU;CACtD,UAAU,EACP,OAAO,EACN,UAAU,EAAE,MAAM,sBAAsB,EACzC,CAAC,CACD,UAAU;CACb,eAAe,EAAE,QAAQ,CAAC,UAAU;CACpC,0BAA0B,EAAE,SAAS,CAAC,UAAU;CACjD,CAAC;;;;;;;;;;;;AAoDF,SAAgB,aAAa,QAA4C;AACvE,QAAO;;AAGT,SAAgB,cAAc,MAAc,QAAQ,KAAK,EAAU;AACjE,QAAO,KAAK,KAAK,gBAAgB;;AAGnC,SAAgB,aAAa,MAAc,QAAQ,KAAK,EAAW;AACjE,QAAO,WAAW,cAAc,IAAI,CAAC;;AAGvC,MAAM,gBAAkC;CACtC,eAAe;CACf,0BAA0B;CAC3B;AAED,eAAsB,WACpB,MAAc,QAAQ,KAAK,EACA;CAC3B,MAAM,aAAa,cAAc,IAAI;AAErC,KAAI,CAAC,WAAW,WAAW,CAAE,QAAO;CAEpC,MAAM,eAAqC,MAAM,OAC/C,cAAc,WAAW,CAAC;CAE5B,MAAM,SAAS,uBAAuB,MAAM,aAAa,QAAQ;AAEjE,QAAO;EACL,GAAG;EACH,eAAe,OAAO,iBAAiB;EACvC,0BAA0B,OAAO,4BAA4B;EAC9D;;AAGH,SAAgB,mBACd,QACA,MAAc,QAAQ,KAAK,EACrB;CACN,MAAM,aAAa,cAAc,IAAI;CAErC,MAAM,QAAkB;EACtB;EACA;EACA;EACD;AAED,KAAI,OAAO,6BAA6B,OACtC,OAAM,KACJ,+BAA+B,OAAO,yBAAyB,GAChE;AAGH,KAAI,OAAO,cAAc,OAAO,WAAW,SAAS,GAAG;AACrD,QAAM,KAAK,kBAAkB;AAC7B,OAAK,MAAM,UAAU,OAAO,WAC1B,OAAM,KACJ,mBAAmB,OAAO,QAAQ,aAAa,OAAO,MAAM,MAC7D;AAEH,QAAM,KAAK,OAAO;;AAGpB,KAAI,OAAO,UAAU;AACnB,QAAM,KAAK,gBAAgB;AAC3B,QAAM,KAAK,kBAAkB;AAC7B,OAAK,MAAM,OAAO,OAAO,SAAS,SAChC,KAAI,IAAI,aAAa,IAAI,UAAU,SAAS,GAAG;GAC7C,MAAM,UAAU,IAAI,UAAU,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK;AAC7D,SAAM,KACJ,kBAAkB,IAAI,KAAK,YAAY,IAAI,KAAK,iBAAiB,QAAQ,MAC1E;QAED,OAAM,KAAK,kBAAkB,IAAI,KAAK,YAAY,IAAI,KAAK,MAAM;AAGrE,QAAM,KAAK,SAAS;AACpB,QAAM,KAAK,OAAO;;AAGpB,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;AAEd,eAAc,YAAY,MAAM,KAAK,KAAK,CAAC;;AAG7C,SAAgB,iBAAiB,QAAkC;AACjE,QAAO,OAAO,iBAAiB"}
|