@monolayer/sdk 1.2.0-canary.4

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 (320) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/dist/bin/cli.js +21609 -0
  4. package/dist/cjs/configuration.d.ts +65 -0
  5. package/dist/cjs/configuration.js +45 -0
  6. package/dist/cjs/index.d.ts +4 -0
  7. package/dist/cjs/index.js +20 -0
  8. package/dist/cjs/introspection.d.ts +2 -0
  9. package/dist/cjs/introspection.js +11 -0
  10. package/dist/cjs/make/broadcast.d.ts +10 -0
  11. package/dist/cjs/make/broadcast.js +37 -0
  12. package/dist/cjs/make/config.d.ts +2 -0
  13. package/dist/cjs/make/config.js +44 -0
  14. package/dist/cjs/make/cron.d.ts +9 -0
  15. package/dist/cjs/make/cron.js +30 -0
  16. package/dist/cjs/make/make.d.ts +6 -0
  17. package/dist/cjs/make/make.js +134 -0
  18. package/dist/cjs/make/manifest.d.ts +202 -0
  19. package/dist/cjs/make/manifest.js +165 -0
  20. package/dist/cjs/make/required-filtes.d.ts +1 -0
  21. package/dist/cjs/make/required-filtes.js +17 -0
  22. package/dist/cjs/make/task.d.ts +9 -0
  23. package/dist/cjs/make/task.js +30 -0
  24. package/dist/cjs/package.json +3 -0
  25. package/dist/cjs/packages/docker/df.d.ts +543 -0
  26. package/dist/cjs/packages/docker/df.js +395 -0
  27. package/dist/cjs/packages/docker/validator.d.ts +7 -0
  28. package/dist/cjs/packages/docker/validator.js +18 -0
  29. package/dist/cjs/packages/utils/create-file.d.ts +1 -0
  30. package/dist/cjs/packages/utils/create-file.js +18 -0
  31. package/dist/cjs/packages/utils/date-string.d.ts +1 -0
  32. package/dist/cjs/packages/utils/date-string.js +12 -0
  33. package/dist/cjs/packages/utils/exception.d.ts +1 -0
  34. package/dist/cjs/packages/utils/exception.js +8 -0
  35. package/dist/cjs/packages/utils/hash-value.d.ts +16 -0
  36. package/dist/cjs/packages/utils/hash-value.js +25 -0
  37. package/dist/cjs/packages/utils/import-default.d.ts +1 -0
  38. package/dist/cjs/packages/utils/import-default.js +14 -0
  39. package/dist/cjs/packages/utils/import-file.d.ts +8 -0
  40. package/dist/cjs/packages/utils/import-file.js +41 -0
  41. package/dist/cjs/packages/utils/log-with-spinner.d.ts +1 -0
  42. package/dist/cjs/packages/utils/log-with-spinner.js +24 -0
  43. package/dist/cjs/packages/utils/path.d.ts +2 -0
  44. package/dist/cjs/packages/utils/path.js +21 -0
  45. package/dist/cjs/packages/utils/playground.d.ts +1 -0
  46. package/dist/cjs/packages/utils/playground.js +35 -0
  47. package/dist/cjs/scaffolding/add-env-var.d.ts +6 -0
  48. package/dist/cjs/scaffolding/add-env-var.js +65 -0
  49. package/dist/cjs/scaffolding/add-import.d.ts +16 -0
  50. package/dist/cjs/scaffolding/add-import.js +43 -0
  51. package/dist/cjs/scaffolding/add-script.d.ts +1 -0
  52. package/dist/cjs/scaffolding/add-script.js +35 -0
  53. package/dist/cjs/scaffolding/broadcast-workload.d.ts +1 -0
  54. package/dist/cjs/scaffolding/broadcast-workload.js +36 -0
  55. package/dist/cjs/scaffolding/bucket-workload.d.ts +6 -0
  56. package/dist/cjs/scaffolding/bucket-workload.js +23 -0
  57. package/dist/cjs/scaffolding/cron-workload.d.ts +6 -0
  58. package/dist/cjs/scaffolding/cron-workload.js +28 -0
  59. package/dist/cjs/scaffolding/drizzle.d.ts +4 -0
  60. package/dist/cjs/scaffolding/drizzle.js +22 -0
  61. package/dist/cjs/scaffolding/lifecycle.d.ts +9 -0
  62. package/dist/cjs/scaffolding/lifecycle.js +61 -0
  63. package/dist/cjs/scaffolding/postgres-database-workload.d.ts +15 -0
  64. package/dist/cjs/scaffolding/postgres-database-workload.js +39 -0
  65. package/dist/cjs/scaffolding/prisma.d.ts +4 -0
  66. package/dist/cjs/scaffolding/prisma.js +40 -0
  67. package/dist/cjs/scaffolding/replace-string.d.ts +10 -0
  68. package/dist/cjs/scaffolding/replace-string.js +37 -0
  69. package/dist/cjs/scaffolding/task-workload.d.ts +6 -0
  70. package/dist/cjs/scaffolding/task-workload.js +30 -0
  71. package/dist/cjs/scaffolding/workload.d.ts +1 -0
  72. package/dist/cjs/scaffolding/workload.js +18 -0
  73. package/dist/cjs/scan/project.d.ts +23 -0
  74. package/dist/cjs/scan/project.js +79 -0
  75. package/dist/cjs/scan/workload-imports.d.ts +21 -0
  76. package/dist/cjs/scan/workload-imports.js +188 -0
  77. package/dist/cjs/test-helpers/postgres.d.ts +13 -0
  78. package/dist/cjs/test-helpers/postgres.js +52 -0
  79. package/dist/cjs/test-helpers/redis.d.ts +13 -0
  80. package/dist/cjs/test-helpers/redis.js +46 -0
  81. package/dist/cjs/test-helpers/task.d.ts +14 -0
  82. package/dist/cjs/test-helpers/task.js +18 -0
  83. package/dist/cjs/test-helpers.d.ts +3 -0
  84. package/dist/cjs/test-helpers.js +10 -0
  85. package/dist/cjs/workloads/app-lifecycle/after-rollout.d.ts +22 -0
  86. package/dist/cjs/workloads/app-lifecycle/after-rollout.js +28 -0
  87. package/dist/cjs/workloads/app-lifecycle/before-rollout.d.ts +22 -0
  88. package/dist/cjs/workloads/app-lifecycle/before-rollout.js +28 -0
  89. package/dist/cjs/workloads/app-lifecycle/bootstrap.d.ts +22 -0
  90. package/dist/cjs/workloads/app-lifecycle/bootstrap.js +28 -0
  91. package/dist/cjs/workloads/app-lifecycle/lifecycle-workload.d.ts +11 -0
  92. package/dist/cjs/workloads/app-lifecycle/lifecycle-workload.js +11 -0
  93. package/dist/cjs/workloads/assertions.d.ts +13 -0
  94. package/dist/cjs/workloads/assertions.js +14 -0
  95. package/dist/cjs/workloads/stateful/bucket.d.ts +82 -0
  96. package/dist/cjs/workloads/stateful/bucket.js +95 -0
  97. package/dist/cjs/workloads/stateful/database.d.ts +25 -0
  98. package/dist/cjs/workloads/stateful/database.js +42 -0
  99. package/dist/cjs/workloads/stateful/postgres-database.d.ts +29 -0
  100. package/dist/cjs/workloads/stateful/postgres-database.js +39 -0
  101. package/dist/cjs/workloads/stateful/redis.d.ts +30 -0
  102. package/dist/cjs/workloads/stateful/redis.js +40 -0
  103. package/dist/cjs/workloads/stateful/stateful-workload.d.ts +25 -0
  104. package/dist/cjs/workloads/stateful/stateful-workload.js +41 -0
  105. package/dist/cjs/workloads/stateless/broadcast/channel-data.d.ts +3 -0
  106. package/dist/cjs/workloads/stateless/broadcast/channel-data.js +6 -0
  107. package/dist/cjs/workloads/stateless/broadcast/client/app-sync-client.d.ts +78 -0
  108. package/dist/cjs/workloads/stateless/broadcast/client/app-sync-client.js +128 -0
  109. package/dist/cjs/workloads/stateless/broadcast/client/app-sync-publisher.d.ts +34 -0
  110. package/dist/cjs/workloads/stateless/broadcast/client/app-sync-publisher.js +78 -0
  111. package/dist/cjs/workloads/stateless/broadcast/client/authenticator.d.ts +28 -0
  112. package/dist/cjs/workloads/stateless/broadcast/client/authenticator.js +43 -0
  113. package/dist/cjs/workloads/stateless/broadcast/client/broadcast-provider.d.ts +17 -0
  114. package/dist/cjs/workloads/stateless/broadcast/client/broadcast-provider.js +34 -0
  115. package/dist/cjs/workloads/stateless/broadcast/client/client.d.ts +8 -0
  116. package/dist/cjs/workloads/stateless/broadcast/client/client.js +28 -0
  117. package/dist/cjs/workloads/stateless/broadcast/client/connectionManager.d.ts +62 -0
  118. package/dist/cjs/workloads/stateless/broadcast/client/connectionManager.js +166 -0
  119. package/dist/cjs/workloads/stateless/broadcast/client/eventEmitter.d.ts +32 -0
  120. package/dist/cjs/workloads/stateless/broadcast/client/eventEmitter.js +53 -0
  121. package/dist/cjs/workloads/stateless/broadcast/client/messageBuilder.d.ts +24 -0
  122. package/dist/cjs/workloads/stateless/broadcast/client/messageBuilder.js +43 -0
  123. package/dist/cjs/workloads/stateless/broadcast/client/parser.d.ts +12 -0
  124. package/dist/cjs/workloads/stateless/broadcast/client/parser.js +22 -0
  125. package/dist/cjs/workloads/stateless/broadcast/client/provider.d.ts +4 -0
  126. package/dist/cjs/workloads/stateless/broadcast/client/provider.js +11 -0
  127. package/dist/cjs/workloads/stateless/broadcast/client/subscriptionManager.d.ts +34 -0
  128. package/dist/cjs/workloads/stateless/broadcast/client/subscriptionManager.js +91 -0
  129. package/dist/cjs/workloads/stateless/broadcast/client/types.d.ts +72 -0
  130. package/dist/cjs/workloads/stateless/broadcast/client/types.js +6 -0
  131. package/dist/cjs/workloads/stateless/broadcast/matcher.d.ts +13 -0
  132. package/dist/cjs/workloads/stateless/broadcast/matcher.js +46 -0
  133. package/dist/cjs/workloads/stateless/broadcast/router.d.ts +103 -0
  134. package/dist/cjs/workloads/stateless/broadcast/router.js +98 -0
  135. package/dist/cjs/workloads/stateless/broadcast/types.d.ts +17 -0
  136. package/dist/cjs/workloads/stateless/broadcast/types.js +2 -0
  137. package/dist/cjs/workloads/stateless/cron.d.ts +49 -0
  138. package/dist/cjs/workloads/stateless/cron.js +55 -0
  139. package/dist/cjs/workloads/stateless/stateless-workload.d.ts +3 -0
  140. package/dist/cjs/workloads/stateless/stateless-workload.js +7 -0
  141. package/dist/cjs/workloads/stateless/task/backoffs.d.ts +9 -0
  142. package/dist/cjs/workloads/stateless/task/backoffs.js +17 -0
  143. package/dist/cjs/workloads/stateless/task/dispatcher.d.ts +3 -0
  144. package/dist/cjs/workloads/stateless/task/dispatcher.js +22 -0
  145. package/dist/cjs/workloads/stateless/task/local.d.ts +14 -0
  146. package/dist/cjs/workloads/stateless/task/local.js +54 -0
  147. package/dist/cjs/workloads/stateless/task/perform-later.d.ts +2 -0
  148. package/dist/cjs/workloads/stateless/task/perform-later.js +7 -0
  149. package/dist/cjs/workloads/stateless/task/perform-now.d.ts +5 -0
  150. package/dist/cjs/workloads/stateless/task/perform-now.js +24 -0
  151. package/dist/cjs/workloads/stateless/task/perform.d.ts +7 -0
  152. package/dist/cjs/workloads/stateless/task/perform.js +10 -0
  153. package/dist/cjs/workloads/stateless/task/task.d.ts +88 -0
  154. package/dist/cjs/workloads/stateless/task/task.js +61 -0
  155. package/dist/cjs/workloads/stateless/task/validate-data-size.d.ts +1 -0
  156. package/dist/cjs/workloads/stateless/task/validate-data-size.js +10 -0
  157. package/dist/cjs/workloads/workload.d.ts +14 -0
  158. package/dist/cjs/workloads/workload.js +16 -0
  159. package/dist/cjs/workloads.d.ts +22 -0
  160. package/dist/cjs/workloads.js +30 -0
  161. package/dist/esm/configuration.d.ts +65 -0
  162. package/dist/esm/configuration.js +15 -0
  163. package/dist/esm/index.d.ts +4 -0
  164. package/dist/esm/index.js +4 -0
  165. package/dist/esm/introspection.d.ts +2 -0
  166. package/dist/esm/introspection.js +2 -0
  167. package/dist/esm/make/broadcast.d.ts +10 -0
  168. package/dist/esm/make/broadcast.js +30 -0
  169. package/dist/esm/make/config.d.ts +2 -0
  170. package/dist/esm/make/config.js +41 -0
  171. package/dist/esm/make/cron.d.ts +9 -0
  172. package/dist/esm/make/cron.js +23 -0
  173. package/dist/esm/make/make.d.ts +6 -0
  174. package/dist/esm/make/make.js +120 -0
  175. package/dist/esm/make/manifest.d.ts +202 -0
  176. package/dist/esm/make/manifest.js +162 -0
  177. package/dist/esm/make/required-filtes.d.ts +1 -0
  178. package/dist/esm/make/required-filtes.js +11 -0
  179. package/dist/esm/make/task.d.ts +9 -0
  180. package/dist/esm/make/task.js +23 -0
  181. package/dist/esm/package.json +3 -0
  182. package/dist/esm/packages/docker/df.d.ts +543 -0
  183. package/dist/esm/packages/docker/df.js +381 -0
  184. package/dist/esm/packages/docker/validator.d.ts +7 -0
  185. package/dist/esm/packages/docker/validator.js +14 -0
  186. package/dist/esm/packages/utils/create-file.d.ts +1 -0
  187. package/dist/esm/packages/utils/create-file.js +11 -0
  188. package/dist/esm/packages/utils/date-string.d.ts +1 -0
  189. package/dist/esm/packages/utils/date-string.js +8 -0
  190. package/dist/esm/packages/utils/exception.d.ts +1 -0
  191. package/dist/esm/packages/utils/exception.js +4 -0
  192. package/dist/esm/packages/utils/hash-value.d.ts +16 -0
  193. package/dist/esm/packages/utils/hash-value.js +20 -0
  194. package/dist/esm/packages/utils/import-default.d.ts +1 -0
  195. package/dist/esm/packages/utils/import-default.js +10 -0
  196. package/dist/esm/packages/utils/import-file.d.ts +8 -0
  197. package/dist/esm/packages/utils/import-file.js +13 -0
  198. package/dist/esm/packages/utils/log-with-spinner.d.ts +1 -0
  199. package/dist/esm/packages/utils/log-with-spinner.js +17 -0
  200. package/dist/esm/packages/utils/path.d.ts +2 -0
  201. package/dist/esm/packages/utils/path.js +17 -0
  202. package/dist/esm/packages/utils/playground.d.ts +1 -0
  203. package/dist/esm/packages/utils/playground.js +11 -0
  204. package/dist/esm/scaffolding/add-env-var.d.ts +6 -0
  205. package/dist/esm/scaffolding/add-env-var.js +57 -0
  206. package/dist/esm/scaffolding/add-import.d.ts +16 -0
  207. package/dist/esm/scaffolding/add-import.js +39 -0
  208. package/dist/esm/scaffolding/add-script.d.ts +1 -0
  209. package/dist/esm/scaffolding/add-script.js +29 -0
  210. package/dist/esm/scaffolding/broadcast-workload.d.ts +1 -0
  211. package/dist/esm/scaffolding/broadcast-workload.js +30 -0
  212. package/dist/esm/scaffolding/bucket-workload.d.ts +6 -0
  213. package/dist/esm/scaffolding/bucket-workload.js +17 -0
  214. package/dist/esm/scaffolding/cron-workload.d.ts +6 -0
  215. package/dist/esm/scaffolding/cron-workload.js +22 -0
  216. package/dist/esm/scaffolding/drizzle.d.ts +4 -0
  217. package/dist/esm/scaffolding/drizzle.js +19 -0
  218. package/dist/esm/scaffolding/lifecycle.d.ts +9 -0
  219. package/dist/esm/scaffolding/lifecycle.js +53 -0
  220. package/dist/esm/scaffolding/postgres-database-workload.d.ts +15 -0
  221. package/dist/esm/scaffolding/postgres-database-workload.js +31 -0
  222. package/dist/esm/scaffolding/prisma.d.ts +4 -0
  223. package/dist/esm/scaffolding/prisma.js +34 -0
  224. package/dist/esm/scaffolding/replace-string.d.ts +10 -0
  225. package/dist/esm/scaffolding/replace-string.js +30 -0
  226. package/dist/esm/scaffolding/task-workload.d.ts +6 -0
  227. package/dist/esm/scaffolding/task-workload.js +24 -0
  228. package/dist/esm/scaffolding/workload.d.ts +1 -0
  229. package/dist/esm/scaffolding/workload.js +12 -0
  230. package/dist/esm/scan/project.d.ts +23 -0
  231. package/dist/esm/scan/project.js +69 -0
  232. package/dist/esm/scan/workload-imports.d.ts +21 -0
  233. package/dist/esm/scan/workload-imports.js +144 -0
  234. package/dist/esm/test-helpers/postgres.d.ts +13 -0
  235. package/dist/esm/test-helpers/postgres.js +26 -0
  236. package/dist/esm/test-helpers/redis.d.ts +13 -0
  237. package/dist/esm/test-helpers/redis.js +20 -0
  238. package/dist/esm/test-helpers/task.d.ts +14 -0
  239. package/dist/esm/test-helpers/task.js +14 -0
  240. package/dist/esm/test-helpers.d.ts +3 -0
  241. package/dist/esm/test-helpers.js +3 -0
  242. package/dist/esm/workloads/app-lifecycle/after-rollout.d.ts +22 -0
  243. package/dist/esm/workloads/app-lifecycle/after-rollout.js +24 -0
  244. package/dist/esm/workloads/app-lifecycle/before-rollout.d.ts +22 -0
  245. package/dist/esm/workloads/app-lifecycle/before-rollout.js +24 -0
  246. package/dist/esm/workloads/app-lifecycle/bootstrap.d.ts +22 -0
  247. package/dist/esm/workloads/app-lifecycle/bootstrap.js +24 -0
  248. package/dist/esm/workloads/app-lifecycle/lifecycle-workload.d.ts +11 -0
  249. package/dist/esm/workloads/app-lifecycle/lifecycle-workload.js +7 -0
  250. package/dist/esm/workloads/assertions.d.ts +13 -0
  251. package/dist/esm/workloads/assertions.js +6 -0
  252. package/dist/esm/workloads/stateful/bucket.d.ts +82 -0
  253. package/dist/esm/workloads/stateful/bucket.js +95 -0
  254. package/dist/esm/workloads/stateful/database.d.ts +25 -0
  255. package/dist/esm/workloads/stateful/database.js +42 -0
  256. package/dist/esm/workloads/stateful/postgres-database.d.ts +29 -0
  257. package/dist/esm/workloads/stateful/postgres-database.js +35 -0
  258. package/dist/esm/workloads/stateful/redis.d.ts +30 -0
  259. package/dist/esm/workloads/stateful/redis.js +36 -0
  260. package/dist/esm/workloads/stateful/stateful-workload.d.ts +25 -0
  261. package/dist/esm/workloads/stateful/stateful-workload.js +41 -0
  262. package/dist/esm/workloads/stateless/broadcast/channel-data.d.ts +3 -0
  263. package/dist/esm/workloads/stateless/broadcast/channel-data.js +2 -0
  264. package/dist/esm/workloads/stateless/broadcast/client/app-sync-client.d.ts +78 -0
  265. package/dist/esm/workloads/stateless/broadcast/client/app-sync-client.js +130 -0
  266. package/dist/esm/workloads/stateless/broadcast/client/app-sync-publisher.d.ts +34 -0
  267. package/dist/esm/workloads/stateless/broadcast/client/app-sync-publisher.js +76 -0
  268. package/dist/esm/workloads/stateless/broadcast/client/authenticator.d.ts +28 -0
  269. package/dist/esm/workloads/stateless/broadcast/client/authenticator.js +39 -0
  270. package/dist/esm/workloads/stateless/broadcast/client/broadcast-provider.d.ts +17 -0
  271. package/dist/esm/workloads/stateless/broadcast/client/broadcast-provider.js +29 -0
  272. package/dist/esm/workloads/stateless/broadcast/client/client.d.ts +8 -0
  273. package/dist/esm/workloads/stateless/broadcast/client/client.js +25 -0
  274. package/dist/esm/workloads/stateless/broadcast/client/connectionManager.d.ts +62 -0
  275. package/dist/esm/workloads/stateless/broadcast/client/connectionManager.js +164 -0
  276. package/dist/esm/workloads/stateless/broadcast/client/eventEmitter.d.ts +32 -0
  277. package/dist/esm/workloads/stateless/broadcast/client/eventEmitter.js +50 -0
  278. package/dist/esm/workloads/stateless/broadcast/client/messageBuilder.d.ts +24 -0
  279. package/dist/esm/workloads/stateless/broadcast/client/messageBuilder.js +39 -0
  280. package/dist/esm/workloads/stateless/broadcast/client/parser.d.ts +12 -0
  281. package/dist/esm/workloads/stateless/broadcast/client/parser.js +19 -0
  282. package/dist/esm/workloads/stateless/broadcast/client/provider.d.ts +4 -0
  283. package/dist/esm/workloads/stateless/broadcast/client/provider.js +8 -0
  284. package/dist/esm/workloads/stateless/broadcast/client/subscriptionManager.d.ts +34 -0
  285. package/dist/esm/workloads/stateless/broadcast/client/subscriptionManager.js +91 -0
  286. package/dist/esm/workloads/stateless/broadcast/client/types.d.ts +72 -0
  287. package/dist/esm/workloads/stateless/broadcast/client/types.js +5 -0
  288. package/dist/esm/workloads/stateless/broadcast/matcher.d.ts +13 -0
  289. package/dist/esm/workloads/stateless/broadcast/matcher.js +43 -0
  290. package/dist/esm/workloads/stateless/broadcast/router.d.ts +103 -0
  291. package/dist/esm/workloads/stateless/broadcast/router.js +93 -0
  292. package/dist/esm/workloads/stateless/broadcast/server/broadcast-server.d.ts +2 -0
  293. package/dist/esm/workloads/stateless/broadcast/server/broadcast-server.js +316 -0
  294. package/dist/esm/workloads/stateless/broadcast/types.d.ts +17 -0
  295. package/dist/esm/workloads/stateless/broadcast/types.js +1 -0
  296. package/dist/esm/workloads/stateless/cron.d.ts +49 -0
  297. package/dist/esm/workloads/stateless/cron.js +52 -0
  298. package/dist/esm/workloads/stateless/stateless-workload.d.ts +3 -0
  299. package/dist/esm/workloads/stateless/stateless-workload.js +8 -0
  300. package/dist/esm/workloads/stateless/task/backoffs.d.ts +9 -0
  301. package/dist/esm/workloads/stateless/task/backoffs.js +14 -0
  302. package/dist/esm/workloads/stateless/task/dispatcher.d.ts +3 -0
  303. package/dist/esm/workloads/stateless/task/dispatcher.js +18 -0
  304. package/dist/esm/workloads/stateless/task/local.d.ts +14 -0
  305. package/dist/esm/workloads/stateless/task/local.js +48 -0
  306. package/dist/esm/workloads/stateless/task/perform-later.d.ts +2 -0
  307. package/dist/esm/workloads/stateless/task/perform-later.js +4 -0
  308. package/dist/esm/workloads/stateless/task/perform-now.d.ts +5 -0
  309. package/dist/esm/workloads/stateless/task/perform-now.js +18 -0
  310. package/dist/esm/workloads/stateless/task/perform.d.ts +7 -0
  311. package/dist/esm/workloads/stateless/task/perform.js +8 -0
  312. package/dist/esm/workloads/stateless/task/task.d.ts +88 -0
  313. package/dist/esm/workloads/stateless/task/task.js +59 -0
  314. package/dist/esm/workloads/stateless/task/validate-data-size.d.ts +1 -0
  315. package/dist/esm/workloads/stateless/task/validate-data-size.js +7 -0
  316. package/dist/esm/workloads/workload.d.ts +14 -0
  317. package/dist/esm/workloads/workload.js +16 -0
  318. package/dist/esm/workloads.d.ts +22 -0
  319. package/dist/esm/workloads.js +13 -0
  320. package/package.json +155 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @module types
