@opendatalabs/personal-server-ts-server 0.2.0 → 1.1.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 (177) hide show
  1. package/dist/api-auth.d.ts +16 -0
  2. package/dist/api-auth.d.ts.map +1 -0
  3. package/dist/api-auth.js +97 -0
  4. package/dist/api-auth.js.map +1 -0
  5. package/dist/api.d.ts +4 -0
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +3 -0
  8. package/dist/api.js.map +1 -1
  9. package/dist/app.d.ts +46 -1
  10. package/dist/app.d.ts.map +1 -1
  11. package/dist/app.js +102 -30
  12. package/dist/app.js.map +1 -1
  13. package/dist/bootstrap.d.ts +11 -3
  14. package/dist/bootstrap.d.ts.map +1 -1
  15. package/dist/bootstrap.js +266 -33
  16. package/dist/bootstrap.js.map +1 -1
  17. package/dist/client.d.ts +17 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +368 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/config/defaults.d.ts +12 -0
  22. package/dist/config/defaults.d.ts.map +1 -0
  23. package/dist/config/defaults.js +14 -0
  24. package/dist/config/defaults.js.map +1 -0
  25. package/dist/config/index.d.ts +4 -0
  26. package/dist/config/index.d.ts.map +1 -0
  27. package/dist/config/index.js +4 -0
  28. package/dist/config/index.js.map +1 -0
  29. package/dist/config/loader.d.ts +8 -0
  30. package/dist/config/loader.d.ts.map +1 -0
  31. package/dist/config/loader.js +74 -0
  32. package/dist/config/loader.js.map +1 -0
  33. package/dist/config/paths.d.ts +9 -0
  34. package/dist/config/paths.d.ts.map +1 -0
  35. package/dist/config/paths.js +22 -0
  36. package/dist/config/paths.js.map +1 -0
  37. package/dist/hono-context.d.ts +14 -0
  38. package/dist/hono-context.d.ts.map +1 -0
  39. package/dist/hono-context.js +2 -0
  40. package/dist/hono-context.js.map +1 -0
  41. package/dist/index.js +64 -12
  42. package/dist/index.js.map +1 -1
  43. package/dist/keys/server-account.d.ts +28 -0
  44. package/dist/keys/server-account.d.ts.map +1 -0
  45. package/dist/keys/server-account.js +48 -0
  46. package/dist/keys/server-account.js.map +1 -0
  47. package/dist/logger/index.d.ts +5 -0
  48. package/dist/logger/index.d.ts.map +1 -0
  49. package/dist/logger/index.js +9 -0
  50. package/dist/logger/index.js.map +1 -0
  51. package/dist/logging/access-log.d.ts +15 -0
  52. package/dist/logging/access-log.d.ts.map +1 -0
  53. package/dist/logging/access-log.js +25 -0
  54. package/dist/logging/access-log.js.map +1 -0
  55. package/dist/logging/access-reader.d.ts +19 -0
  56. package/dist/logging/access-reader.d.ts.map +1 -0
  57. package/dist/logging/access-reader.js +50 -0
  58. package/dist/logging/access-reader.js.map +1 -0
  59. package/dist/middleware/access-log.d.ts.map +1 -1
  60. package/dist/middleware/access-log.js +8 -2
  61. package/dist/middleware/access-log.js.map +1 -1
  62. package/dist/middleware/builder-check.d.ts +2 -2
  63. package/dist/middleware/builder-check.d.ts.map +1 -1
  64. package/dist/middleware/builder-check.js +7 -2
  65. package/dist/middleware/builder-check.js.map +1 -1
  66. package/dist/middleware/owner-check.js +1 -1
  67. package/dist/middleware/owner-check.js.map +1 -1
  68. package/dist/middleware/web3-auth.d.ts +12 -0
  69. package/dist/middleware/web3-auth.d.ts.map +1 -1
  70. package/dist/middleware/web3-auth.js +27 -31
  71. package/dist/middleware/web3-auth.js.map +1 -1
  72. package/dist/migrations/local-state.d.ts +21 -0
  73. package/dist/migrations/local-state.d.ts.map +1 -0
  74. package/dist/migrations/local-state.js +106 -0
  75. package/dist/migrations/local-state.js.map +1 -0
  76. package/dist/routes/access-logs.d.ts +7 -0
  77. package/dist/routes/access-logs.d.ts.map +1 -1
  78. package/dist/routes/access-logs.js +11 -17
  79. package/dist/routes/access-logs.js.map +1 -1
  80. package/dist/routes/auth-device.d.ts +49 -0
  81. package/dist/routes/auth-device.d.ts.map +1 -0
  82. package/dist/routes/auth-device.js +581 -0
  83. package/dist/routes/auth-device.js.map +1 -0
  84. package/dist/routes/data.d.ts +42 -1
  85. package/dist/routes/data.d.ts.map +1 -1
  86. package/dist/routes/data.js +36 -201
  87. package/dist/routes/data.js.map +1 -1
  88. package/dist/routes/grants.d.ts +9 -2
  89. package/dist/routes/grants.d.ts.map +1 -1
  90. package/dist/routes/grants.js +18 -196
  91. package/dist/routes/grants.js.map +1 -1
  92. package/dist/routes/health.d.ts +7 -1
  93. package/dist/routes/health.d.ts.map +1 -1
  94. package/dist/routes/health.js +39 -2
  95. package/dist/routes/health.js.map +1 -1
  96. package/dist/routes/mcp.d.ts +93 -6
  97. package/dist/routes/mcp.d.ts.map +1 -1
  98. package/dist/routes/mcp.js +526 -53
  99. package/dist/routes/mcp.js.map +1 -1
  100. package/dist/routes/oauth-token.d.ts +56 -0
  101. package/dist/routes/oauth-token.d.ts.map +1 -0
  102. package/dist/routes/oauth-token.js +49 -0
  103. package/dist/routes/oauth-token.js.map +1 -0
  104. package/dist/routes/sync.d.ts +7 -0
  105. package/dist/routes/sync.d.ts.map +1 -1
  106. package/dist/routes/sync.js +12 -39
  107. package/dist/routes/sync.js.map +1 -1
  108. package/dist/routes/ui-config.d.ts.map +1 -1
  109. package/dist/routes/ui-config.js +17 -82
  110. package/dist/routes/ui-config.js.map +1 -1
  111. package/dist/routes/ui-registration.d.ts +9 -0
  112. package/dist/routes/ui-registration.d.ts.map +1 -0
  113. package/dist/routes/ui-registration.js +217 -0
  114. package/dist/routes/ui-registration.js.map +1 -0
  115. package/dist/routes/ui.d.ts +1 -0
  116. package/dist/routes/ui.d.ts.map +1 -1
  117. package/dist/routes/ui.js +46 -4
  118. package/dist/routes/ui.js.map +1 -1
  119. package/dist/storage/hierarchy.d.ts +29 -0
  120. package/dist/storage/hierarchy.d.ts.map +1 -0
  121. package/dist/storage/hierarchy.js +241 -0
  122. package/dist/storage/hierarchy.js.map +1 -0
  123. package/dist/storage/index-manager.d.ts +53 -0
  124. package/dist/storage/index-manager.d.ts.map +1 -0
  125. package/dist/storage/index-manager.js +167 -0
  126. package/dist/storage/index-manager.js.map +1 -0
  127. package/dist/storage/index-schema.d.ts +5 -0
  128. package/dist/storage/index-schema.d.ts.map +1 -0
  129. package/dist/storage/index-schema.js +62 -0
  130. package/dist/storage/index-schema.js.map +1 -0
  131. package/dist/storage/node-data-storage.d.ts +9 -0
  132. package/dist/storage/node-data-storage.d.ts.map +1 -0
  133. package/dist/storage/node-data-storage.js +84 -0
  134. package/dist/storage/node-data-storage.js.map +1 -0
  135. package/dist/sync-cursor.d.ts +15 -0
  136. package/dist/sync-cursor.d.ts.map +1 -0
  137. package/dist/sync-cursor.js +110 -0
  138. package/dist/sync-cursor.js.map +1 -0
  139. package/dist/token-store.d.ts +22 -0
  140. package/dist/token-store.d.ts.map +1 -0
  141. package/dist/token-store.js +120 -0
  142. package/dist/token-store.js.map +1 -0
  143. package/dist/tunnel/auth.d.ts +4 -0
  144. package/dist/tunnel/auth.d.ts.map +1 -1
  145. package/dist/tunnel/auth.js +2 -1
  146. package/dist/tunnel/auth.js.map +1 -1
  147. package/dist/tunnel/config.d.ts +1 -0
  148. package/dist/tunnel/config.d.ts.map +1 -1
  149. package/dist/tunnel/config.js +1 -1
  150. package/dist/tunnel/config.js.map +1 -1
  151. package/dist/tunnel/manager.d.ts +21 -1
  152. package/dist/tunnel/manager.d.ts.map +1 -1
  153. package/dist/tunnel/manager.js +78 -23
  154. package/dist/tunnel/manager.js.map +1 -1
  155. package/dist/tunnel/verify.d.ts +1 -1
  156. package/dist/tunnel/verify.d.ts.map +1 -1
  157. package/dist/tunnel/verify.js +8 -2
  158. package/dist/tunnel/verify.js.map +1 -1
  159. package/dist/ui/browser_tls_rustls_bg.wasm +0 -0
  160. package/dist/ui/index.html +2192 -0
  161. package/dist/ui/ps-lite-debug.d.ts +93 -0
  162. package/dist/ui/ps-lite-debug.d.ts.map +1 -0
  163. package/dist/ui/ps-lite-debug.js +129416 -0
  164. package/dist/ui/ps-lite-debug.js.map +1 -0
  165. package/package.json +20 -8
  166. package/dist/middleware/grant-check.d.ts +0 -12
  167. package/dist/middleware/grant-check.d.ts.map +0 -1
  168. package/dist/middleware/grant-check.js +0 -90
  169. package/dist/middleware/grant-check.js.map +0 -1
  170. package/dist/oauth/provider.d.ts +0 -55
  171. package/dist/oauth/provider.d.ts.map +0 -1
  172. package/dist/oauth/provider.js +0 -160
  173. package/dist/oauth/provider.js.map +0 -1
  174. package/dist/oauth/routes.d.ts +0 -10
  175. package/dist/oauth/routes.d.ts.map +0 -1
  176. package/dist/oauth/routes.js +0 -206
  177. package/dist/oauth/routes.js.map +0 -1
