clasp + TypeScriptで作成したときの変換の挙動をメモする

zennに書こうと思ったけど、ほとんど自明なことなのでブログにメモとして残します。

残課題はarrayの関数の変換

claspとは

googleが作成しているGASをローカル上で開発できるようにしているツールです。 - https://github.com/google/clasp

TypeScriptにも対応しているため、型の恩恵等を受けることができます。 - https://github.com/google/clasp/blob/master/docs/typescript.md - 内部的にはts2gasを利用しているそうです。 - https://github.com/grant/ts2gas

初期設定

まずはプロジェクトの初期設定をします。 プロジェクトを作成して、型定義のnpmを追加します。 clasp系の設定はリンク等を参照してください。 - https://qiita.com/HeRo/items/4e65dcc82783b2766c03

npm init -y
mkdir src
npm i -S @types/google-apps-script
clasp create --type standalone --rootDir ./src
  • 公式のドキュメントにしたがって、tsconfig.jsonも設定します。
{
  "compilerOptions": {
    "lib": ["esnext"],
    "experimentalDecorators": true
  }
}
  • 最初の挙動を確かめるために、サンプルにあったソースをそのまま利用します。
const greeter = (person: string) => {
  return `Hello, ${person}!`;
}

function testGreeter() {
  const user = 'Grant';
  Logger.log(greeter(user));
}
  • GASにプッシュします。
clasp push
  • GASのコンソールから結果を確認してみます。
  • constがvarになっているのと文字の連結が変わっています。
// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var greeter = function (person) {
    return "Hello, " + person + "!";
};
function testGreeter() {
    var user = 'Grant';
    Logger.log(greeter(user));
}

各種挙動を確認する

  • class等の記法がどのような形で変換されるのかを見ていきます。

class

  • 変換前
class Clazz {
  constructor(private member: number) {}

    get item() {
        return this.getItem();
    }

    getMember() {
        return this.getMember();
    }

    private getItem() {
        return 'item';
    }

    static factory(member: number) {
        return new Clazz(member);
    }
}
  • 変換後。prototypeベースに置き換わっています。
// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var Clazz = /** @class */ (function () {
    function Clazz(member) {
        this.member = member;
    }
    Object.defineProperty(Clazz.prototype, "item", {
        get: function () {
            return this.getItem();
        },
        enumerable: false,
        configurable: true
    });
    Clazz.prototype.getMember = function () {
        return this.getMember();
    };
    Clazz.prototype.getItem = function () {
        return 'item';
    };
    Clazz.factory = function (member) {
        return new Clazz(member);
    };
    return Clazz;
}());

import/export

変換前

  • module.ts
export const hoge = () => 'hoge';

export const constTest = 'test'
  • sample.ts
import { hoge, constTest } from "./module";

function test() {
    console.log(hoge());
    console.log(constTest);
}

変換後

  • module.gs
// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var exports = exports || {};
var module = module || { exports: exports };
exports.constTest = exports.hoge = void 0;
var hoge = function () { return 'hoge'; };
exports.hoge = hoge;
exports.constTest = 'test';
  • sample.gs
// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var exports = exports || {};
var module = module || { exports: exports };
//import { constTest, hoge } from "./module";

hoge();
  • sample.gsは実行すると失敗します
ReferenceError: constTest is not defined
  • よくよく見てみると、export const で定義したfunctionは成功しますが、変数はエラーになっています。
  • これは、module.tsでhogeはvarとして定義されているために、global変数だとみなされているため参照できるようになっています。
  • ただし、constTestはexportsのメンバ変数として定義されているので、exports.constTestのように呼び出ししないとうまく動作しません

    • にしても、exportsがグローバルなので、変数の競合があると意図しない動きになると思います。
  • 解消方法としては以下の3点があります。ここでは詳細では取り上げません。興味があれば公式のドキュメントを見てみてください。

    • exportsを明示的に変数として定義して、そこから読み込むようにする
      • なんかトリッキーな書き方ですね。複数のモジュールをimportしたいときにうまく動かなそうな感じがする。
    • namespaceを利用する
      • namespace使っていいのか問題はあるが、割と簡単。
    • 先にwebpack等でトランスパイルしてからGASにプッシュする
      • GAS上で見にくくなってもいいならよさそう

