From 7f177f6b83380fbb5542c21ad2502ee35ebf0864 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Thu, 10 Jul 2025 12:28:23 -0400 Subject: [PATCH] Add npm publishing of JS libs (#702) * feat: publish js libs to npm * changed license type * updated readme * added id * added exclusion for web and deno packages * update comment * updating env var --- .github/workflows/ci.yml | 2 +- .github/workflows/js-ci.yml | 37 ------- .github/workflows/release.yml | 120 +++++++++++++++++---- .gitignore | 3 +- packages/web/LICENSE => LICENSE | 0 README.md | 4 +- deno.json | 13 +++ deno.lock | 104 +++++++++++++++--- packages/core/README.md | 1 + packages/core/deno.json | 1 + packages/transport-deno/README.md | 1 + packages/transport-deno/deno.json | 1 + packages/transport-http/README.md | 1 + packages/transport-http/deno.json | 1 + packages/transport-web-bluetooth/README.md | 1 + packages/transport-web-bluetooth/deno.json | 1 + packages/transport-web-serial/README.md | 1 + packages/transport-web-serial/deno.json | 1 + packages/web/deno.json | 1 - scripts/build_npm_package.ts | 101 +++++++++++++++++ 20 files changed, 317 insertions(+), 78 deletions(-) delete mode 100644 .github/workflows/js-ci.yml rename packages/web/LICENSE => LICENSE (100%) create mode 100644 scripts/build_npm_package.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3629d269..507c260a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,4 +41,4 @@ jobs: run: deno fmt --check - name: Build Package - run: deno task build + run: deno task --filter web build diff --git a/.github/workflows/js-ci.yml b/.github/workflows/js-ci.yml deleted file mode 100644 index e03b29e7..00000000 --- a/.github/workflows/js-ci.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Pull Request - -on: - push: - paths: - - "packages/core" - - "packages/transport-deno" - - "packages/transport-http" - - "packages/transport-web-bluetooth" - - "packages/transport-web-serial" - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - - permissions: - contents: read - id-token: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - uses: denoland/setup-deno@v2 - with: - deno-version: v2.x - - - name: Check formatting - run: deno fmt --check - - - name: Check types - run: deno lint - - - name: Publish to JSR - run: npx jsr publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 887dc64c..509c7c84 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,65 +5,140 @@ on: types: [released, prereleased] permissions: + id-token: write # This is required for requesting the JWT contents: write packages: write jobs: - build-and-package: + build-and-publish: runs-on: ubuntu-latest steps: - - name: Checkout + # --- Checkout code --- + - name: Checkout Code uses: actions/checkout@v4 + with: + fetch-depth: 0 + # --- Setup Deno --- - name: Setup Deno uses: denoland/setup-deno@v2 with: deno-version: v2.x - - name: Install Dependencies - working-directory: packages/web - run: deno install + - name: Cache Deno Dependencies + uses: actions/cache@v4 + with: + path: ~/.cache/deno + key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.lock') }} + restore-keys: | + ${{ runner.os }}-deno- - - name: Run tests + # --- Determine Changed Packages --- + - name: Get Changed Package Directories + id: changed_packages + uses: tj-actions/changed-files@v44 + with: + dir_names: true + files: packages/** + files_ignore: "packages/web/**,packages/transport-deno/npm/**" + + # --- Setup Node for NPM Publishing --- + - name: Setup Node.js + if: steps.changed_packages.outputs.all_changed_and_modified_files != '' + uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: "https://registry.npmjs.org" + + - name: Verify NPM Authentication + if: steps.changed_packages.outputs.all_changed_and_modified_files != '' + run: npm whoami + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + # --- Build and Publish Packages to NPM & JSR --- + - name: Build and Publish Changed Packages + if: steps.changed_packages.outputs.all_changed_and_modified_files != '' + run: | + set -euo pipefail + + excluded=("packages/web packages/transport-deno") + + for pkg_dir in ${{ steps.changed_packages.outputs.all_changed_and_modified_files }}; do + + echo "Building for NPM..." + deno task build:npm "$pkg_dir" + + echo "Publishing to NPM..." + npm publish "$pkg_dir/npm" --access public + + echo "Publishing to JSR..." + # We run this in a subshell to change directory just for this command. + # --allow-dirty is necessary because the 'npm' build directory is untracked. + (cd "$pkg_dir" && deno publish --allow-dirty) + done + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: No Packages Changed + if: steps.changed_packages.outputs.all_changed_and_modified_files == '' + run: echo "No changed packages detected. Skipping publish." + + # --- Web Package Specific Tasks --- + - name: Check for Web Package Changes + id: web_changes + + run: | + if [[ "${{ steps.changed_packages.outputs.all_changed_and_modified_files }}" == *"packages/web"* ]]; then + echo "web_changed=true" >> $GITHUB_OUTPUT + else + echo "web_changed=false" >> $GITHUB_OUTPUT + fi + + - name: Run Web App Tests + if: steps.web_changes.outputs.web_changed == 'true' working-directory: packages/web run: deno task test - - name: Build Package + - name: Create Web App Release Archive + if: steps.web_changes.outputs.web_changed == 'true' working-directory: packages/web - run: deno task build + run: deno task package # Generates dist/build.tar - - name: Package Output - working-directory: packages/web - run: deno task package - - - name: Archive compressed build + - name: Upload Web App Archive + if: steps.web_changes.outputs.web_changed == 'true' uses: actions/upload-artifact@v4 with: - name: build + name: web-build + if-no-files-found: error path: packages/web/dist/build.tar - - name: Attach build.tar to release - run: | - gh release upload ${{ github.event.release.tag_name }} packages/web/dist/build.tar + - name: Attach Web Archive to GitHub Release + if: steps.web_changes.outputs.web_changed == 'true' + run: gh release upload ${{ github.event.release.tag_name }} packages/web/dist/build.tar env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # --- Build & Push Container Image --- - name: Set up QEMU + if: steps.web_changes.outputs.web_changed == 'true' uses: docker/setup-qemu-action@v3 - - name: Buildah Build + - name: Build Container Image + if: steps.web_changes.outputs.web_changed == 'true' id: build-container uses: redhat-actions/buildah-build@v2 with: containerfiles: | ./infra/Containerfile - image: ${{github.event.repository.full_name}} - tags: latest ${{ github.sha }} + image: ghcr.io/${{ github.repository }} + tags: latest, ${{ github.event.release.tag_name }} oci: true platforms: linux/amd64, linux/arm64 - - name: Push To Registry + - name: Push Container to GHCR id: push-to-registry + if: steps.web_changes.outputs.web_changed == 'true' uses: redhat-actions/push-to-registry@v2 with: image: ${{ steps.build-container.outputs.image }} @@ -72,5 +147,6 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Print image url + - name: Output Image URL + if: steps.web_changes.outputs.web_changed == 'true' run: echo "Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}" diff --git a/.gitignore b/.gitignore index 9a47b879..8d28e352 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ stats.html dev-dist __screenshots__* *.diff -npm/ \ No newline at end of file +npm/ + diff --git a/packages/web/LICENSE b/LICENSE similarity index 100% rename from packages/web/LICENSE rename to LICENSE diff --git a/README.md b/README.md index 442a7642..d895496a 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ All projects are located within the `packages/` directory: - **`packages/transport-web-bluetooth`:** Web Bluetooth Transport. - **`packages/transport-web-serial`:** Web Serial Transport. -All `Meshtastic JS` packages (core and transports) are published to -[JSR](https://jsr.io/@meshtastic). +All `Meshtastic JS` packages (core and transports) are published both to +[JSR](https://jsr.io/@meshtastic). [NPM](https://www.npmjs.com/org/meshtastic) --- diff --git a/deno.json b/deno.json index 46ddd09a..71604d00 100644 --- a/deno.json +++ b/deno.json @@ -8,8 +8,12 @@ "./packages/transport-web-bluetooth", "./packages/transport-web-serial" ], + "tasks": { + "build:npm": "deno run -A scripts/build_npm_package.ts" + }, "imports": { "@bufbuild/protobuf": "npm:@bufbuild/protobuf@^2.2.3", + "@deno/dnt": "jsr:@deno/dnt@^0.42.1", "@meshtastic/protobufs": "jsr:@meshtastic/protobufs@^2.7.0", "@types/node": "npm:@types/node@^22.13.10", "ste-simple-events": "npm:ste-simple-events@^3.0.11", @@ -33,5 +37,14 @@ }, "unstable": [ "sloppy-imports" + ], + "exclude": [ + "node_modules", + "dist", + "npm", + "build", + "coverage", + "out", + ".vscode-test" ] } diff --git a/deno.lock b/deno.lock index c80a48bc..cddc5bc6 100644 --- a/deno.lock +++ b/deno.lock @@ -1,9 +1,25 @@ { "version": "5", "specifiers": { + "jsr:@david/code-block-writer@^13.0.2": "13.0.3", + "jsr:@deno/cache-dir@0.20": "0.20.1", + "jsr:@deno/dnt@~0.42.1": "0.42.1", + "jsr:@deno/graph@0.86": "0.86.9", "jsr:@meshtastic/protobufs@^2.7.0": "2.7.0", + "jsr:@std/bytes@^1.0.5": "1.0.6", + "jsr:@std/fmt@1": "1.0.8", + "jsr:@std/fmt@^1.0.3": "1.0.8", + "jsr:@std/fs@1": "1.0.19", + "jsr:@std/fs@^1.0.6": "1.0.19", "jsr:@std/internal@^1.0.9": "1.0.9", + "jsr:@std/io@0.225": "0.225.2", + "jsr:@std/path@*": "1.1.1", + "jsr:@std/path@1": "1.1.1", + "jsr:@std/path@^1.0.8": "1.1.1", "jsr:@std/path@^1.1.0": "1.1.1", + "jsr:@std/path@^1.1.1": "1.1.1", + "jsr:@ts-morph/bootstrap@0.25": "0.25.0", + "jsr:@ts-morph/common@0.25": "0.25.0", "npm:@bufbuild/protobuf@^2.2.3": "2.6.0", "npm:@bufbuild/protobuf@^2.6.0": "2.6.0", "npm:@hookform/resolvers@^5.1.1": "5.1.1_react-hook-form@7.60.0__react@19.1.0_react@19.1.0", @@ -30,11 +46,11 @@ "npm:@radix-ui/react-toggle-group@^1.1.10": "1.1.10_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@radix-ui/react-tooltip@^1.2.7": "1.2.7_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@tailwindcss/postcss@^4.1.11": "4.1.11", - "npm:@tanstack/react-router-devtools@^1.125.4": "1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/react-router@^1.125.4": "1.125.4_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/react-router-devtools@^1.125.4": "1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/react-router@^1.125.4": "1.125.6_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@tanstack/router-cli@^1.125.4": "1.125.4", - "npm:@tanstack/router-devtools@^1.125.4": "1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", - "npm:@tanstack/router-plugin@^1.125.5": "1.125.5_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0", + "npm:@tanstack/router-devtools@^1.125.4": "1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0", + "npm:@tanstack/router-plugin@^1.125.5": "1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0", "npm:@testing-library/jest-dom@^6.6.3": "6.6.3", "npm:@testing-library/react@^16.3.0": "16.3.0_@testing-library+dom@10.4.0_@types+react@19.1.8_@types+react-dom@19.1.6__@types+react@19.1.8_react@19.1.0_react-dom@19.1.0__react@19.1.0", "npm:@testing-library/user-event@^14.6.1": "14.6.1_@testing-library+dom@10.4.0", @@ -94,20 +110,79 @@ "npm:zustand@5.0.6": "5.0.6_@types+react@19.1.8_immer@10.1.1_react@19.1.0" }, "jsr": { + "@david/code-block-writer@13.0.3": { + "integrity": "f98c77d320f5957899a61bfb7a9bead7c6d83ad1515daee92dbacc861e13bb7f" + }, + "@deno/cache-dir@0.20.1": { + "integrity": "dc4f3add14307f3ff3b712441ea4acabcbfc9a13f67c5adc78c3aac16ac5e2a0", + "dependencies": [ + "jsr:@deno/graph", + "jsr:@std/fmt@^1.0.3", + "jsr:@std/fs@^1.0.6", + "jsr:@std/io", + "jsr:@std/path@^1.0.8" + ] + }, + "@deno/dnt@0.42.1": { + "integrity": "85322b38eb40d4e8c5216d62536152c35b1bda9dc47c8c60860610397b960223", + "dependencies": [ + "jsr:@david/code-block-writer", + "jsr:@deno/cache-dir", + "jsr:@std/fmt@1", + "jsr:@std/fs@1", + "jsr:@std/path@1", + "jsr:@ts-morph/bootstrap" + ] + }, + "@deno/graph@0.86.9": { + "integrity": "c4f353a695bcc5246c099602977dabc6534eacea9999a35a8cb24e807192e6a1" + }, "@meshtastic/protobufs@2.7.0": { "integrity": "38357241bd8a7431c87366dbe12ce9e69f204ebb6ec23da12f7682765b6c8376", "dependencies": [ "npm:@bufbuild/protobuf@^2.2.3" ] }, + "@std/bytes@1.0.6": { + "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" + }, + "@std/fmt@1.0.8": { + "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" + }, + "@std/fs@1.0.19": { + "integrity": "051968c2b1eae4d2ea9f79a08a3845740ef6af10356aff43d3e2ef11ed09fb06", + "dependencies": [ + "jsr:@std/internal", + "jsr:@std/path@^1.1.1" + ] + }, "@std/internal@1.0.9": { "integrity": "bdfb97f83e4db7a13e8faab26fb1958d1b80cc64366501af78a0aee151696eb8" }, + "@std/io@0.225.2": { + "integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7", + "dependencies": [ + "jsr:@std/bytes" + ] + }, "@std/path@1.1.1": { "integrity": "fe00026bd3a7e6a27f73709b83c607798be40e20c81dde655ce34052fd82ec76", "dependencies": [ "jsr:@std/internal" ] + }, + "@ts-morph/bootstrap@0.25.0": { + "integrity": "3cd33ee80ac0aab8e5d2660c639a02187f0c8abfe454636ce86c00eb7e8407db", + "dependencies": [ + "jsr:@ts-morph/common" + ] + }, + "@ts-morph/common@0.25.0": { + "integrity": "e3ed1771e2fb61fbc3d2cb39ebbc4f89cd686d6d9bc6d91a71372be055ac1967", + "dependencies": [ + "jsr:@std/fs@1", + "jsr:@std/path@1" + ] } }, "npm": { @@ -1681,8 +1756,8 @@ "@tanstack/history@1.121.34": { "integrity": "sha512-YL8dGi5ZU+xvtav2boRlw4zrRghkY6hvdcmHhA0RGSJ/CBgzv+cbADW9eYJLx74XMZvIQ1pp6VMbrpXnnM5gHA==" }, - "@tanstack/react-router-devtools@1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-eRg6Ht6bLno+Eo2Gps3cfjp++Mvy0brc6qs81At4beKZsCkS7jlmqHgrq6pXdH3l2bAQ/Dhr8J9zXvzxvRxf/g==", + "@tanstack/react-router-devtools@1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-3+Np/HPQ1jpdai58xY6fScnjJz08iIG6aKhCVVy8tfPC76jTyXc+ygqM9wtUt3kJYy9/Lf7j3dAJlbtxF+TIXg==", "dependencies": [ "@tanstack/react-router", "@tanstack/router-devtools-core", @@ -1690,8 +1765,8 @@ "react-dom" ] }, - "@tanstack/react-router@1.125.4_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-IIlDiFCR+RN/17dWtYKMYiJvH38tmtgTyciHkeZvr8vSWhThAeuwjzKneF4mQl3B//YHYcrFm7rZM59c24As/A==", + "@tanstack/react-router@1.125.6_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-znyUGTq+WRhXwToNTYiluUBLjMdQVxz+ZQ9Ep2PBuS9O+3Qm3kaM7n64hA84ISoCtLqMwTo7Ofw0W4WeLdjpYg==", "dependencies": [ "@tanstack/history", "@tanstack/react-store", @@ -1743,8 +1818,8 @@ "tiny-invariant" ] }, - "@tanstack/router-devtools@1.125.4_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { - "integrity": "sha512-VpCxC80C+t+HNt8xuRGoXDwV+0c1LFDNzOdL/dPlYSuTZWLd8zwOEi49oMaNSLeGJFLwgQx7FLP020UvQO6pMg==", + "@tanstack/router-devtools@1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_react@19.1.0_react-dom@19.1.0__react@19.1.0": { + "integrity": "sha512-Orlf0+5wANehVq5ocxfe3YyJnEtvc5tcNN/ldX20fOKyYeIhVQzR8Oa6RO3Jk2sY31grMwi6q199MTAJ7XshLQ==", "dependencies": [ "@tanstack/react-router", "@tanstack/react-router-devtools", @@ -1767,8 +1842,8 @@ "zod" ] }, - "@tanstack/router-plugin@1.125.5_@tanstack+react-router@1.125.4__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0": { - "integrity": "sha512-blik4+pgwv0PEGYTtkVy6USQBwbPVex1WOBBfRudOaBf8vnGe7lBoEHZi6fora8QlmdTsEVhqX6IHDXuf3pWaQ==", + "@tanstack/router-plugin@1.125.6_@tanstack+react-router@1.125.6__react@19.1.0__react-dom@19.1.0___react@19.1.0_vite@7.0.2__@types+node@22.16.0__picomatch@4.0.2_@babel+core@7.28.0_react@19.1.0_react-dom@19.1.0__react@19.1.0_@types+node@22.16.0": { + "integrity": "sha512-SWfp++tkjb0grVqa/Xdvi9QAs93e9/fZMBZ6q0fvvQruMyciCmjWyE/qV3tS/Qh0WZdzIRP6yl8Gha2Lin4q1w==", "dependencies": [ "@babel/core", "@babel/plugin-syntax-jsx", @@ -3742,8 +3817,8 @@ "earcut@3.0.1": { "integrity": "sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==" }, - "electron-to-chromium@1.5.179": { - "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==" + "electron-to-chromium@1.5.180": { + "integrity": "sha512-ED+GEyEh3kYMwt2faNmgMB0b8O5qtATGgR4RmRsIp4T6p7B8vdMbIedYndnvZfsaXvSzegtpfqRMDNCjjiSduA==" }, "emoji-regex@8.0.0": { "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" @@ -5105,6 +5180,7 @@ }, "workspace": { "dependencies": [ + "jsr:@deno/dnt@~0.42.1", "jsr:@meshtastic/protobufs@^2.7.0", "npm:@bufbuild/protobuf@^2.2.3", "npm:@types/node@^22.13.10", diff --git a/packages/core/README.md b/packages/core/README.md index 18ce7cf7..cca9d9d1 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -11,6 +11,7 @@ `@meshtastic/core` Provides core functionality for interfacing with Meshtastic devices. Installation instructions are available at [JSR](https://jsr.io/@meshtastic/core) +[NPM](https://www.npmjs.com/org/meshtastic) ## Usage diff --git a/packages/core/deno.json b/packages/core/deno.json index fb29ac95..624babd1 100644 --- a/packages/core/deno.json +++ b/packages/core/deno.json @@ -1,6 +1,7 @@ { "name": "@meshtastic/core", "version": "2.6.4", + "description": "Core functionalities for Meshtastic web applications.", "exports": { ".": "./mod.ts" }, diff --git a/packages/transport-deno/README.md b/packages/transport-deno/README.md index 1c5213f8..1193c476 100644 --- a/packages/transport-deno/README.md +++ b/packages/transport-deno/README.md @@ -11,6 +11,7 @@ `@meshtastic/transport-deno` Provides TCP transport (Deno) for Meshtastic devices. Installation instructions are avaliable at [JSR](https://jsr.io/@meshtastic/transport-deno) +[NPM](https://www.npmjs.com/org/meshtastic/transport-deno) ## Usage diff --git a/packages/transport-deno/deno.json b/packages/transport-deno/deno.json index 50968ed6..39a9178a 100644 --- a/packages/transport-deno/deno.json +++ b/packages/transport-deno/deno.json @@ -1,6 +1,7 @@ { "name": "@meshtastic/transport-deno", "version": "0.1.1", + "description": "Deno-specific transport layer for Meshtastic web applications.", "exports": { ".": "./mod.ts" } diff --git a/packages/transport-http/README.md b/packages/transport-http/README.md index 560b44b4..6fc0e854 100644 --- a/packages/transport-http/README.md +++ b/packages/transport-http/README.md @@ -11,6 +11,7 @@ `@meshtastic/transport-http` Provides HTTP(S) transport for Meshtastic devices. Installation instructions are available at [JSR](https://jsr.io/@meshtastic/transport-http) +[NPM](https://www.npmjs.com/package/@meshtastic/transport-http) ## Usage diff --git a/packages/transport-http/deno.json b/packages/transport-http/deno.json index 1bcb8348..0c3bf171 100644 --- a/packages/transport-http/deno.json +++ b/packages/transport-http/deno.json @@ -1,6 +1,7 @@ { "name": "@meshtastic/transport-http", "version": "0.2.1", + "description": "A transport layer for Meshtastic applications using HTTP.", "exports": { ".": "./mod.ts" } diff --git a/packages/transport-web-bluetooth/README.md b/packages/transport-web-bluetooth/README.md index ab1af911..fc790284 100644 --- a/packages/transport-web-bluetooth/README.md +++ b/packages/transport-web-bluetooth/README.md @@ -11,6 +11,7 @@ `@meshtastic/transport-web-bluetooth` Provides Web Bluetooth transport for Meshtastic devices. Installation instructions are available at [JSR](https://jsr.io/@meshtastic/transport-web-bluetooth) +[NPM](https://www.npmjs.com/org/meshtastic/transport-web-bluetooth) ## Usage diff --git a/packages/transport-web-bluetooth/deno.json b/packages/transport-web-bluetooth/deno.json index 6aab4b7b..169ad310 100644 --- a/packages/transport-web-bluetooth/deno.json +++ b/packages/transport-web-bluetooth/deno.json @@ -1,6 +1,7 @@ { "name": "@meshtastic/transport-web-bluetooth", "version": "0.1.2", + "description": "A transport layer for Meshtastic applications using Web Bluetooth.", "exports": { ".": "./mod.ts" }, diff --git a/packages/transport-web-serial/README.md b/packages/transport-web-serial/README.md index 81c08b99..7022a649 100644 --- a/packages/transport-web-serial/README.md +++ b/packages/transport-web-serial/README.md @@ -11,6 +11,7 @@ `@meshtastic/transport-web-serial` Provides Web Serial transport for Meshtastic devices. Installation instructions are avaliable at [JSR](https://jsr.io/@meshtastic/transport-web-serial) +[NPM](https://www.npmjs.com/package/@meshtastic/transport-web-serial) ## Usage diff --git a/packages/transport-web-serial/deno.json b/packages/transport-web-serial/deno.json index 45a90622..c6f3ead1 100644 --- a/packages/transport-web-serial/deno.json +++ b/packages/transport-web-serial/deno.json @@ -1,6 +1,7 @@ { "name": "@meshtastic/transport-web-serial", "version": "0.2.1", + "description": "A transport layer for Meshtastic applications using Web Serial API.", "exports": { ".": "./mod.ts" }, diff --git a/packages/web/deno.json b/packages/web/deno.json index a3da671b..21f97a4a 100644 --- a/packages/web/deno.json +++ b/packages/web/deno.json @@ -45,7 +45,6 @@ ], "strictPropertyInitialization": false }, - "exclude": [ "routeTree.gen.ts", "node_modules/", diff --git a/scripts/build_npm_package.ts b/scripts/build_npm_package.ts new file mode 100644 index 00000000..49b7a7aa --- /dev/null +++ b/scripts/build_npm_package.ts @@ -0,0 +1,101 @@ +import { build, emptyDir } from "@deno/dnt"; +import { join } from "jsr:@std/path@1/join"; + +interface DenoJsonConfig { + name: string; + version: string; + description: string; + imports?: Record; + exports?: Record; +} + +async function getJson(filePath: string) { + try { + return JSON.parse(await Deno.readTextFile(filePath)); + } catch (e) { + if (e instanceof Error) { + throw new Error(`Error reading or parsing ${filePath}: ${e.message}`); + } + } +} + +if (Deno.args.length !== 1) { + console.error("Usage: deno task build:npm "); + console.error( + "Example: deno task build:npm packages/core", + ); + Deno.exit(1); +} + +const packagePath = Deno.args[0]; +const denoJsonPath = join(packagePath, "deno.json"); +const outDir = join(packagePath, "npm"); + +// Read the deno.json file to get the package metadata. +let jsonContent: DenoJsonConfig; + +try { + jsonContent = await getJson(denoJsonPath); +} catch (error) { + console.log(`Error reading or parsing ${denoJsonPath}:`, error); + + if (error instanceof Deno.errors.NotFound) { + console.error(`Error: Config file not found at ${denoJsonPath}`); + } else { + console.error(`Error reading or parsing ${denoJsonPath}:`, error); + } + Deno.exit(1); +} + +const { name, version, description } = jsonContent; + +if (!name || !version || !description) { + console.error( + `Error: 'name', 'version', and 'description' must be defined in ${denoJsonPath}`, + ); + Deno.exit(1); +} + +console.log(`Building ${name}@${version} from ${packagePath}...`); + +// Clean the output directory before building. +await emptyDir(outDir); + +try { + await build({ + entryPoints: [join(packagePath, "mod.ts")], + outDir, + test: false, + shims: { + deno: true, + }, + package: { + name, + version, + description, + license: "GPL-3.0-only", + repository: { + type: "git", + url: "git+https://github.com/meshtastic/web.git", + }, + bugs: { + url: "https://github.com/meshtastic/web/issues", + }, + }, + compilerOptions: { + lib: ["DOM", "ESNext"], + }, + postBuild() { + Deno.copyFileSync("LICENSE", join(outDir, "LICENSE")); + Deno.copyFileSync( + join(packagePath, "README.md"), + join(outDir, "README.md"), + ); + }, + }); +} catch (error) { + console.error(`Error building ${name}@${version}:`, error); + Deno.exit(1); +} + +console.log(`✅ Successfully built ${name}@${version} to ${outDir}`);