diff --git a/.commitlintrc.js b/.commitlintrc.cjs similarity index 100% rename from .commitlintrc.js rename to .commitlintrc.cjs diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 0981731..f868838 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -10,4 +10,4 @@ jobs: fetch-depth: 0 - uses: wagoid/commitlint-github-action@v4 with: - configFile: .commitlintrc.js + configFile: .commitlintrc.cjs diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index 4d9f0fc..adba2b5 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -6,37 +6,21 @@ jobs: build: runs-on: ubuntu-latest - strategy: - matrix: - node-version: [18.x, 20.x] - steps: - name: Checkout sources uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Cache Node.js modules 💾 - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-node- - ${{ runner.OS }}- + - name: Use bun + uses: oven-sh/setup-bun@v1 - name: Install dependencies ⏬ - run: npm install + run: bun install - name: Lint code 💄 - run: npm run lint - - - name: Build artifacts 🏗️ - run: npm run build + run: bun run lint - name: Test code ✅ - run: npm run test + run: bun run test + - name: Build artifacts 🏗️ + run: bun run build diff --git a/.github/workflows/on-push-main.yml b/.github/workflows/on-push-main.yml new file mode 100644 index 0000000..715a068 --- /dev/null +++ b/.github/workflows/on-push-main.yml @@ -0,0 +1,29 @@ +name: Test Push to main + +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Use bun + uses: oven-sh/setup-bun@v1 + + - name: Install dependencies ⏬ + run: bun install + + - name: Lint code 💄 + run: bun run lint + + - name: Test code ✅ + run: bun run test + + - name: Build artifacts 🏗️ + run: bun run build diff --git a/.github/workflows/on-push-master.yml b/.github/workflows/on-push-master.yml deleted file mode 100644 index cce93d9..0000000 --- a/.github/workflows/on-push-master.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Test Push to Master - -on: - push: - branches: - - master - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x, 20.x] - - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Cache Node.js modules 💾 - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-node- - ${{ runner.OS }}- - - - name: Install dependencies ⏬ - run: npm install - - - name: Lint code 💄 - run: npm run lint - - - name: Build artifacts 🏗️ - run: npm run build - - - name: Test code ✅ - run: npm run test - - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98c14ed..d6972ea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,13 +11,11 @@ jobs: - name: Checkout sources 🔰 uses: actions/checkout@v4 - - name: Setup Node.js 18 👷🏻 - uses: actions/setup-node@v4 - with: - node-version: 18 + - name: Use bun + uses: oven-sh/setup-bun@v1 - name: Install dependencies ⏬ - run: npm ci + run: bun install - name: Release 🚀 uses: cycjimmy/semantic-release-action@v4.1.0 diff --git a/.gitignore b/.gitignore index a3e7371..d334dda 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,4 @@ dist binaries output-bulk -output.map -output.qml -output.sld +TEST_OUTPUT.* diff --git a/README.md b/README.md index a87a344..11bf183 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ between various formats for styling of geographic data. ## tl;dr ``` -npx geostyler-cli --output new-qgis-style.qml my-existing.sld +bunx geostyler-cli --output new-qgis-style.qml my-existing.sld ``` ## Requirements @@ -15,7 +15,7 @@ npx geostyler-cli --output new-qgis-style.qml my-existing.sld ## Standalone application -Binaries are available for Linux, MacOS, and Windows on the +Binaries are available for Linux, MacOS, and Windows on the [Releases](https://github.com/geostyler/geostyler-cli/releases) page. Download the zip file for your operating system, unzip, navigate to the folder and run the `geostyler` command: @@ -26,50 +26,13 @@ geostyler-cli --output new-qgis-style.qml my-existing.sld ## Usage without installation ⚡ -`Node.js` includes [npx](https://docs.npmjs.com/cli/v10/commands/npx), this +`Bun` includes [bunx](https://bun.sh/docs/cli/bunx), this allows you to run commands from an npm package without having to install it. ``` -npx geostyler-cli -s sld -t qgis -o output.qml input.sld +bunx geostyler-cli -s sld -t qgis -o output.qml input.sld ``` -## Global installation - -### Installation 💾 - -`Node.js` includes [npm](https://docs.npmjs.com/cli/v10/commands/npm) - the -JavaScript package manager. To install the `geostyler` command globally: - -``` -npm install -g geostyler-cli -``` - -You can then use the new `geostyler-cli` command, e.g.: - -``` -geostyler-cli -s sld -t qgis -o output.qml input.sld -``` - -To process a folder of files: - -``` -geostyler-cli -s sld -t qgis -o /outputdir /inputdir -``` - - -### Update 🚀 - -``` -npm update -g geostyler-cli -``` - -### Uninstalling 😔 - -``` -npm uninstall -g geostyler-cli -``` - - ## Syntax and examples To convert a single file: @@ -106,12 +69,12 @@ geostyler-cli -t sld testdata/point_simple.qml * `-h` / `--help` Display the help and exit. * `-o` / `--output` Output filename or directory. Required when the source is a directory. For a file leave this empty to write to `stdout`. [string] -* `-s` / `--source` Source parser, either `mapbox`, `mapfile` or `map`, +* `-s` / `--source` Source parser, either `mapbox` (`maplibre`), `lyrx`, `mapfile` or `map`, `sld` or `se` for SLD - the parser will read the version from the file, -and `qgis` or `qml` for QGIS QML files. If not given, it will be guessed from the extension of the input file. +and `qgis` (`qml`) for QGIS QML files. If not given, it will be guessed from the extension of the input file. Mandatory if the the target is a directory. -* `-t` / `--target` Target parser, either `mapbox`, `sld` (for SLD 1.0), `se` (for SLD 1.1), -and `qgis` or `qml` for QGIS QML files. If not given, it will be guessed from +* `-t` / `--target` Target parser, either `mapbox` (`maplibre`), `sld` (for SLD 1.0), `se` (for SLD 1.1), +and `qgis` (`qml`) for QGIS QML files. If not given, it will be guessed from the extension of the output file. Mapfiles are not currently supported as target. Mandatory if the the target is a directory. * `-v` / `--version` Display the version of the program. @@ -121,10 +84,10 @@ Mandatory if the the target is a directory. In your clone of the repo, in the root directory: ```bash -npm install # get dependencies -npm run build # build from possibly changed source +bun install # get dependencies +bun run build # build from possibly changed source # now you can call your build like this: -npm start -- -s sld -t qgis -o output.qml testdata/point_simplepoint.sld +bun run start -- -s sld -t qgis -o output.qml testdata/point_simplepoint.sld ``` ## Funding & financial sponsorship @@ -133,4 +96,3 @@ Maintenance and further development of this code can be funded through the [GeoStyler Open Collective](https://opencollective.com/geostyler). All contributions and expenses can transparently be reviewed by anyone; you see what we use the donated money for. Thank you for any financial support you give the GeoStyler project 💞 - diff --git a/bun.lockb b/bun.lockb index a7cbdda..3b49631 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 60cb15d..4497567 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "version": "4.0.0", "description": "", "type": "module", - "main": "dist/src/index.js", + "main": "src/index.js", "files": [ "dist" ], "bin": { - "geostyler-cli": "dist/src/index.js" + "geostyler-cli": "src/index.js" }, "scripts": { "build": "bun run build-clean && bun run build-only", @@ -26,14 +26,6 @@ "prepublishOnly": "bun run build", "postpublish": "bun run package-binaries" }, - "pkg": { - "targets": [ - "node18-linux-x64", - "node18-macos-x64", - "node18-win-x64" - ], - "outputPath": "./binaries" - }, "repository": { "type": "git", "url": "git+https://github.com/geostyler/geostyler-cli.git" @@ -51,31 +43,31 @@ }, "homepage": "https://github.com/geostyler/geostyler-cli#readme", "engines": { - "node": ">=18.0.0", - "npm": ">=6.0.0" + "bun": ">=1.0.0", + "node": ">=20.0.0", + "npm": ">=10.0.0" }, "devDependencies": { - "@commitlint/cli": "^17.6.5", - "@commitlint/config-conventional": "^17.6.5", + "@commitlint/cli": "^19.5.0", + "@commitlint/config-conventional": "^19.5.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/exec": "^6.0.3", "@semantic-release/git": "^10.0.1", "@terrestris/eslint-config-typescript": "^3.1.0", "@types/gradient-string": "^1.1.2", + "@types/minimist": "^1.2.5", "@types/node": "^20.0.0", "@typescript-eslint/eslint-plugin": "^5.59.1", "@typescript-eslint/parser": "^5.59.1", "adm-zip": "^0.5.10", "eslint": "^8.39.0", - "pkg": "^5.8.1", "rimraf": "^5.0.0", "typescript": "^5.0.4" }, "dependencies": { - "geostyler-lyrx-parser": "^1.0.0", + "geostyler-lyrx-parser": "^1.0.1", "geostyler-mapbox-parser": "^6.0.0", "geostyler-mapfile-parser": "^4.0.1", - "geostyler-openlayers-parser": "^5.0.0", "geostyler-qgis-parser": "^3.0.0", "geostyler-sld-parser": "^6.1.2", "geostyler-style": "^9.1.0", diff --git a/src/index.ts b/src/index.ts index 8bc8ecc..01f26f2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,9 +2,11 @@ import SLDParser from 'geostyler-sld-parser'; import QGISParser from 'geostyler-qgis-parser'; -// import OpenLayersParser from "geostyler-openlayers-parser"; import MapfileParser from 'geostyler-mapfile-parser'; import MapboxParser from 'geostyler-mapbox-parser'; +import ArcGISParser from 'geostyler-lyrx-parser'; +import { StyleParser } from 'geostyler-style'; + import { existsSync, lstatSync, @@ -13,7 +15,6 @@ import { readdirSync } from 'fs'; import minimist from 'minimist'; -import { StyleParser } from 'geostyler-style'; import ora, { Ora } from 'ora'; import { logHelp, @@ -33,10 +34,10 @@ const getParserFromFormat = (inputString: string): StyleParser | undefined => { throw new Error('No input'); } switch (inputString.toLowerCase()) { - // case 'openlayers': - // case 'ol': - // return new OpenLayersParser(); + case 'lyrx': + return new ArcGISParser(); case 'mapbox': + case 'maplibre': return new MapboxParser(); case 'mapfile': case 'map': @@ -62,9 +63,10 @@ const getParserFromFilename = (fileName: string): StyleParser | undefined => { return undefined; } switch (fileEnding.toLowerCase()) { - // case 'ol': - // return new OpenLayersParser(); + case 'lyrx': + return new ArcGISParser(); case 'mapbox': + case 'maplibre': return new MapboxParser(); case 'map': return new MapfileParser(); @@ -82,9 +84,6 @@ const getExtensionFromFormat = (format: string): string => { return ''; } switch (format.toLowerCase()) { - case 'openlayers': - case 'ol': - return 'ts'; case 'mapfile': return 'map'; case 'qgis': @@ -159,12 +158,16 @@ function collectPaths(basePath: string, isFile: boolean): string[] { async function writeFile( sourceFile: string, sourceParser: StyleParser, - targetFile: string, targetParser: StyleParser | undefined, + targetFile: string, targetParser: Exclude | undefined, oraIndicator: Ora ) { const inputFileData = await promises.readFile(sourceFile, 'utf-8'); const indicator = oraIndicator; // for linter. + if (targetParser instanceof ArcGISParser || targetParser instanceof MapfileParser) { + throw new Error('ArcGIS (lyrx) and MapFile are not supported as target.'); + } + try { indicator.text = `Reading from ${sourceFile}`; const { @@ -259,7 +262,7 @@ async function main() { // Check source path arg. if (!sourcePath) { indicator.fail('No input file or folder specified.'); - return; + return Promise.reject('No input file or folder specified.'); } // Check source exists, is a dir or a file ? @@ -271,12 +274,11 @@ async function main() { // Try to define type of target (file or dir). // Assume the target is the same as the source let targetIsFile = sourceIsFile; - const outputExists = existsSync(outputPath); // Dir to file is not possible if (!sourceIsFile && targetIsFile) { indicator.fail('The source is a directory, so the target must be directory, too.'); - return; + return Promise.reject('The source is a directory, so the target must be directory, too.'); } // Get source and target parser. @@ -285,7 +287,7 @@ async function main() { const targetParser = targetFormat && getParserFromFormat(targetFormat) || getParserFromFilename(outputPath); if (!sourceParser) { indicator.fail('No sourceparser was specified.'); - return; + return Promise.reject('No sourceparser was specified.'); } if (!targetParser) { indicator.info('No targetparser was specified. Output will be a GeoStyler object.'); diff --git a/test.js b/test.js index 0e0013a..0bdcf44 100644 --- a/test.js +++ b/test.js @@ -13,7 +13,7 @@ function checkFileCreated(outputFile) { } function runTest(args, outputFile) { - const cmd = 'npm'; + const cmd = 'bun'; const result = spawnSync(cmd, args, { shell: true }); /* eslint-disable no-console */ console.log(`Status: ${result.status.toString()}`); @@ -26,7 +26,7 @@ function runAllTests() { let success = true; // test sld to qgis - let outputFile = 'output.qml'; + let outputFile = 'TEST_OUTPUT.qml'; let args = ['start', '--', '-s', 'sld', '-t', 'qgis', '-o', outputFile, 'testdata/sld/point_simplepoint.sld']; runTest(args, outputFile); @@ -35,7 +35,7 @@ function runAllTests() { } // test qgis to sld - outputFile = 'output.sld'; + outputFile = 'TEST_OUTPUT.sld'; args = ['start', '--', '-s', 'qgis', '-t', 'sld', '-o', outputFile, 'testdata/point_simple.qml']; runTest(args, outputFile); @@ -44,7 +44,7 @@ function runAllTests() { } // test mapfile to geostyler - outputFile = 'output.map'; + outputFile = 'TEST_OUTPUT.geostyler'; args = ['start', '--', '-s', 'mapfile', '-o', outputFile, 'testdata/point_simplepoint.map']; runTest(args, outputFile);