GitHubAPIでリポジトリ作成しようとしたら出た。ユーザ情報の取得には成功したのになぜ?

ブツ

インストール&実行

NAME='Electron.GitHub.API.20220817000000'
git clone https://github.com/ytyaru/$NAME
cd $NAME
npm install
npm start
  1. db/setting.jsonrepositoryに任意のユーザ名、リポジトリ名(mytestrepo等)とrepoスコープ権限を持ったトークンをセットしファイル保存する
  2. dst/mytestrepo/.gitが存在しないことを確認する(あればdstごと削除する)
  3. Ctrl+Shift+Rキーを押す(リロードする)
  4. git initコマンドが実行される
    • repo/リポジトリ名ディレクトリが作成され、その配下に.gitディレクトリが作成される
  5. createRepo実行時、以下のようなダイアログが出てエラーになる

net_error.png

ダイアログUIからテキストコピーできなかったので手書きでメモった。

A JavaScript error occurred in the main process

Uncaught Exception:
Error: net:ERR_CONNECTION_REFUSED
  at SimpleURLLoaderWrapper.<anonymous> (node:electron/js2c/browser_init:101:7169)
  at SimpleURLLoaderWrapper.emit (node:events:527:28)

何がなんだかさっぱりわからん。以下のときはユーザ情報取得するGitHub APIに成功したのに。なんで今回はエラーなの? 同じくEelctronのnet.requestを使ったのに! 原因はユーザ取得APIからリポジトリ作成用APIに変えたことくらいしか思いつかない。

ググってみたけどさっぱり

これは誰が出したエラーなの? Electron? Node.js? Chromiumブラウザ? OSのネットワークシステム?

どうすれば解決するの? ググったページには以下のように絶望的なことが書いてあった。

ERR_CONNECTION_REFUSEDも問題が発生したことを知らせますが、問題が発生した理由を説明してくれません。真の原因を特定し、可能であれば処理するのはユーザーの仕事です。

ノーヒントとか無理ゲーだよorz

コード抜粋

main.js

const { app, BrowserWindow, ipcMain, dialog, net } = require('electron')
ipcMain.handle('request', async(event, params, onData=null, onEnd=null)=>{
    console.log('----- request -----')
    console.log(params)
    const request = net.request(params.params)
    if (params.hasOwnProperty('body')) { console.log(JSON.stringify(params.body)); request.write(JSON.stringify(params.body)); }
    console.log(request)
    request.on('response', (response) => {
        console.debug(`STATUS: ${response.statusCode}`)
        console.debug(`HEADERS: ${JSON.stringify(response.headers)}`)
        response.on('data', (chunk) => {
            console.debug(`BODY: ${chunk}`)
            if (onData) {
                onData(JSON.parse(chunk), response)
            }
        })
        response.on('end', () => {
            console.debug('No more data in response.')
            if (onEnd) {
                onEnd(response)
            }
        })
    })
    request.end()
})

preload.js

const {remote,contextBridge,ipcRenderer} =  require('electron');
contextBridge.exposeInMainWorld('myApi', {
    request:async(params)=>await ipcRenderer.invoke('request', params, onData=null, onEnd=null),
})

renderer.js

window.addEventListener('DOMContentLoaded', async(event) => {
    const setting = await Setting.load()
    const git = new Git(setting?.github)
    const hub = new GitHub(setting?.github)
    if (setting?.github?.repo) {
        document.getElementById('github-repo').value = setting.github.repo
        const exists = await git.init(document.getElementById('github-repo').value)
        if (!exists) {
            await hub.createRepo({
                name:setting.github.repo,
                description:"リポジトリの説明",
            })
        }
    }

github.js

class GitHub {
    constructor(opt=null) {
        this.username = opt?.username
        this.token = opt?.token
        this.branch = `master`
    }
    async createRepo(params) { // https://docs.github.com/ja/rest/repos/repos#create-a-repository-for-the-authenticated-user
        if (!params.hasOwnProperty('name')) {
            console.error(`引数paramsのプロパティにnameは必須です。`)
            return false
        }
        if (!this.#validRepoName(params.name)) {
            console.error(`引数params.nameの値が不正値です。英数字._-100字以内にしてください。`)
            return false
        }
        await window.myApi.request({
            'method': 'POST',
            url: 'https://api.github.com/user/repos',
            headers: {
                'Authorization': `token ${this.token}`,
            },
            "body": params,
        },(json, res)=>{
            console.debug(res)
            console.debug(json)
        },(res)=>{
            console.debug(res)
        })
        console.log(`リモートリポジトリを作成しました。`)
    }
    #validRepoName(name) { return name.match(/[a-zA-Z0-9\._\-]{1,100}/g) }