@undefineds.co/xpod 0.2.34 → 0.2.36

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 (302) hide show
  1. package/dist/agents/schema/agent-config.js +1 -1
  2. package/dist/agents/schema/agent-config.js.map +1 -1
  3. package/dist/agents/schema/create-agent-schema.js +17 -16
  4. package/dist/agents/schema/create-agent-schema.js.map +1 -1
  5. package/dist/agents/schema/tables.js +1 -1
  6. package/dist/agents/schema/tables.js.map +1 -1
  7. package/dist/ai/schema/config.js +1 -1
  8. package/dist/ai/schema/config.js.map +1 -1
  9. package/dist/ai/schema/model.js +2 -2
  10. package/dist/ai/schema/model.js.map +1 -1
  11. package/dist/ai/schema/provider.js +1 -1
  12. package/dist/ai/schema/provider.js.map +1 -1
  13. package/dist/ai/schema/vector-store.js +2 -2
  14. package/dist/ai/schema/vector-store.js.map +1 -1
  15. package/dist/api/container/local.js +1 -5
  16. package/dist/api/container/local.js.map +1 -1
  17. package/dist/api/container/routes.js +16 -1
  18. package/dist/api/container/routes.js.map +1 -1
  19. package/dist/api/handlers/PodManagementHandler.d.ts +8 -0
  20. package/dist/api/handlers/PodManagementHandler.js +5 -3
  21. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  22. package/dist/api/handlers/WebIdProfileHandler.js +64 -6
  23. package/dist/api/handlers/WebIdProfileHandler.js.map +1 -1
  24. package/dist/api/runtime.js +11 -6
  25. package/dist/api/runtime.js.map +1 -1
  26. package/dist/components/components.jsonld +1 -0
  27. package/dist/components/context.jsonld +36 -0
  28. package/dist/credential/schema/tables.js +3 -3
  29. package/dist/credential/schema/tables.js.map +1 -1
  30. package/dist/edge/LocalNetworkManager.d.ts +2 -7
  31. package/dist/edge/LocalNetworkManager.js +7 -34
  32. package/dist/edge/LocalNetworkManager.js.map +1 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.js +3 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/provision/LocalPodProvisioningService.d.ts +34 -0
  37. package/dist/provision/LocalPodProvisioningService.js +294 -0
  38. package/dist/provision/LocalPodProvisioningService.js.map +1 -0
  39. package/dist/provision/LocalPodProvisioningService.jsonld +142 -0
  40. package/dist/provision/ProvisionPodCreator.js +3 -4
  41. package/dist/provision/ProvisionPodCreator.js.map +1 -1
  42. package/dist/tunnel/LocalTunnelProvider.d.ts +2 -2
  43. package/dist/tunnel/LocalTunnelProvider.js +12 -14
  44. package/dist/tunnel/LocalTunnelProvider.js.map +1 -1
  45. package/dist/tunnel/TunnelProvider.d.ts +2 -0
  46. package/dist/tunnel/TunnelProvider.js.map +1 -1
  47. package/dist/tunnel/TunnelProvider.jsonld +4 -0
  48. package/package.json +2 -2
  49. package/node_modules/@undefineds.co/models/README.md +0 -578
  50. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/columns.d.ts +0 -37
  51. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/columns.js +0 -1
  52. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/pod-table.d.ts +0 -3
  53. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/pod-table.js +0 -1
  54. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/types.d.ts +0 -40
  55. package/node_modules/@undefineds.co/models/dist/_drizzle-solid/types.js +0 -1
  56. package/node_modules/@undefineds.co/models/dist/agent.providers.d.ts +0 -13
  57. package/node_modules/@undefineds.co/models/dist/agent.providers.js +0 -69
  58. package/node_modules/@undefineds.co/models/dist/agent.repository.d.ts +0 -85
  59. package/node_modules/@undefineds.co/models/dist/agent.repository.js +0 -7
  60. package/node_modules/@undefineds.co/models/dist/agent.schema.d.ts +0 -1
  61. package/node_modules/@undefineds.co/models/dist/agent.schema.js +0 -1
  62. package/node_modules/@undefineds.co/models/dist/ai-config/index.d.ts +0 -61
  63. package/node_modules/@undefineds.co/models/dist/ai-config/index.js +0 -294
  64. package/node_modules/@undefineds.co/models/dist/ai-config.d.ts +0 -1
  65. package/node_modules/@undefineds.co/models/dist/ai-config.js +0 -1
  66. package/node_modules/@undefineds.co/models/dist/ai-model.schema.d.ts +0 -1
  67. package/node_modules/@undefineds.co/models/dist/ai-model.schema.js +0 -1
  68. package/node_modules/@undefineds.co/models/dist/ai-provider.schema.d.ts +0 -1
  69. package/node_modules/@undefineds.co/models/dist/ai-provider.schema.js +0 -1
  70. package/node_modules/@undefineds.co/models/dist/approval.schema.d.ts +0 -1
  71. package/node_modules/@undefineds.co/models/dist/approval.schema.js +0 -1
  72. package/node_modules/@undefineds.co/models/dist/audit.schema.d.ts +0 -1
  73. package/node_modules/@undefineds.co/models/dist/audit.schema.js +0 -1
  74. package/node_modules/@undefineds.co/models/dist/chat.repository.d.ts +0 -61
  75. package/node_modules/@undefineds.co/models/dist/chat.repository.js +0 -8
  76. package/node_modules/@undefineds.co/models/dist/chat.schema.d.ts +0 -1
  77. package/node_modules/@undefineds.co/models/dist/chat.schema.js +0 -1
  78. package/node_modules/@undefineds.co/models/dist/chat.utils.d.ts +0 -3
  79. package/node_modules/@undefineds.co/models/dist/chat.utils.js +0 -30
  80. package/node_modules/@undefineds.co/models/dist/contact.repository.d.ts +0 -85
  81. package/node_modules/@undefineds.co/models/dist/contact.repository.js +0 -8
  82. package/node_modules/@undefineds.co/models/dist/contact.schema.d.ts +0 -1
  83. package/node_modules/@undefineds.co/models/dist/contact.schema.js +0 -1
  84. package/node_modules/@undefineds.co/models/dist/core/agent-provider.schema.d.ts +0 -1
  85. package/node_modules/@undefineds.co/models/dist/core/agent-provider.schema.js +0 -1
  86. package/node_modules/@undefineds.co/models/dist/core/agent-status.schema.d.ts +0 -12
  87. package/node_modules/@undefineds.co/models/dist/core/agent-status.schema.js +0 -18
  88. package/node_modules/@undefineds.co/models/dist/core/agent.schema.d.ts +0 -72
  89. package/node_modules/@undefineds.co/models/dist/core/agent.schema.js +0 -38
  90. package/node_modules/@undefineds.co/models/dist/core/ai-config.schema.d.ts +0 -11
  91. package/node_modules/@undefineds.co/models/dist/core/ai-config.schema.js +0 -18
  92. package/node_modules/@undefineds.co/models/dist/core/ai-model.schema.d.ts +0 -15
  93. package/node_modules/@undefineds.co/models/dist/core/ai-model.schema.js +0 -21
  94. package/node_modules/@undefineds.co/models/dist/core/ai-provider.schema.d.ts +0 -16
  95. package/node_modules/@undefineds.co/models/dist/core/ai-provider.schema.js +0 -28
  96. package/node_modules/@undefineds.co/models/dist/core/approval.schema.d.ts +0 -21
  97. package/node_modules/@undefineds.co/models/dist/core/approval.schema.js +0 -33
  98. package/node_modules/@undefineds.co/models/dist/core/audit.schema.d.ts +0 -17
  99. package/node_modules/@undefineds.co/models/dist/core/audit.schema.js +0 -29
  100. package/node_modules/@undefineds.co/models/dist/core/chat.schema.d.ts +0 -36
  101. package/node_modules/@undefineds.co/models/dist/core/chat.schema.js +0 -45
  102. package/node_modules/@undefineds.co/models/dist/core/contact.schema.d.ts +0 -47
  103. package/node_modules/@undefineds.co/models/dist/core/contact.schema.js +0 -59
  104. package/node_modules/@undefineds.co/models/dist/core/credential.schema.d.ts +0 -56
  105. package/node_modules/@undefineds.co/models/dist/core/credential.schema.js +0 -40
  106. package/node_modules/@undefineds.co/models/dist/core/extension/extension.schema.d.ts +0 -4
  107. package/node_modules/@undefineds.co/models/dist/core/extension/extension.schema.js +0 -11
  108. package/node_modules/@undefineds.co/models/dist/core/extension/index.d.ts +0 -1
  109. package/node_modules/@undefineds.co/models/dist/core/extension/index.js +0 -1
  110. package/node_modules/@undefineds.co/models/dist/core/extension.d.ts +0 -1
  111. package/node_modules/@undefineds.co/models/dist/core/extension.js +0 -1
  112. package/node_modules/@undefineds.co/models/dist/core/favorite/favorite.schema.d.ts +0 -24
  113. package/node_modules/@undefineds.co/models/dist/core/favorite/favorite.schema.js +0 -34
  114. package/node_modules/@undefineds.co/models/dist/core/favorite/index.d.ts +0 -1
  115. package/node_modules/@undefineds.co/models/dist/core/favorite/index.js +0 -1
  116. package/node_modules/@undefineds.co/models/dist/core/file/file.schema.d.ts +0 -39
  117. package/node_modules/@undefineds.co/models/dist/core/file/file.schema.js +0 -51
  118. package/node_modules/@undefineds.co/models/dist/core/file/index.d.ts +0 -1
  119. package/node_modules/@undefineds.co/models/dist/core/file/index.js +0 -1
  120. package/node_modules/@undefineds.co/models/dist/core/file.d.ts +0 -1
  121. package/node_modules/@undefineds.co/models/dist/core/file.js +0 -1
  122. package/node_modules/@undefineds.co/models/dist/core/grant.schema.d.ts +0 -16
  123. package/node_modules/@undefineds.co/models/dist/core/grant.schema.js +0 -29
  124. package/node_modules/@undefineds.co/models/dist/core/import/import-job.schema.d.ts +0 -5
  125. package/node_modules/@undefineds.co/models/dist/core/import/import-job.schema.js +0 -5
  126. package/node_modules/@undefineds.co/models/dist/core/import/index.d.ts +0 -1
  127. package/node_modules/@undefineds.co/models/dist/core/import/index.js +0 -1
  128. package/node_modules/@undefineds.co/models/dist/core/import.d.ts +0 -1
  129. package/node_modules/@undefineds.co/models/dist/core/import.js +0 -1
  130. package/node_modules/@undefineds.co/models/dist/core/inbox-notification.schema.d.ts +0 -9
  131. package/node_modules/@undefineds.co/models/dist/core/inbox-notification.schema.js +0 -16
  132. package/node_modules/@undefineds.co/models/dist/core/index.d.ts +0 -31
  133. package/node_modules/@undefineds.co/models/dist/core/index.js +0 -32
  134. package/node_modules/@undefineds.co/models/dist/core/knowledge/index.d.ts +0 -1
  135. package/node_modules/@undefineds.co/models/dist/core/knowledge/index.js +0 -1
  136. package/node_modules/@undefineds.co/models/dist/core/knowledge/knowledge-folder.schema.d.ts +0 -7
  137. package/node_modules/@undefineds.co/models/dist/core/knowledge/knowledge-folder.schema.js +0 -6
  138. package/node_modules/@undefineds.co/models/dist/core/knowledge.d.ts +0 -1
  139. package/node_modules/@undefineds.co/models/dist/core/knowledge.js +0 -1
  140. package/node_modules/@undefineds.co/models/dist/core/message.schema.d.ts +0 -33
  141. package/node_modules/@undefineds.co/models/dist/core/message.schema.js +0 -49
  142. package/node_modules/@undefineds.co/models/dist/core/namespaces.d.ts +0 -176
  143. package/node_modules/@undefineds.co/models/dist/core/namespaces.js +0 -289
  144. package/node_modules/@undefineds.co/models/dist/core/profile.d.ts +0 -16
  145. package/node_modules/@undefineds.co/models/dist/core/profile.js +0 -19
  146. package/node_modules/@undefineds.co/models/dist/core/schema.d.ts +0 -304
  147. package/node_modules/@undefineds.co/models/dist/core/schema.js +0 -46
  148. package/node_modules/@undefineds.co/models/dist/core/session/index.d.ts +0 -1
  149. package/node_modules/@undefineds.co/models/dist/core/session/index.js +0 -1
  150. package/node_modules/@undefineds.co/models/dist/core/session/session.schema.d.ts +0 -6
  151. package/node_modules/@undefineds.co/models/dist/core/session/session.schema.js +0 -6
  152. package/node_modules/@undefineds.co/models/dist/core/session.d.ts +0 -1
  153. package/node_modules/@undefineds.co/models/dist/core/session.js +0 -1
  154. package/node_modules/@undefineds.co/models/dist/core/settings/index.d.ts +0 -1
  155. package/node_modules/@undefineds.co/models/dist/core/settings/index.js +0 -1
  156. package/node_modules/@undefineds.co/models/dist/core/settings/settings.schema.d.ts +0 -49
  157. package/node_modules/@undefineds.co/models/dist/core/settings/settings.schema.js +0 -63
  158. package/node_modules/@undefineds.co/models/dist/core/settings.d.ts +0 -1
  159. package/node_modules/@undefineds.co/models/dist/core/settings.js +0 -1
  160. package/node_modules/@undefineds.co/models/dist/core/thread.schema.d.ts +0 -28
  161. package/node_modules/@undefineds.co/models/dist/core/thread.schema.js +0 -36
  162. package/node_modules/@undefineds.co/models/dist/core/types/collaboration-blocks.d.ts +0 -52
  163. package/node_modules/@undefineds.co/models/dist/core/types/collaboration-blocks.js +0 -7
  164. package/node_modules/@undefineds.co/models/dist/core/types/message-block.d.ts +0 -270
  165. package/node_modules/@undefineds.co/models/dist/core/types/message-block.js +0 -125
  166. package/node_modules/@undefineds.co/models/dist/core/vector-store.schema.d.ts +0 -25
  167. package/node_modules/@undefineds.co/models/dist/core/vector-store.schema.js +0 -35
  168. package/node_modules/@undefineds.co/models/dist/core/vocab/_namespaces.d.ts +0 -1
  169. package/node_modules/@undefineds.co/models/dist/core/vocab/_namespaces.js +0 -3
  170. package/node_modules/@undefineds.co/models/dist/core/vocab/chat.vocab.d.ts +0 -16
  171. package/node_modules/@undefineds.co/models/dist/core/vocab/chat.vocab.js +0 -22
  172. package/node_modules/@undefineds.co/models/dist/core/vocab/contact.vocab.d.ts +0 -21
  173. package/node_modules/@undefineds.co/models/dist/core/vocab/contact.vocab.js +0 -22
  174. package/node_modules/@undefineds.co/models/dist/core/vocab/index.d.ts +0 -6
  175. package/node_modules/@undefineds.co/models/dist/core/vocab/index.js +0 -6
  176. package/node_modules/@undefineds.co/models/dist/core/vocab/message.vocab.d.ts +0 -20
  177. package/node_modules/@undefineds.co/models/dist/core/vocab/message.vocab.js +0 -24
  178. package/node_modules/@undefineds.co/models/dist/core/vocab/sidecar.vocab.d.ts +0 -46
  179. package/node_modules/@undefineds.co/models/dist/core/vocab/sidecar.vocab.js +0 -47
  180. package/node_modules/@undefineds.co/models/dist/core/vocab/thread.vocab.d.ts +0 -11
  181. package/node_modules/@undefineds.co/models/dist/core/vocab/thread.vocab.js +0 -14
  182. package/node_modules/@undefineds.co/models/dist/core/vocab/workspace.vocab.d.ts +0 -12
  183. package/node_modules/@undefineds.co/models/dist/core/vocab/workspace.vocab.js +0 -13
  184. package/node_modules/@undefineds.co/models/dist/core/vocab.d.ts +0 -1
  185. package/node_modules/@undefineds.co/models/dist/core/vocab.js +0 -1
  186. package/node_modules/@undefineds.co/models/dist/core/workspace.schema.d.ts +0 -35
  187. package/node_modules/@undefineds.co/models/dist/core/workspace.schema.js +0 -106
  188. package/node_modules/@undefineds.co/models/dist/core.d.ts +0 -1
  189. package/node_modules/@undefineds.co/models/dist/core.js +0 -1
  190. package/node_modules/@undefineds.co/models/dist/credential.schema.d.ts +0 -1
  191. package/node_modules/@undefineds.co/models/dist/credential.schema.js +0 -1
  192. package/node_modules/@undefineds.co/models/dist/discovery/index.d.ts +0 -31
  193. package/node_modules/@undefineds.co/models/dist/discovery/index.js +0 -147
  194. package/node_modules/@undefineds.co/models/dist/discovery/models.json +0 -2623
  195. package/node_modules/@undefineds.co/models/dist/discovery/providers.json +0 -156
  196. package/node_modules/@undefineds.co/models/dist/discovery/types.d.ts +0 -103
  197. package/node_modules/@undefineds.co/models/dist/discovery/types.js +0 -12
  198. package/node_modules/@undefineds.co/models/dist/discovery/vercel.d.ts +0 -25
  199. package/node_modules/@undefineds.co/models/dist/discovery/vercel.js +0 -95
  200. package/node_modules/@undefineds.co/models/dist/discovery.d.ts +0 -1
  201. package/node_modules/@undefineds.co/models/dist/discovery.js +0 -1
  202. package/node_modules/@undefineds.co/models/dist/extension/extension.schema.d.ts +0 -1
  203. package/node_modules/@undefineds.co/models/dist/extension/extension.schema.js +0 -1
  204. package/node_modules/@undefineds.co/models/dist/extension/index.d.ts +0 -1
  205. package/node_modules/@undefineds.co/models/dist/extension/index.js +0 -1
  206. package/node_modules/@undefineds.co/models/dist/extension.d.ts +0 -1
  207. package/node_modules/@undefineds.co/models/dist/extension.js +0 -1
  208. package/node_modules/@undefineds.co/models/dist/favorite/favorite.schema.d.ts +0 -1
  209. package/node_modules/@undefineds.co/models/dist/favorite/favorite.schema.js +0 -1
  210. package/node_modules/@undefineds.co/models/dist/favorite/index.d.ts +0 -2
  211. package/node_modules/@undefineds.co/models/dist/favorite/index.js +0 -7
  212. package/node_modules/@undefineds.co/models/dist/favorite/starred-sync.d.ts +0 -66
  213. package/node_modules/@undefineds.co/models/dist/favorite/starred-sync.js +0 -156
  214. package/node_modules/@undefineds.co/models/dist/favorite.d.ts +0 -1
  215. package/node_modules/@undefineds.co/models/dist/favorite.js +0 -1
  216. package/node_modules/@undefineds.co/models/dist/file/file.schema.d.ts +0 -1
  217. package/node_modules/@undefineds.co/models/dist/file/file.schema.js +0 -1
  218. package/node_modules/@undefineds.co/models/dist/file/index.d.ts +0 -1
  219. package/node_modules/@undefineds.co/models/dist/file/index.js +0 -1
  220. package/node_modules/@undefineds.co/models/dist/file.d.ts +0 -1
  221. package/node_modules/@undefineds.co/models/dist/file.js +0 -1
  222. package/node_modules/@undefineds.co/models/dist/fixtures/contracts-chat-contact.d.ts +0 -13
  223. package/node_modules/@undefineds.co/models/dist/fixtures/contracts-chat-contact.js +0 -76
  224. package/node_modules/@undefineds.co/models/dist/grant.schema.d.ts +0 -1
  225. package/node_modules/@undefineds.co/models/dist/grant.schema.js +0 -1
  226. package/node_modules/@undefineds.co/models/dist/import/import-job.schema.d.ts +0 -5
  227. package/node_modules/@undefineds.co/models/dist/import/import-job.schema.js +0 -5
  228. package/node_modules/@undefineds.co/models/dist/import/index.d.ts +0 -1
  229. package/node_modules/@undefineds.co/models/dist/import/index.js +0 -1
  230. package/node_modules/@undefineds.co/models/dist/import.d.ts +0 -1
  231. package/node_modules/@undefineds.co/models/dist/import.js +0 -1
  232. package/node_modules/@undefineds.co/models/dist/inbox-notification.schema.d.ts +0 -1
  233. package/node_modules/@undefineds.co/models/dist/inbox-notification.schema.js +0 -1
  234. package/node_modules/@undefineds.co/models/dist/index.d.ts +0 -41
  235. package/node_modules/@undefineds.co/models/dist/index.js +0 -83
  236. package/node_modules/@undefineds.co/models/dist/knowledge/index.d.ts +0 -1
  237. package/node_modules/@undefineds.co/models/dist/knowledge/index.js +0 -1
  238. package/node_modules/@undefineds.co/models/dist/knowledge/knowledge-folder.schema.d.ts +0 -1
  239. package/node_modules/@undefineds.co/models/dist/knowledge/knowledge-folder.schema.js +0 -1
  240. package/node_modules/@undefineds.co/models/dist/knowledge.d.ts +0 -1
  241. package/node_modules/@undefineds.co/models/dist/knowledge.js +0 -1
  242. package/node_modules/@undefineds.co/models/dist/message.repository.d.ts +0 -81
  243. package/node_modules/@undefineds.co/models/dist/message.repository.js +0 -8
  244. package/node_modules/@undefineds.co/models/dist/message.schema.d.ts +0 -1
  245. package/node_modules/@undefineds.co/models/dist/message.schema.js +0 -1
  246. package/node_modules/@undefineds.co/models/dist/namespaces.d.ts +0 -1
  247. package/node_modules/@undefineds.co/models/dist/namespaces.js +0 -1
  248. package/node_modules/@undefineds.co/models/dist/profile.d.ts +0 -1
  249. package/node_modules/@undefineds.co/models/dist/profile.js +0 -1
  250. package/node_modules/@undefineds.co/models/dist/repository.d.ts +0 -59
  251. package/node_modules/@undefineds.co/models/dist/repository.js +0 -186
  252. package/node_modules/@undefineds.co/models/dist/schema.d.ts +0 -1
  253. package/node_modules/@undefineds.co/models/dist/schema.js +0 -1
  254. package/node_modules/@undefineds.co/models/dist/session/index.d.ts +0 -1
  255. package/node_modules/@undefineds.co/models/dist/session/index.js +0 -1
  256. package/node_modules/@undefineds.co/models/dist/session/session.schema.d.ts +0 -1
  257. package/node_modules/@undefineds.co/models/dist/session/session.schema.js +0 -1
  258. package/node_modules/@undefineds.co/models/dist/session.d.ts +0 -1
  259. package/node_modules/@undefineds.co/models/dist/session.js +0 -1
  260. package/node_modules/@undefineds.co/models/dist/settings/index.d.ts +0 -1
  261. package/node_modules/@undefineds.co/models/dist/settings/index.js +0 -1
  262. package/node_modules/@undefineds.co/models/dist/settings/settings.schema.d.ts +0 -1
  263. package/node_modules/@undefineds.co/models/dist/settings/settings.schema.js +0 -1
  264. package/node_modules/@undefineds.co/models/dist/settings.d.ts +0 -1
  265. package/node_modules/@undefineds.co/models/dist/settings.js +0 -1
  266. package/node_modules/@undefineds.co/models/dist/sidecar/index.d.ts +0 -2
  267. package/node_modules/@undefineds.co/models/dist/sidecar/index.js +0 -2
  268. package/node_modules/@undefineds.co/models/dist/sidecar/persistence-mapping.d.ts +0 -51
  269. package/node_modules/@undefineds.co/models/dist/sidecar/persistence-mapping.js +0 -44
  270. package/node_modules/@undefineds.co/models/dist/sidecar/sidecar-events.d.ts +0 -632
  271. package/node_modules/@undefineds.co/models/dist/sidecar/sidecar-events.js +0 -133
  272. package/node_modules/@undefineds.co/models/dist/thread.repository.d.ts +0 -41
  273. package/node_modules/@undefineds.co/models/dist/thread.repository.js +0 -8
  274. package/node_modules/@undefineds.co/models/dist/thread.schema.d.ts +0 -1
  275. package/node_modules/@undefineds.co/models/dist/thread.schema.js +0 -1
  276. package/node_modules/@undefineds.co/models/dist/types/collaboration-blocks.d.ts +0 -52
  277. package/node_modules/@undefineds.co/models/dist/types/collaboration-blocks.js +0 -7
  278. package/node_modules/@undefineds.co/models/dist/types/message-block.d.ts +0 -270
  279. package/node_modules/@undefineds.co/models/dist/types/message-block.js +0 -125
  280. package/node_modules/@undefineds.co/models/dist/vocab/_namespaces.d.ts +0 -1
  281. package/node_modules/@undefineds.co/models/dist/vocab/_namespaces.js +0 -3
  282. package/node_modules/@undefineds.co/models/dist/vocab/chat.vocab.d.ts +0 -16
  283. package/node_modules/@undefineds.co/models/dist/vocab/chat.vocab.js +0 -22
  284. package/node_modules/@undefineds.co/models/dist/vocab/contact.vocab.d.ts +0 -21
  285. package/node_modules/@undefineds.co/models/dist/vocab/contact.vocab.js +0 -22
  286. package/node_modules/@undefineds.co/models/dist/vocab/index.d.ts +0 -6
  287. package/node_modules/@undefineds.co/models/dist/vocab/index.js +0 -6
  288. package/node_modules/@undefineds.co/models/dist/vocab/message.vocab.d.ts +0 -20
  289. package/node_modules/@undefineds.co/models/dist/vocab/message.vocab.js +0 -24
  290. package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.d.ts +0 -46
  291. package/node_modules/@undefineds.co/models/dist/vocab/sidecar.vocab.js +0 -47
  292. package/node_modules/@undefineds.co/models/dist/vocab/thread.vocab.d.ts +0 -11
  293. package/node_modules/@undefineds.co/models/dist/vocab/thread.vocab.js +0 -14
  294. package/node_modules/@undefineds.co/models/dist/vocab/workspace.vocab.d.ts +0 -12
  295. package/node_modules/@undefineds.co/models/dist/vocab/workspace.vocab.js +0 -13
  296. package/node_modules/@undefineds.co/models/dist/vocab.d.ts +0 -1
  297. package/node_modules/@undefineds.co/models/dist/vocab.js +0 -1
  298. package/node_modules/@undefineds.co/models/dist/workspace.repository.d.ts +0 -45
  299. package/node_modules/@undefineds.co/models/dist/workspace.repository.js +0 -8
  300. package/node_modules/@undefineds.co/models/dist/workspace.schema.d.ts +0 -1
  301. package/node_modules/@undefineds.co/models/dist/workspace.schema.js +0 -1
  302. package/node_modules/@undefineds.co/models/package.json +0 -67
