@tapflowio/relay 0.18.0 → 0.19.0

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 (97) hide show
  1. package/README.md +1 -1
  2. package/dist/RelayServer.d.ts +263 -2
  3. package/dist/RelayServer.d.ts.map +1 -1
  4. package/dist/RelayServer.js +936 -177
  5. package/dist/RelayServer.js.map +1 -1
  6. package/dist/SessionManager.d.ts +83 -17
  7. package/dist/SessionManager.d.ts.map +1 -1
  8. package/dist/SessionManager.js +107 -14
  9. package/dist/SessionManager.js.map +1 -1
  10. package/dist/index.d.ts +0 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/types.d.ts +2 -38
  13. package/dist/types.d.ts.map +1 -1
  14. package/dist/types.js +13 -0
  15. package/dist/types.js.map +1 -1
  16. package/package.json +8 -8
  17. package/public/assets/{AppCenter-B3FO67aw.js → AppCenter-DyP0aqfF.js} +2 -2
  18. package/public/assets/AppCenter-DyP0aqfF.js.br +0 -0
  19. package/public/assets/Default-D7ScPE30.js +1 -0
  20. package/public/assets/Default-D7ScPE30.js.br +0 -0
  21. package/public/assets/Invite-UmhV5rAf.js +1 -0
  22. package/public/assets/Invite-UmhV5rAf.js.br +0 -0
  23. package/public/assets/MacResources-MS4E00w3.js +1 -0
  24. package/public/assets/MacResources-MS4E00w3.js.br +0 -0
  25. package/public/assets/NotFound-BoDDivK5.js +1 -0
  26. package/public/assets/NotFound-BoDDivK5.js.br +0 -0
  27. package/public/assets/QASession-CjgJHDZ3.js +125 -0
  28. package/public/assets/QASession-CjgJHDZ3.js.br +0 -0
  29. package/public/assets/ResetPassword-CAlB6CfP.js +1 -0
  30. package/public/assets/ResetPassword-CAlB6CfP.js.br +0 -0
  31. package/public/assets/Setup-CPm2-hPJ.js +1 -0
  32. package/public/assets/Setup-CPm2-hPJ.js.br +0 -0
  33. package/public/assets/{Team-CBsjuUwh.js → Team-GEIzrM1D.js} +2 -2
  34. package/public/assets/Team-GEIzrM1D.js.br +0 -0
  35. package/public/assets/Tokens-DSeBz_CJ.js +1 -0
  36. package/public/assets/Tokens-DSeBz_CJ.js.br +0 -0
  37. package/public/assets/alert-dialog-BsXI9SVV.js +1 -0
  38. package/public/assets/alert-dialog-BsXI9SVV.js.br +0 -0
  39. package/public/assets/badge-BkdYQFsh.js +1 -0
  40. package/public/assets/badge-BkdYQFsh.js.br +0 -0
  41. package/public/assets/{build-format-B78hbKY9.js → build-format-CXuQt1X2.js} +3 -3
  42. package/public/assets/build-format-CXuQt1X2.js.br +0 -0
  43. package/public/assets/{dialog-BxC9v2BL.js → dialog-DuXZpbiF.js} +3 -3
  44. package/public/assets/dialog-DuXZpbiF.js.br +0 -0
  45. package/public/assets/{index-uGJGo6ac.css → index-Bk2hqaHZ.css} +1 -1
  46. package/public/assets/index-Bk2hqaHZ.css.br +0 -0
  47. package/public/assets/index-bitr6DIC.js +215 -0
  48. package/public/assets/index-bitr6DIC.js.br +0 -0
  49. package/public/assets/{pencil-Cq64I9LV.js → pencil-iRR275s8.js} +1 -1
  50. package/public/assets/pencil-iRR275s8.js.br +0 -0
  51. package/public/assets/table-CHmhGpHG.js +1 -0
  52. package/public/assets/table-CHmhGpHG.js.br +0 -0
  53. package/public/assets/tabs-BnbeuAOe.js +1 -0
  54. package/public/assets/tabs-BnbeuAOe.js.br +0 -0
  55. package/public/assets/{trash-2-CszwJHEh.js → trash-2-QI162w2K.js} +1 -1
  56. package/public/assets/trash-2-QI162w2K.js.br +0 -0
  57. package/public/assets/vendor-charts-DyX5CBcf.js +5 -0
  58. package/public/assets/vendor-charts-DyX5CBcf.js.br +0 -0
  59. package/public/assets/vendor-react-AJpf4YZ0.js +49 -0
  60. package/public/assets/vendor-react-AJpf4YZ0.js.br +0 -0
  61. package/public/assets/vendor-router-ChFy8CZ1.js +12 -0
  62. package/public/assets/vendor-router-ChFy8CZ1.js.br +0 -0
  63. package/public/index.html +4 -2
  64. package/public/index.html.br +0 -0
  65. package/public/assets/AppCenter-B3FO67aw.js.br +0 -0
  66. package/public/assets/Default-BlNUv5dw.js +0 -1
  67. package/public/assets/Default-BlNUv5dw.js.br +0 -0
  68. package/public/assets/Invite-CKYFmy7S.js +0 -1
  69. package/public/assets/Invite-CKYFmy7S.js.br +0 -0
  70. package/public/assets/MacResources-BK4VQnFc.js +0 -5
  71. package/public/assets/MacResources-BK4VQnFc.js.br +0 -0
  72. package/public/assets/NotFound-BMmi1paB.js +0 -1
  73. package/public/assets/NotFound-BMmi1paB.js.br +0 -0
  74. package/public/assets/QASession-CVTlqW3d.js +0 -125
  75. package/public/assets/QASession-CVTlqW3d.js.br +0 -0
  76. package/public/assets/ResetPassword-VPPBWzSI.js +0 -1
  77. package/public/assets/ResetPassword-VPPBWzSI.js.br +0 -0
  78. package/public/assets/Setup-CRdnCl41.js +0 -1
  79. package/public/assets/Setup-CRdnCl41.js.br +0 -0
  80. package/public/assets/Team-CBsjuUwh.js.br +0 -0
  81. package/public/assets/Tokens-CU9HB9WD.js +0 -1
  82. package/public/assets/Tokens-CU9HB9WD.js.br +0 -0
  83. package/public/assets/alert-dialog-DWqGDQTB.js +0 -1
  84. package/public/assets/alert-dialog-DWqGDQTB.js.br +0 -0
  85. package/public/assets/badge-OToVq1dK.js +0 -1
  86. package/public/assets/badge-OToVq1dK.js.br +0 -0
  87. package/public/assets/build-format-B78hbKY9.js.br +0 -3
  88. package/public/assets/dialog-BxC9v2BL.js.br +0 -0
  89. package/public/assets/index-DXjMx9hQ.js +0 -274
  90. package/public/assets/index-DXjMx9hQ.js.br +0 -0
  91. package/public/assets/index-uGJGo6ac.css.br +0 -0
  92. package/public/assets/pencil-Cq64I9LV.js.br +0 -0
  93. package/public/assets/table-CbATN5Pi.js +0 -1
  94. package/public/assets/table-CbATN5Pi.js.br +0 -0
  95. package/public/assets/tabs-BVumgDA4.js +0 -1
  96. package/public/assets/tabs-BVumgDA4.js.br +0 -0
  97. package/public/assets/trash-2-CszwJHEh.js.br +0 -0
@@ -1,12 +1,25 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import { WebSocket } from 'ws';
3
- import { ValidationError } from '@tapflowio/agent-core';
4
3
  const DEFAULT_IDLE_TIMEOUT_MS = parseInt(process.env['IDLE_TIMEOUT_MS'] ?? String(5 * 60 * 1000));