namespace

変換前

namespace Module {
  export function foo() {}
  function bar() {}  // this function can only be addressed from within the `Module` namespace
}

変換後

// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var Module;
(function (Module) {
    function foo() { }
    Module.foo = foo;
    function bar() { } // this function can only be addressed from within the `Module` namespace
})(Module || (Module = {}));
  • Moduleという変数が定義されていて、それの変数として、foo、barが定義されています。
  • そのため、moduleは外からの呼び出しにも対応できます。

array

変換前

const number = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

number.find((i) => i === 10);
number.findIndex((i) => i === 10);
number.filter((i) => i % 2);
number.map((i) => i ^ i);
number.reduce((pre, cur) => pre + cur, 0);
number.some((i) => i % 2);
number.slice(0);
[...number].sort((a, b) => b - a);
number.forEach(a => a);
number.every(i => true);

変換後

// Compiled using clasp-test 1.0.0 (TypeScript 4.3.5)
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
    for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
        to[j] = from[i];
    return to;
};
var number = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
number.find(function (i) { return i === 10; });
number.findIndex(function (i) { return i === 10; });
number.filter(function (i) { return i % 2; });
number.map(function (i) { return i ^ i; });
number.reduce(function (pre, cur) { return pre + cur; }, 0);
number.some(function (i) { return i % 2; });
number.slice(0);
__spreadArray([], number).sort(function (a, b) { return b - a; });
number.forEach(function (a) { return a; });
number.every(function (i) { return true; });
  • スプレッド変数のみ変換がかかっていて、ほかのarrayはそのままになっています。
  • ES3相当の変換なのに、ES3で存在しないはずの変数が残っている。。ここではまったので別の機会に解消の仕方を書きます。

育休からはや半年経過

育児休暇から早くも半年がたとうとしています。 色々振り返ってみたことを記載しておきます。

育休はやっぱりいい

平日はどうしても仕事が大半の時間を占めるので、子供と向き合える時間は結構少ないと改めて感じている。

特に生まれてすぐは成長が早いので、日ごとにできることが変わっていく。

最近だと、ずりばい覚えたらすぐに家じゅうを動き回るようになったり。

そんな中で、子供とゆっくり(夜に強制的に起こされたりはするけど)接する時間を持てたことはとてもありがたい。

仕事について

家でコロナの感染者が出ると、色々と大変なので、在宅勤務をメインとしている。

長女が保育園から帰った後に一気に家事の負担が増えるので、なるべく仕事を早い時間に終わらせたい。

そのため、朝5時~7時で仕事をすることによって18時までには仕事を終わらせるようにしている。 7時~9時は家族と一緒にすごして、9時ごろからまた仕事している。

朝の時間は勉強や技術記事書いたりする時間にあてていることも多いので、めっちゃ仕事しているわけではないが。。

変則的な働き方でも特に文句言われたりしないので、今の会社で働けていることにとても感謝している。

ちなみに、夜は子供と一緒に寝ることにしているので、22時くらいに寝ることが多い。

働き方について

子供と過ごす時間が以前と比べてだいぶ長くなった。 以前だったら、朝ご飯を食べさせて、保育園に一緒行くくらいしか時間がなかった。夜は帰ったら大体寝ているか寝かしつけの途中で話す時間はなかった。 子供とかかわれる時間が増えたことはうれしい。ご飯食べたら一緒に遊んだり、お風呂はいったり。

一方で、自分の時間がめっちゃ減っている。 今までは通勤の時間は自由だったので、読書など好きなことをしていた。 今は在宅勤務なので、移動時間がない。そのため、家事 → 仕事 → 家事のようにやることが常にあって、のんびりする時間がない。 子供が一人遊びうまくなってきたので、もうちょっとすれば、夕食後に時間が取れるようになるのかもしれない。 まあ、一緒に遊んでくれるのもそんなに長くないと思うので、できる限りは遊んであげたいとは思う。

体重を定期的に計測して1年が経過した

前職の健康保険組合ではポイントが毎年付与されていた。

健康に関するもの限定ではあったが、交換する商品は幅広く、医薬品以外にもApple Watchやキャンプ用品など結構なんでもありだった。

前職を辞めるときに使い切る必要があり、色々買ったものの中に体重計があった。

