@pasosdejesus/m 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/dist/blockchain/deployments.d.ts +40 -0
  2. package/dist/blockchain/deployments.d.ts.map +1 -0
  3. package/dist/blockchain/deployments.js +64 -0
  4. package/dist/debug/DebugConsole.d.ts +22 -0
  5. package/dist/debug/DebugConsole.d.ts.map +1 -0
  6. package/dist/debug/DebugConsole.js +79 -0
  7. package/dist/debug/Logger.d.ts +38 -0
  8. package/dist/debug/Logger.d.ts.map +1 -0
  9. package/dist/debug/Logger.js +94 -0
  10. package/dist/debug/index.d.ts +6 -0
  11. package/dist/debug/index.d.ts.map +1 -0
  12. package/dist/debug/index.js +4 -0
  13. package/dist/debug/useLogger.d.ts +14 -0
  14. package/dist/debug/useLogger.d.ts.map +1 -0
  15. package/dist/debug/useLogger.js +23 -0
  16. package/dist/debug/utils.d.ts +10 -0
  17. package/dist/debug/utils.d.ts.map +1 -0
  18. package/dist/debug/utils.js +53 -0
  19. package/dist/e2e/assertions.d.ts +5 -0
  20. package/dist/e2e/assertions.d.ts.map +1 -0
  21. package/dist/e2e/assertions.js +18 -0
  22. package/dist/e2e/browser.d.ts +37 -0
  23. package/dist/e2e/browser.d.ts.map +1 -0
  24. package/dist/e2e/browser.js +97 -0
  25. package/dist/e2e/env.d.ts +18 -0
  26. package/dist/e2e/env.d.ts.map +1 -0
  27. package/dist/e2e/env.js +57 -0
  28. package/dist/e2e/index.d.ts +11 -0
  29. package/dist/e2e/index.d.ts.map +1 -0
  30. package/dist/e2e/index.js +8 -0
  31. package/dist/e2e/navigation.d.ts +4 -0
  32. package/dist/e2e/navigation.d.ts.map +1 -0
  33. package/dist/e2e/navigation.js +32 -0
  34. package/dist/e2e/siwe-mock.d.ts +11 -0
  35. package/dist/e2e/siwe-mock.d.ts.map +1 -0
  36. package/dist/e2e/siwe-mock.js +112 -0
  37. package/dist/e2e/siwe.d.ts +15 -0
  38. package/dist/e2e/siwe.d.ts.map +1 -0
  39. package/dist/e2e/siwe.js +85 -0
  40. package/dist/e2e/wallet-mock.d.ts +13 -0
  41. package/dist/e2e/wallet-mock.d.ts.map +1 -0
  42. package/dist/e2e/wallet-mock.js +91 -0
  43. package/dist/i18n/common-cli.d.ts +11 -0
  44. package/dist/i18n/common-cli.d.ts.map +1 -0
  45. package/dist/i18n/common-cli.js +22 -0
  46. package/dist/i18n/createTranslator.d.ts +28 -0
  47. package/dist/i18n/createTranslator.d.ts.map +1 -0
  48. package/dist/i18n/createTranslator.js +48 -0
  49. package/dist/i18n/index.d.ts +4 -0
  50. package/dist/i18n/index.d.ts.map +1 -0
  51. package/dist/i18n/index.js +2 -0
  52. package/dist/i18n/locales/cli.d.ts +3 -0
  53. package/dist/i18n/locales/cli.d.ts.map +1 -0
  54. package/dist/i18n/locales/cli.js +180 -0
  55. package/dist/i18n/types.d.ts +3 -0
  56. package/dist/i18n/types.d.ts.map +1 -0
  57. package/dist/i18n/types.js +1 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +15 -0
  61. package/dist/index.test.d.ts +2 -0
  62. package/dist/index.test.d.ts.map +1 -0
  63. package/dist/index.test.js +10 -0
  64. package/dist/m.d.ts +2 -0
  65. package/dist/m.d.ts.map +1 -0
  66. package/dist/m.js +334 -0
  67. package/dist/plugin.d.ts +10 -0
  68. package/dist/plugin.d.ts.map +1 -0
  69. package/dist/plugin.js +7 -0
  70. package/dist/shadcn_components/cn.d.ts +13 -0
  71. package/dist/shadcn_components/cn.d.ts.map +1 -0
  72. package/dist/shadcn_components/cn.js +15 -0
  73. package/dist/shadcn_components/ui/accordion.d.ts +8 -0
  74. package/dist/shadcn_components/ui/accordion.d.ts.map +1 -0
  75. package/dist/shadcn_components/ui/accordion.js +14 -0
  76. package/dist/shadcn_components/ui/alert-dialog.d.ts +21 -0
  77. package/dist/shadcn_components/ui/alert-dialog.d.ts.map +1 -0
  78. package/dist/shadcn_components/ui/alert-dialog.js +27 -0
  79. package/dist/shadcn_components/ui/alert.d.ts +9 -0
  80. package/dist/shadcn_components/ui/alert.d.ts.map +1 -0
  81. package/dist/shadcn_components/ui/alert.js +22 -0
  82. package/dist/shadcn_components/ui/avatar.d.ts +7 -0
  83. package/dist/shadcn_components/ui/avatar.d.ts.map +1 -0
  84. package/dist/shadcn_components/ui/avatar.js +12 -0
  85. package/dist/shadcn_components/ui/badge.d.ts +10 -0
  86. package/dist/shadcn_components/ui/badge.d.ts.map +1 -0
  87. package/dist/shadcn_components/ui/badge.js +22 -0
  88. package/dist/shadcn_components/ui/button.d.ts +11 -0
  89. package/dist/shadcn_components/ui/button.d.ts.map +1 -0
  90. package/dist/shadcn_components/ui/button.js +31 -0
  91. package/dist/shadcn_components/ui/card.d.ts +10 -0
  92. package/dist/shadcn_components/ui/card.d.ts.map +1 -0
  93. package/dist/shadcn_components/ui/card.js +24 -0
  94. package/dist/shadcn_components/ui/checkbox.d.ts +5 -0
  95. package/dist/shadcn_components/ui/checkbox.d.ts.map +1 -0
  96. package/dist/shadcn_components/ui/checkbox.js +9 -0
  97. package/dist/shadcn_components/ui/dialog.d.ts +20 -0
  98. package/dist/shadcn_components/ui/dialog.d.ts.map +1 -0
  99. package/dist/shadcn_components/ui/dialog.js +23 -0
  100. package/dist/shadcn_components/ui/dropdown-menu.d.ts +28 -0
  101. package/dist/shadcn_components/ui/dropdown-menu.d.ts.map +1 -0
  102. package/dist/shadcn_components/ui/dropdown-menu.js +36 -0
  103. package/dist/shadcn_components/ui/form.d.ts +24 -0
  104. package/dist/shadcn_components/ui/form.d.ts.map +1 -0
  105. package/dist/shadcn_components/ui/form.js +63 -0
  106. package/dist/shadcn_components/ui/input.d.ts +4 -0
  107. package/dist/shadcn_components/ui/input.d.ts.map +1 -0
  108. package/dist/shadcn_components/ui/input.js +6 -0
  109. package/dist/shadcn_components/ui/label.d.ts +6 -0
  110. package/dist/shadcn_components/ui/label.d.ts.map +1 -0
  111. package/dist/shadcn_components/ui/label.js +10 -0
  112. package/dist/shadcn_components/ui/menubar.d.ts +29 -0
  113. package/dist/shadcn_components/ui/menubar.d.ts.map +1 -0
  114. package/dist/shadcn_components/ui/menubar.js +46 -0
  115. package/dist/shadcn_components/ui/popover.d.ts +7 -0
  116. package/dist/shadcn_components/ui/popover.d.ts.map +1 -0
  117. package/dist/shadcn_components/ui/popover.js +10 -0
  118. package/dist/shadcn_components/ui/progress.d.ts +5 -0
  119. package/dist/shadcn_components/ui/progress.d.ts.map +1 -0
  120. package/dist/shadcn_components/ui/progress.js +8 -0
  121. package/dist/shadcn_components/ui/radio-group.d.ts +6 -0
  122. package/dist/shadcn_components/ui/radio-group.d.ts.map +1 -0
  123. package/dist/shadcn_components/ui/radio-group.js +15 -0
  124. package/dist/shadcn_components/ui/scroll-area.d.ts +6 -0
  125. package/dist/shadcn_components/ui/scroll-area.d.ts.map +1 -0
  126. package/dist/shadcn_components/ui/scroll-area.js +12 -0
  127. package/dist/shadcn_components/ui/select.d.ts +14 -0
  128. package/dist/shadcn_components/ui/select.d.ts.map +1 -0
  129. package/dist/shadcn_components/ui/select.js +27 -0
  130. package/dist/shadcn_components/ui/separator.d.ts +5 -0
  131. package/dist/shadcn_components/ui/separator.d.ts.map +1 -0
  132. package/dist/shadcn_components/ui/separator.js +8 -0
  133. package/dist/shadcn_components/ui/sheet.d.ts +26 -0
  134. package/dist/shadcn_components/ui/sheet.d.ts.map +1 -0
  135. package/dist/shadcn_components/ui/sheet.js +37 -0
  136. package/dist/shadcn_components/ui/skeleton.d.ts +3 -0
  137. package/dist/shadcn_components/ui/skeleton.d.ts.map +1 -0
  138. package/dist/shadcn_components/ui/skeleton.js +6 -0
  139. package/dist/shadcn_components/ui/slider.d.ts +5 -0
  140. package/dist/shadcn_components/ui/slider.d.ts.map +1 -0
  141. package/dist/shadcn_components/ui/slider.js +8 -0
  142. package/dist/shadcn_components/ui/switch.d.ts +5 -0
  143. package/dist/shadcn_components/ui/switch.d.ts.map +1 -0
  144. package/dist/shadcn_components/ui/switch.js +8 -0
  145. package/dist/shadcn_components/ui/table.d.ts +11 -0
  146. package/dist/shadcn_components/ui/table.d.ts.map +1 -0
  147. package/dist/shadcn_components/ui/table.js +20 -0
  148. package/dist/shadcn_components/ui/tabs.d.ts +8 -0
  149. package/dist/shadcn_components/ui/tabs.d.ts.map +1 -0
  150. package/dist/shadcn_components/ui/tabs.js +13 -0
  151. package/dist/shadcn_components/ui/textarea.d.ts +4 -0
  152. package/dist/shadcn_components/ui/textarea.d.ts.map +1 -0
  153. package/dist/shadcn_components/ui/textarea.js +8 -0
  154. package/dist/shadcn_components/ui/toast.d.ts +16 -0
  155. package/dist/shadcn_components/ui/toast.d.ts.map +1 -0
  156. package/dist/shadcn_components/ui/toast.js +34 -0
  157. package/dist/shadcn_components/ui/toaster.d.ts +2 -0
  158. package/dist/shadcn_components/ui/toaster.d.ts.map +1 -0
  159. package/dist/shadcn_components/ui/toaster.js +10 -0
  160. package/dist/shadcn_components/ui/tooltip.d.ts +8 -0
  161. package/dist/shadcn_components/ui/tooltip.d.ts.map +1 -0
  162. package/dist/shadcn_components/ui/tooltip.js +11 -0
  163. package/dist/shadcn_components/ui/use-toast.d.ts +45 -0
  164. package/dist/shadcn_components/ui/use-toast.d.ts.map +1 -0
  165. package/dist/shadcn_components/ui/use-toast.js +126 -0
  166. package/dist/tasks/context.d.ts +13 -0
  167. package/dist/tasks/context.d.ts.map +1 -0
  168. package/dist/tasks/context.js +310 -0
  169. package/dist/tasks/create.d.ts +2 -0
  170. package/dist/tasks/create.d.ts.map +1 -0
  171. package/dist/tasks/create.js +91 -0
  172. package/dist/tasks/db.d.ts +19 -0
  173. package/dist/tasks/db.d.ts.map +1 -0
  174. package/dist/tasks/db.js +791 -0
  175. package/dist/tasks/e2e.d.ts +2 -0
  176. package/dist/tasks/e2e.d.ts.map +1 -0
  177. package/dist/tasks/e2e.js +124 -0
  178. package/dist/tasks/edit.d.ts +7 -0
  179. package/dist/tasks/edit.d.ts.map +1 -0
  180. package/dist/tasks/edit.js +471 -0
  181. package/dist/tasks/engine.d.ts +2 -0
  182. package/dist/tasks/engine.d.ts.map +1 -0
  183. package/dist/tasks/engine.js +149 -0
  184. package/dist/tasks/env-diff.d.ts +2 -0
  185. package/dist/tasks/env-diff.d.ts.map +1 -0
  186. package/dist/tasks/env-diff.js +140 -0
  187. package/dist/tasks/fuzzy.d.ts +9 -0
  188. package/dist/tasks/fuzzy.d.ts.map +1 -0
  189. package/dist/tasks/fuzzy.js +153 -0
  190. package/dist/tasks/glob.d.ts +5 -0
  191. package/dist/tasks/glob.d.ts.map +1 -0
  192. package/dist/tasks/glob.js +57 -0
  193. package/dist/tasks/grep.d.ts +9 -0
  194. package/dist/tasks/grep.d.ts.map +1 -0
  195. package/dist/tasks/grep.js +93 -0
  196. package/dist/tasks/readfile.d.ts +2 -0
  197. package/dist/tasks/readfile.d.ts.map +1 -0
  198. package/dist/tasks/readfile.js +177 -0
  199. package/dist/tasks/update.d.ts +5 -0
  200. package/dist/tasks/update.d.ts.map +1 -0
  201. package/dist/tasks/update.js +200 -0
  202. package/dist/tasks/util.d.ts +12 -0
  203. package/dist/tasks/util.d.ts.map +1 -0
  204. package/dist/tasks/util.js +42 -0
  205. package/dist/tasks/wallet.d.ts +2 -0
  206. package/dist/tasks/wallet.d.ts.map +1 -0
  207. package/dist/tasks/wallet.js +697 -0
  208. package/dist/tasks/writefile.d.ts +2 -0
  209. package/dist/tasks/writefile.d.ts.map +1 -0
  210. package/dist/tasks/writefile.js +66 -0
  211. package/dist/templates/AGENTS.md.hbs +81 -0
  212. package/dist/templates/ARCHITECTURE.md.hbs +146 -0
  213. package/dist/templates/CONTRIBUTING.md.hbs +83 -0
  214. package/dist/templates/LICENCIA.md +21 -0
  215. package/dist/templates/LICENSE.md +15 -0
  216. package/dist/templates/Makefile +16 -0
  217. package/dist/templates/README.md.hbs +111 -0
  218. package/dist/templates/apps/.env.example.hbs +75 -0
  219. package/dist/templates/apps/hardhat/.prettierrc +16 -0
  220. package/dist/templates/apps/hardhat/MOCK_USDT_README.md +20 -0
  221. package/dist/templates/apps/hardhat/Makefile +13 -0
  222. package/dist/templates/apps/hardhat/README.md +129 -0
  223. package/dist/templates/apps/hardhat/bin/MusdtVerification +4 -0
  224. package/dist/templates/apps/hardhat/bin/approveDepositOwner +7 -0
  225. package/dist/templates/apps/hardhat/bin/contractVerification +9 -0
  226. package/dist/templates/apps/hardhat/bin/deployMockUSDT +7 -0
  227. package/dist/templates/apps/hardhat/bin/prepadJ.sh +14 -0
  228. package/dist/templates/apps/hardhat/bin/verifyMockUSDT +7 -0
  229. package/dist/templates/apps/hardhat/contracts/MockUSDT.sol +47 -0
  230. package/dist/templates/apps/hardhat/hardhat.config.ts +102 -0
  231. package/dist/templates/apps/hardhat/package.json +55 -0
  232. package/dist/templates/apps/hardhat/scripts/approveDepositOwner.ts +22 -0
  233. package/dist/templates/apps/hardhat/scripts/deployMockUSDT.ts +49 -0
  234. package/dist/templates/apps/hardhat/scripts/verifyDeployment.ts +93 -0
  235. package/dist/templates/apps/hardhat/scripts/verifyMockUSDT.ts +52 -0
  236. package/dist/templates/apps/hardhat/sync-abis.mjs +58 -0
  237. package/dist/templates/apps/hardhat/test/MockUSDT.test.ts +40 -0
  238. package/dist/templates/apps/hardhat/tsconfig.json +27 -0
  239. package/dist/templates/apps/nextjs/.config/kysely.config.ts +36 -0
  240. package/dist/templates/apps/nextjs/Makefile +24 -0
  241. package/dist/templates/apps/nextjs/README.md.hbs +76 -0
  242. package/dist/templates/apps/nextjs/abis/IERC20.json +74 -0
  243. package/dist/templates/apps/nextjs/abis/MockUSDT.json +242 -0
  244. package/dist/templates/apps/nextjs/abis/ReentrancyGuard.json +1 -0
  245. package/dist/templates/apps/nextjs/app/globals.css +3 -0
  246. package/dist/templates/apps/nextjs/app/layout.tsx.hbs +26 -0
  247. package/dist/templates/apps/nextjs/app/page.tsx.hbs +225 -0
  248. package/dist/templates/apps/nextjs/app/testui/page.tsx +371 -0
  249. package/dist/templates/apps/nextjs/bin/m +8 -0
  250. package/dist/templates/apps/nextjs/components.json +21 -0
  251. package/dist/templates/apps/nextjs/next-env.d.ts +5 -0
  252. package/dist/templates/apps/nextjs/next.config.ts +10 -0
  253. package/dist/templates/apps/nextjs/package.json.hbs +48 -0
  254. package/dist/templates/apps/nextjs/pnpm-workspace.yaml +13 -0
  255. package/dist/templates/apps/nextjs/postcss.config.mjs +6 -0
  256. package/dist/templates/apps/nextjs/tailwind.config.js +11 -0
  257. package/dist/templates/apps/nextjs/tests/helpers.ts +31 -0
  258. package/dist/templates/apps/nextjs/tests/index.test.ts +7 -0
  259. package/dist/templates/apps/nextjs/tests/setup-env.ts.hbs +8 -0
  260. package/dist/templates/apps/nextjs/tests/test-utils.example.test.ts +168 -0
  261. package/dist/templates/apps/nextjs/tsconfig.json +44 -0
  262. package/dist/templates/apps/nextjs/tsconfig.test.json +38 -0
  263. package/dist/templates/apps/nextjs/vitest.config.ts +13 -0
  264. package/dist/test-utils/fs-mocks.d.ts +32 -0
  265. package/dist/test-utils/fs-mocks.d.ts.map +1 -0
  266. package/dist/test-utils/fs-mocks.js +63 -0
  267. package/dist/test-utils/i18n-mock.d.ts +21 -0
  268. package/dist/test-utils/i18n-mock.d.ts.map +1 -0
  269. package/dist/test-utils/i18n-mock.js +29 -0
  270. package/dist/test-utils/index.d.ts +12 -0
  271. package/dist/test-utils/index.d.ts.map +1 -0
  272. package/dist/test-utils/index.js +11 -0
  273. package/dist/test-utils/kysely-mocks.d.ts +298 -0
  274. package/dist/test-utils/kysely-mocks.d.ts.map +1 -0
  275. package/dist/test-utils/kysely-mocks.js +173 -0
  276. package/dist/test-utils/radix-mocks.d.ts +134 -0
  277. package/dist/test-utils/radix-mocks.d.ts.map +1 -0
  278. package/dist/test-utils/radix-mocks.js +175 -0
  279. package/dist/test-utils/rainbowkit-mocks.d.ts +80 -0
  280. package/dist/test-utils/rainbowkit-mocks.d.ts.map +1 -0
  281. package/dist/test-utils/rainbowkit-mocks.js +247 -0
  282. package/dist/test-utils/viem-mocks.d.ts +86 -0
  283. package/dist/test-utils/viem-mocks.d.ts.map +1 -0
  284. package/dist/test-utils/viem-mocks.js +54 -0
  285. package/dist/util/cli-parser.d.ts +20 -0
  286. package/dist/util/cli-parser.d.ts.map +1 -0
  287. package/dist/util/cli-parser.js +38 -0
  288. package/dist/util/colors.d.ts +5 -0
  289. package/dist/util/colors.d.ts.map +1 -0
  290. package/dist/util/colors.js +5 -0
  291. package/dist/util/locale.d.ts +3 -0
  292. package/dist/util/locale.d.ts.map +1 -0
  293. package/dist/util/locale.js +10 -0
  294. package/dist/wba/client.d.ts +19 -0
  295. package/dist/wba/client.d.ts.map +1 -0
  296. package/dist/wba/client.js +31 -0
  297. package/dist/wba/index.d.ts +4 -0
  298. package/dist/wba/index.d.ts.map +1 -0
  299. package/dist/wba/index.js +2 -0
  300. package/dist/wba/routes/event.d.ts +32 -0
  301. package/dist/wba/routes/event.d.ts.map +1 -0
  302. package/dist/wba/routes/event.js +42 -0
  303. package/dist/wba/routes/index.d.ts +3 -0
  304. package/dist/wba/routes/index.d.ts.map +1 -0
  305. package/dist/wba/routes/index.js +2 -0
  306. package/dist/wba/routes/summary.d.ts +44 -0
  307. package/dist/wba/routes/summary.d.ts.map +1 -0
  308. package/dist/wba/routes/summary.js +146 -0
  309. package/dist/wba/server.d.ts +18 -0
  310. package/dist/wba/server.d.ts.map +1 -0
  311. package/dist/wba/server.js +29 -0
  312. package/dist/wba/types.d.ts +68 -0
  313. package/dist/wba/types.d.ts.map +1 -0
  314. package/dist/wba/types.js +6 -0
  315. package/package.json +223 -0
  316. package/src/blockchain/README.md +80 -0
  317. package/src/debug/README.md +94 -0
  318. package/src/e2e/README.md +105 -0
  319. package/src/i18n/README.md +143 -0
  320. package/src/shadcn_components/README.md +125 -0
  321. package/src/tasks/README.md +69 -0
  322. package/src/test-utils/README.md +638 -0
  323. package/src/util/README.md +18 -0
  324. package/src/wba/README.md +175 -0
