Skip to content

Commit 775b0b3

Browse files
authored
💥 Improve CLI DX (#16)
Adds Commander to improve CLI developer experience. Commander out-of-the-box features delivers a help system, error handling, and (most notably to css-typed users) better argument/option handling. (You can finally pass `--dashes` before the pattern.) Closes #5 BREAKING CHANGE: Removes specific exit codes. Upgrades glob dependency given breaking change already. +semver:minor (0.x semver)
1 parent 193962d commit 775b0b3

File tree

8 files changed

+102
-75
lines changed

8 files changed

+102
-75
lines changed

‎.github/workflows/pipeline.yaml

+8-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ jobs:
7878
- name: Run css-typed (the test)
7979
# `node dist/main.js` is executing local `css-typed` as if installed (same as `bin`)
8080
# Use `-I '//.*'` to ignore the first line (comment) which has generated path and timestamp
81+
# Test --dashes in both positions
8182
run: |
8283
cp src/fixtures/kebab-case/kebab-case.css "$RUNNER_TEMP/kebab-case.css"
8384
@@ -87,6 +88,9 @@ jobs:
8788
node dist/main.js "$RUNNER_TEMP/*.css" --dashes
8889
diff --strip-trailing-cr -uI '//.*' src/fixtures/kebab-case/kebab-case-dashes.d.css.ts "$RUNNER_TEMP/kebab-case.d.css.ts"
8990
91+
node dist/main.js --dashes "$RUNNER_TEMP/*.css"
92+
diff --strip-trailing-cr -uI '//.*' src/fixtures/kebab-case/kebab-case-dashes.d.css.ts "$RUNNER_TEMP/kebab-case.d.css.ts"
93+
9094
Publish:
9195
if: ${{ github.ref == 'refs/heads/main' }}
9296
name: Publish
@@ -109,7 +113,10 @@ jobs:
109113
registry-url: https://registry.npmjs.org
110114

111115
- name: Set version
112-
run: sed -i 's/0.0.0-gitversion/${{ env.GitVersion_SemVer }}/g' package.json
116+
run: |
117+
expr='s/0.0.0-gitversion/${{ env.GitVersion_SemVer }}/g'
118+
sed -i "$expr" package.json
119+
sed -i "$expr" src/version.js
113120
114121
- name: Install
115122
run: npm install --omit=dev

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# css-typed
22

3-
Basic TypeScript declaration generator for CSS files.
3+
TypeScript declaration generator for CSS files.
44

55
**Table of contents**
66

‎package-lock.json

+50-35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "css-typed",
33
"version": "0.0.0-gitversion",
4-
"description": "Basic TypeScript declaration generator for CSS files",
4+
"description": "TypeScript declaration generator for CSS files",
55
"keywords": [
66
"CSS",
77
"modules",
@@ -33,7 +33,7 @@
3333
"dist"
3434
],
3535
"scripts": {
36-
"build": "rm -rf dist && mkdir -p dist && cp src/main.js src/logic.js dist",
36+
"build": "rm -rf dist && mkdir -p dist && cp src/main.js src/logic.js src/version.js dist",
3737
"ci-build": "npm-run-all -l -p build eslint prettier test",
3838
"eslint": "eslint -f pretty .",
3939
"eslint:fix": "npm run eslint -- --fix",
@@ -44,8 +44,10 @@
4444
},
4545
"engineStrict": true,
4646
"dependencies": {
47+
"@commander-js/extra-typings": "^12.1.0",
48+
"commander": "^12.1.0",
4749
"css-tree": "^2.3.1",
48-
"glob": "^10.3.14"
50+
"glob": "^11.0.0"
4951
},
5052
"devDependencies": {
5153
"@types/css-tree": "^2.3.8",

‎src/logic.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { parse as parseCss, walk } from "css-tree";
1616
* @returns {Promise<string | undefined>} TypeScript declaration file content or
1717
* `undefined` if no declarations to write.
1818
*/
19-
export async function generateDeclaration(stylesheetPath, time, options) {
19+
export async function generateDeclaration(stylesheetPath, time, options = {}) {
2020
// Handle case where the file got deleted by the time we got here
2121
if (!existsSync(stylesheetPath)) return undefined;
2222

‎src/logic.test.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import { readFileSync } from "node:fs";
22
import path from "node:path";
3-
import { fileURLToPath } from "node:url";
43

54
import { describe, expect, it } from "vitest";
65

76
import { dtsPath, generateDeclaration } from "./logic.js";
87

9-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
10-
118
describe(`css-typed`, () => {
129
it(`should not generate an empty declaration file [#9]`, async () => {
1310
const path = fixtureFile(`no-declaration-file.css`);
@@ -46,5 +43,5 @@ describe(`css-typed`, () => {
4643
});
4744

4845
function fixtureFile(filename) {
49-
return path.join(__dirname, `fixtures`, filename);
46+
return path.join(import.meta.dirname, `fixtures`, filename);
5047
}

‎src/main.js

+34-30
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,44 @@
22

33
import { writeFile } from "node:fs/promises";
44

5+
import { Command } from "@commander-js/extra-typings";
56
import { glob } from "glob";
67

78
import { dtsPath, generateDeclaration } from "./logic.js";
8-
9-
/* globals process -- Node/CLI tool */
10-
await main(process.argv[2], process.argv[3] === `--dashes`);
11-
// See https://github.com/connorjs/css-typed/issues/5 for "proper" CLI arg handling
12-
13-
async function main(pattern, dashesEnabled) {
14-
if (!pattern) {
15-
console.error(`Expected glob pattern`);
16-
process.exit(2);
17-
}
18-
const options = dashesEnabled ? { localsConvention: `dashes` } : {};
19-
20-
const files = await glob(pattern);
21-
22-
const time = new Date().toISOString();
23-
const results = await Promise.all(
24-
files.map((file) =>
25-
generateDeclaration(file, time, options).then((ts) =>
26-
writeDeclarationFile(file, ts),
9+
import { version } from "./version.js";
10+
11+
await new Command()
12+
.name(`css-typed`)
13+
.description(`TypeScript declaration generator for CSS files.`)
14+
.version(version)
15+
.argument(`<pattern>`, `Glob path for CSS files to target.`)
16+
.option(
17+
`--dashes`,
18+
`Transform kebab-case classes (dashed names) to camelCase.`,
19+
false,
20+
)
21+
.action(async function (pattern, options, program) {
22+
const declarationOptions = options.dashes
23+
? { localsConvention: `dashes` }
24+
: {};
25+
26+
const files = await glob(pattern);
27+
28+
const time = new Date().toISOString();
29+
const results = await Promise.all(
30+
files.map((file) =>
31+
generateDeclaration(file, time, declarationOptions).then((ts) =>
32+
writeDeclarationFile(file, ts),
33+
),
2734
),
28-
),
29-
);
30-
31-
const errors = results.filter(Boolean);
32-
if (errors.length > 0) {
33-
console.error(`Errors encountered`, errors);
34-
process.exit(3);
35-
}
36-
37-
process.exit(0);
38-
}
35+
);
36+
37+
const errors = results.filter(Boolean);
38+
if (errors.length > 0) {
39+
program.error(`Errors encountered: ${errors}`);
40+
}
41+
})
42+
.parseAsync();
3943

4044
/**
4145
* Writes the TypeScript declaration content to file. Handles the output path.

‎src/version.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Replaced with actual version in Publish (see `pipeline.yaml`)
2+
export const version = `0.0.0-gitversion`;

0 commit comments

Comments
 (0)