@@ -97,20 +97,25 @@ function registerWebIdProfileRoutes(server, options) {
97
97
  server.get('/api/v1/identity/:username', async (_request, response, params) => {
98
98
  const username = decodeURIComponent(params.username);
99
99
  try {
100
- const profile = await resolveProfileWithStorageBackfill(username, options);
100
+ const profile = await resolveIdentityLookup(username, options);
101
101
  if (!profile) {
102
102
  sendError(response, 404, 'Profile not found');
103
103
  return;
104
104
  }
105
- sendJson(response, 200, {
105
+ const body = {
106
106
  username: profile.username,
107
107
  webidUrl: profile.webidUrl,
108
108
  storageUrl: profile.storageUrl,
109
109
  storageMode: profile.storageMode,
110
110
  oidcIssuer: profile.oidcIssuer,
111
- createdAt: profile.createdAt.toISOString(),
112
- updatedAt: profile.updatedAt.toISOString(),
113
- });
111
+ };
112
+ if (profile.createdAt) {
113
+ body.createdAt = profile.createdAt.toISOString();
114
+ }
115
+ if (profile.updatedAt) {
116
+ body.updatedAt = profile.updatedAt.toISOString();
117
+ }
118
+ sendJson(response, 200, body);
114
119
  }
115
120
  catch (error) {
116
121
  logger.error(`Failed to get profile for ${username}: ${error}`);
@@ -171,6 +176,44 @@ function registerWebIdProfileRoutes(server, options) {
171
176
  });
172
177
  logger.info('WebID Profile routes registered');
173
178
  }
179
+ async function resolveIdentityLookup(username, options) {
180
+ try {
181
+ const profile = await resolveProfileWithStorageBackfill(username, options);
182
+ if (profile) {
183
+ return profile;
184
+ }
185
+ }
186
+ catch (error) {
187
+ logger.warn(`Profile lookup unavailable for ${username}, falling back to Pod index: ${error}`);
188
+ }
189
+ return resolveProfileFromPods(username, options);
190
+ }
191
+ async function resolveProfileFromPods(username, options) {
192
+ const { podLookupRepo } = options;
193
+ if (!podLookupRepo) {
194
+ return null;
195
+ }
196
+ let pods;
197
+ try {
198
+ pods = await podLookupRepo.listAllPods();
199
+ }
200
+ catch (error) {
201
+ logger.warn(`Pod index lookup unavailable for ${username}: ${error}`);
202
+ return null;
203
+ }
204
+ const match = pods.find((pod) => derivePodSlug(pod.baseUrl) === username);
205
+ if (!match) {
206
+ return null;
207
+ }
208
+ const storageUrl = ensureTrailingSlash(match.baseUrl);
209
+ return {
210
+ username,
211
+ webidUrl: `${storageUrl}profile/card#me`,
212
+ storageUrl,
213
+ storageMode: 'cloud',
214
+ oidcIssuer: deriveOrigin(storageUrl),
215
+ };
216
+ }
174
217
  async function resolveProfileWithStorageBackfill(username, options) {
175
218
  const { profileRepo, podLookupRepo } = options;
176
219
  const profile = await profileRepo.get(username);
@@ -180,7 +223,14 @@ async function resolveProfileWithStorageBackfill(username, options) {
180
223
  if (profile.storageUrl || !profile.accountId || !podLookupRepo) {
181
224
  return profile;
182
225
  }
183
- const pods = await podLookupRepo.listByAccountId(profile.accountId);
226
+ let pods;
227
+ try {
228
+ pods = await podLookupRepo.listByAccountId(profile.accountId);
229
+ }
230
+ catch (error) {
231
+ logger.warn(`Skipped storage backfill for ${username}: pod index unavailable for account ${profile.accountId}: ${error}`);
232
+ return profile;
233
+ }
184
234
  const storageUrl = selectStorageBackfillCandidate(username, pods);
185
235
  if (!storageUrl) {
186
236
  logger.warn(`Skipped storage backfill for ${username}: no unambiguous pod found for account ${profile.accountId}`);
@@ -230,6 +280,14 @@ function derivePodSlug(baseUrl) {
230
280
  function ensureTrailingSlash(url) {
231
281
  return url.replace(/\/+$/, '') + '/';
232
282
  }
283
+ function deriveOrigin(url) {
284
+ try {
285
+ return ensureTrailingSlash(new URL(url).origin);
286
+ }
287
+ catch {
288
+ return undefined;
289
+ }
290
+ }
233
291
  async function readJsonBody(request) {
234
292
  return new Promise((resolve, reject) => {
235
293
  let data = '';
@@ -1 +1 @@
1
- {"version":3,"file":"WebIdProfileHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/WebIdProfileHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WebID Profile API Handler\n *\n * 提供 WebID Profile 托管服务的 HTTP API\n *\n * GET /{username}/profile/card - 获取 WebID Profile (Turtle 格式)\n * POST /api/v1/identity/{username}/storage - 更新 storage 指针 (需认证)\n */\n\nimport type { ServerResponse, IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\n\nconst logger = getLoggerFor('WebIdProfileHandler');\n\nexport interface WebIdProfileHandlerOptions {\n profileRepo: WebIdProfileRepository;\n podLookupRepo?: PodLookupRepository;\n}\n\nexport function registerWebIdProfileRoutes(\n server: ApiServer,\n options: WebIdProfileHandlerOptions,\n): void {\n const { profileRepo } = options;\n\n /**\n * GET /{username}/profile/card\n *\n * 获取 WebID Profile (Turtle 格式)\n * 这是 Solid 标准的 WebID 端点\n */\n server.get('/:username/profile/card', async (_request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n // 返回 Turtle 格式\n const turtle = profileRepo.generateProfileTurtle(profile);\n\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/turtle');\n response.setHeader('Link', `<${profile.webidUrl}>; rel=\"describedby\"`);\n response.end(turtle);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity/{username}/storage\n *\n * 更新 storage 指针\n * 用于 Local 节点更新其 storage URL\n *\n * Request body:\n * {\n * \"storageUrl\": \"https://alice.undefineds.xyz/\"\n * }\n */\n server.post('/api/v1/identity/:username/storage', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const body = await readJsonBody(request);\n const payload = body as { storageUrl?: string; storageMode?: string } | undefined;\n\n if (!payload?.storageUrl) {\n sendError(response, 400, 'storageUrl is required');\n return;\n }\n\n // 验证 URL 格式\n try {\n new URL(payload.storageUrl);\n } catch {\n sendError(response, 400, 'Invalid storageUrl format');\n return;\n }\n\n const profile = await profileRepo.updateStorage(username, {\n storageUrl: payload.storageUrl,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n });\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n logger.info(`Updated storage for ${username}: ${payload.storageUrl}`);\n\n sendJson(response, 200, {\n success: true,\n username,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n updatedAt: profile.updatedAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to update storage for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n /**\n * GET /api/v1/identity/{username}\n *\n * 获取 WebID Profile 信息 (JSON 格式)\n */\n server.get('/api/v1/identity/:username', async (_request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n sendJson(response, 200, {\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n oidcIssuer: profile.oidcIssuer,\n createdAt: profile.createdAt.toISOString(),\n updatedAt: profile.updatedAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity\n *\n * 创建 WebID Profile\n *\n * Request body:\n * {\n * \"username\": \"alice\",\n * \"storageMode\": \"local\", // optional, default: \"cloud\"\n * \"storageUrl\": \"https://alice.undefineds.xyz/\" // optional\n * }\n */\n server.post('/api/v1/identity', async (request, response, _params) => {\n try {\n const body = await readJsonBody(request);\n const payload = body as {\n username?: string;\n storageMode?: string;\n storageUrl?: string;\n accountId?: string;\n } | undefined;\n\n if (!payload?.username) {\n sendError(response, 400, 'username is required');\n return;\n }\n\n // 验证用户名格式\n if (!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(payload.username)) {\n sendError(response, 400, 'Invalid username format');\n return;\n }\n\n // 检查是否已存在\n const existing = await profileRepo.get(payload.username);\n if (existing) {\n sendError(response, 409, 'Username already taken');\n return;\n }\n\n const profile = await profileRepo.create({\n username: payload.username,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n storageUrl: payload.storageUrl,\n accountId: payload.accountId,\n });\n\n logger.info(`Created profile for ${payload.username}`);\n\n sendJson(response, 201, {\n success: true,\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n createdAt: profile.createdAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to create profile: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n logger.info('WebID Profile routes registered');\n}\n\nasync function resolveProfileWithStorageBackfill(\n username: string,\n options: WebIdProfileHandlerOptions,\n) {\n const { profileRepo, podLookupRepo } = options;\n const profile = await profileRepo.get(username);\n if (!profile) {\n return null;\n }\n\n if (profile.storageUrl || !profile.accountId || !podLookupRepo) {\n return profile;\n }\n\n const pods = await podLookupRepo.listByAccountId(profile.accountId);\n const storageUrl = selectStorageBackfillCandidate(username, pods);\n if (!storageUrl) {\n logger.warn(`Skipped storage backfill for ${username}: no unambiguous pod found for account ${profile.accountId}`);\n return profile;\n }\n\n try {\n const updated = await profileRepo.updateStorage(username, {\n storageUrl,\n storageMode: profile.storageMode,\n });\n if (updated) {\n logger.info(`Backfilled storage for ${username}: ${storageUrl}`);\n return updated;\n }\n } catch (error) {\n logger.warn(`Failed to backfill storage for ${username}: ${error}`);\n }\n\n return profile;\n}\n\nfunction selectStorageBackfillCandidate(\n username: string,\n pods: PodLookupResult[],\n): string | null {\n if (pods.length === 0) {\n return null;\n }\n\n const exactMatches = pods.filter((pod) => derivePodSlug(pod.baseUrl) === username);\n if (exactMatches.length === 1) {\n return ensureTrailingSlash(exactMatches[0].baseUrl);\n }\n\n if (exactMatches.length > 1) {\n return null;\n }\n\n if (pods.length === 1) {\n return ensureTrailingSlash(pods[0].baseUrl);\n }\n\n return null;\n}\n\nfunction derivePodSlug(baseUrl: string): string | null {\n try {\n const parsed = new URL(baseUrl);\n const [slug] = parsed.pathname.split('/').filter(Boolean);\n return slug || null;\n } catch {\n return null;\n }\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '') + '/';\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction sendError(response: ServerResponse, status: number, message: string): void {\n sendJson(response, status, { error: message });\n}\n"]}
1
+ {"version":3,"file":"WebIdProfileHandler.js","sourceRoot":"","sources":["../../../src/api/handlers/WebIdProfileHandler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WebID Profile API Handler\n *\n * 提供 WebID Profile 托管服务的 HTTP API\n *\n * GET /{username}/profile/card - 获取 WebID Profile (Turtle 格式)\n * POST /api/v1/identity/{username}/storage - 更新 storage 指针 (需认证)\n */\n\nimport type { ServerResponse, IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { ApiServer } from '../ApiServer';\nimport type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport type { PodLookupRepository, PodLookupResult } from '../../identity/drizzle/PodLookupRepository';\n\nconst logger = getLoggerFor('WebIdProfileHandler');\n\nexport interface WebIdProfileHandlerOptions {\n profileRepo: WebIdProfileRepository;\n podLookupRepo?: PodLookupRepository;\n}\n\ninterface IdentityProfileResponse {\n username: string;\n webidUrl: string;\n storageUrl?: string;\n storageMode: 'cloud' | 'local' | 'custom';\n oidcIssuer?: string;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nexport function registerWebIdProfileRoutes(\n server: ApiServer,\n options: WebIdProfileHandlerOptions,\n): void {\n const { profileRepo } = options;\n\n /**\n * GET /{username}/profile/card\n *\n * 获取 WebID Profile (Turtle 格式)\n * 这是 Solid 标准的 WebID 端点\n */\n server.get('/:username/profile/card', async (_request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n // 返回 Turtle 格式\n const turtle = profileRepo.generateProfileTurtle(profile);\n\n response.statusCode = 200;\n response.setHeader('Content-Type', 'text/turtle');\n response.setHeader('Link', `<${profile.webidUrl}>; rel=\"describedby\"`);\n response.end(turtle);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity/{username}/storage\n *\n * 更新 storage 指针\n * 用于 Local 节点更新其 storage URL\n *\n * Request body:\n * {\n * \"storageUrl\": \"https://alice.undefineds.xyz/\"\n * }\n */\n server.post('/api/v1/identity/:username/storage', async (request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const body = await readJsonBody(request);\n const payload = body as { storageUrl?: string; storageMode?: string } | undefined;\n\n if (!payload?.storageUrl) {\n sendError(response, 400, 'storageUrl is required');\n return;\n }\n\n // 验证 URL 格式\n try {\n new URL(payload.storageUrl);\n } catch {\n sendError(response, 400, 'Invalid storageUrl format');\n return;\n }\n\n const profile = await profileRepo.updateStorage(username, {\n storageUrl: payload.storageUrl,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n });\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n logger.info(`Updated storage for ${username}: ${payload.storageUrl}`);\n\n sendJson(response, 200, {\n success: true,\n username,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n updatedAt: profile.updatedAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to update storage for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n /**\n * GET /api/v1/identity/{username}\n *\n * 获取 WebID Profile 信息 (JSON 格式)\n */\n server.get('/api/v1/identity/:username', async (_request, response, params) => {\n const username = decodeURIComponent(params.username);\n\n try {\n const profile = await resolveIdentityLookup(username, options);\n\n if (!profile) {\n sendError(response, 404, 'Profile not found');\n return;\n }\n\n const body: Record<string, unknown> = {\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n oidcIssuer: profile.oidcIssuer,\n };\n if (profile.createdAt) {\n body.createdAt = profile.createdAt.toISOString();\n }\n if (profile.updatedAt) {\n body.updatedAt = profile.updatedAt.toISOString();\n }\n sendJson(response, 200, body);\n } catch (error) {\n logger.error(`Failed to get profile for ${username}: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n }, { public: true });\n\n /**\n * POST /api/v1/identity\n *\n * 创建 WebID Profile\n *\n * Request body:\n * {\n * \"username\": \"alice\",\n * \"storageMode\": \"local\", // optional, default: \"cloud\"\n * \"storageUrl\": \"https://alice.undefineds.xyz/\" // optional\n * }\n */\n server.post('/api/v1/identity', async (request, response, _params) => {\n try {\n const body = await readJsonBody(request);\n const payload = body as {\n username?: string;\n storageMode?: string;\n storageUrl?: string;\n accountId?: string;\n } | undefined;\n\n if (!payload?.username) {\n sendError(response, 400, 'username is required');\n return;\n }\n\n // 验证用户名格式\n if (!/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(payload.username)) {\n sendError(response, 400, 'Invalid username format');\n return;\n }\n\n // 检查是否已存在\n const existing = await profileRepo.get(payload.username);\n if (existing) {\n sendError(response, 409, 'Username already taken');\n return;\n }\n\n const profile = await profileRepo.create({\n username: payload.username,\n storageMode: payload.storageMode as 'cloud' | 'local' | 'custom' | undefined,\n storageUrl: payload.storageUrl,\n accountId: payload.accountId,\n });\n\n logger.info(`Created profile for ${payload.username}`);\n\n sendJson(response, 201, {\n success: true,\n username: profile.username,\n webidUrl: profile.webidUrl,\n storageUrl: profile.storageUrl,\n storageMode: profile.storageMode,\n createdAt: profile.createdAt.toISOString(),\n });\n } catch (error) {\n logger.error(`Failed to create profile: ${error}`);\n sendError(response, 500, 'Internal server error');\n }\n });\n\n logger.info('WebID Profile routes registered');\n}\n\nasync function resolveIdentityLookup(\n username: string,\n options: WebIdProfileHandlerOptions,\n): Promise<IdentityProfileResponse | null> {\n try {\n const profile = await resolveProfileWithStorageBackfill(username, options);\n if (profile) {\n return profile;\n }\n } catch (error) {\n logger.warn(`Profile lookup unavailable for ${username}, falling back to Pod index: ${error}`);\n }\n\n return resolveProfileFromPods(username, options);\n}\n\nasync function resolveProfileFromPods(\n username: string,\n options: WebIdProfileHandlerOptions,\n): Promise<IdentityProfileResponse | null> {\n const { podLookupRepo } = options;\n if (!podLookupRepo) {\n return null;\n }\n\n let pods: PodLookupResult[];\n try {\n pods = await podLookupRepo.listAllPods();\n } catch (error) {\n logger.warn(`Pod index lookup unavailable for ${username}: ${error}`);\n return null;\n }\n\n const match = pods.find((pod) => derivePodSlug(pod.baseUrl) === username);\n if (!match) {\n return null;\n }\n\n const storageUrl = ensureTrailingSlash(match.baseUrl);\n return {\n username,\n webidUrl: `${storageUrl}profile/card#me`,\n storageUrl,\n storageMode: 'cloud',\n oidcIssuer: deriveOrigin(storageUrl),\n };\n}\n\nasync function resolveProfileWithStorageBackfill(\n username: string,\n options: WebIdProfileHandlerOptions,\n) {\n const { profileRepo, podLookupRepo } = options;\n const profile = await profileRepo.get(username);\n if (!profile) {\n return null;\n }\n\n if (profile.storageUrl || !profile.accountId || !podLookupRepo) {\n return profile;\n }\n\n let pods: PodLookupResult[];\n try {\n pods = await podLookupRepo.listByAccountId(profile.accountId);\n } catch (error) {\n logger.warn(`Skipped storage backfill for ${username}: pod index unavailable for account ${profile.accountId}: ${error}`);\n return profile;\n }\n const storageUrl = selectStorageBackfillCandidate(username, pods);\n if (!storageUrl) {\n logger.warn(`Skipped storage backfill for ${username}: no unambiguous pod found for account ${profile.accountId}`);\n return profile;\n }\n\n try {\n const updated = await profileRepo.updateStorage(username, {\n storageUrl,\n storageMode: profile.storageMode,\n });\n if (updated) {\n logger.info(`Backfilled storage for ${username}: ${storageUrl}`);\n return updated;\n }\n } catch (error) {\n logger.warn(`Failed to backfill storage for ${username}: ${error}`);\n }\n\n return profile;\n}\n\nfunction selectStorageBackfillCandidate(\n username: string,\n pods: PodLookupResult[],\n): string | null {\n if (pods.length === 0) {\n return null;\n }\n\n const exactMatches = pods.filter((pod) => derivePodSlug(pod.baseUrl) === username);\n if (exactMatches.length === 1) {\n return ensureTrailingSlash(exactMatches[0].baseUrl);\n }\n\n if (exactMatches.length > 1) {\n return null;\n }\n\n if (pods.length === 1) {\n return ensureTrailingSlash(pods[0].baseUrl);\n }\n\n return null;\n}\n\nfunction derivePodSlug(baseUrl: string): string | null {\n try {\n const parsed = new URL(baseUrl);\n const [slug] = parsed.pathname.split('/').filter(Boolean);\n return slug || null;\n } catch {\n return null;\n }\n}\n\nfunction ensureTrailingSlash(url: string): string {\n return url.replace(/\\/+$/, '') + '/';\n}\n\nfunction deriveOrigin(url: string): string | undefined {\n try {\n return ensureTrailingSlash(new URL(url).origin);\n } catch {\n return undefined;\n }\n}\n\nasync function readJsonBody(request: IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let data = '';\n request.setEncoding('utf8');\n request.on('data', (chunk: string) => {\n data += chunk;\n });\n request.on('end', () => {\n if (!data) {\n resolve(undefined);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n resolve(undefined);\n }\n });\n request.on('error', reject);\n });\n}\n\nfunction sendJson(response: ServerResponse, status: number, data: unknown): void {\n response.statusCode = status;\n response.setHeader('Content-Type', 'application/json');\n response.end(JSON.stringify(data));\n}\n\nfunction sendError(response: ServerResponse, status: number, message: string): void {\n sendJson(response, status, { error: message });\n}\n"]}
@@ -55,16 +55,21 @@ async function startBackgroundServices(container, logger) {
55
55
  logger.error(`Failed to initialize DdnsManager: ${error}`);
56
56
  }
57
57
  try {
58
- const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
59
58
  const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true });
60
- if (!localNetworkManager && localTunnelProvider) {
61
- logger.info('Starting Cloudflare Tunnel (standalone mode)...');
62
- await localTunnelProvider.start();
63
- logger.info('Cloudflare Tunnel started');
59
+ if (localTunnelProvider) {
60
+ logger.info('Starting local tunnel provider...');
61
+ const localPort = Number.parseInt(process.env.XPOD_MAIN_PORT ?? process.env.CSS_PORT ?? process.env.PORT ?? '3000', 10);
62
+ const config = await localTunnelProvider.setup({
63
+ subdomain: 'local',
64
+ localPort: Number.isFinite(localPort) && localPort > 0 ? localPort : 3000,
65
+ localProtocol: 'http',
66
+ });
67
+ await localTunnelProvider.start(config);
68
+ logger.info('Local tunnel provider started');
64
69
  }
65
70
  }
66
71
  catch (error) {
67
- logger.error(`Failed to start Cloudflare Tunnel: ${error}`);
72
+ logger.error(`Failed to start local tunnel provider: ${error}`);
68
73
  }
69
74
  }
70
75
  async function stopBackgroundServices(container) {
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/api/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { asValue, type AwilixContainer } from 'awilix';\nimport { setGlobalLoggerFactory, getLoggerFor } from 'global-logger-factory';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\nimport { createApiContainer, loadConfigFromEnv, type ApiContainerConfig, type ApiContainerCradle } from './container';\nimport { registerRoutes } from './container/routes';\nimport type { AuthContext } from './auth/AuthContext';\nimport { OpenAuthMiddleware } from './middleware/OpenAuthMiddleware';\nimport type { RuntimeHost } from '../runtime/host/types';\n\nexport interface StartApiServiceOptions {\n config?: ApiContainerConfig;\n open?: boolean;\n authContext?: AuthContext;\n initializeLogger?: boolean;\n runtimeHost?: RuntimeHost;\n}\n\nexport interface ApiServiceHandle {\n config: ApiContainerConfig;\n container: AwilixContainer<ApiContainerCradle>;\n stop: () => Promise<void>;\n}\n\nfunction initApiLogger(): void {\n const loggerFactory = new ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {\n fileName: './logs/xpod-%DATE%.log',\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n}\n\nasync function registerPrimaryServiceToken(\n container: AwilixContainer<ApiContainerCradle>,\n config: ApiContainerConfig,\n logger: ReturnType<typeof getLoggerFor>,\n): Promise<void> {\n try {\n const serviceToken = process.env.XPOD_SERVICE_TOKEN;\n if (!serviceToken) {\n return;\n }\n\n const serviceTokenRepo = container.resolve('serviceTokenRepo') as any;\n const serviceType = config.edition === 'cloud' ? 'cloud' : 'local';\n const serviceId = process.env.XPOD_NODE_ID || (config.edition === 'cloud' ? 'cloud-1' : 'local-1');\n\n await serviceTokenRepo.registerToken(serviceToken, {\n serviceType,\n serviceId,\n scopes: ['quota:write', 'usage:read', 'account:manage'],\n });\n\n logger.info(`Registered service token for ${serviceType}:${serviceId}`);\n } catch (error) {\n logger.error(`Failed to register service token: ${error}`);\n }\n}\n\nasync function startBackgroundServices(\n container: AwilixContainer<ApiContainerCradle>,\n logger: ReturnType<typeof getLoggerFor>,\n): Promise<void> {\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true }) as any;\n if (localNetworkManager) {\n localNetworkManager.start();\n }\n } catch (error) {\n logger.error(`Failed to initialize LocalNetworkManager: ${error}`);\n }\n\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n if (ddnsManager) {\n await ddnsManager.start();\n logger.info('DDNS Manager started');\n }\n } catch (error) {\n logger.error(`Failed to initialize DdnsManager: ${error}`);\n }\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n\n if (!localNetworkManager && localTunnelProvider) {\n logger.info('Starting Cloudflare Tunnel (standalone mode)...');\n await localTunnelProvider.start();\n logger.info('Cloudflare Tunnel started');\n }\n } catch (error) {\n logger.error(`Failed to start Cloudflare Tunnel: ${error}`);\n }\n}\n\nasync function stopBackgroundServices(container: AwilixContainer<ApiContainerCradle>): Promise<void> {\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n ddnsManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n await localNetworkManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n await localTunnelProvider?.stop();\n } catch {\n // ignore shutdown errors\n }\n}\n\nexport async function startApiService(options: StartApiServiceOptions = {}): Promise<ApiServiceHandle> {\n if (options.initializeLogger !== false) {\n initApiLogger();\n }\n\n const baseConfig = options.config ?? loadConfigFromEnv();\n const config = {\n ...baseConfig,\n runtimeHost: options.runtimeHost ?? baseConfig.runtimeHost,\n };\n const logger = getLoggerFor('ApiRuntime');\n\n if (!config.databaseUrl) {\n throw new Error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');\n }\n\n logger.info(`Starting API Service (edition: ${config.edition})...`);\n\n const container = createApiContainer(config);\n\n if (options.open) {\n container.register({\n authMiddleware: asValue(new OpenAuthMiddleware({ context: options.authContext })),\n });\n }\n\n registerRoutes(container);\n await registerPrimaryServiceToken(container, config, logger);\n await startBackgroundServices(container, logger);\n\n const server = container.resolve('apiServer');\n await server.start();\n logger.info(`API Service active on ${config.socketPath ? `unix://${config.socketPath}` : `${config.host}:${config.port}`}`);\n\n return {\n config,\n container,\n stop: async(): Promise<void> => {\n logger.info('Stopping API Service...');\n await stopBackgroundServices(container);\n await server.stop();\n },\n };\n}\n"]}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/api/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { asValue, type AwilixContainer } from 'awilix';\nimport { setGlobalLoggerFactory, getLoggerFor } from 'global-logger-factory';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\nimport { createApiContainer, loadConfigFromEnv, type ApiContainerConfig, type ApiContainerCradle } from './container';\nimport { registerRoutes } from './container/routes';\nimport type { AuthContext } from './auth/AuthContext';\nimport { OpenAuthMiddleware } from './middleware/OpenAuthMiddleware';\nimport type { RuntimeHost } from '../runtime/host/types';\n\nexport interface StartApiServiceOptions {\n config?: ApiContainerConfig;\n open?: boolean;\n authContext?: AuthContext;\n initializeLogger?: boolean;\n runtimeHost?: RuntimeHost;\n}\n\nexport interface ApiServiceHandle {\n config: ApiContainerConfig;\n container: AwilixContainer<ApiContainerCradle>;\n stop: () => Promise<void>;\n}\n\nfunction initApiLogger(): void {\n const loggerFactory = new ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {\n fileName: './logs/xpod-%DATE%.log',\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n}\n\nasync function registerPrimaryServiceToken(\n container: AwilixContainer<ApiContainerCradle>,\n config: ApiContainerConfig,\n logger: ReturnType<typeof getLoggerFor>,\n): Promise<void> {\n try {\n const serviceToken = process.env.XPOD_SERVICE_TOKEN;\n if (!serviceToken) {\n return;\n }\n\n const serviceTokenRepo = container.resolve('serviceTokenRepo') as any;\n const serviceType = config.edition === 'cloud' ? 'cloud' : 'local';\n const serviceId = process.env.XPOD_NODE_ID || (config.edition === 'cloud' ? 'cloud-1' : 'local-1');\n\n await serviceTokenRepo.registerToken(serviceToken, {\n serviceType,\n serviceId,\n scopes: ['quota:write', 'usage:read', 'account:manage'],\n });\n\n logger.info(`Registered service token for ${serviceType}:${serviceId}`);\n } catch (error) {\n logger.error(`Failed to register service token: ${error}`);\n }\n}\n\nasync function startBackgroundServices(\n container: AwilixContainer<ApiContainerCradle>,\n logger: ReturnType<typeof getLoggerFor>,\n): Promise<void> {\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true }) as any;\n if (localNetworkManager) {\n localNetworkManager.start();\n }\n } catch (error) {\n logger.error(`Failed to initialize LocalNetworkManager: ${error}`);\n }\n\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n if (ddnsManager) {\n await ddnsManager.start();\n logger.info('DDNS Manager started');\n }\n } catch (error) {\n logger.error(`Failed to initialize DdnsManager: ${error}`);\n }\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n\n if (localTunnelProvider) {\n logger.info('Starting local tunnel provider...');\n const localPort = Number.parseInt(\n process.env.XPOD_MAIN_PORT ?? process.env.CSS_PORT ?? process.env.PORT ?? '3000',\n 10,\n );\n const config = await localTunnelProvider.setup({\n subdomain: 'local',\n localPort: Number.isFinite(localPort) && localPort > 0 ? localPort : 3000,\n localProtocol: 'http',\n });\n await localTunnelProvider.start(config);\n logger.info('Local tunnel provider started');\n }\n } catch (error) {\n logger.error(`Failed to start local tunnel provider: ${error}`);\n }\n}\n\nasync function stopBackgroundServices(container: AwilixContainer<ApiContainerCradle>): Promise<void> {\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n ddnsManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n await localNetworkManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n await localTunnelProvider?.stop();\n } catch {\n // ignore shutdown errors\n }\n}\n\nexport async function startApiService(options: StartApiServiceOptions = {}): Promise<ApiServiceHandle> {\n if (options.initializeLogger !== false) {\n initApiLogger();\n }\n\n const baseConfig = options.config ?? loadConfigFromEnv();\n const config = {\n ...baseConfig,\n runtimeHost: options.runtimeHost ?? baseConfig.runtimeHost,\n };\n const logger = getLoggerFor('ApiRuntime');\n\n if (!config.databaseUrl) {\n throw new Error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');\n }\n\n logger.info(`Starting API Service (edition: ${config.edition})...`);\n\n const container = createApiContainer(config);\n\n if (options.open) {\n container.register({\n authMiddleware: asValue(new OpenAuthMiddleware({ context: options.authContext })),\n });\n }\n\n registerRoutes(container);\n await registerPrimaryServiceToken(container, config, logger);\n await startBackgroundServices(container, logger);\n\n const server = container.resolve('apiServer');\n await server.start();\n logger.info(`API Service active on ${config.socketPath ? `unix://${config.socketPath}` : `${config.host}:${config.port}`}`);\n\n return {\n config,\n container,\n stop: async(): Promise<void> => {\n logger.info('Stopping API Service...');\n await stopBackgroundServices(container);\n await server.stop();\n },\n };\n}\n"]}
@@ -83,6 +83,7 @@
83
83
  "undefineds:dist/storage/locking/UrlAwareRedisLocker.jsonld",
84
84
  "undefineds:dist/provision/ProvisionPodCreator.jsonld",
85
85
  "undefineds:dist/provision/ProvisionCodeCodec.jsonld",
86
+ "undefineds:dist/provision/LocalPodProvisioningService.jsonld",
86
87
  "undefineds:dist/authorization/AuthModeSelector.jsonld"
87
88
  ]
88
89
  }
@@ -1911,6 +1911,42 @@
1911
1911
  }
1912
1912
  }