@@ -0,0 +1,56 @@
1
+ /**
2
+ * RFC 6749 §5 token endpoint.
3
+ *
4
+ * Supports two grant types:
5
+ *
6
+ * 1. `client_credentials` (RFC 6749 §4.4) — used by the cloud control
7
+ * plane (e.g. account.vana.org) to mint server-issued bearer tokens.
8
+ * Caller authenticates with `client_id="control-plane"` and
9
+ * `client_secret=<PS_ACCESS_TOKEN>` (HTTP Basic per §2.3.1, or in the
10
+ * request body per §2.3.1's "alternative method").
11
+ *
12
+ * 2. `urn:ietf:params:oauth:grant-type:device_code` (RFC 8628 §3.4) —
13
+ * used by the CLI to redeem an approved device-authorization session
14
+ * for a bearer token. Wraps the existing `/auth/device/poll` flow in
15
+ * a standard envelope.
16
+ *
17
+ * All issued tokens are opaque, persisted to the same {@link TokenStore}
18
+ * that backs the existing CLI session tokens, and accepted by every owner
19
+ * route's web3-auth middleware via the `tokenStore` injection. Standard
20
+ * OAuth2 error responses per RFC 6749 §5.2.
21
+ *
22
+ * Why hand-rolled instead of `@node-oauth/oauth2-server`: the wire
23
+ * protocol for these two grants is small enough (RFC 6749 §4.4 + §5 is
24
+ * one page) that the abstraction tax of a full OAuth server framework
25
+ * exceeds the spec implementation cost. We reuse the framework where it
26
+ * matters (clients, see oauth4webapi on the account.vana.org side).
27
+ */
28
+ import { Hono } from "hono";
29
+ import type { Logger } from "pino";
30
+ import type { OAuthDeviceSessionLookup } from "@opendatalabs/personal-server-ts-core/contracts";
31
+ import type { TokenStore } from "../token-store.js";
32
+ /**
33
+ * In-memory map of device-flow sessions keyed by device_code. The existing
34
+ * `/auth/device/poll` endpoint maintains the canonical state in
35
+ * `auth-device.ts`; this endpoint reuses that same module-level `sessions`
36
+ * map by accepting a `findDeviceSessionByDeviceCode` dep.
37
+ */
38
+ export interface DeviceSessionLookup extends OAuthDeviceSessionLookup {
39
+ findByDeviceCode(deviceCode: string): {
40
+ status: "pending" | "approved" | "expired";
41
+ accessToken?: string;
42
+ accessTokenExpiresAt?: string;
43
+ sessionId: string;
44
+ } | null;
45
+ consume(sessionId: string): void;
46
+ }
47
+ export interface OauthTokenRouteDeps {
48
+ logger: Logger;
49
+ tokenStore: TokenStore;
50
+ /** PS_ACCESS_TOKEN — the long-lived control-plane secret. */
51
+ controlPlaneSecret?: string;
52
+ /** Optional device-flow session lookup. When omitted, only client_credentials is supported. */
53
+ deviceSessions?: DeviceSessionLookup;
54
+ }
55
+ export declare function oauthTokenRoutes(deps: OauthTokenRouteDeps): Hono;
56
+ //# sourceMappingURL=oauth-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-token.d.ts","sourceRoot":"","sources":["../../src/routes/oauth-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iDAAiD,CAAC;AAEhG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,mBAAoB,SAAQ,wBAAwB;IACnE,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG;QACpC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;QAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;IACT,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+FAA+F;IAC/F,cAAc,CAAC,EAAE,mBAAmB,CAAC;CACtC;AASD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAchE"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * RFC 6749 §5 token endpoint.
3
+ *
4
+ * Supports two grant types:
5
+ *
6
+ * 1. `client_credentials` (RFC 6749 §4.4) — used by the cloud control
7
+ * plane (e.g. account.vana.org) to mint server-issued bearer tokens.
8
+ * Caller authenticates with `client_id="control-plane"` and
9
+ * `client_secret=<PS_ACCESS_TOKEN>` (HTTP Basic per §2.3.1, or in the
10
+ * request body per §2.3.1's "alternative method").
11
+ *
12
+ * 2. `urn:ietf:params:oauth:grant-type:device_code` (RFC 8628 §3.4) —
13
+ * used by the CLI to redeem an approved device-authorization session
14
+ * for a bearer token. Wraps the existing `/auth/device/poll` flow in
15
+ * a standard envelope.
16
+ *
17
+ * All issued tokens are opaque, persisted to the same {@link TokenStore}
18
+ * that backs the existing CLI session tokens, and accepted by every owner
19
+ * route's web3-auth middleware via the `tokenStore` injection. Standard
20
+ * OAuth2 error responses per RFC 6749 §5.2.
21
+ *
22
+ * Why hand-rolled instead of `@node-oauth/oauth2-server`: the wire
23
+ * protocol for these two grants is small enough (RFC 6749 §4.4 + §5 is
24
+ * one page) that the abstraction tax of a full OAuth server framework
25
+ * exceeds the spec implementation cost. We reuse the framework where it
26
+ * matters (clients, see oauth4webapi on the account.vana.org side).
27
+ */
28
+ import { randomBytes, timingSafeEqual } from "node:crypto";
29
+ import { Hono } from "hono";
30
+ import { handlePersonalServerOauthTokenRequest } from "@opendatalabs/personal-server-ts-core/api";
31
+ function safeCompare(a, b) {
32
+ const bufA = Buffer.from(a, "utf-8");
33
+ const bufB = Buffer.from(b, "utf-8");
34
+ if (bufA.length !== bufB.length)
35
+ return false;
36
+ return timingSafeEqual(bufA, bufB);
37
+ }
38
+ export function oauthTokenRoutes(deps) {
39
+ const app = new Hono();
40
+ app.all("/", (c) => handlePersonalServerOauthTokenRequest(c.req.raw, {
41
+ tokenStore: deps.tokenStore,
42
+ controlPlaneSecret: deps.controlPlaneSecret,
43
+ deviceSessions: deps.deviceSessions,
44
+ randomToken: () => `vana_ps_${randomBytes(32).toString("hex")}`,
45
+ safeCompare,
46
+ }));
47
+ return app;
48
+ }
49
+ //# sourceMappingURL=oauth-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-token.js","sourceRoot":"","sources":["../../src/routes/oauth-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,qCAAqC,EAAE,MAAM,2CAA2C,CAAC;AA4BlG,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC9C,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,qCAAqC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE;QAC/C,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;QAC3C,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;QAC/D,WAAW;KACZ,CAAC,CACH,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -5,12 +5,19 @@
5
5
  import { Hono } from "hono";
6
6
  import type { Logger } from "pino";
7
7
  import type { SyncManager } from "@opendatalabs/personal-server-ts-core/sync";
8
+ import { type PersonalServerApiDispatchOptions } from "@opendatalabs/personal-server-ts-core/api";
9
+ import type { TokenStore } from "../token-store.js";
10
+ import type { GatewayClient } from "@opendatalabs/vana-sdk/node";
8
11
  export interface SyncRouteDeps {
9
12
  logger: Logger;
10
13
  serverOrigin: string | (() => string);
11
14
  serverOwner?: `0x${string}`;
15
+ gateway: GatewayClient;
12
16
  devToken?: string;
17
+ accessToken?: string;
18
+ tokenStore?: TokenStore;
13
19
  syncManager: SyncManager | null;
20
+ mountPath?: PersonalServerApiDispatchOptions["basePath"];
14
21
  }
15
22
  export declare function syncRoutes(deps: SyncRouteDeps): Hono;
16
23
  //# sourceMappingURL=sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAI9E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAsDpD"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAC9E,OAAO,EAEL,KAAK,gCAAgC,EACtC,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACtC,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,gCAAgC,CAAC,UAAU,CAAC,CAAC;CAC1D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAyBpD"}
@@ -3,50 +3,23 @@
3
3
  * All endpoints require owner authentication.
4
4
  */
5
5
  import { Hono } from "hono";
6
- import { createWeb3AuthMiddleware } from "../middleware/web3-auth.js";
7
- import { createOwnerCheckMiddleware } from "../middleware/owner-check.js";
6
+ import { handlePersonalServerSyncRequest, } from "@opendatalabs/personal-server-ts-core/api";
7
+ import { createServerApiAuth } from "../api-auth.js";
8
8
  export function syncRoutes(deps) {
9
9
  const app = new Hono();
10
- const web3Auth = createWeb3AuthMiddleware({
10
+ const auth = createServerApiAuth({
11
11
  serverOrigin: deps.serverOrigin,
12
- devToken: deps.devToken,
13
12
  serverOwner: deps.serverOwner,
13
+ gateway: deps.gateway,
14
+ devToken: deps.devToken,
15
+ accessToken: deps.accessToken,
16
+ tokenStore: deps.tokenStore,
14
17
  });
15
- const ownerCheck = createOwnerCheckMiddleware(deps.serverOwner);
16
- // POST /trigger — request a full sync (owner auth required)
17
- app.post("/trigger", web3Auth, ownerCheck, async (c) => {
18
- if (!deps.syncManager) {
19
- return c.json({ status: "disabled", message: "Sync is not enabled" }, 200);
20
- }
21
- await deps.syncManager.trigger();
22
- return c.json({ status: "started", message: "Sync triggered" }, 202);
23
- });
24
- // GET /status — current sync status (owner auth required)
25
- app.get("/status", web3Auth, ownerCheck, async (c) => {
26
- if (!deps.syncManager) {
27
- return c.json({
28
- enabled: false,
29
- running: false,
30
- lastSync: null,
31
- lastProcessedTimestamp: null,
32
- pendingFiles: 0,
33
- errors: [],
34
- });
35
- }
36
- return c.json(deps.syncManager.getStatus());
37
- });
38
- // POST /file/:fileId — request sync for a specific file (owner auth required)
39
- app.post("/file/:fileId", web3Auth, ownerCheck, async (c) => {
40
- const fileId = c.req.param("fileId");
41
- if (!deps.syncManager) {
42
- return c.json({ fileId, status: "disabled", message: "Sync is not enabled" }, 200);
43
- }
44
- // Trigger a full sync (individual file sync is handled by the download worker
45
- // when it encounters the fileId from Gateway)
46
- deps.logger.info({ fileId }, "File sync requested, triggering full sync");
47
- await deps.syncManager.trigger();
48
- return c.json({ fileId, status: "started" }, 202);
49
- });
18
+ app.all("*", (c) => handlePersonalServerSyncRequest(c.req.raw, {
19
+ auth,
20
+ syncManager: deps.syncManager,
21
+ logger: deps.logger,
22
+ }, { basePath: deps.mountPath }));
50
23
  return app;
51
24
  }
52
25
  //# sourceMappingURL=sync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAU1E,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,QAAQ,GAAG,wBAAwB,CAAC;QACxC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,0BAA0B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAEhE,4DAA4D;IAC5D,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACrD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,EAAE,EACtD,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,GAAG,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACnD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,IAAI,CAAC;gBACZ,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,IAAI;gBACd,sBAAsB,EAAE,IAAI;gBAC5B,YAAY,EAAE,CAAC;gBACf,MAAM,EAAE,EAAE;aACX,CAAC,CAAC;QACL,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAC9D,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,8EAA8E;QAC9E,8CAA8C;QAC9C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,2CAA2C,CAAC,CAAC;QAC1E,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EACL,+BAA+B,GAEhC,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAerD,MAAM,UAAU,UAAU,CAAC,IAAmB;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,IAAI,GAAG,mBAAmB,CAAC;QAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,+BAA+B,CAC7B,CAAC,CAAC,GAAG,CAAC,GAAG,EACT;QACE,IAAI;QACJ,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAC7B,CACF,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ui-config.d.ts","sourceRoot":"","sources":["../../src/routes/ui-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA8G5D"}
1
+ {"version":3,"file":"ui-config.d.ts","sourceRoot":"","sources":["../../src/routes/ui-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA2B5D"}
@@ -1,89 +1,24 @@
1
1
  import { readFile, writeFile } from "node:fs/promises";
2
2
  import { Hono } from "hono";
3
- import { ServerConfigSchema } from "@opendatalabs/personal-server-ts-core/schemas";
3
+ import { MissingAuthError } from "@opendatalabs/personal-server-ts-core/errors";
4
+ import { handlePersonalServerConfigRequest } from "@opendatalabs/personal-server-ts-core/api";
4
5
  export function uiConfigRoutes(deps) {
5
6
  const app = new Hono();
6
- const requireDevToken = async (c, next) => {
7
- const authHeader = c.req.header("authorization");
8
- if (authHeader !== `Bearer ${deps.devToken}`) {
9
- return c.json({
10
- error: {
11
- code: 401,
12
- errorCode: "UNAUTHORIZED",
13
- message: "Invalid dev token",
14
- },
15
- }, 401);
16
- }
17
- await next();
18
- };
19
- // GET /ui/api/config — read config from disk
20
- app.get("/config", requireDevToken, async (c) => {
21
- try {
22
- const contents = await readFile(deps.configPath, "utf-8");
23
- const config = JSON.parse(contents);
24
- return c.json(config);
25
- }
26
- catch (err) {
27
- if (err instanceof Error &&
28
- "code" in err &&
29
- err.code === "ENOENT") {
30
- return c.json({
31
- error: {
32
- code: 404,
33
- errorCode: "NOT_FOUND",
34
- message: "Config file not found",
35
- },
36
- }, 404);
37
- }
38
- return c.json({
39
- error: {
40
- code: 500,
41
- errorCode: "READ_ERROR",
42
- message: "Failed to read config",
43
- },
44
- }, 500);
45
- }
46
- });
47
- // PUT /ui/api/config — validate and write config to disk
48
- app.put("/config", requireDevToken, async (c) => {
49
- let body;
50
- try {
51
- body = await c.req.json();
52
- }
53
- catch {
54
- return c.json({
55
- error: {
56
- code: 400,
57
- errorCode: "INVALID_BODY",
58
- message: "Invalid JSON body",
59
- },
60
- }, 400);
61
- }
62
- const result = ServerConfigSchema.safeParse(body);
63
- if (!result.success) {
64
- return c.json({
65
- error: {
66
- code: 400,
67
- errorCode: "VALIDATION_ERROR",
68
- message: "Invalid config",
69
- issues: result.error.issues,
70
- },
71
- }, 400);
72
- }
73
- try {
74
- await writeFile(deps.configPath, JSON.stringify(result.data, null, 2) + "\n");
75
- return c.json({ status: "saved", config: result.data });
76
- }
77
- catch {
78
- return c.json({
79
- error: {
80
- code: 500,
81
- errorCode: "WRITE_ERROR",
82
- message: "Failed to write config",
83
- },
84
- }, 500);
85
- }
86
- });
7
+ app.all("/config", (c) => handlePersonalServerConfigRequest(c.req.raw, {
8
+ auth: {
9
+ async authorizeOwner(request) {
10
+ if (request.headers.get("authorization") !== `Bearer ${deps.devToken}`) {
11
+ throw new MissingAuthError();
12
+ }
13
+ },
14
+ },
15
+ async readConfig() {
16
+ return JSON.parse(await readFile(deps.configPath, "utf-8"));
17
+ },
18
+ async writeConfig(config) {
19
+ await writeFile(deps.configPath, `${JSON.stringify(config, null, 2)}\n`);
20
+ },
21
+ }));
87
22
  return app;
88
23
  }
89
24
  //# sourceMappingURL=ui-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-config.js","sourceRoot":"","sources":["../../src/routes/ui-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui-config.js","sourceRoot":"","sources":["../../src/routes/ui-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAChF,OAAO,EAAE,iCAAiC,EAAE,MAAM,2CAA2C,CAAC;AAO9F,MAAM,UAAU,cAAc,CAAC,IAAuB;IACpD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CACvB,iCAAiC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE;QAC3C,IAAI,EAAE;YACJ,KAAK,CAAC,cAAc,CAAC,OAAO;gBAC1B,IACE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,UAAU,IAAI,CAAC,QAAQ,EAAE,EAClE,CAAC;oBACD,MAAM,IAAI,gBAAgB,EAAE,CAAC;gBAC/B,CAAC;YACH,CAAC;SACF;QACD,KAAK,CAAC,UAAU;YACd,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAY,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAM;YACtB,MAAM,SAAS,CACb,IAAI,CAAC,UAAU,EACf,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACvC,CAAC;QACJ,CAAC;KACF,CAAC,CACH,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Hono } from "hono";
2
+ export interface UiRegistrationRouteDeps {
3
+ devToken: string;
4
+ ownerPrivateKey?: `0x${string}`;
5
+ /** Called when registration is confirmed (fresh or already registered). */
6
+ onRegistered?: (serverId: string | null) => void;
7
+ }
8
+ export declare function uiRegistrationRoutes(deps: UiRegistrationRouteDeps): Hono;
9
+ //# sourceMappingURL=ui-registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-registration.d.ts","sourceRoot":"","sources":["../../src/routes/ui-registration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAiB5B,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAChC,2EAA2E;IAC3E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAClD;AAqED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,CA0MxE"}
@@ -0,0 +1,217 @@
1
+ import { Hono } from "hono";
2
+ import { createGatewayClient, serverRegistrationDomain, SERVER_REGISTRATION_TYPES, } from "@opendatalabs/vana-sdk/node";
3
+ import { privateKeyToAccount } from "viem/accounts";
4
+ function isHexAddress(value) {
5
+ return typeof value === "string" && /^0x[0-9a-fA-F]{40}$/.test(value);
6
+ }
7
+ function normalizePrivateKey(value) {
8
+ const normalized = value.startsWith("0x") ? value : `0x${value}`;
9
+ return /^0x[0-9a-fA-F]{64}$/.test(normalized)
10
+ ? normalized
11
+ : null;
12
+ }
13
+ function parseGatewayConfig(value) {
14
+ if (!value || typeof value !== "object")
15
+ return null;
16
+ const record = value;
17
+ const contracts = record.contracts;
18
+ if (typeof record.url !== "string" ||
19
+ typeof record.chainId !== "number" ||
20
+ !contracts ||
21
+ typeof contracts.dataPortabilityServer !== "string") {
22
+ return null;
23
+ }
24
+ return value;
25
+ }
26
+ function parseCandidate(value) {
27
+ if (!value || typeof value !== "object")
28
+ return null;
29
+ const record = value;
30
+ if (!isHexAddress(record.ownerAddress) ||
31
+ !isHexAddress(record.serverAddress) ||
32
+ typeof record.publicKey !== "string" ||
33
+ !record.publicKey.startsWith("0x") ||
34
+ typeof record.serverUrl !== "string") {
35
+ return null;
36
+ }
37
+ return {
38
+ ownerAddress: record.ownerAddress,
39
+ serverAddress: record.serverAddress,
40
+ publicKey: record.publicKey,
41
+ serverUrl: record.serverUrl,
42
+ };
43
+ }
44
+ function isLocalUrl(serverUrl) {
45
+ try {
46
+ const url = new URL(serverUrl);
47
+ const hostname = url.hostname.toLowerCase();
48
+ return (hostname === "localhost" ||
49
+ hostname === "127.0.0.1" ||
50
+ hostname === "0.0.0.0" ||
51
+ hostname === "[::1]" ||
52
+ hostname === "ps-lite.local" ||
53
+ hostname.startsWith("10.") ||
54
+ hostname.startsWith("192.168.") ||
55
+ /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname));
56
+ }
57
+ catch {
58
+ return true;
59
+ }
60
+ }
61
+ export function uiRegistrationRoutes(deps) {
62
+ const app = new Hono();
63
+ const requireDevToken = async (c, next) => {
64
+ const authHeader = c.req.header("authorization");
65
+ if (authHeader !== `Bearer ${deps.devToken}`) {
66
+ return c.json({
67
+ error: {
68
+ code: 401,
69
+ errorCode: "UNAUTHORIZED",
70
+ message: "Invalid dev token",
71
+ },
72
+ }, 401);
73
+ }
74
+ await next();
75
+ };
76
+ app.get("/registration", requireDevToken, (c) => {
77
+ return c.json({
78
+ ownerPrivateKeyConfigured: Boolean(deps.ownerPrivateKey),
79
+ });
80
+ });
81
+ app.post("/registration/server", requireDevToken, async (c) => {
82
+ if (!deps.ownerPrivateKey) {
83
+ return c.json({
84
+ error: {
85
+ code: 503,
86
+ errorCode: "OWNER_PRIVATE_KEY_NOT_CONFIGURED",
87
+ message: "Set VANA_OWNER_PRIVATE_KEY to register servers.",
88
+ },
89
+ }, 503);
90
+ }
91
+ const ownerPrivateKey = normalizePrivateKey(deps.ownerPrivateKey);
92
+ if (!ownerPrivateKey) {
93
+ return c.json({
94
+ error: {
95
+ code: 500,
96
+ errorCode: "INVALID_OWNER_PRIVATE_KEY",
97
+ message: "VANA_OWNER_PRIVATE_KEY must be a 32-byte hex private key.",
98
+ },
99
+ }, 500);
100
+ }
101
+ let body;
102
+ try {
103
+ body = await c.req.json();
104
+ }
105
+ catch {
106
+ return c.json({
107
+ error: {
108
+ code: 400,
109
+ errorCode: "INVALID_BODY",
110
+ message: "Invalid JSON body",
111
+ },
112
+ }, 400);
113
+ }
114
+ const record = body;
115
+ const gatewayConfig = parseGatewayConfig(record.gatewayConfig);
116
+ const candidate = parseCandidate(record.registration);
117
+ if (!gatewayConfig || !candidate) {
118
+ return c.json({
119
+ error: {
120
+ code: 400,
121
+ errorCode: "INVALID_REGISTRATION",
122
+ message: "Registration payload is incomplete.",
123
+ },
124
+ }, 400);
125
+ }
126
+ if (isLocalUrl(candidate.serverUrl)) {
127
+ return c.json({
128
+ error: {
129
+ code: 400,
130
+ errorCode: "PUBLIC_API_URL_REQUIRED",
131
+ message: "Register using the public PS API URL.",
132
+ },
133
+ }, 400);
134
+ }
135
+ const account = privateKeyToAccount(ownerPrivateKey);
136
+ if (account.address.toLowerCase() !== candidate.ownerAddress.toLowerCase()) {
137
+ return c.json({
138
+ error: {
139
+ code: 400,
140
+ errorCode: "OWNER_KEY_MISMATCH",
141
+ message: "VANA_OWNER_PRIVATE_KEY does not match registration owner.",
142
+ },
143
+ }, 400);
144
+ }
145
+ const gateway = createGatewayClient(gatewayConfig.url);
146
+ const existing = await gateway.getServer(candidate.serverAddress);
147
+ if (existing?.id) {
148
+ deps.onRegistered?.(existing.id);
149
+ return c.json({
150
+ alreadyRegistered: true,
151
+ serverId: existing.id,
152
+ candidate,
153
+ });
154
+ }
155
+ const signature = await account.signTypedData({
156
+ domain: serverRegistrationDomain(gatewayConfig),
157
+ types: SERVER_REGISTRATION_TYPES,
158
+ primaryType: "ServerRegistration",
159
+ message: candidate,
160
+ });
161
+ const result = await gateway.registerServer({
162
+ ...candidate,
163
+ signature,
164
+ });
165
+ deps.onRegistered?.(result.serverId ?? null);
166
+ return c.json({
167
+ ...result,
168
+ candidate,
169
+ });
170
+ });
171
+ app.post("/rpc/files", requireDevToken, async (c) => {
172
+ let body;
173
+ try {
174
+ body = await c.req.json();
175
+ }
176
+ catch {
177
+ return c.json({
178
+ error: {
179
+ code: 400,
180
+ errorCode: "INVALID_BODY",
181
+ message: "Invalid JSON body",
182
+ },
183
+ }, 400);
184
+ }
185
+ const record = body;
186
+ const gatewayUrl = record.gatewayUrl;
187
+ const fileIds = record.fileIds;
188
+ if (typeof gatewayUrl !== "string" ||
189
+ !Array.isArray(fileIds) ||
190
+ !fileIds.every((fileId) => typeof fileId === "string")) {
191
+ return c.json({
192
+ error: {
193
+ code: 400,
194
+ errorCode: "INVALID_RPC_FILE_CHECK",
195
+ message: "gatewayUrl and fileIds are required.",
196
+ },
197
+ }, 400);
198
+ }
199
+ const gateway = createGatewayClient(gatewayUrl);
200
+ const results = {};
201
+ await Promise.all(fileIds.map(async (fileId) => {
202
+ try {
203
+ const dataPoint = await gateway.getDataPoint(fileId);
204
+ results[fileId] = { registered: Boolean(dataPoint) };
205
+ }
206
+ catch (err) {
207
+ results[fileId] = {
208
+ registered: false,
209
+ error: err instanceof Error ? err.message : String(err),
210
+ };
211
+ }
212
+ }));
213
+ return c.json({ files: results });
214
+ });
215
+ return app;
216
+ }
217
+ //# sourceMappingURL=ui-registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-registration.js","sourceRoot":"","sources":["../../src/routes/ui-registration.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Hono } from "hono";
2
2
  export interface UiRouteDeps {
3
3
  devToken: string;
4
+ psLiteBootstrap?: unknown;
4
5
  }
5
6
  export declare function uiRoute(deps: UiRouteDeps): Hono;
6
7
  //# sourceMappingURL=ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/routes/ui.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiBD,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAsB/C"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/routes/ui.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAqCD,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAoD/C"}