@omnigateway/pokemon 1.0.0 → 1.0.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.
package/omni-plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "pokemon",
3
3
  "name": "Pok\u00e9mon Companion",
4
- "version": "1.0.0",
4
+ "version": "1.0.1",
5
5
  "api": 1,
6
6
  "sdk": "^0.1.0",
7
7
  "server": "server/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnigateway/pokemon",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A Pokémon companion for OmniGateway. Each gateway key raises one that hatches, evolves, and graduates into a Pokédex on the tokens that key spends.",
5
5
  "license": "MIT",
6
6
  "author": "Harismawan <mail@harismawan.com>",
package/server/index.js CHANGED
@@ -348,6 +348,12 @@ async function loadDetail(deps, id, chains) {
348
348
  function speciesDetail(deps, id) {
349
349
  return loadDetail(deps, id, new Map);
350
350
  }
351
+ async function cachedSpeciesName(deps, id) {
352
+ if (!isFetchableSpeciesId(id))
353
+ return null;
354
+ const cached = parseCachedDetail(await readJson(deps, speciesPath(id)), id);
355
+ return cached?.names.en ?? null;
356
+ }
351
357
  function parseCachedIndex(raw) {
352
358
  const entries = asArray(raw);
353
359
  if (entries === null)
@@ -726,6 +732,18 @@ function readCompanion(storage, apiKeyId) {
726
732
  lastCreditAt: row.last_credit_at
727
733
  };
728
734
  }
735
+ function listCompanions(storage) {
736
+ const rows = storage.all(`SELECT api_key_id, state, tokens_total, tokens_spent, last_credit_at
737
+ FROM {{companion}}
738
+ ORDER BY last_credit_at IS NULL, last_credit_at DESC, tokens_total DESC, api_key_id ASC`);
739
+ return rows.map((row) => ({
740
+ apiKeyId: row.api_key_id,
741
+ state: parseState(row.state),
742
+ tokensTotal: row.tokens_total,
743
+ tokensSpent: row.tokens_spent,
744
+ lastCreditAt: row.last_credit_at
745
+ }));
746
+ }
729
747
  function creditTokens(storage, apiKeyId, tokens, now) {
730
748
  if (tokens <= 0)
731
749
  return;
@@ -876,6 +894,18 @@ var server_default = definePlugin({
876
894
  inFlight.set(apiKeyId, started);
877
895
  return started;
878
896
  };
897
+ const names = new Map;
898
+ const nameOf = async (speciesId) => {
899
+ if (speciesId === null || files === undefined)
900
+ return null;
901
+ const known = names.get(speciesId);
902
+ if (known !== undefined)
903
+ return known;
904
+ const found = await cachedSpeciesName({ files }, speciesId);
905
+ if (found !== null)
906
+ names.set(speciesId, found);
907
+ return found;
908
+ };
879
909
  const settleAndRecord = (apiKeyId) => {
880
910
  const result = settle(storage, apiKeyId, ctx.now());
881
911
  if (result === null)
@@ -980,10 +1010,33 @@ var server_default = definePlugin({
980
1010
  });
981
1011
  }
982
1012
  const routes = [
1013
+ {
1014
+ method: "GET",
1015
+ path: "/keys",
1016
+ handler: async () => {
1017
+ const rows = listCompanions(storage);
1018
+ const keys = await Promise.all(rows.map(async (row) => {
1019
+ const active = row.state?.active ?? null;
1020
+ const speciesId = active === null ? null : active.plannedPath[active.stageIndex] ?? null;
1021
+ return {
1022
+ apiKeyId: row.apiKeyId,
1023
+ speciesId,
1024
+ name: await nameOf(speciesId),
1025
+ rarity: active?.rarity ?? null,
1026
+ isShiny: active?.isShiny ?? false,
1027
+ tokensTotal: row.tokensTotal,
1028
+ wallet: wallet(row),
1029
+ lastCreditAt: row.lastCreditAt,
1030
+ unreadable: row.state === null
1031
+ };
1032
+ }));
1033
+ return { json: { keys } };
1034
+ }
1035
+ },
983
1036
  {
984
1037
  method: "GET",
985
1038
  path: "/keys/:id",
986
- handler: (request) => {
1039
+ handler: async (request) => {
987
1040
  const apiKeyId = request.params.id ?? "";
988
1041
  settleAndRecord(apiKeyId);
989
1042
  const row = readCompanion(storage, apiKeyId);
@@ -992,13 +1045,15 @@ var server_default = definePlugin({
992
1045
  if (row.state !== null)
993
1046
  prefetchOnce(apiKeyId, row.state).catch(() => {});
994
1047
  const active = row.state?.active ?? null;
1048
+ const dex = readDex(storage, apiKeyId);
995
1049
  return {
996
1050
  json: {
997
1051
  state: row.state,
998
1052
  tokensTotal: row.tokensTotal,
999
1053
  wallet: wallet(row),
1000
1054
  lastCreditAt: row.lastCreditAt,
1001
- dex: readDex(storage, apiKeyId),
1055
+ name: await nameOf(active === null ? null : active.plannedPath[active.stageIndex] ?? null),
1056
+ dex: await Promise.all(dex.map(async (entry) => ({ ...entry, name: await nameOf(entry.finalId) }))),
1002
1057
  shop: shopCatalogue(),
1003
1058
  nextThreshold: active === null ? EGG_HATCH_THRESHOLD : phaseThreshold(active.rarity, active.plannedPath.length, active.stageIndex),
1004
1059
  progress: active === null ? row.state?.eggUsage ?? 0 : active.usedAtStage
package/ui/index.js CHANGED
@@ -1,68 +1,195 @@
1
- function w(t){return t}import{useMutation as _,useQuery as K,useQueryClient as G}from"@tanstack/react-query";import{useState as f}from"react";import s from"styled-components";import{jsx as n,jsxs as r,Fragment as P}from"react/jsx-runtime";var c=s.section`
1
+ function V(e){return e}import{useMutation as we,useQuery as ve,useQueryClient as De}from"@tanstack/react-query";import{useState as Pe}from"react";function w(e,r,i){return`/api/plugins/${e}/sprite/${r}${i?"?shiny=1":""}`}function c(e){if(e>=1e9)return`${(e/1e9).toFixed(2)}B`;if(e>=1e6)return`${(e/1e6).toFixed(1)}M`;return e.toLocaleString()}function v(e,r){return e??`#${r}`}function A(e,r,i){return`${e??`Species ${r}`}${i?", shiny":""}`}function R(e){return e.replace(/([A-Z])/g," $1").toLowerCase()}function F(e){if(e.kind==="item")return R(e.item);return e.tier===null?"fresh egg":`fresh egg (${e.tier}+)`}var te=["rareCandy","mint"],ne=[null,"common","uncommon","rare","legendary"],re=60000,ee=60*re;function T(e,r,i){if(!e)return"egg";if(r===null)return"sleep";let o=i-r;if(o<5*re)return"working";if(o<ee)return"idle";if(o<8*ee)return"tired";return"sleep"}import a from"styled-components";var l={xs:"4px",sm:"8px",md:"12px",lg:"20px",xl:"32px"},H="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",I=a.section`
2
2
  background: var(--panel);
3
3
  border: 1px solid var(--rule);
4
- border-radius: 6px;
5
- padding: 16px;
4
+ border-radius: 8px;
5
+ padding: ${l.lg};
6
6
  color: var(--ink);
7
- `,b=s.div`
7
+ `,P=a.h3`
8
8
  display: flex;
9
- gap: 16px;
9
+ align-items: center;
10
+ gap: ${l.md};
11
+ margin: ${l.xl} 0 ${l.md};
12
+ font-size: 11px;
13
+ font-weight: 600;
14
+ letter-spacing: 0.12em;
15
+ text-transform: uppercase;
16
+ color: var(--ink-dim);
17
+
18
+ &::after {
19
+ content: "";
20
+ flex: 1;
21
+ height: 1px;
22
+ background: var(--rule);
23
+ }
24
+ `,y=a.div`
25
+ display: flex;
26
+ gap: ${l.md};
10
27
  align-items: center;
11
28
  flex-wrap: wrap;
12
- `,H=s.img`
29
+ `,p=a.span`
30
+ color: var(--ink-dim);
31
+ `,G=a.p`
32
+ color: var(--warn);
33
+ background: var(--warn-wash);
34
+ border-radius: 6px;
35
+ padding: ${l.md};
36
+ margin: ${l.md} 0 0;
37
+ `,b=a.span`
38
+ display: inline-flex;
39
+ align-items: center;
40
+ gap: ${l.xs};
41
+ padding: 2px ${l.sm};
42
+ border: 1px solid var(--rule);
43
+ border-radius: 999px;
44
+ font-size: 11px;
45
+ letter-spacing: 0.08em;
46
+ text-transform: uppercase;
47
+ color: var(--ink-dim);
48
+ white-space: nowrap;
49
+ `,ie=a(b)`
50
+ border-color: var(--rule-strong);
51
+ color: var(--ink);
52
+ font-weight: 600;
53
+ `,C=a.img`
13
54
  width: 96px;
14
55
  height: 96px;
15
56
  image-rendering: pixelated;
16
57
  background: var(--panel-sunk);
17
- border-radius: 4px;
18
- `,C=s.div`
58
+ border: 1px solid var(--rule);
59
+ border-radius: 6px;
60
+ `,D=a.div`
61
+ width: 96px;
62
+ height: 96px;
63
+ border-radius: 50% 50% 45% 45%;
19
64
  background: var(--panel-sunk);
20
- border-radius: 3px;
21
- height: 8px;
22
- overflow: hidden;
23
- min-width: 200px;
24
- `,N=s.div`
25
- background: var(--accent);
26
- height: 100%;
27
- width: ${(t)=>Math.min(100,Math.max(0,t.$pct))}%;
28
- `,a=s.span`
29
- color: var(--ink-dim);
30
- `,J=s.div`
31
- display: grid;
32
- grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
33
- gap: 8px;
34
- margin-top: 12px;
35
- `,x=s.button`
65
+ border: 2px solid var(--rule-strong);
66
+ `,oe=a.div`
67
+ width: 96px;
68
+ height: 96px;
69
+ border-radius: 6px;
70
+ background: var(--warn-wash);
71
+ border: 2px dashed var(--warn);
72
+ `,x=a.button`
36
73
  background: var(--panel-raised);
37
74
  border: 1px solid var(--rule);
38
- border-radius: 4px;
75
+ border-radius: 6px;
39
76
  color: var(--ink);
40
- padding: 6px 10px;
77
+ padding: ${l.sm} ${l.md};
78
+ font: inherit;
41
79
  cursor: pointer;
80
+
81
+ &:hover:not(:disabled) {
82
+ border-color: var(--rule-strong);
83
+ }
84
+ &:focus-visible {
85
+ outline: 2px solid var(--accent);
86
+ outline-offset: 2px;
87
+ }
88
+ &[aria-pressed="true"] {
89
+ background: var(--accent-wash);
90
+ border-color: var(--accent);
91
+ color: var(--ink);
92
+ }
42
93
  &:disabled {
43
94
  color: var(--ink-faint);
44
95
  cursor: not-allowed;
45
96
  }
46
- `,U=s.p`
47
- color: var(--warn);
48
- `,Q=s.figure`
97
+ `,B=a.span`
98
+ font-family: ${H};
99
+ font-variant-numeric: tabular-nums;
100
+ `,ae=a.div`
101
+ display: flex;
102
+ gap: 3px;
103
+ min-width: 240px;
104
+ max-width: 340px;
105
+ `,se=a.div`
106
+ flex: 1;
107
+ height: 10px;
108
+ background: var(--panel-sunk);
109
+ border: 1px solid var(--rule);
110
+ border-radius: 3px;
111
+ overflow: hidden;
112
+ `,q=a.div`
113
+ height: 100%;
114
+ background: var(--accent);
115
+ width: ${(e)=>Math.min(100,Math.max(0,e.$pct))}%;
116
+ transition: width 480ms ease-out;
117
+
118
+ @media (prefers-reduced-motion: reduce) {
119
+ transition: none;
120
+ }
121
+ `,le=a.dl`
122
+ display: flex;
123
+ flex-wrap: wrap;
124
+ gap: ${l.xl};
125
+ margin: ${l.lg} 0 0;
126
+ padding-top: ${l.lg};
127
+ border-top: 1px solid var(--rule);
128
+ `,N=a.div`
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 2px;
132
+ `,L=a.dt`
133
+ font-size: 11px;
134
+ letter-spacing: 0.08em;
135
+ text-transform: uppercase;
136
+ color: var(--ink-faint);
137
+ `,_=a.dd`
138
+ margin: 0;
139
+ font-family: ${H};
140
+ font-variant-numeric: tabular-nums;
141
+ font-size: 18px;
142
+ color: var(--ink);
143
+ `,pe=a.div`
144
+ display: grid;
145
+ grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
146
+ gap: ${l.md};
147
+ `,ue=a.figure`
49
148
  margin: 0;
50
149
  display: flex;
51
150
  flex-direction: column;
52
151
  align-items: center;
53
152
  gap: 2px;
54
- `,j=s.figcaption`
153
+ `,z=a.figcaption`
55
154
  color: var(--ink-dim);
56
155
  font-size: 11px;
57
156
  text-align: center;
58
- `,W=s.div`
157
+ overflow-wrap: anywhere;
158
+ `,de=a.div`
159
+ display: grid;
160
+ grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
161
+ gap: ${l.md};
162
+ `,ce=a.button`
59
163
  display: flex;
164
+ flex-direction: column;
60
165
  align-items: center;
61
- gap: 8px;
62
- `,z=s.div`
63
- width: 96px;
64
- height: 96px;
65
- border-radius: 50% 50% 45% 45%;
166
+ gap: ${l.sm};
167
+ padding: ${l.md};
66
168
  background: var(--panel-raised);
67
- border: 2px solid var(--rule-strong);
68
- `;function B(t,l,d){return`/api/plugins/${t}/sprite/${l}${d?"?shiny=1":""}`}function p(t){if(t>=1e9)return`${(t/1e9).toFixed(2)}B`;if(t>=1e6)return`${(t/1e6).toFixed(1)}M`;return t.toLocaleString()}function S(t){return t.replace(/([A-Z])/g," $1").toLowerCase()}function M(t){if(t.kind==="item")return S(t.item);return t.tier===null?"fresh egg":`fresh egg (${t.tier}+)`}var Y=["rareCandy","mint"],Z=[null,"common","uncommon","rare","legendary"],L=60000,O=60*L;function X(t,l,d){if(!t)return"egg";if(l===null)return"sleep";let g=d-l;if(g<5*L)return"working";if(g<O)return"idle";if(g<8*O)return"tired";return"sleep"}function ee({pluginId:t,api:l}){let[d,g]=f(""),[u,V]=f(""),[m,F]=f(null),A=G(),k=K({queryKey:["companion",u],queryFn:()=>l.get(`keys/${u}`),enabled:u!==""}),[T,h]=f(null),E=_({mutationFn:(e)=>l.post(`keys/${u}/purchase`,e),onMutate:()=>h(null),onError:(e)=>h(e instanceof Error?e.message:"the purchase was refused"),onSuccess:()=>A.invalidateQueries({queryKey:["companion",u]})}),v=_({mutationFn:(e)=>l.post(`keys/${u}/use`,{item:e}),onMutate:()=>h(null),onError:(e)=>h(e instanceof Error?e.message:"the item could not be used"),onSuccess:()=>A.invalidateQueries({queryKey:["companion",u]})});if(u==="")return r(c,{children:[n("h2",{children:"Companion"}),n("p",{children:n(a,{children:"Each API key raises its own Pokémon. Enter a key id to see it."})}),r("form",{onSubmit:(e)=>{e.preventDefault(),V(d.trim())},children:[n("input",{"aria-label":"API key id",onChange:(e)=>g(e.target.value),placeholder:"key id",value:d}),n(x,{type:"submit",children:"Show"})]})]});if(k.isPending)return n(c,{children:"Loading…"});if(k.isError)return n(c,{children:"No companion for that key yet."});let i=k.data;if(i.state===null)return r(c,{children:[n("h2",{children:"Companion"}),n(U,{children:"This key's save could not be read. It has been left untouched rather than replaced — nothing has been lost, but it needs looking at."})]});let{active:o}=i.state,y=o===null?null:o.plannedPath[o.stageIndex],R=X(o!==null,i.lastCreditAt,Date.now()),D=Object.entries(i.state.inventory).filter(([,e])=>e>0),I=m===null?i.dex:i.dex.filter((e)=>e.rarity===m);return r(c,{children:[n("h2",{children:"Companion"}),r(b,{children:[y===void 0||y===null?n(z,{"aria-label":"An egg, not yet hatched",role:"img"}):n(H,{alt:`Species ${y}${o?.isShiny===!0?", shiny":""}`,src:B(t,y,o?.isShiny===!0)}),r("div",{children:[o===null?r(P,{children:[r("div",{children:["Egg",i.state.eggTier===null?"":` (${i.state.eggTier}+ guaranteed)`]}),r(a,{children:[p(i.progress)," / ",p(i.nextThreshold)," tokens incubated"]}),n(C,{"aria-label":"Incubation",children:n(N,{$pct:i.progress/Math.max(1,i.nextThreshold)*100})})]}):r(P,{children:[r("div",{children:["Stage ",o.stageIndex+1," of ",o.plannedPath.length," · ",o.rarity,o.isShiny?" · shiny":"",o.dittoDisguise===null?"":" · ?"]}),n(a,{children:o.nature}),n(C,{"aria-label":"Growth to the next evolution",children:n(N,{$pct:i.progress/Math.max(1,i.nextThreshold)*100})}),r(a,{children:[p(i.progress)," / ",p(i.nextThreshold)," to the next stage"]})]}),n("div",{"aria-label":`Activity: ${R}`,role:"status",children:R})]})]}),n("p",{children:r(a,{children:[p(i.tokensTotal)," tokens earned · ",p(i.wallet)," to spend"]})}),n("h3",{children:"Shop"}),n(b,{children:i.shop.map((e)=>r(x,{disabled:i.wallet<e.price||E.isPending,onClick:()=>E.mutate(e.entry),type:"button",children:[M(e.entry)," · ",p(e.price)]},`${e.entry.kind}:${M(e.entry)}`))}),n("h3",{children:"Bag"}),D.length===0?n(a,{children:"Nothing in the bag."}):n(b,{children:D.map(([e,q])=>r(W,{children:[r("span",{children:[S(e)," · ",q]}),Y.includes(e)?r(x,{disabled:v.isPending,onClick:()=>v.mutate(e),type:"button",children:["Use ",S(e)]}):n(a,{children:"held"})]},e))}),T===null?null:n(U,{role:"alert",children:T}),n("h3",{children:"Pokédex"}),i.dex.length===0?n(a,{children:"Nothing graduated yet."}):r(P,{children:[n(b,{children:Z.map((e)=>n(x,{"aria-pressed":m===e,onClick:()=>F(e),type:"button",children:e??"all"},e??"all"))}),I.length===0?r(a,{children:["No ",m," graduates yet."]}):n(J,{children:I.map((e)=>r(Q,{children:[n("img",{alt:`${e.rarity}${e.isShiny?" shiny":""} species ${e.finalId}`,src:B(t,e.finalId,e.isShiny),style:{width:"64px",height:"64px",imageRendering:"pixelated"}}),e.nature===null?null:n(j,{children:e.nature})]},e.id))})]})]})}var ke=w({mount:ee});export{X as activityOf,ke as default};
169
+ border: 1px solid var(--rule);
170
+ border-radius: 8px;
171
+ color: var(--ink);
172
+ font: inherit;
173
+ cursor: pointer;
174
+ text-align: center;
175
+
176
+ &:hover {
177
+ border-color: var(--rule-strong);
178
+ }
179
+ &:focus-visible {
180
+ outline: 2px solid var(--accent);
181
+ outline-offset: 2px;
182
+ }
183
+ `,K=a.span`
184
+ font-family: ${H};
185
+ font-size: 12px;
186
+ color: var(--ink-dim);
187
+ overflow-wrap: anywhere;
188
+ `,ge=a.div`
189
+ display: flex;
190
+ align-items: center;
191
+ gap: ${l.sm};
192
+ padding: ${l.sm} ${l.md};
193
+ background: var(--panel-sunk);
194
+ border-radius: 6px;
195
+ `;import{jsx as U,jsxs as me}from"react/jsx-runtime";function fe({inventory:e,onUse:r,pending:i}){let o=Object.entries(e).filter(([,t])=>t>0);if(o.length===0)return U(p,{children:"Nothing in the bag."});return U(y,{children:o.map(([t,n])=>me(ge,{children:[U("span",{children:`${R(t)} · ${n}`}),te.includes(t)?me(x,{disabled:i,onClick:()=>r(t),type:"button",children:["Use ",R(t)]}):U(p,{children:"held"})]},t))})}import{useState as $e}from"react";import{jsx as S,jsxs as J,Fragment as Ie}from"react/jsx-runtime";function he({entries:e,pluginId:r}){let[i,o]=$e(null);if(e.length===0)return S(p,{children:"Nothing graduated yet."});let t=i===null?e:e.filter((n)=>n.rarity===i);return J(Ie,{children:[S(y,{children:ne.map((n)=>S(x,{"aria-pressed":i===n,onClick:()=>o(n),type:"button",children:n??"all"},n??"all"))}),t.length===0?J(p,{children:["No ",i," graduates yet."]}):S(pe,{children:t.map((n)=>J(ue,{children:[S("img",{alt:`${n.rarity}${n.isShiny?" shiny":""} ${n.name??`species ${n.finalId}`}`,src:w(r,n.finalId,n.isShiny),style:{width:"64px",height:"64px",imageRendering:"pixelated"}}),S(z,{children:v(n.name,n.finalId)}),n.nature===null?null:S(z,{children:n.nature})]},n.id))})]})}import{jsx as Q,jsxs as Ee}from"react/jsx-runtime";function W({stages:e,stageIndex:r,progress:i,threshold:o,label:t,valueText:n}){let f=i/Math.max(1,o)*100;return Q(ae,{"aria-label":t,"aria-valuemax":o,"aria-valuemin":0,"aria-valuenow":i,"aria-valuetext":n,role:"progressbar",children:Array.from({length:Math.max(1,e)},(s,k)=>Ee(se,{children:[k<r?Q(q,{$pct:100}):null,k===r?Q(q,{$pct:f}):null]},k))})}function ye(e,r,i,o){return`stage ${r+1} of ${e}, ${c(i)} of ${c(o)} tokens`}import{jsx as g,jsxs as m,Fragment as M}from"react/jsx-runtime";function xe({view:e,activity:r,pluginId:i}){let o=e.state;if(o===null)return null;let{active:t}=o,n=t===null?null:t.plannedPath[t.stageIndex]??null;return m(M,{children:[m(y,{children:[n===null?g(D,{"aria-label":"An egg, not yet hatched",role:"img"}):g(C,{alt:A(e.name,n,t?.isShiny===!0),src:w(i,n,t?.isShiny===!0)}),m("div",{children:[g("h3",{children:n===null?"Egg":v(e.name,n)}),m(y,{children:[t===null?o.eggTier===null?null:m(b,{children:[o.eggTier,"+ guaranteed"]}):m(M,{children:[g(b,{children:t.rarity}),t.isShiny?m(ie,{children:[g("span",{"aria-hidden":"true",children:"✦"}),"shiny"]}):null,g(b,{children:t.nature}),t.dittoDisguise===null?null:g(b,{children:"?"})]}),g(b,{"aria-label":`Activity: ${r}`,role:"status",children:r})]}),t===null?m(M,{children:[g(W,{label:"Incubation",progress:e.progress,stageIndex:0,stages:1,threshold:e.nextThreshold,valueText:`${c(e.progress)} of ${c(e.nextThreshold)} tokens incubated`}),m(p,{children:[c(e.progress)," / ",c(e.nextThreshold)," tokens incubated"]})]}):m(M,{children:[g(W,{label:"Growth to the next evolution",progress:e.progress,stageIndex:t.stageIndex,stages:t.plannedPath.length,threshold:e.nextThreshold,valueText:ye(t.plannedPath.length,t.stageIndex,e.progress,e.nextThreshold)}),m(p,{children:["Stage ",t.stageIndex+1," of ",t.plannedPath.length]}),m(p,{children:[c(e.progress)," / ",c(e.nextThreshold)," to the next stage"]})]})]})]}),m(le,{children:[m(N,{children:[g(L,{children:"Earned"}),g(_,{children:c(e.tokensTotal)})]}),m(N,{children:[g(L,{children:"To spend"}),g(_,{children:c(e.wallet)})]}),m(N,{children:[g(L,{children:"Graduated"}),g(_,{children:e.dex.length.toLocaleString()})]})]})]})}import{useState as Ae}from"react";import{jsx as u,jsxs as O}from"react/jsx-runtime";function be({keys:e,onPick:r,pluginId:i,rosterFailed:o}){let[t,n]=Ae("");return O(I,{children:[u("h2",{children:"Companion"}),u("p",{children:u(p,{children:"Each API key raises its own Pokémon on the tokens it spends. Pick a key."})}),e.length>0?u(de,{children:e.map((f)=>u(Re,{entry:f,onPick:r,pluginId:i},f.apiKeyId))}):u(p,{children:o?"The list of keys could not be loaded. Enter a key id below to reach a companion directly.":"No key has spent a token yet. A companion appears the first time a key serves a request."}),u(P,{children:"Or by key id"}),u("form",{onSubmit:(f)=>{f.preventDefault();let s=t.trim();if(s!=="")r(s)},children:O(y,{children:[u("input",{"aria-label":"API key id",onChange:(f)=>n(f.target.value),placeholder:"key id",value:t}),u(x,{type:"submit",children:"Show"})]})})]})}function Re({entry:e,onPick:r,pluginId:i}){let o=T(e.speciesId!==null,e.lastCreditAt,Date.now());return O(ce,{onClick:()=>r(e.apiKeyId),type:"button",children:[e.unreadable?u(oe,{"aria-label":"This key's save could not be read",role:"img"}):e.speciesId===null?u(D,{"aria-label":"An egg, not yet hatched",role:"img"}):u(C,{alt:A(e.name,e.speciesId,e.isShiny),src:w(i,e.speciesId,e.isShiny)}),u("strong",{children:e.unreadable?"Save unreadable":e.speciesId===null?"Egg":v(e.name,e.speciesId)}),e.rarity===null?null:u(b,{children:e.rarity}),u(K,{children:e.apiKeyId}),O(p,{children:[u(B,{children:c(e.tokensTotal)}),e.unreadable?null:` · ${o}`]})]})}import{jsx as ke,jsxs as Ce}from"react/jsx-runtime";function Se({offers:e,wallet:r,onBuy:i,pending:o}){return ke(y,{children:e.map((t)=>Ce(x,{disabled:r<t.price||o,onClick:()=>i(t.entry),type:"button",children:[F(t.entry)," · ",ke(B,{children:c(t.price)})]},`${t.entry.kind}:${F(t.entry)}`))})}import{jsx as d,jsxs as Y,Fragment as _e}from"react/jsx-runtime";var Be=15000;function Ne({pluginId:e,api:r}){let[i,o]=Pe({at:"start"}),t=De(),n=ve({queryKey:["roster"],queryFn:()=>r.get("keys")}),f=n.data?.keys??[];if(i.at==="start"&&!n.isPending){let h=f.length===1?f[0]:void 0;o(h===void 0?{at:"roster"}:{at:"key",apiKeyId:h.apiKeyId})}let s=i.at==="key"?i.apiKeyId:null,k=ve({queryKey:["companion",s],queryFn:()=>r.get(`keys/${s}`),enabled:s!==null,refetchInterval:Be}),[Te,E]=Pe(null),Z=()=>{t.invalidateQueries({queryKey:["companion",s]}),t.invalidateQueries({queryKey:["roster"]})},X=we({mutationFn:(h)=>r.post(`keys/${s}/purchase`,h),onMutate:()=>E(null),onError:(h)=>E(h instanceof Error?h.message:"the purchase was refused"),onSuccess:Z}),j=we({mutationFn:(h)=>r.post(`keys/${s}/use`,{item:h}),onMutate:()=>E(null),onError:(h)=>E(h instanceof Error?h.message:"the item could not be used"),onSuccess:Z});if(n.isPending)return d(I,{children:"Loading…"});if(s===null)return d(be,{keys:f,onPick:(h)=>o({at:"key",apiKeyId:h}),pluginId:e,rosterFailed:n.isError});return Y(I,{children:[Y(y,{children:[d("h2",{children:"Companion"}),d(K,{children:s}),d(x,{onClick:()=>o({at:"roster"}),type:"button",children:"All keys"})]}),d(Le,{buy:X.mutate,buying:X.isPending,keyId:s,onUse:j.mutate,pluginId:e,query:k,refusal:Te,using:j.isPending})]})}function Le({query:e,pluginId:r,buy:i,onUse:o,buying:t,using:n,refusal:f}){if(e.isPending)return d(p,{children:"Loading…"});if(e.isError||e.data===void 0)return d(p,{children:"No companion for that key yet."});let s=e.data;if(s.state===null)return d(G,{children:"This key's save could not be read. It has been left untouched rather than replaced — nothing has been lost, but it needs looking at."});let k=T(s.state.active!==null,s.lastCreditAt,Date.now());return Y(_e,{children:[d(xe,{activity:k,pluginId:r,view:s}),d(P,{children:"Shop"}),d(Se,{offers:s.shop,onBuy:i,pending:t,wallet:s.wallet}),d(P,{children:"Bag"}),d(fe,{inventory:s.state.inventory,onUse:o,pending:n}),f===null?null:d(G,{role:"alert",children:f}),d(P,{children:"Pokédex"}),d(he,{entries:s.dex,pluginId:r})]})}var Ut=V({mount:Ne});export{T as activityOf,Ut as default};