www.amazon.co.jp

ずっと前に、体重を毎日はかるだけで痩せるっていう紹介がテレビでされていた。

その際にしばらく体重を毎日はかってみたが、特に効果がなかったのでそれ以来は体重をはかる習慣はなかった。

今回はスマホ連携できる体重計を手に入れたので、体重を毎日記録することにした。

記録するコストが小さいので、1年以上たった今でも毎日体重測定ができている。

1年間体重測定だけした結果、体重がグラフのようになった。

f:id:nyaonyaoto:20210910055712p:plain
体重測定

数値だと大体75kg → 68kg。

一時期、リングフィットして運動していたにしても、基本的に在宅勤務で全然動かないのに体重はだいぶ減った。

良かったのは以下の3点なのかなと考えている。

  • 定期的に体重計に乗ることによって、その日に食べたもののフィードバックができる

    • 体重が増えると、その日に食べ過ぎたのか、何か別の要因があるのか考えさせられる
    • 大体の場合、平日は体重が減って、土日にちょっと戻るっていうのを繰り返している
    • 平日はお昼ご飯をぱっと済ませることが多いので、その影響が大きいのだろう。
    • リングフィットした当日は体重はちょっと増え気味で、翌日から減るパターンが多かった気がする。あれ、筋肉量減っているってことか?  
  • ご飯の量を減らした

    • お米の量をはかることが増えた。今は1食130gくらいかな。
    • ただ、長女が残したやつも結構食べているので、150gくらいな気がする。
    • そうめん茹でると何故か目測を誤って茹ですぎるらしく、体重が増える。
  • 単純に体重が減るとうれしいので正のフィードバックが働く

    • 今日はお菓子食べなかったから体重減っているなーとか考えるの楽しい

どうでもいいけど、markdown記法で日記っぽく書くのなんか難しい。

AppSyncでnodeクライアントアプリを作成後、webpackでバンドルすると「realFetch.call is not a function」というエラーが発生する

何度かはまったので、メモです。

  • isomorphic-fetchの特定のバージョンでwebpackした場合にうまく動作しなくなるエラーが発生します。

github.com

  • isomorphic-fetchが3.0.0だと発生するので、2.2.1以下のバージョンに変更してあげる必要があります。

  • おそらく、このチュートリアルをなぞって開発すると発生します(未検証) docs.aws.amazon.com

  • 以前のチュートリアルだとisomorphic-fetchのバージョン指定があったのだが、いつの間にかなくなってる。。

余談

  • はじめてPR送ったけど、数か月だった今でも反応なし。。

github.com

npm7にバージョンアップした後にserverless frameworkでエラーが出るようになった

メモです。

概要

npmのバージョンを7にしました。

そのあとに以前から使っていたプロジェクトでserverless deployをしたところ以下のようなエラーが出ました

npm.cmd ls -prod -json -depth=1 failed with code 1

環境

  • Operating System: win32
  • Node Version: 14.17.0
  • Framework Version: 2.55.0 (local)
  • npm 7.20.6

エラー詳細と調査

Error: npm.cmd ls -prod -json -depth=1 failed with code 1
      at ChildProcess.<anonymous> (C:\workspace\xxxx\node_modules\serverless-webpack\lib\utils.js:91:16)
      at ChildProcess.emit (events.js:376:20)
      at ChildProcess.emit (domain.js:470:12)
      at maybeClose (internal/child_process.js:1055:16)
      at Process.ChildProcess._handle.onexit (internal/child_process.js:288:5)
  • エラーの文字文字列を調べてもなかなかわからず、node_modulesを削除してみたり、yarn.lockを削除したりしました。が全然解消しませんでした。
  • serverless offlineは起動するのとエラーの発生した部分がwebpackだったのでその周辺を調査すると原因がわかりました。

解決

  • 以下のリンクと同じ原因でした。なので、serverless webpackのバージョンを上げるか、serverless-webpackのpackeagerをyarnに変更してあげればOK github.com

  • serverless-webpackのプラグインは一部のエラーは無視するように作られているようです。

  • npm7でエラーの出力形式が変わったために、従来は無視できていたエラーが引っかかるようになってしまったために発生するエラーのようです。