5
4
  export class SessionManager {
6
5
  sessions = new Map();
7
6
  agentResources = new Map();
8
7
  agentSocketIndex = new Map();
9
8
  streamSocketIndex = new Map();
9
+ /**
10
+ * Which sessions a browser socket holds. **A set, because the relation is one-to-many** — and it was a
11
+ * single `Session` until #507 was diagnosed, which is the whole of that defect.
12
+ *
13
+ * `mcp-server` opens exactly one socket (`client.ts`, one `new WebSocket`) and sends a `session:start`
14
+ * per device, because an LLM can hold several sessions at once and its waiters are keyed per session.
15
+ * With one slot per socket, the second join silently overwrote the first — `A.browserSocket` still
16
+ * pointed at the socket, so *commands* kept working, and only the reverse lookup lost A. The close
17
+ * handler resolves through that lookup, so **A was never released**: `busy: true` for the life of the
18
+ * relay, no idle timer, and a device left booted with nobody watching it.
19
+ *
20
+ * That is also why the obvious reading of #507 — "release the previous session when a socket joins
21
+ * another" — is a regression rather than a fix. Two independent design reviews reached it separately.
22
+ */
10
23
  browserSocketIndex = new Map();
11
24
  idleTimeoutMs;
12
25
  constructor(options = {}) {
@@ -42,6 +55,9 @@ export class SessionManager {
42
55
  ...SessionManager.agentFields(agent, d),
43
56
  agentSocket,
44
57
  browserSocket: null,
58
+ owner: null,
59
+ ownerMinted: false,
60
+ ownerUser: null,
45
61
  streamSocket: null,
46
62
  deviceId: d.id,
47
63
  readySent: false,
@@ -86,24 +102,78 @@ export class SessionManager {
86
102
  getByStreamSocket(ws) {
87
103
  return this.streamSocketIndex.get(ws);
88
104
  }
105
+ /** Every session this socket holds. **Plural**, and the caller must treat it as such — the close
106
+ * handler releasing only the first is the defect the index comment above describes. */
89
107
  getByBrowserSocket(ws) {
90
- return this.browserSocketIndex.get(ws);
108
+ return [...(this.browserSocketIndex.get(ws) ?? [])];
109
+ }
110
+ /** Drop `session` from its browser socket's set, and the key with it when the set empties. Leaving an
111
+ * empty `Set` behind would keep a closed socket referenced for the life of the relay. */
112
+ unindexBrowser(session) {
113
+ const ws = session.browserSocket;
114
+ if (!ws)
115
+ return;
116
+ const held = this.browserSocketIndex.get(ws);
117
+ if (!held)
118
+ return;
119
+ held.delete(session);
120
+ if (held.size === 0)
121
+ this.browserSocketIndex.delete(ws);
91
122
  }
92
- join(sessionId, browserSocket) {
123
+ /**
124
+ * @returns `not-found` and `held-by-another` rather than throwing them, **so an unexpected failure and
125
+ * an expected one stop sharing a channel.** `session:start` answered both from one `catch`, and
126
+ * the comment there said reaching it meant something the handler did not anticipate — while the
127
+ * most common way to reach it was a socket re-joining the session it already holds (#515). An
128
+ * expected failure that travels as an exception is indistinguishable from a bug by the time it
129
+ * is caught, and the handler then has to guess a `reason`.
130
+ */
131
+ join(sessionId, browserSocket, owner, isAlive) {
93
132
  const session = this.sessions.get(sessionId);
94
133
  if (!session)
95
- throw new ValidationError(`Session not found: ${sessionId}`);
96
- if (session.browserSocket?.readyState === WebSocket.OPEN) {
97
- throw new ValidationError(`Session busy: ${sessionId}`);
134
+ return { ok: false, failure: 'not-found' };
135
+ // **Three conditions, and each one is an issue.** A session is occupied only when someone *else* holds
136
+ // it, on a socket that is open, and that socket is answering.
137
+ //
138
+ // - `owner !== owner` is #527 and #515: a re-join by the same client is idempotent whether or not the
139
+ // socket is the same one, which is what makes a tab's four sockets one holder and an automatic
140
+ // reconnect a takeover rather than a refusal.
141
+ // - `readyState === OPEN` was the whole test, and it is not a liveness signal. A laptop that went to
142
+ // sleep leaves it OPEN until TCP or the heartbeat notices.
143
+ // - `isAlive` is that signal, passed in because liveness lives on the server rather than here — as a
144
+ // predicate over the socket rather than a thunk, so it is applied to *this* session's holder and
145
+ // cannot be closed over a stale one. `list()` below takes the same shape for the same reason.
146
+ // #579 is the gap between `readyState` and this.
147
+ if (session.browserSocket &&
148
+ session.owner !== null &&
149
+ session.owner !== owner.key &&
150
+ session.browserSocket.readyState === WebSocket.OPEN &&
151
+ isAlive(session.browserSocket)) {
152
+ return { ok: false, failure: 'held-by-another' };
98
153
  }
99
154
  if (session.idleTimer) {
100
155
  clearTimeout(session.idleTimer);
101
156
  session.idleTimer = null;
102
157
  }
103
- if (session.browserSocket)
104
- this.browserSocketIndex.delete(session.browserSocket);
158
+ // Unconditional, and **the order is what makes it safe**: this releases the session from whichever
159
+ // socket held it, which on a re-join is the socket joining. Removing and re-adding the same entry is a
160
+ // no-op; doing it *after* the add below would delete the entry this join just made, leaving the
161
+ // session bound for commands and invisible to the close handler — #507 rebuilt one method over.
162
+ //
163
+ // A guard reading `!== browserSocket` stood here with that reasoning written as its justification. It
164
+ // was dead: mutation testing removed the guard and every test still passed, because the add follows.
165
+ this.unindexBrowser(session);
105
166
  session.browserSocket = browserSocket;
106
- this.browserSocketIndex.set(browserSocket, session);
167
+ session.owner = owner.key;
168
+ session.ownerMinted = owner.minted;
169
+ session.ownerUser = owner.user;
170
+ let held = this.browserSocketIndex.get(browserSocket);
171
+ if (!held) {
172
+ held = new Set();
173
+ this.browserSocketIndex.set(browserSocket, held);
174
+ }
175
+ held.add(session);
176
+ return { ok: true };
107
177
  }
108
178
  remove(sessionId) {
109
179
  const session = this.sessions.get(sessionId);
@@ -115,8 +185,7 @@ export class SessionManager {
115
185
  }
116
186
  if (session.streamSocket)
117
187
  this.streamSocketIndex.delete(session.streamSocket);
118
- if (session.browserSocket)
119
- this.browserSocketIndex.delete(session.browserSocket);
188
+ this.unindexBrowser(session);
120
189
  const agentIds = this.agentSocketIndex.get(session.agentSocket);
121
190
  agentIds?.delete(sessionId);
122
191
  if (agentIds?.size === 0)
@@ -128,9 +197,12 @@ export class SessionManager {
128
197
  if (!session)
129
198
  return;
130
199
  if (session.browserSocket) {
131
- this.browserSocketIndex.delete(session.browserSocket);
200
+ this.unindexBrowser(session);
132
201
  session.browserSocket = null;
133
202
  }
203
+ session.owner = null;
204
+ session.ownerMinted = false;
205
+ session.ownerUser = null;
134
206
  if (session.idleTimer) {
135
207
  clearTimeout(session.idleTimer);
136
208
  session.idleTimer = null;
@@ -247,7 +319,20 @@ export class SessionManager {
247
319
  if (session)
248
320
  session.deviceStatus = status;
249
321
  }
250
- list() {
322
+ /**
323
+ * @param asker the owner key of the socket that asked, so `busy` can mean *busy for you*.
324
+ * @param isAlive whether a holder's socket is answering — the same predicate occupancy uses.
325
+ *
326
+ * **`busy` has to agree with the occupancy test or the UI locks a tester out of their own session.**
327
+ * `browserSocket !== null` said "someone holds it", which is a different question from "you cannot have
328
+ * it": `QASession` renders `disabled={isBusy}`, so a tester whose socket reconnected automatically found
329
+ * their own device greyed out with no way to reach the takeover that would have worked. And a holder
330
+ * that has stopped answering keeps the card locked for everyone until the sweep notices.
331
+ *
332
+ * Passing the same `isAlive` rather than a second liveness rule is the point — two predicates that
333
+ * disagree would flash a device as free while a join for it is still refused.
334
+ */
335
+ list(asker, isAlive) {
251
336
  // Group sessions by agentSocket
252
337
  const agentMap = new Map();
253
338
  for (const session of this.sessions.values()) {
@@ -275,7 +360,15 @@ export class SessionManager {
275
360
  status: s.deviceStatus,
276
361
  osVersion: s.deviceOsVersion,
277
362
  sessionId: s.id,
278
- busy: s.browserSocket !== null,
363
+ busy: s.owner !== null &&
364
+ s.owner !== asker &&
365
+ s.browserSocket !== null &&
366
+ // The clause that was missing, and its absence was the mirror of the failure the docstring warns
367
+ // about: a socket in CLOSING has not fired `close` yet, so `isAlive` is still true — the card
368
+ // read `busy` while a join for it would have succeeded, locking every other tester out of a
369
+ // device the relay was ready to hand them.
370
+ s.browserSocket.readyState === WebSocket.OPEN &&
371
+ isAlive(s.browserSocket),
279
372
  })),
280
373
  }));
281
374
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -11,5 +11,4 @@ export { startTlsBackgroundTasks } from './lib/tlsTasks.js';
11
11
  export type { DnsProviderEntry } from './lib/cert/index.js';
12
12
  export type { TlsConfig } from './lib/cert/index.js';
13
13
  export type { Session } from './SessionManager.js';
14
- export type { RelayMessage, MessageType } from './types.js';
15
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AACrF,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC/G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AACrF,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC/G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA"}
package/dist/types.d.ts CHANGED
@@ -1,42 +1,6 @@
1
- export type MessageType = 'agent:register' | 'agent:registered' | 'agent:resources' | 'agents:list' | 'agents:listed' | 'session:start' | 'session:joined' | 'session:chrome' | 'session:deviceInfo' | 'session:end' | 'session:leave' | 'session:terminated' | 'session:agent-away' | 'session:rebound' | 'stream:register' | 'stream:registered' | 'device:boot' | 'device:booting' | 'device:ready' | 'device:boot-error' | 'device:shutdown' | 'device:shutdown-done' | 'app:install' | 'app:install-done' | 'app:install-error' | 'app:launch' | 'app:launch-done' | 'app:launch-error' | 'open-url' | 'open-url:done' | 'open-url:error' | 'app:clear-state' | 'app:clear-state-done' | 'app:clear-state-error' | 'input:touch:start' | 'input:touch:move' | 'input:touch:end' | 'input:pinch:start' | 'input:pinch:move' | 'input:pinch:end' | 'input:key' | 'input:type' | 'input:type-done' | 'input:type-error' | 'input:done' | 'input:error' | 'input:button' | 'input:rotate' | 'input:keyboard:toggle' | 'keyboard:toggled' | 'screenshot:request' | 'screenshot:done' | 'screenshot:error' | 'ui:tree:request' | 'ui:tree:response' | 'ui:tree:error' | 'clipboard:read' | 'clipboard:write' | 'clipboard:data' | 'clipboard:write-done' | 'clipboard:error' | 'error';
2
1
  import type { AgentResources, UIElement } from '@tapflowio/agent-core';
3
2
  export type { AgentResources, UIElement };
4
- import type { DeviceSummary, SessionTerminatedReason } from '@tapflowio/protocol';
5
- export type { DeviceReport, DeviceSummary, SessionTerminatedReason } from '@tapflowio/protocol';
3
+ import type { DeviceSummary } from '@tapflowio/protocol';
4
+ export type { DeviceDetails, DeviceReport, DeviceSummary, SessionInfo, SessionTerminatedReason } from '@tapflowio/protocol';
6
5
  export type DeviceInfo = DeviceSummary;
7
- export interface SessionInfo {
8
- agentName?: string;
9
- platform?: string;
10
- resources?: AgentResources;
11
- devices: DeviceInfo[];
12
- }
13
- export interface RelayMessage {
14
- type: MessageType;
15
- sessionId?: string;
16
- payload?: unknown;
17
- message?: string;
18
- agentName?: string;
19
- agentId?: string;
20
- devices?: Array<{
21
- id: string;
22
- name: string;
23
- platform: string;
24
- status: string;
25
- osVersion?: string;
26
- }>;
27
- platform?: string;
28
- capabilities?: string[];
29
- sessions?: SessionInfo[];
30
- registeredSessions?: Array<{
31
- deviceId: string;
32
- sessionId: string;
33
- }>;
34
- buildId?: number;
35
- resources?: AgentResources;
36
- requestId?: string;
37
- data?: string;
38
- format?: 'png' | 'jpeg';
39
- elements?: UIElement[];
40
- reason?: SessionTerminatedReason;
41
- }
42
6
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,CAAA;AAIzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE3H,MAAM,MAAM,UAAU,GAAG,aAAa,CAAA"}
package/dist/types.js CHANGED
@@ -1,2 +1,15 @@
1
+ // The wire contract lives in @tapflowio/protocol. This file holds what the relay adds on top of it —
2
+ // today only the re-exports and aliases below.
3
+ //
4
+ // **`RelayMessage` and `MessageType` were removed here (#550).** They were a flat interface where
5
+ // `type` was the only required member and a hand-copied union of 63 literals beside it, and they were
6
+ // the relay's *inbound* type: `route` took a `RelayMessage`, so every field it read was optional by
7
+ // construction and every one it needed came with a `!`. That is why the two type systems could
8
+ // disagree about the same wire field — `format?` here against a required `format` in the protocol —
9
+ // with nothing to report it.
10
+ //
11
+ // What replaced them is not another declaration but a parse: `@tapflowio/protocol/validate` turns an
12
+ // inbound frame into a discriminated union at the door, and the relay's own membership assertions
13
+ // went with the literal list they were holding, because there is no longer a second copy to hold.
1
14
  export {};
2
15
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,+CAA+C;AAC/C,EAAE;AACF,kGAAkG;AAClG,sGAAsG;AACtG,oGAAoG;AACpG,+FAA+F;AAC/F,oGAAoG;AACpG,6BAA6B;AAC7B,EAAE;AACF,qGAAqG;AACrG,kGAAkG;AAClG,kGAAkG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapflowio/relay",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "WebSocket relay server for tapflow — NAT traversal, session routing, JWT auth, bundled dashboard",
5
5
  "keywords": [
6
6
  "tapflow",
@@ -39,7 +39,7 @@
39
39
  "LICENSE"
40
40
  ],
41
41
  "engines": {
42
- "node": ">=20.12.0"
42
+ "node": ">=22.0.0"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"
@@ -49,17 +49,17 @@
49
49
  "better-sqlite3": "^12.11.1",
50
50
  "busboy": "^1.6.0",
51
51
  "jsonwebtoken": "^9.0.3",
52
- "nodemailer": "^9.0.3",
53
- "ws": "^8.21.1",
52
+ "nodemailer": "^9.0.5",
53
+ "ws": "^8.21.3",
54
54
  "zod": "^4.4.3",
55
- "@tapflowio/agent-core": "0.18.0",
56
- "@tapflowio/protocol": "0.18.0"
55
+ "@tapflowio/agent-core": "0.19.0",
56
+ "@tapflowio/protocol": "0.19.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/better-sqlite3": "^7.6.13",
60
60
  "@types/busboy": "^1.5.4",
61
61
  "@types/jsonwebtoken": "^9.0.10",
62
- "@types/node": "^20.19.43",
62
+ "@types/node": "^22.20.1",
63
63
  "@types/nodemailer": "^8.0.1",
64
64
  "@types/ws": "^8.0.0",
65
65
  "typescript": "^5.0.0",
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsc -b && rm -rf dist/migrations && cp -r src/migrations dist/migrations",
71
- "typecheck": "tsc -b",
71
+ "typecheck": "tsc -b && tsc -p src/__tests__/tsconfig.json",
72
72
  "start": "node dist/server.js",
73
73
  "test": "vitest run",
74
74
  "lint": "eslint src"
@@ -1,4 +1,4 @@
1
- import{W as C,a6 as r,a3 as e,B as y,L as b,a8 as k,J,I as M,S as Q,f as W,ak as Y,al as K}from"./index-DXjMx9hQ.js";import{e as X,S as ee,P as se,g as ae,h as te,i as le,b as ne,d as re,s as ce,u as ie}from"./build-format-B78hbKY9.js";import{D as O,f as L,a as U,d as E,e as V,S as A,i as _,j as B,g as z,h as i,C as oe}from"./dialog-BxC9v2BL.js";import{P as de,T as ue}from"./trash-2-CszwJHEh.js";import{B as T}from"./badge-OToVq1dK.js";import{A as he,c as xe,f as pe,g as me,d as fe,e as ge,b as je,a as ve}from"./alert-dialog-DWqGDQTB.js";/**
1
+ import{i as r,j as e}from"./vendor-react-AJpf4YZ0.js";import{W as C,B as y,L as b,a4 as k,J,I as M,S as Q,f as W}from"./index-bitr6DIC.js";import{e as Y,S as K,P as X,g as ee,h as se,i as ae,b as te,d as le,s as ne,u as re}from"./build-format-CXuQt1X2.js";import{D as O,f as L,a as U,d as E,e as V,S as A,i as _,j as B,g as z,h as i,C as ce}from"./dialog-DuXZpbiF.js";import{P as ie,T as oe}from"./trash-2-QI162w2K.js";import{B as T}from"./badge-BkdYQFsh.js";import{A as de,c as ue,f as he,g as xe,d as pe,e as me,b as fe,a as ge}from"./alert-dialog-BsXI9SVV.js";import{b as je,c as ve}from"./vendor-router-ChFy8CZ1.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -18,4 +18,4 @@ import{W as C,a6 as r,a3 as e,B as y,L as b,a8 as k,J,I as M,S as Q,f as W,ak as
18
18
  *
19
19
  * This source code is licensed under the ISC license.
20
20
  * See the LICENSE file in the root directory of this source tree.
21
- */const De=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Ce=C("upload",De);function Ae({onSuccess:s,appId:l}){const[h,c]=r.useState(!1),[t,g]=r.useState(null),[o,x]=r.useState("none"),j=r.useRef(null);function p(n){if(n.preventDefault(),!t)return;const d=new FormData;d.append("file",t),o!=="none"&&d.append("status",o),l&&d.append("app_id",String(l));const w=fetch("/api/v1/builds",{method:"POST",credentials:"include",body:d}).then(async u=>{if(!u.ok){const m=await u.json().catch(()=>({}));throw new Error(m.error??"Upload failed. Check the file format.")}s()});k.promise(w,{loading:"Uploading build…",success:"Build uploaded",error:u=>u instanceof Error?u.message:"Failed to upload build"}),c(!1),g(null),x("none")}function N(n){c(n),n||(g(null),x("none"))}return e.jsxs(O,{open:h,onOpenChange:N,children:[e.jsx(L,{asChild:!0,children:e.jsxs(y,{size:"sm",children:[e.jsx(Ce,{className:"mr-2 h-4 w-4"}),"Upload build"]})}),e.jsxs(U,{className:"sm:max-w-md",children:[e.jsx(E,{children:e.jsx(V,{children:"Upload build"})}),e.jsxs("form",{onSubmit:p,className:"flex flex-col gap-4 pt-2",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(b,{children:"File"}),e.jsx("div",{className:"flex h-24 cursor-pointer items-center justify-center rounded-md border-2 border-dashed text-sm text-muted-foreground hover:border-primary",onClick:()=>{var n;return(n=j.current)==null?void 0:n.click()},onDragOver:n=>n.preventDefault(),onDrop:n=>{n.preventDefault();const d=n.dataTransfer.files[0];d&&g(d)},children:t?t.name:"Click or drag to upload"}),e.jsx("input",{ref:j,type:"file",accept:".zip,.apk,.tgz,.tar.gz,application/gzip,application/x-gzip",className:"hidden",onChange:n=>{var d;return g(((d=n.target.files)==null?void 0:d[0])??null)}}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["iOS: ",e.jsx("code",{children:".app.zip"})," or ",e.jsx("code",{children:".tar.gz"})," / ",e.jsx("code",{children:".tgz"})," (e.g. an EAS simulator build)  · Android: ",e.jsx("code",{children:".apk"})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(b,{children:["Status ",e.jsx("span",{className:"text-muted-foreground",children:"(optional)"})]}),e.jsxs(A,{value:o,onValueChange:x,children:[e.jsx(_,{children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"none",children:"None"}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"outline",className:"w-24",onClick:()=>c(!1),children:"Cancel"}),e.jsx(y,{type:"submit",className:"w-24",disabled:!t,children:"Upload"})]})]})]})]})}function D({className:s,...l}){return e.jsx("span",{className:J("font-mono text-xs tabular-nums tracking-tight",s),...l})}function _e({onSuccess:s}){const[l,h]=r.useState(!1),[c,t]=r.useState(""),[g,o]=r.useState(""),[x,j]=r.useState("ios"),[p,N]=r.useState(""),[n,d]=r.useState(!1);async function w(u){u.preventDefault(),N(""),d(!0);try{const m=await X({name:c.trim(),bundle_id_key:g.trim(),platform:x});if(!m){N("Failed to create app");return}if("error"in m){N(m.error);return}h(!1),t(""),o(""),j("ios"),k.success("App created"),s()}catch{k.error("Failed to create app — check your network")}finally{d(!1)}}return e.jsxs(O,{open:l,onOpenChange:h,children:[e.jsx(L,{asChild:!0,children:e.jsxs("button",{className:"flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-left text-sm text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",children:[e.jsx(de,{className:"size-3.5 shrink-0"}),e.jsx("span",{children:"Add App"})]})}),e.jsxs(U,{className:"sm:max-w-sm",children:[e.jsx(E,{children:e.jsx(V,{children:"Add App"})}),e.jsxs("form",{onSubmit:w,className:"flex flex-col gap-4 pt-2",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"app-name",children:"Name"}),e.jsx(M,{id:"app-name",value:c,onChange:u=>t(u.target.value),placeholder:"My App",required:!0})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"bundle-id",children:"Bundle ID"}),e.jsx(M,{id:"bundle-id",value:g,onChange:u=>o(u.target.value),placeholder:"com.example.myapp",required:!0})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"platform",children:"Platform"}),e.jsxs(A,{value:x,onValueChange:u=>j(u),children:[e.jsx(_,{id:"platform",children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"ios",children:"iOS"}),e.jsx(i,{value:"android",children:"Android"}),e.jsx(i,{value:"both",children:"Both"})]})]})]}),p&&e.jsx("p",{className:"text-sm text-destructive",children:p}),e.jsx(y,{type:"submit",disabled:n,className:"w-full",children:n?"Creating…":"Create App"})]})]})]})}function Be({apps:s,selectedAppId:l,onSelect:h,onAdd:c}){return e.jsxs("aside",{className:"w-64 shrink-0 border-r flex flex-col gap-1 p-3 overflow-y-auto",children:[e.jsx("span",{className:"px-2 pb-1 font-mono text-xs font-medium text-muted-foreground uppercase tracking-wider",children:"Apps"}),s.length===0&&e.jsx("span",{className:"px-2 text-sm text-muted-foreground",children:"No apps yet"}),s.map(t=>e.jsxs("button",{onClick:()=>h(t.id),className:["flex flex-col gap-0.5 rounded-md px-2 py-2 text-left text-sm hover:bg-accent overflow-hidden",t.id===l?"bg-accent font-medium":""].join(" "),children:[e.jsx("span",{className:"truncate",children:t.name}),e.jsx(D,{className:"text-muted-foreground truncate",children:t.bundle_id_key})]},t.id)),e.jsx("div",{className:"mt-1 border-t pt-1",children:e.jsx(_e,{onSuccess:c})})]})}function ze(s){const l=/[zZ]|[+-]\d{2}:?\d{2}$/.test(s),c=new Date(l?s:s.replace(" ","T")+"Z").getTime()-Date.now();if(c<=0)return{label:"Deleting…",urgent:!0};const t=Math.floor(c/36e5);return t<1?{label:"Deletes in < 1h",urgent:!0}:t<24?{label:`Deletes in ${t}h`,urgent:t<6}:{label:`Deletes in ${Math.floor(t/24)}d`,urgent:!1}}function Ie({build:s,isLast:l,onNavigate:h,onStatusChange:c,onScheduleDeletion:t,onCancelDeletion:g}){const[o,x]=r.useState(!1),j=s.status_label==="Done",p=s.delete_after?ze(s.delete_after):null;function N(n){c(s.id,n==="none"?null:n)}return e.jsxs(e.Fragment,{children:[e.jsx(he,{open:o,onOpenChange:x,children:e.jsxs(xe,{children:[e.jsxs(pe,{children:[e.jsx(me,{children:"Schedule deletion?"}),e.jsx(fe,{children:"Build files will be deleted after 7 days. You can cancel the scheduled deletion anytime before then."})]}),e.jsxs(ge,{children:[e.jsx(je,{children:"Cancel"}),e.jsx(ve,{onClick:()=>{t(s.id),x(!1)},children:"Schedule deletion"})]})]})}),e.jsxs("div",{className:["flex items-center gap-3 px-4 py-3",l?"":"border-b"].join(" "),children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs("span",{className:"text-sm font-medium",children:["build ",e.jsx(D,{children:s.build_number??"—"})]}),e.jsx(T,{tone:s.platform==="ios"?"ios":"android",className:"text-xs capitalize",children:s.platform}),s.status_label&&e.jsx(T,{tone:ee[s.status_label],className:"text-xs",children:s.status_label}),p&&e.jsx(T,{tone:p.urgent?"rejected":"backlog",className:"text-xs",children:p.label})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"row",gap:"14px",marginTop:"0.7rem",alignItems:"center"},className:"text-xs text-muted-foreground",children:[s.uploader&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:s.uploader}),e.jsx(Q,{orientation:"vertical",className:"h-3"})]}),e.jsx(D,{children:new Date(s.uploaded_at).toLocaleDateString()})]})]}),e.jsxs(A,{value:s.status_label??"none",onValueChange:N,children:[e.jsx(_,{className:"h-9 w-32 text-xs",children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"none",children:e.jsx("span",{className:"text-muted-foreground",children:"—"})}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]}),p?e.jsx(y,{size:"icon-sm",variant:"outline",onClick:()=>g(s.id),title:"Cancel scheduled deletion",children:e.jsx(ke,{className:"h-3.5 w-3.5"})}):e.jsx(y,{size:"icon-sm",variant:"destructive",onClick:()=>x(!0),title:"Schedule deletion",children:e.jsx(ue,{className:"h-3.5 w-3.5"})}),e.jsxs(y,{size:"sm",onClick:()=>h(s.id),disabled:j,children:[e.jsx(se,{className:"mr-1.5 h-3.5 w-3.5"}),"Start QA"]})]})]})}function Pe({versionName:s,builds:l,isOpen:h,onToggle:c,onNavigate:t,onStatusChange:g,onScheduleDeletion:o,onCancelDeletion:x}){return e.jsxs("div",{className:"rounded-lg shadow-card-2 overflow-hidden",children:[e.jsxs("button",{className:"flex w-full items-center gap-2 px-4 py-3 text-left hover:bg-accent/50 bg-card",onClick:c,children:[h?e.jsx(oe,{className:"h-4 w-4 shrink-0 text-muted-foreground"}):e.jsx(W,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),e.jsx(D,{className:"font-medium text-sm text-foreground",children:s}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",l.length," build",l.length>1?"s":"",")"]})]}),h&&e.jsx("div",{className:"border-t bg-card",children:l.map((j,p)=>e.jsx(Ie,{build:j,isLast:p===l.length-1,onNavigate:t,onStatusChange:g,onScheduleDeletion:o,onCancelDeletion:x},j.id))})]})}function Ue(){const s=Y(),[l,h]=K(),[c,t]=r.useState([]),[g,o]=r.useState([]),[x,j]=r.useState(""),[p,N]=r.useState("all"),[n,d]=r.useState(!0),[w,u]=r.useState(new Set),m=l.get("appId")?Number(l.get("appId")):null,F=c.find(a=>a.id===m)??null,I=r.useCallback(async()=>{const a=await ae();t(a),!l.get("appId")&&a.length>0&&h({appId:String(a[0].id)},{replace:!0})},[l,h]),P=r.useCallback(async()=>{if(!m){o([]),d(!1);return}d(!0);try{const a=await te({appId:m,search:x,statusFilter:p});o(a),a.length>0&&w.size===0&&u(new Set([a[0].version_name??"Unversioned"]))}finally{d(!1)}},[m,x,p]);r.useEffect(()=>{I()},[]),r.useEffect(()=>{P()},[P]);function $(a){a!==m&&(o([]),u(new Set)),h({appId:String(a)})}function q(a){u(v=>{const f=new Set(v);return f.has(a)?f.delete(a):f.add(a),f})}async function H(a,v){await ie(a,v),o(f=>f.map(S=>S.id===a?{...S,status_label:v}:S))}async function Z(a){try{const v=await ce(a);o(f=>f.map(S=>S.id===a?{...S,delete_after:v}:S))}catch{k.error("Failed to schedule deletion")}}async function G(a){try{await re(a),o(v=>v.map(f=>f.id===a?{...f,delete_after:null}:f))}catch{k.error("Failed to cancel scheduled deletion")}}const R=le(g);return e.jsxs("div",{className:"flex h-full gap-0",children:[e.jsx(Be,{apps:c,selectedAppId:m,onSelect:$,onAdd:I}),e.jsxs("div",{className:"flex-1 flex flex-col gap-4 p-4 overflow-y-auto min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsx("h1",{className:"text-xl font-semibold tracking-display-sm",children:F?F.name:"App Center"}),e.jsx(Ae,{onSuccess:()=>{I(),P()},appId:m})]}),m?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(ne,{placeholder:"Search version…",value:x,onChange:j}),e.jsxs(A,{value:p,onValueChange:N,children:[e.jsx(_,{className:"h-8 w-36",children:e.jsx(B,{placeholder:"Status"})}),e.jsxs(z,{children:[e.jsx(i,{value:"all",children:"All statuses"}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]})]}),n?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"}):R.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-2 text-center",children:[e.jsx(we,{className:"w-8 h-8 text-muted-foreground/40"}),e.jsx("p",{className:"text-sm font-medium",children:"No builds yet"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Upload the first build to get started."})]}):e.jsx("div",{className:"flex flex-col gap-2",children:R.map(({versionName:a,builds:v})=>e.jsx(Pe,{versionName:a,builds:v,isOpen:w.has(a),onToggle:()=>q(a),onNavigate:f=>s(`/app-center/build?id=${f}`),onStatusChange:H,onScheduleDeletion:Z,onCancelDeletion:G},a))})]}):e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-2 text-center",children:[e.jsx(Se,{className:"w-8 h-8 text-muted-foreground/40"}),e.jsx("p",{className:"text-sm font-medium",children:"No app selected"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Choose an app from the sidebar to view its builds."})]})]})]})}export{Ue as AppCenter};
21
+ */const De=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Ce=C("upload",De);function Ae({onSuccess:s,appId:l}){const[h,c]=r.useState(!1),[t,g]=r.useState(null),[o,x]=r.useState("none"),j=r.useRef(null);function p(n){if(n.preventDefault(),!t)return;const d=new FormData;d.append("file",t),o!=="none"&&d.append("status",o),l&&d.append("app_id",String(l));const w=fetch("/api/v1/builds",{method:"POST",credentials:"include",body:d}).then(async u=>{if(!u.ok){const m=await u.json().catch(()=>({}));throw new Error(m.error??"Upload failed. Check the file format.")}s()});k.promise(w,{loading:"Uploading build…",success:"Build uploaded",error:u=>u instanceof Error?u.message:"Failed to upload build"}),c(!1),g(null),x("none")}function N(n){c(n),n||(g(null),x("none"))}return e.jsxs(O,{open:h,onOpenChange:N,children:[e.jsx(L,{asChild:!0,children:e.jsxs(y,{size:"sm",children:[e.jsx(Ce,{className:"mr-2 h-4 w-4"}),"Upload build"]})}),e.jsxs(U,{className:"sm:max-w-md",children:[e.jsx(E,{children:e.jsx(V,{children:"Upload build"})}),e.jsxs("form",{onSubmit:p,className:"flex flex-col gap-4 pt-2",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(b,{children:"File"}),e.jsx("div",{className:"flex h-24 cursor-pointer items-center justify-center rounded-md border-2 border-dashed text-sm text-muted-foreground hover:border-primary",onClick:()=>{var n;return(n=j.current)==null?void 0:n.click()},onDragOver:n=>n.preventDefault(),onDrop:n=>{n.preventDefault();const d=n.dataTransfer.files[0];d&&g(d)},children:t?t.name:"Click or drag to upload"}),e.jsx("input",{ref:j,type:"file",accept:".zip,.apk,.tgz,.tar.gz,application/gzip,application/x-gzip",className:"hidden",onChange:n=>{var d;return g(((d=n.target.files)==null?void 0:d[0])??null)}}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["iOS: ",e.jsx("code",{children:".app.zip"})," or ",e.jsx("code",{children:".tar.gz"})," / ",e.jsx("code",{children:".tgz"})," (e.g. an EAS simulator build)  · Android: ",e.jsx("code",{children:".apk"})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(b,{children:["Status ",e.jsx("span",{className:"text-muted-foreground",children:"(optional)"})]}),e.jsxs(A,{value:o,onValueChange:x,children:[e.jsx(_,{children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"none",children:"None"}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(y,{type:"button",variant:"outline",className:"w-24",onClick:()=>c(!1),children:"Cancel"}),e.jsx(y,{type:"submit",className:"w-24",disabled:!t,children:"Upload"})]})]})]})]})}function D({className:s,...l}){return e.jsx("span",{className:J("font-mono text-xs tabular-nums tracking-tight",s),...l})}function _e({onSuccess:s}){const[l,h]=r.useState(!1),[c,t]=r.useState(""),[g,o]=r.useState(""),[x,j]=r.useState("ios"),[p,N]=r.useState(""),[n,d]=r.useState(!1);async function w(u){u.preventDefault(),N(""),d(!0);try{const m=await Y({name:c.trim(),bundle_id_key:g.trim(),platform:x});if(!m){N("Failed to create app");return}if("error"in m){N(m.error);return}h(!1),t(""),o(""),j("ios"),k.success("App created"),s()}catch{k.error("Failed to create app — check your network")}finally{d(!1)}}return e.jsxs(O,{open:l,onOpenChange:h,children:[e.jsx(L,{asChild:!0,children:e.jsxs("button",{className:"flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-left text-sm text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",children:[e.jsx(ie,{className:"size-3.5 shrink-0"}),e.jsx("span",{children:"Add App"})]})}),e.jsxs(U,{className:"sm:max-w-sm",children:[e.jsx(E,{children:e.jsx(V,{children:"Add App"})}),e.jsxs("form",{onSubmit:w,className:"flex flex-col gap-4 pt-2",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"app-name",children:"Name"}),e.jsx(M,{id:"app-name",value:c,onChange:u=>t(u.target.value),placeholder:"My App",required:!0})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"bundle-id",children:"Bundle ID"}),e.jsx(M,{id:"bundle-id",value:g,onChange:u=>o(u.target.value),placeholder:"com.example.myapp",required:!0})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(b,{htmlFor:"platform",children:"Platform"}),e.jsxs(A,{value:x,onValueChange:u=>j(u),children:[e.jsx(_,{id:"platform",children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"ios",children:"iOS"}),e.jsx(i,{value:"android",children:"Android"}),e.jsx(i,{value:"both",children:"Both"})]})]})]}),p&&e.jsx("p",{className:"text-sm text-destructive",children:p}),e.jsx(y,{type:"submit",disabled:n,className:"w-full",children:n?"Creating…":"Create App"})]})]})]})}function Be({apps:s,selectedAppId:l,onSelect:h,onAdd:c}){return e.jsxs("aside",{className:"w-64 shrink-0 border-r flex flex-col gap-1 p-3 overflow-y-auto",children:[e.jsx("span",{className:"px-2 pb-1 font-mono text-xs font-medium text-muted-foreground uppercase tracking-wider",children:"Apps"}),s.length===0&&e.jsx("span",{className:"px-2 text-sm text-muted-foreground",children:"No apps yet"}),s.map(t=>e.jsxs("button",{onClick:()=>h(t.id),className:["flex flex-col gap-0.5 rounded-md px-2 py-2 text-left text-sm hover:bg-accent overflow-hidden",t.id===l?"bg-accent font-medium":""].join(" "),children:[e.jsx("span",{className:"truncate",children:t.name}),e.jsx(D,{className:"text-muted-foreground truncate",children:t.bundle_id_key})]},t.id)),e.jsx("div",{className:"mt-1 border-t pt-1",children:e.jsx(_e,{onSuccess:c})})]})}function ze(s){const l=/[zZ]|[+-]\d{2}:?\d{2}$/.test(s),c=new Date(l?s:s.replace(" ","T")+"Z").getTime()-Date.now();if(c<=0)return{label:"Deleting…",urgent:!0};const t=Math.floor(c/36e5);return t<1?{label:"Deletes in < 1h",urgent:!0}:t<24?{label:`Deletes in ${t}h`,urgent:t<6}:{label:`Deletes in ${Math.floor(t/24)}d`,urgent:!1}}function Ie({build:s,isLast:l,onNavigate:h,onStatusChange:c,onScheduleDeletion:t,onCancelDeletion:g}){const[o,x]=r.useState(!1),j=s.status_label==="Done",p=s.delete_after?ze(s.delete_after):null;function N(n){c(s.id,n==="none"?null:n)}return e.jsxs(e.Fragment,{children:[e.jsx(de,{open:o,onOpenChange:x,children:e.jsxs(ue,{children:[e.jsxs(he,{children:[e.jsx(xe,{children:"Schedule deletion?"}),e.jsx(pe,{children:"Build files will be deleted after 7 days. You can cancel the scheduled deletion anytime before then."})]}),e.jsxs(me,{children:[e.jsx(fe,{children:"Cancel"}),e.jsx(ge,{onClick:()=>{t(s.id),x(!1)},children:"Schedule deletion"})]})]})}),e.jsxs("div",{className:["flex items-center gap-3 px-4 py-3",l?"":"border-b"].join(" "),children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsxs("span",{className:"text-sm font-medium",children:["build ",e.jsx(D,{children:s.build_number??"—"})]}),e.jsx(T,{tone:s.platform==="ios"?"ios":"android",className:"text-xs capitalize",children:s.platform}),s.status_label&&e.jsx(T,{tone:K[s.status_label],className:"text-xs",children:s.status_label}),p&&e.jsx(T,{tone:p.urgent?"rejected":"backlog",className:"text-xs",children:p.label})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"row",gap:"14px",marginTop:"0.7rem",alignItems:"center"},className:"text-xs text-muted-foreground",children:[s.uploader&&e.jsxs(e.Fragment,{children:[e.jsx("span",{children:s.uploader}),e.jsx(Q,{orientation:"vertical",className:"h-3"})]}),e.jsx(D,{children:new Date(s.uploaded_at).toLocaleDateString()})]})]}),e.jsxs(A,{value:s.status_label??"none",onValueChange:N,children:[e.jsx(_,{className:"h-9 w-32 text-xs",children:e.jsx(B,{})}),e.jsxs(z,{children:[e.jsx(i,{value:"none",children:e.jsx("span",{className:"text-muted-foreground",children:"—"})}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]}),p?e.jsx(y,{size:"icon-sm",variant:"outline",onClick:()=>g(s.id),title:"Cancel scheduled deletion",children:e.jsx(ke,{className:"h-3.5 w-3.5"})}):e.jsx(y,{size:"icon-sm",variant:"destructive",onClick:()=>x(!0),title:"Schedule deletion",children:e.jsx(oe,{className:"h-3.5 w-3.5"})}),e.jsxs(y,{size:"sm",onClick:()=>h(s.id),disabled:j,children:[e.jsx(X,{className:"mr-1.5 h-3.5 w-3.5"}),"Start QA"]})]})]})}function Pe({versionName:s,builds:l,isOpen:h,onToggle:c,onNavigate:t,onStatusChange:g,onScheduleDeletion:o,onCancelDeletion:x}){return e.jsxs("div",{className:"rounded-lg shadow-card-2 overflow-hidden",children:[e.jsxs("button",{className:"flex w-full items-center gap-2 px-4 py-3 text-left hover:bg-accent/50 bg-card",onClick:c,children:[h?e.jsx(ce,{className:"h-4 w-4 shrink-0 text-muted-foreground"}):e.jsx(W,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),e.jsx(D,{className:"font-medium text-sm text-foreground",children:s}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",l.length," build",l.length>1?"s":"",")"]})]}),h&&e.jsx("div",{className:"border-t bg-card",children:l.map((j,p)=>e.jsx(Ie,{build:j,isLast:p===l.length-1,onNavigate:t,onStatusChange:g,onScheduleDeletion:o,onCancelDeletion:x},j.id))})]})}function Ve(){const s=je(),[l,h]=ve(),[c,t]=r.useState([]),[g,o]=r.useState([]),[x,j]=r.useState(""),[p,N]=r.useState("all"),[n,d]=r.useState(!0),[w,u]=r.useState(new Set),m=l.get("appId")?Number(l.get("appId")):null,F=c.find(a=>a.id===m)??null,I=r.useCallback(async()=>{const a=await ee();t(a),!l.get("appId")&&a.length>0&&h({appId:String(a[0].id)},{replace:!0})},[l,h]),P=r.useCallback(async()=>{if(!m){o([]),d(!1);return}d(!0);try{const a=await se({appId:m,search:x,statusFilter:p});o(a),a.length>0&&w.size===0&&u(new Set([a[0].version_name??"Unversioned"]))}finally{d(!1)}},[m,x,p]);r.useEffect(()=>{I()},[]),r.useEffect(()=>{P()},[P]);function $(a){a!==m&&(o([]),u(new Set)),h({appId:String(a)})}function q(a){u(v=>{const f=new Set(v);return f.has(a)?f.delete(a):f.add(a),f})}async function H(a,v){await re(a,v),o(f=>f.map(S=>S.id===a?{...S,status_label:v}:S))}async function Z(a){try{const v=await ne(a);o(f=>f.map(S=>S.id===a?{...S,delete_after:v}:S))}catch{k.error("Failed to schedule deletion")}}async function G(a){try{await le(a),o(v=>v.map(f=>f.id===a?{...f,delete_after:null}:f))}catch{k.error("Failed to cancel scheduled deletion")}}const R=ae(g);return e.jsxs("div",{className:"flex h-full gap-0",children:[e.jsx(Be,{apps:c,selectedAppId:m,onSelect:$,onAdd:I}),e.jsxs("div",{className:"flex-1 flex flex-col gap-4 p-4 overflow-y-auto min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-2",children:[e.jsx("h1",{className:"text-xl font-semibold tracking-display-sm",children:F?F.name:"App Center"}),e.jsx(Ae,{onSuccess:()=>{I(),P()},appId:m})]}),m?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(te,{placeholder:"Search version…",value:x,onChange:j}),e.jsxs(A,{value:p,onValueChange:N,children:[e.jsx(_,{className:"h-8 w-36",children:e.jsx(B,{placeholder:"Status"})}),e.jsxs(z,{children:[e.jsx(i,{value:"all",children:"All statuses"}),e.jsx(i,{value:"Backlog",children:"Backlog"}),e.jsx(i,{value:"In Progress",children:"In Progress"}),e.jsx(i,{value:"Done",children:"Done"}),e.jsx(i,{value:"Rejected",children:"Rejected"})]})]})]}),n?e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading…"}):R.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-2 text-center",children:[e.jsx(we,{className:"w-8 h-8 text-muted-foreground/40"}),e.jsx("p",{className:"text-sm font-medium",children:"No builds yet"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Upload the first build to get started."})]}):e.jsx("div",{className:"flex flex-col gap-2",children:R.map(({versionName:a,builds:v})=>e.jsx(Pe,{versionName:a,builds:v,isOpen:w.has(a),onToggle:()=>q(a),onNavigate:f=>s(`/app-center/build?id=${f}`),onStatusChange:H,onScheduleDeletion:Z,onCancelDeletion:G},a))})]}):e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center gap-2 text-center",children:[e.jsx(Se,{className:"w-8 h-8 text-muted-foreground/40"}),e.jsx("p",{className:"text-sm font-medium",children:"No app selected"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Choose an app from the sidebar to view its builds."})]})]})]})}export{Ve as AppCenter};
@@ -0,0 +1 @@
1
+ import{i,j as e}from"./vendor-react-AJpf4YZ0.js";import{ai as X,a6 as Z,ad as S,a5 as y,ah as I,C as g,c as j,d as v,a as w,L as m,I as h,S as M,h as O,a4 as n,B as u,E as ee,J as se,H as ae,a2 as C,_ as $,a3 as p}from"./index-bitr6DIC.js";import{B as re}from"./badge-BkdYQFsh.js";import{A as te,h as oe,c as ne,f as ie,g as le,d as ce,e as de,b as me,a as he}from"./alert-dialog-BsXI9SVV.js";import{P as W}from"./pencil-iRR275s8.js";import"./vendor-router-ChFy8CZ1.js";const ue=C({teamName:p().min(1),logo:$(File).nullable().optional()}),pe=C({displayName:p().min(1),avatar:$(File).nullable().optional()}),fe=C({currentPassword:p().min(1),newPassword:p().min(8),confirmPassword:p()}).refine(f=>f.newPassword===f.confirmPassword,{message:"Passwords do not match",path:["confirmPassword"]});function Ne(){const{resolvedTheme:f}=X(),J=f==="dark"?"/logo-dark.svg":"/logo.svg",{user:o}=Z(),b=(o==null?void 0:o.role)==="Admin",N=(o==null?void 0:o.role)==="Admin"||(o==null?void 0:o.role)==="Developer",[V,P]=i.useState(null),A=i.useRef(null),d=S({resolver:y(ue),mode:"onBlur",defaultValues:{teamName:"",logo:null}});i.useEffect(()=>{b&&fetch("/api/v1/settings",{credentials:"include"}).then(s=>s.ok?s.json():null).then(s=>{s&&(d.reset({teamName:s.team_name,logo:null}),P(s.logo_url))})},[b]);async function Q(s){const a=new FormData;a.append("team_name",s.teamName),s.logo&&a.append("logo",s.logo);try{if(!(await fetch("/api/v1/settings",{method:"PATCH",credentials:"include",body:a})).ok){n.error("Failed to update workspace");return}n.success("Workspace updated")}catch{n.error("Failed to update workspace")}}const[k,F]=i.useState(null),D=i.useRef(null),c=S({resolver:y(pe),mode:"onBlur",defaultValues:{displayName:"",avatar:null}});i.useEffect(()=>{o&&(c.reset({displayName:o.displayName??"",avatar:null}),F(o.avatarUrl??null))},[o]);async function Y(s){const a=new FormData;a.append("display_name",s.displayName),s.avatar&&a.append("avatar",s.avatar);try{if(!(await fetch("/api/v1/profile",{method:"PATCH",credentials:"include",body:a})).ok){n.error("Failed to update profile");return}n.success("Profile updated")}catch{n.error("Failed to update profile")}}const t=S({resolver:y(fe),mode:"onBlur"});async function q(s){try{const a=await fetch("/api/v1/auth/change-password",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({currentPassword:s.currentPassword,newPassword:s.newPassword})});if(!a.ok){const r=await a.json();t.setError("root",{message:r.error??"Failed to change password"});return}t.reset(),n.success("Password changed")}catch{t.setError("root",{message:"Network error"})}}const[T,E]=i.useState([]),[B,L]=i.useState({}),[U,z]=i.useState({}),[R,_]=i.useState({});i.useEffect(()=>{N&&fetch("/api/v1/apps",{credentials:"include"}).then(s=>s.ok?s.json():null).then(s=>{if(!s)return;E(s.items);const a={};s.items.forEach(r=>{a[r.id]=r.name}),L(a)})},[N]);async function G(s){_(a=>({...a,[s]:!0}));try{if(!(await fetch(`/api/v1/apps/${s}`,{method:"DELETE",credentials:"include"})).ok){n.error("Failed to delete app");return}E(r=>r.filter(l=>l.id!==s)),n.success("App deleted")}catch{n.error("Failed to delete app")}finally{_(a=>({...a,[s]:!1}))}}async function K(s){z(a=>({...a,[s]:!0}));try{if(!(await fetch(`/api/v1/apps/${s}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:B[s]})})).ok){n.error("Failed to update app");return}n.success("App updated")}catch{n.error("Failed to update app")}finally{z(a=>({...a,[s]:!1}))}}const x=I({control:c.control,name:"displayName"});return e.jsxs("div",{className:"flex flex-col gap-6 max-w-[900px] mx-auto w-full p-6",children:[e.jsx("h1",{className:"text-xl font-semibold tracking-display-sm",children:"Settings"}),b&&e.jsxs(g,{children:[e.jsx(j,{children:e.jsx(v,{children:"Workspace"})}),e.jsx(w,{children:e.jsxs("form",{onSubmit:d.handleSubmit(Q),className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(m,{htmlFor:"team-name",children:"Team name"}),e.jsx(h,{id:"team-name",placeholder:"My QA Team",...d.register("teamName")}),d.formState.errors.teamName&&e.jsx("p",{className:"text-sm text-destructive",children:d.formState.errors.teamName.message})]}),e.jsx(M,{}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(m,{children:["Logo ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(png · jpg, max 2MB)"})]}),e.jsx(O,{name:"logo",control:d.control,render:({field:s})=>e.jsxs("div",{className:"relative w-16 h-16",children:[e.jsx("img",{src:V??J,alt:"Workspace logo",className:"w-16 h-16 rounded-lg object-contain"}),e.jsx("button",{type:"button","aria-label":"Change logo",onClick:()=>{var a;return(a=A.current)==null?void 0:a.click()},className:"absolute bottom-0 right-0 w-6 h-6 rounded-full bg-background border border-border shadow-sm flex items-center justify-center hover:bg-accent transition-colors",children:e.jsx(W,{className:"w-3 h-3","aria-hidden":"true"})}),e.jsx("input",{ref:A,type:"file",accept:".png,.jpg,.jpeg",className:"hidden",onChange:a=>{var l;const r=(l=a.target.files)==null?void 0:l[0];if(r&&r.size>2*1024*1024){n.error("Image must be 2MB or less");return}r&&(s.onChange(r),P(URL.createObjectURL(r)))}})]})})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(u,{type:"submit",size:"sm",disabled:d.formState.isSubmitting,children:d.formState.isSubmitting?"Saving…":"Save changes"})})]})})]}),e.jsxs(g,{children:[e.jsx(j,{children:e.jsx(v,{children:"Profile"})}),e.jsx(w,{children:e.jsxs("form",{onSubmit:c.handleSubmit(Y),className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(m,{htmlFor:"display-name",children:"Nickname"}),e.jsx(h,{id:"display-name",placeholder:"Your name",...c.register("displayName")}),c.formState.errors.displayName&&e.jsx("p",{className:"text-sm text-destructive",children:c.formState.errors.displayName.message})]}),e.jsx(M,{}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(m,{children:["Avatar ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(png · jpg, max 2MB)"})]}),e.jsx(O,{name:"avatar",control:c.control,render:({field:s})=>{var a;return e.jsxs("div",{className:"relative w-14 h-14",children:[k?e.jsx("img",{src:k,alt:"Profile avatar",className:"w-14 h-14 rounded-full object-cover border"}):e.jsx("div",{className:"w-14 h-14 rounded-full flex items-center justify-center text-lg font-medium",style:(()=>{const r=ee(x||(o==null?void 0:o.email)||"");return{backgroundColor:r.bg,color:r.fg}})(),children:((a=x==null?void 0:x[0])==null?void 0:a.toUpperCase())??"?"}),e.jsx("button",{type:"button","aria-label":"Change avatar",onClick:()=>{var r;return(r=D.current)==null?void 0:r.click()},className:"absolute bottom-0 right-0 w-6 h-6 rounded-full bg-background border border-border shadow-sm flex items-center justify-center hover:bg-accent transition-colors",children:e.jsx(W,{className:"w-3 h-3","aria-hidden":"true"})}),e.jsx("input",{ref:D,type:"file",accept:".png,.jpg,.jpeg",className:"hidden",onChange:r=>{var H;const l=(H=r.target.files)==null?void 0:H[0];if(l&&l.size>2*1024*1024){n.error("Image must be 2MB or less");return}l&&(s.onChange(l),F(URL.createObjectURL(l)))}})]})}})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx(u,{type:"submit",size:"sm",disabled:c.formState.isSubmitting,children:c.formState.isSubmitting?"Saving…":"Save changes"})})]})})]}),e.jsxs(g,{children:[e.jsx(j,{children:e.jsx(v,{children:"Password"})}),e.jsx(w,{children:e.jsxs("form",{onSubmit:t.handleSubmit(q),className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(m,{htmlFor:"current-password",children:"Current password"}),e.jsx(h,{id:"current-password",type:"password",...t.register("currentPassword")}),t.formState.errors.currentPassword&&e.jsx("p",{className:"text-sm text-destructive",children:t.formState.errors.currentPassword.message})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(m,{htmlFor:"new-password",children:"New password"}),e.jsx(h,{id:"new-password",type:"password",...t.register("newPassword")}),t.formState.errors.newPassword&&e.jsx("p",{className:"text-sm text-destructive",children:t.formState.errors.newPassword.message})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(m,{htmlFor:"confirm-password",children:"Confirm new password"}),e.jsx(h,{id:"confirm-password",type:"password",...t.register("confirmPassword")}),t.formState.errors.confirmPassword&&e.jsx("p",{className:"text-sm text-destructive",children:t.formState.errors.confirmPassword.message})]}),t.formState.errors.root&&e.jsx("p",{className:"text-sm text-destructive",children:t.formState.errors.root.message}),e.jsx("div",{className:"flex justify-end",children:e.jsx(u,{type:"submit",size:"sm",disabled:t.formState.isSubmitting,children:t.formState.isSubmitting?"Saving…":"Change password"})})]})})]}),N&&T.length>0&&e.jsxs(g,{children:[e.jsx(j,{children:e.jsx(v,{children:"Apps"})}),e.jsx(w,{children:e.jsx("div",{className:"flex flex-col divide-y divide-border",children:T.map(s=>e.jsxs("div",{className:"flex flex-col gap-2 py-4 first:pt-0 last:pb-0",children:[e.jsx(m,{htmlFor:`app-${s.id}`,children:"App Name"}),e.jsx(h,{id:`app-${s.id}`,value:B[s.id]??"",onChange:a=>L(r=>({...r,[s.id]:a.target.value}))}),e.jsxs("div",{className:"flex flex-col gap-1.5 mt-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted-foreground font-mono",children:s.bundle_id_key}),e.jsx(re,{tone:s.platform==="ios"?"ios":s.platform==="android"?"android":void 0,variant:s.platform==="both"?"secondary":void 0,className:"capitalize",children:s.platform})]}),e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx(u,{size:"sm",variant:"outline",disabled:U[s.id],onClick:()=>K(s.id),children:U[s.id]?"Saving…":"Save"}),e.jsxs(te,{children:[e.jsx(oe,{asChild:!0,children:e.jsx(u,{size:"sm",variant:"destructive",disabled:R[s.id],children:R[s.id]?"Deleting…":"Delete"})}),e.jsxs(ne,{children:[e.jsxs(ie,{children:[e.jsx(le,{children:"Delete app?"}),e.jsxs(ce,{children:["This will permanently delete ",e.jsx("strong",{children:s.name})," and all its builds. This action cannot be undone."]})]}),e.jsxs(de,{children:[e.jsx(me,{className:"w-24",children:"Cancel"}),e.jsx(he,{className:se(ae({variant:"destructive"}),"w-24"),onClick:()=>G(s.id),children:"Delete"})]})]})]})]})]})]},s.id))})})]})]})}export{Ne as DefaultSettings};
@@ -0,0 +1 @@
1
+ import{i as n,j as e}from"./vendor-react-AJpf4YZ0.js";import{ad as I,a5 as A,ah as L,C as b,c as y,d as C,b as k,a as M,L as d,I as h,h as T,E as U,S as _,B as D,a2 as O,a3 as x,_ as Y}from"./index-bitr6DIC.js";import{b as z,c as H}from"./vendor-router-ChFy8CZ1.js";import{P as V}from"./pencil-iRR275s8.js";const W=O({displayName:x().optional(),avatar:Y(File).nullable().optional(),password:x().min(8),confirm:x()}).refine(o=>o.password===o.confirm,{message:"Passwords do not match",path:["confirm"]});function K(){const o=z(),[S]=H(),c=S.get("token")??"",[f,m]=n.useState("loading"),[P,F]=n.useState(""),[v,R]=n.useState(null),j=n.useRef(null),{register:p,handleSubmit:B,control:g,setError:u,formState:{errors:t,isSubmitting:w}}=I({resolver:A(W),mode:"onBlur",defaultValues:{displayName:"",avatar:null}}),l=L({control:g,name:"displayName"})??"";n.useEffect(()=>{if(!c){m("invalid");return}fetch(`/api/v1/invitations/verify?token=${c}`).then(a=>a.ok?a.json():Promise.reject()).then(a=>{F(a.role),m("valid")}).catch(()=>m("invalid"))},[c]);async function E(a){var r;try{const s=new FormData;if(s.append("token",c),s.append("password",a.password),(r=a.displayName)!=null&&r.trim()&&s.append("display_name",a.displayName.trim()),a.avatar&&s.append("avatar",a.avatar),!(await fetch("/api/v1/invitations/accept",{method:"POST",body:s})).ok){u("root",{message:"Failed to accept invitation"});return}o("/app-center",{replace:!0})}catch{u("root",{message:"Network error. Please try again."})}}return f==="loading"?e.jsx("div",{className:"flex min-h-svh items-center justify-center"}):f==="invalid"?e.jsx("div",{className:"bg-mesh-gradient flex min-h-svh items-center justify-center overflow-hidden p-4",children:e.jsx(b,{level:4,className:"w-full max-w-sm text-center",children:e.jsxs(y,{children:[e.jsx(C,{children:"Invitation expired"}),e.jsx(k,{children:"This invite link is invalid or has expired. Ask your admin for a new one."})]})})}):e.jsx("div",{className:"bg-mesh-gradient flex min-h-svh items-center justify-center overflow-hidden p-4",children:e.jsxs(b,{level:4,className:"w-full max-w-sm",children:[e.jsxs(y,{className:"text-center",children:[e.jsx(C,{children:"Set up your account"}),e.jsxs(k,{children:["You're joining as ",e.jsx("strong",{children:P})]})]}),e.jsx(M,{children:e.jsxs("form",{onSubmit:B(E),className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(d,{htmlFor:"display-name",children:["Nickname ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(optional)"})]}),e.jsx(h,{id:"display-name",placeholder:"Your name",...p("displayName")})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs(d,{children:["Avatar ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(optional, png · jpg, max 2MB)"})]}),e.jsx(T,{name:"avatar",control:g,render:({field:a})=>{var r;return e.jsxs("div",{className:"relative w-14 h-14",children:[v?e.jsx("img",{src:v,alt:"Avatar preview",className:"w-14 h-14 rounded-full object-cover border"}):e.jsx("div",{className:"w-14 h-14 rounded-full flex items-center justify-center text-lg font-medium",style:(()=>{const s=U(l);return{backgroundColor:s.bg,color:s.fg}})(),children:((r=l==null?void 0:l[0])==null?void 0:r.toUpperCase())??"?"}),e.jsx("button",{type:"button","aria-label":"Change avatar",onClick:()=>{var s;return(s=j.current)==null?void 0:s.click()},className:"absolute bottom-0 right-0 w-6 h-6 rounded-full bg-background border border-border shadow-sm flex items-center justify-center hover:bg-accent transition-colors",children:e.jsx(V,{className:"w-3 h-3","aria-hidden":"true"})}),e.jsx("input",{ref:j,type:"file",accept:"image/png,image/jpeg",className:"hidden",onChange:s=>{var N;const i=(N=s.target.files)==null?void 0:N[0];if(i){if(i.size>2*1024*1024){u("avatar",{message:"Max 2MB for avatar"});return}a.onChange(i),R(URL.createObjectURL(i))}}})]})}}),t.avatar&&e.jsx("p",{className:"text-sm text-destructive",children:t.avatar.message})]}),e.jsx(_,{}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(d,{htmlFor:"password",children:"Password"}),e.jsx(h,{id:"password",type:"password",...p("password")}),t.password&&e.jsx("p",{className:"text-sm text-destructive",children:t.password.message})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(d,{htmlFor:"confirm",children:"Confirm password"}),e.jsx(h,{id:"confirm",type:"password",...p("confirm")}),t.confirm&&e.jsx("p",{className:"text-sm text-destructive",children:t.confirm.message})]}),t.root&&e.jsx("p",{className:"text-sm text-destructive",children:t.root.message}),e.jsx(D,{type:"submit",disabled:w,className:"w-full",children:w?"Creating account…":"Create account"})]})})]})})}export{K as Invite};
@@ -0,0 +1 @@
1
+ import{i,j as e}from"./vendor-react-AJpf4YZ0.js";import{u as Q,T as Z,b as K,c as ee}from"./tabs-BnbeuAOe.js";import{a7 as te,M as se}from"./index-bitr6DIC.js";import{u as ne,h as oe,g as re,e as ae,c as ie,G as le,A as ce,m as V,d as de,a as ue,b as he,L as me,B as fe,l as xe,P as pe,f as ge}from"./vendor-charts-DyX5CBcf.js";import"./vendor-router-ChFy8CZ1.js";const je={cpu:{label:"CPU",color:"#60a5fa"},mem:{label:"RAM",color:"#a78bfa"}},W={"1h":"1h","6h":"6h","24h":"24h","7d":"7d"},z={"1h":36e5,"6h":216e5,"24h":864e5,"7d":6048e5},ve={"1h":6e5,"6h":36e5,"24h":108e5,"7d":864e5};function be(o,x){const n=new Date(o);return x==="7d"?`${n.getMonth()+1}/${n.getDate()}`:`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}function $e(){const[o,x]=i.useState([]),[n,l]=i.useState([]),[a,c]=i.useState(null),[u,h]=i.useState("24h"),[k,v]=i.useState([]),[b,$]=i.useState(()=>Date.now()),[C,T]=i.useState(!1),{setNode:w}=te();i.useEffect(()=>(w(e.jsx("span",{className:"text-sm font-medium",children:"Mac Resources"})),()=>w(null)),[w]);const R=i.useCallback(t=>{t.type==="agents:listed"&&x(t.sessions??[])},[]),{send:N,connected:m}=Q(R);i.useEffect(()=>{if(!m)return;N({type:"agents:list"});const t=setInterval(()=>N({type:"agents:list"}),1e4);return()=>clearInterval(t)},[m,N]),i.useEffect(()=>{fetch("/api/v1/agents",{credentials:"include"}).then(t=>t.ok?t.json():[]).then(l)},[]);const p=o.map(t=>t.agentName).filter(Boolean),d=[...new Set([...p,...n])],S=new Set(p);i.useEffect(()=>{!a&&d.length>0&&c(d[0])},[d.join(",")]),i.useEffect(()=>{a&&(T(!0),fetch(`/api/v1/agents/${encodeURIComponent(a)}/resources?range=${u}`,{credentials:"include"}).then(t=>t.ok?t.json():[]).then(t=>{v(t),$(Date.now())}).finally(()=>T(!1)))},[a,u]);const M=k.map(t=>({time:t.recorded_at,cpu:Math.round(t.cpu_percent*10)/10,mem:Math.round(t.mem_percent*10)/10}));return e.jsxs("div",{className:"flex h-full min-h-0",children:[e.jsxs("aside",{"aria-labelledby":"macs-heading",className:"w-64 shrink-0 border-r flex flex-col gap-1 p-3 overflow-y-auto",children:[e.jsx("h2",{id:"macs-heading",className:"px-2 pb-1 font-mono text-xs font-medium text-muted-foreground uppercase tracking-wider",children:"Macs"}),d.length===0?e.jsx("span",{className:"px-2 text-sm text-muted-foreground",children:m?"No agents yet.":"Connecting…"}):d.map(t=>{const y=S.has(t),g=a===t;return e.jsxs("button",{onClick:()=>c(t),className:["flex items-center gap-2 rounded-md px-2 py-2 text-left text-sm hover:bg-accent transition-colors",g?"bg-accent font-medium":""].join(" "),children:[e.jsx("span",{className:`inline-block h-1.5 w-1.5 shrink-0 rounded-full ${y?"bg-emerald-400":"bg-muted-foreground/40"}`}),e.jsx("span",{className:"truncate min-w-0",children:t})]},t)})]}),e.jsx("div",{className:"flex-1 min-w-0 overflow-auto",children:a?e.jsxs("div",{className:"flex flex-col gap-6 p-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h1",{className:"text-base font-semibold",children:a}),e.jsx(Z,{value:u,onValueChange:t=>h(t),children:e.jsx(K,{children:Object.keys(W).map(t=>e.jsx(ee,{value:t,children:W[t]},t))})})]}),C?e.jsx("div",{className:"flex h-40 items-center justify-center text-sm text-muted-foreground",children:"Loading…"}):M.length===0?e.jsx("div",{className:"flex h-40 items-center justify-center text-sm text-muted-foreground",children:"No data yet for this range. Data is collected every minute while the agent is connected."}):e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsx(X,{title:"CPU %",color:"cpu",data:M,dataKey:"cpu",range:u,now:b}),e.jsx(X,{title:"RAM %",color:"mem",data:M,dataKey:"mem",range:u,now:b})]})]}):e.jsxs("div",{className:"flex h-full items-center justify-center gap-2 text-muted-foreground",children:[e.jsx(se,{className:"h-8 w-8"}),e.jsx("p",{className:"text-sm",children:"Select a Mac to view resource history."})]})})]})}const A=o=>new Date(o.time).getTime(),H=o=>new Date(o.time).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hourCycle:"h23"}),P=o=>`${Math.round(o*10)/10}%`,ye=ge(A).left,f={top:8,right:24,bottom:24,left:40},L=16;function X({title:o,color:x,data:n,dataKey:l,range:a,now:c}){const u=je[x].color;return e.jsxs("div",{className:"rounded-lg border p-4 flex flex-col gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"inline-block h-2.5 w-2.5 rounded-full",style:{background:u}}),e.jsx("h2",{className:"text-sm font-medium",children:o})]}),e.jsx("div",{className:"relative h-[220px] w-full",children:e.jsx(pe,{children:({width:h,height:k})=>h>0&&k>0?e.jsx(ke,{width:h,height:k,data:n,dataKey:l,hex:u,range:a,now:c,label:o}):null})})]})}function ke({width:o,height:x,data:n,dataKey:l,hex:a,range:c,now:u,label:h}){const{showTooltip:k,hideTooltip:v,tooltipData:b,tooltipLeft:$,tooltipTop:C}=ne(),T=`chart-hint-${l}`,[w,R]=i.useState(null),N=Math.max(0,n.length-1),m=w===null?N:Math.min(w,N),p=o-f.left-f.right,d=x-f.top-f.bottom,S=ve[c],M=Math.ceil(u/S)*S,t=M-z[c],y=oe({domain:[t,M],range:[L,Math.max(L,p-L)]}),g=re({domain:[0,100],range:[d,L]}),Y=Array.from({length:z[c]/S+1},(s,r)=>new Date(t+r*S)),O=`fill-${l}`,_=`plot-${l}`,I=s=>{const r=n[s];r&&(R(s),k({tooltipData:r,tooltipLeft:y(A(r)),tooltipTop:g(r[l])}))},q=s=>{if(n.length===0)return;if(s.key==="Escape"){v();return}const r=m,j=s.key==="ArrowLeft"||s.key==="ArrowDown"?Math.max(0,r-1):s.key==="ArrowRight"||s.key==="ArrowUp"?Math.min(n.length-1,r+1):s.key==="Home"?0:s.key==="End"?n.length-1:null;j!==null&&(s.preventDefault(),I(j))},B=s=>{const r=xe(s);if(!r)return;const j=y.invert(r.x-f.left).getTime(),F=ye(n,j),D=n[F-1],E=n[F],U=D&&E?j-A(D)<A(E)-j?D:E:D??E;U&&I(n.indexOf(U))},G=n[n.length-1],J=s=>`${h}, ${H(s)}, ${P(s[l])}`;return e.jsxs(e.Fragment,{children:[e.jsxs("svg",{width:o,height:x,role:"group","aria-label":G?`${h}, last ${c}. Latest ${P(G[l])}.`:`${h}, last ${c}. No samples.`,children:[e.jsx(ae,{id:O,from:a,to:a,fromOpacity:.3,toOpacity:0,fromOffset:"5%",toOffset:"95%"}),e.jsx("clipPath",{id:_,children:e.jsx("rect",{x:0,y:0,width:Math.max(0,p),height:Math.max(0,d)})}),e.jsxs(ie,{left:f.left,top:f.top,children:[e.jsx(le,{scale:g,width:p,tickValues:[0,25,50,75,100],strokeDasharray:"3 3",stroke:"hsl(var(--border))"}),e.jsxs("g",{clipPath:`url(#${_})`,children:[e.jsx(ce,{data:n,x:s=>y(A(s)),y:s=>g(s[l]),yScale:g,curve:V,fill:`url(#${O})`}),e.jsx(de,{data:n,x:s=>y(A(s)),y:s=>g(s[l]),curve:V,stroke:a,strokeWidth:1.5})]}),e.jsx(ue,{top:d,scale:y,tickValues:Y,tickFormat:s=>be(new Date(+s).toISOString(),c),hideAxisLine:!0,hideTicks:!0,tickLength:0,tickLabelProps:(s,r,j)=>({fontSize:11,fill:"currentColor",textAnchor:r===0?"start":r===j.length-1?"end":"middle",dy:6,className:"fill-muted-foreground"})}),e.jsx(he,{scale:g,tickValues:[0,25,50,75,100],tickFormat:s=>`${s}%`,hideAxisLine:!0,hideTicks:!0,tickLabelProps:()=>({fontSize:11,fill:"currentColor",textAnchor:"end",dx:-4,dy:3,className:"fill-muted-foreground"})}),b&&e.jsxs("g",{style:{transition:"transform 0.25s ease-out",transform:`translateX(${$??0}px)`},pointerEvents:"none",children:[e.jsx(me,{from:{x:0,y:L},to:{x:0,y:d},stroke:"hsl(var(--border))",strokeWidth:1}),e.jsx("circle",{cx:0,cy:0,r:3,fill:a,stroke:"hsl(var(--background))",strokeWidth:1.5,style:{transition:"transform 0.25s ease-out",transform:`translateY(${C??0}px)`}})]}),e.jsx(fe,{x:0,y:0,width:Math.max(0,p),height:Math.max(0,d),fill:"transparent",tabIndex:0,role:"slider","aria-label":`${h} samples`,"aria-valuemin":0,"aria-valuemax":Math.max(0,n.length-1),"aria-valuenow":m,"aria-valuetext":n[m]?J(n[m]):void 0,"aria-describedby":T,className:"outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",onFocus:()=>I(m),onBlur:v,onKeyDown:q,onMouseMove:B,onMouseLeave:v,onTouchMove:B,onTouchEnd:v,onTouchCancel:v})]})]}),e.jsx("p",{id:T,className:"sr-only",children:"Use the arrow keys to read individual samples. Escape hides the reading."}),b&&e.jsxs("div",{"aria-hidden":"true",className:"pointer-events-none absolute top-0 left-0 whitespace-nowrap rounded-lg border bg-background px-3 py-2 text-xs text-foreground shadow-md",style:{transform:`translate(${($??0)+f.left}px, ${(C??0)+f.top}px) translate(${($??0)>p*.6?"calc(-100% - 12px)":"12px"}, -50%)`,transition:"transform 0.25s ease-out"},children:[e.jsxs("p",{className:"mb-1",children:["Date:"," ",H(b)]}),e.jsxs("p",{children:[h,": ",P(b[l])]})]})]})}export{ke as AreaChartInner,$e as MacResources};
@@ -0,0 +1 @@
1
+ import{j as e}from"./vendor-react-AJpf4YZ0.js";function r({code:s,message:t}){return e.jsx("div",{className:"flex min-h-svh items-center justify-center bg-background p-4",children:e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-lg font-semibold tracking-tight text-foreground",children:s}),e.jsx("span",{className:"h-6 w-px bg-border","aria-hidden":"true"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:t})]})})}function a(){return e.jsx(r,{code:404,message:"page not found"})}export{a as NotFound};