auklet 0.0.19 → 0.0.21
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/LICENSE +21 -0
- package/README.md +183 -393
- package/bin/entry.mjs +5 -0
- package/dist/build/bundleConfig.js +3 -2
- package/dist/build/cliOverrides.d.ts +22 -0
- package/dist/build/cliOverrides.js +22 -0
- package/dist/build/moduleConfig.js +1 -1
- package/dist/build/runTsdown.d.ts +2 -0
- package/dist/build/runTsdown.js +4 -3
- package/dist/build/tsdown/common.d.ts +2 -2
- package/dist/build/tsdown/context.d.ts +2 -1
- package/dist/build/tsdown/context.js +2 -1
- package/dist/build/tsdown/define.js +3 -2
- package/dist/build/tsdown/dependencies.js +3 -1
- package/dist/build/tsdown/entries.d.ts +2 -2
- package/dist/build/tsdown/entries.js +10 -10
- package/dist/build/tsdown/types.d.ts +1 -0
- package/dist/cli/build.d.ts +5 -0
- package/dist/cli/build.js +30 -0
- package/dist/cli/buildArgs.d.ts +8 -0
- package/dist/cli/buildArgs.js +114 -0
- package/dist/cli/buildCss.d.ts +12 -0
- package/dist/cli/buildCss.js +53 -0
- package/dist/cli/dev.d.ts +1 -0
- package/dist/cli/dev.js +39 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +95 -0
- package/dist/cli/publish.d.ts +2 -0
- package/dist/cli/publish.js +9 -0
- package/dist/config.d.ts +3 -1
- package/dist/config.js +7 -1
- package/dist/configLoader.d.ts +1 -0
- package/dist/configLoader.js +42 -61
- package/dist/css/production/buildReporter.d.ts +3 -0
- package/dist/css/production/buildReporter.js +19 -0
- package/dist/css/production/builder.d.ts +8 -3
- package/dist/css/production/builder.js +9 -13
- package/dist/css/vite/hmr.js +10 -8
- package/dist/css/vite/moduleGraph/graph.js +2 -3
- package/dist/css/vite/moduleGraph/packageSource/monorepo.d.ts +5 -1
- package/dist/css/vite/moduleGraph/packageSource/monorepo.js +42 -33
- package/dist/css/vite/moduleGraph/packageSource/singlePackage.js +3 -3
- package/dist/css/vite/moduleGraph/requestCache.d.ts +4 -4
- package/dist/css/vite/moduleGraph/requestCache.js +8 -4
- package/dist/css/vite/moduleGraph/styleCodeFactory.js +4 -4
- package/dist/css/vite/moduleGraph/types.d.ts +0 -1
- package/dist/css/watch/watcher.d.ts +0 -1
- package/dist/css/watch/watcher.js +9 -15
- package/dist/index.d.ts +6 -7
- package/dist/index.js +5 -5
- package/dist/logger.d.ts +5 -0
- package/dist/logger.js +14 -0
- package/dist/publish/api/gitApi.d.ts +7 -0
- package/dist/publish/api/gitApi.js +55 -0
- package/dist/publish/api/packageJsonApi.d.ts +7 -0
- package/dist/publish/api/packageJsonApi.js +35 -0
- package/dist/publish/api/pnpmApi.d.ts +9 -0
- package/dist/publish/api/pnpmApi.js +85 -0
- package/dist/publish/api/pnpmPublishApi.d.ts +4 -0
- package/dist/publish/api/pnpmPublishApi.js +7 -0
- package/dist/publish/api/publishArgs.d.ts +2 -0
- package/dist/publish/api/publishArgs.js +25 -0
- package/dist/publish/api/publishHookApi.d.ts +10 -0
- package/dist/publish/api/publishHookApi.js +53 -0
- package/dist/publish/cli.d.ts +2 -0
- package/dist/publish/cli.js +95 -0
- package/dist/publish/ownerRunner.d.ts +6 -0
- package/dist/publish/ownerRunner.js +22 -0
- package/dist/publish/publishRunner.d.ts +16 -0
- package/dist/publish/publishRunner.js +108 -0
- package/dist/publish/runner/packageBuilder.d.ts +4 -0
- package/dist/publish/runner/packageBuilder.js +16 -0
- package/dist/publish/runner/packagePublisher.d.ts +7 -0
- package/dist/publish/runner/packagePublisher.js +21 -0
- package/dist/publish/runner/publishFailureReporter.d.ts +3 -0
- package/dist/publish/runner/publishFailureReporter.js +14 -0
- package/dist/publish/runner/publishOutputFormatter.d.ts +2 -0
- package/dist/publish/runner/publishOutputFormatter.js +83 -0
- package/dist/publish/runner/publishPreflight.d.ts +8 -0
- package/dist/publish/runner/publishPreflight.js +26 -0
- package/dist/publish/runner/publishSummaryReporter.d.ts +10 -0
- package/dist/publish/runner/publishSummaryReporter.js +81 -0
- package/dist/publish/runner/publishTargetError.d.ts +9 -0
- package/dist/publish/runner/publishTargetError.js +14 -0
- package/dist/publish/runner/releaseGitController.d.ts +10 -0
- package/dist/publish/runner/releaseGitController.js +41 -0
- package/dist/publish/runner/versionWriter.d.ts +13 -0
- package/dist/publish/runner/versionWriter.js +78 -0
- package/dist/publish/targetResolver.d.ts +7 -0
- package/dist/publish/targetResolver.js +195 -0
- package/dist/publish/types.d.ts +70 -0
- package/dist/publish/types.js +0 -0
- package/dist/publish/version.d.ts +5 -0
- package/dist/publish/version.js +55 -0
- package/dist/types.d.ts +8 -7
- package/dist/workspace/packages.d.ts +9 -0
- package/dist/workspace/packages.js +62 -0
- package/dist/workspace/root.d.ts +1 -0
- package/dist/workspace/root.js +14 -0
- package/package.json +15 -7
- package/bin/entry.cjs +0 -163
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createAukletLogger, createScopedAukletLogger } from '#auklet/logger';
|
|
2
|
+
import { runPublishHook } from '#auklet/publish/api/publishHookApi';
|
|
3
|
+
import { runPackageBuilds, validateBuildScript, } from '#auklet/publish/runner/packageBuilder';
|
|
4
|
+
import { formatPublishOutputs } from '#auklet/publish/runner/publishOutputFormatter';
|
|
5
|
+
import { resolvePublishPlan } from '#auklet/publish/targetResolver';
|
|
6
|
+
import { PackagePublisher } from '#auklet/publish/runner/packagePublisher';
|
|
7
|
+
import { reportPublishFailure } from '#auklet/publish/runner/publishFailureReporter';
|
|
8
|
+
import { reportPublishSummary } from '#auklet/publish/runner/publishSummaryReporter';
|
|
9
|
+
import { PublishPreflight } from '#auklet/publish/runner/publishPreflight';
|
|
10
|
+
import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
|
|
11
|
+
import { ReleaseGitController } from '#auklet/publish/runner/releaseGitController';
|
|
12
|
+
import { VersionWriter } from '#auklet/publish/runner/versionWriter';
|
|
13
|
+
export class PublishRunner {
|
|
14
|
+
git;
|
|
15
|
+
publisher;
|
|
16
|
+
preflight;
|
|
17
|
+
versions;
|
|
18
|
+
logger;
|
|
19
|
+
summaryLogger;
|
|
20
|
+
options;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.logger = createScopedAukletLogger('publish');
|
|
24
|
+
this.summaryLogger = createAukletLogger();
|
|
25
|
+
this.git = new ReleaseGitController(this.options, this.logger);
|
|
26
|
+
this.publisher = new PackagePublisher(this.options);
|
|
27
|
+
this.preflight = new PublishPreflight(this.options);
|
|
28
|
+
this.versions = new VersionWriter(this.options, this.logger);
|
|
29
|
+
}
|
|
30
|
+
async run() {
|
|
31
|
+
const plan = await this.preparePlan();
|
|
32
|
+
let failureHookEnabled = false;
|
|
33
|
+
try {
|
|
34
|
+
await runPublishHook({ status: 'beforeBuild', plan });
|
|
35
|
+
failureHookEnabled = true;
|
|
36
|
+
this.versions.writeBeforeBuild(plan);
|
|
37
|
+
await runPackageBuilds(plan.targets, this.logger);
|
|
38
|
+
await runPublishHook({ status: 'afterBuild', plan });
|
|
39
|
+
await formatPublishOutputs(plan.targets, this.options.format);
|
|
40
|
+
await runPublishHook({ status: 'beforePublish', plan });
|
|
41
|
+
await this.publishWithPlan(plan);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (!failureHookEnabled) {
|
|
45
|
+
reportPublishSummary(this.summaryLogger, {
|
|
46
|
+
plan,
|
|
47
|
+
status: 'failure',
|
|
48
|
+
error,
|
|
49
|
+
});
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
await this.handleFailure(plan, error);
|
|
53
|
+
}
|
|
54
|
+
await this.runAfterPublishSuccess(plan);
|
|
55
|
+
}
|
|
56
|
+
async preparePlan() {
|
|
57
|
+
const plan = await resolvePublishPlan(this.options, this.logger);
|
|
58
|
+
validateBuildScript(plan.targets);
|
|
59
|
+
await this.git.checkBeforePublish(plan);
|
|
60
|
+
this.versions.logDryRunPlan(plan);
|
|
61
|
+
return plan;
|
|
62
|
+
}
|
|
63
|
+
async publishWithPlan(plan) {
|
|
64
|
+
if (plan.dryRun) {
|
|
65
|
+
await this.preflight.run(plan);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await this.preflight.run(plan);
|
|
69
|
+
await this.git.commitAndTag(plan);
|
|
70
|
+
await this.publisher.run(plan);
|
|
71
|
+
}
|
|
72
|
+
async handleFailure(plan, error) {
|
|
73
|
+
const failedTarget = error instanceof PublishTargetError ? error.target : undefined;
|
|
74
|
+
try {
|
|
75
|
+
await runPublishHook({
|
|
76
|
+
status: 'afterPublish',
|
|
77
|
+
plan,
|
|
78
|
+
result: 'failure',
|
|
79
|
+
failedTarget,
|
|
80
|
+
error: error instanceof PublishTargetError ? error.originalError : error,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (hookError) {
|
|
84
|
+
this.logger.error?.(hookError);
|
|
85
|
+
}
|
|
86
|
+
if (error instanceof PublishTargetError) {
|
|
87
|
+
reportPublishFailure(error, plan.version, this.logger);
|
|
88
|
+
}
|
|
89
|
+
reportPublishSummary(this.summaryLogger, {
|
|
90
|
+
plan,
|
|
91
|
+
status: 'failure',
|
|
92
|
+
error,
|
|
93
|
+
});
|
|
94
|
+
this.versions.logWrittenVersionFailure(plan);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
async runAfterPublishSuccess(plan) {
|
|
98
|
+
await runPublishHook({
|
|
99
|
+
status: 'afterPublish',
|
|
100
|
+
plan,
|
|
101
|
+
result: 'success',
|
|
102
|
+
});
|
|
103
|
+
reportPublishSummary(this.summaryLogger, {
|
|
104
|
+
plan,
|
|
105
|
+
status: 'success',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PublishTarget } from '#auklet/publish/types';
|
|
2
|
+
import type { AukletLogger } from '#auklet/logger';
|
|
3
|
+
export declare function validateBuildScript(targets: Array<PublishTarget>): void;
|
|
4
|
+
export declare function runPackageBuilds(targets: Array<PublishTarget>, logger: AukletLogger): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isString } from 'aidly';
|
|
2
|
+
import { runPnpmBuild } from '#auklet/publish/api/pnpmApi';
|
|
3
|
+
export function validateBuildScript(targets) {
|
|
4
|
+
for (const target of targets) {
|
|
5
|
+
const buildScript = target.packageJson.scripts?.build;
|
|
6
|
+
if (!isString(buildScript) || !buildScript) {
|
|
7
|
+
throw new Error(`[auklet:publish] package ${target.packageName} must define package.json#scripts.build before publishing.`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export async function runPackageBuilds(targets, logger) {
|
|
12
|
+
for (const target of targets) {
|
|
13
|
+
logger.step('build ', logger.package(target.packageName));
|
|
14
|
+
await runPnpmBuild(target.packageRoot);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PnpmPublishApi } from '#auklet/publish/api/pnpmPublishApi';
|
|
2
|
+
import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
|
|
3
|
+
export class PackagePublisher {
|
|
4
|
+
options;
|
|
5
|
+
pnpm = new PnpmPublishApi();
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
async run(plan) {
|
|
10
|
+
const publishedTargets = [];
|
|
11
|
+
for (const target of plan.targets) {
|
|
12
|
+
try {
|
|
13
|
+
await this.pnpm.publish(target, this.options);
|
|
14
|
+
publishedTargets.push(target);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw new PublishTargetError(target, 'publish', error, publishedTargets);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function reportPublishFailure(error, version, logger) {
|
|
2
|
+
if (error.phase === 'publish' && error.publishedTargets.length) {
|
|
3
|
+
logger.error('partial publish detected');
|
|
4
|
+
logger.error('published packages:');
|
|
5
|
+
for (const target of error.publishedTargets) {
|
|
6
|
+
logger.error(formatPublishedTarget(logger, target.packageName, version));
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
logger.error('failed package:');
|
|
10
|
+
logger.error(formatPublishedTarget(logger, error.target.packageName, version));
|
|
11
|
+
}
|
|
12
|
+
const formatPublishedTarget = (logger, packageName, version) => {
|
|
13
|
+
return ['- ', logger.package(packageName), '@', logger.version(version)];
|
|
14
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import prettier from 'prettier';
|
|
4
|
+
const supportedExtensions = new Set([
|
|
5
|
+
'.js',
|
|
6
|
+
'.ts',
|
|
7
|
+
'.tsx',
|
|
8
|
+
'.css',
|
|
9
|
+
'.json',
|
|
10
|
+
'.yaml',
|
|
11
|
+
'.yml',
|
|
12
|
+
]);
|
|
13
|
+
export async function formatPublishOutputs(targets, enabled) {
|
|
14
|
+
if (!enabled)
|
|
15
|
+
return;
|
|
16
|
+
for (const target of targets) {
|
|
17
|
+
const files = collectPublishFiles(target);
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
await formatFile(file);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const collectPublishFiles = (target) => {
|
|
24
|
+
const patterns = target.packageJson.files ?? [];
|
|
25
|
+
const includes = patterns.filter((item) => !item.startsWith('!'));
|
|
26
|
+
const excludes = patterns
|
|
27
|
+
.filter((item) => item.startsWith('!'))
|
|
28
|
+
.map((item) => item.slice(1));
|
|
29
|
+
const files = new Set();
|
|
30
|
+
for (const include of includes) {
|
|
31
|
+
const absolutePath = path.resolve(target.packageRoot, include);
|
|
32
|
+
if (!fs.existsSync(absolutePath))
|
|
33
|
+
continue;
|
|
34
|
+
for (const file of walkFiles(absolutePath)) {
|
|
35
|
+
if (isExcluded(target.packageRoot, file, excludes))
|
|
36
|
+
continue;
|
|
37
|
+
if (!isSupportedStyleFile(file))
|
|
38
|
+
continue;
|
|
39
|
+
files.add(file);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return [...files].sort();
|
|
43
|
+
};
|
|
44
|
+
const walkFiles = (absolutePath) => {
|
|
45
|
+
const stat = fs.statSync(absolutePath);
|
|
46
|
+
if (stat.isFile())
|
|
47
|
+
return [absolutePath];
|
|
48
|
+
if (!stat.isDirectory())
|
|
49
|
+
return [];
|
|
50
|
+
const files = [];
|
|
51
|
+
for (const entry of fs.readdirSync(absolutePath)) {
|
|
52
|
+
files.push(...walkFiles(path.join(absolutePath, entry)));
|
|
53
|
+
}
|
|
54
|
+
return files;
|
|
55
|
+
};
|
|
56
|
+
const isExcluded = (packageRoot, file, excludes) => {
|
|
57
|
+
const relativePath = path
|
|
58
|
+
.relative(packageRoot, file)
|
|
59
|
+
.split(path.sep)
|
|
60
|
+
.join('/');
|
|
61
|
+
return excludes.some((exclude) => {
|
|
62
|
+
const normalized = exclude.replace(/\\/g, '/').replace(/\/$/, '');
|
|
63
|
+
return (relativePath === normalized || relativePath.startsWith(`${normalized}/`));
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
const isSupportedStyleFile = (file) => {
|
|
67
|
+
if (file.endsWith('.d.ts'))
|
|
68
|
+
return true;
|
|
69
|
+
return supportedExtensions.has(path.extname(file));
|
|
70
|
+
};
|
|
71
|
+
const formatFile = async (file) => {
|
|
72
|
+
const source = fs.readFileSync(file, 'utf8');
|
|
73
|
+
let formatted;
|
|
74
|
+
try {
|
|
75
|
+
formatted = await prettier.format(source, { filepath: file });
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (formatted !== source) {
|
|
81
|
+
fs.writeFileSync(file, formatted);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
|
|
2
|
+
export declare class PublishPreflight {
|
|
3
|
+
private readonly options;
|
|
4
|
+
private readonly pnpm;
|
|
5
|
+
constructor(options: PublishOptions);
|
|
6
|
+
run(plan: PublishPlan): Promise<void>;
|
|
7
|
+
private verifyPnpmPublishDryRun;
|
|
8
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { PnpmPublishApi } from '#auklet/publish/api/pnpmPublishApi';
|
|
2
|
+
import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
|
|
3
|
+
export class PublishPreflight {
|
|
4
|
+
options;
|
|
5
|
+
pnpm = new PnpmPublishApi();
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
async run(plan) {
|
|
10
|
+
await this.verifyPnpmPublishDryRun(plan);
|
|
11
|
+
}
|
|
12
|
+
async verifyPnpmPublishDryRun(plan) {
|
|
13
|
+
const options = {
|
|
14
|
+
...this.options,
|
|
15
|
+
dryRun: true,
|
|
16
|
+
};
|
|
17
|
+
for (const target of plan.targets) {
|
|
18
|
+
try {
|
|
19
|
+
await this.pnpm.publish(target, options);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new PublishTargetError(target, 'preflight', error, []);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AukletLogger } from '#auklet/logger';
|
|
2
|
+
import type { PublishPlan } from '#auklet/publish/types';
|
|
3
|
+
type PublishSummaryStatus = 'success' | 'failure';
|
|
4
|
+
type PublishSummaryOptions = {
|
|
5
|
+
plan: PublishPlan;
|
|
6
|
+
status: PublishSummaryStatus;
|
|
7
|
+
error?: unknown;
|
|
8
|
+
};
|
|
9
|
+
export declare function reportPublishSummary(logger: AukletLogger, options: PublishSummaryOptions): void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PublishTargetError } from '#auklet/publish/runner/publishTargetError';
|
|
2
|
+
export function reportPublishSummary(logger, options) {
|
|
3
|
+
const publishError = options.error instanceof PublishTargetError ? options.error : undefined;
|
|
4
|
+
const failedTarget = publishError?.target;
|
|
5
|
+
const publishedTargets = publishError?.publishedTargets ?? [];
|
|
6
|
+
const publishedTargetRoots = new Set(publishedTargets.map((target) => getTargetKey(target)));
|
|
7
|
+
const publishedCount = options.status === 'success' && !options.plan.dryRun
|
|
8
|
+
? options.plan.targets.length
|
|
9
|
+
: publishedTargets.length;
|
|
10
|
+
logger.newline();
|
|
11
|
+
logger.raw(logger.colors.gray('-'.repeat(56)));
|
|
12
|
+
logger.newline();
|
|
13
|
+
logger.result({
|
|
14
|
+
title: logger.colors.bold(getSummaryTitle(options.status, options.plan)),
|
|
15
|
+
status: options.status === 'success' ? 'success' : 'error',
|
|
16
|
+
body: getSummaryBody(options.status, options.plan, failedTarget),
|
|
17
|
+
details: {
|
|
18
|
+
mode: options.plan.dryRun ? 'dry-run' : 'publish',
|
|
19
|
+
packages: String(options.plan.targets.length),
|
|
20
|
+
version: logger.version(options.plan.version),
|
|
21
|
+
published: String(publishedCount),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
logger.tasks({
|
|
25
|
+
tasks: getVersionChangeTasks(logger, {
|
|
26
|
+
targets: options.plan.targets,
|
|
27
|
+
status: options.status,
|
|
28
|
+
dryRun: options.plan.dryRun,
|
|
29
|
+
failedTarget,
|
|
30
|
+
publishedTargetRoots,
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
logger.newline();
|
|
34
|
+
}
|
|
35
|
+
const getSummaryTitle = (status, plan) => {
|
|
36
|
+
if (status === 'failure')
|
|
37
|
+
return 'Publish failed';
|
|
38
|
+
return plan.dryRun ? 'Publish dry-run complete' : 'Publish complete';
|
|
39
|
+
};
|
|
40
|
+
const getSummaryBody = (status, plan, failedTarget) => {
|
|
41
|
+
if (status === 'success') {
|
|
42
|
+
return [
|
|
43
|
+
plan.dryRun
|
|
44
|
+
? 'Preflight completed without publishing packages.'
|
|
45
|
+
: 'All selected packages were published.',
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
if (failedTarget) {
|
|
49
|
+
return [['Failed at ', failedTarget.packageName, '. Check logs above.']];
|
|
50
|
+
}
|
|
51
|
+
return ['Publish stopped before package publishing completed.'];
|
|
52
|
+
};
|
|
53
|
+
const getVersionChangeTasks = (logger, options) => {
|
|
54
|
+
return options.targets.map((target) => ({
|
|
55
|
+
title: [
|
|
56
|
+
logger.package(target.packageName),
|
|
57
|
+
' ',
|
|
58
|
+
...formatVersionChange(logger, target.version, target.publishVersion),
|
|
59
|
+
],
|
|
60
|
+
status: getVersionChangeTaskStatus(target, options),
|
|
61
|
+
}));
|
|
62
|
+
};
|
|
63
|
+
const getVersionChangeTaskStatus = (target, options) => {
|
|
64
|
+
if (options.dryRun)
|
|
65
|
+
return 'skipped';
|
|
66
|
+
if (options.status === 'success')
|
|
67
|
+
return 'success';
|
|
68
|
+
if (options.failedTarget &&
|
|
69
|
+
getTargetKey(target) === getTargetKey(options.failedTarget)) {
|
|
70
|
+
return 'error';
|
|
71
|
+
}
|
|
72
|
+
if (options.publishedTargetRoots.has(getTargetKey(target)))
|
|
73
|
+
return 'success';
|
|
74
|
+
return 'skipped';
|
|
75
|
+
};
|
|
76
|
+
const getTargetKey = (target) => {
|
|
77
|
+
return `${target.packageRoot}:${target.packageName}`;
|
|
78
|
+
};
|
|
79
|
+
const formatVersionChange = (logger, from, to) => {
|
|
80
|
+
return [logger.version(from), logger.colors.gray(' -> '), logger.version(to)];
|
|
81
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PublishTarget } from '#auklet/publish/types';
|
|
2
|
+
export type PublishPhase = 'preflight' | 'publish';
|
|
3
|
+
export declare class PublishTargetError extends Error {
|
|
4
|
+
readonly target: PublishTarget;
|
|
5
|
+
readonly phase: PublishPhase;
|
|
6
|
+
readonly originalError: unknown;
|
|
7
|
+
readonly publishedTargets: Array<PublishTarget>;
|
|
8
|
+
constructor(target: PublishTarget, phase: PublishPhase, originalError: unknown, publishedTargets: Array<PublishTarget>);
|
|
9
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export class PublishTargetError extends Error {
|
|
3
|
+
target;
|
|
4
|
+
phase;
|
|
5
|
+
originalError;
|
|
6
|
+
publishedTargets;
|
|
7
|
+
constructor(target, phase, originalError, publishedTargets) {
|
|
8
|
+
super(`[auklet:publish] ${phase} failed for ${target.packageName} at ${path.relative(process.cwd(), target.packageRoot) || target.packageRoot}.`);
|
|
9
|
+
this.target = target;
|
|
10
|
+
this.phase = phase;
|
|
11
|
+
this.originalError = originalError;
|
|
12
|
+
this.publishedTargets = publishedTargets;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
|
|
2
|
+
import type { AukletLogger } from '#auklet/logger';
|
|
3
|
+
export declare class ReleaseGitController {
|
|
4
|
+
private readonly options;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(options: PublishOptions, logger: AukletLogger);
|
|
7
|
+
checkBeforePublish(plan: PublishPlan): Promise<void>;
|
|
8
|
+
commitAndTag(plan: PublishPlan): Promise<void>;
|
|
9
|
+
private warnOnce;
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { commitRelease, createVersionTag, ensureGitClean, hasGitChanges, isGitRepository, } from '#auklet/publish/api/gitApi';
|
|
2
|
+
export class ReleaseGitController {
|
|
3
|
+
options;
|
|
4
|
+
logger;
|
|
5
|
+
constructor(options, logger) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
this.logger = logger;
|
|
8
|
+
}
|
|
9
|
+
async checkBeforePublish(plan) {
|
|
10
|
+
const git = await isGitRepository(plan.root);
|
|
11
|
+
if (plan.dryRun || !git)
|
|
12
|
+
return;
|
|
13
|
+
if (this.options.allowDirty) {
|
|
14
|
+
this.warnOnce('--allow-dirty enabled, skipping git clean check, commit, and tag.');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
await ensureGitClean(plan.root);
|
|
18
|
+
}
|
|
19
|
+
async commitAndTag(plan) {
|
|
20
|
+
const git = await isGitRepository(plan.root);
|
|
21
|
+
if (git && this.options.allowDirty) {
|
|
22
|
+
this.warnOnce('--allow-dirty enabled, skipping git commit and tag.');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!git) {
|
|
26
|
+
this.warnOnce('git repository not found, skipping commit and tag.');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const changed = await hasGitChanges(plan.root);
|
|
30
|
+
if (changed) {
|
|
31
|
+
if (!this.options.version) {
|
|
32
|
+
throw new Error('[auklet:publish] build or format changed files. Commit changes before publishing without --version.');
|
|
33
|
+
}
|
|
34
|
+
await commitRelease(plan.root, plan.version);
|
|
35
|
+
}
|
|
36
|
+
await createVersionTag(plan.root, plan.version, this.logger);
|
|
37
|
+
}
|
|
38
|
+
warnOnce(content) {
|
|
39
|
+
this.logger.warnOnce(content);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PublishOptions, PublishPlan } from '#auklet/publish/types';
|
|
2
|
+
import type { AukletLogger } from '#auklet/logger';
|
|
3
|
+
export declare class VersionWriter {
|
|
4
|
+
private readonly options;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor(options: PublishOptions, logger: AukletLogger);
|
|
7
|
+
writeBeforeBuild(plan: PublishPlan): void;
|
|
8
|
+
logDryRunPlan(plan: PublishPlan): void;
|
|
9
|
+
logWrittenVersionFailure(plan: PublishPlan): void;
|
|
10
|
+
private writeVersions;
|
|
11
|
+
private formatPackage;
|
|
12
|
+
private formatVersionChange;
|
|
13
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { readPackageJson, writePackageJson, } from '#auklet/publish/api/packageJsonApi';
|
|
2
|
+
export class VersionWriter {
|
|
3
|
+
options;
|
|
4
|
+
logger;
|
|
5
|
+
constructor(options, logger) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
this.logger = logger;
|
|
8
|
+
}
|
|
9
|
+
writeBeforeBuild(plan) {
|
|
10
|
+
if (!plan.dryRun && this.options.version) {
|
|
11
|
+
this.writeVersions(plan);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
logDryRunPlan(plan) {
|
|
15
|
+
if (!plan.dryRun || !this.options.version)
|
|
16
|
+
return;
|
|
17
|
+
const logger = this.logger;
|
|
18
|
+
logger.info('dry-run mode: package.json files will not be changed');
|
|
19
|
+
if (plan.workspaceMode === 'monorepo') {
|
|
20
|
+
const rootPackageJson = readPackageJson(plan.root);
|
|
21
|
+
logger.summary({
|
|
22
|
+
title: 'Publish dry-run plan',
|
|
23
|
+
values: {
|
|
24
|
+
mode: plan.workspaceMode,
|
|
25
|
+
sharedVersion: this.formatVersionChange(rootPackageJson.version, plan.version),
|
|
26
|
+
targets: plan.targets.length,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
for (const target of plan.targets) {
|
|
30
|
+
logger.info('planned package ', this.formatPackage(target.packageName), ': ', ...this.formatVersionChange(target.version, target.publishVersion));
|
|
31
|
+
}
|
|
32
|
+
logger.info('builds will still read each package.json#version');
|
|
33
|
+
logger.info('pnpm publish --dry-run will still read each package.json#version');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const [target] = plan.targets;
|
|
37
|
+
if (target) {
|
|
38
|
+
logger.summary({
|
|
39
|
+
title: 'Publish dry-run plan',
|
|
40
|
+
values: {
|
|
41
|
+
package: this.formatPackage(target.packageName),
|
|
42
|
+
version: this.formatVersionChange(target.version, target.publishVersion),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
logger.info(`build will still read package.json#version: ${target.version}`);
|
|
46
|
+
logger.info(`pnpm publish --dry-run will still read package.json#version: ${target.version}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
logWrittenVersionFailure(plan) {
|
|
50
|
+
if (!plan.dryRun && this.options.version) {
|
|
51
|
+
this.logger.error('package.json versions may have been written. Auklet will not roll them back; check publish output before retrying.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
writeVersions(plan) {
|
|
55
|
+
const packageRoots = new Set([
|
|
56
|
+
plan.root,
|
|
57
|
+
...plan.targets.map((target) => target.packageRoot),
|
|
58
|
+
]);
|
|
59
|
+
for (const packageRoot of packageRoots) {
|
|
60
|
+
const packageJson = readPackageJson(packageRoot);
|
|
61
|
+
const packageName = plan.targets.find((target) => target.packageRoot === packageRoot)
|
|
62
|
+
?.packageName ?? (packageRoot === plan.root ? 'root' : packageRoot);
|
|
63
|
+
if (packageJson.version !== plan.version) {
|
|
64
|
+
this.logger.info('writing version ', this.formatPackage(packageName), ': ', ...this.formatVersionChange(packageJson.version, plan.version));
|
|
65
|
+
}
|
|
66
|
+
packageJson.version = plan.version;
|
|
67
|
+
writePackageJson(packageRoot, packageJson);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
formatPackage(packageName) {
|
|
71
|
+
return this.logger.package(packageName);
|
|
72
|
+
}
|
|
73
|
+
formatVersionChange(from, to) {
|
|
74
|
+
const logger = this.logger;
|
|
75
|
+
const fromVersion = String(from);
|
|
76
|
+
return [logger.version(fromVersion), ' -> ', logger.version(to)];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AukletLogger } from '#auklet/logger';
|
|
2
|
+
import type { OwnerOptions, PublishOptions, PublishPlan } from '#auklet/publish/types';
|
|
3
|
+
type ResolvePublishTargetsOptions = Pick<PublishOptions, 'cwd' | 'filters' | 'version' | 'dryRun'>;
|
|
4
|
+
type ResolveOwnerTargetsOptions = Pick<OwnerOptions, 'cwd' | 'filters' | 'packages'>;
|
|
5
|
+
export declare function resolvePublishPlan(options: ResolvePublishTargetsOptions, logger?: AukletLogger): Promise<PublishPlan>;
|
|
6
|
+
export declare function resolveOwnerPackageNames(options: ResolveOwnerTargetsOptions): Promise<string[]>;
|
|
7
|
+
export {};
|