A Deno-compatible AT Protocol OAuth client that serves as a drop-in replacement for @atproto/oauth-client-node
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add npm publishing with trusted publishing (OIDC)

Add dnt build script to compile TypeScript for npm distribution.
Update publish workflow to publish to both JSR and npm using
GitHub Actions OIDC trusted publishing with provenance.

+171 -7
+35 -5
.github/workflows/publish.yml
··· 1 - name: Publish to JSR 1 + name: Publish 2 2 3 3 on: 4 4 push: ··· 6 6 - "v*" 7 7 8 8 jobs: 9 - publish: 9 + publish-jsr: 10 10 runs-on: ubuntu-latest 11 - 12 11 permissions: 13 12 contents: read 14 - id-token: write # Required for provenance generation 13 + id-token: write 15 14 16 15 steps: 17 16 - name: Checkout code 18 17 uses: actions/checkout@v4 19 18 20 19 - name: Setup Deno 21 - uses: denoland/setup-deno@v1 20 + uses: denoland/setup-deno@v2 22 21 with: 23 22 deno-version: v2.x 24 23 ··· 33 32 34 33 - name: Publish to JSR 35 34 run: deno publish 35 + 36 + publish-npm: 37 + runs-on: ubuntu-latest 38 + needs: publish-jsr 39 + permissions: 40 + contents: read 41 + id-token: write 42 + 43 + steps: 44 + - name: Checkout code 45 + uses: actions/checkout@v4 46 + 47 + - name: Setup Deno 48 + uses: denoland/setup-deno@v2 49 + with: 50 + deno-version: v2.x 51 + 52 + - name: Setup Node.js 53 + uses: actions/setup-node@v4 54 + with: 55 + node-version: "22" 56 + registry-url: "https://registry.npmjs.org" 57 + 58 + - name: Install latest npm 59 + run: npm install -g npm@latest 60 + 61 + - name: Build npm package 62 + run: deno task build:npm 63 + 64 + - name: Publish to npm 65 + run: cd npm && npm publish --provenance --access public
+1
.gitignore
··· 4 4 # Build outputs 5 5 dist/ 6 6 build/ 7 + npm/ 7 8 8 9 # Test coverage 9 10 coverage/
+78
_build_npm.ts
··· 1 + import { build, emptyDir } from "jsr:@deno/dnt@0.42.3"; 2 + 3 + const denoJson = JSON.parse(Deno.readTextFileSync("./deno.json")); 4 + 5 + await emptyDir("./npm"); 6 + 7 + await build({ 8 + entryPoints: ["./mod.ts"], 9 + outDir: "./npm", 10 + shims: {}, 11 + test: false, 12 + importMap: "./deno.json", 13 + filterDiagnostic(diagnostic) { 14 + const fileName = diagnostic.file?.fileName; 15 + if (fileName && fileName.includes("@std/assert")) return false; 16 + if (fileName && fileName.includes("@panva/jose")) return false; 17 + return true; 18 + }, 19 + compilerOptions: { 20 + lib: ["ES2022", "DOM"], 21 + }, 22 + package: { 23 + name: "@tijs/oauth-client-deno", 24 + version: denoJson.version, 25 + description: 26 + "AT Protocol OAuth client built with Web Crypto API - handle-focused alternative to @atproto/oauth-client-node", 27 + license: "MIT", 28 + repository: { 29 + type: "git", 30 + url: "git+https://github.com/tijs/oauth-client-deno.git", 31 + }, 32 + keywords: [ 33 + "atproto", 34 + "oauth", 35 + "bluesky", 36 + "authentication", 37 + "dpop", 38 + "web-crypto", 39 + ], 40 + dependencies: { 41 + "jose": "^6.0.0", 42 + }, 43 + }, 44 + postBuild() { 45 + // Fix the jose import in the built files since dnt bundles @panva/jose from JSR 46 + // but we want to use the npm jose package instead 47 + for (const dir of ["esm", "script"]) { 48 + for (const entry of [...Deno.readDirSync(`npm/${dir}/src`)]) { 49 + if (entry.isFile && entry.name.endsWith(".js")) { 50 + const filePath = `npm/${dir}/src/${entry.name}`; 51 + let content = Deno.readTextFileSync(filePath); 52 + if (content.includes("deps/jsr.io/@panva/jose")) { 53 + content = content.replace( 54 + /from\s+["']\.\.\/deps\/jsr\.io\/@panva\/jose\/[^"']+["']/g, 55 + 'from "jose"', 56 + ); 57 + content = content.replace( 58 + /require\(["']\.\.\/deps\/jsr\.io\/@panva\/jose\/[^"']+["']\)/g, 59 + 'require("jose")', 60 + ); 61 + Deno.writeTextFileSync(filePath, content); 62 + } 63 + } 64 + } 65 + } 66 + // Remove bundled jose files (we use the npm package instead) 67 + const removeDirRecursive = (path: string) => { 68 + try { 69 + Deno.removeSync(path, { recursive: true }); 70 + } catch { /* ignore */ } 71 + }; 72 + removeDirRecursive("npm/esm/deps"); 73 + removeDirRecursive("npm/script/deps"); 74 + 75 + Deno.copyFileSync("LICENSE", "npm/LICENSE"); 76 + Deno.copyFileSync("README.md", "npm/README.md"); 77 + }, 78 + });
+5 -1
deno.json
··· 26 26 "exclude": [ 27 27 ".github/", 28 28 ".vscode/", 29 + "npm/", 30 + "_build_npm.ts", 31 + "_build_import_map.json", 29 32 "coverage/", 30 33 "test/", 31 34 "*.test.ts", ··· 40 43 "fmt:fix": "deno fmt", 41 44 "lint": "deno lint", 42 45 "ci": "deno task fmt && deno task lint && deno task check && deno task test", 43 - "prepare": "deno task ci" 46 + "prepare": "deno task ci", 47 + "build:npm": "deno run -A _build_npm.ts" 44 48 }, 45 49 "fmt": { 46 50 "useTabs": false,
+52 -1
deno.lock
··· 1 1 { 2 2 "version": "5", 3 3 "specifiers": { 4 + "jsr:@david/code-block-writer@^13.0.3": "13.0.3", 5 + "jsr:@deno/dnt@0.42.3": "0.42.3", 4 6 "jsr:@panva/jose@6.1.0": "6.1.0", 5 7 "jsr:@std/assert@1.0.13": "1.0.13", 8 + "jsr:@std/fmt@1": "1.0.9", 9 + "jsr:@std/fs@1": "1.0.23", 10 + "jsr:@std/internal@^1.0.12": "1.0.12", 6 11 "jsr:@std/internal@^1.0.6": "1.0.12", 12 + "jsr:@std/path@1": "1.1.4", 13 + "jsr:@std/path@^1.1.4": "1.1.4", 14 + "jsr:@ts-morph/bootstrap@0.27": "0.27.0", 15 + "jsr:@ts-morph/common@0.27": "0.27.0", 7 16 "npm:@atproto/syntax@0.4.0": "0.4.0" 8 17 }, 9 18 "jsr": { 19 + "@david/code-block-writer@13.0.3": { 20 + "integrity": "f98c77d320f5957899a61bfb7a9bead7c6d83ad1515daee92dbacc861e13bb7f" 21 + }, 22 + "@deno/dnt@0.42.3": { 23 + "integrity": "62a917a0492f3c8af002dce90605bb0d41f7d29debc06aca40dba72ab65d8ae3", 24 + "dependencies": [ 25 + "jsr:@david/code-block-writer", 26 + "jsr:@std/fmt", 27 + "jsr:@std/fs", 28 + "jsr:@std/path@1", 29 + "jsr:@ts-morph/bootstrap" 30 + ] 31 + }, 10 32 "@panva/jose@6.1.0": { 11 33 "integrity": "9ecffef33d822f4326341ace652bf30eef30d4dc9f7134faf7901e5480c2e761" 12 34 }, 13 35 "@std/assert@1.0.13": { 14 36 "integrity": "ae0d31e41919b12c656c742b22522c32fb26ed0cba32975cb0de2a273cb68b29", 15 37 "dependencies": [ 16 - "jsr:@std/internal" 38 + "jsr:@std/internal@^1.0.6" 39 + ] 40 + }, 41 + "@std/fmt@1.0.9": { 42 + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" 43 + }, 44 + "@std/fs@1.0.23": { 45 + "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", 46 + "dependencies": [ 47 + "jsr:@std/internal@^1.0.12", 48 + "jsr:@std/path@^1.1.4" 17 49 ] 18 50 }, 19 51 "@std/internal@1.0.12": { 20 52 "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" 53 + }, 54 + "@std/path@1.1.4": { 55 + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", 56 + "dependencies": [ 57 + "jsr:@std/internal@^1.0.12" 58 + ] 59 + }, 60 + "@ts-morph/bootstrap@0.27.0": { 61 + "integrity": "b8d7bc8f7942ce853dde4161b28f9aa96769cef3d8eebafb379a81800b9e2448", 62 + "dependencies": [ 63 + "jsr:@ts-morph/common" 64 + ] 65 + }, 66 + "@ts-morph/common@0.27.0": { 67 + "integrity": "c7b73592d78ce8479b356fd4f3d6ec3c460d77753a8680ff196effea7a939052", 68 + "dependencies": [ 69 + "jsr:@std/fs", 70 + "jsr:@std/path@1" 71 + ] 21 72 } 22 73 }, 23 74 "npm": {