@schlenkr/ragents 0.1.17 → 0.1.19

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.
@@ -1,144 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { compareVersions, readVersion, releaseVersion, versionLine, writeHostPackageVersion, writeVersion } from "../publish-version.ts";
5
- import { buildPackage, PACKAGE_FOLDER, PACKAGE_NAME } from "./build-package.ts";
6
-
7
- const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
8
-
9
- const usage = `Usage: pnpm publish:package [--dry-run]
10
- Builds the package ${PACKAGE_NAME} and publishes it on npm. The token comes from the
11
- environment variable npm_key. --dry-run passes the dry run through to npm and publishes nothing.
12
- The version is in the root package.json; before building, the script raises the last place
13
- above the last published version, in a dry run only in the output.`;
14
-
15
- const REGISTRY_TOKEN_KEY = "npm_config_//registry.npmjs.org/:_authToken";
16
-
17
- export interface NpmResult {
18
- readonly status: number;
19
- readonly stdout: string;
20
- readonly stderr: string;
21
- }
22
-
23
- export type NpmRunner = (args: readonly string[], options: { cwd: string; token?: string }) => NpmResult;
24
-
25
- /** The token goes only as configuration into the child process's environment, never onto the command line. */
26
- export const publishEnvironment = (token: string, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv =>
27
- ({ ...base, [REGISTRY_TOKEN_KEY]: token });
28
-
29
- /** Everything that comes from npm goes through this mask so that the token does not show up even in an error message. */
30
- export const redacting = (token: string) => (text: string): string => token ? text.split(token).join("<npm_key>") : text;
31
-
32
- /** An error message is one line; npm's output is therefore moved onto one. */
33
- export const oneLine = (text: string): string => text.split("\n").map((line) => line.trim()).filter(Boolean).join("; ");
34
-
35
- const runNpm: NpmRunner = (args, options) => {
36
- const result = spawnSync("npm", [...args], {
37
- cwd: options.cwd,
38
- encoding: "utf8",
39
- env: options.token ? publishEnvironment(options.token) : process.env,
40
- stdio: ["ignore", "pipe", "pipe"],
41
- });
42
- if (result.error) throw new Error(`npm ${args[0]} could not be started: ${result.error.message}`);
43
- return { status: result.status ?? 1, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
44
- };
45
-
46
- /** The versions already on npm; a package unknown there is the empty list, not an error. */
47
- export const publishedVersions = (name: string, npm: NpmRunner): readonly string[] => {
48
- const result = npm(["view", name, "versions", "--json"], { cwd: repositoryRoot });
49
- if (result.status !== 0) {
50
- if (/E404|404 Not Found/.test(`${result.stdout}\n${result.stderr}`)) return [];
51
- throw new Error(`npm view ${name} versions ended with code ${result.status}: ${oneLine(result.stderr)}`);
52
- }
53
- const parsed = JSON.parse(result.stdout.trim() || "[]") as string | readonly string[];
54
- return typeof parsed === "string" ? [parsed] : parsed;
55
- };
56
-
57
- /** The highest version on npm; a package unknown there has none. */
58
- export const latestPublishedVersion = (npm: NpmRunner = runNpm, name = PACKAGE_NAME): string | undefined =>
59
- [...publishedVersions(name, npm)].sort(compareVersions).at(-1);
60
-
61
- export interface PublishPlan {
62
- readonly name: string;
63
- readonly version: string;
64
- readonly hostVersion: string;
65
- }
66
-
67
- /** What must be right before a publish: the built manifest and a version that does not yet exist on npm. */
68
- export const publishPlan = (manifest: Record<string, unknown>, published: readonly string[], version: string): PublishPlan => {
69
- const { name } = manifest as { name?: unknown };
70
- const access = (manifest.publishConfig as { access?: unknown } | undefined)?.access;
71
- const hostVersion = (manifest.ragents as { hostVersion?: unknown } | undefined)?.hostVersion;
72
- if (name !== PACKAGE_NAME) throw new Error(`The built package is named ${String(name)}, but ${PACKAGE_NAME} is published`);
73
- if (access !== "public") throw new Error(`${PACKAGE_NAME} has a scope and needs publishConfig.access "public", not ${JSON.stringify(access)}`);
74
- if (!/^\d+\.\d+\.\d+(?:-[0-9a-z.-]+)?$/.test(version)) {
75
- throw new Error(`The version ${JSON.stringify(version)} is not a version; it is the version in the root package.json`);
76
- }
77
- if (typeof hostVersion !== "string" || !/^[0-9a-f]{40}$/.test(hostVersion)) {
78
- throw new Error("The package lacks ragents.hostVersion as a full Git commit; it is built only from a checkout");
79
- }
80
- if (published.includes(version)) {
81
- throw new Error(`${PACKAGE_NAME}@${version} is already on npm (there: ${published.join(", ")}); `
82
- + "raise version in the root package.json and rebuild");
83
- }
84
- return { name: PACKAGE_NAME, version, hostVersion };
85
- };
86
-
87
- export interface PublishOptions {
88
- readonly directory: string;
89
- readonly version: string;
90
- readonly token: string;
91
- readonly dryRun: boolean;
92
- readonly npm: NpmRunner;
93
- readonly log: (line: string) => void;
94
- }
95
-
96
- /** npm reports a missing organization as 404; without the hint you look for the error in the package. */
97
- const scopeAdvice = (output: string): string => /Scope not found/i.test(output)
98
- ? ` The organization ${PACKAGE_NAME.split("/")[0]} does not exist on npm or the token may not use it: `
99
- + "create it on npmjs.com or grant the token access to the scope."
100
- : "";
101
-
102
- /** Publishes the built folder; exit 0 of npm publish is the confirmation. */
103
- export const publishDirectory = (options: PublishOptions): void => {
104
- const hide = redacting(options.token);
105
- const published = options.npm(["publish", "--access", "public", ...options.dryRun ? ["--dry-run"] : []], { cwd: options.directory, token: options.token });
106
- const output = `${published.stdout}${published.stderr}`;
107
- for (const line of output.split("\n")) if (line.trim()) options.log(hide(line));
108
- if (published.status !== 0) throw new Error(`npm publish ended with code ${published.status}.${scopeAdvice(output)}`);
109
- if (options.dryRun) {
110
- options.log("== Dry run: nothing published");
111
- return;
112
- }
113
- options.log(`== Published: ${PACKAGE_NAME}@${options.version}`);
114
- };
115
-
116
- const main = async (): Promise<void> => {
117
- const dryRun = process.argv.includes("--dry-run");
118
- const unknown = process.argv.slice(2).filter((argument) => argument !== "--dry-run");
119
- if (unknown.length) throw new Error(`Unknown argument: ${unknown.join(" ")}\n${usage}`);
120
- const token = process.env.npm_key;
121
- if (!token) throw new Error(`npm_key is missing: the npm token with write access to ${PACKAGE_NAME}.\n${usage}`);
122
- const manifestFile = path.join(repositoryRoot, "package.json");
123
- const published = publishedVersions(PACKAGE_NAME, runNpm);
124
- const extensionManifestFile = path.join(repositoryRoot, "apps", "vscode", "package.json");
125
- const next = releaseVersion([readVersion(manifestFile), readVersion(extensionManifestFile)], published);
126
- console.log(versionLine(next));
127
- if (!dryRun) {
128
- writeVersion(manifestFile, next.version);
129
- writeVersion(extensionManifestFile, next.version);
130
- writeHostPackageVersion(extensionManifestFile, next.version);
131
- }
132
- const built = await buildPackage(path.join(repositoryRoot, "dist", PACKAGE_FOLDER));
133
- const plan = publishPlan(built.manifest, published, next.version);
134
- console.log(`== ${plan.name}@${plan.version} from host ${plan.hostVersion.slice(0, 12)}, ${built.fileCount} files, ${(built.byteSize / 1024 / 1024).toFixed(1)} MB`);
135
- publishDirectory({ directory: built.directory, version: plan.version, token, dryRun, npm: runNpm, log: (line) => console.log(line) });
136
- };
137
-
138
- const moduleUrl: string | undefined = import.meta.url;
139
- if (moduleUrl && process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(moduleUrl)) {
140
- main().catch((error: unknown) => {
141
- console.error(error instanceof Error ? error.message : String(error));
142
- process.exit(1);
143
- });
144
- }