@modulify/conventional-release 0.1.0 → 0.1.2

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/dist/plan.cjs ADDED
@@ -0,0 +1,260 @@
1
+ require("./_virtual/_rolldown/runtime.cjs");
2
+ require("./constants.cjs");
3
+ let node_path = require("node:path");
4
+ let _modulify_conventional_git = require("@modulify/conventional-git");
5
+ let _modulify_pkg = require("@modulify/pkg");
6
+ //#region src/plan.ts
7
+ function toScope(scope, cwd) {
8
+ return {
9
+ mode: scope.mode,
10
+ packages: scope.packages.map((pkg) => toScopePackage(pkg, cwd)),
11
+ affected: scope.affected.map((pkg) => toScopePackage(pkg, cwd)),
12
+ slices: scope.slices.map((slice) => toSlice(slice, cwd))
13
+ };
14
+ }
15
+ /** Discovers packages, affected scope, and ordered release slices without side effects. */
16
+ async function discover(runtime, options) {
17
+ const root = (0, _modulify_pkg.read)(runtime.cwd);
18
+ const packages = [];
19
+ await (0, _modulify_pkg.walk)([root], async (pkg) => {
20
+ packages.push(pkg);
21
+ });
22
+ const discovered = sortPackages(uniquePackages(applyWorkspaceFilters(packages, runtime.cwd, options.workspaces)), runtime.cwd);
23
+ const mode = options.mode ?? "sync";
24
+ const affectedPaths = mode === "hybrid" ? null : await detectAffectedPackages({
25
+ cwd: runtime.cwd,
26
+ root,
27
+ packages: discovered,
28
+ history: runtime.history,
29
+ range: {
30
+ fromTag: options.fromTag,
31
+ tagPrefix: options.tagPrefix
32
+ }
33
+ });
34
+ const affected = affectedPaths ? sortPackages(uniquePackages(discovered.filter((pkg) => affectedPaths.has(pkg.path))), runtime.cwd) : [];
35
+ const slices = mode === "hybrid" ? await createHybridSlices({
36
+ root,
37
+ packages: discovered,
38
+ cwd: runtime.cwd,
39
+ history: runtime.history,
40
+ fromTag: options.fromTag,
41
+ tagPrefix: options.tagPrefix,
42
+ partitions: options.partitions
43
+ }) : createSlices({
44
+ mode,
45
+ packages: discovered,
46
+ affected,
47
+ cwd: runtime.cwd,
48
+ fromTag: options.fromTag,
49
+ tagPrefix: options.tagPrefix
50
+ });
51
+ return {
52
+ mode,
53
+ packages: discovered,
54
+ affected: mode === "hybrid" ? sortPackages(uniquePackages(slices.flatMap((slice) => slice.packages)), runtime.cwd) : affected,
55
+ slices
56
+ };
57
+ }
58
+ function toScopePackage(pkg, cwd) {
59
+ return {
60
+ name: pkg.manifest.name ?? pkg.name,
61
+ version: pkg.manifest.version,
62
+ path: toPublicPath(pkg, cwd)
63
+ };
64
+ }
65
+ function toSlice(slice, cwd) {
66
+ return {
67
+ id: slice.id,
68
+ kind: slice.kind,
69
+ mode: slice.mode,
70
+ partition: slice.partition,
71
+ packages: slice.packages.map((pkg) => toScopePackage(pkg, cwd)),
72
+ range: slice.range
73
+ };
74
+ }
75
+ function uniquePackages(packages) {
76
+ const seen = /* @__PURE__ */ new Set();
77
+ return packages.filter((pkg) => {
78
+ if (seen.has(pkg.path)) return false;
79
+ seen.add(pkg.path);
80
+ return true;
81
+ });
82
+ }
83
+ function uniqueStrings(values) {
84
+ return [...new Set(values)];
85
+ }
86
+ function packageIdentity(pkg, cwd) {
87
+ const name = pkg.manifest.name ?? pkg.name;
88
+ if (name) return name;
89
+ const path = packagePath(pkg, cwd);
90
+ return path === "" || path === "." ? "root" : path;
91
+ }
92
+ function createSlices({ mode, packages, affected, cwd, fromTag, tagPrefix }) {
93
+ if (mode === "sync") return affected.length ? [{
94
+ id: "sync:default",
95
+ kind: "sync",
96
+ mode: "sync",
97
+ packages,
98
+ range: {
99
+ fromTag,
100
+ tagPrefix
101
+ }
102
+ }] : [];
103
+ return affected.map((pkg) => ({
104
+ id: `async:${packageIdentity(pkg, cwd)}`,
105
+ kind: "async",
106
+ mode: "async",
107
+ packages: [pkg],
108
+ range: {
109
+ fromTag,
110
+ tagPrefix
111
+ }
112
+ }));
113
+ }
114
+ async function createHybridSlices({ root, packages, cwd, history, fromTag, tagPrefix, partitions }) {
115
+ const partitionEntries = Object.entries(partitions ?? {}).sort(([a], [b]) => a.localeCompare(b));
116
+ const partitioned = [];
117
+ const usedPaths = /* @__PURE__ */ new Set();
118
+ for (const [partition, definition] of partitionEntries) {
119
+ const matched = sortPackages(packages.filter((pkg) => {
120
+ if (usedPaths.has(pkg.path)) return false;
121
+ return definition.workspaces.some((selector) => matchesPackageSelector(pkg, cwd, selector));
122
+ }), cwd);
123
+ for (const pkg of matched) usedPaths.add(pkg.path);
124
+ const affectedPaths = await detectAffectedPackages({
125
+ cwd,
126
+ root,
127
+ packages: matched,
128
+ history,
129
+ range: resolvePartitionRange({
130
+ fromTag,
131
+ tagPrefix,
132
+ partition: definition
133
+ })
134
+ });
135
+ const scoped = matched.filter((pkg) => affectedPaths.has(pkg.path));
136
+ if (!scoped.length) continue;
137
+ const resolvedRange = resolvePartitionRange({
138
+ fromTag,
139
+ tagPrefix,
140
+ partition: definition
141
+ });
142
+ if (definition.mode === "sync") {
143
+ partitioned.push({
144
+ id: `partition:${partition}`,
145
+ kind: "partition",
146
+ mode: "sync",
147
+ partition,
148
+ packages: scoped,
149
+ range: resolvedRange
150
+ });
151
+ continue;
152
+ }
153
+ partitioned.push(...scoped.map((pkg) => ({
154
+ id: `partition:${partition}:${packageIdentity(pkg, cwd)}`,
155
+ kind: "partition",
156
+ mode: "async",
157
+ partition,
158
+ packages: [pkg],
159
+ range: resolvedRange
160
+ })));
161
+ }
162
+ const fallbackCandidates = sortPackages(packages.filter((pkg) => !usedPaths.has(pkg.path)), cwd);
163
+ const fallbackPaths = await detectAffectedPackages({
164
+ cwd,
165
+ root,
166
+ packages: fallbackCandidates,
167
+ history,
168
+ range: {
169
+ fromTag,
170
+ tagPrefix
171
+ }
172
+ });
173
+ const fallback = fallbackCandidates.filter((pkg) => fallbackPaths.has(pkg.path)).map((pkg) => ({
174
+ id: `hybrid:${packageIdentity(pkg, cwd)}`,
175
+ kind: "async",
176
+ mode: "async",
177
+ packages: [pkg],
178
+ range: {
179
+ fromTag,
180
+ tagPrefix
181
+ }
182
+ }));
183
+ return [...partitioned, ...fallback];
184
+ }
185
+ function resolvePartitionRange({ fromTag, tagPrefix, partition }) {
186
+ return {
187
+ fromTag: partition.fromTag ?? fromTag,
188
+ tagPrefix: partition.tagPrefix ?? tagPrefix
189
+ };
190
+ }
191
+ async function detectAffectedPackages({ cwd, root, packages, history, range }) {
192
+ const touched = await readCommitRangePaths(history, range);
193
+ if (touched === null) return new Set(packages.map((pkg) => pkg.path));
194
+ if (!touched.length) return /* @__PURE__ */ new Set();
195
+ const normalizedRoot = normalizePath((0, node_path.relative)(cwd, root.path));
196
+ const children = packages.filter((pkg) => pkg.path !== root.path).map((pkg) => ({
197
+ packagePath: pkg.path,
198
+ relativePath: normalizePath((0, node_path.relative)(cwd, pkg.path))
199
+ })).sort((a, b) => b.relativePath.length - a.relativePath.length);
200
+ const affected = /* @__PURE__ */ new Set();
201
+ for (const path of touched.map(normalizePath)) {
202
+ if (!isPathInside(path, normalizedRoot)) continue;
203
+ const child = children.find((entry) => isPathInside(path, entry.relativePath));
204
+ affected.add(child?.packagePath ?? root.path);
205
+ }
206
+ return affected;
207
+ }
208
+ function applyWorkspaceFilters(packages, cwd, selector) {
209
+ if (!selector?.include?.length && !selector?.exclude?.length) return packages;
210
+ return packages.filter((pkg) => {
211
+ if (!(selector.include?.length ? selector.include.some((entry) => matchesPackageSelector(pkg, cwd, entry)) : true)) return false;
212
+ return !(selector.exclude?.some((entry) => matchesPackageSelector(pkg, cwd, entry)) ?? false);
213
+ });
214
+ }
215
+ function sortPackages(packages, cwd) {
216
+ return [...packages].sort((a, b) => packagePath(a, cwd).localeCompare(packagePath(b, cwd)));
217
+ }
218
+ function packagePath(pkg, cwd) {
219
+ return normalizePath((0, node_path.relative)(cwd, pkg.path));
220
+ }
221
+ function toPublicPath(pkg, cwd) {
222
+ return packagePath(pkg, cwd) || ".";
223
+ }
224
+ function matchesPackageSelector(pkg, cwd, selector) {
225
+ const name = pkg.manifest.name ?? pkg.name ?? "";
226
+ const path = packagePath(pkg, cwd);
227
+ return matchesGlob(name, selector) || matchesGlob(path, selector);
228
+ }
229
+ function matchesGlob(input, pattern) {
230
+ if (!pattern) return false;
231
+ if (pattern === "*") return true;
232
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "__DOUBLE_STAR__").replace(/\*/g, "[^/]*").replace(/__DOUBLE_STAR__/g, ".*");
233
+ return new RegExp(`^${escaped}$`).test(input);
234
+ }
235
+ async function readCommitRangePaths(history, range) {
236
+ try {
237
+ return (await history.traverse({
238
+ fromTag: range.fromTag,
239
+ tagPrefix: range.tagPrefix,
240
+ changeset: true,
241
+ traversers: [(0, _modulify_conventional_git.createChangesetTraverser)()]
242
+ })).results.get("changeset").paths;
243
+ } catch {
244
+ return null;
245
+ }
246
+ }
247
+ function normalizePath(path) {
248
+ return path.replace(/\\/g, "/");
249
+ }
250
+ function isPathInside(path, root) {
251
+ return !root || root === "." || root === path || path.startsWith(`${root}/`);
252
+ }
253
+ //#endregion
254
+ exports.discover = discover;
255
+ exports.packageIdentity = packageIdentity;
256
+ exports.toScope = toScope;
257
+ exports.toScopePackage = toScopePackage;
258
+ exports.toSlice = toSlice;
259
+ exports.uniquePackages = uniquePackages;
260
+ exports.uniqueStrings = uniqueStrings;
package/dist/plan.mjs ADDED
@@ -0,0 +1,253 @@
1
+ import "./constants.mjs";
2
+ import { relative } from "node:path";
3
+ import { createChangesetTraverser } from "@modulify/conventional-git";
4
+ import { read, walk } from "@modulify/pkg";
5
+ //#region src/plan.ts
6
+ function toScope(scope, cwd) {
7
+ return {
8
+ mode: scope.mode,
9
+ packages: scope.packages.map((pkg) => toScopePackage(pkg, cwd)),
10
+ affected: scope.affected.map((pkg) => toScopePackage(pkg, cwd)),
11
+ slices: scope.slices.map((slice) => toSlice(slice, cwd))
12
+ };
13
+ }
14
+ /** Discovers packages, affected scope, and ordered release slices without side effects. */
15
+ async function discover(runtime, options) {
16
+ const root = read(runtime.cwd);
17
+ const packages = [];
18
+ await walk([root], async (pkg) => {
19
+ packages.push(pkg);
20
+ });
21
+ const discovered = sortPackages(uniquePackages(applyWorkspaceFilters(packages, runtime.cwd, options.workspaces)), runtime.cwd);
22
+ const mode = options.mode ?? "sync";
23
+ const affectedPaths = mode === "hybrid" ? null : await detectAffectedPackages({
24
+ cwd: runtime.cwd,
25
+ root,
26
+ packages: discovered,
27
+ history: runtime.history,
28
+ range: {
29
+ fromTag: options.fromTag,
30
+ tagPrefix: options.tagPrefix
31
+ }
32
+ });
33
+ const affected = affectedPaths ? sortPackages(uniquePackages(discovered.filter((pkg) => affectedPaths.has(pkg.path))), runtime.cwd) : [];
34
+ const slices = mode === "hybrid" ? await createHybridSlices({
35
+ root,
36
+ packages: discovered,
37
+ cwd: runtime.cwd,
38
+ history: runtime.history,
39
+ fromTag: options.fromTag,
40
+ tagPrefix: options.tagPrefix,
41
+ partitions: options.partitions
42
+ }) : createSlices({
43
+ mode,
44
+ packages: discovered,
45
+ affected,
46
+ cwd: runtime.cwd,
47
+ fromTag: options.fromTag,
48
+ tagPrefix: options.tagPrefix
49
+ });
50
+ return {
51
+ mode,
52
+ packages: discovered,
53
+ affected: mode === "hybrid" ? sortPackages(uniquePackages(slices.flatMap((slice) => slice.packages)), runtime.cwd) : affected,
54
+ slices
55
+ };
56
+ }
57
+ function toScopePackage(pkg, cwd) {
58
+ return {
59
+ name: pkg.manifest.name ?? pkg.name,
60
+ version: pkg.manifest.version,
61
+ path: toPublicPath(pkg, cwd)
62
+ };
63
+ }
64
+ function toSlice(slice, cwd) {
65
+ return {
66
+ id: slice.id,
67
+ kind: slice.kind,
68
+ mode: slice.mode,
69
+ partition: slice.partition,
70
+ packages: slice.packages.map((pkg) => toScopePackage(pkg, cwd)),
71
+ range: slice.range
72
+ };
73
+ }
74
+ function uniquePackages(packages) {
75
+ const seen = /* @__PURE__ */ new Set();
76
+ return packages.filter((pkg) => {
77
+ if (seen.has(pkg.path)) return false;
78
+ seen.add(pkg.path);
79
+ return true;
80
+ });
81
+ }
82
+ function uniqueStrings(values) {
83
+ return [...new Set(values)];
84
+ }
85
+ function packageIdentity(pkg, cwd) {
86
+ const name = pkg.manifest.name ?? pkg.name;
87
+ if (name) return name;
88
+ const path = packagePath(pkg, cwd);
89
+ return path === "" || path === "." ? "root" : path;
90
+ }
91
+ function createSlices({ mode, packages, affected, cwd, fromTag, tagPrefix }) {
92
+ if (mode === "sync") return affected.length ? [{
93
+ id: "sync:default",
94
+ kind: "sync",
95
+ mode: "sync",
96
+ packages,
97
+ range: {
98
+ fromTag,
99
+ tagPrefix
100
+ }
101
+ }] : [];
102
+ return affected.map((pkg) => ({
103
+ id: `async:${packageIdentity(pkg, cwd)}`,
104
+ kind: "async",
105
+ mode: "async",
106
+ packages: [pkg],
107
+ range: {
108
+ fromTag,
109
+ tagPrefix
110
+ }
111
+ }));
112
+ }
113
+ async function createHybridSlices({ root, packages, cwd, history, fromTag, tagPrefix, partitions }) {
114
+ const partitionEntries = Object.entries(partitions ?? {}).sort(([a], [b]) => a.localeCompare(b));
115
+ const partitioned = [];
116
+ const usedPaths = /* @__PURE__ */ new Set();
117
+ for (const [partition, definition] of partitionEntries) {
118
+ const matched = sortPackages(packages.filter((pkg) => {
119
+ if (usedPaths.has(pkg.path)) return false;
120
+ return definition.workspaces.some((selector) => matchesPackageSelector(pkg, cwd, selector));
121
+ }), cwd);
122
+ for (const pkg of matched) usedPaths.add(pkg.path);
123
+ const affectedPaths = await detectAffectedPackages({
124
+ cwd,
125
+ root,
126
+ packages: matched,
127
+ history,
128
+ range: resolvePartitionRange({
129
+ fromTag,
130
+ tagPrefix,
131
+ partition: definition
132
+ })
133
+ });
134
+ const scoped = matched.filter((pkg) => affectedPaths.has(pkg.path));
135
+ if (!scoped.length) continue;
136
+ const resolvedRange = resolvePartitionRange({
137
+ fromTag,
138
+ tagPrefix,
139
+ partition: definition
140
+ });
141
+ if (definition.mode === "sync") {
142
+ partitioned.push({
143
+ id: `partition:${partition}`,
144
+ kind: "partition",
145
+ mode: "sync",
146
+ partition,
147
+ packages: scoped,
148
+ range: resolvedRange
149
+ });
150
+ continue;
151
+ }
152
+ partitioned.push(...scoped.map((pkg) => ({
153
+ id: `partition:${partition}:${packageIdentity(pkg, cwd)}`,
154
+ kind: "partition",
155
+ mode: "async",
156
+ partition,
157
+ packages: [pkg],
158
+ range: resolvedRange
159
+ })));
160
+ }
161
+ const fallbackCandidates = sortPackages(packages.filter((pkg) => !usedPaths.has(pkg.path)), cwd);
162
+ const fallbackPaths = await detectAffectedPackages({
163
+ cwd,
164
+ root,
165
+ packages: fallbackCandidates,
166
+ history,
167
+ range: {
168
+ fromTag,
169
+ tagPrefix
170
+ }
171
+ });
172
+ const fallback = fallbackCandidates.filter((pkg) => fallbackPaths.has(pkg.path)).map((pkg) => ({
173
+ id: `hybrid:${packageIdentity(pkg, cwd)}`,
174
+ kind: "async",
175
+ mode: "async",
176
+ packages: [pkg],
177
+ range: {
178
+ fromTag,
179
+ tagPrefix
180
+ }
181
+ }));
182
+ return [...partitioned, ...fallback];
183
+ }
184
+ function resolvePartitionRange({ fromTag, tagPrefix, partition }) {
185
+ return {
186
+ fromTag: partition.fromTag ?? fromTag,
187
+ tagPrefix: partition.tagPrefix ?? tagPrefix
188
+ };
189
+ }
190
+ async function detectAffectedPackages({ cwd, root, packages, history, range }) {
191
+ const touched = await readCommitRangePaths(history, range);
192
+ if (touched === null) return new Set(packages.map((pkg) => pkg.path));
193
+ if (!touched.length) return /* @__PURE__ */ new Set();
194
+ const normalizedRoot = normalizePath(relative(cwd, root.path));
195
+ const children = packages.filter((pkg) => pkg.path !== root.path).map((pkg) => ({
196
+ packagePath: pkg.path,
197
+ relativePath: normalizePath(relative(cwd, pkg.path))
198
+ })).sort((a, b) => b.relativePath.length - a.relativePath.length);
199
+ const affected = /* @__PURE__ */ new Set();
200
+ for (const path of touched.map(normalizePath)) {
201
+ if (!isPathInside(path, normalizedRoot)) continue;
202
+ const child = children.find((entry) => isPathInside(path, entry.relativePath));
203
+ affected.add(child?.packagePath ?? root.path);
204
+ }
205
+ return affected;
206
+ }
207
+ function applyWorkspaceFilters(packages, cwd, selector) {
208
+ if (!selector?.include?.length && !selector?.exclude?.length) return packages;
209
+ return packages.filter((pkg) => {
210
+ if (!(selector.include?.length ? selector.include.some((entry) => matchesPackageSelector(pkg, cwd, entry)) : true)) return false;
211
+ return !(selector.exclude?.some((entry) => matchesPackageSelector(pkg, cwd, entry)) ?? false);
212
+ });
213
+ }
214
+ function sortPackages(packages, cwd) {
215
+ return [...packages].sort((a, b) => packagePath(a, cwd).localeCompare(packagePath(b, cwd)));
216
+ }
217
+ function packagePath(pkg, cwd) {
218
+ return normalizePath(relative(cwd, pkg.path));
219
+ }
220
+ function toPublicPath(pkg, cwd) {
221
+ return packagePath(pkg, cwd) || ".";
222
+ }
223
+ function matchesPackageSelector(pkg, cwd, selector) {
224
+ const name = pkg.manifest.name ?? pkg.name ?? "";
225
+ const path = packagePath(pkg, cwd);
226
+ return matchesGlob(name, selector) || matchesGlob(path, selector);
227
+ }
228
+ function matchesGlob(input, pattern) {
229
+ if (!pattern) return false;
230
+ if (pattern === "*") return true;
231
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "__DOUBLE_STAR__").replace(/\*/g, "[^/]*").replace(/__DOUBLE_STAR__/g, ".*");
232
+ return new RegExp(`^${escaped}$`).test(input);
233
+ }
234
+ async function readCommitRangePaths(history, range) {
235
+ try {
236
+ return (await history.traverse({
237
+ fromTag: range.fromTag,
238
+ tagPrefix: range.tagPrefix,
239
+ changeset: true,
240
+ traversers: [createChangesetTraverser()]
241
+ })).results.get("changeset").paths;
242
+ } catch {
243
+ return null;
244
+ }
245
+ }
246
+ function normalizePath(path) {
247
+ return path.replace(/\\/g, "/");
248
+ }
249
+ function isPathInside(path, root) {
250
+ return !root || root === "." || root === path || path.startsWith(`${root}/`);
251
+ }
252
+ //#endregion
253
+ export { discover, packageIdentity, toScope, toScopePackage, toSlice, uniquePackages, uniqueStrings };
@@ -0,0 +1,33 @@
1
+ //#region src/reporter.ts
2
+ function createRunContext({ cwd, dry }) {
3
+ return {
4
+ cwd,
5
+ dry
6
+ };
7
+ }
8
+ async function reportStart(reporter, context) {
9
+ await reporter?.onStart?.(context);
10
+ }
11
+ async function reportScope(reporter, scope, context) {
12
+ await reporter?.onScope?.(scope, context);
13
+ }
14
+ async function reportSliceStart(reporter, slice, context) {
15
+ await reporter?.onSliceStart?.(slice, context);
16
+ }
17
+ async function reportSliceSuccess(reporter, slice, context) {
18
+ await reporter?.onSliceSuccess?.(slice, context);
19
+ }
20
+ async function reportSuccess(reporter, result, context) {
21
+ await reporter?.onSuccess?.(result, context);
22
+ }
23
+ async function reportError(reporter, error, context) {
24
+ await reporter?.onError?.(error, context);
25
+ }
26
+ //#endregion
27
+ exports.createRunContext = createRunContext;
28
+ exports.reportError = reportError;
29
+ exports.reportScope = reportScope;
30
+ exports.reportSliceStart = reportSliceStart;
31
+ exports.reportSliceSuccess = reportSliceSuccess;
32
+ exports.reportStart = reportStart;
33
+ exports.reportSuccess = reportSuccess;
@@ -0,0 +1,27 @@
1
+ //#region src/reporter.ts
2
+ function createRunContext({ cwd, dry }) {
3
+ return {
4
+ cwd,
5
+ dry
6
+ };
7
+ }
8
+ async function reportStart(reporter, context) {
9
+ await reporter?.onStart?.(context);
10
+ }
11
+ async function reportScope(reporter, scope, context) {
12
+ await reporter?.onScope?.(scope, context);
13
+ }
14
+ async function reportSliceStart(reporter, slice, context) {
15
+ await reporter?.onSliceStart?.(slice, context);
16
+ }
17
+ async function reportSliceSuccess(reporter, slice, context) {
18
+ await reporter?.onSliceSuccess?.(slice, context);
19
+ }
20
+ async function reportSuccess(reporter, result, context) {
21
+ await reporter?.onSuccess?.(result, context);
22
+ }
23
+ async function reportError(reporter, error, context) {
24
+ await reporter?.onError?.(error, context);
25
+ }
26
+ //#endregion
27
+ export { createRunContext, reportError, reportScope, reportSliceStart, reportSliceSuccess, reportStart, reportSuccess };
@@ -0,0 +1,68 @@
1
+ require("./_virtual/_rolldown/runtime.cjs");
2
+ const require_constants = require("./constants.cjs");
3
+ let _modulify_git_toolkit = require("@modulify/git-toolkit");
4
+ let _modulify_git_toolkit_shell = require("@modulify/git-toolkit/shell");
5
+ let node_fs = require("node:fs");
6
+ let node_path = require("node:path");
7
+ let _modulify_conventional_git = require("@modulify/conventional-git");
8
+ let _modulify_conventional_changelog = require("@modulify/conventional-changelog");
9
+ //#region src/runtime.ts
10
+ /** Creates the default runtime used by the public planning and release APIs. */
11
+ function createRuntime({ cwd = process.cwd(), dry = false, changelogFile = require_constants.DEFAULT_CHANGELOG_FILE } = {}) {
12
+ const sh = new _modulify_git_toolkit_shell.Runner(cwd);
13
+ return {
14
+ cwd,
15
+ dry,
16
+ changelogFile,
17
+ packageManager: resolvePackageManager(cwd),
18
+ history: new _modulify_conventional_git.Client({ cwd }),
19
+ writeChangelog: (changes) => (0, _modulify_conventional_changelog.writeChangelog)(changes, { file: dry ? void 0 : (0, node_path.join)(cwd, changelogFile) }),
20
+ sh,
21
+ git: createGit(sh)
22
+ };
23
+ }
24
+ function createGit(sh) {
25
+ const git = new _modulify_git_toolkit.GitCommander({ sh });
26
+ return {
27
+ add: (files) => git.add(files),
28
+ commit: (options) => git.commit(options),
29
+ tag: (options) => git.tag(options)
30
+ };
31
+ }
32
+ function resolvePackageManager(cwd) {
33
+ const command = readPackageManager(cwd) ?? inferPackageManagerFromLockfile(cwd) ?? "npm";
34
+ return {
35
+ command,
36
+ lockfile: resolveLockfile(cwd, command)
37
+ };
38
+ }
39
+ function readPackageManager(cwd) {
40
+ const file = (0, node_path.join)(cwd, "package.json");
41
+ if (!(0, node_fs.existsSync)(file)) return null;
42
+ const content = JSON.parse((0, node_fs.readFileSync)(file, "utf-8"));
43
+ if (typeof content.packageManager !== "string" || content.packageManager === "") return null;
44
+ const [name] = content.packageManager.split("@");
45
+ return isPackageManagerName(name) ? name : null;
46
+ }
47
+ function inferPackageManagerFromLockfile(cwd) {
48
+ if ((0, node_fs.existsSync)((0, node_path.join)(cwd, "yarn.lock"))) return "yarn";
49
+ if ((0, node_fs.existsSync)((0, node_path.join)(cwd, "pnpm-lock.yaml"))) return "pnpm";
50
+ if ((0, node_fs.existsSync)((0, node_path.join)(cwd, "package-lock.json"))) return "npm";
51
+ if ((0, node_fs.existsSync)((0, node_path.join)(cwd, "bun.lock"))) return "bun";
52
+ if ((0, node_fs.existsSync)((0, node_path.join)(cwd, "bun.lockb"))) return "bun";
53
+ return null;
54
+ }
55
+ function resolveLockfile(cwd, command) {
56
+ if (command === "bun" && (0, node_fs.existsSync)((0, node_path.join)(cwd, "bun.lockb"))) return "bun.lockb";
57
+ return {
58
+ yarn: "yarn.lock",
59
+ pnpm: "pnpm-lock.yaml",
60
+ npm: "package-lock.json",
61
+ bun: "bun.lock"
62
+ }[command];
63
+ }
64
+ function isPackageManagerName(value) {
65
+ return value === "yarn" || value === "pnpm" || value === "npm" || value === "bun";
66
+ }
67
+ //#endregion
68
+ exports.createRuntime = createRuntime;