3
+ * Defines TypeScript interfaces for the AWS AppSync Events WebSocket protocol messages.
4
+ */
5
+ /**
6
+ * Base interface for all AppSync WebSocket messages.
7
+ */
8
+ export interface AppSyncMessage {
9
+ type: string;
10
+ }
11
+ /**
12
+ * Interface for the 'connection_ack' message.
13
+ */
14
+ export interface ConnectionAckMessage extends AppSyncMessage {
15
+ type: "connection_ack";
16
+ connectionTimeoutMs: number;
17
+ }
18
+ /**
19
+ * Interface for the 'ka' (keep-alive) message.
20
+ */
21
+ export interface KaMessage extends AppSyncMessage {
22
+ type: "ka";
23
+ }
24
+ /**
25
+ * Interface for 'subscribe_success' message.
26
+ */
27
+ export interface SubscribeSuccessMessage extends AppSyncMessage {
28
+ type: "subscribe_success";
29
+ id: string;
30
+ }
31
+ /**
32
+ * Interface for 'subscribe_error' message.
33
+ */
34
+ export interface SubscribeErrorMessage extends AppSyncMessage {
35
+ type: "subscribe_error";
36
+ id: string;
37
+ errors: any[];
38
+ }
39
+ /**
40
+ * Interface for 'data' message.
41
+ */
42
+ export interface DataMessage extends AppSyncMessage {
43
+ type: "data";
44
+ id: string;
45
+ event: string;
46
+ }
47
+ /**
48
+ * Interface for 'broadcast_error' message.
49
+ */
50
+ export interface BroadcastErrorMessage extends AppSyncMessage {
51
+ type: "broadcast_error";
52
+ id: string;
53
+ errors: any[];
54
+ }
55
+ /**
56
+ * Interface for 'publish_success' message.
57
+ */
58
+ export interface PublishSuccessMessage extends AppSyncMessage {
59
+ type: "publish_success";
60
+ id: string;
61
+ successful: any[];
62
+ failed: any[];
63
+ }
64
+ /**
65
+ * Interface for 'publish_error' message.
66
+ */
67
+ export interface PublishErrorMessage extends AppSyncMessage {
68
+ type: "publish_error";
69
+ id: string;
70
+ errors: any[];
71
+ }
72
+ export type AppSyncWebSocketMessage = ConnectionAckMessage | KaMessage | SubscribeSuccessMessage | SubscribeErrorMessage | DataMessage | BroadcastErrorMessage | PublishSuccessMessage | PublishErrorMessage;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @module types
3
+ * Defines TypeScript interfaces for the AWS AppSync Events WebSocket protocol messages.
4
+ */
5
+ export {};
@@ -0,0 +1,13 @@
1
+ type RouteParams = {
2
+ [key: string]: string;
3
+ };
4
+ export declare class RouteMatcher {
5
+ private routes;
6
+ constructor(routes: string[]);
7
+ private buildRegex;
8
+ match(url: string): {
9
+ route: string;
10
+ params: RouteParams;
11
+ } | null;
12
+ }
13
+ export {};
@@ -0,0 +1,43 @@
1
+ export class RouteMatcher {
2
+ routes;
3
+ constructor(routes) {
4
+ this.routes = routes;
5
+ }
6
+ buildRegex(route) {
7
+ // Escape static segments and convert dynamic segments (e.g., [id]) into capture groups
8
+ const pattern = route
9
+ .split("/")
10
+ .map((segment) => {
11
+ if (segment.startsWith("[") && segment.endsWith("]")) {
12
+ // Capture dynamic segment as a parameter
13
+ return "([^/]+)";
14
+ }
15
+ // Escape static segments
16
+ return segment.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
17
+ })
18
+ .join("/");
19
+ return new RegExp(`^${pattern}$`);
20
+ }
21
+ match(url) {
22
+ for (const route of this.routes) {
23
+ const regex = this.buildRegex(route);
24
+ const match = url.match(regex);
25
+ if (match) {
26
+ // Extract dynamic parameters from the match
27
+ const params = {};
28
+ const segments = route
29
+ .split("/")
30
+ .filter((segment) => segment.startsWith("[") && segment.endsWith("]"));
31
+ const values = match.slice(1);
32
+ segments.forEach((segment, index) => {
33
+ const paramName = segment.slice(1, -1); // Remove the square brackets
34
+ if (values[index]) {
35
+ params[paramName] = values[index];
36
+ }
37
+ });
38
+ return { route, params };
39
+ }
40
+ }
41
+ return null; // No match found
42
+ }
43
+ }
@@ -0,0 +1,103 @@
1
+ import { Workload } from "../../../workloads/workload.js";
2
+ import type { RouteParams } from "./types.js";
3
+ export type IsValidSegment<S extends string> = S extends `${infer _Start}[${infer Param}]${infer After}` ? After extends `/${string}` | "" ? IsValidSegment<After> : false : true;
4
+ export type ValidateRouteFormat<T extends string> = IsValidSegment<T> extends true ? T : never;
5
+ export type ExtractRouteParamsTuple<T extends string, Acc extends string[] = []> = T extends `${string}[${infer Param}]${infer Rest}` ? ExtractRouteParamsTuple<Rest, [...Acc, Param]> : Acc;
6
+ export type HasDuplicates<T extends readonly any[]> = T extends [
7
+ infer F,
8
+ ...infer R
9
+ ] ? F extends R[number] ? true : HasDuplicates<R> : false;
10
+ export type ValidateUniqueParams<T extends string> = HasDuplicates<ExtractRouteParamsTuple<T>> extends true ? never : T;
11
+ export type ValidateRoute<T extends string> = ValidateRouteFormat<T> extends never ? never : ValidateUniqueParams<T> extends never ? never : T;
12
+ export type ValidateRoutes<T extends Record<string, any>> = {
13
+ [K in keyof T]: ValidateRoute<K & string> extends never ? never : T[K];
14
+ };
15
+ export type DrainOuterGeneric<T> = [T] extends [unknown] ? T : never;
16
+ export type Simplify<T> = DrainOuterGeneric<{
17
+ [K in keyof T]: T[K];
18
+ } & {}>;
19
+ /**
20
+ * Creates a Broadcast workloads
21
+ *
22
+ * The constructore takes a session handler and a configuration object for channels. Each channel
23
+ * is mapped to a path and an optional authorization handler. The channel paths can
24
+ * include dynamic segments, like `/users/[id]`, which are parsed and passed to the
25
+ * authorization logic.
26
+ *
27
+ * @template T - A record mapping channel strings to their channel data types.
28
+ * @template S - The type of the session object, returned by the `session` function.
29
+ *
30
+ * @param session A function that resolves to a session object. This object is available
31
+ * within the authorization handlers. It receives an object with `cookies` as an argument.
32
+ * @param channels An object where keys are route strings and values are objects defining
33
+ * the channel and its authorization logic.
34
+ * - `auth`: An optional function to authorize "PUBLISH" or "SUBSCRIBE" operations.
35
+ * It receives the operation type, route parameters, and the session object.
36
+ * - `channel`: The channel instance for the route.
37
+ *
38
+ * @returns An object containing the configured channels, an internal authorization function (`authFn`),
39
+ * and the session handler.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { channel, Broadcast } from "@monolayer/sdk";
44
+ *
45
+ * const broadcast = new Broadcast(
46
+ * async () => ({ userId: 1 }),
47
+ * {
48
+ * "/todos": {
49
+ * channel: channel<{ message: string }>(),
50
+ * auth: async (ctx) => {
51
+ * console.log("User trying to access todos:", ctx.session.userId);
52
+ * return true; // Allow access
53
+ * },
54
+ * },
55
+ * "/users/[id]": {
56
+ * channel: channel<{ salute: string }>(),
57
+ * auth: async (ctx) => {
58
+ * // Only allow users to access their own channel
59
+ * return ctx.session.userId === Number(ctx.params.id);
60
+ * },
61
+ * },
62
+ * }
63
+ * );
64
+ *
65
+ * export default broadcast;
66
+ * ```
67
+ */
68
+ export declare class Broadcast<T extends Record<string, any>, S> extends Workload {
69
+ session: (opts: {
70
+ cookies: Record<string, string>;
71
+ }) => Promise<S>;
72
+ channels: {
73
+ [channel in keyof T]: ValidateRoute<channel & string> extends never ? never : {
74
+ auth?: (ctx: {
75
+ operation: "PUBLISH" | "SUBSCRIBE";
76
+ params: channel extends string ? Simplify<RouteParams<channel>> : never;
77
+ session: S;
78
+ }) => Promise<boolean>;
79
+ data: T[channel];
80
+ };
81
+ };
82
+ _channelDataType: {
83
+ [K in keyof T]: T[K];
84
+ };
85
+ constructor(initOpts: {
86
+ session?: (opts: {
87
+ cookies: Record<string, string>;
88
+ }) => Promise<S>;
89
+ channels: {
90
+ [channel in keyof T]: ValidateRoute<channel & string> extends never ? never : {
91
+ auth?: (ctx: {
92
+ operation: "PUBLISH" | "SUBSCRIBE";
93
+ params: channel extends string ? Simplify<RouteParams<channel>> : never;
94
+ session: S;
95
+ }) => Promise<boolean>;
96
+ data: T[channel];
97
+ };
98
+ };
99
+ });
100
+ authFn(route: string, operation: "PUBLISH" | "SUBSCRIBE", session: S): Promise<boolean>;
101
+ get connectionStringEnvVar(): "ML_BROADCAST_URL";
102
+ }
103
+ export type AnyBroadcast = Broadcast<any, any>;
@@ -0,0 +1,93 @@
1
+ import path from "path";
2
+ import { Workload } from "../../../workloads/workload.js";
3
+ import { RouteMatcher } from "./matcher.js";
4
+ /**
5
+ * Creates a Broadcast workloads
6
+ *
7
+ * The constructore takes a session handler and a configuration object for channels. Each channel
8
+ * is mapped to a path and an optional authorization handler. The channel paths can
9
+ * include dynamic segments, like `/users/[id]`, which are parsed and passed to the
10
+ * authorization logic.
11
+ *
12
+ * @template T - A record mapping channel strings to their channel data types.
13
+ * @template S - The type of the session object, returned by the `session` function.
14
+ *
15
+ * @param session A function that resolves to a session object. This object is available
16
+ * within the authorization handlers. It receives an object with `cookies` as an argument.
17
+ * @param channels An object where keys are route strings and values are objects defining
18
+ * the channel and its authorization logic.
19
+ * - `auth`: An optional function to authorize "PUBLISH" or "SUBSCRIBE" operations.
20
+ * It receives the operation type, route parameters, and the session object.
21
+ * - `channel`: The channel instance for the route.
22
+ *
23
+ * @returns An object containing the configured channels, an internal authorization function (`authFn`),
24
+ * and the session handler.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { channel, Broadcast } from "@monolayer/sdk";
29
+ *
30
+ * const broadcast = new Broadcast(
31
+ * async () => ({ userId: 1 }),
32
+ * {
33
+ * "/todos": {
34
+ * channel: channel<{ message: string }>(),
35
+ * auth: async (ctx) => {
36
+ * console.log("User trying to access todos:", ctx.session.userId);
37
+ * return true; // Allow access
38
+ * },
39
+ * },
40
+ * "/users/[id]": {
41
+ * channel: channel<{ salute: string }>(),
42
+ * auth: async (ctx) => {
43
+ * // Only allow users to access their own channel
44
+ * return ctx.session.userId === Number(ctx.params.id);
45
+ * },
46
+ * },
47
+ * }
48
+ * );
49
+ *
50
+ * export default broadcast;
51
+ * ```
52
+ */
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ export class Broadcast extends Workload {
55
+ session;
56
+ channels;
57
+ constructor(initOpts) {
58
+ super("broadcast");
59
+ this.session =
60
+ initOpts.session ??
61
+ (async () => {
62
+ return {};
63
+ });
64
+ this.channels = initOpts.channels;
65
+ }
66
+ async authFn(route, operation, session) {
67
+ const auth = {};
68
+ for (const routeName of Object.keys(this.channels)) {
69
+ if (this.channels[routeName]) {
70
+ auth[`${path.join("default", routeName)}`] =
71
+ this.channels[routeName].auth;
72
+ }
73
+ }
74
+ const matcher = new RouteMatcher(Object.keys(this.channels).map((r) => path.join("default", r)));
75
+ const match = matcher.match(route);
76
+ if (match) {
77
+ const routeAuth = auth[route];
78
+ if (routeAuth === undefined)
79
+ return true;
80
+ return await routeAuth({
81
+ session: session,
82
+ params: match.params,
83
+ operation,
84
+ });
85
+ }
86
+ else {
87
+ return true;
88
+ }
89
+ }
90
+ get connectionStringEnvVar() {
91
+ return "ML_BROADCAST_URL";
92
+ }
93
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable max-lines */
3
+ import { WebSocketServer } from "ws";
4
+ const PORT = 9311;
5
+ const PING_INTERVAL = 1000 * 60; // 60 seconds
6
+ class AppSyncTestServer {
7
+ wss;
8
+ session;
9
+ clients;
10
+ interval = null;
11
+ connectionTimeoutMs;
12
+ channelAuth;
13
+ constructor(opts) {
14
+ this.wss = new WebSocketServer({ port: opts.port });
15
+ this.clients = new Set();
16
+ this.connectionTimeoutMs = opts.connectionTimeoutMs ?? 300000;
17
+ this.channelAuth = opts.channelAuth;
18
+ this.session = opts.session;
19
+ this.setupServer();
20
+ }
21
+ setupServer() {
22
+ this.wss.on("headers", (d) => {
23
+ console.log(d);
24
+ });
25
+ this.wss.on("connection", async (ws, request) => {
26
+ console.log(request.url);
27
+ const client = ws;
28
+ client.isAlive = true;
29
+ client.subscriptions = new Map();
30
+ console.log("Client connected");
31
+ const protocol = request.headers["sec-websocket-protocol"];
32
+ const authProtocol = protocol?.split(",")[1]?.trim();
33
+ const authProtocolName = protocol?.split(",")[0]?.trim();
34
+ if (authProtocol && authProtocolName === "aws-appsync-event-ws") {
35
+ try {
36
+ const encodedHeader = authProtocol.substring("header-".length);
37
+ const decodedHeader = Buffer.from(encodedHeader, "base64url").toString("utf8");
38
+ console.log("Decoded", decodedHeader);
39
+ const auth = JSON.parse(decodedHeader);
40
+ console.log("Authorization header:", auth);
41
+ if (auth.Authorization === undefined) {
42
+ console.error("Unauthorized");
43
+ client.close(3000, "Unauthorized");
44
+ return;
45
+ }
46
+ client._authorizationToken = auth.Authorization;
47
+ if (this.session) {
48
+ client._session = await this.session({ cookies: {} });
49
+ }
50
+ this.clients.add(client);
51
+ }
52
+ catch (e) {
53
+ console.error("Failed to parse authorization header:", e);
54
+ client.close(1008, "Invalid authorization header");
55
+ return;
56
+ }
57
+ }
58
+ else {
59
+ console.error("Mising authorization:");
60
+ client.close(1008, "Missing authorization");
61
+ }
62
+ client.on("pong", () => {
63
+ client.isAlive = true;
64
+ });
65
+ client.on("message", async (message) => {
66
+ console.log(`Received message: ${message}`);
67
+ try {
68
+ const parsedMessage = JSON.parse(message);
69
+ console.log(parsedMessage);
70
+ await this.handleMessage(client, parsedMessage);
71
+ }
72
+ catch (e) {
73
+ console.error("Failed to parse message:", e);
74
+ client.send(JSON.stringify({ type: "error", message: "Invalid JSON message" }));
75
+ }
76
+ });
77
+ client.on("close", () => {
78
+ console.log("Client disconnected");
79
+ this.clients.delete(client);
80
+ });
81
+ client.on("error", (error) => {
82
+ console.error("WebSocket error:", error);
83
+ });
84
+ });
85
+ this.interval = setInterval(() => {
86
+ this.clients.forEach((client) => {
87
+ if (client.isAlive === false) {
88
+ console.log("Client not alive, terminating connection");
89
+ return client.terminate();
90
+ }
91
+ client.isAlive = false;
92
+ client.ping();
93
+ });
94
+ }, PING_INTERVAL);
95
+ this.wss.on("close", () => {
96
+ if (this.interval) {
97
+ clearInterval(this.interval);
98
+ }
99
+ });
100
+ console.log("AppSync Test Server started");
101
+ }
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ async handleMessage(client, message) {
104
+ switch (message.type) {
105
+ case "connection_init":
106
+ client.connectionTimeoutMs = this.connectionTimeoutMs;
107
+ client.send(JSON.stringify({
108
+ type: "connection_ack",
109
+ connectionTimeoutMs: client.connectionTimeoutMs,
110
+ }));
111
+ break;
112
+ case "subscribe":
113
+ if (!message.id || !message.channel) {
114
+ client.send(JSON.stringify({
115
+ type: "subscribe_error",
116
+ id: message.id,
117
+ errors: [
118
+ {
119
+ errorType: "ValidationError",
120
+ message: "Missing id or channel",
121
+ },
122
+ ],
123
+ }));
124
+ return;
125
+ }
126
+ if (client.subscriptions.has(message.id)) {
127
+ client.send(JSON.stringify({
128
+ type: "subscribe_error",
129
+ id: message.id,
130
+ errors: [
131
+ {
132
+ errorType: "DuplicateSubscriptionError",
133
+ message: "Subscription ID already exists",
134
+ },
135
+ ],
136
+ }));
137
+ return;
138
+ }
139
+ if (this.channelAuth) {
140
+ try {
141
+ const isAuthorized = await this.channelAuth(message.channel, "SUBSCRIBE", client._session);
142
+ if (!isAuthorized) {
143
+ console.error("Unauthorized");
144
+ client.send(JSON.stringify({
145
+ type: "subscribe_error",
146
+ id: message.id,
147
+ errors: [
148
+ {
149
+ errorType: "Unauthorized",
150
+ message: "Unauthorized to subscribe",
151
+ },
152
+ ],
153
+ }));
154
+ return;
155
+ }
156
+ }
157
+ catch {
158
+ console.error("Internal Error");
159
+ client.send(JSON.stringify({
160
+ type: "internal_error",
161
+ id: message.id,
162
+ errors: [
163
+ {
164
+ errorType: "Internal Error",
165
+ },
166
+ ],
167
+ }));
168
+ return;
169
+ }
170
+ }
171
+ client.subscriptions.set(message.id, message.channel);
172
+ client.send(JSON.stringify({ type: "subscribe_success", id: message.id }));
173
+ console.log(`Client subscribed to channel: ${message.channel} with id: ${message.id}`);
174
+ break;
175
+ case "unsubscribe":
176
+ if (!message.id) {
177
+ client.send(JSON.stringify({
178
+ type: "unsubscribe_error",
179
+ id: message.id,
180
+ errors: [{ errorType: "ValidationError", message: "Missing id" }],
181
+ }));
182
+ return;
183
+ }
184
+ if (client.subscriptions.delete(message.id)) {
185
+ client.send(JSON.stringify({ type: "unsubscribe_success", id: message.id }));
186
+ console.log(`Client unsubscribed from id: ${message.id}`);
187
+ }
188
+ else {
189
+ client.send(JSON.stringify({
190
+ type: "unsubscribe_error",
191
+ id: message.id,
192
+ errors: [
193
+ {
194
+ errorType: "UnknownOperationError",
195
+ message: `Unknown subscription id ${message.id}`,
196
+ },
197
+ ],
198
+ }));
199
+ }
200
+ break;
201
+ case "publish":
202
+ if (!message.id || !message.channel || !message.events) {
203
+ client.send(JSON.stringify({
204
+ type: "publish_error",
205
+ id: message.id,
206
+ errors: [
207
+ {
208
+ errorType: "ValidationError",
209
+ message: "Missing id, channel, or events",
210
+ },
211
+ ],
212
+ }));
213
+ return;
214
+ }
215
+ console.log(`Client publishing to channel: ${message.channel} with events:`, message.events);
216
+ if (this.channelAuth) {
217
+ try {
218
+ const isAuthorized = await this.channelAuth(message.channel, "PUBLISH", {});
219
+ if (!isAuthorized) {
220
+ console.error("Unauthorized");
221
+ client.send(JSON.stringify({
222
+ type: "subscribe_error",
223
+ id: message.id,
224
+ errors: [
225
+ {
226
+ errorType: "Unauthorized",
227
+ message: "Unauthorized to subscribe",
228
+ },
229
+ ],
230
+ }));
231
+ return;
232
+ }
233
+ }
234
+ catch {
235
+ console.error("Internal Error");
236
+ client.send(JSON.stringify({
237
+ type: "internal_error",
238
+ id: message.id,
239
+ errors: [
240
+ {
241
+ errorType: "Internal Error",
242
+ },
243
+ ],
244
+ }));
245
+ return;
246
+ }
247
+ }
248
+ this.broadcast(message.channel, message.events, message.id);
249
+ console.log("message", message);
250
+ client.send(JSON.stringify({
251
+ type: "publish_success",
252
+ id: message.id,
253
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
+ successful: message.events.map((_, index) => ({
255
+ identifier: `event-${index}`,
256
+ index,
257
+ })),
258
+ failed: [],
259
+ }));
260
+ break;
261
+ default:
262
+ client.send(JSON.stringify({ type: "error", message: "Unknown message type" }));
263
+ break;
264
+ }
265
+ }
266
+ broadcast(channel, events, publishId) {
267
+ this.clients.forEach((client) => {
268
+ client.subscriptions.forEach((subscribedChannel, subscriptionId) => {
269
+ if (subscribedChannel === channel) {
270
+ events.forEach((event) => {
271
+ client.send(JSON.stringify({
272
+ type: "data",
273
+ id: subscriptionId,
274
+ event: [event],
275
+ publishId: publishId, // Include publishId for correlation if needed
276
+ }));
277
+ });
278
+ }
279
+ });
280
+ });
281
+ }
282
+ close() {
283
+ this.wss.close();
284
+ if (this.interval) {
285
+ clearInterval(this.interval);
286
+ }
287
+ console.log("AppSync Test Server closed");
288
+ }
289
+ stopKeepAlive() {
290
+ if (this.interval) {
291
+ clearInterval(this.interval);
292
+ this.interval = null;
293
+ }
294
+ }
295
+ sendKeepAlive(client) {
296
+ client.send(JSON.stringify({ type: "ka" }));
297
+ }
298
+ }
299
+ async function main() {
300
+ const routesPath = "/app/workloads/broadcast.js";
301
+ const ru = await import(routesPath);
302
+ const server = new AppSyncTestServer({
303
+ port: PORT,
304
+ channelAuth: ru.authFn,
305
+ session: ru.session,
306
+ });
307
+ process.on("SIGINT", () => {
308
+ server.close();
309
+ process.exit();
310
+ });
311
+ process.on("SIGTERM", () => {
312
+ server.close();
313
+ process.exit();
314
+ });
315
+ }
316
+ main().catch(console.error);
@@ -0,0 +1,17 @@
1
+ export type Channel<T> = {
2
+ _data: T;
3
+ subscribed?: (ctx: any) => void;
4
+ unsubscribed?: (ctx: any) => void;
5
+ };
6
+ export type ChannelData<T extends Channel<any>> = T extends Channel<infer D> ? D : never;
7
+ export type Channels = Record<string, Channel<any>>;
8
+ export type ExtractRouteParamsTuple<T extends string, Acc extends string[] = []> = T extends `${string}[${infer Param}]${infer Rest}` ? ExtractRouteParamsTuple<Rest, [...Acc, Param]> : Acc;
9
+ export type HasDuplicates<T extends readonly any[]> = T extends [
10
+ infer F,
11
+ ...infer R
12
+ ] ? F extends R[number] ? true : HasDuplicates<R> : false;
13
+ export type ValidateUniqueParams<T extends string> = HasDuplicates<ExtractRouteParamsTuple<T>> extends true ? ["❌ Duplicate route params not allowed in", T] : T;
14
+ export type TupleToParamObject<T extends readonly string[]> = {
15
+ [K in T[number]]: string;
16
+ };
17
+ export type RouteParams<T extends string> = TupleToParamObject<ExtractRouteParamsTuple<T>>;
@@ -0,0 +1 @@
1
+ export {};