Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/silly-foxes-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@bomb.sh/tools": minor
---

Updatess `oxfmt` config:

- Sets `"singleQuote"` option to `true`
- Adds `"*.json", "*.md", "*.yml", "*.jsonc"` to `"ignorePatterns"` option

Updates `format` command to include all files by default instead of the `./src` directory

Extracts `publint` from the `lint` command into a separate command
5 changes: 4 additions & 1 deletion oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"useTabs": true
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"useTabs": true,
"singleQuote": true,
"ignorePatterns": ["*.json", "*.md", "*.yml", "*.jsonc"]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"format": "pnpm run bsh format",
"init": "pnpm run bsh init",
"lint": "pnpm run bsh lint",
"publint": "pnpm run bsh publint",
"test": "pnpm run bsh test"
},
"dependencies": {
Expand Down
11 changes: 6 additions & 5 deletions rules/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ const plugin = {
const src = context.sourceCode.text;
let idx = node.start - 1;
// Walk backwards past whitespace
while (idx >= 0 && (src[idx] === ' ' || src[idx] === '\t' || src[idx] === '\n' || src[idx] === '\r')) {
while (
idx >= 0 &&
(src[idx] === ' ' || src[idx] === '\t' || src[idx] === '\n' || src[idx] === '\r')
) {
idx--;
}
// Check if preceding non-whitespace ends with */
Expand All @@ -82,8 +85,7 @@ const plugin = {
const parent = node.parent;
if (!parent) return false;
return (
parent.type === 'ExportNamedDeclaration' ||
parent.type === 'ExportDefaultDeclaration'
parent.type === 'ExportNamedDeclaration' || parent.type === 'ExportDefaultDeclaration'
);
}

Expand Down Expand Up @@ -124,8 +126,7 @@ const plugin = {
const parent = node.parent;
if (!parent) return false;
return (
parent.type === 'ExportNamedDeclaration' ||
parent.type === 'ExportDefaultDeclaration'
parent.type === 'ExportNamedDeclaration' || parent.type === 'ExportDefaultDeclaration'
);
}

Expand Down
21 changes: 11 additions & 10 deletions src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
#!/usr/bin/env node
import { argv } from "node:process";
import { build } from "./commands/build.ts";
import { dev } from "./commands/dev.ts";
import { format } from "./commands/format.ts";
import { init } from "./commands/init.ts";
import { lint } from "./commands/lint.ts";
import { test } from "./commands/test.ts";
import { argv } from 'node:process';
import { build } from './commands/build.ts';
import { dev } from './commands/dev.ts';
import { format } from './commands/format.ts';
import { init } from './commands/init.ts';
import { lint } from './commands/lint.ts';
import { publintCommand as publint } from './commands/publint.ts';
import { test } from './commands/test.ts';

const commands = { build, dev, format, init, lint, test };
const commands = { build, dev, format, init, lint, publint, test };

async function main() {
const [command, ...args] = argv.slice(2);

if (!command) {
console.log(`No command provided. Available commands: ${Object.keys(commands).join(", ")}\n`);
console.log(`No command provided. Available commands: ${Object.keys(commands).join(', ')}\n`);
return;
}

const run = commands[command as keyof typeof commands];
if (!run) {
console.log(
`Unknown command: ${command}. Available commands: ${Object.keys(commands).join(", ")}`,
`Unknown command: ${command}. Available commands: ${Object.keys(commands).join(', ')}`,
);
return;
}
Expand Down
12 changes: 6 additions & 6 deletions src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { parse } from "@bomb.sh/args";
import { build as tsdown } from "tsdown";
import type { CommandContext } from "../context.ts";
import { parse } from '@bomb.sh/args';
import { build as tsdown } from 'tsdown';
import type { CommandContext } from '../context.ts';

export async function build(ctx: CommandContext) {
const args = parse(ctx.args, {
boolean: ["bundle", "dts", "minify"],
boolean: ['bundle', 'dts', 'minify'],
});

const entry = args._.length > 0 ? args._.map(String) : ["src/**/*.ts", "!src/**/*.test.ts"];
const entry = args._.length > 0 ? args._.map(String) : ['src/**/*.ts', '!src/**/*.test.ts'];

await tsdown({
config: false,
entry,
format: "esm",
format: 'esm',
sourcemap: true,
clean: true,
unbundle: !args.bundle,
Expand Down
24 changes: 12 additions & 12 deletions src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { x } from "tinyexec";
import type { CommandContext } from "../context.ts";
import { x } from 'tinyexec';
import type { CommandContext } from '../context.ts';

// standardized `dev` command, shells out to `node --strip-types`
export async function dev(ctx: CommandContext) {
const { args } = ctx;
const [file = "./src/index.ts", ...rest] = args;
const [file = './src/index.ts', ...rest] = args;
// console.clear();
console.log(
`node --experimental-transform-types --disable-warning=ExperimentalWarning ${args.join(" ")}`,
`node --experimental-transform-types --disable-warning=ExperimentalWarning ${args.join(' ')}`,
);
const stdio = x("node", [
"--experimental-transform-types",
"--no-warnings",
"--watch-path=./src/",
const stdio = x('node', [
'--experimental-transform-types',
'--no-warnings',
'--watch-path=./src/',
file,
...rest,
]);
console.log("Starting dev server...");
console.log("Press Ctrl+C to stop the server.");
console.log('Starting dev server...');
console.log('Press Ctrl+C to stop the server.');

for await (const line of stdio) {
if (line.startsWith("Restarting")) {
if (line.startsWith('Restarting')) {
console.log(line);
continue;
}
if (line.startsWith("Completed")) {
if (line.startsWith('Completed')) {
console.log();
continue;
}
Expand Down
12 changes: 6 additions & 6 deletions src/commands/format.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { fileURLToPath } from "node:url";
import { x } from "tinyexec";
import type { CommandContext } from "../context.ts";
import { local } from "../utils.ts";
import { fileURLToPath } from 'node:url';
import { x } from 'tinyexec';
import type { CommandContext } from '../context.ts';
import { local } from '../utils.ts';

const config = fileURLToPath(new URL("../../oxfmtrc.json", import.meta.url));
const config = fileURLToPath(new URL('../../oxfmtrc.json', import.meta.url));

export async function format(ctx: CommandContext) {
const stdio = x(local("oxfmt"), ["-c", config, "./src", ...ctx.args]);
const stdio = x(local('oxfmt'), ['-c', config, ...ctx.args]);

for await (const line of stdio) {
console.log(line);
Expand Down
26 changes: 13 additions & 13 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { readFile, writeFile } from "node:fs/promises";
import { cwd } from "node:process";
import { pathToFileURL } from "node:url";
import { x } from "tinyexec";
import type { CommandContext } from "../context.ts";
import { readFile, writeFile } from 'node:fs/promises';
import { cwd } from 'node:process';
import { pathToFileURL } from 'node:url';
import { x } from 'tinyexec';
import type { CommandContext } from '../context.ts';

export async function init(ctx: CommandContext) {
const [_name = "."] = ctx.args;
const [_name = '.'] = ctx.args;
const cwdUrl = pathToFileURL(`${cwd()}/`);
const name =
_name === "." ? new URL("../", cwdUrl).pathname.split("/").filter(Boolean).pop()! : _name;
const dest = new URL("./.temp/", cwdUrl);
for await (const line of x("pnpx", ["giget@latest", "gh:bombshell-dev/template", name])) {
_name === '.' ? new URL('../', cwdUrl).pathname.split('/').filter(Boolean).pop()! : _name;
const dest = new URL('./.temp/', cwdUrl);
for await (const line of x('pnpx', ['giget@latest', 'gh:bombshell-dev/template', name])) {
console.log(line);
}

const promises: Promise<void>[] = [];
for (const file of ["package.json", "README.md"]) {
for (const file of ['package.json', 'README.md']) {
promises.push(
postprocess(new URL(file, dest), (contents) => {
return contents.replaceAll("$name", name);
return contents.replaceAll('$name', name);
}),
);
}
Expand All @@ -29,8 +29,8 @@ async function postprocess(
file: URL,
transform: (contents: string) => string | undefined | Promise<string | undefined>,
) {
const contents = await readFile(file, { encoding: "utf8" });
const contents = await readFile(file, { encoding: 'utf8' });
const result = await transform(contents);
if (!result) return;
await writeFile(file, result, { encoding: "utf8" });
await writeFile(file, result, { encoding: 'utf8' });
}
44 changes: 22 additions & 22 deletions src/commands/lint.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { createFixture } from "../test-utils/index.ts";
import { runOxlint, runKnip } from "./lint.ts";
import { fileURLToPath } from "node:url";
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { createFixture } from '../test-utils/index.ts';
import { runOxlint, runKnip } from './lint.ts';
import { fileURLToPath } from 'node:url';

describe("lint command", () => {
describe('lint command', () => {
let originalCwd: string;
let fixture: Awaited<ReturnType<typeof createFixture>>;

Expand All @@ -16,57 +16,57 @@ describe("lint command", () => {
if (fixture) await fixture.cleanup();
});

describe("runOxlint", () => {
it("detects violations in bad code", async () => {
describe('runOxlint', () => {
it('detects violations in bad code', async () => {
fixture = await createFixture({
src: {
"index.ts": "var x = 1;",
'index.ts': 'var x = 1;',
},
});
process.chdir(fileURLToPath(fixture.root));

const violations = await runOxlint(["./src"]);
const violations = await runOxlint(['./src']);

expect(violations).not.toEqual([]);
expect(violations).toMatchSnapshot();
});

it("returns empty array for clean code", async () => {
it('returns empty array for clean code', async () => {
fixture = await createFixture({
src: {
"index.ts": `
'index.ts': `
export const x = 1;
`,
},
});
process.chdir(fileURLToPath(fixture.root));

const violations = await runOxlint(["./src"]);
const violations = await runOxlint(['./src']);

expect(violations).toEqual([]);
});
});

describe("runKnip", () => {
it("detects unused exports and unused files", async () => {
describe('runKnip', () => {
it('detects unused exports and unused files', async () => {
fixture = await createFixture({
"package.json": {
name: "test-pkg",
version: "1.0.0",
type: "module",
exports: "./src/index.ts",
'package.json': {
name: 'test-pkg',
version: '1.0.0',
type: 'module',
exports: './src/index.ts',
},
src: {
"index.ts": `
'index.ts': `
import { used } from "./used";
console.log(used);
export const value = 42;
`,
"used.ts": `
'used.ts': `
export const used = "used";
export const unusedExport = "unusedExport";
`,
"unused-file.ts": `
'unused-file.ts': `
export const unused = "unused";
`,
},
Expand Down
Loading
Loading