package/package.json ADDED
@@ -0,0 +1,223 @@
1
+ {
2
+ "name": "@pasosdejesus/m",
3
+ "version": "0.15.0",
4
+ "description": "Motor para crear y gestionar proyectos al estilo Pasos de Jesus.",
5
+ "author": "",
6
+ "license": "ISC",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "type": "module",
13
+ "exports": {
14
+ "./package.json": "./package.json",
15
+ ".": {
16
+ "import": "./dist/index.js",
17
+ "types": "./dist/index.d.ts"
18
+ },
19
+ "./dist/*": {
20
+ "import": "./dist/*",
21
+ "types": "./dist/*.d.ts"
22
+ },
23
+ "./plugin": {
24
+ "import": "./dist/plugin.js",
25
+ "types": "./dist/plugin.d.ts"
26
+ },
27
+ "./test-utils": {
28
+ "import": "./dist/test-utils/index.js",
29
+ "types": "./dist/test-utils/index.d.ts"
30
+ },
31
+ "./test-utils/*": {
32
+ "import": "./dist/test-utils/*.js",
33
+ "types": "./dist/test-utils/*.d.ts"
34
+ },
35
+ "./i18n": {
36
+ "import": "./dist/i18n/index.js",
37
+ "types": "./dist/i18n/index.d.ts"
38
+ },
39
+ "./debug": {
40
+ "import": "./dist/debug/index.js",
41
+ "types": "./dist/debug/index.d.ts"
42
+ },
43
+ "./wba": {
44
+ "import": "./dist/wba/index.js",
45
+ "types": "./dist/wba/index.d.ts"
46
+ },
47
+ "./wba/routes": {
48
+ "import": "./dist/wba/routes/index.js",
49
+ "types": "./dist/wba/routes/index.d.ts"
50
+ },
51
+ "./wba/routes/*": {
52
+ "import": "./dist/wba/routes/*.js",
53
+ "types": "./dist/wba/routes/*.d.ts"
54
+ },
55
+ "./shadcn-components/ui/*": {
56
+ "import": "./dist/shadcn_components/ui/*.js",
57
+ "types": "./dist/shadcn_components/ui/*.d.ts"
58
+ },
59
+ "./shadcn-components/cn": {
60
+ "import": "./dist/shadcn_components/cn.js",
61
+ "types": "./dist/shadcn_components/cn.d.ts"
62
+ },
63
+ "./blockchain": {
64
+ "import": "./dist/blockchain/index.js",
65
+ "types": "./dist/blockchain/index.d.ts"
66
+ },
67
+ "./blockchain/deployments": {
68
+ "import": "./dist/blockchain/deployments.js",
69
+ "types": "./dist/blockchain/deployments.d.ts"
70
+ },
71
+ "./blockchain/credentials": {
72
+ "import": "./dist/blockchain/credentials.js",
73
+ "types": "./dist/blockchain/credentials.d.ts"
74
+ },
75
+ "./blockchain/admin-credentials": {
76
+ "import": "./dist/blockchain/admin-credentials.js",
77
+ "types": "./dist/blockchain/admin-credentials.d.ts"
78
+ },
79
+ "./blockchain/credential-images": {
80
+ "import": "./dist/blockchain/credential-images.js",
81
+ "types": "./dist/blockchain/credential-images.d.ts"
82
+ },
83
+ "./blockchain/credential-cache": {
84
+ "import": "./dist/blockchain/credential-cache.js",
85
+ "types": "./dist/blockchain/credential-cache.d.ts"
86
+ },
87
+ "./blockchain/ecosystem-addresses": {
88
+ "import": "./dist/blockchain/ecosystem-addresses.js",
89
+ "types": "./dist/blockchain/ecosystem-addresses.d.ts"
90
+ },
91
+ "./blockchain/slearn-info": {
92
+ "import": "./dist/blockchain/SlearnInfo.js",
93
+ "types": "./dist/blockchain/SlearnInfo.d.ts"
94
+ },
95
+ "./m": {
96
+ "import": "./dist/m.js",
97
+ "types": "./dist/m.d.ts"
98
+ },
99
+ "./e2e": {
100
+ "import": "./dist/e2e/index.js",
101
+ "types": "./dist/e2e/index.d.ts"
102
+ }
103
+ },
104
+ "bin": {
105
+ "m": "dist/m.js"
106
+ },
107
+ "files": [
108
+ "CHANGELOG.md",
109
+ "dist",
110
+ "doc",
111
+ "src/tasks/README.md",
112
+ "src/util/README.md",
113
+ "src/wba/README.md",
114
+ "src/i18n/README.md",
115
+ "src/debug/README.md",
116
+ "src/shadcn_components/README.md",
117
+ "src/test-utils/README.md",
118
+ "src/blockchain/README.md",
119
+ "src/e2e/README.md"
120
+ ],
121
+ "dependencies": {
122
+ "dotenv": "^17.4.2",
123
+ "execa": "^9.6.1",
124
+ "glob": "^13.0.6",
125
+ "picocolors": "^1.1.1"
126
+ },
127
+ "optionalDependencies": {
128
+ "@pasosdejesus/edr": "0.1.0",
129
+ "@pasosdejesus/contract-test": "0.1.0"
130
+ },
131
+ "devDependencies": {
132
+ "@radix-ui/react-accordion": "^1.2.12",
133
+ "@radix-ui/react-alert-dialog": "^1.1.15",
134
+ "@radix-ui/react-avatar": "^1.1.11",
135
+ "@radix-ui/react-checkbox": "^1.3.3",
136
+ "@radix-ui/react-dialog": "^1.1.15",
137
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
138
+ "@radix-ui/react-label": "^2.1.8",
139
+ "@radix-ui/react-menubar": "^1.1.16",
140
+ "@radix-ui/react-popover": "^1.1.15",
141
+ "@radix-ui/react-progress": "^1.1.8",
142
+ "@radix-ui/react-radio-group": "^1.3.8",
143
+ "@radix-ui/react-scroll-area": "^1.2.10",
144
+ "@radix-ui/react-select": "^2.2.6",
145
+ "@radix-ui/react-separator": "^1.1.8",
146
+ "@radix-ui/react-slider": "^1.3.6",
147
+ "@radix-ui/react-slot": "^1.2.4",
148
+ "@radix-ui/react-switch": "^1.2.6",
149
+ "@radix-ui/react-tabs": "^1.1.13",
150
+ "@radix-ui/react-toast": "^1.2.15",
151
+ "@radix-ui/react-tooltip": "^1.2.8",
152
+ "@remix-project/remix-lib": "link:../remix-project/libs/remix-lib",
153
+ "@remix-project/remix-simulator": "link:../remix-project/libs/remix-simulator",
154
+ "@testing-library/jest-dom": "^6.9.1",
155
+ "@testing-library/react": "^16.3.2",
156
+ "@types/node": "^20.19.41",
157
+ "@types/react": "^19.2.15",
158
+ "@types/react-dom": "^19.2.3",
159
+ "autoprefixer": "^10.5.0",
160
+ "class-variance-authority": "^0.7.1",
161
+ "clsx": "^2.1.1",
162
+ "jsdom": "^29.1.1",
163
+ "kysely": "^0.27.6",
164
+ "kysely-codegen": "^0.20.0",
165
+ "kysely-ctl": "^0.21.0",
166
+ "lucide-react": "^1.16.0",
167
+ "next": "^15.5.21",
168
+ "next-auth": "^4.24.14",
169
+ "pg": "^8.21.0",
170
+ "postcss": "^8.5.15",
171
+ "react": "^19.2.8",
172
+ "react-dom": "^19.2.8",
173
+ "react-hook-form": "^7.76.1",
174
+ "siwe": "^2.3.2",
175
+ "tailwind-merge": "^3.6.0",
176
+ "tailwindcss": "^4.3.0",
177
+ "typescript": "^5.9.3",
178
+ "viem": "^2.55.0",
179
+ "vitest": "2.1.9",
180
+ "wagmi": "^2.19.5"
181
+ },
182
+ "optionalPeerDependencies": {
183
+ "@radix-ui/react-accordion": "^1.2.12",
184
+ "@radix-ui/react-alert-dialog": "^1.1.15",
185
+ "@radix-ui/react-avatar": "^1.1.11",
186
+ "@radix-ui/react-checkbox": "^1.3.3",
187
+ "@radix-ui/react-dialog": "^1.1.15",
188
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
189
+ "@radix-ui/react-label": "^2.1.8",
190
+ "@radix-ui/react-menubar": "^1.1.16",
191
+ "@radix-ui/react-popover": "^1.1.15",
192
+ "@radix-ui/react-progress": "^1.1.8",
193
+ "@radix-ui/react-radio-group": "^1.3.8",
194
+ "@radix-ui/react-scroll-area": "^1.2.10",
195
+ "@radix-ui/react-select": "^2.2.6",
196
+ "@radix-ui/react-separator": "^1.1.8",
197
+ "@radix-ui/react-slider": "^1.3.6",
198
+ "@radix-ui/react-slot": "^1.2.4",
199
+ "@radix-ui/react-switch": "^1.2.6",
200
+ "@radix-ui/react-tabs": "^1.1.13",
201
+ "@radix-ui/react-toast": "^1.2.15",
202
+ "@radix-ui/react-tooltip": "^1.2.8",
203
+ "@testing-library/react": "^16.0.0",
204
+ "class-variance-authority": "^0.7.1",
205
+ "clsx": "^2.1.1",
206
+ "lucide-react": "^0.525.0",
207
+ "tailwind-merge": "^3.5.0",
208
+ "viem": "^2.51.0",
209
+ "next-auth": "^4.0.0",
210
+ "wagmi": "^2.0.0",
211
+ "siwe": "^2.1.0",
212
+ "kysely": "^0.27.0",
213
+ "pg": "^8.11.0",
214
+ "react-hook-form": "^7.0.0"
215
+ },
216
+ "scripts": {
217
+ "build": "rm -rf dist && npx tsc && perl -pi -e 'print \"#!/usr/bin/env node\\n\" if $. == 1' dist/m.js && mkdir -p dist/templates dist/blockchain && cp -R templates/* dist/templates/",
218
+ "start": "node dist/m.js m:create",
219
+ "test": "npx vitest run",
220
+ "typecheck": "tsc --noEmit",
221
+ "postinstall": "echo Instalación completada"
222
+ }
223
+ }
@@ -0,0 +1,80 @@
1
+ # Blockchain — Deployments (`@pasosdejesus/m/blockchain`)
2
+
3
+ > "For the Lord loves justice" (Psalm 37:28)
4
+
5
+ Shared deployment address resolution for Hardhat contract deployments.
6
+
7
+ > ⚠️ **Monorepo v0.15.0**: Los módulos de credenciales, admin, imágenes, cache,
8
+ > ecosystem-addresses y slearn-info se movieron a `@pasosdejesus/mpdj/blockchain/*`.
9
+ > Este archivo solo documenta `deployments` que permanece en `@pasosdejesus/m`.
10
+ > Ver [`packages/mpdj/src/blockchain/`](../../../mpdj/src/blockchain/) para los demás.
11
+
12
+ ## Exports
13
+
14
+ ### Deployments (`@pasosdejesus/m/blockchain/deployments`)
15
+
16
+ | Export | Type | Purpose |
17
+ |--------|------|---------|
18
+ | `readDeployment(network, deploymentsDir, opts?)` | function | Reads deployment JSON. `opts: { contract?, version? }` enables hierarchical path `{contract}/{version}/{network}.json` (falls back to flat `{network}.json`). |
19
+ | `getContractAddress(network, envVar, deploymentsDir, opts?)` | function | Address from deployment or env fallback |
20
+ | `getCeloCredentialsAddress(deploymentsDir, opts?)` | function | Celo address helper |
21
+ | `getBaseCredentialsAddress(deploymentsDir, opts?)` | function | Base address helper |
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import {
27
+ getCeloCredentialsAddress,
28
+ getContractAddress,
29
+ readDeployment,
30
+ } from '@pasosdejesus/m/blockchain/deployments'
31
+ import path from 'path'
32
+
33
+ const deploymentsDir = path.join(process.cwd(), '..', 'hardhat', 'deployments', 'PasosDeJesusCredentials')
34
+ const addr = getCeloCredentialsAddress(deploymentsDir)
35
+
36
+ // Read a specific deployment
37
+ const deployment = readDeployment('celoSepolia', deploymentsDir, { contract: 'PasosDeJesusCredentials', version: 'v1' })
38
+
39
+ // Get address with env fallback
40
+ const usdt = getContractAddress('celo', 'NEXT_PUBLIC_USDT_ADDRESS', deploymentsDir, { contract: 'USDT' })
41
+ ```
42
+
43
+ ## Architecture
44
+
45
+ ```
46
+ ┌──────────────────────────────────────────────────────┐
47
+ │ Project (sivel.xyz / learn.tg) │
48
+ │ │
49
+ │ apps/hardhat/deployments/ │
50
+ │ └── *.json (deployment addresses) │
51
+ │ │
52
+ │ lib/deployments.ts │
53
+ │ └── re-exports from @pasosdejesus/m/blockchain │
54
+ │ /deployments with local paths │
55
+ └──────────────────────────────────────────────────────┘
56
+ ```
57
+
58
+ ## Módulos movidos a `@pasosdejesus/mpdj`
59
+
60
+ Los siguientes módulos eran parte de `@pasosdejesus/m/blockchain` antes de v0.15.0.
61
+ Ahora están en `@pasosdejesus/mpdj/blockchain/*`:
62
+
63
+ | Módulo | Nueva ruta |
64
+ |--------|-----------|
65
+ | Credentials (mint, query) | `@pasosdejesus/mpdj/blockchain` |
66
+ | Admin (grant/revoke roles) | `@pasosdejesus/mpdj/blockchain/admin-credentials` |
67
+ | Credential images (SVG+PNG) | `@pasosdejesus/mpdj/blockchain/credential-images` |
68
+ | Credential cache (DB metadata) | `@pasosdejesus/mpdj/blockchain/credential-cache` |
69
+ | Ecosystem addresses | `@pasosdejesus/mpdj/blockchain/ecosystem-addresses` |
70
+ | SlearnInfo (React component) | `@pasosdejesus/mpdj/blockchain/slearn-info` |
71
+
72
+ Para migrar imports existentes:
73
+
74
+ ```diff
75
+ - import { mintCredentialWithRetry } from '@pasosdejesus/m/blockchain'
76
+ + import { mintCredentialWithRetry } from '@pasosdejesus/mpdj/blockchain'
77
+
78
+ - import { SLEARN_ADDRESSES } from '@pasosdejesus/m/blockchain/ecosystem-addresses'
79
+ + import { SLEARN_ADDRESSES } from '@pasosdejesus/mpdj/blockchain/ecosystem-addresses'
80
+ ```
@@ -0,0 +1,94 @@
1
+ # Debug Console — `@pasosdejesus/m/debug`
2
+
3
+ > *"Y todo lo que hagáis, hacedlo de corazón, como para el Señor y no para los hombres"* (Colosenses 3:23)
4
+
5
+ Floating debug console for MiniPay and embedded browsers. Displays real-time logs
6
+ inside the application without needing browser DevTools.
7
+
8
+ ## Exports
9
+
10
+ | Export | Type | Purpose |
11
+ |--------|------|---------|
12
+ | `Logger` | class | Logging engine — singleton, buffers 500 entries, writes to `console.*` |
13
+ | `logger` | instance | Pre-instantiated singleton |
14
+ | `useLogger` | hook (`'use client'`) | React hook — returns `{ logs, logger, isEnabled }` |
15
+ | `DebugConsole` | component (`'use client'`) | Floating UI — <kbd>&gt;_</kbd> button → log viewer |
16
+ | `safeStringify` | function | Serializes objects safely (circular references, Errors, truncation) |
17
+ | `debugLog` | function | `console.log` with `[DEBUG]` prefix and safe serialization |
18
+
19
+ ## Usage
20
+
21
+ ### 1. Render the console in your root layout
22
+
23
+ ```tsx
24
+ import { DebugConsole } from '@pasosdejesus/m/debug'
25
+
26
+ export default function ClientLayout({ children }) {
27
+ return (
28
+ <>
29
+ {children}
30
+ <DebugConsole />
31
+ </>
32
+ )
33
+ }
34
+ ```
35
+
36
+ The component renders `null` when disabled — no performance impact.
37
+
38
+ ### 2. Write logs from anywhere
39
+
40
+ ```typescript
41
+ import { logger } from '@pasosdejesus/m/debug'
42
+
43
+ logger.info('Loading data...', 'MyModule')
44
+ logger.success('Data loaded', 'MyModule')
45
+ logger.error('Failed to fetch', 'MyModule')
46
+ logger.warning('Retrying...', 'MyModule')
47
+ ```
48
+
49
+ The second argument (`source`) groups logs by module in the console UI.
50
+
51
+ ### 3. Enable the console
52
+
53
+ | Method | How |
54
+ |--------|-----|
55
+ | **URL parameter** | Add `?debug=1` to the URL |
56
+ | **Environment variable** | Set `NEXT_PUBLIC_M_DEBUGGER_CONSOLE=1` at build time |
57
+
58
+ ## Activate via URL (recommended)
59
+
60
+ ```
61
+ https://example.com/page?debug=1
62
+ ```
63
+
64
+ In all cases, logs are always written to `console.log`/`console.error` via
65
+ browser DevTools regardless of the floating console state.
66
+
67
+ ## Architecture
68
+
69
+ ```
70
+ ClientLayout
71
+ └── <DebugConsole /> ← renders always (returns null when disabled)
72
+ └── useLogger() ← subscribes to Logger singleton
73
+
74
+ Any component/module ← writes via
75
+ └── logger.info('msg') → Logger singleton → console.log (always)
76
+ → subscribers (debug UI)
77
+ ```
78
+
79
+ ## FAQ
80
+
81
+ ### Why doesn't the console appear?
82
+
83
+ - Make sure the URL has `?debug=1`
84
+ - Restart the app
85
+
86
+ ### Are logs persisted?
87
+
88
+ No. Logs are volatile (buffer up to 500 entries). Use the **copy** button (📋)
89
+ before closing to preserve them.
90
+
91
+ ### Can I use it on desktop?
92
+
93
+ Yes. On desktop you can also use F12 DevTools — the Logger writes to
94
+ `console.log` regardless of the floating console.
@@ -0,0 +1,105 @@
1
+ # @pasosdejesus/m/e2e
2
+
3
+ E2E test helpers for Puppeteer + SIWE on OpenBSD/adJ.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # In your project
9
+ pnpm add -D puppeteer-core
10
+ mkdir -p e2e/specs e2e/smoke
11
+ ```
12
+
13
+ ```js
14
+ // e2e/specs/my-test.spec.mjs
15
+ import {
16
+ initTestEnv, launchBrowser, newPage,
17
+ resetFailures, ok, fail, summary,
18
+ simulateSIWE, checkSessionFull,
19
+ waitForText, short,
20
+ } from '@pasosdejesus/m/e2e'
21
+
22
+ const env = await initTestEnv()
23
+ const browser = await launchBrowser(env.headless)
24
+ const page = await newPage(browser, env.account.address, env.timeout)
25
+
26
+ await page.goto(`${env.base}/en`, { waitUntil: 'domcontentloaded' })
27
+ await simulateSIWE(page, env)
28
+ ok('SIWE completed')
29
+
30
+ await browser.close()
31
+ const failures = summary(performance.now())
32
+ process.exit(failures > 0 ? 1 : 0)
33
+ ```
34
+
35
+ Run:
36
+ ```bash
37
+ CHROME_PATH=/usr/local/bin/chromium IPDES=learn.tg node e2e/specs/my-test.spec.mjs
38
+ ```
39
+
40
+ Or via CLI:
41
+ ```bash
42
+ ./bin/m test:e2e my-test
43
+ ./bin/m test:e2e --smoke # HTTP-only, no Chrome
44
+ ./bin/m test:e2e --grep session # Filter by name
45
+ ```
46
+
47
+ ## API
48
+
49
+ ### Assertions
50
+ ```ts
51
+ ok(msg: string) // ✅ success
52
+ fail(msg: string) // ❌ failure (increments counter)
53
+ resetFailures() // Reset counter
54
+ summary(t0: number): number // Print summary, return failure count
55
+ ```
56
+
57
+ ### Environment
58
+ ```ts
59
+ await initTestEnv(): E2EEnv // { base, timeout, account, chainId, headless, ... }
60
+ short(addr: string): string // Truncate address to 10 chars + ...
61
+ ```
62
+
63
+ ### Browser
64
+ ```ts
65
+ findChrome(): string
66
+ launchBrowser(headless?: boolean): Promise<E2EBrowser>
67
+ newPage(browser, address, timeout?): Promise<E2EPage>
68
+ newIncognitoContext(browser): Promise<E2EBrowserContext>
69
+ newIncognitoPage(ctx, address, timeout?): Promise<E2EPage> // with mock auto-injected
70
+ clearBrowserCache(page): Promise<void>
71
+ ```
72
+
73
+ ### SIWE
74
+ ```ts
75
+ simulateSIWE(page, params): Promise<boolean>
76
+ // params: { account, host, domainPort, base, chainId, statement? }
77
+ checkSessionFull(page): Promise<boolean>
78
+ checkPartialLogin(page): Promise<boolean> // detect "Partial login" guard message in DOM
79
+ ```
80
+
81
+ ### Navigation
82
+ ```ts
83
+ safeNavigate(page, link, hrefFallback?): Promise<void>
84
+ waitForText(page, text, maxSeconds?): Promise<boolean>
85
+ ```
86
+
87
+ ### Wallet Mock
88
+ ```ts
89
+ ethereumMockCode({ address, chainId? }): string
90
+ eip6963MockCode({ address, chainId?, walletName? }): string // wagmi-compatible
91
+ injectEIP6963(page, { address, chainId?, walletName? }): Promise<void>
92
+ ```
93
+
94
+ Use `eip6963MockCode` or `injectEIP6963` when tests need `useAccount()`, `useWalletClient()`,
95
+ or `usePublicClient()` from wagmi. Pass `useEIP6963: true` to `newPage()` or `newIncognitoPage()`.
96
+
97
+ ```js
98
+ // Spec with wagmi support
99
+ const page = await newPage(browser, address, timeout, true)
100
+ // GoodDollarClaimButton, wallet interactions now work
101
+ ```
102
+
103
+ ## Environment Variables
104
+
105
+ See [doc/e2e.md](../../../../doc/e2e.md) for full reference.
@@ -0,0 +1,143 @@
1
+ # `@pasosdejesus/m/i18n` — Zero-Dependency Internationalization
2
+
3
+ Framework-free translations for Next.js apps. Pure TypeScript objects, no i18n library.
4
+
5
+ ## Exports
6
+
7
+ | Export | Location | Dependencies | Use in |
8
+ |--------|----------|-------------|--------|
9
+ | `createTranslator` | `createTranslator.ts` | None | Server components, pure functions, client components |
10
+ | `TranslationSet` | `types.ts` | None | Type definitions |
11
+ | `LocaleStrings` | `types.ts` | None | Type definitions |
12
+
13
+ > **Note:** `useTranslation` (React hook) is **not** included in this package
14
+ > to avoid a hard dependency on `next/navigation`. Each project creates its
15
+ > own thin wrapper — see "Client component" example below.
16
+
17
+ ## Usage
18
+
19
+ ### 1. Define translations
20
+
21
+ ```ts
22
+ // In your component or page
23
+ const localT = {
24
+ en: { hello: 'Hello', greeting: 'Hello {{0}}' },
25
+ es: { hello: 'Hola', greeting: 'Hola {{0}}' },
26
+ }
27
+ ```
28
+
29
+ ### 2a. Client component (with `useTranslation` hook)
30
+
31
+ Each project creates its own thin wrapper hook:
32
+
33
+ ```tsx
34
+ // hooks/useTranslation.ts
35
+ 'use client'
36
+ import { useParams } from 'next/navigation'
37
+ import { useMemo } from 'react'
38
+ import { createTranslator } from '@pasosdejesus/m/i18n'
39
+ import type { TranslationSet } from '@pasosdejesus/m/i18n'
40
+ import commonTranslations from '@/lib/i18n/common'
41
+
42
+ export function useTranslation(
43
+ translations: TranslationSet,
44
+ paramName: string = 'locale'
45
+ ) {
46
+ const params = useParams()
47
+ const locale = ((params?.[paramName] as string) || 'en')
48
+ const t = useMemo(
49
+ () => createTranslator(locale, translations, commonTranslations),
50
+ [locale, translations]
51
+ )
52
+ return { t, locale }
53
+ }
54
+ ```
55
+
56
+ Then in any component:
57
+
58
+ ```tsx
59
+ 'use client'
60
+ import { useTranslation } from '@/hooks/useTranslation'
61
+
62
+ const localT = {
63
+ en: { hello: 'Hello' },
64
+ es: { hello: 'Hola' },
65
+ }
66
+
67
+ export function MyComponent() {
68
+ const { t } = useTranslation(localT)
69
+ return <h1>{t('hello')}</h1>
70
+ }
71
+ ```
72
+
73
+ ### 2b. Server component
74
+
75
+ ```tsx
76
+ import { createTranslator } from '@pasosdejesus/m/i18n'
77
+
78
+ const localT = {
79
+ en: { title: 'Hello' },
80
+ es: { title: 'Hola' },
81
+ }
82
+
83
+ export default async function Page({ params }: { params: { locale: string } }) {
84
+ const { locale } = await params
85
+ const t = createTranslator(locale, localT)
86
+ return <h1>{t('title')}</h1>
87
+ }
88
+ ```
89
+
90
+ ### 3. Common translations (shared across the app)
91
+
92
+ ```ts
93
+ // lib/i18n/common.ts
94
+ import type { TranslationSet } from '@pasosdejesus/m/i18n'
95
+
96
+ const common: TranslationSet = {
97
+ en: { save: 'Save', cancel: 'Cancel' },
98
+ es: { save: 'Guardar', cancel: 'Cancelar' },
99
+ }
100
+ export default common
101
+ ```
102
+
103
+ Pass `common` to `createTranslator` (server):
104
+
105
+ ```tsx
106
+ import { createTranslator } from '@pasosdejesus/m/i18n'
107
+ import common from '@/lib/i18n/common'
108
+
109
+ const t = createTranslator(locale, localT, common)
110
+ t('save') // → 'Guardar' (from common[es])
111
+ ```
112
+
113
+ For client components, the project's `useTranslation` hook injects `commonTranslations`
114
+ automatically (see 2a), so no extra import is needed:
115
+
116
+ ### Fallback Resolution Order
117
+
118
+ 1. `translations[locale]`
119
+ 2. `translations['en']`
120
+ 3. `common[locale]` (if provided)
121
+ 4. `common['en']` (if provided)
122
+ 5. The raw key
123
+
124
+ ### Interpolation
125
+
126
+ Use `{{0}}`, `{{1}}`, etc. as placeholders:
127
+
128
+ ```ts
129
+ const localT = {
130
+ en: { greeting: 'Hello {{0}}', welcome: 'Welcome {{0}}, you have {{1}} messages' },
131
+ es: { greeting: 'Hola {{0}}', welcome: 'Bienvenido {{0}}, tienes {{1}} mensajes' },
132
+ }
133
+
134
+ const t = createTranslator('es', localT)
135
+ t('greeting', 'Mundo') // → 'Hola Mundo'
136
+
137
+ const tEn = createTranslator('en', localT)
138
+ tEn('welcome', 'John', '5') // → 'Welcome John, you have 5 messages'
139
+ ```
140
+
141
+ ## Why no i18n library?
142
+
143
+ Traditional i18n libraries (`next-i18next`, `next-intl`) have shown compatibility or performance issues on **OpenBSD/adJ**. Pure TypeScript objects give maximum performance, zero external dependencies, and full type safety.