mirror of
https://github.com/oven-sh/setup-bun.git
synced 2025-07-18 04:28:28 +02:00
feat: use @iarna/toml
This commit is contained in:
parent
2db092bddd
commit
7a1e37eece
4 changed files with 152 additions and 173 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -27,7 +27,8 @@
|
||||||
"@actions/exec": "^1.1.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"@actions/glob": "^0.4.0",
|
"@actions/glob": "^0.4.0",
|
||||||
"@actions/io": "^1.1.2",
|
"@actions/io": "^1.1.2",
|
||||||
"@actions/tool-cache": "^2.0.1"
|
"@actions/tool-cache": "^2.0.1",
|
||||||
|
"@iarna/toml": "^2.2.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.1.13",
|
"@types/bun": "^1.1.13",
|
||||||
|
|
207
src/bunfig.ts
207
src/bunfig.ts
|
@ -1,6 +1,6 @@
|
||||||
import { EOL } from "node:os";
|
|
||||||
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
||||||
import { info } from "@actions/core";
|
import { info } from "@actions/core";
|
||||||
|
import { parse, stringify } from "@iarna/toml";
|
||||||
|
|
||||||
export type Registry = {
|
export type Registry = {
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -8,164 +8,79 @@ export type Registry = {
|
||||||
token?: string;
|
token?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FieldType {
|
type BunfigConfig = {
|
||||||
GLOBAL_REGISTRY,
|
install?: {
|
||||||
INSTALL_WITH_SCOPE,
|
registry?: {
|
||||||
}
|
url: string;
|
||||||
|
token?: string;
|
||||||
type Field = {
|
};
|
||||||
type: FieldType;
|
scopes?: Record<string, { url: string; token?: string }>;
|
||||||
value: string;
|
};
|
||||||
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createField(registry: Registry): Field {
|
|
||||||
const { url: registryUrl, scope, token } = registry;
|
|
||||||
|
|
||||||
let url: URL | undefined;
|
|
||||||
if (registryUrl) {
|
|
||||||
try {
|
|
||||||
url = new URL(registryUrl);
|
|
||||||
} catch {
|
|
||||||
throw new Error(`Invalid registry url ${registryUrl}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let owner: string | undefined;
|
|
||||||
if (scope) {
|
|
||||||
owner = scope.startsWith("@")
|
|
||||||
? scope.toLocaleLowerCase()
|
|
||||||
: `@${scope.toLocaleLowerCase()}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url && owner) {
|
|
||||||
return {
|
|
||||||
type: FieldType.INSTALL_WITH_SCOPE,
|
|
||||||
value: `'${owner}' = { url = "${url}"${
|
|
||||||
token ? `, token = "${token}"` : ""
|
|
||||||
} }`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url && !owner) {
|
|
||||||
return {
|
|
||||||
type: FieldType.GLOBAL_REGISTRY,
|
|
||||||
value: `registry = "${url}"`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBunfig(registries: Registry[]): Field[] | null {
|
|
||||||
const fields = registries.map(createField).filter((field) => field);
|
|
||||||
if (fields.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
fields.filter((field) => field.type === FieldType.GLOBAL_REGISTRY).length >
|
|
||||||
1
|
|
||||||
) {
|
|
||||||
throw new Error("You can't have more than one global registry.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function serializeInstallScopes(
|
|
||||||
fields: Field[],
|
|
||||||
header: boolean = false
|
|
||||||
): string {
|
|
||||||
const installScopes = fields
|
|
||||||
.filter((field) => field.type === FieldType.INSTALL_WITH_SCOPE)
|
|
||||||
.map((field) => field.value)
|
|
||||||
.join(EOL);
|
|
||||||
|
|
||||||
if (!installScopes) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${header ? `[install.scopes]${EOL}` : ""}${installScopes}${EOL}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function serializeGlobalRegistry(
|
|
||||||
fields: Field[],
|
|
||||||
header: boolean = false
|
|
||||||
): string {
|
|
||||||
const globalRegistry = fields
|
|
||||||
.filter((field) => field.type === FieldType.GLOBAL_REGISTRY)
|
|
||||||
.map((field) => field.value)
|
|
||||||
.join(EOL);
|
|
||||||
|
|
||||||
if (!globalRegistry) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${header ? `[install]${EOL}` : ""}${globalRegistry}${EOL}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function writeBunfig(path: string, registries: Registry[]): void {
|
export function writeBunfig(path: string, registries: Registry[]): void {
|
||||||
const bunfig = createBunfig(registries);
|
if (!registries.length) {
|
||||||
if (!bunfig) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let globalRegistryCount = 0;
|
||||||
|
registries.forEach((registry) => {
|
||||||
|
try {
|
||||||
|
new URL(registry.url);
|
||||||
|
} catch {
|
||||||
|
throw new Error(`Invalid registry URL: ${registry.url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!registry.scope) {
|
||||||
|
globalRegistryCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (globalRegistryCount > 1) {
|
||||||
|
throw new Error("You can't have more than one global registry.");
|
||||||
|
}
|
||||||
|
|
||||||
info(`Writing bunfig.toml to '${path}'.`);
|
info(`Writing bunfig.toml to '${path}'.`);
|
||||||
|
|
||||||
if (!existsSync(path)) {
|
let config: BunfigConfig = {};
|
||||||
writeFileSync(
|
if (existsSync(path)) {
|
||||||
path,
|
try {
|
||||||
`${serializeGlobalRegistry(bunfig, true)}${serializeInstallScopes(
|
const content = readFileSync(path, { encoding: "utf-8" });
|
||||||
bunfig,
|
config = parse(content) as BunfigConfig;
|
||||||
true
|
} catch (error) {
|
||||||
)}`,
|
info(`Error reading existing bunfig: ${error.message}`);
|
||||||
{
|
config = {};
|
||||||
encoding: "utf8",
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let newContent = "";
|
config.install = config?.install || {};
|
||||||
const contents = readFileSync(path, {
|
config.install.scopes = config?.install.scopes || {};
|
||||||
encoding: "utf-8",
|
|
||||||
}).split(EOL);
|
|
||||||
|
|
||||||
contents.forEach((line, index, array) => {
|
const globalRegistry = registries.find((r) => !r.scope);
|
||||||
if (index > 0 && array[index - 1].includes("[install.scopes]")) {
|
if (globalRegistry) {
|
||||||
newContent += serializeInstallScopes(bunfig);
|
config.install.registry = {
|
||||||
}
|
url: globalRegistry.url,
|
||||||
|
...(globalRegistry.token ? { token: globalRegistry.token } : {}),
|
||||||
if (index > 0 && array[index - 1].includes("[install]")) {
|
};
|
||||||
newContent += serializeGlobalRegistry(bunfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
line.startsWith("registry = ") ||
|
|
||||||
!bunfig.some(
|
|
||||||
(field) =>
|
|
||||||
field.type === FieldType.INSTALL_WITH_SCOPE &&
|
|
||||||
(line.startsWith(field.value.split(" ")[0]) ||
|
|
||||||
((line[0] === "'" || line[0] === '"') &&
|
|
||||||
line
|
|
||||||
.toLowerCase()
|
|
||||||
.startsWith(field.value.split(" ")[0].slice(1).slice(0, -1))))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
newContent += line + EOL;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!contents.includes("[install.scopes]")) {
|
|
||||||
newContent += serializeInstallScopes(bunfig, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contents.includes("[install]")) {
|
for (const registry of registries) {
|
||||||
newContent += serializeGlobalRegistry(bunfig, true);
|
if (registry.scope) {
|
||||||
|
const scopeName = registry.scope.startsWith("@")
|
||||||
|
? registry.scope.toLowerCase()
|
||||||
|
: `@${registry.scope.toLowerCase()}`;
|
||||||
|
|
||||||
|
config.install.scopes[scopeName] = {
|
||||||
|
url: registry.url,
|
||||||
|
...(registry.token ? { token: registry.token } : {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(path, newContent, {
|
if (Object.keys(config.install.scopes).length === 0) {
|
||||||
encoding: "utf8",
|
delete config.install.scopes;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
writeFileSync(path, stringify(config), { encoding: "utf8" });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { afterEach, describe, expect, it } from "bun:test";
|
import { afterEach, describe, expect, it } from "bun:test";
|
||||||
import { unlinkSync } from "node:fs";
|
import { existsSync, unlinkSync } from "node:fs";
|
||||||
import { writeBunfig } from "../src/bunfig";
|
import { writeBunfig } from "../src/bunfig";
|
||||||
import { EOL } from "os";
|
import { EOL } from "os";
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ describe("writeBunfig", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
unlinkSync(filePath);
|
if (existsSync(filePath)) unlinkSync(filePath);
|
||||||
console.log(`${filePath} was deleted`);
|
console.log(`${filePath} was deleted`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,8 +33,9 @@ describe("writeBunfig", () => {
|
||||||
expect(file.exists()).resolves.toBeTrue();
|
expect(file.exists()).resolves.toBeTrue();
|
||||||
|
|
||||||
const expectedContents = [
|
const expectedContents = [
|
||||||
"[install.scopes]",
|
'[install.scopes."@foo-bar"]',
|
||||||
'\'@foo-bar\' = { url = "https://npm.pkg.github.com/", token = "$BUN_AUTH_TOKEN" }',
|
'url = "https://npm.pkg.github.com"',
|
||||||
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -46,6 +47,31 @@ describe("writeBunfig", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should create a new file with global registry", async () => {
|
it("should create a new file with global registry", async () => {
|
||||||
|
writeBunfig(filePath, [
|
||||||
|
{
|
||||||
|
url: "https://npm.pkg.github.com",
|
||||||
|
scope: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { file, contents } = await getFileAndContents();
|
||||||
|
|
||||||
|
expect(file.exists()).resolves.toBeTrue();
|
||||||
|
|
||||||
|
const expectedContents = [
|
||||||
|
"[install.registry]",
|
||||||
|
'url = "https://npm.pkg.github.com"',
|
||||||
|
"",
|
||||||
|
];
|
||||||
|
|
||||||
|
contents.forEach((content, index) =>
|
||||||
|
expect(content).toBe(expectedContents[index])
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(contents.length).toBe(expectedContents.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create a new file with global registry & token", async () => {
|
||||||
writeBunfig(filePath, [
|
writeBunfig(filePath, [
|
||||||
{
|
{
|
||||||
url: "https://npm.pkg.github.com",
|
url: "https://npm.pkg.github.com",
|
||||||
|
@ -59,8 +85,9 @@ describe("writeBunfig", () => {
|
||||||
expect(file.exists()).resolves.toBeTrue();
|
expect(file.exists()).resolves.toBeTrue();
|
||||||
|
|
||||||
const expectedContents = [
|
const expectedContents = [
|
||||||
"[install]",
|
"[install.registry]",
|
||||||
'registry = "https://npm.pkg.github.com/"',
|
'url = "https://npm.pkg.github.com"',
|
||||||
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -94,10 +121,12 @@ describe("writeBunfig", () => {
|
||||||
"[install]",
|
"[install]",
|
||||||
"optional = true",
|
"optional = true",
|
||||||
"",
|
"",
|
||||||
"[install.cache]",
|
" [install.cache]",
|
||||||
"disable = true",
|
" disable = true",
|
||||||
"[install.scopes]",
|
"",
|
||||||
'\'@foo-bar\' = { url = "https://npm.pkg.github.com/", token = "$BUN_AUTH_TOKEN" }',
|
'[install.scopes."@foo-bar"]',
|
||||||
|
'url = "https://npm.pkg.github.com"',
|
||||||
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -129,12 +158,16 @@ describe("writeBunfig", () => {
|
||||||
"[install]",
|
"[install]",
|
||||||
"optional = true",
|
"optional = true",
|
||||||
"",
|
"",
|
||||||
"[install.scopes]",
|
'[install.scopes."@bla-ble"]',
|
||||||
'\'@foo-bar\' = { url = "https://npm.pkg.github.com/", token = "$BUN_AUTH_TOKEN" }',
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
'\'@bla-ble\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }',
|
'url = "https://npm.pkg.github.com/"',
|
||||||
"",
|
"",
|
||||||
"[install.cache]",
|
'[install.scopes."@foo-bar"]',
|
||||||
"disable = true",
|
'url = "https://npm.pkg.github.com"',
|
||||||
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
|
"",
|
||||||
|
" [install.cache]",
|
||||||
|
" disable = true",
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -166,12 +199,16 @@ describe("writeBunfig", () => {
|
||||||
"[install]",
|
"[install]",
|
||||||
"optional = true",
|
"optional = true",
|
||||||
"",
|
"",
|
||||||
"[install.scopes]",
|
'[install.scopes."@foo-bar"]',
|
||||||
'\'@foo-bar\' = { url = "https://npm.pkg.github.com/", token = "$BUN_AUTH_TOKEN" }',
|
'url = "https://npm.pkg.github.com"',
|
||||||
'\'@bla-ble\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }',
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
"[install.cache]",
|
'[install.scopes."@bla-ble"]',
|
||||||
"disable = true",
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
|
'url = "https://npm.pkg.github.com/"',
|
||||||
|
"",
|
||||||
|
" [install.cache]",
|
||||||
|
" disable = true",
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -206,15 +243,22 @@ describe("writeBunfig", () => {
|
||||||
|
|
||||||
const expectedContents = [
|
const expectedContents = [
|
||||||
"[install]",
|
"[install]",
|
||||||
'registry = "https://bun.sh/"',
|
|
||||||
"optional = true",
|
"optional = true",
|
||||||
"",
|
"",
|
||||||
"[install.scopes]",
|
'[install.scopes."@foo-bar"]',
|
||||||
'\'@foo-bar\' = { url = "https://npm.pkg.github.com/", token = "$BUN_AUTH_TOKEN" }',
|
'url = "https://npm.pkg.github.com"',
|
||||||
'\'@bla-ble\' = { token = "$BUN_AUTH_TOKEN", url = "https://npm.pkg.github.com/" }',
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
"[install.cache]",
|
'[install.scopes."@bla-ble"]',
|
||||||
"disable = true",
|
'token = "$BUN_AUTH_TOKEN"',
|
||||||
|
'url = "https://npm.pkg.github.com/"',
|
||||||
|
"",
|
||||||
|
" [install.cache]",
|
||||||
|
" disable = true",
|
||||||
|
"",
|
||||||
|
" [install.registry]",
|
||||||
|
' url = "https://bun.sh"',
|
||||||
|
' token = "$BUN_AUTH_TOKEN"',
|
||||||
"",
|
"",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -225,4 +269,23 @@ describe("writeBunfig", () => {
|
||||||
expect(contents.length).toBe(expectedContents.length);
|
expect(contents.length).toBe(expectedContents.length);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when multiple global registries are provided", () => {
|
||||||
|
it("should throw an error", () => {
|
||||||
|
expect(() => {
|
||||||
|
writeBunfig(filePath, [
|
||||||
|
{
|
||||||
|
url: "https://npm.pkg.github.com",
|
||||||
|
scope: "",
|
||||||
|
token: "$BUN_AUTH_TOKEN",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "https://bun.sh",
|
||||||
|
scope: "",
|
||||||
|
token: "$BUN_AUTH_TOKEN",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}).toThrow("You can't have more than one global registry.");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue