tina4-nodejs 3.13.136 → 3.13.138

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 (243) hide show
  1. package/CLAUDE.md +33 -3
  2. package/COMMERCIAL-LICENSE.md +8 -0
  3. package/LICENSE +373 -0
  4. package/NOTICE +11 -0
  5. package/README.md +24 -2
  6. package/package.json +44 -6
  7. package/packages/cli/dist/bin.js +19440 -18017
  8. package/packages/cli/src/bin.ts +8 -0
  9. package/packages/cli/src/commands/build.ts +8 -0
  10. package/packages/cli/src/commands/generate.ts +8 -0
  11. package/packages/cli/src/commands/init.ts +8 -0
  12. package/packages/cli/src/commands/lint.ts +8 -0
  13. package/packages/cli/src/commands/migrate.ts +8 -0
  14. package/packages/cli/src/commands/migrateCreate.ts +8 -0
  15. package/packages/cli/src/commands/migrateRollback.ts +8 -0
  16. package/packages/cli/src/commands/migrateStatus.ts +8 -0
  17. package/packages/cli/src/commands/queue.ts +8 -0
  18. package/packages/cli/src/commands/routes.ts +8 -0
  19. package/packages/cli/src/commands/seed.ts +8 -0
  20. package/packages/cli/src/commands/serve.ts +11 -0
  21. package/packages/cli/src/commands/test.ts +8 -0
  22. package/packages/core/dist/index.js +19432 -18012
  23. package/packages/core/gallery/auth/src/routes/api/gallery/auth/login/post.ts +8 -0
  24. package/packages/core/gallery/auth/src/routes/api/gallery/auth/verify/get.ts +8 -0
  25. package/packages/core/gallery/auth/src/routes/gallery/auth/get.ts +8 -0
  26. package/packages/core/gallery/database/src/routes/api/gallery/db/notes/get.ts +8 -0
  27. package/packages/core/gallery/database/src/routes/api/gallery/db/notes/post.ts +8 -0
  28. package/packages/core/gallery/database/src/routes/api/gallery/db/tables/get.ts +8 -0
  29. package/packages/core/gallery/error-overlay/src/routes/api/gallery/crash/get.ts +8 -0
  30. package/packages/core/gallery/orm/src/routes/api/gallery/products/get.ts +8 -0
  31. package/packages/core/gallery/orm/src/routes/api/gallery/products/post.ts +8 -0
  32. package/packages/core/gallery/queue/src/lib/queueDb.ts +8 -0
  33. package/packages/core/gallery/queue/src/routes/api/gallery/queue/consume/post.ts +8 -0
  34. package/packages/core/gallery/queue/src/routes/api/gallery/queue/fail/post.ts +8 -0
  35. package/packages/core/gallery/queue/src/routes/api/gallery/queue/produce/post.ts +8 -0
  36. package/packages/core/gallery/queue/src/routes/api/gallery/queue/retry/post.ts +8 -0
  37. package/packages/core/gallery/queue/src/routes/api/gallery/queue/status/get.ts +8 -0
  38. package/packages/core/gallery/queue/src/routes/gallery/queue/get.ts +8 -0
  39. package/packages/core/gallery/rest-api/src/routes/api/gallery/hello/get.ts +8 -0
  40. package/packages/core/gallery/rest-api/src/routes/api/gallery/hello/post.ts +8 -0
  41. package/packages/core/gallery/templates/src/routes/gallery/page/get.ts +8 -0
  42. package/packages/core/gallery/templates/src/templates/gallery_page.twig +8 -0
  43. package/packages/core/public/THIRD-PARTY-NOTICES.md +55 -0
  44. package/packages/core/public/bundled-component-provenance.json +48 -0
  45. package/packages/core/public/js/tina4js.min.js +13 -3
  46. package/packages/core/public/licenses/swagger-ui-3.10.0-original-notice.txt +11 -0
  47. package/packages/core/public/licenses/swagger-ui-5.17.14-NOTICE.txt +2 -0
  48. package/packages/core/public/licenses/swagger-ui-Apache-2.0.txt +202 -0
  49. package/packages/core/public/licenses/tina4-css-MIT.txt +21 -0
  50. package/packages/core/public/licenses/tina4-dev-admin-components.json +240 -0
  51. package/packages/core/public/licenses/tina4-dev-admin-third-party.txt +919 -0
  52. package/packages/core/public/licenses/tina4-js-MIT.txt +20 -0
  53. package/packages/core/src/__feedback/widget.js +8 -0
  54. package/packages/core/src/_missing.ts +8 -0
  55. package/packages/core/src/ai.ts +8 -0
  56. package/packages/core/src/aiClient.ts +22 -7
  57. package/packages/core/src/api.ts +15 -3
  58. package/packages/core/src/auth.ts +21 -8
  59. package/packages/core/src/authGate.ts +8 -0
  60. package/packages/core/src/background.ts +8 -0
  61. package/packages/core/src/cache.ts +43 -4
  62. package/packages/core/src/constants.ts +8 -0
  63. package/packages/core/src/container.ts +8 -0
  64. package/packages/core/src/context/chunker.ts +8 -0
  65. package/packages/core/src/context/index.ts +8 -0
  66. package/packages/core/src/devAdmin.ts +185 -59
  67. package/packages/core/src/devMailbox.ts +8 -0
  68. package/packages/core/src/dispatchPipeline.ts +8 -0
  69. package/packages/core/src/docs.ts +8 -0
  70. package/packages/core/src/docsAutoDiscovery.ts +8 -0
  71. package/packages/core/src/docsParser.ts +8 -0
  72. package/packages/core/src/docsScanner.ts +44 -0
  73. package/packages/core/src/docsSignatures.ts +8 -0
  74. package/packages/core/src/dotenv.ts +8 -0
  75. package/packages/core/src/env.ts +8 -0
  76. package/packages/core/src/errorOverlay.ts +8 -0
  77. package/packages/core/src/events.ts +8 -0
  78. package/packages/core/src/fakeData.ts +8 -0
  79. package/packages/core/src/feedback.ts +8 -0
  80. package/packages/core/src/graphql.ts +16 -5
  81. package/packages/core/src/health.ts +8 -0
  82. package/packages/core/src/htmlElement.ts +8 -0
  83. package/packages/core/src/i18n.ts +8 -0
  84. package/packages/core/src/index.ts +8 -0
  85. package/packages/core/src/job.ts +8 -0
  86. package/packages/core/src/logger.ts +8 -0
  87. package/packages/core/src/mcp.test.ts +8 -0
  88. package/packages/core/src/mcp.ts +8 -0
  89. package/packages/core/src/messenger.ts +143 -86
  90. package/packages/core/src/metrics.ts +13 -0
  91. package/packages/core/src/middleware.ts +1178 -1096
  92. package/packages/core/src/mqtt.ts +8 -0
  93. package/packages/core/src/mqttMessage.ts +8 -0
  94. package/packages/core/src/optionalPackage.ts +48 -0
  95. package/packages/core/src/plan.ts +8 -0
  96. package/packages/core/src/portTakeover.ts +8 -0
  97. package/packages/core/src/projectIndex.ts +8 -0
  98. package/packages/core/src/projectIndexExtractors.ts +8 -0
  99. package/packages/core/src/projectIndexStorage.ts +8 -0
  100. package/packages/core/src/push.ts +8 -0
  101. package/packages/core/src/queue.ts +8 -0
  102. package/packages/core/src/queueBackends/kafkaBackend.ts +8 -0
  103. package/packages/core/src/queueBackends/liteBackend.ts +8 -0
  104. package/packages/core/src/queueBackends/mongoBackend.ts +21 -8
  105. package/packages/core/src/queueBackends/rabbitmqBackend.ts +8 -0
  106. package/packages/core/src/rateLimiter.ts +8 -0
  107. package/packages/core/src/request.ts +59 -10
  108. package/packages/core/src/response.ts +79 -5
  109. package/packages/core/src/routeDiscovery.ts +8 -0
  110. package/packages/core/src/router.ts +8 -0
  111. package/packages/core/src/server.ts +73 -24
  112. package/packages/core/src/service.ts +8 -0
  113. package/packages/core/src/session.ts +8 -0
  114. package/packages/core/src/sessionHandlers/childError.ts +8 -0
  115. package/packages/core/src/sessionHandlers/databaseHandler.ts +8 -0
  116. package/packages/core/src/sessionHandlers/memcachedHandler.ts +8 -0
  117. package/packages/core/src/sessionHandlers/mongoClient.ts +8 -0
  118. package/packages/core/src/sessionHandlers/mongoHandler.ts +8 -0
  119. package/packages/core/src/sessionHandlers/respClient.ts +8 -0
  120. package/packages/core/src/sessionHandlers/sqlClient.ts +8 -0
  121. package/packages/core/src/sessionHandlers/syncBridge.ts +8 -0
  122. package/packages/core/src/sessionHandlers/syncSocket.ts +8 -0
  123. package/packages/core/src/sessionHandlers/valkeyHandler.ts +8 -0
  124. package/packages/core/src/sso.ts +8 -0
  125. package/packages/core/src/static.ts +8 -0
  126. package/packages/core/src/test.ts +8 -0
  127. package/packages/core/src/testClient.ts +8 -0
  128. package/packages/core/src/testing.ts +8 -0
  129. package/packages/core/src/transport.ts +369 -0
  130. package/packages/core/src/trustedProxy.ts +8 -0
  131. package/packages/core/src/types.ts +13 -0
  132. package/packages/core/src/validator.ts +8 -0
  133. package/packages/core/src/version.ts +8 -0
  134. package/packages/core/src/websocket.ts +8 -0
  135. package/packages/core/src/websocketBackplane.ts +49 -32
  136. package/packages/core/src/websocketConnection.ts +8 -0
  137. package/packages/core/src/wsdl.ts +197 -115
  138. package/packages/core/templates/errors/302.twig +8 -0
  139. package/packages/core/templates/errors/401.twig +8 -0
  140. package/packages/core/templates/errors/403.twig +8 -0
  141. package/packages/core/templates/errors/404.twig +8 -0
  142. package/packages/core/templates/errors/500.twig +8 -0
  143. package/packages/core/templates/errors/502.twig +8 -0
  144. package/packages/core/templates/errors/503.twig +8 -0
  145. package/packages/core/templates/errors/base.twig +8 -0
  146. package/packages/frond/dist/index.js +151 -17
  147. package/packages/frond/src/engine.ts +177 -17
  148. package/packages/frond/src/index.ts +8 -0
  149. package/packages/orm/dist/index.js +8135 -6713
  150. package/packages/orm/src/adapters/firebird.ts +50 -3
  151. package/packages/orm/src/adapters/mongodb.ts +8 -0
  152. package/packages/orm/src/adapters/mssql.ts +29 -7
  153. package/packages/orm/src/adapters/mysql.ts +17 -1
  154. package/packages/orm/src/adapters/odbc.ts +11 -0
  155. package/packages/orm/src/adapters/pg-types.d.ts +8 -0
  156. package/packages/orm/src/adapters/postgres.ts +34 -8
  157. package/packages/orm/src/adapters/sqlDialect.ts +57 -0
  158. package/packages/orm/src/adapters/sqlite.ts +26 -0
  159. package/packages/orm/src/autoCrud.ts +78 -36
  160. package/packages/orm/src/baseModel.ts +61 -29
  161. package/packages/orm/src/cachedDatabase.ts +67 -1
  162. package/packages/orm/src/connectTimeout.ts +8 -0
  163. package/packages/orm/src/database.ts +649 -401
  164. package/packages/orm/src/databaseResult.ts +8 -0
  165. package/packages/orm/src/databaseUrl.ts +8 -0
  166. package/packages/orm/src/docstore.ts +23 -1
  167. package/packages/orm/src/fakeData.ts +8 -0
  168. package/packages/orm/src/graph/adapters/arango.ts +8 -0
  169. package/packages/orm/src/graph/adapters/bolt.ts +8 -0
  170. package/packages/orm/src/graph/adapters/ultipa.ts +8 -0
  171. package/packages/orm/src/graph/connectTimeout.ts +8 -0
  172. package/packages/orm/src/graph/errors.ts +8 -0
  173. package/packages/orm/src/graph/graphAdapter.ts +8 -0
  174. package/packages/orm/src/graph/graphDatabase.ts +8 -0
  175. package/packages/orm/src/graph/graphUrl.ts +10 -1
  176. package/packages/orm/src/graph/shapes.ts +8 -0
  177. package/packages/orm/src/index.ts +147 -139
  178. package/packages/orm/src/migration.ts +21 -0
  179. package/packages/orm/src/model.ts +8 -0
  180. package/packages/orm/src/modelCollection.ts +8 -0
  181. package/packages/orm/src/point.ts +8 -0
  182. package/packages/orm/src/query.ts +149 -33
  183. package/packages/orm/src/queryBuilder.ts +8 -0
  184. package/packages/orm/src/realtime/index.ts +8 -0
  185. package/packages/orm/src/realtime/models/attachment.ts +8 -0
  186. package/packages/orm/src/realtime/models/channel.ts +8 -0
  187. package/packages/orm/src/realtime/models/channelMember.ts +8 -0
  188. package/packages/orm/src/realtime/models/message.ts +8 -0
  189. package/packages/orm/src/realtime/models/workspace.ts +8 -0
  190. package/packages/orm/src/realtime/realtime.ts +8 -0
  191. package/packages/orm/src/realtime/storage.ts +43 -12
  192. package/packages/orm/src/seeder.ts +8 -0
  193. package/packages/orm/src/seederTable.ts +8 -0
  194. package/packages/orm/src/seederTypes.ts +8 -0
  195. package/packages/orm/src/sqlTranslator.ts +185 -8
  196. package/packages/orm/src/types.ts +15 -0
  197. package/packages/orm/src/validation.ts +8 -0
  198. package/packages/swagger/src/generator.ts +8 -0
  199. package/packages/swagger/src/index.ts +8 -0
  200. package/packages/swagger/src/ui.ts +8 -0
  201. package/types/core/src/aiClient.d.ts +2 -2
  202. package/types/core/src/background.d.ts +0 -16
  203. package/types/core/src/cache.d.ts +6 -0
  204. package/types/core/src/devAdmin.d.ts +18 -12
  205. package/types/core/src/docs.d.ts +0 -17
  206. package/types/core/src/errorOverlay.d.ts +0 -24
  207. package/types/core/src/events.d.ts +0 -12
  208. package/types/core/src/feedback.d.ts +0 -23
  209. package/types/core/src/graphql.d.ts +0 -21
  210. package/types/core/src/htmlElement.d.ts +0 -15
  211. package/types/core/src/messenger.d.ts +12 -1
  212. package/types/core/src/metrics.d.ts +2 -0
  213. package/types/core/src/middleware.d.ts +45 -1
  214. package/types/core/src/mqtt.d.ts +0 -33
  215. package/types/core/src/optionalPackage.d.ts +25 -0
  216. package/types/core/src/plan.d.ts +0 -10
  217. package/types/core/src/projectIndex.d.ts +0 -10
  218. package/types/core/src/queueBackends/mongoBackend.d.ts +2 -0
  219. package/types/core/src/request.d.ts +12 -0
  220. package/types/core/src/response.d.ts +13 -0
  221. package/types/core/src/server.d.ts +19 -0
  222. package/types/core/src/sessionHandlers/childError.d.ts +0 -15
  223. package/types/core/src/transport.d.ts +28 -0
  224. package/types/core/src/trustedProxy.d.ts +0 -16
  225. package/types/core/src/types.d.ts +5 -0
  226. package/types/core/src/websocketBackplane.d.ts +1 -0
  227. package/types/core/src/wsdl.d.ts +8 -22
  228. package/types/frond/src/engine.d.ts +7 -1
  229. package/types/orm/src/adapters/firebird.d.ts +12 -0
  230. package/types/orm/src/adapters/mssql.d.ts +11 -0
  231. package/types/orm/src/adapters/mysql.d.ts +2 -0
  232. package/types/orm/src/adapters/postgres.d.ts +11 -0
  233. package/types/orm/src/adapters/sqlDialect.d.ts +25 -0
  234. package/types/orm/src/adapters/sqlite.d.ts +7 -0
  235. package/types/orm/src/baseModel.d.ts +5 -0
  236. package/types/orm/src/cachedDatabase.d.ts +27 -0
  237. package/types/orm/src/database.d.ts +46 -7
  238. package/types/orm/src/graph/graphUrl.d.ts +0 -8
  239. package/types/orm/src/index.d.ts +1 -1
  240. package/types/orm/src/query.d.ts +48 -2
  241. package/types/orm/src/realtime/storage.d.ts +2 -1
  242. package/types/orm/src/sqlTranslator.d.ts +70 -18
  243. package/types/orm/src/types.d.ts +6 -0
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Auth — login endpoint, returns a JWT token. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Auth — verify a JWT token. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Auth — JWT login with a visual demo page. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Database — list notes from the gallery database. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Database — create a note in the gallery database. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Database — list tables in the gallery database. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Error Overlay — deliberately crash to demo the debug overlay.
2
10
  *
