react-native-store-version 1.4.1 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +511 -51
  3. package/dist/checkVersion.d.ts +73 -0
  4. package/dist/checkVersion.d.ts.map +1 -0
  5. package/dist/checkVersion.js +193 -0
  6. package/dist/cli/check.js +38 -0
  7. package/dist/cli/checks/ids.js +111 -0
  8. package/dist/cli/checks/installed.js +51 -0
  9. package/dist/cli/checks/peers.js +31 -0
  10. package/dist/cli/checks/rollout.js +141 -0
  11. package/dist/cli/checks/store.js +71 -0
  12. package/dist/cli/checks/versions.js +83 -0
  13. package/dist/cli/index.js +43 -0
  14. package/dist/cli/main.js +182 -0
  15. package/dist/cli/output.js +77 -0
  16. package/dist/cli/packages.js +40 -0
  17. package/dist/cli/project/android.js +60 -0
  18. package/dist/cli/project/expo.js +194 -0
  19. package/dist/cli/project/files.js +42 -0
  20. package/dist/cli/project/gradle.js +145 -0
  21. package/dist/cli/project/index.js +10 -0
  22. package/dist/cli/project/ios.js +190 -0
  23. package/dist/cli/project/jsx.js +327 -0
  24. package/dist/cli/project/plist.js +166 -0
  25. package/dist/cli/project/sources.js +86 -0
  26. package/dist/cli/result.js +12 -0
  27. package/dist/compare.d.ts +31 -0
  28. package/dist/compare.d.ts.map +1 -0
  29. package/dist/compare.js +68 -0
  30. package/dist/detect.d.ts +68 -0
  31. package/dist/detect.d.ts.map +1 -0
  32. package/dist/detect.js +103 -0
  33. package/dist/errors.d.ts +33 -0
  34. package/dist/errors.d.ts.map +1 -0
  35. package/dist/errors.js +23 -0
  36. package/dist/fetchers/android.d.ts +53 -0
  37. package/dist/fetchers/android.d.ts.map +1 -0
  38. package/dist/fetchers/android.js +91 -0
  39. package/dist/fetchers/custom.d.ts +29 -0
  40. package/dist/fetchers/custom.d.ts.map +1 -0
  41. package/dist/fetchers/custom.js +41 -0
  42. package/dist/fetchers/ios.d.ts +61 -0
  43. package/dist/fetchers/ios.d.ts.map +1 -0
  44. package/dist/fetchers/ios.js +79 -0
  45. package/dist/index.d.ts +15 -14
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +9 -58
  48. package/dist/openStore.d.ts +29 -0
  49. package/dist/openStore.d.ts.map +1 -0
  50. package/dist/openStore.js +46 -0
  51. package/dist/policy.d.ts +75 -0
  52. package/dist/policy.d.ts.map +1 -0
  53. package/dist/policy.js +128 -0
  54. package/dist/react/DefaultForceModal.d.ts +26 -0
  55. package/dist/react/DefaultForceModal.d.ts.map +1 -0
  56. package/dist/react/DefaultForceModal.js +58 -0
  57. package/dist/react/DefaultWarningSheet.d.ts +26 -0
  58. package/dist/react/DefaultWarningSheet.d.ts.map +1 -0
  59. package/dist/react/DefaultWarningSheet.js +66 -0
  60. package/dist/react/StoreVersionModal.d.ts +52 -0
  61. package/dist/react/StoreVersionModal.d.ts.map +1 -0
  62. package/dist/react/StoreVersionModal.js +250 -0
  63. package/dist/react/StoreVersionProvider.d.ts +51 -0
  64. package/dist/react/StoreVersionProvider.d.ts.map +1 -0
  65. package/dist/react/StoreVersionProvider.js +69 -0
  66. package/dist/react/defaultUi.d.ts +72 -0
  67. package/dist/react/defaultUi.d.ts.map +1 -0
  68. package/dist/react/defaultUi.js +118 -0
  69. package/dist/react/engine.d.ts +146 -0
  70. package/dist/react/engine.d.ts.map +1 -0
  71. package/dist/react/engine.js +541 -0
  72. package/dist/react/texts.d.ts +43 -0
  73. package/dist/react/texts.d.ts.map +1 -0
  74. package/dist/react/texts.js +57 -0
  75. package/dist/react/useIsomorphicLayoutEffect.d.ts +3 -0
  76. package/dist/react/useIsomorphicLayoutEffect.d.ts.map +1 -0
  77. package/dist/react/useIsomorphicLayoutEffect.js +6 -0
  78. package/dist/react/useStoreVersion.d.ts +121 -0
  79. package/dist/react/useStoreVersion.d.ts.map +1 -0
  80. package/dist/react/useStoreVersion.js +23 -0
  81. package/dist/request.d.ts +78 -0
  82. package/dist/request.d.ts.map +1 -0
  83. package/dist/request.js +227 -0
  84. package/dist/resolve.d.ts +98 -0
  85. package/dist/resolve.d.ts.map +1 -0
  86. package/dist/resolve.js +218 -0
  87. package/dist/texts/ja.d.ts +8 -0
  88. package/dist/texts/ja.d.ts.map +1 -0
  89. package/dist/texts/ja.js +18 -0
  90. package/dist/vendor/compare-versions.d.ts +52 -0
  91. package/dist/vendor/compare-versions.d.ts.map +1 -0
  92. package/dist/vendor/compare-versions.js +111 -0
  93. package/package.json +84 -45
  94. package/src/checkVersion.ts +273 -0
  95. package/src/cli/check.ts +59 -0
  96. package/src/cli/checks/ids.ts +163 -0
  97. package/src/cli/checks/installed.ts +75 -0
  98. package/src/cli/checks/peers.ts +34 -0
  99. package/src/cli/checks/rollout.ts +183 -0
  100. package/src/cli/checks/store.ts +105 -0
  101. package/src/cli/checks/versions.ts +108 -0
  102. package/src/cli/index.ts +51 -0
  103. package/src/cli/main.ts +229 -0
  104. package/src/cli/output.ts +122 -0
  105. package/src/cli/packages.ts +43 -0
  106. package/src/cli/project/android.ts +96 -0
  107. package/src/cli/project/expo.ts +232 -0
  108. package/src/cli/project/files.ts +56 -0
  109. package/src/cli/project/gradle.ts +181 -0
  110. package/src/cli/project/index.ts +18 -0
  111. package/src/cli/project/ios.ts +284 -0
  112. package/src/cli/project/jsx.ts +354 -0
  113. package/src/cli/project/plist.ts +179 -0
  114. package/src/cli/project/sources.ts +118 -0
  115. package/src/cli/result.ts +34 -0
  116. package/src/compare.ts +101 -0
  117. package/src/detect.ts +178 -0
  118. package/src/errors.ts +63 -0
  119. package/src/fetchers/android.ts +136 -0
  120. package/src/fetchers/custom.ts +84 -0
  121. package/src/fetchers/ios.ts +160 -0
  122. package/src/index.ts +37 -0
  123. package/src/openStore.ts +74 -0
  124. package/src/policy.ts +223 -0
  125. package/src/react/DefaultForceModal.tsx +100 -0
  126. package/src/react/DefaultWarningSheet.tsx +115 -0
  127. package/src/react/StoreVersionModal.tsx +365 -0
  128. package/src/react/StoreVersionProvider.tsx +149 -0
  129. package/src/react/defaultUi.tsx +205 -0
  130. package/src/react/engine.ts +768 -0
  131. package/src/react/texts.ts +119 -0
  132. package/src/react/useIsomorphicLayoutEffect.ts +8 -0
  133. package/src/react/useStoreVersion.ts +153 -0
  134. package/src/request.ts +328 -0
  135. package/src/resolve.ts +388 -0
  136. package/src/texts/ja.ts +26 -0
  137. package/src/vendor/compare-versions.ts +128 -0
  138. package/texts/ja.d.ts +2 -0
  139. package/texts/ja.js +3 -0
  140. package/.eslintrc.js +0 -51
  141. package/.github/FUNDING.yml +0 -3
  142. package/.github/workflows/pr.yml +0 -24
  143. package/.github/workflows/release.yml +0 -31
  144. package/.prettierrc.js +0 -6
  145. package/babel.config.js +0 -3
  146. package/dist/android.d.ts +0 -1
  147. package/dist/android.js +0 -17
  148. package/dist/ios.d.ts +0 -1
  149. package/dist/ios.js +0 -18
@@ -0,0 +1,121 @@
1
+ import { type ComponentType } from 'react';
2
+ import type { ColorValue, ImageSourcePropType } from 'react-native';
3
+ import type { CompareDetail, CompareResult, DiffType } from '../compare.ts';
4
+ import type { StoreVersionError } from '../errors.ts';
5
+ import type { Action } from '../policy.ts';
6
+ import type { StoreVersionForceTexts, StoreVersionTexts, StoreVersionWarningTexts } from './texts.ts';
7
+ /**
8
+ * 進行状態。
9
+ * - `idle`: まだ判定していない(マウント直後。バックグラウンドのままマウントされたら active になるまで)
10
+ * - `checking`: 判定中
11
+ * - `ready`: 判定できた(`result` / `action` などに値が入る)
12
+ * - `skipped`: 判定しない環境(web / ios・android 以外の OS / Expo Go / `enabled={false}`)。`onError` は呼ばない
13
+ * - `error`: 判定できなかった(`error` に理由。UI は出さない)
14
+ */
15
+ export type StoreVersionStatus = 'idle' | 'checking' | 'ready' | 'skipped' | 'error';
16
+ /** {@link useStoreVersion} の戻り値 */
17
+ export type UseStoreVersionResult = {
18
+ /** 進行状態 */
19
+ status: StoreVersionStatus;
20
+ /**
21
+ * 比較の結果(`ready` のときのみ。再チェック中の `checking` では前回の ready の値)。v1 の `checkVersion()` と同じ値で、policy では変わらない。
22
+ * 最新バージョンが比較できず、最低バージョンで force になったときは null
23
+ */
24
+ result: CompareResult | null;
25
+ /** v1 の `checkVersion()` と同じ `detail`(`result` と同じく、ready と再チェック中のみ) */
26
+ detail: CompareDetail | null;
27
+ /**
28
+ * policy と最低バージョンを当てた結果(`result` と同じく、ready と再チェック中のみ)。デフォルト UI はこれで出す。
29
+ * 再チェックの間も前回の値のままなので、force のモーダルは再チェック中に消えない
30
+ */
31
+ action: Action | null;
32
+ /** 差分の種類(`result` が `'new'` のときのみ) */
33
+ diff: DiffType | null;
34
+ /** `action` が `warning` だが「あとで」(`dismiss`)が押されて UI を出していない。remote が変われば false に戻る */
35
+ dismissed: boolean;
36
+ /** アプリのバージョン(ネイティブのバージョン)。判定を始めた後に入る */
37
+ local: string | null;
38
+ /** 最新バージョン(`result` と同じく、ready と再チェック中のみ) */
39
+ remote: string | null;
40
+ /** 開くべきストアの URL(`result` と同じく、ready と再チェック中のみ)。iOS で URL を取得中・取得に失敗したときは null */
41
+ storeUrl: string | null;
42
+ /** iOS でストアのバージョンを使ったときの `releaseNotes`(`result` と同じく、ready と再チェック中のみ)。Android と `getLatestVersion` 使用時は undefined */
43
+ releaseNotes: string | undefined;
44
+ /**
45
+ * ストアのアプリのページを開く。iOS で URL を取得中なら待ち、取れていなければその場でもう一度 lookup する。
46
+ * 開けたら true、開けなかったら false で resolve する(reject しない。`onPress={openStore}` のまま使える)。
47
+ * 失敗(iOS の lookup の失敗・`Linking.openURL` の失敗・判定前や skipped で開く先が分からない)は
48
+ * `STORE_URL_UNAVAILABLE` で `onError` に渡す。`status` / `error` は変えない
49
+ */
50
+ openStore: () => Promise<boolean>;
51
+ /** warning を閉じる(同じ remote のバージョンの間は出さない。メモリだけに持つので、次に起動したら再び出る) */
52
+ dismiss: () => void;
53
+ /**
54
+ * 手動で再チェックする(判定中なら、それを取り消してやり直す)。再チェックの間も前回の結果は残り、失敗したら前回の結果に戻る。
55
+ * バックグラウンドの間に呼ばれたら、active になってから始める
56
+ */
57
+ recheck: () => void;
58
+ /** 判定できなかった理由(`error` のときのみ。再チェックの失敗では前回の結果に戻るので入らない。`onError` には渡る) */
59
+ error: StoreVersionError | null;
60
+ };
61
+ /**
62
+ * `components.Force` に渡す props。このコンポーネントが描くのはカードの中身だけで、Modal・幕・配置・
63
+ * Android の戻るボタンで閉じないこと・開閉のアニメーションはライブラリが持つ。
64
+ * 置かれ方: 左右 24 の余白の内側で画面の縦中央、ScrollView の中。カードの面(背景・角丸・影・最大幅 480)はライブラリは掛けないので、
65
+ * このコンポーネントが自分で描く
66
+ */
67
+ export type StoreVersionForceProps = {
68
+ local: string;
69
+ /** 最新バージョン。Play の版が比較できず、最低バージョンで force になったときは null */
70
+ remote: string | null;
71
+ storeUrl: string | null;
72
+ releaseNotes: string | undefined;
73
+ /** `{remote}` / `{local}` を置き換え済みの文言 */
74
+ texts: StoreVersionForceTexts;
75
+ icon: ImageSourcePropType | undefined;
76
+ /** 開けたら true、開けなかったら false(reject しない。失敗は `onError` に渡る) */
77
+ openStore: () => Promise<boolean>;
78
+ };
79
+ /**
80
+ * `components.Warning` に渡す props。Force の props に加えて `dismiss`(「あとで」)。このコンポーネントが描くのはシートの中身だけで、
81
+ * Modal・幕・配置・戻るボタン / 背景タップで `dismiss` すること・開閉のアニメーションはライブラリが持つ。
82
+ * 置かれ方: 画面幅で下寄せ、ScrollView の中。シートの面(背景・角丸・影・最大幅 480)はライブラリは掛けないので、
83
+ * このコンポーネントが自分で描く
84
+ */
85
+ export type StoreVersionWarningProps = Omit<StoreVersionForceProps, 'texts'> & {
86
+ /** `{remote}` / `{local}` を置き換え済みの文言 */
87
+ texts: StoreVersionWarningTexts;
88
+ dismiss: () => void;
89
+ };
90
+ /**
91
+ * デフォルト UI の中身の差し替え。差し替えられるのはカード(Force)/ シート(Warning)の中身だけ。
92
+ * Modal、幕(オーバーレイ)の色、配置、Android の戻るボタンと背景タップの扱い(Force は閉じない、Warning は `dismiss`)、
93
+ * 開閉のアニメーションはライブラリが持ち、差し替えても変わらない。
94
+ * 置かれ方: Force は左右 24 の余白の内側で画面の縦中央、Warning は画面幅で下寄せ。どちらも ScrollView の中。
95
+ * カード / シートの面(背景・角丸・影・最大幅 480)はライブラリは掛けないので、差し替えたコンポーネントが自分で描く
96
+ */
97
+ export type StoreVersionComponents = {
98
+ Force?: ComponentType<StoreVersionForceProps>;
99
+ Warning?: ComponentType<StoreVersionWarningProps>;
100
+ };
101
+ /** デフォルト UI に渡す表示の設定(Provider の props をそのまま置く) */
102
+ export type StoreVersionDisplay = {
103
+ ui: boolean;
104
+ texts: StoreVersionTexts | undefined;
105
+ icon: ImageSourcePropType | undefined;
106
+ components: StoreVersionComponents | undefined;
107
+ primaryColor: ColorValue | undefined;
108
+ };
109
+ /**
110
+ * 判定の状態の Context(hook が読む。パッケージの入口からは export しない)。
111
+ * 表示の設定とは分けてある(インラインの `texts` などで Provider が描画し直しても、hook を使う側を描画し直さないように)
112
+ */
113
+ export declare const StoreVersionStateContext: import("react").Context<UseStoreVersionResult | null>;
114
+ /** 表示の設定の Context(デフォルト UI が読む。パッケージの入口からは export しない) */
115
+ export declare const StoreVersionDisplayContext: import("react").Context<StoreVersionDisplay | null>;
116
+ /**
117
+ * `StoreVersionProvider` が持つ判定結果を読む。Provider 配下ならどこでも呼べ、何箇所で呼んでも fetch は増えない。
118
+ * Provider の外で呼ぶと throw する
119
+ */
120
+ export declare const useStoreVersion: () => UseStoreVersionResult;
121
+ //# sourceMappingURL=useStoreVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStoreVersion.d.ts","sourceRoot":"","sources":["../../src/react/useStoreVersion.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAA6B,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EACV,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,OAAO,CAAC;AAEZ,mCAAmC;AACnC,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW;IACX,MAAM,EAAE,kBAAkB,CAAC;IAC3B;;;OAGG;IACH,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,wEAAwE;IACxE,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sCAAsC;IACtC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sHAAsH;IACtH,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,mEAAmE;IACnE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,wCAAwC;IACxC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,IAAI,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACtC,4DAA4D;IAC5D,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG,IAAI,CAAC,sBAAsB,EAAE,OAAO,CAAC,GAAG;IAC7E,wCAAwC;IACxC,KAAK,EAAE,wBAAwB,CAAC;IAChC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;CACnD,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACrC,IAAI,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACtC,UAAU,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC/C,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,uDACc,CAAC;AAGpD,0DAA0D;AAC1D,eAAO,MAAM,0BAA0B,qDACU,CAAC;AAGlD;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAO,qBAQlC,CAAC"}
@@ -0,0 +1,23 @@
1
+ // Provider が持つ判定結果を配下に配る Context と、それを読むだけの hook。
2
+ // 判定は Provider が 1 つだけ持つので、hook を何箇所で使っても fetch は増えない
3
+ import { createContext, useContext } from 'react';
4
+ /**
5
+ * 判定の状態の Context(hook が読む。パッケージの入口からは export しない)。
6
+ * 表示の設定とは分けてある(インラインの `texts` などで Provider が描画し直しても、hook を使う側を描画し直さないように)
7
+ */
8
+ export const StoreVersionStateContext = createContext(null);
9
+ StoreVersionStateContext.displayName = 'StoreVersionStateContext';
10
+ /** 表示の設定の Context(デフォルト UI が読む。パッケージの入口からは export しない) */
11
+ export const StoreVersionDisplayContext = createContext(null);
12
+ StoreVersionDisplayContext.displayName = 'StoreVersionDisplayContext';
13
+ /**
14
+ * `StoreVersionProvider` が持つ判定結果を読む。Provider 配下ならどこでも呼べ、何箇所で呼んでも fetch は増えない。
15
+ * Provider の外で呼ぶと throw する
16
+ */
17
+ export const useStoreVersion = () => {
18
+ const state = useContext(StoreVersionStateContext);
19
+ if (state === null) {
20
+ throw new Error('useStoreVersion() must be called inside <StoreVersionProvider>. Wrap your app (or the component tree that calls it) with <StoreVersionProvider> from react-native-store-version.');
21
+ }
22
+ return state;
23
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * 呼び出し元の `signal` が abort されたときに投げるエラー(`name === 'AbortError'`)。
3
+ * 古い Hermes には DOMException が無いので、name だけを合わせた Error にする
4
+ */
5
+ export declare const createAbortError: () => Error;
6
+ /** `createAbortError` や fetch の abort で投げられたエラーか */
7
+ export declare const isAbortError: (error: unknown) => boolean;
8
+ /** 呼び出し元の signal とタイムアウトを 1 つにまとめた signal({@link createScope}) */
9
+ export type Scope = {
10
+ /** 呼び出し元の signal が abort されたとき、またはタイムアウトしたときに abort される */
11
+ readonly signal: AbortSignal;
12
+ /** abort の理由がタイムアウトだったか */
13
+ readonly timedOut: boolean;
14
+ /** 自分から abort する(タイムアウト扱いにはしない) */
15
+ abort(): void;
16
+ /** タイマーと呼び出し元の signal への登録を外す(終わったら必ず呼ぶ) */
17
+ dispose(): void;
18
+ };
19
+ /**
20
+ * 呼び出し元の `signal` と `timeoutMs` から、どちらかで abort される signal を作る。
21
+ * `timeoutMs` が未指定(または正の有限の数でない)ならタイムアウトしない
22
+ */
23
+ export declare const createScope: ({ signal, timeoutMs, }?: {
24
+ signal?: AbortSignal;
25
+ timeoutMs?: number;
26
+ }) => Scope;
27
+ /**
28
+ * `promise` の完了か `signal` の abort の早い方で終わる。abort なら `createAbortError()` で reject する。
29
+ * `signal` を見ない処理(開発者の `getLatestVersion` など)を、タイムアウトや呼び出し元の abort で打ち切るため。
30
+ * 打ち切った後に `promise` が reject しても unhandled rejection にはならない
31
+ */
32
+ export declare const raceAbort: <T>(promise: PromiseLike<T>, signal: AbortSignal) => Promise<T>;
33
+ /** {@link requestText} の結果。成功・失敗を問わず status と本文を返す(status の扱いは fetcher が決める) */
34
+ export type TextResponse = {
35
+ readonly status: number;
36
+ readonly body: string;
37
+ };
38
+ /** {@link requestText} のオプション */
39
+ export type RequestOptions = {
40
+ /**
41
+ * この呼び出し元のタイムアウト(ms)。未指定ならタイムアウトしない(10 秒の既定は Provider が渡す)。
42
+ * 共有中の取得に後から加わった呼び出し元も、自分の `timeoutMs` で数える(ほかの呼び出し元の値には影響されない)。
43
+ * 時間切れの呼び出し元だけが `TIMEOUT` で抜け、その時点で待っている呼び出し元がいなければ fetch も止める
44
+ */
45
+ timeoutMs?: number;
46
+ /**
47
+ * この呼び出し元の取り消し。abort するとこの呼び出し元だけが `AbortError` で抜ける。
48
+ * ほかの呼び出し元が同じ取得を待っていれば fetch は続く
49
+ */
50
+ signal?: AbortSignal;
51
+ /**
52
+ * iTunes Lookup の CDN キャッシュを避ける。URL の末尾にタイムスタンプ(`&<ts>`)を付け、
53
+ * `cache-control: no-cache` を送る(v1 と同じ形)
54
+ */
55
+ noCache?: boolean;
56
+ };
57
+ /**
58
+ * {@link requestText} の `NETWORK` のうち、応答(status)は受け取ったが本文の読み込みに失敗したものなら、その status を返す。
59
+ * fetch 自体が失敗した場合やほかの値なら undefined。v1 互換の checkVersion が、v1 と同じく Android の 200 以外を
60
+ * 本文より先に `androidStoreURL is invalid.` にするために使う(パッケージの入口からは export しない)
61
+ */
62
+ export declare const failedResponseStatusOf: (error: unknown) => number | undefined;
63
+ /**
64
+ * `url` を取得して status と本文を返す。同じ取得先(タイムスタンプを付ける前の URL と `noCache`)への同時の呼び出しは
65
+ * 1 回の fetch にまとめ、完了したら(成功・失敗とも)共有をやめる(次の呼び出しは取り直す。キャッシュしない)。
66
+ *
67
+ * - 通信の失敗(fetch の reject / 本文の読み込みの失敗)は `StoreVersionError('NETWORK')`(cause に元のエラー)
68
+ * - この呼び出し元のタイムアウトは `StoreVersionError('TIMEOUT')`
69
+ * - この呼び出し元の `signal` の abort は `AbortError`({@link isAbortError})
70
+ * - 実際の fetch を止めるのは、待っている呼び出し元が全員抜けたとき。タイムアウトで抜けた場合はすぐ止め、
71
+ * abort で抜けた場合は次のタスクまで待ってから止める(StrictMode では 1 回目の effect の cleanup の abort の直後に
72
+ * 2 回目の effect が同じ取得に加わるので、それを受け取れるようにするため)。上位(resolve など)のタイムアウトは
73
+ * `signal` の abort として届くので、abort と同じく次のタスクで止める
74
+ *
75
+ * HTTP の status は見ない(200 以外の扱いは fetcher が決める)
76
+ */
77
+ export declare const requestText: (url: string, { timeoutMs, signal, noCache }?: RequestOptions) => Promise<TextResponse>;
78
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAO,KAInC,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,OAGO,CAAC;AAStD,kEAAkE;AAClE,MAAM,MAAM,KAAK,GAAG;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,mCAAmC;IACnC,KAAK,IAAI,IAAI,CAAC;IACd,4CAA4C;IAC5C,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,4BAGrB;IACD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,KAAQ,KA6CR,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,WAChB,WAAW,CAAC,CAAC,CAAC,UACf,WAAW,KAClB,OAAO,CAAC,CAAC,CAkBR,CAAC;AAEL,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,iCAAiC;AACjC,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,UAAW,OAAO,KAAG,MAAM,GAAG,SAGlD,CAAC;AAqFhB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,QACjB,MAAM,mCAC6B,cAAc,KACrD,OAAO,CAAC,YAAY,CA6DnB,CAAC"}
@@ -0,0 +1,227 @@
1
+ // ストアへの取得の共通部分(タイムアウト / in-flight の共有 / iTunes のキャッシュ回避)。
2
+ // react-native を import しない(Node でも動かす。canary でも使う)。
3
+ // 古い Hermes に無い API(AbortSignal.timeout / AbortSignal.any / DOMException など)は使わず、
4
+ // AbortController と setTimeout だけで組む
5
+ import { StoreVersionError } from './errors.js';
6
+ /**
7
+ * 呼び出し元の `signal` が abort されたときに投げるエラー(`name === 'AbortError'`)。
8
+ * 古い Hermes には DOMException が無いので、name だけを合わせた Error にする
9
+ */
10
+ export const createAbortError = () => {
11
+ const error = new Error('The operation was aborted.');
12
+ error.name = 'AbortError';
13
+ return error;
14
+ };
15
+ /** `createAbortError` や fetch の abort で投げられたエラーか */
16
+ export const isAbortError = (error) => typeof error === 'object' &&
17
+ error !== null &&
18
+ error.name === 'AbortError';
19
+ // setTimeout は 2^31 - 1 ms を超えるとすぐに発火する(オーバーフロー)ので、そこで頭打ちにする
20
+ const MAX_TIMEOUT_MS = 2147483647;
21
+ /** タイムアウトを入れるか。正の有限の数のときだけ(0 / 負 / NaN / Infinity / 未指定はタイムアウトなし) */
22
+ const hasTimeout = (timeoutMs) => typeof timeoutMs === 'number' && timeoutMs > 0 && timeoutMs !== Infinity;
23
+ /**
24
+ * 呼び出し元の `signal` と `timeoutMs` から、どちらかで abort される signal を作る。
25
+ * `timeoutMs` が未指定(または正の有限の数でない)ならタイムアウトしない
26
+ */
27
+ export const createScope = ({ signal, timeoutMs, } = {}) => {
28
+ const controller = new AbortController();
29
+ let timedOut = false;
30
+ let timer;
31
+ const dispose = () => {
32
+ if (timer !== undefined) {
33
+ clearTimeout(timer);
34
+ timer = undefined;
35
+ }
36
+ signal?.removeEventListener('abort', onAbort);
37
+ };
38
+ function onAbort() {
39
+ dispose();
40
+ controller.abort();
41
+ }
42
+ if (signal?.aborted) {
43
+ controller.abort();
44
+ }
45
+ else {
46
+ signal?.addEventListener('abort', onAbort);
47
+ if (hasTimeout(timeoutMs)) {
48
+ timer = setTimeout(() => {
49
+ timer = undefined;
50
+ timedOut = true;
51
+ dispose();
52
+ controller.abort();
53
+ }, Math.min(timeoutMs, MAX_TIMEOUT_MS));
54
+ }
55
+ }
56
+ return {
57
+ signal: controller.signal,
58
+ get timedOut() {
59
+ return timedOut;
60
+ },
61
+ abort: () => {
62
+ dispose();
63
+ controller.abort();
64
+ },
65
+ dispose,
66
+ };
67
+ };
68
+ /**
69
+ * `promise` の完了か `signal` の abort の早い方で終わる。abort なら `createAbortError()` で reject する。
70
+ * `signal` を見ない処理(開発者の `getLatestVersion` など)を、タイムアウトや呼び出し元の abort で打ち切るため。
71
+ * 打ち切った後に `promise` が reject しても unhandled rejection にはならない
72
+ */
73
+ export const raceAbort = (promise, signal) => new Promise((resolve, reject) => {
74
+ const onAbort = () => reject(createAbortError());
75
+ if (signal.aborted) {
76
+ onAbort();
77
+ }
78
+ else {
79
+ signal.addEventListener('abort', onAbort);
80
+ }
81
+ promise.then((value) => {
82
+ signal.removeEventListener('abort', onAbort);
83
+ resolve(value);
84
+ }, (error) => {
85
+ signal.removeEventListener('abort', onAbort);
86
+ reject(error);
87
+ });
88
+ });
89
+ // 本文の読み込みに失敗した NETWORK のエラーと、その応答の status。StoreVersionError にフィールドを足さずに(公開の形を変えずに)
90
+ // v1 互換の checkVersion へ status を渡すため。WeakMap なのでエラーが捨てられれば消える(キャッシュではない)
91
+ const failedResponseStatus = new WeakMap();
92
+ /**
93
+ * {@link requestText} の `NETWORK` のうち、応答(status)は受け取ったが本文の読み込みに失敗したものなら、その status を返す。
94
+ * fetch 自体が失敗した場合やほかの値なら undefined。v1 互換の checkVersion が、v1 と同じく Android の 200 以外を
95
+ * 本文より先に `androidStoreURL is invalid.` にするために使う(パッケージの入口からは export しない)
96
+ */
97
+ export const failedResponseStatusOf = (error) => typeof error === 'object' && error !== null
98
+ ? failedResponseStatus.get(error)
99
+ : undefined;
100
+ // 取得中のものだけを持つ(完了したら消す。結果は保持しない)。キーはタイムスタンプを付ける前の取得先
101
+ const inflight = new Map();
102
+ const clearIdleTimer = (entry) => {
103
+ if (entry.idleTimer !== undefined) {
104
+ clearTimeout(entry.idleTimer);
105
+ entry.idleTimer = undefined;
106
+ }
107
+ };
108
+ /** 誰も待っていなければ fetch を止める。後から来た呼び出し元は新しく取り直す */
109
+ const stopIfIdle = (entry) => {
110
+ clearIdleTimer(entry);
111
+ if (entry.settled || entry.waiters > 0) {
112
+ return;
113
+ }
114
+ if (inflight.get(entry.key) === entry) {
115
+ inflight.delete(entry.key);
116
+ }
117
+ entry.controller.abort();
118
+ };
119
+ const start = (key, url, noCache) => {
120
+ const controller = new AbortController();
121
+ // v1 と同じく、タイムスタンプはクエリの最後に `&<ts>` で付ける
122
+ const target = noCache
123
+ ? `${url}${url.includes('?') ? '&' : '?'}${Date.now()}`
124
+ : url;
125
+ const init = noCache
126
+ ? { headers: { 'cache-control': 'no-cache' }, signal: controller.signal }
127
+ : { signal: controller.signal };
128
+ const promise = (async () => {
129
+ let status;
130
+ try {
131
+ const response = await fetch(target, init);
132
+ status = response.status;
133
+ return { status, body: await response.text() };
134
+ }
135
+ catch (cause) {
136
+ const error = new StoreVersionError('NETWORK', `request to ${url} failed`, { cause });
137
+ // 応答は来たが本文の読み込みに失敗した場合だけ、その status を添える({@link failedResponseStatusOf})
138
+ if (typeof status === 'number') {
139
+ failedResponseStatus.set(error, status);
140
+ }
141
+ throw error;
142
+ }
143
+ })();
144
+ const entry = {
145
+ key,
146
+ promise,
147
+ controller,
148
+ waiters: 0,
149
+ settled: false,
150
+ idleTimer: undefined,
151
+ };
152
+ const settle = () => {
153
+ entry.settled = true;
154
+ clearIdleTimer(entry);
155
+ if (inflight.get(key) === entry) {
156
+ inflight.delete(key);
157
+ }
158
+ };
159
+ // 待っている呼び出し元が全員抜けた後の reject(abort)も、ここで受けるので unhandled rejection にならない
160
+ promise.then(settle, settle);
161
+ return entry;
162
+ };
163
+ /**
164
+ * `url` を取得して status と本文を返す。同じ取得先(タイムスタンプを付ける前の URL と `noCache`)への同時の呼び出しは
165
+ * 1 回の fetch にまとめ、完了したら(成功・失敗とも)共有をやめる(次の呼び出しは取り直す。キャッシュしない)。
166
+ *
167
+ * - 通信の失敗(fetch の reject / 本文の読み込みの失敗)は `StoreVersionError('NETWORK')`(cause に元のエラー)
168
+ * - この呼び出し元のタイムアウトは `StoreVersionError('TIMEOUT')`
169
+ * - この呼び出し元の `signal` の abort は `AbortError`({@link isAbortError})
170
+ * - 実際の fetch を止めるのは、待っている呼び出し元が全員抜けたとき。タイムアウトで抜けた場合はすぐ止め、
171
+ * abort で抜けた場合は次のタスクまで待ってから止める(StrictMode では 1 回目の effect の cleanup の abort の直後に
172
+ * 2 回目の effect が同じ取得に加わるので、それを受け取れるようにするため)。上位(resolve など)のタイムアウトは
173
+ * `signal` の abort として届くので、abort と同じく次のタスクで止める
174
+ *
175
+ * HTTP の status は見ない(200 以外の扱いは fetcher が決める)
176
+ */
177
+ export const requestText = (url, { timeoutMs, signal, noCache = false } = {}) => new Promise((resolve, reject) => {
178
+ const scope = createScope({ signal, timeoutMs });
179
+ if (scope.signal.aborted) {
180
+ reject(createAbortError());
181
+ return;
182
+ }
183
+ const key = `${noCache ? 'no-cache ' : ''}${url}`;
184
+ let entry = inflight.get(key);
185
+ if (!entry) {
186
+ entry = start(key, url, noCache);
187
+ inflight.set(key, entry);
188
+ }
189
+ const joined = entry;
190
+ joined.waiters += 1;
191
+ clearIdleTimer(joined);
192
+ let done = false;
193
+ const finish = () => {
194
+ done = true;
195
+ scope.signal.removeEventListener('abort', onLeave);
196
+ scope.dispose();
197
+ };
198
+ // finish() で外すので、結果を受け取った後には呼ばれない
199
+ function onLeave() {
200
+ const timedOut = scope.timedOut;
201
+ finish();
202
+ joined.waiters -= 1;
203
+ if (joined.waiters === 0) {
204
+ if (timedOut) {
205
+ stopIfIdle(joined);
206
+ }
207
+ else {
208
+ joined.idleTimer = setTimeout(() => stopIfIdle(joined), 0);
209
+ }
210
+ }
211
+ reject(timedOut
212
+ ? new StoreVersionError('TIMEOUT', `request to ${url} timed out after ${timeoutMs}ms`)
213
+ : createAbortError());
214
+ }
215
+ scope.signal.addEventListener('abort', onLeave);
216
+ joined.promise.then((value) => {
217
+ if (!done) {
218
+ finish();
219
+ resolve(value);
220
+ }
221
+ }, (error) => {
222
+ if (!done) {
223
+ finish();
224
+ reject(error);
225
+ }
226
+ });
227
+ });
@@ -0,0 +1,98 @@
1
+ import { type CompareDetail, type CompareResult, type DiffType } from './compare.ts';
2
+ import { StoreVersionError } from './errors.ts';
3
+ import { type VersionGetter } from './fetchers/custom.ts';
4
+ import { type StoreUrlResult } from './fetchers/ios.ts';
5
+ import { type Action, type Policy } from './policy.ts';
6
+ export type { StoreUrlResult, VersionGetter };
7
+ /** {@link resolve} の引数 */
8
+ export type ResolveParams = {
9
+ platform: 'ios' | 'android';
10
+ /**
11
+ * アプリのバージョン。必ずネイティブのバージョン(iOS の `CFBundleShortVersionString` / Android の `versionName`)を渡す。
12
+ * `Constants.expoConfig.version` や `package.json` の値は OTA 更新で変わってしまうので使わない
13
+ */
14
+ version: string;
15
+ /** iOS は bundleId、Android は package name */
16
+ appId: string;
17
+ /** iTunes Lookup の `country`(Android では使わない) */
18
+ country: string;
19
+ /** 省略 / null はデフォルト(`{ major: 'force', minor: 'warning', patch: 'warning' }`) */
20
+ policy?: Policy | null;
21
+ /** 指定するとストアのバージョンは使わない(iOS はストア URL を得るためだけに lookup する。Android はストアに問い合わせない) */
22
+ getLatestVersion?: VersionGetter | null;
23
+ /** これ未満は差分に関係なく force */
24
+ getMinimumVersion?: VersionGetter | null;
25
+ /**
26
+ * 判定全体のタイムアウト(ms)。最新バージョンと最低バージョンの取得の両方に同じものが効く。
27
+ * 最新バージョンが間に合わなければ `TIMEOUT` で reject する。最新バージョンが間に合い、最低バージョンだけが
28
+ * 間に合わなければ、最低バージョンの判定だけを飛ばして続ける(`MINIMUM_VERSION_FAILED`。cause に `TIMEOUT`)。
29
+ * 未指定(または正の有限の数でない)ならタイムアウトしない。10 秒の既定は Provider が渡す
30
+ */
31
+ timeoutMs?: number;
32
+ /** 判定の取り消し(abort すると `AbortError` で reject する) */
33
+ signal?: AbortSignal;
34
+ };
35
+ /** {@link resolve} の結果(判定できたとき) */
36
+ export type ResolveResult = {
37
+ /**
38
+ * 最新バージョン(ストア、または `getLatestVersion` の値)。比較できない値でもそのまま入る。
39
+ * Play Store のページから版を取れなかった(Varies with device / 比較できない版)が、最低バージョンで force になったときだけ null
40
+ */
41
+ latest: string | null;
42
+ /** `getMinimumVersion` の値。指定なし(空文字 / null / undefined)・未指定・取得の失敗は null。比較できない値でもそのまま入る */
43
+ minimum: string | null;
44
+ /**
45
+ * 判定の時点で分かっているストアの URL。iOS で URL を取れていない(lookup 中・失敗・`trackViewUrl` が無い)ときは null。
46
+ * 理由は {@link ResolveResult.storeUrlResult} の `error`(lookup 中なら、終わってから受け取れる)
47
+ */
48
+ storeUrl: string | null;
49
+ /**
50
+ * ストアの URL の取得の完了(reject しない)。iOS で `getLatestVersion` を使うときは判定と並行に走る lookup の結果で、
51
+ * 判定はこれを待たずに返る(lookup にも `timeoutMs` と `signal` が効き続ける)。それ以外は判定の時点で完了している。
52
+ * 失敗は `STORE_URL_UNAVAILABLE`(cause に lookup のエラー。タイムアウトなら `TIMEOUT`、`signal` の abort なら `AbortError`)
53
+ */
54
+ storeUrlResult: Promise<StoreUrlResult>;
55
+ /** iOS でストアのバージョンを使ったときの `releaseNotes`。`getLatestVersion` 使用時と Android は undefined */
56
+ releaseNotes?: string;
57
+ /** v1 の `compareVersion(local, latest)` と同じ(policy では変わらない)。最新が比較できず最低バージョンで force になったときは null */
58
+ result: CompareResult | null;
59
+ /** v1 と同じ `detail`。`result` が null なら null */
60
+ detail: CompareDetail | null;
61
+ /** policy と最低バージョンから決まる扱い */
62
+ action: Action;
63
+ /** 差分の種類(`result === 'new'` のときだけ) */
64
+ diff: DiffType | null;
65
+ /**
66
+ * 判定を止めなかったが `onError` に渡すべきエラー(空なら無し)。
67
+ * `MINIMUM_VERSION_FAILED`(getMinimumVersion の失敗・タイムアウト・比較できない最低バージョン)と、
68
+ * 最新が比較できないが最低バージョンで force にしたときの `INVALID_VERSION`
69
+ */
70
+ errors: readonly StoreVersionError[];
71
+ };
72
+ /**
73
+ * {@link resolve} が reject したエラーに添えた、`onError` に渡すべきほかのエラー(無ければ空)。
74
+ * 例: 最新バージョンと最低バージョンがどちらも比較できないときは、reject の `INVALID_VERSION` に
75
+ * `MINIMUM_VERSION_FAILED` が添えてある(開発者のバグを onError で気づけるように)
76
+ */
77
+ export declare const attachedErrorsOf: (error: unknown) => readonly StoreVersionError[];
78
+ /**
79
+ * 1 回の判定を行う。latest(ストア / `getLatestVersion`)と minimum(`getMinimumVersion`)は並行に取得し、
80
+ * `evaluatePolicy` で判定する。
81
+ *
82
+ * 判定を止めるエラーは `StoreVersionError` で reject する(`onError` に渡す。UI は出さない):
83
+ * - `POLICY_FAILED`: 値で指定した policy が不正(取得の前に検証する)/ policy の関数が throw・不正な値
84
+ * - `INVALID_VERSION`: local が比較できない(取得の前に検証する)/ 最新が比較できず、最低バージョンでも force にならない
85
+ * - `TIMEOUT`: 最新バージョン(ストア / `getLatestVersion`)が `timeoutMs` までに取れない
86
+ * (最低バージョンだけが間に合わないときは止めず、`MINIMUM_VERSION_FAILED` を `errors` に入れて続ける)
87
+ * - `NETWORK` / `NOT_FOUND` / `PARSE_FAILED`: ストアの取得の失敗
88
+ * - `LATEST_VERSION_FAILED`: `getLatestVersion` の失敗(ストアにはフォールバックしない)
89
+ * - `signal` の abort は `AbortError`
90
+ *
91
+ * reject したエラーに、止めなかったエラー(getMinimumVersion の失敗・比較できない最低バージョン)が添えてあれば
92
+ * {@link attachedErrorsOf} で取れる。latest の取得の失敗(`NETWORK` / `NOT_FOUND` / `PARSE_FAILED` / `TIMEOUT` /
93
+ * `LATEST_VERSION_FAILED`)で止めるときは、その時点で getMinimumVersion が完了していれば添え、完了していなければ添えない
94
+ * (待たない)。呼び出し元の abort(判定の取り消し)で止めるときは何も添えない。
95
+ * 判定を止めないエラーは {@link ResolveResult.errors} に入る。
96
+ */
97
+ export declare const resolve: (params: ResolveParams) => Promise<ResolveResult>;
98
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,cAAc,EAGpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,MAAM,EAGX,KAAK,MAAM,EAGZ,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AAE9C,0BAA0B;AAC1B,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACxC,yBAAyB;IACzB,iBAAiB,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,mCAAmC;AACnC,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACxC,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mGAAmG;IACnG,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,8CAA8C;IAC9C,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7B,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB;;;;OAIG;IACH,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACtC,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UACpB,OAAO,KACb,SAAS,iBAAiB,EAC+C,CAAC;AAsE7E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,OAAO,WACV,aAAa,KACpB,OAAO,CAAC,aAAa,CAuLvB,CAAC"}