tegami 0.2.1 → 1.0.0-beta.1

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.
@@ -0,0 +1,293 @@
1
+ import { i as isNodeError, n as execFailure } from "../error-DNy8R5ue.js";
2
+ import { n as WorkspacePackage } from "../graph-gThXu8Cz.js";
3
+ import { relative, resolve } from "node:path";
4
+ import { x } from "tinyexec";
5
+ import * as semver$1 from "semver";
6
+ import z from "zod";
7
+ //#region src/plugins/go.ts
8
+ const goWorkJsonSchema = z.object({ Use: z.array(z.object({
9
+ DiskPath: z.string(),
10
+ ModulePath: z.string().optional()
11
+ })).optional() });
12
+ const goModJsonSchema = z.object({
13
+ Module: z.object({ Path: z.string() }),
14
+ Require: z.array(z.object({
15
+ Path: z.string(),
16
+ Version: z.string().optional()
17
+ })).optional(),
18
+ Replace: z.array(z.object({
19
+ Old: z.object({
20
+ Path: z.string(),
21
+ Version: z.string().optional()
22
+ }),
23
+ New: z.object({
24
+ Path: z.string(),
25
+ Version: z.string().optional()
26
+ })
27
+ })).optional()
28
+ });
29
+ var GoPackage = class extends WorkspacePackage {
30
+ path;
31
+ mod;
32
+ manager = "go";
33
+ versionValue;
34
+ pendingRequires = /* @__PURE__ */ new Map();
35
+ constructor(path, mod, version) {
36
+ super();
37
+ this.path = path;
38
+ this.mod = mod;
39
+ this.versionValue = version;
40
+ }
41
+ get name() {
42
+ return this.mod.module;
43
+ }
44
+ get version() {
45
+ return this.versionValue;
46
+ }
47
+ setVersion(version) {
48
+ this.versionValue = version;
49
+ }
50
+ setRequire(module, version) {
51
+ const formatted = formatGoVersion(version);
52
+ this.mod.requires.set(module, formatted);
53
+ this.pendingRequires.set(module, formatted);
54
+ }
55
+ async write() {
56
+ if (this.pendingRequires.size === 0) return;
57
+ const args = ["mod", "edit"];
58
+ for (const [module, version] of this.pendingRequires) args.push(`-require=${module}@${version}`);
59
+ const result = await x("go", args, { nodeOptions: { cwd: this.path } });
60
+ if (result.exitCode !== 0) throw execFailure(`Failed to update go.mod requires in ${this.path}.`, result);
61
+ this.pendingRequires.clear();
62
+ }
63
+ };
64
+ const packageLockSchema = z.object({
65
+ id: z.string(),
66
+ version: z.string()
67
+ });
68
+ /**
69
+ * Experimental plugin for Golang, the release flow of Golang is pretty special, there's some exceptions for it:
70
+ *
71
+ * - Version is stored in lock file, normally, it should prefer to store versions in a file like `package.json` & `Cargo.toml`, but for Golang, there is no such file.
72
+ * - Publishing is handed to Git plugin, because Golang uses Git tag for publishing.
73
+ */
74
+ function go({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
75
+ let active = false;
76
+ return {
77
+ name: "go",
78
+ enforce: "post",
79
+ async resolve() {
80
+ await discoverGoPackages(this.cwd, (pkg) => this.graph.add(pkg));
81
+ active = this.graph.getPackages().some((pkg) => pkg instanceof GoPackage);
82
+ if (active && !this.plugins.some((plugin) => plugin.name === "git")) throw new Error("The go plugin requires the git plugin. Add git() from \"tegami/plugins/git\" to your plugins array.");
83
+ },
84
+ initDraft(plan) {
85
+ if (!active) return;
86
+ plan.addPolicy(depsPolicy(this, getBumpDepType));
87
+ },
88
+ async applyDraft(draft) {
89
+ if (!active) return;
90
+ const { graph } = this;
91
+ const writes = [];
92
+ for (const pkg of graph.getPackages()) {
93
+ if (!(pkg instanceof GoPackage)) continue;
94
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
95
+ if (bumped) pkg.setVersion(bumped);
96
+ }
97
+ for (const pkg of graph.getPackages()) {
98
+ if (!(pkg instanceof GoPackage)) continue;
99
+ for (const [moduleName, requireVersion] of pkg.mod.requires) {
100
+ const linked = graph.get(`go:${moduleName}`);
101
+ if (!linked || !(linked instanceof GoPackage)) continue;
102
+ if (semver$1.satisfies(linked.version, stripGoVersion(requireVersion))) continue;
103
+ pkg.setRequire(moduleName, linked.version);
104
+ }
105
+ writes.push(pkg.write());
106
+ }
107
+ await Promise.all(writes);
108
+ },
109
+ initPublishLock({ lock, draft }) {
110
+ if (!active) return;
111
+ for (const [id, packageDraft] of draft.getPackageDrafts()) {
112
+ const pkg = this.graph.get(id);
113
+ if (!(pkg instanceof GoPackage) || !packageDraft.type) continue;
114
+ lock.write("go:packages", {
115
+ id,
116
+ version: pkg.version
117
+ });
118
+ }
119
+ },
120
+ initPublishPlan({ lock, plan }) {
121
+ if (!active) return;
122
+ let data;
123
+ while (data = lock.read("go:packages")) {
124
+ const parsed = packageLockSchema.safeParse(data).data;
125
+ if (!parsed) continue;
126
+ const pkg = this.graph.get(parsed.id);
127
+ if (pkg instanceof GoPackage) pkg.setVersion(parsed.version);
128
+ }
129
+ for (const [id, packagePlan] of plan.packages) {
130
+ const pkg = this.graph.get(id);
131
+ if (!(pkg instanceof GoPackage)) continue;
132
+ packagePlan.git ??= {};
133
+ packagePlan.git.tag = formatGoTag(this.cwd, pkg.path, pkg.version);
134
+ }
135
+ },
136
+ async publishPreflight({ pkg }) {
137
+ if (!(pkg instanceof GoPackage)) return;
138
+ const wait = [];
139
+ for (const [moduleName] of pkg.mod.requires) {
140
+ const linked = this.graph.get(`go:${moduleName}`);
141
+ if (linked instanceof GoPackage) wait.push(linked.id);
142
+ }
143
+ for (const replace of pkg.mod.replaces.values()) {
144
+ if (!replace.path) continue;
145
+ const linked = findLocalModule(this.graph, pkg.path, replace.path);
146
+ if (!linked) continue;
147
+ wait.push(linked.id);
148
+ }
149
+ return {
150
+ publish: !await isModulePublished(pkg.name, pkg.version),
151
+ wait
152
+ };
153
+ },
154
+ async publish({ pkg }) {
155
+ if (!(pkg instanceof GoPackage)) return;
156
+ return { type: "published" };
157
+ },
158
+ cli: { async draftApplied() {
159
+ if (!active || !updateLockFile) return;
160
+ if (await listGoWorkUsePaths(this.cwd)) {
161
+ const result = await x("go", ["work", "sync"], { nodeOptions: { cwd: this.cwd } });
162
+ if (result.exitCode !== 0) throw execFailure("Failed to run `go work sync`.", result);
163
+ return;
164
+ }
165
+ await Promise.all(this.graph.getPackages().map(async (pkg) => {
166
+ if (!(pkg instanceof GoPackage)) return;
167
+ const result = await x("go", ["mod", "tidy"], { nodeOptions: { cwd: pkg.path } });
168
+ if (result.exitCode !== 0) throw execFailure(`Failed to run \`go mod tidy\` in ${pkg.path}.`, result);
169
+ }));
170
+ } }
171
+ };
172
+ }
173
+ function depsPolicy({ graph }, getBumpDepType = () => "patch") {
174
+ return {
175
+ id: "go:deps",
176
+ onUpdate({ pkg, packageDraft: plan }) {
177
+ if (!(pkg instanceof GoPackage)) return;
178
+ const group = graph.getPackageGroup(pkg.id);
179
+ for (const dependent of graph.getPackages()) {
180
+ if (!(dependent instanceof GoPackage)) continue;
181
+ for (const [moduleName, requireVersion] of dependent.mod.requires) {
182
+ if (pkg.id !== `go:${moduleName}`) continue;
183
+ if (group?.options.syncBump && graph.getPackageGroup(dependent.id) === group) continue;
184
+ const bumped = plan.bumpVersion(pkg);
185
+ if (!bumped || semver$1.satisfies(bumped, stripGoVersion(requireVersion))) continue;
186
+ const bumpType = getBumpDepType?.({
187
+ name: pkg.name,
188
+ dependent,
189
+ version: requireVersion
190
+ });
191
+ if (bumpType === false) continue;
192
+ this.bumpPackage(dependent, {
193
+ type: bumpType,
194
+ reason: `update require "${moduleName}"`
195
+ });
196
+ }
197
+ }
198
+ }
199
+ };
200
+ }
201
+ async function discoverGoPackages(cwd, add) {
202
+ const modulePaths = await listModulePaths(cwd);
203
+ await Promise.all(modulePaths.map(async (modulePath) => {
204
+ const mod = await readGoMod(modulePath).catch((error) => {
205
+ if (isNodeError(error) && error.code === "ENOENT") return void 0;
206
+ throw error;
207
+ });
208
+ if (!mod) return;
209
+ add(new GoPackage(modulePath, mod, await readLatestVersion(cwd, modulePath)));
210
+ }));
211
+ }
212
+ async function listModulePaths(cwd) {
213
+ const workPaths = await listGoWorkUsePaths(cwd);
214
+ if (workPaths) return workPaths;
215
+ if (await readGoMod(cwd)) return [cwd];
216
+ return [];
217
+ }
218
+ async function listGoWorkUsePaths(cwd) {
219
+ const result = await x("go", [
220
+ "work",
221
+ "edit",
222
+ "-json"
223
+ ], { nodeOptions: { cwd } });
224
+ if (result.exitCode !== 0) return void 0;
225
+ const data = goWorkJsonSchema.safeParse(JSON.parse(result.stdout)).data;
226
+ if (!data?.Use?.length) return [cwd];
227
+ return data.Use.map((use) => resolve(cwd, use.DiskPath));
228
+ }
229
+ async function readGoMod(path) {
230
+ const result = await x("go", [
231
+ "mod",
232
+ "edit",
233
+ "-json"
234
+ ], { nodeOptions: { cwd: path } });
235
+ if (result.exitCode !== 0) return;
236
+ const data = goModJsonSchema.safeParse(JSON.parse(result.stdout)).data;
237
+ if (!data) return;
238
+ const requires = /* @__PURE__ */ new Map();
239
+ for (const req of data.Require ?? []) if (req.Version) requires.set(req.Path, req.Version);
240
+ const replaces = /* @__PURE__ */ new Map();
241
+ for (const rep of data.Replace ?? []) replaces.set(rep.Old.Path, {
242
+ module: rep.New.Path,
243
+ path: rep.New.Version ? void 0 : rep.New.Path,
244
+ version: rep.New.Version
245
+ });
246
+ return {
247
+ module: data.Module.Path,
248
+ requires,
249
+ replaces
250
+ };
251
+ }
252
+ function findLocalModule(graph, modulePath, replacePath) {
253
+ const absolute = resolve(modulePath, replacePath);
254
+ return graph.getPackages().find((pkg) => pkg instanceof GoPackage && pkg.path === absolute);
255
+ }
256
+ async function readLatestVersion(cwd, modulePath) {
257
+ const result = await x("git", [
258
+ "tag",
259
+ "--list",
260
+ formatGoTag(cwd, modulePath, "v*"),
261
+ "--sort=-v:refname"
262
+ ], { nodeOptions: { cwd } });
263
+ if (result.exitCode !== 0) return "0.0.0";
264
+ for (const tag of result.stdout.split("\n")) {
265
+ const version = parseTagVersion(tag.trim());
266
+ if (version) return version;
267
+ }
268
+ return "0.0.0";
269
+ }
270
+ function parseTagVersion(tag) {
271
+ const version = stripGoVersion(tag.slice(tag.lastIndexOf("/") + 1));
272
+ if (semver$1.valid(version)) return version;
273
+ }
274
+ function formatGoTag(cwd, modulePath, version) {
275
+ const relativeDir = relative(cwd, modulePath).replaceAll("\\", "/");
276
+ if (relativeDir === "") return formatGoVersion(version);
277
+ return `${relativeDir}/${formatGoVersion(version)}`;
278
+ }
279
+ function formatGoVersion(version) {
280
+ return version.startsWith("v") ? version : `v${version}`;
281
+ }
282
+ function stripGoVersion(version) {
283
+ return version.startsWith("v") ? version.slice(1) : version;
284
+ }
285
+ async function isModulePublished(module, version) {
286
+ const formatted = formatGoVersion(version);
287
+ const response = await fetch(`https://proxy.golang.org/${encodeURIComponent(module)}/@v/${formatted}.info`);
288
+ if (response.status === 200) return true;
289
+ if (response.status === 404) return false;
290
+ throw new Error(`Unable to validate ${module}@${formatted} against proxy.golang.org: ${await response.text()}`);
291
+ }
292
+ //#endregion
293
+ export { GoPackage, go };
@@ -1,2 +1,2 @@
1
- import { d as cargo, l as CargoPackage, u as CargoPluginOptions } from "../types-DEaKjB3O.js";
1
+ import { g as cargo, h as CargoPluginOptions, m as CargoPackage } from "../types-BbDtPn8I.js";
2
2
  export { CargoPackage, CargoPluginOptions, cargo };
@@ -1,9 +1,9 @@
1
1
  import { i as isNodeError, n as execFailure } from "../error-DNy8R5ue.js";
2
- import { n as WorkspacePackage } from "../graph-DrzluXw8.js";
2
+ import { n as WorkspacePackage } from "../graph-gThXu8Cz.js";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
4
  import { join, normalize } from "node:path";
5
5
  import { x } from "tinyexec";
6
- import * as semver from "semver";
6
+ import * as semver$1 from "semver";
7
7
  import initToml, { edit, parse as parse$1 } from "@rainbowatcher/toml-edit-js";
8
8
  import { glob } from "tinyglobby";
9
9
  //#region src/providers/cargo.ts
@@ -29,7 +29,7 @@ var CargoPackage = class extends WorkspacePackage {
29
29
  return this.packageInfo.name;
30
30
  }
31
31
  get version() {
32
- return stringValue(this.packageInfo.version) ?? this.workspaceVersion ?? "0.0.0";
32
+ return stringValue(this.packageInfo.version) ?? this.workspaceVersion;
33
33
  }
34
34
  setVersion(version) {
35
35
  this.packageInfo.version = version;
@@ -76,7 +76,7 @@ function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
76
76
  wait.push(id);
77
77
  }
78
78
  return {
79
- publish: pkg.packageInfo.publish !== false && !await isPackagePublished(pkg.name, pkg.version),
79
+ publish: pkg.version !== void 0 && pkg.packageInfo.publish !== false && !await isPackagePublished(pkg.name, pkg.version),
80
80
  wait
81
81
  };
82
82
  },
