tegami 1.1.0 → 1.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.
@@ -0,0 +1,1252 @@
1
+ import { c as somePromise, i as isNodeError, n as execFailure, r as handlePluginError, s as joinPath } from "./error-BhMYq9iW.js";
2
+ import { t as _accessExpressionAsString } from "./_accessExpressionAsString-QhbUZzwv.js";
3
+ import { n as _validateReport, t as _createStandardSchema } from "./_createStandardSchema-BGQyz-uA.js";
4
+ import { a as parseChangelogFile, i as parsePublishLock, n as validateChangelogStore, r as validatePackageStore } from "./draft-CzUiQasJ.js";
5
+ import { t as _assertGuard } from "./_assertGuard-BBn2NbSz.js";
6
+ import { n as WorkspacePackage } from "./graph-BmXTJZxx.js";
7
+ import fs, { readFile, writeFile } from "node:fs/promises";
8
+ import path, { join } from "node:path";
9
+ import { x } from "tinyexec";
10
+ import * as semver$1 from "semver";
11
+ import { parse as parse$1, parseDocument, stringify } from "yaml";
12
+ import { detect } from "package-manager-detector";
13
+ import { tmpdir } from "node:os";
14
+ import { intro, note, outro } from "@clack/prompts";
15
+ import { glob } from "tinyglobby";
16
+ //#region src/plans/publish.ts
17
+ async function initPublishPlan(context, options) {
18
+ let lock;
19
+ try {
20
+ lock = parsePublishLock(await fs.readFile(context.lockPath, "utf8"));
21
+ } catch {
22
+ return;
23
+ }
24
+ let data;
25
+ const packages = /* @__PURE__ */ new Map();
26
+ const changelogs = /* @__PURE__ */ new Map();
27
+ while (data = lock.read("core:changelogs")) {
28
+ const validated = validateChangelogStore(data);
29
+ if (!validated.success) continue;
30
+ const entry = validated.data;
31
+ const parsed = parseChangelogFile(entry.filename, entry.content);
32
+ if (!parsed) continue;
33
+ changelogs.set(parsed.id, parsed);
34
+ }
35
+ while (data = lock.read("core:packages")) {
36
+ const validated = validatePackageStore(data);
37
+ if (!validated.success) continue;
38
+ const parsed = validated.data;
39
+ if (!context.graph.get(parsed.id)) continue;
40
+ const pkgChangelogs = [];
41
+ for (const id of parsed.changelogIds ?? []) {
42
+ const entry = changelogs.get(id);
43
+ if (entry) pkgChangelogs.push(entry);
44
+ }
45
+ packages.set(parsed.id, {
46
+ changelogs: pkgChangelogs,
47
+ updated: parsed.updated
48
+ });
49
+ }
50
+ const plan = {
51
+ options,
52
+ changelogs,
53
+ packages
54
+ };
55
+ for (const plugin of context.plugins) await handlePluginError(plugin, "initPublishPlan", () => plugin.initPublishPlan?.call(context, {
56
+ lock,
57
+ plan
58
+ }));
59
+ return plan;
60
+ }
61
+ function resolvePublishTargets(plan) {
62
+ const ordered = [];
63
+ const scanned = /* @__PURE__ */ new Set();
64
+ function scan(id, stack) {
65
+ const preflight = plan.packages.get(id)?.preflight;
66
+ if (!preflight || !preflight.shouldPublish) return;
67
+ if (stack.has(id)) throw new Error(`circular reference of deps: ${[...stack, id].join(" -> ")}`);
68
+ if (scanned.has(id)) return;
69
+ if (preflight.wait) {
70
+ stack.add(id);
71
+ for (const dep of preflight.wait) scan(dep, stack);
72
+ stack.delete(id);
73
+ }
74
+ ordered.push(id);
75
+ scanned.add(id);
76
+ }
77
+ const stack = /* @__PURE__ */ new Set();
78
+ for (const id of plan.packages.keys()) scan(id, stack);
79
+ return ordered;
80
+ }
81
+ async function runPublishPlan(context, plan) {
82
+ const { dryRun = false } = plan.options;
83
+ const onPublishResult = async (pkg, publishResult) => {
84
+ const packagePlan = plan.packages.get(pkg.id);
85
+ if (!packagePlan) return;
86
+ packagePlan.publishResult = publishResult;
87
+ if (publishResult.type === "skipped") return;
88
+ for (const plugin of context.plugins) await handlePluginError(plugin, "afterPublish", () => plugin.afterPublish?.call(context, {
89
+ pkg,
90
+ plan
91
+ }));
92
+ };
93
+ publishLoop: for (const id of resolvePublishTargets(plan)) {
94
+ const pkg = context.graph.get(id);
95
+ if (dryRun) {
96
+ await onPublishResult(pkg, { type: "published" });
97
+ continue;
98
+ }
99
+ for (const plugin of context.plugins) if (await handlePluginError(plugin, "willPublish", () => plugin.willPublish?.call(context, { pkg })) === false) continue publishLoop;
100
+ for (const plugin of context.plugins) {
101
+ const publishResult = await handlePluginError(plugin, "publish", () => plugin.publish?.call(context, {
102
+ pkg,
103
+ plan
104
+ }));
105
+ if (publishResult) {
106
+ await onPublishResult(pkg, publishResult);
107
+ continue publishLoop;
108
+ }
109
+ }
110
+ await onPublishResult(pkg, {
111
+ type: "failed",
112
+ error: `There is no plugin to publish package "${pkg.id}", please make sure the package has a supported provider plugin.`
113
+ });
114
+ }
115
+ for (const packagePlan of plan.packages.values()) packagePlan.publishResult ??= { type: "skipped" };
116
+ for (const plugin of context.plugins) await handlePluginError(plugin, "afterPublishAll", () => plugin.afterPublishAll?.call(context, { plan }));
117
+ }
118
+ async function runPreflights(context, plan) {
119
+ const promises = [];
120
+ for (const [id, packagePlan] of plan.packages) {
121
+ const pkg = context.graph.get(id);
122
+ packagePlan.preflight = { shouldPublish: false };
123
+ if (!packagePlan.updated) continue;
124
+ promises.push((async () => {
125
+ for (const plugin of context.plugins) {
126
+ const res = await handlePluginError(plugin, "publishPreflight", () => plugin.publishPreflight?.call(context, {
127
+ pkg,
128
+ plan
129
+ }));
130
+ if (res) {
131
+ packagePlan.preflight = res;
132
+ break;
133
+ }
134
+ }
135
+ })());
136
+ }
137
+ await Promise.all(promises);
138
+ for (const plugin of context.plugins) await handlePluginError(plugin, "afterPreflight", () => plugin.afterPreflight?.call(context, { plan }));
139
+ }
140
+ async function publishPlanStatus(plan, context) {
141
+ for (const plugin of context.plugins) {
142
+ const status = await handlePluginError(plugin, "resolvePlanStatus", () => plugin.resolvePlanStatus?.call(context, { plan }));
143
+ if (Array.isArray(status) && await somePromise(status, (v) => v === "pending")) return "pending";
144
+ if (status === "pending") return "pending";
145
+ }
146
+ return "success";
147
+ }
148
+ //#endregion
149
+ //#region src/providers/npm/cli.ts
150
+ const PLACEHOLDER_VERSION = "0.0.0-tegami-trusted-publish-setup";
151
+ const PLACEHOLDER_DIST_TAG = "temp";
152
+ const PROJECT_FLAG = {
153
+ gitlab: "--project",
154
+ github: "--repo"
155
+ };
156
+ function registerNpmCli(cli, options) {
157
+ cli.command("npm pretrust", { description: "publish empty placeholder packages and configure npm trusted publishing for new packages" }).option("dry-run", {
158
+ type: "boolean",
159
+ description: "show packages that would be configured without publishing"
160
+ }).action(async ({ context, values }) => {
161
+ intro("npm pretrust");
162
+ if (!context.graph.getPackages().some((pkg) => pkg instanceof NpmPackage)) throw new Error("No npm packages found in the workspace.");
163
+ const dryRun = values["dry-run"] ?? false;
164
+ let repo;
165
+ if (options.provider === "github") {
166
+ if (!context.github?.repo) throw new Error("The GitHub plugin must be configured with `repo` specified.");
167
+ repo = context.github.repo;
168
+ } else if (options.provider === "gitlab") {
169
+ if (!context.gitlab?.repo) throw new Error("The GitLab plugin must be configured with `repo` specified.");
170
+ repo = context.gitlab.repo;
171
+ } else throw new Error(`Invalid npm trusted publishing provider: ${options.provider}`);
172
+ const targets = await resolvePretrustTargets(context);
173
+ if (targets.length === 0) {
174
+ outro("All publishable packages in the publish lock already exist on npm.");
175
+ return;
176
+ }
177
+ const prepareLines = ["Make sure to run login command first, it will publish empty packages."];
178
+ for (const pkg of targets) prepareLines.push(`${pkg.name}: will publish a placeholder under dist-tag "${PLACEHOLDER_DIST_TAG}", then configure trusted publishing.`);
179
+ note(prepareLines.join("\n"), dryRun ? "Dry run" : "Configure trusted publishing");
180
+ const lines = [];
181
+ let lock;
182
+ if (!dryRun) try {
183
+ lock = parsePublishLock(await fs.readFile(context.lockPath, "utf8"));
184
+ } catch {}
185
+ for (const pkg of targets) {
186
+ if (dryRun) {
187
+ lines.push(`would configure ${pkg.name} (placeholder ${PLACEHOLDER_VERSION}@${PLACEHOLDER_DIST_TAG})`);
188
+ continue;
189
+ }
190
+ await publishPlaceholder(pkg);
191
+ await npmTrust(context, pkg, options, repo);
192
+ lines.push(`configured ${pkg.name} (placeholder ${PLACEHOLDER_VERSION}@${PLACEHOLDER_DIST_TAG})`);
193
+ lock?.write("npm:mark-latest", { id: pkg.id });
194
+ }
195
+ if (lock) await fs.writeFile(context.lockPath, lock.serialize());
196
+ note(lines.join("\n"), "Result");
197
+ outro(dryRun ? "Dry run complete. Re-run without --dry-run to publish placeholders and configure trusted publishing." : "Trusted publishing configured. CI can now publish real package versions with OIDC.");
198
+ });
199
+ }
200
+ async function resolvePretrustTargets(context) {
201
+ const plan = await initPublishPlan(context, {});
202
+ if (!plan) throw new Error(`No publish lock found at ${context.lockPath}. Run "tegami version" before configuring trusted publishing.`);
203
+ await runPreflights(context, plan);
204
+ return (await Promise.all(Array.from(plan.packages, async ([id, { preflight }]) => {
205
+ if (!preflight?.shouldPublish) return;
206
+ const pkg = context.graph.get(id);
207
+ if (!pkg || !(pkg instanceof NpmPackage)) return;
208
+ if (await isPackageOnRegistry(pkg.name, pkg.getRegistry())) return;
209
+ return pkg;
210
+ }))).filter((pkg) => pkg !== void 0);
211
+ }
212
+ async function isPackageOnRegistry(name, registry = "https://registry.npmjs.org") {
213
+ const response = await fetch(joinPath(registry, name), { headers: { Accept: "application/json" } });
214
+ if (response.status === 404) return false;
215
+ if (!response.ok) throw new Error(`Unable to check whether ${name} exists on the npm registry${registry ? ` "${registry}"` : ""}.`);
216
+ return true;
217
+ }
218
+ async function publishPlaceholder(pkg) {
219
+ const registry = pkg.getRegistry();
220
+ const access = pkg.manifest.publishConfig?.access;
221
+ const dir = await fs.mkdtemp(join(tmpdir(), "tegami-npm-placeholder-"));
222
+ try {
223
+ await fs.writeFile(join(dir, "package.json"), `${JSON.stringify({
224
+ name: pkg.name,
225
+ version: PLACEHOLDER_VERSION,
226
+ description: "Placeholder published by Tegami for npm trusted publishing setup."
227
+ }, null, 2)}\n`);
228
+ await fs.writeFile(join(dir, "README.md"), `# Placeholder package
229
+
230
+ This empty package was published by [Tegami](https://tegami.fuma-nama.dev) to configure npm trusted publishing.
231
+
232
+ The real package contents will be published via CI with OIDC.
233
+ `);
234
+ const args = [
235
+ "publish",
236
+ "--tag",
237
+ PLACEHOLDER_DIST_TAG,
238
+ "--ignore-scripts",
239
+ "--registry",
240
+ registry
241
+ ];
242
+ if (access) args.push("--access", access);
243
+ const result = await x("npm", args, { nodeOptions: {
244
+ cwd: dir,
245
+ stdio: "inherit"
246
+ } });
247
+ if (result.exitCode !== 0) {
248
+ const hint = result.stderr.includes("EOTP") ? " Complete npm 2FA in the terminal, or publish with an OTP-capable session." : "";
249
+ throw execFailure(`Failed to publish placeholder ${pkg.name}@${PLACEHOLDER_VERSION} with dist-tag "${PLACEHOLDER_DIST_TAG}".${hint}`, result);
250
+ }
251
+ } finally {
252
+ await fs.rm(dir, {
253
+ recursive: true,
254
+ force: true
255
+ });
256
+ }
257
+ }
258
+ async function npmTrust(context, pkg, options, repo) {
259
+ const result = await x("npm", [
260
+ "trust",
261
+ options.provider,
262
+ pkg.name,
263
+ PROJECT_FLAG[options.provider],
264
+ repo,
265
+ "--file",
266
+ options.workflow,
267
+ "--allow-publish",
268
+ "-y",
269
+ "--registry",
270
+ pkg.getRegistry()
271
+ ], { nodeOptions: {
272
+ cwd: context.cwd,
273
+ stdio: "inherit"
274
+ } });
275
+ if (result.exitCode !== 0) {
276
+ const hint = result.stderr.includes("EOTP") ? " Complete npm 2FA in the terminal when prompted." : "";
277
+ throw execFailure(`Failed to configure trusted publishing for ${pkg.name}.${hint}`, result);
278
+ }
279
+ }
280
+ //#endregion
281
+ //#region src/providers/npm/graph.ts
282
+ var NpmPackage = class extends WorkspacePackage {
283
+ path;
284
+ manifest;
285
+ manager = "npm";
286
+ dependencies;
287
+ constructor(path, manifest) {
288
+ super();
289
+ this.path = path;
290
+ this.manifest = manifest;
291
+ }
292
+ get name() {
293
+ return this.manifest.name;
294
+ }
295
+ get version() {
296
+ return this.manifest.version;
297
+ }
298
+ async write() {
299
+ await writeFile(path.join(this.path, "package.json"), `${JSON.stringify(this.manifest, null, 2)}\n`);
300
+ }
301
+ initDraft() {
302
+ const defaults = super.initDraft();
303
+ defaults.npm = { distTag: this.manifest.publishConfig?.tag };
304
+ return defaults;
305
+ }
306
+ getRegistry() {
307
+ return this.manifest.publishConfig?.registry ?? "https://registry.npmjs.org";
308
+ }
309
+ configureDraft({ draft }) {
310
+ super.configureDraft({ draft });
311
+ const { distTag = this.group?.options?.npm?.distTag } = this.options.npm ?? {};
312
+ if (distTag) {
313
+ draft.npm ??= {};
314
+ draft.npm.distTag = distTag;
315
+ } else if (draft.prerelease) {
316
+ draft.npm ??= {};
317
+ draft.npm.distTag ??= draft.prerelease;
318
+ }
319
+ }
320
+ listDependencies(graph) {
321
+ return this.dependencies ??= listDependencies(graph, this);
322
+ }
323
+ };
324
+ const assertPnpmWorkspace = (() => {
325
+ const _io0 = (input) => (void 0 === input.packages || Array.isArray(input.packages) && input.packages.every((elem) => "string" === typeof elem)) && (void 0 === input.catalog || "object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) && _io1(input.catalog)) && (void 0 === input.catalogs || "object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) && _io2(input.catalogs));
326
+ const _io1 = (input) => Object.keys(input).every((key) => {
327
+ const value = input[key];
328
+ if (void 0 === value) return true;
329
+ return "string" === typeof value;
330
+ });
331
+ const _io2 = (input) => Object.keys(input).every((key) => {
332
+ const value = input[key];
333
+ if (void 0 === value) return true;
334
+ return "object" === typeof value && null !== value && false === Array.isArray(value) && _io1(value);
335
+ });
336
+ const _ao0 = (input, _path, _exceptionable = true) => (void 0 === input.packages || (Array.isArray(input.packages) || _assertGuard(_exceptionable, {
337
+ method: "typia.createAssert",
338
+ path: _path + ".packages",
339
+ expected: "(Array<string> | undefined)",
340
+ value: input.packages
341
+ }, _errorFactory)) && input.packages.every((elem, _index2) => "string" === typeof elem || _assertGuard(_exceptionable, {
342
+ method: "typia.createAssert",
343
+ path: _path + ".packages[" + _index2 + "]",
344
+ expected: "string",
345
+ value: elem
346
+ }, _errorFactory)) || _assertGuard(_exceptionable, {
347
+ method: "typia.createAssert",
348
+ path: _path + ".packages",
349
+ expected: "(Array<string> | undefined)",
350
+ value: input.packages
351
+ }, _errorFactory)) && (void 0 === input.catalog || ("object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) || _assertGuard(_exceptionable, {
352
+ method: "typia.createAssert",
353
+ path: _path + ".catalog",
354
+ expected: "(Record<string, string> | undefined)",
355
+ value: input.catalog
356
+ }, _errorFactory)) && _ao1(input.catalog, _path + ".catalog", _exceptionable) || _assertGuard(_exceptionable, {
357
+ method: "typia.createAssert",
358
+ path: _path + ".catalog",
359
+ expected: "(Record<string, string> | undefined)",
360
+ value: input.catalog
361
+ }, _errorFactory)) && (void 0 === input.catalogs || ("object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) || _assertGuard(_exceptionable, {
362
+ method: "typia.createAssert",
363
+ path: _path + ".catalogs",
364
+ expected: "(Record<string, Record<string, string>> | undefined)",
365
+ value: input.catalogs
366
+ }, _errorFactory)) && _ao2(input.catalogs, _path + ".catalogs", _exceptionable) || _assertGuard(_exceptionable, {
367
+ method: "typia.createAssert",
368
+ path: _path + ".catalogs",
369
+ expected: "(Record<string, Record<string, string>> | undefined)",
370
+ value: input.catalogs
371
+ }, _errorFactory));
372
+ const _ao1 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every((key) => {
373
+ const value = input[key];
374
+ if (void 0 === value) return true;
375
+ return "string" === typeof value || _assertGuard(_exceptionable, {
376
+ method: "typia.createAssert",
377
+ path: _path + _accessExpressionAsString(key),
378
+ expected: "string",
379
+ value
380
+ }, _errorFactory);
381
+ });
382
+ const _ao2 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every((key) => {
383
+ const value = input[key];
384
+ if (void 0 === value) return true;
385
+ return ("object" === typeof value && null !== value && false === Array.isArray(value) || _assertGuard(_exceptionable, {
386
+ method: "typia.createAssert",
387
+ path: _path + _accessExpressionAsString(key),
388
+ expected: "Record<string, string>",
389
+ value
390
+ }, _errorFactory)) && _ao1(value, _path + _accessExpressionAsString(key), _exceptionable) || _assertGuard(_exceptionable, {
391
+ method: "typia.createAssert",
392
+ path: _path + _accessExpressionAsString(key),
393
+ expected: "Record<string, string>",
394
+ value
395
+ }, _errorFactory);
396
+ });
397
+ const __is = (input) => "object" === typeof input && null !== input && false === Array.isArray(input) && _io0(input);
398
+ let _errorFactory;
399
+ return (input, errorFactory) => {
400
+ if (false === __is(input)) {
401
+ _errorFactory = errorFactory;
402
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input && false === Array.isArray(input) || _assertGuard(true, {
403
+ method: "typia.createAssert",
404
+ path: _path + "",
405
+ expected: "PnpmWorkspace",
406
+ value: input
407
+ }, _errorFactory)) && _ao0(input, _path + "", true) || _assertGuard(true, {
408
+ method: "typia.createAssert",
409
+ path: _path + "",
410
+ expected: "PnpmWorkspace",
411
+ value: input
412
+ }, _errorFactory))(input, "$input", true);
413
+ }
414
+ return input;
415
+ };
416
+ })();
417
+ const assertPackageManifest = (() => {
418
+ const _io0 = (input) => "string" === typeof input.name && (void 0 === input.version || "string" === typeof input.version) && (void 0 === input["private"] || "boolean" === typeof input["private"]) && (void 0 === input.publishConfig || "object" === typeof input.publishConfig && null !== input.publishConfig && false === Array.isArray(input.publishConfig) && _io1(input.publishConfig)) && (void 0 === input.scripts || "object" === typeof input.scripts && null !== input.scripts && false === Array.isArray(input.scripts) && _io2(input.scripts)) && null !== input.workspaces && (void 0 === input.workspaces || Array.isArray(input.workspaces) && input.workspaces.every((elem) => "string" === typeof elem) || "object" === typeof input.workspaces && null !== input.workspaces && false === Array.isArray(input.workspaces) && _io3(input.workspaces)) && (void 0 === input.catalog || "object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) && _io2(input.catalog)) && (void 0 === input.catalogs || "object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) && _io4(input.catalogs)) && (void 0 === input.dependencies || "object" === typeof input.dependencies && null !== input.dependencies && false === Array.isArray(input.dependencies) && _io2(input.dependencies)) && (void 0 === input.devDependencies || "object" === typeof input.devDependencies && null !== input.devDependencies && false === Array.isArray(input.devDependencies) && _io2(input.devDependencies)) && (void 0 === input.peerDependencies || "object" === typeof input.peerDependencies && null !== input.peerDependencies && false === Array.isArray(input.peerDependencies) && _io2(input.peerDependencies)) && (void 0 === input.optionalDependencies || "object" === typeof input.optionalDependencies && null !== input.optionalDependencies && false === Array.isArray(input.optionalDependencies) && _io2(input.optionalDependencies));
419
+ const _io1 = (input) => (void 0 === input.access || "public" === input.access || "restricted" === input.access) && (void 0 === input.registry || "string" === typeof input.registry) && (void 0 === input.tag || "string" === typeof input.tag);
420
+ const _io2 = (input) => Object.keys(input).every((key) => {
421
+ const value = input[key];
422
+ if (void 0 === value) return true;
423
+ return "string" === typeof value;
424
+ });
425
+ const _io3 = (input) => (void 0 === input.packages || Array.isArray(input.packages) && input.packages.every((elem) => "string" === typeof elem)) && (void 0 === input.catalog || "object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) && _io2(input.catalog)) && (void 0 === input.catalogs || "object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) && _io4(input.catalogs));
426
+ const _io4 = (input) => Object.keys(input).every((key) => {
427
+ const value = input[key];
428
+ if (void 0 === value) return true;
429
+ return "object" === typeof value && null !== value && false === Array.isArray(value) && _io2(value);
430
+ });
431
+ const _ao0 = (input, _path, _exceptionable = true) => ("string" === typeof input.name || _assertGuard(_exceptionable, {
432
+ method: "typia.createAssert",
433
+ path: _path + ".name",
434
+ expected: "string",
435
+ value: input.name
436
+ }, _errorFactory)) && (void 0 === input.version || "string" === typeof input.version || _assertGuard(_exceptionable, {
437
+ method: "typia.createAssert",
438
+ path: _path + ".version",
439
+ expected: "(string | undefined)",
440
+ value: input.version
441
+ }, _errorFactory)) && (void 0 === input["private"] || "boolean" === typeof input["private"] || _assertGuard(_exceptionable, {
442
+ method: "typia.createAssert",
443
+ path: _path + "[\"private\"]",
444
+ expected: "(boolean | undefined)",
445
+ value: input["private"]
446
+ }, _errorFactory)) && (void 0 === input.publishConfig || ("object" === typeof input.publishConfig && null !== input.publishConfig && false === Array.isArray(input.publishConfig) || _assertGuard(_exceptionable, {
447
+ method: "typia.createAssert",
448
+ path: _path + ".publishConfig",
449
+ expected: "(__type | undefined)",
450
+ value: input.publishConfig
451
+ }, _errorFactory)) && _ao1(input.publishConfig, _path + ".publishConfig", _exceptionable) || _assertGuard(_exceptionable, {
452
+ method: "typia.createAssert",
453
+ path: _path + ".publishConfig",
454
+ expected: "(__type | undefined)",
455
+ value: input.publishConfig
456
+ }, _errorFactory)) && (void 0 === input.scripts || ("object" === typeof input.scripts && null !== input.scripts && false === Array.isArray(input.scripts) || _assertGuard(_exceptionable, {
457
+ method: "typia.createAssert",
458
+ path: _path + ".scripts",
459
+ expected: "(Record<string, string> | undefined)",
460
+ value: input.scripts
461
+ }, _errorFactory)) && _ao2(input.scripts, _path + ".scripts", _exceptionable) || _assertGuard(_exceptionable, {
462
+ method: "typia.createAssert",
463
+ path: _path + ".scripts",
464
+ expected: "(Record<string, string> | undefined)",
465
+ value: input.scripts
466
+ }, _errorFactory)) && (null !== input.workspaces || _assertGuard(_exceptionable, {
467
+ method: "typia.createAssert",
468
+ path: _path + ".workspaces",
469
+ expected: "(Array<string> | BunWorkspaces | undefined)",
470
+ value: input.workspaces
471
+ }, _errorFactory)) && (void 0 === input.workspaces || Array.isArray(input.workspaces) && input.workspaces.every((elem, _index3) => "string" === typeof elem || _assertGuard(_exceptionable, {
472
+ method: "typia.createAssert",
473
+ path: _path + ".workspaces[" + _index3 + "]",
474
+ expected: "string",
475
+ value: elem
476
+ }, _errorFactory)) || "object" === typeof input.workspaces && null !== input.workspaces && false === Array.isArray(input.workspaces) && _ao3(input.workspaces, _path + ".workspaces", _exceptionable) || _assertGuard(_exceptionable, {
477
+ method: "typia.createAssert",
478
+ path: _path + ".workspaces",
479
+ expected: "(Array<string> | BunWorkspaces | undefined)",
480
+ value: input.workspaces
481
+ }, _errorFactory) || _assertGuard(_exceptionable, {
482
+ method: "typia.createAssert",
483
+ path: _path + ".workspaces",
484
+ expected: "(Array<string> | BunWorkspaces | undefined)",
485
+ value: input.workspaces
486
+ }, _errorFactory)) && (void 0 === input.catalog || ("object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) || _assertGuard(_exceptionable, {
487
+ method: "typia.createAssert",
488
+ path: _path + ".catalog",
489
+ expected: "(Record<string, string> | undefined)",
490
+ value: input.catalog
491
+ }, _errorFactory)) && _ao2(input.catalog, _path + ".catalog", _exceptionable) || _assertGuard(_exceptionable, {
492
+ method: "typia.createAssert",
493
+ path: _path + ".catalog",
494
+ expected: "(Record<string, string> | undefined)",
495
+ value: input.catalog
496
+ }, _errorFactory)) && (void 0 === input.catalogs || ("object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) || _assertGuard(_exceptionable, {
497
+ method: "typia.createAssert",
498
+ path: _path + ".catalogs",
499
+ expected: "(Record<string, Record<string, string>> | undefined)",
500
+ value: input.catalogs
501
+ }, _errorFactory)) && _ao4(input.catalogs, _path + ".catalogs", _exceptionable) || _assertGuard(_exceptionable, {
502
+ method: "typia.createAssert",
503
+ path: _path + ".catalogs",
504
+ expected: "(Record<string, Record<string, string>> | undefined)",
505
+ value: input.catalogs
506
+ }, _errorFactory)) && (void 0 === input.dependencies || ("object" === typeof input.dependencies && null !== input.dependencies && false === Array.isArray(input.dependencies) || _assertGuard(_exceptionable, {
507
+ method: "typia.createAssert",
508
+ path: _path + ".dependencies",
509
+ expected: "(Record<string, string> | undefined)",
510
+ value: input.dependencies
511
+ }, _errorFactory)) && _ao2(input.dependencies, _path + ".dependencies", _exceptionable) || _assertGuard(_exceptionable, {
512
+ method: "typia.createAssert",
513
+ path: _path + ".dependencies",
514
+ expected: "(Record<string, string> | undefined)",
515
+ value: input.dependencies
516
+ }, _errorFactory)) && (void 0 === input.devDependencies || ("object" === typeof input.devDependencies && null !== input.devDependencies && false === Array.isArray(input.devDependencies) || _assertGuard(_exceptionable, {
517
+ method: "typia.createAssert",
518
+ path: _path + ".devDependencies",
519
+ expected: "(Record<string, string> | undefined)",
520
+ value: input.devDependencies
521
+ }, _errorFactory)) && _ao2(input.devDependencies, _path + ".devDependencies", _exceptionable) || _assertGuard(_exceptionable, {
522
+ method: "typia.createAssert",
523
+ path: _path + ".devDependencies",
524
+ expected: "(Record<string, string> | undefined)",
525
+ value: input.devDependencies
526
+ }, _errorFactory)) && (void 0 === input.peerDependencies || ("object" === typeof input.peerDependencies && null !== input.peerDependencies && false === Array.isArray(input.peerDependencies) || _assertGuard(_exceptionable, {
527
+ method: "typia.createAssert",
528
+ path: _path + ".peerDependencies",
529
+ expected: "(Record<string, string> | undefined)",
530
+ value: input.peerDependencies
531
+ }, _errorFactory)) && _ao2(input.peerDependencies, _path + ".peerDependencies", _exceptionable) || _assertGuard(_exceptionable, {
532
+ method: "typia.createAssert",
533
+ path: _path + ".peerDependencies",
534
+ expected: "(Record<string, string> | undefined)",
535
+ value: input.peerDependencies
536
+ }, _errorFactory)) && (void 0 === input.optionalDependencies || ("object" === typeof input.optionalDependencies && null !== input.optionalDependencies && false === Array.isArray(input.optionalDependencies) || _assertGuard(_exceptionable, {
537
+ method: "typia.createAssert",
538
+ path: _path + ".optionalDependencies",
539
+ expected: "(Record<string, string> | undefined)",
540
+ value: input.optionalDependencies
541
+ }, _errorFactory)) && _ao2(input.optionalDependencies, _path + ".optionalDependencies", _exceptionable) || _assertGuard(_exceptionable, {
542
+ method: "typia.createAssert",
543
+ path: _path + ".optionalDependencies",
544
+ expected: "(Record<string, string> | undefined)",
545
+ value: input.optionalDependencies
546
+ }, _errorFactory));
547
+ const _ao1 = (input, _path, _exceptionable = true) => (void 0 === input.access || "public" === input.access || "restricted" === input.access || _assertGuard(_exceptionable, {
548
+ method: "typia.createAssert",
549
+ path: _path + ".access",
550
+ expected: "(\"public\" | \"restricted\" | undefined)",
551
+ value: input.access
552
+ }, _errorFactory)) && (void 0 === input.registry || "string" === typeof input.registry || _assertGuard(_exceptionable, {
553
+ method: "typia.createAssert",
554
+ path: _path + ".registry",
555
+ expected: "(string | undefined)",
556
+ value: input.registry
557
+ }, _errorFactory)) && (void 0 === input.tag || "string" === typeof input.tag || _assertGuard(_exceptionable, {
558
+ method: "typia.createAssert",
559
+ path: _path + ".tag",
560
+ expected: "(string | undefined)",
561
+ value: input.tag
562
+ }, _errorFactory));
563
+ const _ao2 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every((key) => {
564
+ const value = input[key];
565
+ if (void 0 === value) return true;
566
+ return "string" === typeof value || _assertGuard(_exceptionable, {
567
+ method: "typia.createAssert",
568
+ path: _path + _accessExpressionAsString(key),
569
+ expected: "string",
570
+ value
571
+ }, _errorFactory);
572
+ });
573
+ const _ao3 = (input, _path, _exceptionable = true) => (void 0 === input.packages || (Array.isArray(input.packages) || _assertGuard(_exceptionable, {
574
+ method: "typia.createAssert",
575
+ path: _path + ".packages",
576
+ expected: "(Array<string> | undefined)",
577
+ value: input.packages
578
+ }, _errorFactory)) && input.packages.every((elem, _index4) => "string" === typeof elem || _assertGuard(_exceptionable, {
579
+ method: "typia.createAssert",
580
+ path: _path + ".packages[" + _index4 + "]",
581
+ expected: "string",
582
+ value: elem
583
+ }, _errorFactory)) || _assertGuard(_exceptionable, {
584
+ method: "typia.createAssert",
585
+ path: _path + ".packages",
586
+ expected: "(Array<string> | undefined)",
587
+ value: input.packages
588
+ }, _errorFactory)) && (void 0 === input.catalog || ("object" === typeof input.catalog && null !== input.catalog && false === Array.isArray(input.catalog) || _assertGuard(_exceptionable, {
589
+ method: "typia.createAssert",
590
+ path: _path + ".catalog",
591
+ expected: "(Record<string, string> | undefined)",
592
+ value: input.catalog
593
+ }, _errorFactory)) && _ao2(input.catalog, _path + ".catalog", _exceptionable) || _assertGuard(_exceptionable, {
594
+ method: "typia.createAssert",
595
+ path: _path + ".catalog",
596
+ expected: "(Record<string, string> | undefined)",
597
+ value: input.catalog
598
+ }, _errorFactory)) && (void 0 === input.catalogs || ("object" === typeof input.catalogs && null !== input.catalogs && false === Array.isArray(input.catalogs) || _assertGuard(_exceptionable, {
599
+ method: "typia.createAssert",
600
+ path: _path + ".catalogs",
601
+ expected: "(Record<string, Record<string, string>> | undefined)",
602
+ value: input.catalogs
603
+ }, _errorFactory)) && _ao4(input.catalogs, _path + ".catalogs", _exceptionable) || _assertGuard(_exceptionable, {
604
+ method: "typia.createAssert",
605
+ path: _path + ".catalogs",
606
+ expected: "(Record<string, Record<string, string>> | undefined)",
607
+ value: input.catalogs
608
+ }, _errorFactory));
609
+ const _ao4 = (input, _path, _exceptionable = true) => false === _exceptionable || Object.keys(input).every((key) => {
610
+ const value = input[key];
611
+ if (void 0 === value) return true;
612
+ return ("object" === typeof value && null !== value && false === Array.isArray(value) || _assertGuard(_exceptionable, {
613
+ method: "typia.createAssert",
614
+ path: _path + _accessExpressionAsString(key),
615
+ expected: "Record<string, string>",
616
+ value
617
+ }, _errorFactory)) && _ao2(value, _path + _accessExpressionAsString(key), _exceptionable) || _assertGuard(_exceptionable, {
618
+ method: "typia.createAssert",
619
+ path: _path + _accessExpressionAsString(key),
620
+ expected: "Record<string, string>",
621
+ value
622
+ }, _errorFactory);
623
+ });
624
+ const __is = (input) => "object" === typeof input && null !== input && _io0(input);
625
+ let _errorFactory;
626
+ return (input, errorFactory) => {
627
+ if (false === __is(input)) {
628
+ _errorFactory = errorFactory;
629
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _assertGuard(true, {
630
+ method: "typia.createAssert",
631
+ path: _path + "",
632
+ expected: "PackageManifest",
633
+ value: input
634
+ }, _errorFactory)) && _ao0(input, _path + "", true) || _assertGuard(true, {
635
+ method: "typia.createAssert",
636
+ path: _path + "",
637
+ expected: "PackageManifest",
638
+ value: input
639
+ }, _errorFactory))(input, "$input", true);
640
+ }
641
+ return input;
642
+ };
643
+ })();
644
+ const DEP_FIELDS = [
645
+ "dependencies",
646
+ "devDependencies",
647
+ "peerDependencies",
648
+ "optionalDependencies"
649
+ ];
650
+ function listDependencies(graph, pkg) {
651
+ const out = [];
652
+ for (const field of DEP_FIELDS) {
653
+ const table = pkg.manifest[field];
654
+ if (!table) continue;
655
+ for (const [name, raw] of Object.entries(table)) out.push(resolveDependency(graph, pkg, field, name, raw, (range) => {
656
+ table[name] = range;
657
+ }));
658
+ }
659
+ return out;
660
+ }
661
+ function parseDependencySpec(raw) {
662
+ if (raw.startsWith("workspace:")) {
663
+ const body = raw.slice(10);
664
+ if (!body) return {
665
+ protocol: "workspace",
666
+ range: "*"
667
+ };
668
+ if (body.startsWith(".") || body.startsWith("/")) return {
669
+ protocol: "workspace",
670
+ range: body,
671
+ path: body
672
+ };
673
+ const separator = body.lastIndexOf("@");
674
+ if (separator > 0) return {
675
+ protocol: "workspace",
676
+ packageName: body.slice(0, separator),
677
+ range: body.slice(separator + 1) || "*"
678
+ };
679
+ if (separator === 0) return {
680
+ protocol: "workspace",
681
+ packageName: body,
682
+ range: "*"
683
+ };
684
+ return {
685
+ protocol: "workspace",
686
+ range: body
687
+ };
688
+ }
689
+ if (raw.startsWith("file:")) return {
690
+ protocol: "file",
691
+ path: raw.slice(5)
692
+ };
693
+ if (raw.startsWith("portal:")) return {
694
+ protocol: "portal",
695
+ path: raw.slice(7)
696
+ };
697
+ if (raw === "catalog:") return {
698
+ protocol: "catalog",
699
+ catalogName: "default"
700
+ };
701
+ if (raw.startsWith("catalog:")) return {
702
+ protocol: "catalog",
703
+ catalogName: raw.slice(8).trim() || "default"
704
+ };
705
+ if (raw.startsWith("npm:")) {
706
+ const spec = raw.slice(4);
707
+ const separator = spec.lastIndexOf("@");
708
+ if (separator > 0) return {
709
+ protocol: "npm",
710
+ alias: spec.slice(0, separator),
711
+ range: spec.slice(separator + 1)
712
+ };
713
+ }
714
+ return { range: raw };
715
+ }
716
+ function formatDependencySpec(spec, range) {
717
+ switch (spec.protocol) {
718
+ case "workspace":
719
+ if (spec.path) return `workspace:${spec.path}`;
720
+ if (spec.packageName) {
721
+ const next = range ?? spec.range;
722
+ return `workspace:${spec.packageName}@${next}`;
723
+ }
724
+ return `workspace:${range ?? spec.range}`;
725
+ case "file": return `file:${spec.path}`;
726
+ case "portal": return `portal:${spec.path}`;
727
+ case "catalog": return spec.catalogName === "default" ? "catalog:" : `catalog:${spec.catalogName}`;
728
+ case "npm": return `npm:${spec.alias}@${range ?? spec.range}`;
729
+ default: return range ?? spec.range;
730
+ }
731
+ }
732
+ async function resolveNpmGraph(cwd, client) {
733
+ const packages = /* @__PURE__ */ new Map();
734
+ const packagesByPath = /* @__PURE__ */ new Map();
735
+ const catalogSources = [];
736
+ function addPackage(packagePath, manifest) {
737
+ const pkg = new NpmPackage(packagePath, manifest);
738
+ packages.set(pkg.name, pkg);
739
+ packagesByPath.set(packagePath, pkg);
740
+ }
741
+ const patterns = [];
742
+ const rootManifest = await readManifest(cwd).catch(() => void 0);
743
+ if (rootManifest) {
744
+ catalogSources.push(createRootCatalogSource(rootManifest));
745
+ if (rootManifest.name) addPackage(cwd, rootManifest);
746
+ if (Array.isArray(rootManifest.workspaces)) patterns.push(...rootManifest.workspaces);
747
+ else if (rootManifest.workspaces?.packages) patterns.push(...rootManifest.workspaces.packages);
748
+ }
749
+ if (client === "pnpm") {
750
+ const pnpmWorkspacePath = path.join(cwd, "pnpm-workspace.yaml");
751
+ const content = await readFile(pnpmWorkspacePath, "utf8").catch((error) => {
752
+ if (isNodeError(error) && error.code === "ENOENT") return void 0;
753
+ throw error;
754
+ });
755
+ const data = content && assertPnpmWorkspace(parse$1(content));
756
+ if (data) {
757
+ catalogSources.push(createPnpmCatalogSource(pnpmWorkspacePath, data));
758
+ patterns.push(...data.packages ?? []);
759
+ }
760
+ } else if (client === "yarn") {
761
+ const yarnCatalog = await readYarnCatalog(cwd);
762
+ if (yarnCatalog) catalogSources.push(yarnCatalog);
763
+ }
764
+ if (patterns?.length) {
765
+ const candidatePaths = await expandWorkspacePatterns(cwd, patterns);
766
+ await Promise.all(candidatePaths.map(async (packagePath) => {
767
+ const manifest = await readManifest(packagePath).catch(() => void 0);
768
+ if (!manifest) return;
769
+ addPackage(packagePath, manifest);
770
+ }));
771
+ }
772
+ return {
773
+ root: cwd,
774
+ packages,
775
+ packagesByPath,
776
+ catalogs: catalogSources
777
+ };
778
+ }
779
+ function resolveDependency(graph, dependent, field, name, raw, write) {
780
+ const spec = parseDependencySpec(raw);
781
+ const linked = resolveLinkedPackage(graph, dependent, name, spec);
782
+ let range;
783
+ let customSetRange;
784
+ switch (spec.protocol) {
785
+ case "catalog":
786
+ for (const source of graph.catalogs) {
787
+ const resolved = source.resolve(name, spec.catalogName);
788
+ if (!resolved) continue;
789
+ range = resolved;
790
+ customSetRange = (v) => source.setRange(name, spec.catalogName, v);
791
+ break;
792
+ }
793
+ break;
794
+ case "workspace":
795
+ range = semver$1.validRange(spec.range) ? spec.range : void 0;
796
+ break;
797
+ case "npm":
798
+ case void 0:
799
+ range = spec.range;
800
+ break;
801
+ }
802
+ return {
803
+ field,
804
+ name,
805
+ spec,
806
+ linked,
807
+ range,
808
+ setRange(nextRange) {
809
+ if (customSetRange) {
810
+ customSetRange(nextRange);
811
+ return;
812
+ }
813
+ write(formatDependencySpec(spec, nextRange));
814
+ }
815
+ };
816
+ }
817
+ function resolveLinkedPackage(graph, dependent, name, spec) {
818
+ switch (spec.protocol) {
819
+ case "workspace":
820
+ if (spec.path) return findPackageByPath(graph, dependent.path, spec.path);
821
+ return graph.packages.get(spec.packageName || name);
822
+ case "file":
823
+ case "portal": return findPackageByPath(graph, dependent.path, spec.path);
824
+ case "npm": return graph.packages.get(spec.alias);
825
+ default: return graph.packages.get(name);
826
+ }
827
+ }
828
+ function findPackageByPath(graph, from, target) {
829
+ let absolute = path.resolve(from, target);
830
+ if (path.basename(absolute) === "package.json") absolute = path.dirname(absolute);
831
+ return graph.packagesByPath.get(absolute);
832
+ }
833
+ async function expandWorkspacePatterns(cwd, patterns) {
834
+ if (patterns.length === 0) return [];
835
+ return (await glob(patterns, {
836
+ absolute: true,
837
+ cwd,
838
+ ignore: ["**/node_modules/**", "**/dist/**"],
839
+ onlyDirectories: true,
840
+ onlyFiles: false
841
+ })).map((item) => item.endsWith(path.sep) ? item.slice(0, -1) : item);
842
+ }
843
+ async function readManifest(packagePath) {
844
+ const content = await readFile(path.join(packagePath, "package.json"), "utf8");
845
+ const parsed = JSON.parse(content);
846
+ assertPackageManifest(parsed);
847
+ return parsed;
848
+ }
849
+ function createPnpmCatalogSource(filePath, workspace) {
850
+ return {
851
+ resolve(name, catalogName) {
852
+ if (catalogName === "default") return workspace.catalog?.[name];
853
+ return workspace.catalogs?.[catalogName]?.[name];
854
+ },
855
+ setRange(name, catalogName, range) {
856
+ if (catalogName === "default") {
857
+ workspace.catalog ??= {};
858
+ workspace.catalog[name] = range;
859
+ } else {
860
+ workspace.catalogs ??= {};
861
+ workspace.catalogs[catalogName] ??= {};
862
+ workspace.catalogs[catalogName][name] = range;
863
+ }
864
+ },
865
+ async write() {
866
+ await writeFile(filePath, `${stringify(workspace, { lineWidth: 0 }).trim()}\n`);
867
+ }
868
+ };
869
+ }
870
+ function createRootCatalogSource(manifest) {
871
+ return {
872
+ resolve(name, catalogName) {
873
+ const fromWorkspaces = typeof manifest.workspaces === "object" && !Array.isArray(manifest.workspaces) ? catalogName === "default" ? manifest.workspaces.catalog?.[name] : manifest.workspaces.catalogs?.[catalogName]?.[name] : void 0;
874
+ if (fromWorkspaces) return fromWorkspaces;
875
+ if (catalogName === "default") return manifest.catalog?.[name];
876
+ return manifest.catalogs?.[catalogName]?.[name];
877
+ },
878
+ setRange(name, catalogName, range) {
879
+ if (typeof manifest.workspaces === "object" && !Array.isArray(manifest.workspaces)) if (catalogName === "default") {
880
+ manifest.workspaces.catalog ??= {};
881
+ manifest.workspaces.catalog[name] = range;
882
+ } else {
883
+ manifest.workspaces.catalogs ??= {};
884
+ manifest.workspaces.catalogs[catalogName] ??= {};
885
+ manifest.workspaces.catalogs[catalogName][name] = range;
886
+ }
887
+ else if (catalogName === "default") {
888
+ manifest.catalog ??= {};
889
+ manifest.catalog[name] = range;
890
+ } else {
891
+ manifest.catalogs ??= {};
892
+ manifest.catalogs[catalogName] ??= {};
893
+ manifest.catalogs[catalogName][name] = range;
894
+ }
895
+ }
896
+ };
897
+ }
898
+ async function readYarnCatalog(cwd) {
899
+ const filePath = path.join(cwd, ".yarnrc.yml");
900
+ const content = await readFile(filePath, "utf8").catch(() => void 0);
901
+ if (!content) return;
902
+ const doc = parseDocument(content);
903
+ return {
904
+ resolve(name, catalogName) {
905
+ const value = doc.getIn(catalogName === "default" ? ["catalog", name] : [
906
+ "catalogs",
907
+ catalogName,
908
+ name
909
+ ]);
910
+ return typeof value === "string" ? value : void 0;
911
+ },
912
+ setRange(name, catalogName, range) {
913
+ doc.setIn(catalogName === "default" ? ["catalog", name] : [
914
+ "catalogs",
915
+ catalogName,
916
+ name
917
+ ], range);
918
+ },
919
+ async write() {
920
+ const output = doc.toString();
921
+ await writeFile(filePath, output.endsWith("\n") ? output : `${output}\n`);
922
+ }
923
+ };
924
+ }
925
+ //#endregion
926
+ //#region src/providers/npm.ts
927
+ const validateNpmPackageLock = (() => {
928
+ const _io0 = (input) => "string" === typeof input.id && (void 0 === input.distTag || "string" === typeof input.distTag);
929
+ const _vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.id || _report(_exceptionable, {
930
+ path: _path + ".id",
931
+ expected: "string",
932
+ value: input.id
933
+ }), void 0 === input.distTag || "string" === typeof input.distTag || _report(_exceptionable, {
934
+ path: _path + ".distTag",
935
+ expected: "(string | undefined)",
936
+ value: input.distTag
937
+ })].every((flag) => flag);
938
+ const __is = (input) => "object" === typeof input && null !== input && _io0(input);
939
+ let errors;
940
+ let _report;
941
+ return _createStandardSchema((input) => {
942
+ if (false === __is(input)) {
943
+ errors = [];
944
+ _report = _validateReport(errors);
945
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
946
+ path: _path + "",
947
+ expected: "NpmPackageLock",
948
+ value: input
949
+ })) && _vo0(input, _path + "", true) || _report(true, {
950
+ path: _path + "",
951
+ expected: "NpmPackageLock",
952
+ value: input
953
+ }))(input, "$input", true);
954
+ const success = 0 === errors.length;
955
+ return success ? {
956
+ success,
957
+ data: input
958
+ } : {
959
+ success,
960
+ errors,
961
+ data: input
962
+ };
963
+ }
964
+ return {
965
+ success: true,
966
+ data: input
967
+ };
968
+ });
969
+ })();
970
+ const validateNpmMarkLatestLock = (() => {
971
+ const _io0 = (input) => "string" === typeof input.id;
972
+ const _vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.id || _report(_exceptionable, {
973
+ path: _path + ".id",
974
+ expected: "string",
975
+ value: input.id
976
+ })].every((flag) => flag);
977
+ const __is = (input) => "object" === typeof input && null !== input && _io0(input);
978
+ let errors;
979
+ let _report;
980
+ return _createStandardSchema((input) => {
981
+ if (false === __is(input)) {
982
+ errors = [];
983
+ _report = _validateReport(errors);
984
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
985
+ path: _path + "",
986
+ expected: "NpmMarkLatestLock",
987
+ value: input
988
+ })) && _vo0(input, _path + "", true) || _report(true, {
989
+ path: _path + "",
990
+ expected: "NpmMarkLatestLock",
991
+ value: input
992
+ }))(input, "$input", true);
993
+ const success = 0 === errors.length;
994
+ return success ? {
995
+ success,
996
+ data: input
997
+ } : {
998
+ success,
999
+ errors,
1000
+ data: input
1001
+ };
1002
+ }
1003
+ return {
1004
+ success: true,
1005
+ data: input
1006
+ };
1007
+ });
1008
+ })();
1009
+ function npm({ client: defaultClient, onBreakPeerDep = "set", updateLockFile = true, trustedPublish, bumpDep: getBumpDepType = ({ kind }) => {
1010
+ switch (kind) {
1011
+ case "dependencies":
1012
+ case "optionalDependencies": return "patch";
1013
+ case "devDependencies": return false;
1014
+ case "peerDependencies":
1015
+ if (onBreakPeerDep === "ignore") return false;
1016
+ return "major";
1017
+ }
1018
+ } } = {}) {
1019
+ let active = false;
1020
+ let client;
1021
+ return {
1022
+ name: "npm",
1023
+ enforce: "pre",
1024
+ async init() {
1025
+ if (defaultClient) client = defaultClient;
1026
+ else client = (await detect({ cwd: this.cwd }))?.name ?? "npm";
1027
+ this.npm = { client };
1028
+ },
1029
+ async resolve() {
1030
+ if (!this.npm) return;
1031
+ const graph = await resolveNpmGraph(this.cwd, this.npm.client);
1032
+ if (graph.packages.size === 0) return;
1033
+ this.npm.graph = graph;
1034
+ for (const pkg of graph.packages.values()) this.graph.add(pkg);
1035
+ active = true;
1036
+ },
1037
+ async publishPreflight({ pkg }) {
1038
+ if (!(pkg instanceof NpmPackage)) return;
1039
+ return { shouldPublish: pkg.version !== void 0 && pkg.manifest.private !== true };
1040
+ },
1041
+ resolvePlanStatus({ plan }) {
1042
+ if (!active) return;
1043
+ return Array.from(plan.packages, async ([id, { preflight }]) => {
1044
+ if (!preflight.shouldPublish) return;
1045
+ const pkg = this.graph.get(id);
1046
+ if (!(pkg instanceof NpmPackage) || !pkg.version) return;
1047
+ if (!await isPackagePublished(pkg.name, pkg.version, pkg.getRegistry())) return "pending";
1048
+ });
1049
+ },
1050
+ initPublishLock({ lock, draft }) {
1051
+ for (const [id, pkg] of draft.getPackageDrafts()) {
1052
+ if (!pkg.npm) continue;
1053
+ lock.write("npm:packages", {
1054
+ id,
1055
+ distTag: pkg.npm.distTag
1056
+ });
1057
+ }
1058
+ },
1059
+ initPublishPlan({ lock, plan }) {
1060
+ let data;
1061
+ while (data = lock.read("npm:packages")) {
1062
+ const validated = validateNpmPackageLock(data);
1063
+ if (!validated.success) continue;
1064
+ const parsed = validated.data;
1065
+ const packagePlan = plan.packages.get(parsed.id);
1066
+ if (!packagePlan) continue;
1067
+ packagePlan.npm = { distTag: parsed.distTag };
1068
+ }
1069
+ while (data = lock.read("npm:mark-latest")) {
1070
+ const validated = validateNpmMarkLatestLock(data);
1071
+ if (!validated.success) continue;
1072
+ const parsed = validated.data;
1073
+ const packagePlan = plan.packages.get(parsed.id);
1074
+ if (!packagePlan) continue;
1075
+ packagePlan.npm ??= {};
1076
+ packagePlan.npm.markLatest = true;
1077
+ }
1078
+ },
1079
+ async publish({ pkg, plan }) {
1080
+ if (!(pkg instanceof NpmPackage)) return;
1081
+ const { distTag, markLatest } = plan.packages.get(pkg.id)?.npm ?? {};
1082
+ const result = await publish(client, pkg, distTag);
1083
+ if (result.type === "published" && markLatest) {
1084
+ const tagResult = await x("npm", [
1085
+ "dist-tag",
1086
+ "add",
1087
+ `${pkg.name}@${pkg.version}`,
1088
+ "latest",
1089
+ "--registry",
1090
+ pkg.getRegistry()
1091
+ ], { nodeOptions: { cwd: pkg.path } });
1092
+ if (tagResult.exitCode !== 0) return {
1093
+ type: "failed",
1094
+ error: execFailure("Failed to mark package as latest", tagResult).message
1095
+ };
1096
+ }
1097
+ return result;
1098
+ },
1099
+ initDraft(plan) {
1100
+ if (!active) return;
1101
+ plan.addPolicy(depsPolicy(this, getBumpDepType));
1102
+ },
1103
+ async applyDraft(draft) {
1104
+ if (!active || !this.npm?.graph) return;
1105
+ const npmGraph = this.npm.graph;
1106
+ const writes = [];
1107
+ for (const pkg of npmGraph.packages.values()) {
1108
+ const bumped = draft.getPackageDraft(pkg.id)?.bumpVersion(pkg);
1109
+ if (bumped) pkg.manifest.version = bumped;
1110
+ }
1111
+ for (const pkg of npmGraph.packages.values()) {
1112
+ for (const dep of pkg.listDependencies(npmGraph)) {
1113
+ if (!dep.linked || !dep.range || !dep.setRange) continue;
1114
+ if (!dep.linked.version || semver$1.satisfies(dep.linked.version, dep.range)) continue;
1115
+ const isPeer = dep.field === "peerDependencies";
1116
+ if (isPeer && onBreakPeerDep === "ignore") continue;
1117
+ let updatedRange;
1118
+ if (isPeer && onBreakPeerDep === "set") updatedRange = dep.linked.version;
1119
+ else if (isPeer && onBreakPeerDep === "error") throw new Error(`[Tegami] the version of "${dep.linked.name}" is beyond its peer dependency constraint "${formatDependencySpec(dep.spec)}" in package "${pkg.name}", please update the constraint to satisfy.`);
1120
+ else if (dep.range.startsWith("^")) updatedRange = `^${dep.linked.version}`;
1121
+ else if (dep.range.startsWith("~")) updatedRange = `~${dep.linked.version}`;
1122
+ else updatedRange = dep.linked.version;
1123
+ dep.setRange(updatedRange);
1124
+ }
1125
+ writes.push(pkg.write());
1126
+ }
1127
+ for (const source of npmGraph.catalogs) writes.push(source.write?.());
1128
+ await Promise.all(writes);
1129
+ },
1130
+ async applyCliDraft() {
1131
+ if (!active || !updateLockFile) return;
1132
+ const result = await x(client, ["install"], { nodeOptions: { cwd: this.cwd } });
1133
+ if (result.exitCode !== 0) throw execFailure("Failed to update lockfile.", result);
1134
+ },
1135
+ initCli(cli) {
1136
+ if (!trustedPublish) return;
1137
+ registerNpmCli(cli, trustedPublish);
1138
+ }
1139
+ };
1140
+ }
1141
+ function depsPolicy(context, getBumpDepType) {
1142
+ const npmGraph = context.npm?.graph;
1143
+ if (!npmGraph) throw new Error("npm graph is missing");
1144
+ const dependentMap = /* @__PURE__ */ new Map();
1145
+ for (const pkg of npmGraph.packages.values()) for (const resolved of pkg.listDependencies(npmGraph)) {
1146
+ if (!resolved.linked) continue;
1147
+ const refs = dependentMap.get(resolved.linked.id);
1148
+ const ref = {
1149
+ dependent: pkg,
1150
+ kind: resolved.field,
1151
+ name: resolved.name,
1152
+ spec: resolved.spec,
1153
+ resolved
1154
+ };
1155
+ if (refs) refs.push(ref);
1156
+ else dependentMap.set(resolved.linked.id, [ref]);
1157
+ }
1158
+ function needsDependencyUpdate(resolved, target) {
1159
+ if (!resolved.linked) return false;
1160
+ switch (resolved.spec.protocol) {
1161
+ case "file":
1162
+ case "portal": return true;
1163
+ case "workspace": switch (resolved.spec.range) {
1164
+ case "":
1165
+ case "*": return true;
1166
+ case "^":
1167
+ case "~": return !semver$1.satisfies(target, `${resolved.spec.range}${resolved.linked.version ?? "0.0.0"}`);
1168
+ }
1169
+ }
1170
+ if (!resolved.range || !semver$1.validRange(resolved.range)) return false;
1171
+ return !semver$1.satisfies(target, resolved.range);
1172
+ }
1173
+ return {
1174
+ id: "npm:deps",
1175
+ onUpdate({ pkg, packageDraft: plan }) {
1176
+ if (!(pkg instanceof NpmPackage)) return;
1177
+ const deps = dependentMap.get(pkg.id);
1178
+ if (!deps) return;
1179
+ const bumped = plan.bumpVersion(pkg);
1180
+ if (!bumped) return;
1181
+ for (const dep of deps) {
1182
+ if (pkg.group?.options.syncBump && dep.dependent.group === pkg.group) continue;
1183
+ if (!needsDependencyUpdate(dep.resolved, bumped)) continue;
1184
+ const bumpType = getBumpDepType(dep);
1185
+ if (bumpType === false) continue;
1186
+ this.bumpPackage(dep.dependent, {
1187
+ type: bumpType,
1188
+ reason: `update dependency "${dep.name}"`
1189
+ });
1190
+ }
1191
+ }
1192
+ };
1193
+ }
1194
+ async function publish(client, pkg, distTag) {
1195
+ if (!pkg.version || await isPackagePublished(pkg.name, pkg.version, pkg.getRegistry())) return { type: "skipped" };
1196
+ if (client === "bun") {
1197
+ for (const script of [
1198
+ "prepublishOnly",
1199
+ "prepack",
1200
+ "prepare"
1201
+ ]) {
1202
+ if (!pkg.manifest.scripts?.[script]) continue;
1203
+ const result = await x("bun", ["run", script], { nodeOptions: { cwd: pkg.path } });
1204
+ if (result.exitCode === 0) continue;
1205
+ return {
1206
+ type: "failed",
1207
+ error: execFailure(`Failed to run ${script} script for ${pkg.name}@${pkg.version}.`, result).message
1208
+ };
1209
+ }
1210
+ const tarballPath = path.resolve(pkg.path, "pkg.tgz");
1211
+ const packResult = await x("bun", [
1212
+ "pm",
1213
+ "pack",
1214
+ "--filename",
1215
+ tarballPath
1216
+ ], { nodeOptions: { cwd: pkg.path } });
1217
+ if (packResult.exitCode !== 0) return {
1218
+ type: "failed",
1219
+ error: execFailure(`Failed to pack ${pkg.name}@${pkg.version}.`, packResult).message
1220
+ };
1221
+ const publishArgs = ["publish", tarballPath];
1222
+ if (distTag) publishArgs.push("--tag", distTag);
1223
+ const publishResult = await x("npm", publishArgs, { nodeOptions: { cwd: pkg.path } });
1224
+ if (publishResult.exitCode !== 0) return {
1225
+ type: "failed",
1226
+ error: execFailure(`Failed to publish ${pkg.name}@${pkg.version}${distTag ? ` with dist-tag "${distTag}"` : ""}.`, publishResult).message
1227
+ };
1228
+ return { type: "published" };
1229
+ }
1230
+ let command;
1231
+ const args = ["publish"];
1232
+ if (distTag) args.push("--tag", distTag);
1233
+ if (client === "pnpm") {
1234
+ command = "pnpm";
1235
+ args.push("--no-git-checks");
1236
+ } else if (client === "yarn") command = "yarn";
1237
+ else command = "npm";
1238
+ const result = await x(command, args, { nodeOptions: { cwd: pkg.path } });
1239
+ if (result.exitCode !== 0) return {
1240
+ type: "failed",
1241
+ error: execFailure(`Failed to publish ${pkg.name}@${pkg.version}${distTag ? ` with dist-tag "${distTag}"` : ""}.`, result).message
1242
+ };
1243
+ return { type: "published" };
1244
+ }
1245
+ async function isPackagePublished(name, version, registry) {
1246
+ const response = await fetch(joinPath(registry, name, version), { headers: { Accept: "application/json" } });
1247
+ if (response.status === 404) return false;
1248
+ if (!response.ok) throw new Error(`Unable to validate ${name}@${version} against the npm registry${registry ? ` "${registry}"` : ""}.`);
1249
+ return true;
1250
+ }
1251
+ //#endregion
1252
+ export { runPreflights as a, publishPlanStatus as i, NpmPackage as n, runPublishPlan as o, initPublishPlan as r, npm as t };