1913
1913
  },
1914
+ "LocalPodProvisioningService": {
1915
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService",
1916
+ "@prefix": true,
1917
+ "@context": {
1918
+ "options_baseUrl": {
1919
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_baseUrl"
1920
+ },
1921
+ "options_rootDir": {
1922
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_rootDir"
1923
+ },
1924
+ "options_sparqlEndpoint": {
1925
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_sparqlEndpoint"
1926
+ },
1927
+ "options_identityDbUrl": {
1928
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_identityDbUrl"
1929
+ },
1930
+ "options_oidcIssuer": {
1931
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_oidcIssuer"
1932
+ },
1933
+ "baseUrl": {
1934
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_baseUrl"
1935
+ },
1936
+ "rootDir": {
1937
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_rootDir"
1938
+ },
1939
+ "sparqlEndpoint": {
1940
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_sparqlEndpoint"
1941
+ },
1942
+ "identityDbUrl": {
1943
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_identityDbUrl"
1944
+ },
1945
+ "oidcIssuer": {
1946
+ "@id": "undefineds:dist/provision/LocalPodProvisioningService.jsonld#LocalPodProvisioningService_options_oidcIssuer"
1947
+ }
1948
+ }
1949
+ },
1914
1950
  "AuthModeSelector": {
1915
1951
  "@id": "undefineds:dist/authorization/AuthModeSelector.jsonld#AuthModeSelector",
1916
1952
  "@prefix": true,
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Credential = exports.OAuthCredential = exports.ApiKeyCredential = void 0;
4
4
  const models_1 = require("@undefineds.co/models");
5
- exports.ApiKeyCredential = models_1.apiKeyCredentialTable;
6
- exports.OAuthCredential = models_1.oauthCredentialTable;
7
- exports.Credential = models_1.credentialTable;
5
+ exports.ApiKeyCredential = models_1.apiKeyCredentialResource;
6
+ exports.OAuthCredential = models_1.oauthCredentialResource;
7
+ exports.Credential = models_1.credentialResource;
8
8
  //# sourceMappingURL=tables.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../../src/credential/schema/tables.ts"],"names":[],"mappings":";;;AAAA,kDAI+B;AAElB,QAAA,gBAAgB,GAAG,8BAA4B,CAAC;AAChD,QAAA,eAAe,GAAG,6BAA2B,CAAC;AAC9C,QAAA,UAAU,GAAG,wBAAsB,CAAC","sourcesContent":["import {\n apiKeyCredentialTable,\n credentialTable,\n oauthCredentialTable,\n} from '@undefineds.co/models';\n\nexport const ApiKeyCredential = apiKeyCredentialTable as any;\nexport const OAuthCredential = oauthCredentialTable as any;\nexport const Credential = credentialTable as any;\n\nexport type ApiKeyCredentialRow = typeof ApiKeyCredential.$inferSelect;\nexport type ApiKeyCredentialInsert = typeof ApiKeyCredential.$inferInsert;\nexport type OAuthCredentialRow = typeof OAuthCredential.$inferSelect;\nexport type OAuthCredentialInsert = typeof OAuthCredential.$inferInsert;\nexport type CredentialRow = typeof Credential.$inferSelect;\nexport type CredentialInsert = typeof Credential.$inferInsert;\n"]}
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../../src/credential/schema/tables.ts"],"names":[],"mappings":";;;AAAA,kDAI+B;AAElB,QAAA,gBAAgB,GAAG,iCAA+B,CAAC;AACnD,QAAA,eAAe,GAAG,gCAA8B,CAAC;AACjD,QAAA,UAAU,GAAG,2BAAyB,CAAC","sourcesContent":["import {\n apiKeyCredentialResource,\n credentialResource,\n oauthCredentialResource,\n} from '@undefineds.co/models';\n\nexport const ApiKeyCredential = apiKeyCredentialResource as any;\nexport const OAuthCredential = oauthCredentialResource as any;\nexport const Credential = credentialResource as any;\n\nexport type ApiKeyCredentialRow = typeof ApiKeyCredential.$inferSelect;\nexport type ApiKeyCredentialInsert = typeof ApiKeyCredential.$inferInsert;\nexport type OAuthCredentialRow = typeof OAuthCredential.$inferSelect;\nexport type OAuthCredentialInsert = typeof OAuthCredential.$inferInsert;\nexport type CredentialRow = typeof Credential.$inferSelect;\nexport type CredentialInsert = typeof Credential.$inferInsert;\n"]}
@@ -1,11 +1,8 @@
1
1
  import type { EdgeNodeCapabilityDetector } from './EdgeNodeCapabilityDetector';
2
2
  import type { EdgeNodeDnsCoordinator } from './EdgeNodeDnsCoordinator';
3
- import type { TunnelProvider } from '../tunnel/TunnelProvider';
4
3
  export interface LocalNetworkManagerOptions {
5
4
  detector: EdgeNodeCapabilityDetector;
6
5
  dnsCoordinator: EdgeNodeDnsCoordinator;
7
- tunnelProvider?: TunnelProvider;
8
- localPort?: number;
9
6
  intervalMs?: number;
10
7
  }
11
8
  /**
@@ -16,15 +13,13 @@ export interface LocalNetworkManagerOptions {
16
13
  *
17
14
  * 逻辑:
18
15
  * 1. 优先探测公网 IP (IPv6 > IPv4)。
19
- * 2. 如果有公网 IP -> 停止 Tunnel -> 更新 AAAA/A 记录。
20
- * 3. 如果无公网 IP -> 启动 Tunnel (Fallback) -> Tunnel 接管 CNAME。
16
+ * 2. 如果有公网 IP -> 更新 AAAA/A 记录。
17
+ * 3. 如果无公网 IP -> 维持本机/局域网可用,不触发隧道启停。
21
18
  */
22
19
  export declare class LocalNetworkManager {
23
20
  private readonly logger;
24
21
  private readonly detector;
25
22
  private readonly dnsCoordinator;
26
- private readonly tunnelProvider?;
27
- private readonly localPort;
28
23
  private readonly intervalMs;
29
24
  private interval?;
30
25
  private lastState;
@@ -10,8 +10,8 @@ const global_logger_factory_1 = require("global-logger-factory");
10
10
  *
11
11
  * 逻辑:
12
12
  * 1. 优先探测公网 IP (IPv6 > IPv4)。
13
- * 2. 如果有公网 IP -> 停止 Tunnel -> 更新 AAAA/A 记录。
14
- * 3. 如果无公网 IP -> 启动 Tunnel (Fallback) -> Tunnel 接管 CNAME。
13
+ * 2. 如果有公网 IP -> 更新 AAAA/A 记录。
14
+ * 3. 如果无公网 IP -> 维持本机/局域网可用,不触发隧道启停。
15
15
  */
16
16
  class LocalNetworkManager {
17
17
  constructor(options) {
@@ -19,12 +19,9 @@ class LocalNetworkManager {
19
19
  // 状态追踪,用于减少重复日志
20
20
  this.lastState = {
21
21
  hasPublicIp: false,
22
- tunnelRunning: false,
23
22
  };
24
23
  this.detector = options.detector;
25
24
  this.dnsCoordinator = options.dnsCoordinator;
26
- this.tunnelProvider = options.tunnelProvider;
27
- this.localPort = options.localPort ?? 3000;
28
25
  this.intervalMs = options.intervalMs ?? 60_000; // 默认 1 分钟
29
26
  }
30
27
  /**
@@ -47,11 +44,7 @@ class LocalNetworkManager {
47
44
  clearInterval(this.interval);
48
45
  this.interval = undefined;
49
46
  }
50
- // 确保退出时关闭 Tunnel,防止僵尸进程
51
- if (this.tunnelProvider?.getStatus().running) {
52
- this.logger.info('Stopping tunnel before exit...');
53
- await this.tunnelProvider.stop();
54
- }
47
+ // 不管理 tunnel 生命周期
55
48
  }
56
49
  async runMaintenance() {
57
50
  try {
@@ -66,45 +59,25 @@ class LocalNetworkManager {
66
59
  subdomain: '@',
67
60
  };
68
61
  const hasPublicIp = !!(metadata.ipv4 || metadata.ipv6);
69
- const tunnelRunning = !!this.tunnelProvider?.getStatus().running;
70
62
  // 检查状态是否发生变化
71
- const stateChanged = hasPublicIp !== this.lastState.hasPublicIp ||
72
- tunnelRunning !== this.lastState.tunnelRunning;
63
+ const stateChanged = hasPublicIp !== this.lastState.hasPublicIp;
73
64
  if (stateChanged) {
74
- this.logger.info(`Network status changed: IP=${hasPublicIp ? 'Public' : 'Private'}, Tunnel=${tunnelRunning ? 'Running' : 'Stopped'} (IPv4=${metadata.ipv4 || 'none'}, IPv6=${metadata.ipv6 || 'none'})`);
65
+ this.logger.info(`Network status changed: IP=${hasPublicIp ? 'Public' : 'Private'} (IPv4=${metadata.ipv4 || 'none'}, IPv6=${metadata.ipv6 || 'none'})`);
75
66
  }
76
67
  else {
77
68
  // 平时仅打印一条极简的调试信息(如果级别设为 info 则每分钟一条)
78
- this.logger.debug(`Status check: IP=${hasPublicIp ? 'Public' : 'Private'}, Tunnel=${tunnelRunning ? 'Running' : 'Stopped'}`);
69
+ this.logger.debug(`Status check: IP=${hasPublicIp ? 'Public' : 'Private'}`);
79
70
  }
80
71
  if (hasPublicIp) {
81
72
  // === 直连模式 ===
82
- if (tunnelRunning) {
83
- this.logger.info('Stopping tunnel fallback to use direct public IP...');
84
- await this.tunnelProvider.stop();
85
- this.lastState.tunnelRunning = false;
86
- }
87
73
  // 仅在 IP 变化或初次运行且有 IP 时同步 DNS
88
74
  await this.dnsCoordinator.synchronize('local-self', metadata);
89
75
  }
90
76
  else {
91
- // === 隧道模式 (Fallback) ===
92
- if (this.tunnelProvider) {
93
- if (!tunnelRunning) {
94
- this.logger.info('No public IP. Starting Cloudflare Tunnel fallback...');
95
- const config = await this.tunnelProvider.setup({
96
- subdomain: 'local',
97
- localPort: this.localPort,
98
- });
99
- await this.tunnelProvider.start(config);
100
- this.logger.info('Tunnel fallback active.');
101
- this.lastState.tunnelRunning = true;
102
- }
103
- }
77
+ this.logger.info('No public IP. Keep local and LAN routes active; tunnel is managed by the runtime provider if configured.');
104
78
  }
105
79
  // 更新状态追踪
106
80
  this.lastState.hasPublicIp = hasPublicIp;
107
- this.lastState.tunnelRunning = !!this.tunnelProvider?.getStatus().running;
108
81
  }
109
82
  catch (error) {
110
83
  this.logger.error(`Maintenance task failed: ${error.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"LocalNetworkManager.js","sourceRoot":"","sources":["../../src/edge/LocalNetworkManager.ts"],"names":[],"mappings":";;;AAAA,iEAAqD;AAarD;;;;;;;;;;GAUG;AACH,MAAa,mBAAmB;IAe9B,YAAmB,OAAmC;QAdrC,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAQ7C,gBAAgB;QACR,cAAS,GAAG;YAClB,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,KAAK;SACrB,CAAC;QAGA,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC,UAAU;IAC5D,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;QAE9E,gBAAgB;QAChB,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5E,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,IAAI;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;QAED,wBAAwB;QACxB,IAAI,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAEzD,aAAa;YACb,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,sBAAsB,EAAE,CAAC;YAE7D,sBAAsB;YACtB,MAAM,QAAQ,GAA4B;gBACxC,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,UAAU,EAAE,QAAQ;gBACpB,SAAS,EAAE,GAAG;aACf,CAAC;YAEF,MAAM,WAAW,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC;YAEjE,aAAa;YACb,MAAM,YAAY,GAAG,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW;gBAC1C,aAAa,KAAK,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;YAEpE,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,YAAY,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,UAAU,QAAQ,CAAC,IAAI,IAAI,MAAM,UAAU,QAAQ,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC;YAC3M,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,YAAY,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC/H,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,eAAe;gBACf,IAAI,aAAa,EAAE,CAAC;oBAClB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;oBACxE,MAAM,IAAI,CAAC,cAAe,CAAC,IAAI,EAAE,CAAC;oBAClC,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,KAAK,CAAC;gBACvC,CAAC;gBAED,6BAA6B;gBAC7B,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAEhE,CAAC;iBAAM,CAAC;gBACN,0BAA0B;gBAC1B,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;oBACxB,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;wBACzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;4BAC7C,SAAS,EAAE,OAAO;4BAClB,SAAS,EAAE,IAAI,CAAC,SAAS;yBAC1B,CAAC,CAAC;wBAEH,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;wBACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;wBAC5C,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC;oBACtC,CAAC;gBACH,CAAC;YACH,CAAC;YAED,SAAS;YACT,IAAI,CAAC,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC;QAE5E,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA6B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF;AAtHD,kDAsHC","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport type { EdgeNodeCapabilityDetector } from './EdgeNodeCapabilityDetector';\nimport type { EdgeNodeDnsCoordinator } from './EdgeNodeDnsCoordinator';\nimport type { TunnelProvider } from '../tunnel/TunnelProvider';\n\nexport interface LocalNetworkManagerOptions {\n detector: EdgeNodeCapabilityDetector;\n dnsCoordinator: EdgeNodeDnsCoordinator;\n tunnelProvider?: TunnelProvider;\n localPort?: number;\n intervalMs?: number;\n}\n\n/**\n * 本地网络管理器\n * \n * 专门用于 Local 模式,定期探测本机 IP 并自动同步到 DNS。\n * 它是“自闭环”的,不依赖外部心跳。\n * \n * 逻辑:\n * 1. 优先探测公网 IP (IPv6 > IPv4)。\n * 2. 如果有公网 IP -> 停止 Tunnel -> 更新 AAAA/A 记录。\n * 3. 如果无公网 IP -> 启动 Tunnel (Fallback) -> Tunnel 接管 CNAME。\n */\nexport class LocalNetworkManager {\n private readonly logger = getLoggerFor(this);\n private readonly detector: EdgeNodeCapabilityDetector;\n private readonly dnsCoordinator: EdgeNodeDnsCoordinator;\n private readonly tunnelProvider?: TunnelProvider;\n private readonly localPort: number;\n private readonly intervalMs: number;\n private interval?: NodeJS.Timeout;\n \n // 状态追踪,用于减少重复日志\n private lastState = {\n hasPublicIp: false,\n tunnelRunning: false,\n };\n\n public constructor(options: LocalNetworkManagerOptions) {\n this.detector = options.detector;\n this.dnsCoordinator = options.dnsCoordinator;\n this.tunnelProvider = options.tunnelProvider;\n this.localPort = options.localPort ?? 3000;\n this.intervalMs = options.intervalMs ?? 60_000; // 默认 1 分钟\n }\n\n /**\n * 启动管理循环\n */\n public start(): void {\n if (this.interval) {\n return;\n }\n this.logger.info(`Starting background loop (interval: ${this.intervalMs}ms)`);\n \n // 立即执行一次,然后开始循环\n void this.runMaintenance();\n this.interval = setInterval(() => this.runMaintenance(), this.intervalMs);\n }\n\n /**\n * 停止\n */\n public async stop(): Promise<void> {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = undefined;\n }\n \n // 确保退出时关闭 Tunnel,防止僵尸进程\n if (this.tunnelProvider?.getStatus().running) {\n this.logger.info('Stopping tunnel before exit...');\n await this.tunnelProvider.stop();\n }\n }\n\n private async runMaintenance(): Promise<void> {\n try {\n this.logger.debug('Starting network detection phase...');\n \n // 1. 探测本机 IP\n const netInfo = await this.detector.detectNetworkAddresses();\n \n // 2. 构造元数据 (只使用公网 IP)\n const metadata: Record<string, unknown> = {\n ipv4: netInfo.ipv4Public,\n ipv6: netInfo.ipv6Public,\n accessMode: 'direct',\n subdomain: '@', \n };\n\n const hasPublicIp = !!(metadata.ipv4 || metadata.ipv6);\n const tunnelRunning = !!this.tunnelProvider?.getStatus().running;\n \n // 检查状态是否发生变化\n const stateChanged = hasPublicIp !== this.lastState.hasPublicIp || \n tunnelRunning !== this.lastState.tunnelRunning;\n\n if (stateChanged) {\n this.logger.info(`Network status changed: IP=${hasPublicIp ? 'Public' : 'Private'}, Tunnel=${tunnelRunning ? 'Running' : 'Stopped'} (IPv4=${metadata.ipv4 || 'none'}, IPv6=${metadata.ipv6 || 'none'})`);\n } else {\n // 平时仅打印一条极简的调试信息(如果级别设为 info 则每分钟一条)\n this.logger.debug(`Status check: IP=${hasPublicIp ? 'Public' : 'Private'}, Tunnel=${tunnelRunning ? 'Running' : 'Stopped'}`);\n }\n\n if (hasPublicIp) {\n // === 直连模式 ===\n if (tunnelRunning) {\n this.logger.info('Stopping tunnel fallback to use direct public IP...');\n await this.tunnelProvider!.stop();\n this.lastState.tunnelRunning = false;\n }\n\n // 仅在 IP 变化或初次运行且有 IP 时同步 DNS\n await this.dnsCoordinator.synchronize('local-self', metadata);\n\n } else {\n // === 隧道模式 (Fallback) ===\n if (this.tunnelProvider) {\n if (!tunnelRunning) {\n this.logger.info('No public IP. Starting Cloudflare Tunnel fallback...');\n const config = await this.tunnelProvider.setup({\n subdomain: 'local',\n localPort: this.localPort,\n });\n \n await this.tunnelProvider.start(config);\n this.logger.info('Tunnel fallback active.');\n this.lastState.tunnelRunning = true;\n }\n }\n }\n \n // 更新状态追踪\n this.lastState.hasPublicIp = hasPublicIp;\n this.lastState.tunnelRunning = !!this.tunnelProvider?.getStatus().running;\n \n } catch (error: unknown) {\n this.logger.error(`Maintenance task failed: ${(error as Error).message}`);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"LocalNetworkManager.js","sourceRoot":"","sources":["../../src/edge/LocalNetworkManager.ts"],"names":[],"mappings":";;;AAAA,iEAAqD;AAUrD;;;;;;;;;;GAUG;AACH,MAAa,mBAAmB;IAY9B,YAAmB,OAAmC;QAXrC,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAM7C,gBAAgB;QACR,cAAS,GAAG;YAClB,WAAW,EAAE,KAAK;SACnB,CAAC;QAGA,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC,UAAU;IAC5D,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC;QAE9E,gBAAgB;QAChB,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5E,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,IAAI;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;QAED,kBAAkB;IACpB,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAEzD,aAAa;YACb,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,sBAAsB,EAAE,CAAC;YAE7D,sBAAsB;YACtB,MAAM,QAAQ,GAA4B;gBACxC,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,IAAI,EAAE,OAAO,CAAC,UAAU;gBACxB,UAAU,EAAE,QAAQ;gBACpB,SAAS,EAAE,GAAG;aACf,CAAC;YAEF,MAAM,WAAW,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEvD,aAAa;YACb,MAAM,YAAY,GAAG,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;YAEhE,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,UAAU,QAAQ,CAAC,IAAI,IAAI,MAAM,UAAU,QAAQ,CAAC,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC;YAC1J,CAAC;iBAAM,CAAC;gBACN,qCAAqC;gBACrC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,eAAe;gBACf,6BAA6B;gBAC7B,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAEhE,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0GAA0G,CAAC,CAAC;YAC/H,CAAC;YAED,SAAS;YACT,IAAI,CAAC,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;QAE3C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA6B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF;AAvFD,kDAuFC","sourcesContent":["import { getLoggerFor } from 'global-logger-factory';\nimport type { EdgeNodeCapabilityDetector } from './EdgeNodeCapabilityDetector';\nimport type { EdgeNodeDnsCoordinator } from './EdgeNodeDnsCoordinator';\n\nexport interface LocalNetworkManagerOptions {\n detector: EdgeNodeCapabilityDetector;\n dnsCoordinator: EdgeNodeDnsCoordinator;\n intervalMs?: number;\n}\n\n/**\n * 本地网络管理器\n * \n * 专门用于 Local 模式,定期探测本机 IP 并自动同步到 DNS。\n * 它是“自闭环”的,不依赖外部心跳。\n * \n * 逻辑:\n * 1. 优先探测公网 IP (IPv6 > IPv4)。\n * 2. 如果有公网 IP -> 更新 AAAA/A 记录。\n * 3. 如果无公网 IP -> 维持本机/局域网可用,不触发隧道启停。\n */\nexport class LocalNetworkManager {\n private readonly logger = getLoggerFor(this);\n private readonly detector: EdgeNodeCapabilityDetector;\n private readonly dnsCoordinator: EdgeNodeDnsCoordinator;\n private readonly intervalMs: number;\n private interval?: NodeJS.Timeout;\n \n // 状态追踪,用于减少重复日志\n private lastState = {\n hasPublicIp: false,\n };\n\n public constructor(options: LocalNetworkManagerOptions) {\n this.detector = options.detector;\n this.dnsCoordinator = options.dnsCoordinator;\n this.intervalMs = options.intervalMs ?? 60_000; // 默认 1 分钟\n }\n\n /**\n * 启动管理循环\n */\n public start(): void {\n if (this.interval) {\n return;\n }\n this.logger.info(`Starting background loop (interval: ${this.intervalMs}ms)`);\n \n // 立即执行一次,然后开始循环\n void this.runMaintenance();\n this.interval = setInterval(() => this.runMaintenance(), this.intervalMs);\n }\n\n /**\n * 停止\n */\n public async stop(): Promise<void> {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = undefined;\n }\n \n // 不管理 tunnel 生命周期\n }\n\n private async runMaintenance(): Promise<void> {\n try {\n this.logger.debug('Starting network detection phase...');\n \n // 1. 探测本机 IP\n const netInfo = await this.detector.detectNetworkAddresses();\n \n // 2. 构造元数据 (只使用公网 IP)\n const metadata: Record<string, unknown> = {\n ipv4: netInfo.ipv4Public,\n ipv6: netInfo.ipv6Public,\n accessMode: 'direct',\n subdomain: '@', \n };\n\n const hasPublicIp = !!(metadata.ipv4 || metadata.ipv6);\n \n // 检查状态是否发生变化\n const stateChanged = hasPublicIp !== this.lastState.hasPublicIp;\n\n if (stateChanged) {\n this.logger.info(`Network status changed: IP=${hasPublicIp ? 'Public' : 'Private'} (IPv4=${metadata.ipv4 || 'none'}, IPv6=${metadata.ipv6 || 'none'})`);\n } else {\n // 平时仅打印一条极简的调试信息(如果级别设为 info 则每分钟一条)\n this.logger.debug(`Status check: IP=${hasPublicIp ? 'Public' : 'Private'}`);\n }\n\n if (hasPublicIp) {\n // === 直连模式 ===\n // 仅在 IP 变化或初次运行且有 IP 时同步 DNS\n await this.dnsCoordinator.synchronize('local-self', metadata);\n\n } else {\n this.logger.info('No public IP. Keep local and LAN routes active; tunnel is managed by the runtime provider if configured.');\n }\n \n // 更新状态追踪\n this.lastState.hasPublicIp = hasPublicIp;\n \n } catch (error: unknown) {\n this.logger.error(`Maintenance task failed: ${(error as Error).message}`);\n }\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -70,6 +70,7 @@ import { AutoDetectIdentityProviderHandler } from './identity/oidc/AutoDetectIde
70
70
  import { LoopbackClientIdAdapterFactory } from './identity/oidc/LoopbackClientIdAdapterFactory';
71
71
  import { ProvisionPodCreator } from './provision/ProvisionPodCreator';
72
72
  import { ProvisionCodeCodec } from './provision/ProvisionCodeCodec';
73
+ import { LocalPodProvisioningService } from './provision/LocalPodProvisioningService';
73
74
  import { AuthModeSelector } from './authorization/AuthModeSelector';
74
75
  export type { DnsProvider, ListDnsRecordsInput, ListableDnsProvider, DeleteDnsRecordInput, DnsRecordSummary, UpsertDnsRecordInput, } from './dns/DnsProvider';
75
76
  export type { EdgeNodeCertificateProvisioner } from './edge/EdgeNodeCertificateProvisioner';
@@ -79,4 +80,4 @@ export type { EntitlementProvider, AccountEntitlement } from './quota/Entitlemen
79
80
  export type { TunnelProvider, TunnelConfig, TunnelSetupOptions, TunnelStatus, } from './tunnel/TunnelProvider';
80
81
  export type { SubdomainRegistration, ConnectivityResult, SubdomainServiceOptions, } from './subdomain/SubdomainService';
81
82
  export { AppStaticAssetHandler } from './http/AppStaticAssetHandler';
82
- export { RepresentationPartialConvertingStore, MinioDataAccessor, QuadstoreSparqlDataAccessor, QuintStoreSparqlDataAccessor, MixDataAccessor, ConfigurableLoggerFactory, SparqlUpdateResourceStore, SubgraphQueryEngine, QuadstoreSparqlEngine, QuintstoreSparqlEngine, SubgraphSparqlHttpHandler, QuotaAdminHttpHandler, ClusterIngressRouter, ClusterWebSocketConfigurator, EdgeNodeDirectDebugHttpHandler, EdgeNodeProxyHttpHandler, RouterHttpHandler, RouterHttpRoute, TracingHandler, EdgeNodeCertificateHttpHandler, TerminalHttpHandler, ReservedSuffixIdentifierGenerator, DrizzleIndexedStorage, WebIdProfileRepository, PostgresKeyValueStorage, RedisKeyValueStorage, SqliteKeyValueStorage, DrizzleQuotaService, NoopQuotaService, HttpEntitlementProvider, NoopEntitlementProvider, PerAccountQuotaStrategy, TencentDnsProvider, EdgeNodeDnsCoordinator, Dns01CertificateProvisioner, SimpleEdgeNodeTunnelManager, NoopEdgeNodeTunnelManager, FrpTunnelManager, EdgeNodeHealthProbeService, EdgeNodeAgent, EdgeNodeCertificateService, AcmeCertificateManager, EdgeNodeModeDetector, ClusterIdentifierStrategy, UsageTrackingStore, CenterNodeRegistrationService, PodRoutingHttpHandler, ReactAppViewHandler, QuintStore, SqliteQuintStore, PgQuintStore, BaseQuintStore, VectorStore, SqliteVectorStore, PostgresVectorStore, VectorHttpHandler, ProviderRegistry, ProviderRegistryImpl, EmbeddingService, EmbeddingServiceImpl, CredentialReader, CredentialReaderImpl, CloudflareTunnelProvider, LocalTunnelProvider, SubdomainService, MultiDomainIdentifierStrategy, SubdomainPodIdentifierStrategy, DisabledOidcHandler, DisabledIdentityProviderHandler, AutoDetectOidcHandler, AutoDetectIdentityProviderHandler, LoopbackClientIdAdapterFactory, UrlAwareRedisLocker, ProvisionPodCreator, ProvisionCodeCodec, AuthModeSelector, };
83
+ export { RepresentationPartialConvertingStore, MinioDataAccessor, QuadstoreSparqlDataAccessor, QuintStoreSparqlDataAccessor, MixDataAccessor, ConfigurableLoggerFactory, SparqlUpdateResourceStore, SubgraphQueryEngine, QuadstoreSparqlEngine, QuintstoreSparqlEngine, SubgraphSparqlHttpHandler, QuotaAdminHttpHandler, ClusterIngressRouter, ClusterWebSocketConfigurator, EdgeNodeDirectDebugHttpHandler, EdgeNodeProxyHttpHandler, RouterHttpHandler, RouterHttpRoute, TracingHandler, EdgeNodeCertificateHttpHandler, TerminalHttpHandler, ReservedSuffixIdentifierGenerator, DrizzleIndexedStorage, WebIdProfileRepository, PostgresKeyValueStorage, RedisKeyValueStorage, SqliteKeyValueStorage, DrizzleQuotaService, NoopQuotaService, HttpEntitlementProvider, NoopEntitlementProvider, PerAccountQuotaStrategy, TencentDnsProvider, EdgeNodeDnsCoordinator, Dns01CertificateProvisioner, SimpleEdgeNodeTunnelManager, NoopEdgeNodeTunnelManager, FrpTunnelManager, EdgeNodeHealthProbeService, EdgeNodeAgent, EdgeNodeCertificateService, AcmeCertificateManager, EdgeNodeModeDetector, ClusterIdentifierStrategy, UsageTrackingStore, CenterNodeRegistrationService, PodRoutingHttpHandler, ReactAppViewHandler, QuintStore, SqliteQuintStore, PgQuintStore, BaseQuintStore, VectorStore, SqliteVectorStore, PostgresVectorStore, VectorHttpHandler, ProviderRegistry, ProviderRegistryImpl, EmbeddingService, EmbeddingServiceImpl, CredentialReader, CredentialReaderImpl, CloudflareTunnelProvider, LocalTunnelProvider, SubdomainService, MultiDomainIdentifierStrategy, SubdomainPodIdentifierStrategy, DisabledOidcHandler, DisabledIdentityProviderHandler, AutoDetectOidcHandler, AutoDetectIdentityProviderHandler, LoopbackClientIdAdapterFactory, UrlAwareRedisLocker, ProvisionPodCreator, ProvisionCodeCodec, LocalPodProvisioningService, AuthModeSelector, };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QuintStore = exports.ReactAppViewHandler = exports.PodRoutingHttpHandler = exports.CenterNodeRegistrationService = exports.UsageTrackingStore = exports.ClusterIdentifierStrategy = exports.EdgeNodeModeDetector = exports.AcmeCertificateManager = exports.EdgeNodeCertificateService = exports.EdgeNodeAgent = exports.EdgeNodeHealthProbeService = exports.FrpTunnelManager = exports.NoopEdgeNodeTunnelManager = exports.SimpleEdgeNodeTunnelManager = exports.Dns01CertificateProvisioner = exports.EdgeNodeDnsCoordinator = exports.TencentDnsProvider = exports.PerAccountQuotaStrategy = exports.NoopEntitlementProvider = exports.HttpEntitlementProvider = exports.NoopQuotaService = exports.DrizzleQuotaService = exports.SqliteKeyValueStorage = exports.RedisKeyValueStorage = exports.PostgresKeyValueStorage = exports.WebIdProfileRepository = exports.DrizzleIndexedStorage = exports.ReservedSuffixIdentifierGenerator = exports.TerminalHttpHandler = exports.EdgeNodeCertificateHttpHandler = exports.TracingHandler = exports.RouterHttpRoute = exports.RouterHttpHandler = exports.EdgeNodeProxyHttpHandler = exports.EdgeNodeDirectDebugHttpHandler = exports.ClusterWebSocketConfigurator = exports.ClusterIngressRouter = exports.QuotaAdminHttpHandler = exports.SubgraphSparqlHttpHandler = exports.QuintstoreSparqlEngine = exports.QuadstoreSparqlEngine = exports.SubgraphQueryEngine = exports.SparqlUpdateResourceStore = exports.ConfigurableLoggerFactory = exports.MixDataAccessor = exports.QuintStoreSparqlDataAccessor = exports.QuadstoreSparqlDataAccessor = exports.MinioDataAccessor = exports.RepresentationPartialConvertingStore = exports.AppStaticAssetHandler = void 0;
4
- exports.AuthModeSelector = exports.ProvisionCodeCodec = exports.ProvisionPodCreator = exports.UrlAwareRedisLocker = exports.LoopbackClientIdAdapterFactory = exports.AutoDetectIdentityProviderHandler = exports.AutoDetectOidcHandler = exports.DisabledIdentityProviderHandler = exports.DisabledOidcHandler = exports.SubdomainPodIdentifierStrategy = exports.MultiDomainIdentifierStrategy = exports.SubdomainService = exports.LocalTunnelProvider = exports.CloudflareTunnelProvider = exports.CredentialReaderImpl = exports.CredentialReader = exports.EmbeddingServiceImpl = exports.EmbeddingService = exports.ProviderRegistryImpl = exports.ProviderRegistry = exports.VectorHttpHandler = exports.PostgresVectorStore = exports.SqliteVectorStore = exports.VectorStore = exports.BaseQuintStore = exports.PgQuintStore = exports.SqliteQuintStore = void 0;
4
+ exports.AuthModeSelector = exports.LocalPodProvisioningService = exports.ProvisionCodeCodec = exports.ProvisionPodCreator = exports.UrlAwareRedisLocker = exports.LoopbackClientIdAdapterFactory = exports.AutoDetectIdentityProviderHandler = exports.AutoDetectOidcHandler = exports.DisabledIdentityProviderHandler = exports.DisabledOidcHandler = exports.SubdomainPodIdentifierStrategy = exports.MultiDomainIdentifierStrategy = exports.SubdomainService = exports.LocalTunnelProvider = exports.CloudflareTunnelProvider = exports.CredentialReaderImpl = exports.CredentialReader = exports.EmbeddingServiceImpl = exports.EmbeddingService = exports.ProviderRegistryImpl = exports.ProviderRegistry = exports.VectorHttpHandler = exports.PostgresVectorStore = exports.SqliteVectorStore = exports.VectorStore = exports.BaseQuintStore = exports.PgQuintStore = exports.SqliteQuintStore = void 0;
5
5
  require("./runtime/configure-drizzle-solid");
6
6
  const RepresentationPartialConvertingStore_1 = require("./storage/RepresentationPartialConvertingStore");
7
7
  Object.defineProperty(exports, "RepresentationPartialConvertingStore", { enumerable: true, get: function () { return RepresentationPartialConvertingStore_1.RepresentationPartialConvertingStore; } });
@@ -152,6 +152,8 @@ const ProvisionPodCreator_1 = require("./provision/ProvisionPodCreator");
152
152
  Object.defineProperty(exports, "ProvisionPodCreator", { enumerable: true, get: function () { return ProvisionPodCreator_1.ProvisionPodCreator; } });
153
153
  const ProvisionCodeCodec_1 = require("./provision/ProvisionCodeCodec");
154
154
  Object.defineProperty(exports, "ProvisionCodeCodec", { enumerable: true, get: function () { return ProvisionCodeCodec_1.ProvisionCodeCodec; } });
155
+ const LocalPodProvisioningService_1 = require("./provision/LocalPodProvisioningService");
156
+ Object.defineProperty(exports, "LocalPodProvisioningService", { enumerable: true, get: function () { return LocalPodProvisioningService_1.LocalPodProvisioningService; } });
155
157
  // Authorization components
156
158
  const AuthModeSelector_1 = require("./authorization/AuthModeSelector");
157
159
  Object.defineProperty(exports, "AuthModeSelector", { enumerable: true, get: function () { return AuthModeSelector_1.AuthModeSelector; } });