2024/10/05 ~ 2024/10/11 のもくもく日記
もくもく 前回までは
2024/09/28 ~ 2024/10/04 のもくもく日記 をご覧ください。
途中経過
その1
とりあえずGoogle のサービスアカウント認証情報を使って、 Spreadsheet に記入したデータからCSV ファイルを作るサンプルが出来た!
const { google } = require('googleapis');
const { writeFile } = require('node:fs/promises');
const path = require('node:path');
const { argv } = require('node:process');
/**
* HTTP Status Code データをGoogle Spreadsheet から取得し、CSV 出力する
*
* @example
* generators 配下に `credentials.json` というファイルを作成し、
* [サービスアカウント認証情報](https://cloud.google.com/iam/docs/service-account-creds) の内容を保存した上で下記コマンドを実行してください。
*
* ``` shell
* node generators/create-status-code-csv.js 'sheetId'
* ```
*
* @param {string} sheetId データがあるSpreadsheet のID
*/
+async function (
sheetId,
) {
if (!sheetId) {
throw Error();
}
const sheetApiClient = await getSheetsApi();
const targetSheet = await sheetApiClient.spreadsheets.values.get({
spreadsheetId: sheetId,
range: 'シート1',
});
const csv = toCSV(targetSheet.data.values);
if (!csv) {
throw Error();
}
await writeFile(
path.join(__dirname, 'HttpStatusCodeGenerator', 'Data', 'HttpStatusCode2.csv'),
csv,
{ encoding: 'utf-8' },
);
}(
argv[2],
);
/**
* Google Sheets API の操作クライアントの取得
*/
async function getSheetsApi() {
// 参考: https://github.com/googleapis/google-api-nodejs-client/issues/1699#issuecomment-1770598231
const jwt = new google.auth.JWT({
keyFile: path.join(__dirname, 'credentials.json'),
scopes: [
'https://www.googleapis.com/auth/spreadsheets.readonly',
]
});
await jwt.authorize();
return google.sheets({ version: 'v4', auth: jwt });
}
/**
* Sheet データをCSV 形式に変換
*
* @param {any[][]|null|undefined} values
*/
function toCSV(values) {
if (!values) { return; }
const list = values;
const header = list.shift();
if (!header) { return; }
const indexCode = header.findIndex(x => x === 'Code');
if (indexCode < 0) { return; }
const indexName = header.findIndex(x => x === 'Name');
if (indexName < 0) { return; }
const indexOldName = header.findIndex(x => x === 'OldName');
if (indexOldName < 0) { return; }
const indexNote = header.findIndex(x => x === 'Note');
if (indexNote < 0) { return; }
const indexCaution = header.findIndex(x => x === 'Caution');
if (indexCaution < 0) { return; }
const indexHasMDN = header.findIndex(x => x === 'HasMDN');
if (indexHasMDN < 0) { return; }
const indexUrl1 = header.findIndex(x => x === 'Url1');
if (indexUrl1 < 0) { return; }
const indexUrl2 = header.findIndex(x => x === 'Url2');
if (indexUrl2 < 0) { return; }
const lines = [
[
header[indexCode],
header[indexName],
header[indexOldName],
header[indexNote],
header[indexCaution],
header[indexHasMDN],
header[indexUrl1],
header[indexUrl2],
].join(','),
];
list.map(item => [
item[indexCode],
item[indexName],
item[indexOldName],
item[indexNote],
item[indexCaution],
item[indexHasMDN],
item[indexUrl1],
item[indexUrl2],
]).forEach(array => {
const separator = ',';
const line = array.join(separator);
const regex = new RegExp(`^${separator}+$`);
if (!regex.test(line)) {
lines.push(line);
}
});
return lines.join('\n');
}
https://github.com/tshion/mktools_lab/blob/main/generators/create-status-code-csv.js
その2
Jinja にインスパイヤされたNunjucks のサンプルも仮実装できた!
const { google } = require('googleapis');
const { writeFile } = require('node:fs/promises');
const path = require('node:path');
const { argv } = require('node:process');
const nunjucks = require('nunjucks');
/**
* HTTP Status Code データをGoogle Spreadsheet から取得し、TypeScript 実装を出力する
*
* @example
* generators 配下に `credentials.json` というファイルを作成し、
* [サービスアカウント認証情報](https://cloud.google.com/iam/docs/service-account-creds) の内容を保存した上で下記コマンドを実行してください。
*
* ``` shell
* node generators/create-status-code-ts.js 'sheetId'
* ```
*
* @param {string} sheetId データがあるSpreadsheet のID
*/
+async function (
sheetId,
) {
if (!sheetId) {
throw Error();
}
const sheetApiClient = await getSheetsApi();
const targetSheet = await sheetApiClient.spreadsheets.values.get({
spreadsheetId: sheetId,
range: 'シート1',
});
const data = parseSheet(targetSheet.data.values);
if (!data) {
throw Error();
}
const replaced = nunjucks.render(
path.join(__dirname, 'HttpStatusCodeGenerator', 'Templates', 'http-status-code.ts.template'),
{ list: data },
);
await writeFile(
path.join(__dirname, 'http-status-code.ts'),
replaced,
{ encoding: 'utf-8' },
);
}(
argv[2],
);
/**
* Google Sheets API の操作クライアントの取得
*/
async function getSheetsApi() {
// 参考: https://github.com/googleapis/google-api-nodejs-client/issues/1699#issuecomment-1770598231
const jwt = new google.auth.JWT({
keyFile: path.join(__dirname, 'credentials.json'),
scopes: [
'https://www.googleapis.com/auth/spreadsheets.readonly',
]
});
await jwt.authorize();
return google.sheets({ version: 'v4', auth: jwt });
}
/**
* Sheet データの解析
*
* @param {any[][]|null|undefined} values
*/
function parseSheet(values) {
if (!values) { return; }
const list = values;
const header = list.shift();
if (!header) { return; }
const indexCode = header.findIndex(x => x === 'Code');
if (indexCode < 0) { return; }
const indexName = header.findIndex(x => x === 'Name');
if (indexName < 0) { return; }
const indexOldName = header.findIndex(x => x === 'OldName');
if (indexOldName < 0) { return; }
const indexNote = header.findIndex(x => x === 'Note');
if (indexNote < 0) { return; }
const indexCaution = header.findIndex(x => x === 'Caution');
if (indexCaution < 0) { return; }
const indexHasMDN = header.findIndex(x => x === 'HasMDN');
if (indexHasMDN < 0) { return; }
const indexUrl1 = header.findIndex(x => x === 'Url1');
if (indexUrl1 < 0) { return; }
const indexUrl2 = header.findIndex(x => x === 'Url2');
if (indexUrl2 < 0) { return; }
const regex = /(?<rfc>rfc\d{4,})/;
return list
.filter(item => 0 < parseInt(item[indexCode]))
.map(item => {
const code = item[indexCode];
const links = [];
if (item[indexHasMDN]) {
links.push({
title: 'MDN Web Docs',
url: `https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/${code}`,
});
}
[
item[indexUrl1],
item[indexUrl2],
].map(url => `${url}`).forEach(url => {
const found = url.match(regex)?.groups;
if (found) {
links.push({
title: found.rfc.toUpperCase(),
url,
})
}
});
const name = `${item[indexName]}`;
return {
code,
key: name.replaceAll(`I'm`, 'I am').split(' ').flatMap(x => x.split('-')).join(''),
links,
name,
};
});
}
https://github.com/tshion/mktools_lab/blob/main/generators/create-status-code-ts.js
その3
GitHub のCodeQL をよく見てみたら、 Swift はUIKit にも対応しているっぽい 👀
その4
GitHub Dependabot を使ってAngular のバージョン更新PR を自動生成しているけど、 angular/cli などのパッケージ毎の単位でPR 生成され、 さらにマージするとDependabot の再チェックが走って既存PR のアプデが走ったりしてちょっと面倒だったので、下記を適用してみた。
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
groups:
angular:
applies-to: version-updates
patterns:
- "@angular*"
update-types:
- "minor"
- "patch"
今回の進捗
- GitHub
- Nintendo Switch でトレーニングを進めた
- 本を読み進めた