@@ -95,18 +95,18 @@ function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
95
95
  const writes = [];
96
96
  for (const pkg of graph.getPackages()) {
97
97
  if (!(pkg instanceof CargoPackage)) continue;
98
- const plan = draft.getPackageDraft(pkg.id);
99
- if (plan) pkg.setVersion(plan.bumpVersion(pkg));
98
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
99
+ if (bumped) pkg.setVersion(bumped);
100
100
  }
101
101
  for (const pkg of graph.getPackages()) {
102
102
  if (!(pkg instanceof CargoPackage)) continue;
103
103
  for (const { table, path: tablePath } of dependencyTables(pkg.manifest, "")) for (const [rawName, rawSpec] of Object.entries(table)) {
104
104
  const spec = parseSpec(rawSpec);
105
- if (!spec || !semver.validRange(spec.version)) continue;
105
+ if (!spec || !semver$1.validRange(spec.version)) continue;
106
106
  const packageName = spec.package ?? rawName;
107
107
  const linked = graph.get(`cargo:${packageName}`);
108
108
  if (!linked || !(linked instanceof CargoPackage)) continue;
109
- if (semver.satisfies(linked.version, spec.version)) continue;
109
+ if (!linked.version || semver$1.satisfies(linked.version, spec.version)) continue;
110
110
  let updatedRange;
111
111
  if (spec.version.startsWith("^")) updatedRange = `^${linked.version}`;
112
112
  else if (spec.version.startsWith("~")) updatedRange = `~${linked.version}`;
@@ -141,12 +141,14 @@ function depsPolicy({ graph }, getBumpDepType = ({ kind }) => {
141
141
  if (!(dependent instanceof CargoPackage)) continue;
142
142
  for (const { table, kind } of dependencyTables(dependent.manifest, "")) for (const [rawName, rawSpec] of Object.entries(table)) {
143
143
  const spec = parseSpec(rawSpec);
144
- if (!spec || !semver.validRange(spec.version)) continue;
144
+ if (!spec || !semver$1.validRange(spec.version)) continue;
145
145
  if (pkg.id !== `cargo:${spec.package ?? rawName}`) continue;
146
146
  if (group?.options.syncBump && graph.getPackageGroup(dependent.id) === group) continue;
147
- if (semver.satisfies(plan.bumpVersion(pkg), spec.version)) continue;
147
+ const bumped = plan.bumpVersion(pkg);
148
+ if (!bumped || semver$1.satisfies(bumped, spec.version)) continue;
148
149
  const bumpType = getBumpDepType({
149
150
  kind,
151
+ dependent,
150
152
  name: pkg.name,
151
153
  version: spec.version
152
154
  });
@@ -185,10 +187,7 @@ async function discoverCargoPackages(cwd, add) {
185
187
  for (const entry of manifests) if (entry) addCargoPackage(entry.path, entry.manifest.manifest, entry.manifest.content, root.manifest, add);
186
188
  }
187
189
  function addCargoPackage(path, manifest, content, workspaceManifest, add) {
188
- const packageInfo = tableValue(manifest.package);
189
- const workspacePackage = tableValue(workspaceManifest.workspace)?.package;
190
- if (!packageInfo?.name) return;
191
- if (!packageInfo.version && !tableValue(workspacePackage)?.version) return;
190
+ if (!tableValue(manifest.package)?.name) return;
192
191
  add(new CargoPackage(path, manifest, content, workspaceManifest));
193
192
  }
194
193
  async function expandWorkspaceMembers(cwd, members, exclude) {
@@ -1,2 +1,2 @@
1
- import { f as NpmPackage, m as npm, p as NpmPluginOptions } from "../types-DEaKjB3O.js";
1
+ import { _ as NpmPackage, v as NpmPluginOptions, y as npm } from "../types-BbDtPn8I.js";
2
2
  export { NpmPackage, NpmPluginOptions, npm };