3
11
  * In debug mode (TINA4_DEBUG=true), you will see:
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: ORM — list products (demo data). */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: ORM — create a product (demo). */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Shared SQLite database helper for the queue gallery demo. */
2
10
  import type { DatabaseAdapter } from "tina4-nodejs/orm";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — consume (complete) the next pending message. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
  import { getQueueDb, now } from "../../../../lib/queueDb.js";
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — deliberately fail the next pending message. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
  import { getQueueDb, now } from "../../../../lib/queueDb.js";
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — produce a message into the queue. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
  import { getQueueDb, now } from "../../../../lib/queueDb.js";
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — retry failed messages (re-queue under max retries). */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
  import { getQueueDb, now, MAX_RETRIES } from "../../../../lib/queueDb.js";
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — list all messages with statuses. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
  import { getQueueDb, MAX_RETRIES } from "../../../../lib/queueDb.js";
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Queue — interactive queue demo with visual web UI. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: REST API — simple JSON GET endpoint. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: REST API — simple JSON POST endpoint. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,3 +1,11 @@
1
+ /*
2
+ Copyright (c) 2026 Code Infinity
3
+ SPDX-License-Identifier: MPL-2.0
4
+ This Source Code Form is subject to the terms of the Mozilla Public
5
+ License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
1
9
  /** Gallery: Templates — render an HTML page with dynamic data via template export. */
2
10
  import type { Tina4Request, Tina4Response } from "tina4-nodejs";
3
11
 
@@ -1,4 +1,12 @@
1
1
  <!DOCTYPE html>
2
+ {#
3
+ Copyright (c) 2026 Code Infinity
4
+ SPDX-License-Identifier: MPL-2.0
5
+ This Source Code Form is subject to the terms of the Mozilla Public
6
+ License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
+ #}
9
+
2
10
  <html lang="en">
3
11
  <head>
4
12
  <meta charset="utf-8">
@@ -0,0 +1,55 @@
1
+ # Bundled browser component notices
2
+
3
+ These components retain their stated licences; the repository's MPL-2.0 licence
4
+ for first-party source does not replace these grants. The standalone Tina4 JS bundle is updated as noted below; other generated browser
5
+ files are preserved unchanged by the licence migration.
6
+
7
+ ## Swagger UI — Apache-2.0
8
+
9
+ `swagger/oauth2-redirect.html` is adapted from Swagger UI 3.10.0. Its executable
10
+ text matches upstream after whitespace and semicolon normalization. Formatting
11
+ and semicolon removal are local modifications. Upstream commit:
12
+ https://github.com/swagger-api/swagger-ui/tree/1013d16d9eb0bb851b30d38d355a58639baf0f3a
13
+
14
+ Original copyright: Copyright 2018 SmartBear Software. The original notice is
15
+ retained in `licenses/swagger-ui-3.10.0-original-notice.txt` and the full Apache
16
+ License 2.0 in `licenses/swagger-ui-Apache-2.0.txt`.
17
+
18
+ `swagger/index.html` loads Swagger UI 5.17.14 JavaScript and CSS from a CDN; those
19
+ remote files are not bundled in this package. Its upstream tag resolves to:
20
+ https://github.com/swagger-api/swagger-ui/tree/74ed0adebfc9c8dd0de2bf8e81495b022a66c083
21
+ The upstream notice, Copyright 2020-2021 SmartBear Software Inc., is retained in
22
+ `licenses/swagger-ui-5.17.14-NOTICE.txt`.
23
+
24
+ ## Tina4 CSS / Frond browser helper — MIT
25
+
26
+ The `js/frond.js`, `js/frond.min.js`, `js/tina4.min.js`, and `css/tina4*.css`
27
+ browser assets originate from the separate Tina4 CSS project. Its original MIT
28
+ licence and copyright notice are retained in `licenses/tina4-css-MIT.txt`.
29
+ The shipped Frond minified file is byte-identical to `dist/frond.min.js` at:
30
+ https://github.com/tina4stack/tina4-css/tree/fab8e670b0c84c44b6e4c657aa87951bbed64824
31
+ The other CSS/legacy helper files are earlier generated snapshots; this reference
32
+ does not claim they match that revision byte-for-byte.
33
+
34
+ ## Tina4 JS 1.7.2 — MPL-2.0
35
+
36
+ `js/tina4js.min.js` is the verified browser build from Tina4 JS 1.7.2,
37
+ including the rendering and request-origin security corrections. Source:
38
+ https://github.com/tina4stack/tina4-js/tree/bb426862b062db0dd6d89577cae997efcba86116
39
+ Copyright (c) 2026 Code Infinity. The full licence and source-disclosure notice
40
+ are included in the package's LICENSE and NOTICE. Previously published Tina4 JS
41
+ releases retain their original licences; the retained MIT text is also used by
42
+ the dashboard's conservative dependency inventory.
43
+
44
+ `bundled-component-provenance.json` records the exact shipped asset hashes covered
45
+ by these notices. Remote assets are not classified as bundled dependencies.
46
+
47
+ ## Tina4 development dashboard — retained component licences
48
+
49
+ `js/tina4-dev-admin.min.js` is byte-identical to `dist/tina4-dev-admin.js` at:
50
+ https://github.com/tina4stack/tina4-dev-admin/tree/21700e0
51
+ Its resolved production component inventory is preserved in
52
+ `licenses/tina4-dev-admin-components.json`; upstream licence notices and terms are
53
+ in `licenses/tina4-dev-admin-third-party.txt`. No dashboard code was rebuilt or
54
+ relicensed by this notice update. The old Tina4 JS packages declare MIT but supply
55
+ no copyright notice; no upstream copyright holder has been invented here.
@@ -0,0 +1,48 @@
1
+ {
2
+ "schema": 1,
3
+ "assets": [
4
+ {
5
+ "path": "swagger/oauth2-redirect.html",
6
+ "component": "swagger-ui-3.10.0-adapted",
7
+ "sha256": "f489ad4d94b7299f24f116557da4745bc79b3c23da47583f207dda05478fb78d"
8
+ },
9
+ {
10
+ "path": "js/frond.min.js",
11
+ "component": "tina4-css",
12
+ "sha256": "4cbaf2131492225d87205d8982c4af5035538e9812e704b43f217f4ac4a5dafc"
13
+ },
14
+ {
15
+ "path": "js/frond.js",
16
+ "component": "tina4-css",
17
+ "sha256": "77560a0800034d91f8ccb5d726b69ff763881b96e39c5d0b6ee7186060c2d27a"
18
+ },
19
+ {
20
+ "path": "js/tina4.min.js",
21
+ "component": "tina4-css",
22
+ "sha256": "01507266f2bb50aadf477f11c1f0f6e17d4c56a5c96e1815ae8580d3ebde06fc"
23
+ },
24
+ {
25
+ "path": "css/tina4.css",
26
+ "component": "tina4-css",
27
+ "sha256": "705605c317763e68ba3a4b8e589e29fb0416abbbf437a4627178008131b30c18"
28
+ },
29
+ {
30
+ "path": "css/tina4.min.css",
31
+ "component": "tina4-css",
32
+ "sha256": "db950f712bd47626c28abba14af083a6f4379ff4b41798a8e77295a554c491c8"
33
+ },
34
+ {
35
+ "path": "js/tina4js.min.js",
36
+ "component": "tina4js-1.7.2",
37
+ "sha256": "45f4e93341450cb7e14a5f87e3981a8e696419e90016511a02b88cee26a8ca0f",
38
+ "source_commit": "bb426862b062db0dd6d89577cae997efcba86116",
39
+ "source_repository": "https://github.com/tina4stack/tina4-js",
40
+ "license": "MPL-2.0"
41
+ },
42
+ {
43
+ "path": "js/tina4-dev-admin.min.js",
44
+ "component": "tina4-dev-admin-21700e0",
45
+ "sha256": "0ca84246c26afb6a3243aafd1c65fa9486c076039e5d721b6f44661b3a59d7c2"
46
+ }
47
+ ]
48
+ }
@@ -1,4 +1,4 @@
1
- "use strict";var Tina4=(()=>{var ee=Object.defineProperty;var Xe=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var et=Object.prototype.hasOwnProperty;var tt=(e,n)=>{for(var t in n)ee(e,t,{get:n[t],enumerable:!0})},nt=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of Ye(n))!et.call(e,o)&&o!==t&&ee(e,o,{get:()=>n[o],enumerable:!(r=Xe(n,o))||r.enumerable});return e};var rt=e=>nt(ee({},"__esModule",{value:!0}),e);var $t={};tt($t,{Tina4Element:()=>N,api:()=>Ae,batch:()=>G,clearPersistedKeys:()=>Ve,computed:()=>ye,createI18n:()=>de,effect:()=>E,html:()=>be,i18n:()=>Je,isSignal:()=>I,navigate:()=>Q,persist:()=>ze,pwa:()=>Ne,route:()=>_e,router:()=>xe,rtc:()=>De,rtcConfig:()=>X,signal:()=>w,sse:()=>Pe,ws:()=>K});var L=null,H=null,U=null,B=null;function O(e){B=e}function J(){return B}var me=null,he=null,ve=[],ot=512;var V=0,te=new Set;function w(e,n){let t=e,r=new Set,o={_t4:!0,get value(){if(L&&(r.add(L),H)){let s=L;H.push(()=>r.delete(s))}return t},set value(s){if(Object.is(s,t))return;let i=t;if(t=s,o._debugInfo&&o._debugInfo.updateCount++,he&&he(o,i,s),V>0)for(let c of r)te.add(c);else{let c;for(let a of[...r])try{a()}catch(l){c===void 0&&(c=l)}if(c!==void 0)throw c}},_subscribe(s){return r.add(s),()=>{r.delete(s)}},peek(){return t}};return me?(o._debugInfo={label:n,createdAt:Date.now(),updateCount:0,subs:r},me(o,n)):ve.length<ot&&ve.push({ref:new WeakRef(o),label:n,createdAt:Date.now(),subs:r}),o}function ye(e){let n=w(void 0);return E(()=>{n.value=e()}),{_t4:!0,get value(){return n.value},set value(t){throw new Error("[tina4] computed signals are read-only")},_subscribe(t){return n._subscribe(t)},peek(){return n.peek()}}}function E(e){let n=!1,t=[],r=[],o=()=>{for(let c of r)c();r=[]},s=()=>{if(n)return;for(let g of t)g();t=[],o();let c=L,a=H,l=U;L=s,H=t,U=r;try{e()}finally{L=c,H=a,U=l}};s();let i=()=>{n=!0;for(let c of t)c();t=[],o()};return U&&U.push(i),B&&B.push(i),i}function G(e){V++;try{e()}finally{if(V--,V===0){let n=[...te];te.clear();let t;for(let r of n)try{r()}catch(o){t===void 0&&(t=o)}if(t!==void 0)throw t}}}function I(e){return e!==null&&typeof e=="object"&&e._t4===!0}var Se=new WeakMap,ne="t4:";function be(e,...n){let t=Se.get(e);if(!t){let i=document.createElement("template"),c=new Map,a="";for(let l=0;l<e.length;l++)if(a+=e[l],l<n.length)if(dt(a)){let m=ut(e[l]);m&&c.set(l,m),a+=`__t4_${l}__`}else a+=`<!--${ne}${l}-->`;i.innerHTML=a,t={template:i,propertyNames:c},Se.set(e,t)}let r=t.template.content.cloneNode(!0),o=st(r);for(let{marker:i,index:c}of o)at(i,n[c]);let s=it(r);for(let i of s)ct(i,n,t.propertyNames);return r}function st(e){let n=[];return se(e,t=>{if(t.nodeType===8){let r=t.data;if(r&&r.startsWith(ne)){let o=parseInt(r.slice(ne.length),10);n.push({marker:t,index:o})}}}),n}function it(e){let n=[];return se(e,t=>{t.nodeType===1&&n.push(t)}),n}function se(e,n){let t=e.childNodes;for(let r=0;r<t.length;r++){let o=t[r];n(o),se(o,n)}}function at(e,n){let t=e.parentNode;if(t)if(I(n)){let r=document.createTextNode("");t.replaceChild(r,e),E(()=>{r.data=String(n.value??"")})}else if(typeof n=="function"){let r=document.createComment("");t.replaceChild(r,e);let o=[],s=[];E(()=>{for(let u of s)u();s=[];let i=[],c=J();O(i);let a=n();O(c),s=i;for(let u of o)u.parentNode?.removeChild(u);o=[];let l=oe(a),g=r.parentNode;if(!g)return;let m=Z(g);for(let u of l){let d=m?D(u,m):u;g.insertBefore(d,r),o.push(d)}})}else if(Te(n)){let r=Z(t);if(r){let o=document.createDocumentFragment();for(let s of Array.from(n.childNodes))o.appendChild(D(s,r));t.replaceChild(o,e)}else t.replaceChild(n,e)}else if(n instanceof Node){let r=Z(t);t.replaceChild(r?D(n,r):n,e)}else if(Array.isArray(n)){let r=Z(t),o=document.createDocumentFragment();for(let s of n){let i=oe(s);for(let c of i)o.appendChild(r?D(c,r):c)}t.replaceChild(o,e)}else{let r=document.createTextNode(String(n??""));t.replaceChild(r,e)}}function ct(e,n,t){let r=[];for(let o of Array.from(e.attributes)){let s=o.name,i=o.value;if(s.startsWith("@")){let a=s.slice(1),l=i.match(/__t4_(\d+)__/);if(l){let g=n[parseInt(l[1],10)];typeof g=="function"&&e.addEventListener(a,m=>G(()=>g(m)))}r.push(s);continue}if(s.startsWith("?")){let a=s.slice(1),l=i.match(/__t4_(\d+)__/);if(l){let g=n[parseInt(l[1],10)];if(I(g)){let m=g;E(()=>{m.value?e.setAttribute(a,""):e.removeAttribute(a)})}else typeof g=="function"?E(()=>{g()?e.setAttribute(a,""):e.removeAttribute(a)}):g&&e.setAttribute(a,"")}r.push(s);continue}if(s.startsWith(".")){let a=i.match(/__t4_(\d+)__/);if(a){let l=parseInt(a[1],10),g=t.get(l)??s.slice(1),m=n[l];I(m)?E(()=>{e[g]=m.value}):typeof m=="function"?E(()=>{e[g]=m()??""}):e[g]=m}r.push(s);continue}let c=i.match(/__t4_(\d+)__/);if(c){let a=n[parseInt(c[1],10)];if(I(a)){let l=a;E(()=>{e.setAttribute(s,String(l.value??""))})}else typeof a=="function"?E(()=>{e.setAttribute(s,String(a()??""))}):e.setAttribute(s,String(a??""))}}for(let o of r)e.removeAttribute(o)}var re="http://www.w3.org/2000/svg",lt="http://www.w3.org/1998/Math/MathML",we="http://www.w3.org/1999/xhtml";function Z(e){let n=e;for(;n&&n.nodeType===1;){let t=n,r=t.namespaceURI;if(r===re&&t.localName==="foreignObject")return null;if(r===re||r===lt)return r;if(r===we)return null;n=n.parentNode}return null}function D(e,n){if(e.nodeType!==1)return e;let t=e;if(t.namespaceURI===n){for(let s of Array.from(t.childNodes)){let i=D(s,n);i!==s&&t.replaceChild(i,s)}return t}let r=document.createElementNS(n,t.localName);for(let s of Array.from(t.attributes))r.setAttribute(s.name,s.value);let o=n===re&&t.localName==="foreignObject"?we:n;for(let s of Array.from(t.childNodes))r.appendChild(D(s,o));return r}function ut(e){return e.match(/\.([^\s"'<>/=]+)\s*=\s*["']?$/)?.[1]}function oe(e){if(e==null||e===!1)return[];if(Te(e))return Array.from(e.childNodes);if(e instanceof Node)return[e];if(Array.isArray(e)){let n=[];for(let t of e)n.push(...oe(t));return n}return[document.createTextNode(String(e))]}function Te(e){return e!=null&&typeof e=="object"&&e.nodeType===11}function dt(e){let n=!1,t=!1,r=!1;for(let o=0;o<e.length;o++){if(!r&&e.startsWith("<!--",o)){let i=e.indexOf("-->",o+4);if(i===-1)return!1;o=i+2;continue}let s=e[o];s==="<"&&!n&&!t&&(r=!0),s===">"&&!n&&!t&&(r=!1),r&&(s==='"'&&!n&&(t=!t),s==="'"&&!t&&(n=!n))}return r}var ke=null,Ce=null;var N=class extends HTMLElement{constructor(){super();this._props={};this._rendered=!1;this._disposeRender=null;this._innerDisposers=[];let t=this.constructor;this._root=t.shadow?this.attachShadow({mode:"open"}):this;for(let[r,o]of Object.entries(t.props))this._props[r]=w(this._coerce(this.getAttribute(r),o))}static get observedAttributes(){return Object.keys(this.props)}connectedCallback(){if(this._rendered)return;this._rendered=!0;let t=this.constructor,r=null;if(t.styles&&t.shadow&&this._root instanceof ShadowRoot){let o=document.createElement("style");o.textContent=t.styles,this._root.appendChild(o),r=o}this._disposeRender=E(()=>{this._innerDisposers.splice(0).forEach(a=>a());let o=[],s=J();O(o);let i=this.render();O(s),this._innerDisposers=o;let c=Array.from(this._root.childNodes);for(let a of c)a!==r&&this._root.removeChild(a);i&&this._root.appendChild(i)}),this.onMount(),ke&&ke(this)}disconnectedCallback(){this._disposeRender&&(this._disposeRender(),this._disposeRender=null),this._innerDisposers.splice(0).forEach(t=>t()),this.onUnmount(),Ce&&Ce(this)}attributeChangedCallback(t,r,o){let i=this.constructor.props[t];i&&this._props[t]&&(this._props[t].value=this._coerce(o,i))}prop(t){if(!this._props[t])throw new Error(`[tina4] Prop '${t}' not declared in static props of <${this.tagName.toLowerCase()}>`);return this._props[t]}emit(t,r){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,...r}))}onMount(){}onUnmount(){}_coerce(t,r){return r===Boolean?t!==null:r===Number?t!==null?Number(t):0:t??""}};N.props={},N.styles="",N.shadow=!0;var ae=[],F=null,j="history",ft=!1,W=[],ie=[],Ee=0;function _e(e,n){let t=[],r;e==="*"?r=".*":r=e.replace(/\{(\w+)\}/g,(s,i)=>(t.push(i),"([^/]+)"));let o=new RegExp(`^${r}$`);typeof n=="function"?ae.push({pattern:e,regex:o,paramNames:t,handler:n}):ae.push({pattern:e,regex:o,paramNames:t,handler:n.handler,guard:n.guard})}function Q(e,n){if(j==="hash")if(n?.replace){let t=new URL(location.href);t.hash="#"+e,history.replaceState(null,"",t.toString()),$()}else{let t=new URL(location.href);t.hash="#"+e,history.pushState(null,"",t.toString()),$()}else n?.replace?history.replaceState(null,"",e):history.pushState(null,"",e),$()}function $(){if(!F)return;let e=performance.now(),n=++Ee,t=j==="hash"?location.hash.slice(1)||"/":location.pathname;for(let r of ae){let o=t.match(r.regex);if(!o)continue;let s={};if(r.paramNames.forEach((a,l)=>{s[a]=decodeURIComponent(o[l+1])}),r.guard){let a=r.guard();if(a===!1)return;if(typeof a=="string"){Q(a,{replace:!0});return}}ie.splice(0).forEach(a=>a()),F.innerHTML="";let i=[];O(i);let c=r.handler(s);if(c instanceof Promise)c.then(a=>{if(O(null),n!==Ee){for(let g of i)g();return}Re(F,a),ie=i;let l=performance.now()-e;for(let g of W)g({path:t,params:s,pattern:r.pattern,durationMs:l})});else{O(null),Re(F,c),ie=i;let a=performance.now()-e;for(let l of W)l({path:t,params:s,pattern:r.pattern,durationMs:a})}return}}function Re(e,n){n instanceof DocumentFragment||n instanceof Node?e.replaceChildren(n):typeof n=="string"?e.innerHTML=n:n!=null&&e.replaceChildren(document.createTextNode(String(n)))}var xe={start(e){if(F=document.querySelector(e.target),!F)throw new Error(`[tina4] Router target '${e.target}' not found in DOM`);j=e.mode??"history",ft=!0,window.addEventListener("popstate",$),j==="hash"&&window.addEventListener("hashchange",$),document.addEventListener("click",n=>{if(n.metaKey||n.ctrlKey||n.shiftKey||n.altKey)return;let t=n.target.closest("a[href]");if(!t||t.origin!==location.origin||t.hasAttribute("target")||t.hasAttribute("download")||t.getAttribute("rel")?.includes("external"))return;n.preventDefault();let r=j==="hash"?t.getAttribute("href"):t.pathname;Q(r)}),$()},on(e,n){return W.push(n),()=>{let t=W.indexOf(n);t>=0&&W.splice(t,1)}}};var _={baseUrl:"",auth:!1,tokenKey:"tina4_token",headers:{}},ce=[],le=[],gt=0;function ue(){try{return localStorage.getItem(_.tokenKey)}catch{return null}}function pt(e){try{localStorage.setItem(_.tokenKey,e)}catch{}}function Me(e,n){let t=Object.entries(n).map(([r,o])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(o))}`).join("&");return e+(e.includes("?")?"&":"?")+t}async function Oe(e,n){e._url=n,e._requestId=++gt;for(let c of ce){let a=c(e);a&&(e=a)}let t=await fetch(n,e),r=t.headers.get("FreshToken");r&&pt(r);let o=t.headers.get("Content-Type")??"",s;o.includes("json")?s=await t.json():s=await t.text();let i={status:t.status,data:s,ok:t.ok,headers:t.headers,_requestId:e._requestId};for(let c of le){let a=c(i);a&&(i=a)}if(!t.ok)throw i;return i.data}async function q(e,n,t,r){let o={method:e,credentials:"same-origin",headers:{"Content-Type":"application/json",..._.headers}};if(_.auth){let s=ue();s&&(o.headers.Authorization=`Bearer ${s}`)}if(t!==void 0&&e!=="GET"){let s=typeof t=="object"&&t!==null?{...t}:t;if(_.auth&&typeof s=="object"&&s!==null){let i=ue();i&&(s.formToken=i)}o.body=JSON.stringify(s)}return r?.headers&&Object.assign(o.headers,r.headers),r?.params&&(n=Me(n,r.params)),Oe(o,_.baseUrl+n)}var Ae={configure(e){Object.assign(_,e)},get(e,n){return q("GET",e,void 0,n)},post(e,n,t){return q("POST",e,n,t)},put(e,n,t){return q("PUT",e,n,t)},patch(e,n,t){return q("PATCH",e,n,t)},delete(e,n){return q("DELETE",e,void 0,n)},async graphql(e,n,t,r){return q("POST",e,{query:n,variables:t||{}},r)},async upload(e,n,t){let r={method:"POST",headers:{..._.headers},body:n};if(delete r.headers["Content-Type"],delete r.headers["content-type"],_.auth){let o=ue();o&&(r.headers.Authorization=`Bearer ${o}`)}return t?.headers&&Object.assign(r.headers,t.headers),t?.params&&(e=Me(e,t.params)),Oe(r,_.baseUrl+e)},intercept(e,n){e==="request"?ce.push(n):le.push(n)},_reset(){_.baseUrl="",_.auth=!1,_.tokenKey="tina4_token",_.headers={},ce.length=0,le.length=0}};function mt(e){let n=e.cacheStrategy??"network-first",t=JSON.stringify(e.precache??[]),r=e.offlineRoute?`'${e.offlineRoute}'`:"null";return`
1
+ "use strict";var Tina4=(()=>{var ie=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var pt=Object.getOwnPropertyNames;var gt=Object.prototype.hasOwnProperty;var mt=(e,n)=>{for(var t in n)ie(e,t,{get:n[t],enumerable:!0})},ht=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of pt(n))!gt.call(e,o)&&o!==t&&ie(e,o,{get:()=>n[o],enumerable:!(r=ft(n,o))||r.enumerable});return e};var yt=e=>ht(ie({},"__esModule",{value:!0}),e);var sn={};mt(sn,{RawHtml:()=>H,Tina4Element:()=>L,ai:()=>Je,api:()=>je,batch:()=>ee,clearPersistedKeys:()=>ct,computed:()=>xe,createI18n:()=>we,effect:()=>x,html:()=>Ae,i18n:()=>ut,isSignal:()=>M,navigate:()=>J,persist:()=>at,push:()=>Ve,pwa:()=>ze,rawHtml:()=>De,route:()=>Fe,router:()=>Ue,rtc:()=>Xe,rtcConfig:()=>re,signal:()=>w,sse:()=>ne,ws:()=>G});var $=null,z=null,K=null,X=null;function P(e){X=e}function Y(){return X}var Ce=null,Ee=null,Re=[],vt=512;var Q=0,ae=new Set;function w(e,n){let t=e,r=new Set,o={_t4:!0,get value(){if($&&(r.add($),z)){let s=$;z.push(()=>r.delete(s))}return t},set value(s){if(Object.is(s,t))return;let a=t;if(t=s,o._debugInfo&&o._debugInfo.updateCount++,Ee&&Ee(o,a,s),Q>0)for(let i of r)ae.add(i);else{let i;for(let l of[...r])try{l()}catch(c){i===void 0&&(i=c)}if(i!==void 0)throw i}},_subscribe(s){return r.add(s),()=>{r.delete(s)}},peek(){return t}};return Ce?(o._debugInfo={label:n,createdAt:Date.now(),updateCount:0,subs:r},Ce(o,n)):Re.length<vt&&Re.push({ref:new WeakRef(o),label:n,createdAt:Date.now(),subs:r}),o}function xe(e){let n=w(void 0);return x(()=>{n.value=e()}),{_t4:!0,get value(){return n.value},set value(t){throw new Error("[tina4] computed signals are read-only")},_subscribe(t){return n._subscribe(t)},peek(){return n.peek()}}}function x(e){let n=!1,t=[],r=[],o=()=>{for(let i of r)i();r=[]},s=()=>{if(n)return;for(let d of t)d();t=[],o();let i=$,l=z,c=K;$=s,z=t,K=r;try{e()}finally{$=i,z=l,K=c}};s();let a=()=>{n=!0;for(let i of t)i();t=[],o()};return K&&K.push(a),X&&X.push(a),a}function ee(e){Q++;try{e()}finally{if(Q--,Q===0){let n=[...ae];ae.clear();let t;for(let r of n)try{r()}catch(o){t===void 0&&(t=o)}if(t!==void 0)throw t}}}function M(e){return e!==null&&typeof e=="object"&&e._t4===!0}var _e=new WeakMap,ce="t4:";function Ae(e,...n){let t=_e.get(e);if(!t){let a=document.createElement("template"),i=new Map,l="";for(let c=0;c<e.length;c++)if(l+=e[c],c<n.length)if(At(l)){let m=_t(e[c]);m&&i.set(c,m),l+=`__t4_${c}__`}else l+=`<!--${ce}${c}-->`;a.innerHTML=l,t={template:a,propertyNames:i},_e.set(e,t)}let r=t.template.content.cloneNode(!0),o=bt(r);for(let{marker:a,index:i}of o)wt(a,n[i]);let s=St(r);for(let a of s)Rt(a,n,t.propertyNames);return r}function bt(e){let n=[];return fe(e,t=>{if(t.nodeType===8){let r=t.data;if(r&&r.startsWith(ce)){let o=parseInt(r.slice(ce.length),10);n.push({marker:t,index:o})}}}),n}function St(e){let n=[];return fe(e,t=>{t.nodeType===1&&n.push(t)}),n}function fe(e,n){let t=e.childNodes;for(let r=0;r<t.length;r++){let o=t[r];n(o),fe(o,n)}}function wt(e,n){let t=e.parentNode;if(t)if(M(n)){let r=document.createTextNode("");t.replaceChild(r,e),x(()=>{r.data=String(n.value??"")})}else if(typeof n=="function"){let r=document.createComment(""),o=document.createComment("");t.replaceChild(o,e),t.insertBefore(r,o);let s=[];x(()=>{for(let u of s)u();s=[];let a=[],i=Y();P(a);let l=n();P(i),s=a;for(let u=r.nextSibling;u&&u!==o;u=r.nextSibling)u.remove();let c=de(l),d=o.parentNode;if(!d)return;let m=te(d);for(let u of c)d.insertBefore(m?q(u,m):u,o)})}else if(Oe(n)){let r=te(t);if(r){let o=document.createDocumentFragment();for(let s of Array.from(n.childNodes))o.appendChild(q(s,r));t.replaceChild(o,e)}else t.replaceChild(n,e)}else if(n instanceof Node){let r=te(t);t.replaceChild(r?q(n,r):n,e)}else if(Array.isArray(n)){let r=te(t),o=document.createDocumentFragment();for(let s of n){let a=de(s);for(let i of a)o.appendChild(r?q(i,r):i)}t.replaceChild(o,e)}else{let r=document.createTextNode(String(n??""));t.replaceChild(r,e)}}var kt=new Set(["href","src","action","formaction","xlink:href","srcdoc"]),le=/__t4_(\d+)__/g;function Tt(e){let n=e.replace(/[\u0000- ]+/g,"").toLowerCase();return n.startsWith("javascript:")||n.startsWith("vbscript:")?!0:n.startsWith("data:")?!n.startsWith("data:image/"):!1}function Ct(e){let n=M(e)?e.value:typeof e=="function"?e():e;return String(n??"")}function Et(e,n){return e.replace(le,(t,r)=>Ct(n[parseInt(r,10)]))}function Rt(e,n,t){let r=[];for(let o of Array.from(e.attributes)){let s=o.name,a=o.value;if(s.startsWith("@")){let i=s.slice(1),l=a.match(/__t4_(\d+)__/);if(l){let c=n[parseInt(l[1],10)];typeof c=="function"&&e.addEventListener(i,d=>ee(()=>c(d)))}r.push(s);continue}if(s.startsWith("?")){let i=s.slice(1),l=a.match(/__t4_(\d+)__/);if(l){let c=n[parseInt(l[1],10)];if(M(c)){let d=c;x(()=>{d.value?e.setAttribute(i,""):e.removeAttribute(i)})}else typeof c=="function"?x(()=>{c()?e.setAttribute(i,""):e.removeAttribute(i)}):c&&e.setAttribute(i,"")}r.push(s);continue}if(s.startsWith(".")){let i=a.match(/__t4_(\d+)__/);if(i){let l=parseInt(i[1],10),c=t.get(l)??s.slice(1),d=n[l];M(d)?x(()=>{e[c]=d.value}):typeof d=="function"?x(()=>{e[c]=d()??""}):e[c]=d}r.push(s);continue}if(le.lastIndex=0,le.test(a)){if(/^on/i.test(s)){r.push(s);continue}let l=[...a.matchAll(/__t4_(\d+)__/g)].map(m=>parseInt(m[1],10)).some(m=>M(n[m])||typeof n[m]=="function"),c=kt.has(s),d=()=>{let m=Et(a,n);c&&Tt(m)&&(m=""),e.setAttribute(s,m)};l?x(d):d()}}for(let o of r)e.removeAttribute(o)}var ue="http://www.w3.org/2000/svg",xt="http://www.w3.org/1998/Math/MathML",Pe="http://www.w3.org/1999/xhtml";function te(e){let n=e;for(;n&&n.nodeType===1;){let t=n,r=t.namespaceURI;if(r===ue&&t.localName==="foreignObject")return null;if(r===ue||r===xt)return r;if(r===Pe)return null;n=n.parentNode}return null}function q(e,n){if(e.nodeType!==1)return e;let t=e;if(t.namespaceURI===n){for(let s of Array.from(t.childNodes)){let a=q(s,n);a!==s&&t.replaceChild(a,s)}return t}let r=document.createElementNS(n,t.localName);for(let s of Array.from(t.attributes))r.setAttribute(s.name,s.value);let o=n===ue&&t.localName==="foreignObject"?Pe:n;for(let s of Array.from(t.childNodes))r.appendChild(q(s,o));return r}function _t(e){return e.match(/\.([^\s"'<>/=]+)\s*=\s*["']?$/)?.[1]}function de(e){if(e==null||e===!1)return[];if(Oe(e))return Array.from(e.childNodes);if(e instanceof Node)return[e];if(Array.isArray(e)){let n=[];for(let t of e)n.push(...de(t));return n}return[document.createTextNode(String(e))]}function Oe(e){return typeof DocumentFragment<"u"&&e instanceof DocumentFragment?!0:typeof Node<"u"&&e instanceof Node&&e.nodeType===11}function At(e){let n=!1,t=!1,r=!1;for(let o=0;o<e.length;o++){if(!r&&e.startsWith("<!--",o)){let a=e.indexOf("-->",o+4);if(a===-1)return!1;o=a+2;continue}let s=e[o];s==="<"&&!n&&!t&&(r=!0),s===">"&&!n&&!t&&(r=!1),r&&(s==='"'&&!n&&(t=!t),s==="'"&&!t&&(n=!n))}return r}var Me=null,Ne=null;var L=class extends HTMLElement{constructor(){super();this._props={};this._rendered=!1;this._disposeRender=null;this._innerDisposers=[];let t=this.constructor;this._root=t.shadow?this.attachShadow({mode:"open"}):this;for(let[r,o]of Object.entries(t.props))this._props[r]=w(this._coerce(this.getAttribute(r),o))}static get observedAttributes(){return Object.keys(this.props)}connectedCallback(){if(this._rendered)return;this._rendered=!0;let t=this.constructor,r=null;if(t.styles&&t.shadow&&this._root instanceof ShadowRoot){let o=document.createElement("style");o.textContent=t.styles,this._root.appendChild(o),r=o}this._disposeRender=x(()=>{this._innerDisposers.splice(0).forEach(l=>l());let o=[],s=Y();P(o);let a=this.render();P(s),this._innerDisposers=o;let i=Array.from(this._root.childNodes);for(let l of i)l!==r&&this._root.removeChild(l);a&&this._root.appendChild(a)}),this.onMount(),Me&&Me(this)}disconnectedCallback(){this._disposeRender&&(this._disposeRender(),this._disposeRender=null),this._innerDisposers.splice(0).forEach(t=>t()),this.onUnmount(),Ne&&Ne(this)}attributeChangedCallback(t,r,o){let a=this.constructor.props[t];a&&this._props[t]&&(this._props[t].value=this._coerce(o,a))}prop(t){if(!this._props[t])throw new Error(`[tina4] Prop '${t}' not declared in static props of <${this.tagName.toLowerCase()}>`);return this._props[t]}emit(t,r){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,...r}))}onMount(){}onUnmount(){}_coerce(t,r){return r===Boolean?t!==null:r===Number?t!==null?Number(t):0:t??""}};L.props={},L.styles="",L.shadow=!0;var H=class{constructor(n){this.html=n}};function De(e){return new H(e)}var ge=[],D=null,B="history",Pt=!1,V=[],pe=[],me=0;function Fe(e,n){let t=[],r;e==="*"?r=".*":r=e.replace(/\{(\w+)\}/g,(s,a)=>(t.push(a),"([^/]+)"));let o=new RegExp(`^${r}$`);typeof n=="function"?ge.push({pattern:e,regex:o,paramNames:t,handler:n}):ge.push({pattern:e,regex:o,paramNames:t,handler:n.handler,guard:n.guard})}function J(e,n){if(B==="hash")if(n?.replace){let t=new URL(location.href);t.hash="#"+e,history.replaceState(null,"",t.toString()),W()}else{let t=new URL(location.href);t.hash="#"+e,history.pushState(null,"",t.toString()),W()}else n?.replace?history.replaceState(null,"",e):history.pushState(null,"",e),W()}function W(){if(!D)return;let e=performance.now(),n=++me,t=B==="hash"?location.hash.slice(1)||"/":location.pathname;for(let r of ge){let o=t.match(r.regex);if(!o)continue;let s={};if(r.paramNames.forEach((a,i)=>{let l=o[i+1];try{s[a]=decodeURIComponent(l)}catch{s[a]=l}}),r.guard){let a=r.guard();if(a&&typeof a.then=="function"){a.then(i=>{if(n===me&&i!==!1){if(typeof i=="string"){J(i,{replace:!0});return}Ie(r,s,t,e,n)}});return}if(a===!1)return;if(typeof a=="string"){J(a,{replace:!0});return}}Ie(r,s,t,e,n);return}}function Ie(e,n,t,r,o){if(!D)return;pe.splice(0).forEach(i=>i()),D.innerHTML="";let s=[];P(s);let a=e.handler(n);if(a instanceof Promise)a.then(i=>{if(P(null),o!==me){for(let c of s)c();return}Le(D,i),pe=s;let l=performance.now()-r;for(let c of V)c({path:t,params:n,pattern:e.pattern,durationMs:l})});else{P(null),Le(D,a),pe=s;let i=performance.now()-r;for(let l of V)l({path:t,params:n,pattern:e.pattern,durationMs:i})}}function Le(e,n){n instanceof DocumentFragment||n instanceof Node?e.replaceChildren(n):n instanceof H?e.innerHTML=n.html:typeof n=="string"?e.replaceChildren(document.createTextNode(n)):n!=null&&e.replaceChildren(document.createTextNode(String(n)))}var Ue={start(e){if(D=document.querySelector(e.target),!D)throw new Error(`[tina4] Router target '${e.target}' not found in DOM`);B=e.mode??"history",Pt=!0,window.addEventListener("popstate",W),B==="hash"&&window.addEventListener("hashchange",W),document.addEventListener("click",n=>{if(n.metaKey||n.ctrlKey||n.shiftKey||n.altKey)return;let t=n.target.closest("a[href]");if(!t||t.origin!==location.origin||t.hasAttribute("target")||t.hasAttribute("download")||t.getAttribute("rel")?.includes("external"))return;n.preventDefault();let r=B==="hash"?t.getAttribute("href"):t.pathname;J(r)}),W()},on(e,n){return V.push(n),()=>{let t=V.indexOf(n);t>=0&&V.splice(t,1)}}};var E={baseUrl:"",auth:!1,tokenKey:"tina4_token",headers:{}},he=[],ye=[],Ot=0;function ve(){try{return localStorage.getItem(E.tokenKey)}catch{return null}}function Mt(e){try{localStorage.setItem(E.tokenKey,e)}catch{}}function qe(e,n){let t=Object.entries(n).map(([r,o])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(o))}`).join("&");return e+(e.includes("?")?"&":"?")+t}function $e(e){try{return new URL(e,typeof location<"u"?location.href:void 0).origin}catch{return null}}function We(e){let n=$e(e);if(n===null)return!1;if(typeof location<"u"&&n===location.origin)return!0;let t=E.baseUrl?$e(E.baseUrl):null;return t!==null&&n===t}async function He(e,n){e._url=n,e._requestId=++Ot;for(let a of he){let i=a(e);i&&(e=i)}let t=await fetch(n,e);if(We(n)){let a=t.headers.get("FreshToken");a&&Mt(a)}let r=t.headers.get("Content-Type")??"",o;r.includes("json")?o=await t.json():o=await t.text();let s={status:t.status,data:o,ok:t.ok,headers:t.headers,_requestId:e._requestId};for(let a of ye){let i=a(s);i&&(s=i)}if(!t.ok)throw s;return s.data}async function j(e,n,t,r){let o={method:e,credentials:"same-origin",headers:{"Content-Type":"application/json",...E.headers}};r?.params&&(n=qe(n,r.params));let s=E.baseUrl+n,a=We(s);if(E.auth&&a){let i=ve();i&&(o.headers.Authorization=`Bearer ${i}`)}if(t!==void 0&&e!=="GET"){let i=typeof t=="object"&&t!==null?{...t}:t;if(E.auth&&a&&typeof i=="object"&&i!==null){let l=ve();l&&(i.formToken=l)}o.body=JSON.stringify(i)}return r?.headers&&Object.assign(o.headers,r.headers),He(o,s)}var je={configure(e){Object.assign(E,e)},get(e,n){return j("GET",e,void 0,n)},post(e,n,t){return j("POST",e,n,t)},put(e,n,t){return j("PUT",e,n,t)},patch(e,n,t){return j("PATCH",e,n,t)},delete(e,n){return j("DELETE",e,void 0,n)},async graphql(e,n,t,r){return j("POST",e,{query:n,variables:t||{}},r)},async upload(e,n,t){let r={method:"POST",headers:{...E.headers},body:n};if(delete r.headers["Content-Type"],delete r.headers["content-type"],E.auth){let o=ve();o&&(r.headers.Authorization=`Bearer ${o}`)}return t?.headers&&Object.assign(r.headers,t.headers),t?.params&&(e=qe(e,t.params)),He(r,E.baseUrl+e)},intercept(e,n){e==="request"?he.push(n):ye.push(n)},_reset(){E.baseUrl="",E.auth=!1,E.tokenKey="tina4_token",E.headers={},he.length=0,ye.length=0}};function Nt(e){let n=e.cacheStrategy??"network-first",t=JSON.stringify(e.precache??[]),r=e.offlineRoute?`'${e.offlineRoute}'`:"null";return`
2
2
  const CACHE = 'tina4-v1';
3
3
  const PRECACHE = ${t};
4
4
  const OFFLINE = ${r};
@@ -17,6 +17,15 @@ self.addEventListener('fetch', (e) => {
17
17
  const req = e.request;
18
18
  if (req.method !== 'GET') return;
19
19
 
20
+ // Never cache authenticated API responses (PWA1): a same-origin /api GET or
21
+ // any request carrying an Authorization header goes straight to the network,
22
+ // so private data cannot be served to another session from the cache.
23
+ const _url = new URL(req.url);
24
+ if (req.headers.get('authorization') ||
25
+ (_url.origin === self.location.origin && _url.pathname.startsWith('/api'))) {
26
+ return;
27
+ }
28
+
20
29
  ${n==="cache-first"?`
21
30
  e.respondWith(
22
31
  caches.match(req).then((cached) => cached || fetch(req).then((res) => {
@@ -44,5 +53,6 @@ self.addEventListener('fetch', (e) => {
44
53
  ))
45
54
  );`}
46
55
  });
47
- `.trim()}function Ie(e){let n={name:e.name,short_name:e.shortName??e.name,start_url:"/",display:e.display??"standalone",background_color:e.backgroundColor??"#ffffff",theme_color:e.themeColor??"#000000"};return e.icon&&(n.icons=[{src:e.icon,sizes:"192x192",type:"image/png"},{src:e.icon,sizes:"512x512",type:"image/png"}]),n}var Ne={register(e){let n=Ie(e),t=new Blob([JSON.stringify(n)],{type:"application/json"}),r=document.createElement("link");r.rel="manifest",r.href=URL.createObjectURL(t),document.head.appendChild(r);let o=document.querySelector('meta[name="theme-color"]');o||(o=document.createElement("meta"),o.name="theme-color",document.head.appendChild(o)),o.content=e.themeColor??"#000000","serviceWorker"in navigator&&(e.swUrl?navigator.serviceWorker.register(e.swUrl).catch(s=>{console.warn("[tina4] Service worker registration failed:",s)}):navigator.serviceWorker.register("/sw.js").catch(()=>{console.info("[tina4] No service worker at /sw.js. Use pwa.generateServiceWorker() to create one, or pass swUrl in config.")}))},generateServiceWorker(e){return mt(e)},generateManifest(e){return Ie(e)}};var ht={reconnect:!0,reconnectDelay:1e3,reconnectMaxDelay:3e4,reconnectAttempts:1/0,protocols:[],token:""};function vt(e){let n=Array.isArray(e.protocols)?e.protocols:e.protocols?[e.protocols]:[];return e.token?["bearer",e.token,...n]:e.protocols}function yt(e,n={}){let t={...ht,...n},r=w("connecting"),o=w(!1),s=w(null),i=w(null),c=w(0),a={message:[],open:[],close:[],error:[]},l=null,g=!1,m=t.reconnectDelay,u=null,d=0;function f(v){if(typeof v!="string")return v;try{return JSON.parse(v)}catch{return v}}function h(){r.value=d>0?"reconnecting":"connecting";try{l=new WebSocket(e,vt(t))}catch{r.value="closed",o.value=!1;return}l.onopen=()=>{r.value="open",o.value=!0,i.value=null,d=0,m=t.reconnectDelay,c.value=0;for(let v of a.open)v()},l.onmessage=v=>{let T=f(v.data);s.value=T;for(let R of a.message)R(T)},l.onclose=v=>{r.value="closed",o.value=!1;for(let T of a.close)T(v.code,v.reason);!g&&t.reconnect&&d<t.reconnectAttempts&&x()},l.onerror=v=>{i.value=v;for(let T of a.error)T(v)}}function x(){d++,c.value=d,r.value="reconnecting",u=setTimeout(()=>{u=null,h()},m),m=Math.min(m*2,t.reconnectMaxDelay)}let C={status:r,connected:o,lastMessage:s,error:i,reconnectCount:c,send(v){if(!l||l.readyState!==WebSocket.OPEN)throw new Error("[tina4] WebSocket is not connected");let T=typeof v=="string"?v:JSON.stringify(v);l.send(T)},on(v,T){return a[v].push(T),()=>{let R=a[v],A=R.indexOf(T);A>=0&&R.splice(A,1)}},pipe(v,T){let R=A=>{v.value=T(A,v.value)};return C.on("message",R)},close(v,T){g=!0,u&&(clearTimeout(u),u=null),l&&l.close(v??1e3,T??""),r.value="closed",o.value=!1}};return h(),C}var K={connect:yt};var St={mode:"eventsource",method:"GET",headers:{},body:void 0,reconnect:!0,reconnectDelay:1e3,reconnectMaxDelay:3e4,reconnectAttempts:1/0,events:[],json:!0};function bt(e,n={}){let t={...St,...n},r=w("connecting"),o=w(!1),s=w(null),i=w(null),c=w(null),a=w(0),l={message:[],open:[],close:[],error:[]},g=null,m=null,u=!1,d=t.reconnectDelay,f=null,h=0;function x(p){if(!t.json||typeof p!="string")return p;try{return JSON.parse(p)}catch{return p}}function C(p,S){s.value=p,i.value=S;for(let k of l.message)k(p,S??void 0)}function v(){r.value="open",o.value=!0,c.value=null,h=0,d=t.reconnectDelay,a.value=0;for(let p of l.open)p()}function T(){r.value="closed",o.value=!1;for(let p of l.close)p();!u&&t.reconnect&&h<t.reconnectAttempts&&Y()}function R(p){c.value=p;for(let S of l.error)S(p)}function A(){r.value=h>0?"reconnecting":"connecting";try{g=new EventSource(e)}catch{r.value="closed",o.value=!1;return}g.onopen=()=>v(),g.onmessage=p=>{C(x(p.data),null)};for(let p of t.events)g.addEventListener(p,S=>{C(x(S.data),p)});g.onerror=p=>{R(p),g&&g.readyState===2&&(g=null,T())}}function z(){r.value=h>0?"reconnecting":"connecting",m=new AbortController;let p={method:t.method,headers:t.headers,signal:m.signal};t.body!==void 0&&(p.body=typeof t.body=="string"?t.body:JSON.stringify(t.body)),fetch(e,p).then(async S=>{if(!S.ok){R(new Error(`[tina4] SSE fetch ${S.status}`)),T();return}v();let k=S.body.getReader(),M=new TextDecoder,P="";for(;;){let{done:Ge,value:Ze}=await k.read();if(Ge)break;P+=M.decode(Ze,{stream:!0});let ge=P.split(`
48
- `);P=ge.pop();for(let Qe of ge){let pe=Qe.trim();pe&&C(x(pe),null)}}let fe=P.trim();fe&&C(x(fe),null),m=null,T()}).catch(S=>{S.name!=="AbortError"&&(m=null,R(S),T())})}function Y(){h++,a.value=h,r.value="reconnecting",f=setTimeout(()=>{f=null,b()},d),d=Math.min(d*2,t.reconnectMaxDelay)}function b(){t.mode==="fetch"?z():A()}let y={status:r,connected:o,lastMessage:s,lastEvent:i,error:c,reconnectCount:a,on(p,S){return l[p].push(S),()=>{let k=l[p],M=k.indexOf(S);M>=0&&k.splice(M,1)}},pipe(p,S){let k=M=>{p.value=S(M,p.value)};return y.on("message",k)},close(){u=!0,f&&(clearTimeout(f),f=null),g&&(g.close(),g=null),m&&(m.abort(),m=null),r.value="closed",o.value=!1}};return b(),y}var Pe={connect:bt};async function X(e="/api/rtc/config"){let n=await fetch(e);if(!n.ok)throw new Error(`[tina4] rtc config fetch failed: ${n.status}`);return n.json()}function wt(){let e=window.location;return`${e.protocol==="https:"?"wss:":"ws:"}//${e.host}`}function Le(e){return/^wss?:\/\//.test(e)?e:wt()+(e.startsWith("/")?e:"/"+e)}function Tt(){let e=globalThis.crypto;if(e&&"randomUUID"in e)return e.randomUUID().slice(0,8);let n="";for(let t=0;t<8;t++)n+=Math.floor(16*(.5+t)).toString(16);return n+Date.now().toString(16).slice(-4)}async function kt(e,n={}){let t=w("connecting"),r=w(null),o=w([]),s=w(!1),i=w(null),c=Tt(),a=n.config??await X(n.configUrl),l=n.iceServers??a.iceServers??[],g=n.signallingUrl??a.signalling??"/ws/rtc",m=Le(g.includes("{room}")?g.replace("{room}",e):`${g}/${e}`),u=null;n.media instanceof MediaStream?u=n.media:n.media!==!1&&(u=await navigator.mediaDevices.getUserMedia(n.media??{audio:!0,video:!0})),r.value=u;let d=u?.getVideoTracks()[0]??null,f=new Map,h=K.connect(m);function x(){o.value=[...f.entries()].map(([b,y])=>({id:b,stream:y.stream}))}function C(b){try{h.send({...b,from:c})}catch{}}function v(b){let y=f.get(b);if(y)return y;let p=new RTCPeerConnection({iceServers:l}),S={pc:p,polite:c<b,makingOffer:!1,ignoreOffer:!1,stream:null};if(f.set(b,S),u)for(let k of u.getTracks())p.addTrack(k,u);return p.onnegotiationneeded=async()=>{try{S.makingOffer=!0,await p.setLocalDescription(),C({type:"desc",to:b,description:p.localDescription})}catch(k){i.value=k}finally{S.makingOffer=!1}},p.onicecandidate=({candidate:k})=>{k&&C({type:"ice",to:b,candidate:k})},p.ontrack=({streams:k})=>{S.stream=k[0]??null,x()},p.onconnectionstatechange=()=>{["failed","closed"].includes(p.connectionState)?T(b):p.connectionState==="connected"&&(t.value="connected")},x(),S}function T(b){let y=f.get(b);if(y){try{y.pc.close()}catch{}f.delete(b),x()}}async function R(b){let y=b,p=y.from;if(!p||p===c||y.to&&y.to!==c)return;if(y.type==="hello"){v(p),C({type:"welcome",to:p});return}if(y.type==="welcome"){v(p);return}if(y.type==="bye"){T(p);return}let S=v(p),k=S.pc;if(y.type==="desc"){let M=y.description,P=M.type==="offer"&&(S.makingOffer||k.signalingState!=="stable");if(S.ignoreOffer=!S.polite&&P,S.ignoreOffer)return;await k.setRemoteDescription(M),M.type==="offer"&&(await k.setLocalDescription(),C({type:"desc",to:p,description:k.localDescription}))}else if(y.type==="ice")try{await k.addIceCandidate(y.candidate)}catch(M){S.ignoreOffer||(i.value=M)}}h.on("message",b=>{R(b)}),h.on("open",()=>{C({type:"hello"})});async function A(b){if(b)for(let{pc:y}of f.values()){let p=y.getSenders().find(S=>S.track?.kind==="video");p&&await p.replaceTrack(b)}}async function z(){await A(d),s.value=!1}async function Y(){let y=(await navigator.mediaDevices.getDisplayMedia({video:!0})).getVideoTracks()[0];await A(y),y.onended=()=>{z()},s.value=!0}return{status:t,localStream:r,peers:o,screenSharing:s,error:i,id:c,shareScreen:Y,stopScreen:z,toggleAudio(b){let y=u?.getAudioTracks()[0];return y?(y.enabled=b??!y.enabled,y.enabled):!1},toggleVideo(b){let y=u?.getVideoTracks()[0];return y?(y.enabled=b??!y.enabled,y.enabled):!1},leave(){C({type:"bye"});for(let b of[...f.keys()])T(b);if(u)for(let b of u.getTracks())b.stop();h.close(),t.value="closed"}}}function Ct(e,n={}){let t=w([]),r=w([]),o=w([]),s=new Map,i=n.typingTimeout??3e3,c=n.url??"/ws/chat",a=Le(c.includes("{channel}")?c.replace("{channel}",String(e)):`${c}/${e}`),l=K.connect(a,{token:n.token});function g(d){o.value.includes(d)||(o.value=[...o.value,d]);let f=s.get(d);f&&clearTimeout(f),s.set(d,setTimeout(()=>{o.value=o.value.filter(h=>h!==d),s.delete(d)},i))}l.on("message",d=>{let f=d;switch(f.type){case"message":t.value=[...t.value,f.message];break;case"presence":f.event==="roster"?r.value=f.users??[]:f.event==="join"&&f.user_id?r.value=[...new Set([...r.value,f.user_id])]:f.event==="leave"&&(r.value=r.value.filter(h=>h!==f.user_id));break;case"typing":f.user_id&&g(f.user_id);break}});let m=n.apiBase??"",u=n.messagesPath??"/api/channels/{id}/messages";return{status:l.status,connected:l.connected,messages:t,presence:r,typing:o,send(d,f){l.send({type:"message",body:d,thread_id:f??null})},sendTyping(){l.send({type:"typing"})},markRead(){l.send({type:"read"})},async history(d,f=50){let h=u.replace("{id}",String(e)),x=new URLSearchParams({limit:String(f)});d&&x.set("before",String(d));let C={};n.token&&(C.Authorization=`Bearer ${n.token}`);let v=await fetch(`${m}${h}?${x}`,{headers:C});if(!v.ok)throw new Error(`[tina4] chat history failed: ${v.status}`);let T=await v.json(),R=[...T].reverse();return t.value=[...R,...t.value],T},close(){for(let d of s.values())clearTimeout(d);s.clear(),l.close()}}}async function Et(e,n,t={}){let r=t.filesPath??"/api/files",o=new FormData;o.append("channel_id",String(e)),o.append("file",n,n.name??"file");let s={};t.token&&(s.Authorization=`Bearer ${t.token}`);let i=await fetch(`${t.apiBase??""}${r}`,{method:"POST",body:o,headers:s});if(!i.ok)throw new Error(`[tina4] file upload failed: ${i.status}`);return i.json()}async function Rt(e,n={}){let t=/^https?:\/\//.test(e)?e:`${n.apiBase??""}${n.filesPath??"/api/files"}/${e}`,r={};n.token&&(r.Authorization=`Bearer ${n.token}`);let o=await fetch(t,{headers:r});if(!o.ok)throw new Error(`[tina4] file fetch failed: ${o.status}`);return URL.createObjectURL(await o.blob())}var De={config:X,call:kt,chat:Ct,upload:Et,fetchBlob:Rt};var Fe={read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},$e=/(token|password|passwd|secret|api[_-]?key|apikey|auth(?!or)|credential|jwt|bearer|otp|seed|private[_-]?key|session[_-]?id)/i,_t=/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}$/,xt=/^[A-Za-z0-9+/_=-]{40,}$/,qe=new Set;function Mt(e,n){if($e.test(e))return`key name "${e}" looks like a credential`;if(typeof n=="string"){if(_t.test(n))return"value looks like a JWT";if(n.length>=40&&xt.test(n))return"value looks like a long base64 / token"}if(n&&typeof n=="object"&&!Array.isArray(n)){for(let t of Object.keys(n))if($e.test(t))return`object contains a credential-shape field "${t}"`}return null}function Ot(e,n){qe.has(n)||(qe.add(n),console.warn(`[tina4 persist] ${e} (key: ${JSON.stringify(n)}). localStorage is XSS-readable and never appropriate for credentials, tokens, passwords, personal data, or secrets. See STORAGE.md.`))}function He(e){if(typeof globalThis>"u")return null;try{let n=e==="local"?globalThis.localStorage:globalThis.sessionStorage;return!n||typeof n.getItem!="function"?null:n}catch{return null}}function je(e,n,t){try{let r=JSON.parse(e);return r&&typeof r=="object"&&"value"in r?{version:r.v,payload:r.value}:{version:void 0,payload:r}}catch{return{version:void 0,payload:t?e:n.read(e)}}}function We(e,n,t){return t?e:n.read(typeof e=="string"?e:JSON.stringify(e))}function At(e,n,t,r,o,s,i){try{let c=n.getItem(t);if(c===null)return;let a=je(c,o,s);if(a.version===r||a.version===void 0){e.value=We(a.payload,o,s);return}if(i){try{e.value=i(a.payload,a.version)}catch(l){console.warn(`[tina4 persist] migrate() threw for key "${t}":`,l)}return}console.warn(`[tina4 persist] stored version ${a.version} does not match current ${r} for key "${t}", and no migrate() was provided. Discarding the stored value.`)}catch(c){console.warn(`[tina4 persist] failed to read key "${t}":`,c)}}function Ke(e,n,t){if(t)return;let r=Mt(e,n);r&&Ot(r,e)}function It(e,n,t,r,o,s,i){return E(()=>{let c=e.value;Ke(t,c,i);try{let a=JSON.stringify(s?{v:r,value:c}:{v:r,value:o.write(c)});n.setItem(t,a)}catch(a){console.warn(`[tina4 persist] failed to write key "${t}":`,a)}})}function Nt(e,n,t,r,o,s,i,c){if(!c||typeof globalThis>"u"||!("addEventListener"in globalThis))return null;let a=l=>{let g=l;if(!(g.storageArea!==n||g.key!==t||g.newValue===null))try{let m=je(g.newValue,o,s);m.version!==void 0&&m.version!==r&&i?e.value=i(m.payload,m.version):(m.version===r||m.version===void 0)&&(e.value=We(m.payload,o,s))}catch(m){console.warn(`[tina4 persist] failed to parse storage event for key "${t}":`,m)}};return globalThis.addEventListener?.("storage",a),()=>{globalThis.removeEventListener?.("storage",a)}}function Pt(e,n){try{e.removeItem(n)}catch(t){console.warn(`[tina4 persist] failed to clear key "${n}":`,t)}}function ze(e,n){let{key:t,storage:r="local",serializer:o=Fe,version:s=1,migrate:i,syncTabs:c=!1,silenceCredentialWarning:a=!1}=n;if(!t||typeof t!="string")throw new Error("[tina4 persist] options.key is required and must be a string");let l=o===Fe,g=He(r);if(!g)return Ue(e,()=>{},()=>{});At(e,g,t,s,o,l,i),Ke(t,e.peek(),a);let m=It(e,g,t,s,o,l,a),u=Nt(e,g,t,s,o,l,i,c);return Ue(e,()=>Pt(g,t),()=>{m(),u&&u()})}function Ue(e,n,t){return Object.assign(e,{clear:n,dispose:t})}function Ve(e,n="local"){let t=He(n);if(t)for(let r of e)try{t.removeItem(r)}catch(o){console.warn(`[tina4 persist] failed to clear key "${r}":`,o)}}var Lt=["ar","he","fa","ur","ps","dv","syr","ckb","yi"];function Dt(){return globalThis.navigator?.language||"en"}function Be(e,n="",t={}){for(let[r,o]of Object.entries(e)){let s=n?`${n}.${r}`:r;if(o!==null&&typeof o=="object"&&!Array.isArray(o))Be(o,s,t);else{let i=String(o);t[s]=i,r in t||(t[r]=i)}}return t}function Ft(e,n){return e.replace(/\{(\w+)\}/g,(t,r)=>Object.prototype.hasOwnProperty.call(n,r)?String(n[r]):t)}function de(e={}){let n=e.locale||Dt(),t=e.fallbackLocale||n,r=new Set([...Lt,...e.rtlLocales||[]]),o=w(n,"i18n.locale"),s=new Map,i=new Map;function c(u,d){let f=Be(d),h=s.get(u);s.set(u,h?{...h,...f}:f)}if(e.messages)for(let[u,d]of Object.entries(e.messages))c(u,d);function a(u,d){return s.get(u)?.[d]}function l(u,d){let f=`n|${u}|${JSON.stringify(d||{})}`,h=i.get(f);return h||(h=new Intl.NumberFormat(u,d),i.set(f,h)),h}function g(u,d){let f=`d|${u}|${JSON.stringify(d||{})}`,h=i.get(f);return h||(h=new Intl.DateTimeFormat(u,d),i.set(f,h)),h}function m(u,d){let f=`r|${u}|${JSON.stringify(d||{})}`,h=i.get(f);return h||(h=new Intl.RelativeTimeFormat(u,d),i.set(f,h)),h}return{locale:o,t(u,d){let f=o.value,h=a(f,u);return h===void 0&&t!==f&&(h=a(t,u)),h===void 0&&(h=u),d?Ft(h,d):h},setLocale(u){o.value=u},getLocale(){return o.value},addMessages:c,hasLocale(u){return s.has(u)},availableLocales(){return[...s.keys()].sort()},async loadMessages(u,d){let f=await fetch(d);if(!f.ok)throw new Error(`[tina4 i18n] failed to load "${u}" from ${d}: ${f.status}`);c(u,await f.json())},number(u,d){return l(o.value,d).format(u)},currency(u,d,f){return l(o.value,{style:"currency",currency:d,...f}).format(u)},date(u,d){let f=u instanceof Date?u:new Date(u);return g(o.value,d).format(f)},relativeTime(u,d,f){return m(o.value,f||{numeric:"auto"}).format(u,d)},isRTL(){return r.has(o.value.split("-")[0].toLowerCase())},dir(){return this.isRTL()?"rtl":"ltr"}}}var Je=de();return rt($t);})();
56
+ `.trim()}function Ke(e){let n={name:e.name,short_name:e.shortName??e.name,start_url:"/",display:e.display??"standalone",background_color:e.backgroundColor??"#ffffff",theme_color:e.themeColor??"#000000"};return e.icon&&(n.icons=[{src:e.icon,sizes:"192x192",type:"image/png"},{src:e.icon,sizes:"512x512",type:"image/png"}]),n}var ze={register(e){let n=Ke(e),t=new Blob([JSON.stringify(n)],{type:"application/json"}),r=document.createElement("link");r.rel="manifest",r.href=URL.createObjectURL(t),document.head.appendChild(r);let o=document.querySelector('meta[name="theme-color"]');o||(o=document.createElement("meta"),o.name="theme-color",document.head.appendChild(o)),o.content=e.themeColor??"#000000","serviceWorker"in navigator&&(e.swUrl?navigator.serviceWorker.register(e.swUrl).catch(s=>{console.warn("[tina4] Service worker registration failed:",s)}):navigator.serviceWorker.register("/sw.js").catch(()=>{console.info("[tina4] No service worker at /sw.js. Use pwa.generateServiceWorker() to create one, or pass swUrl in config.")}))},generateServiceWorker(e){return Nt(e)},generateManifest(e){return Ke(e)}};function Be(e){let n=e.replace(/-/g,"+").replace(/_/g,"/"),t=atob(n+"=".repeat((4-n.length%4)%4));return Uint8Array.from(t,r=>r.charCodeAt(0))}function It(e){let n=e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength),t="";for(let r of n)t+=String.fromCharCode(r);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function Se(){if(typeof navigator>"u"||!("serviceWorker"in navigator)||typeof PushManager>"u")throw new Error("Web Push is not supported in this browser");if(typeof Notification>"u")throw new Error("Web Push requires the browser Notification API")}async function be(e){return Se(),e.serviceWorker??navigator.serviceWorker.ready}var Ve={supported(){return typeof navigator<"u"&&"serviceWorker"in navigator&&typeof PushManager<"u"&&typeof Notification<"u"},async permission(){return Se(),Notification.permission},async requestPermission(){return Se(),Notification.requestPermission()},async subscribe(e){let n=await be(e),t=Notification.permission==="granted"?"granted":await Notification.requestPermission();if(t!=="granted")throw new Error(`Web Push permission was ${t}`);let r=typeof e.applicationServerKey=="string"?Be(e.applicationServerKey):e.applicationServerKey,o=await n.pushManager.subscribe({userVisibleOnly:e.userVisibleOnly??!0,applicationServerKey:r});return this.serialize(o)},async current(e={}){let t=await(await be({applicationServerKey:new Uint8Array,...e})).pushManager.getSubscription();return t?this.serialize(t):null},async unsubscribe(e={}){let t=await(await be({applicationServerKey:new Uint8Array,...e})).pushManager.getSubscription();return t?t.unsubscribe():!1},serialize(e){let n=e.toJSON(),t=n.keys?.p256dh,r=n.keys?.auth;if(!t||!r)throw new Error("Browser returned an incomplete Web Push subscription");return{endpoint:e.endpoint,keys:{p256dh:t,auth:r}}},decodeApplicationServerKey:Be,encodeKey:It};var Lt={reconnect:!0,reconnectDelay:1e3,reconnectMaxDelay:3e4,reconnectAttempts:1/0,protocols:[],token:""};function Dt(e){let n=Array.isArray(e.protocols)?e.protocols:e.protocols?[e.protocols]:[];return e.token?["bearer",e.token,...n]:e.protocols}function Ft(e,n={}){let t={...Lt,...n},r=w("connecting"),o=w(!1),s=w(null),a=w(null),i=w(0),l={message:[],open:[],close:[],error:[]},c=null,d=!1,m=t.reconnectDelay,u=null,p=0;function f(y){if(typeof y!="string")return y;try{return JSON.parse(y)}catch{return y}}function h(){r.value=p>0?"reconnecting":"connecting";try{c=new WebSocket(e,Dt(t))}catch{r.value="closed",o.value=!1;return}c.onopen=()=>{r.value="open",o.value=!0,a.value=null,p=0,m=t.reconnectDelay,i.value=0;for(let y of l.open)y()},c.onmessage=y=>{let k=f(y.data);s.value=k;for(let _ of l.message)_(k)},c.onclose=y=>{r.value="closed",o.value=!1;for(let k of l.close)k(y.code,y.reason);!d&&t.reconnect&&p<t.reconnectAttempts&&R()},c.onerror=y=>{a.value=y;for(let k of l.error)k(y)}}function R(){p++,i.value=p,r.value="reconnecting",u=setTimeout(()=>{u=null,h()},m),m=Math.min(m*2,t.reconnectMaxDelay)}let C={status:r,connected:o,lastMessage:s,error:a,reconnectCount:i,send(y){if(!c||c.readyState!==WebSocket.OPEN)throw new Error("[tina4] WebSocket is not connected");let k=typeof y=="string"?y:JSON.stringify(y);c.send(k)},on(y,k){return l[y].push(k),()=>{let _=l[y],O=_.indexOf(k);O>=0&&_.splice(O,1)}},pipe(y,k){let _=O=>{y.value=k(O,y.value)};return C.on("message",_)},close(y,k){d=!0,u&&(clearTimeout(u),u=null),c&&c.close(y??1e3,k??""),r.value="closed",o.value=!1}};return h(),C}var G={connect:Ft};var Ut={mode:"eventsource",method:"GET",headers:{},body:void 0,reconnect:!0,reconnectDelay:1e3,reconnectMaxDelay:3e4,reconnectAttempts:1/0,events:[],json:!0};function $t(){let e="",n=/\r?\n\r?\n/g,t=r=>{let o=null,s=[];for(let i of r.split(/\r?\n/)){if(!i||i[0]===":")continue;let l=i.indexOf(":"),c=l<0?i:i.slice(0,l),d=l<0?"":i.slice(l+1);d.charCodeAt(0)===32&&(d=d.slice(1)),c==="data"?s.push(d):c==="event"&&(o=d)}if(!s.length)return null;let a=s.join(`
57
+ `);return{data:a,name:o,done:a==="[DONE]"}};return{push(r){e+=r;let o=[],s=0;n.lastIndex=0;let a;for(;a=n.exec(e);){let i=t(e.slice(s,a.index));s=n.lastIndex,i&&o.push(i)}return s&&(e=e.slice(s)),o},flush(){if(!e)return[];let r=t(e);return e="",r?[r]:[]}}}function qt(e,n={}){let t={...Ut,...n},r=w("connecting"),o=w(!1),s=w(null),a=w(null),i=w(null),l=w(0),c={message:[],open:[],close:[],error:[]},d=null,m=null,u=!1,p=t.reconnectDelay,f=null,h=0;function R(g){if(!t.json||typeof g!="string")return g;try{return JSON.parse(g)}catch{return g}}function C(g,b){s.value=g,a.value=b;for(let T of c.message)T(g,b??void 0)}function y(){r.value="open",o.value=!0,i.value=null,h=0,p=t.reconnectDelay,l.value=0;for(let g of c.open)g()}function k(){r.value="closed",o.value=!1;for(let g of c.close)g();!u&&t.reconnect&&h<t.reconnectAttempts&&oe()}function _(g){i.value=g;for(let b of c.error)b(g)}function O(){r.value=h>0?"reconnecting":"connecting";try{d=new EventSource(e)}catch{r.value="closed",o.value=!1;return}d.onopen=()=>y(),d.onmessage=g=>{C(R(g.data),null)};for(let g of t.events)d.addEventListener(g,(b=>{C(R(b.data),g)}));d.onerror=g=>{_(g),d&&d.readyState===2&&(d=null,k())}}function Z(){r.value=h>0?"reconnecting":"connecting",m=new AbortController;let g={method:t.method,headers:t.headers,signal:m.signal};t.body!==void 0&&(g.body=typeof t.body=="string"?t.body:JSON.stringify(t.body)),fetch(e,g).then(async b=>{if(!b.ok){_(new Error(`[tina4] SSE fetch ${b.status}`)),k();return}y();let T=b.body.getReader(),A=new TextDecoder;if((b.headers.get("content-type")||"").toLowerCase().startsWith("text/event-stream")){let N=$t(),F=!1;for(;!F;){let{done:I,value:se}=await T.read();if(I)break;for(let U of N.push(A.decode(se,{stream:!0}))){if(U.done){F=!0;break}C(R(U.data),U.name)}}if(F)T.cancel().catch(()=>{});else for(let I of N.flush()){if(I.done)break;C(R(I.data),I.name)}}else{let N="";for(;;){let{done:I,value:se}=await T.read();if(I)break;N+=A.decode(se,{stream:!0});let U=N.split(`
58
+ `);N=U.pop();for(let dt of U){let Te=dt.trim();Te&&C(R(Te),null)}}let F=N.trim();F&&C(R(F),null)}m=null,k()}).catch(b=>{b.name!=="AbortError"&&(m=null,_(b),k())})}function oe(){h++,l.value=h,r.value="reconnecting",f=setTimeout(()=>{f=null,S()},p),p=Math.min(p*2,t.reconnectMaxDelay)}function S(){t.mode==="fetch"?Z():O()}let v={status:r,connected:o,lastMessage:s,lastEvent:a,error:i,reconnectCount:l,on(g,b){return c[g].push(b),()=>{let T=c[g],A=T.indexOf(b);A>=0&&T.splice(A,1)}},pipe(g,b){let T=A=>{g.value=b(A,g.value)};return v.on("message",T)},close(){u=!0,f&&(clearTimeout(f),f=null),d&&(d.close(),d=null),m&&(m.abort(),m=null),r.value="closed",o.value=!1}};return S(),v}var ne={connect:qt};function Wt(e){return!!e&&typeof e=="object"&&typeof e.type=="string"}var Je={async*stream(e,n){let{headers:t,...r}=n,o=[],s=null,a=!1,i=()=>{let c=s;s=null,c?.()},l=ne.connect(e,{mode:"fetch",method:"POST",headers:{"Content-Type":"application/json",...t||{}},body:r,json:!0,reconnect:!1});l.on("message",c=>{Wt(c)&&(o.push(c),i())}),l.on("close",()=>{a=!0,i()}),l.on("error",c=>{o.push({type:"error",message:c instanceof Error?c.message:String(c)}),a=!0,i()});try{for(;;){for(;o.length>0;){let c=o.shift();if(yield c,c.type==="done"||c.type==="error")return}if(a)return;await new Promise(c=>{s=c})}}finally{l.close()}}};async function re(e="/api/rtc/config"){let n=await fetch(e);if(!n.ok)throw new Error(`[tina4] rtc config fetch failed: ${n.status}`);return n.json()}function Ht(){let e=window.location;return`${e.protocol==="https:"?"wss:":"ws:"}//${e.host}`}function Ze(e){return/^wss?:\/\//.test(e)?e:Ht()+(e.startsWith("/")?e:"/"+e)}function jt(){let e=globalThis.crypto;if(e&&"randomUUID"in e)return e.randomUUID().slice(0,8);let n="";for(let t=0;t<8;t++)n+=Math.floor(16*(.5+t)).toString(16);return n+Date.now().toString(16).slice(-4)}async function Kt(e,n={}){let t=w("connecting"),r=w(null),o=w([]),s=w(!1),a=w(null),i=jt(),l=n.config??await re(n.configUrl),c=n.iceServers??l.iceServers??[],d=n.signallingUrl??l.signalling??"/ws/rtc",m=Ze(d.includes("{room}")?d.replace("{room}",e):`${d}/${e}`),u=null;n.media instanceof MediaStream?u=n.media:n.media!==!1&&(u=await navigator.mediaDevices.getUserMedia(n.media??{audio:!0,video:!0})),r.value=u;let p=u?.getVideoTracks()[0]??null,f=new Map,h=G.connect(m);function R(){o.value=[...f.entries()].map(([S,v])=>({id:S,stream:v.stream}))}function C(S){try{h.send({...S,from:i})}catch{}}function y(S){let v=f.get(S);if(v)return v;let g=new RTCPeerConnection({iceServers:c}),b={pc:g,polite:i<S,makingOffer:!1,ignoreOffer:!1,stream:null};if(f.set(S,b),u)for(let T of u.getTracks())g.addTrack(T,u);return g.onnegotiationneeded=async()=>{try{b.makingOffer=!0,await g.setLocalDescription(),C({type:"desc",to:S,description:g.localDescription})}catch(T){a.value=T}finally{b.makingOffer=!1}},g.onicecandidate=({candidate:T})=>{T&&C({type:"ice",to:S,candidate:T})},g.ontrack=({streams:T})=>{b.stream=T[0]??null,R()},g.onconnectionstatechange=()=>{["failed","closed"].includes(g.connectionState)?k(S):g.connectionState==="connected"&&(t.value="connected")},R(),b}function k(S){let v=f.get(S);if(v){try{v.pc.close()}catch{}f.delete(S),R()}}async function _(S){let v=S,g=v.from;if(!g||g===i||v.to&&v.to!==i)return;if(v.type==="hello"){y(g),C({type:"welcome",to:g});return}if(v.type==="welcome"){y(g);return}if(v.type==="bye"){k(g);return}let b=y(g),T=b.pc;if(v.type==="desc"){let A=v.description,ke=A.type==="offer"&&(b.makingOffer||T.signalingState!=="stable");if(b.ignoreOffer=!b.polite&&ke,b.ignoreOffer)return;await T.setRemoteDescription(A),A.type==="offer"&&(await T.setLocalDescription(),C({type:"desc",to:g,description:T.localDescription}))}else if(v.type==="ice")try{await T.addIceCandidate(v.candidate)}catch(A){b.ignoreOffer||(a.value=A)}}h.on("message",S=>{_(S)}),h.on("open",()=>{C({type:"hello"})});async function O(S){if(S)for(let{pc:v}of f.values()){let g=v.getSenders().find(b=>b.track?.kind==="video");g&&await g.replaceTrack(S)}}async function Z(){await O(p),s.value=!1}async function oe(){let v=(await navigator.mediaDevices.getDisplayMedia({video:!0})).getVideoTracks()[0];await O(v),v.onended=()=>{Z()},s.value=!0}return{status:t,localStream:r,peers:o,screenSharing:s,error:a,id:i,shareScreen:oe,stopScreen:Z,toggleAudio(S){let v=u?.getAudioTracks()[0];return v?(v.enabled=S??!v.enabled,v.enabled):!1},toggleVideo(S){let v=u?.getVideoTracks()[0];return v?(v.enabled=S??!v.enabled,v.enabled):!1},leave(){C({type:"bye"});for(let S of[...f.keys()])k(S);if(u)for(let S of u.getTracks())S.stop();h.close(),t.value="closed"}}}function zt(e,n={}){let t=w([]),r=w([]),o=w([]),s=new Map,a=n.typingTimeout??3e3,i=n.url??"/ws/chat",l=Ze(i.includes("{channel}")?i.replace("{channel}",String(e)):`${i}/${e}`),c=G.connect(l,{token:n.token});function d(p){o.value.includes(p)||(o.value=[...o.value,p]);let f=s.get(p);f&&clearTimeout(f),s.set(p,setTimeout(()=>{o.value=o.value.filter(h=>h!==p),s.delete(p)},a))}c.on("message",p=>{let f=p;switch(f.type){case"message":t.value=[...t.value,f.message];break;case"presence":f.event==="roster"?r.value=f.users??[]:f.event==="join"&&f.user_id?r.value=[...new Set([...r.value,f.user_id])]:f.event==="leave"&&(r.value=r.value.filter(h=>h!==f.user_id));break;case"typing":f.user_id&&d(f.user_id);break}});let m=n.apiBase??"",u=n.messagesPath??"/api/channels/{id}/messages";return{status:c.status,connected:c.connected,messages:t,presence:r,typing:o,send(p,f){c.send({type:"message",body:p,thread_id:f??null})},sendTyping(){c.send({type:"typing"})},markRead(){c.send({type:"read"})},async history(p,f=50){let h=u.replace("{id}",String(e)),R=new URLSearchParams({limit:String(f)});p&&R.set("before",String(p));let C={};n.token&&(C.Authorization=`Bearer ${n.token}`);let y=await fetch(`${m}${h}?${R}`,{headers:C});if(!y.ok)throw new Error(`[tina4] chat history failed: ${y.status}`);let k=await y.json(),_=[...k].reverse();return t.value=[..._,...t.value],k},close(){for(let p of s.values())clearTimeout(p);s.clear(),c.close()}}}function Ge(e){try{return new URL(e,typeof location<"u"?location.href:void 0).origin}catch{return null}}function Qe(e,n){let t=Ge(e);if(t===null)return!1;if(typeof location<"u"&&t===location.origin)return!0;let r=n?Ge(n):null;return r!==null&&t===r}async function Bt(e,n,t={}){let r=t.filesPath??"/api/files",o=`${t.apiBase??""}${r}`,s=new FormData;s.append("channel_id",String(e)),s.append("file",n,n.name??"file");let a={};t.token&&Qe(o,t.apiBase)&&(a.Authorization=`Bearer ${t.token}`);let i=await fetch(o,{method:"POST",body:s,headers:a});if(!i.ok)throw new Error(`[tina4] file upload failed: ${i.status}`);return i.json()}async function Vt(e,n={}){let t=/^https?:\/\//.test(e)?e:`${n.apiBase??""}${n.filesPath??"/api/files"}/${e}`,r={};n.token&&Qe(t,n.apiBase)&&(r.Authorization=`Bearer ${n.token}`);let o=await fetch(t,{headers:r});if(!o.ok)throw new Error(`[tina4] file fetch failed: ${o.status}`);return URL.createObjectURL(await o.blob())}var Xe={config:re,call:Kt,chat:zt,upload:Bt,fetchBlob:Vt};var Ye={read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},et=/(token|password|passwd|secret|api[_-]?key|apikey|auth(?!or)|credential|jwt|bearer|otp|seed|private[_-]?key|session[_-]?id)/i,Jt=/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}$/,Gt=/^[A-Za-z0-9+/_=-]{40,}$/,tt=new Set;function Zt(e,n){if(et.test(e))return`key name "${e}" looks like a credential`;if(typeof n=="string"){if(Jt.test(n))return"value looks like a JWT";if(n.length>=40&&Gt.test(n))return"value looks like a long base64 / token"}if(n&&typeof n=="object"&&!Array.isArray(n)){for(let t of Object.keys(n))if(et.test(t))return`object contains a credential-shape field "${t}"`}return null}function Qt(e,n){tt.has(n)||(tt.add(n),console.warn(`[tina4 persist] ${e} (key: ${JSON.stringify(n)}). localStorage is XSS-readable and never appropriate for credentials, tokens, passwords, personal data, or secrets. See STORAGE.md.`))}function rt(e){if(typeof globalThis>"u")return null;try{let n=e==="local"?globalThis.localStorage:globalThis.sessionStorage;return!n||typeof n.getItem!="function"?null:n}catch{return null}}function ot(e,n,t){try{let r=JSON.parse(e);return r&&typeof r=="object"&&"value"in r?{version:r.v,payload:r.value}:{version:void 0,payload:r}}catch{return{version:void 0,payload:t?e:n.read(e)}}}function st(e,n,t){return t?e:n.read(typeof e=="string"?e:JSON.stringify(e))}function Xt(e,n,t,r,o,s,a){try{let i=n.getItem(t);if(i===null)return;let l=ot(i,o,s);if(l.version===r||l.version===void 0){e.value=st(l.payload,o,s);return}if(a){try{e.value=a(l.payload,l.version)}catch(c){console.warn(`[tina4 persist] migrate() threw for key "${t}":`,c)}return}console.warn(`[tina4 persist] stored version ${l.version} does not match current ${r} for key "${t}", and no migrate() was provided. Discarding the stored value.`)}catch(i){console.warn(`[tina4 persist] failed to read key "${t}":`,i)}}function it(e,n,t){if(t)return;let r=Zt(e,n);r&&Qt(r,e)}function Yt(e,n,t,r,o,s,a){return x(()=>{let i=e.value;it(t,i,a);try{let l=JSON.stringify(s?{v:r,value:i}:{v:r,value:o.write(i)});n.setItem(t,l)}catch(l){console.warn(`[tina4 persist] failed to write key "${t}":`,l)}})}function en(e,n,t,r,o,s,a,i){if(!i||typeof globalThis>"u"||!("addEventListener"in globalThis))return null;let l=c=>{let d=c;if(!(d.storageArea!==n||d.key!==t||d.newValue===null))try{let m=ot(d.newValue,o,s);m.version!==void 0&&m.version!==r&&a?e.value=a(m.payload,m.version):(m.version===r||m.version===void 0)&&(e.value=st(m.payload,o,s))}catch(m){console.warn(`[tina4 persist] failed to parse storage event for key "${t}":`,m)}};return globalThis.addEventListener?.("storage",l),()=>{globalThis.removeEventListener?.("storage",l)}}function tn(e,n){try{e.removeItem(n)}catch(t){console.warn(`[tina4 persist] failed to clear key "${n}":`,t)}}function at(e,n){let{key:t,storage:r="local",serializer:o=Ye,version:s=1,migrate:a,syncTabs:i=!1,silenceCredentialWarning:l=!1}=n;if(!t||typeof t!="string")throw new Error("[tina4 persist] options.key is required and must be a string");let c=o===Ye,d=rt(r);if(!d)return nt(e,()=>{},()=>{});Xt(e,d,t,s,o,c,a),it(t,e.peek(),l);let m=Yt(e,d,t,s,o,c,l),u=en(e,d,t,s,o,c,a,i);return nt(e,()=>tn(d,t),()=>{m(),u&&u()})}function nt(e,n,t){return Object.assign(e,{clear:n,dispose:t})}function ct(e,n="local"){let t=rt(n);if(t)for(let r of e)try{t.removeItem(r)}catch(o){console.warn(`[tina4 persist] failed to clear key "${r}":`,o)}}var nn=["ar","he","fa","ur","ps","dv","syr","ckb","yi"];function rn(){return globalThis.navigator?.language||"en"}function lt(e,n="",t={}){for(let[r,o]of Object.entries(e)){let s=n?`${n}.${r}`:r;if(o!==null&&typeof o=="object"&&!Array.isArray(o))lt(o,s,t);else{let a=String(o);t[s]=a,r in t||(t[r]=a)}}return t}function on(e,n){return e.replace(/\{(\w+)\}/g,(t,r)=>Object.prototype.hasOwnProperty.call(n,r)?String(n[r]):t)}function we(e={}){let n=e.locale||rn(),t=e.fallbackLocale||n,r=new Set([...nn,...e.rtlLocales||[]]),o=w(n,"i18n.locale"),s=new Map,a=new Map;function i(u,p){let f=lt(p),h=s.get(u);s.set(u,h?{...h,...f}:f)}if(e.messages)for(let[u,p]of Object.entries(e.messages))i(u,p);function l(u,p){return s.get(u)?.[p]}function c(u,p){let f=`n|${u}|${JSON.stringify(p||{})}`,h=a.get(f);return h||(h=new Intl.NumberFormat(u,p),a.set(f,h)),h}function d(u,p){let f=`d|${u}|${JSON.stringify(p||{})}`,h=a.get(f);return h||(h=new Intl.DateTimeFormat(u,p),a.set(f,h)),h}function m(u,p){let f=`r|${u}|${JSON.stringify(p||{})}`,h=a.get(f);return h||(h=new Intl.RelativeTimeFormat(u,p),a.set(f,h)),h}return{locale:o,t(u,p){let f=o.value,h=l(f,u);return h===void 0&&t!==f&&(h=l(t,u)),h===void 0&&(h=u),p?on(h,p):h},setLocale(u){o.value=u},getLocale(){return o.value},addMessages:i,hasLocale(u){return s.has(u)},availableLocales(){return[...s.keys()].sort()},async loadMessages(u,p){let f=await fetch(p);if(!f.ok)throw new Error(`[tina4 i18n] failed to load "${u}" from ${p}: ${f.status}`);i(u,await f.json())},number(u,p){return c(o.value,p).format(u)},currency(u,p,f){return c(o.value,{style:"currency",currency:p,...f}).format(u)},date(u,p){let f=u instanceof Date?u:new Date(u);return d(o.value,p).format(f)},relativeTime(u,p,f){return m(o.value,f||{numeric:"auto"}).format(u,p)},isRTL(){return r.has(o.value.split("-")[0].toLowerCase())},dir(){return this.isRTL()?"rtl":"ltr"}}}var ut=we();return yt(sn);})();
@@ -0,0 +1,11 @@
1
+ Copyright 2018 SmartBear Software
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at [apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
@@ -0,0 +1,2 @@
1
+ swagger-ui
2
+ Copyright 2020-2021 SmartBear Software Inc.