最後に

  • うまく検索できれば一発で解決できたのに。。勘所が鈍っている気がします。

育休2か月

本当は3月の最初に書こうと思っていたのですが遅くなってしまった。。。 育児休暇を取得して2か月がたちました。備忘としていろいろ書いていきます。

子供の成長について

  • 表情が豊かになってきた気がする。不満があると泣くのではなく、文句を言うのが何となくわかる感じ
  • 体重は 30g / day くらいで増えるらしいので、順調に成長している。まだ全然重くないけど、長時間抱っこしていると頭側が重くなってくる
  • ミルクは相変わらずあんまり飲まない。最初にやる気があっても、5分くらい飲んでいると満足するらしく寝てしまう。そのままではまずいので、1時間くらいかけて何とかして飲ませている。
  • ミルクの感覚が3時間おきから、4時間、夜には5時間になったのでちゃんと寝れるようになった。

時間について

  • 保育園は引き続き自粛していたので、制約なく自分の自由な時間があるのは1日1時間ないくらい。スマホ触るくらいであればちょいちょい時間はあるけど、子供の面倒見ないでそんなことしいて言いていいのか?ってなる。大体見ちゃうけど。
  • 義母に来てもらう間隔を隔日にしたので、家事をしているときなどは長女に我慢してもらうこともしばしば。家事と子供複数人の世話を一人でやっている世の中のお母さんってすごいなと改めて思う。

仕事について

  • スマホにslackが入っているのでslackのみ定期的に見ている。自分だけ仕事をしていないのにほかの人は仕事をどんどん進めているので、おいてかれる感じが強い。割り切ってあんまり見ないほうが良かったかもしれない。

育児休暇1か月

次女が生まれて1か月たったのでいろいろ思ったことをまとめておきます。 とりあえず世の中の親ってすごいわっていうのを改めて感じました。

戦略

  • 母乳とミルクは適度にバランスよくする
  • 3時間おきのミルクは交代しながら行う。睡眠不足は昼寝で何とかする
  • 義母には長女の相手と睡眠不足を補うためにきてもらう
  • 長女は通常通り保育園に通う

実際

  • 次女の体重が思ったより増えなかったので、最初の2週間は量がわかる哺乳瓶での授乳が必須になった
    • 母乳は搾乳したものをあげていた
    • 結果的にミルクの分担がしやすくてよかった
  • 緊急事態宣言により、保育園は自粛に。。
    • 義母に毎日来てもらって、主に娘の相手をしてもらう
  • 私は家事担当、妻は次女、義母は長女の担当みたいになった

買ってよかったもの

搾乳機

www.amazon.co.jp - 手動のものがすでに家にあったけど、最初は都度搾乳する必要があったので購入 - 搾乳の手間が大幅に省けたらしく、とてもよかった

フリーザーパック

www.amazon.co.jp - 搾乳した場合の保存に必須。

その他いろいろ

ミルクについて

最初は次女はあんまり積極的にミルクを飲まないので、欲しく無さそうでも、強制的にミルクを飲ませる必要がありました。 無理やり口開けて飲ませるので、めっちゃ嫌がっていて、ごめんねって思いながらあげてました。 ミルクあげた後にげっぷする顔が結構怖いです。目を開けて、絶対に忘れないぞって感じの表情してます。 最近は飲ませすぎるせいか、結構吐き戻しが多いです。初めてのときは結構焦るくらいの量出てきます。

生活リズム

生後1か月くらいは定期的にミルクをあげる必要があるので、3時間おきにミルクをあげていました。 夫婦で担当分けても少なくともどちらかはまとまった睡眠をとれなくなるので、結構しんどいです。

育児について

次女はミルク飲んでいる以外は大体寝てくれていたので、今のところ、そんなに大変ではない感じです。 これからどうなるやら。

緊急事態宣言の影響

出産の立ち合いが10分程度になったのと、入院時にお見舞いができなかったのが結構大きかったです。 長女はママに会えなくて寂しかったみたいで、初日は大変でした。 それ以外は、基本的に外に出ないので、そんなに影響はない気がします。

欲しいものリスト

欲しいものリストで思った以上にいろいろなものをいただきました。ありがとうございます。 まだ月齢的に出番のないものもありますが、基本的にめっちゃ使ってます。