@nac3/forge-cli 0.2.0-alpha.1

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 (561) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +371 -0
  3. package/dist/bin/yf.d.ts +5 -0
  4. package/dist/bin/yf.d.ts.map +1 -0
  5. package/dist/bin/yf.js +86 -0
  6. package/dist/bin/yf.js.map +1 -0
  7. package/dist/chat/claude.d.ts +100 -0
  8. package/dist/chat/claude.d.ts.map +1 -0
  9. package/dist/chat/claude.js +228 -0
  10. package/dist/chat/claude.js.map +1 -0
  11. package/dist/chat/ingest_session.d.ts +97 -0
  12. package/dist/chat/ingest_session.d.ts.map +1 -0
  13. package/dist/chat/ingest_session.js +99 -0
  14. package/dist/chat/ingest_session.js.map +1 -0
  15. package/dist/chat/panel.d.ts +15 -0
  16. package/dist/chat/panel.d.ts.map +1 -0
  17. package/dist/chat/panel.js +1526 -0
  18. package/dist/chat/panel.js.map +1 -0
  19. package/dist/chat/persistence.d.ts +37 -0
  20. package/dist/chat/persistence.d.ts.map +1 -0
  21. package/dist/chat/persistence.js +91 -0
  22. package/dist/chat/persistence.js.map +1 -0
  23. package/dist/chat/server.d.ts +34 -0
  24. package/dist/chat/server.d.ts.map +1 -0
  25. package/dist/chat/server.js +1540 -0
  26. package/dist/chat/server.js.map +1 -0
  27. package/dist/chat/spec_extract.d.ts +35 -0
  28. package/dist/chat/spec_extract.d.ts.map +1 -0
  29. package/dist/chat/spec_extract.js +152 -0
  30. package/dist/chat/spec_extract.js.map +1 -0
  31. package/dist/chat/spec_plan.d.ts +65 -0
  32. package/dist/chat/spec_plan.d.ts.map +1 -0
  33. package/dist/chat/spec_plan.js +160 -0
  34. package/dist/chat/spec_plan.js.map +1 -0
  35. package/dist/chat/spec_scaffold.d.ts +95 -0
  36. package/dist/chat/spec_scaffold.d.ts.map +1 -0
  37. package/dist/chat/spec_scaffold.js +220 -0
  38. package/dist/chat/spec_scaffold.js.map +1 -0
  39. package/dist/chat/tools/git.d.ts +59 -0
  40. package/dist/chat/tools/git.d.ts.map +1 -0
  41. package/dist/chat/tools/git.js +313 -0
  42. package/dist/chat/tools/git.js.map +1 -0
  43. package/dist/chat/tools/github.d.ts +59 -0
  44. package/dist/chat/tools/github.d.ts.map +1 -0
  45. package/dist/chat/tools/github.js +310 -0
  46. package/dist/chat/tools/github.js.map +1 -0
  47. package/dist/chat/tools/lifecycle.d.ts +82 -0
  48. package/dist/chat/tools/lifecycle.d.ts.map +1 -0
  49. package/dist/chat/tools/lifecycle.js +295 -0
  50. package/dist/chat/tools/lifecycle.js.map +1 -0
  51. package/dist/chat/tools/manual.d.ts +26 -0
  52. package/dist/chat/tools/manual.d.ts.map +1 -0
  53. package/dist/chat/tools/manual.js +164 -0
  54. package/dist/chat/tools/manual.js.map +1 -0
  55. package/dist/chat/tools/reader.d.ts +80 -0
  56. package/dist/chat/tools/reader.d.ts.map +1 -0
  57. package/dist/chat/tools/reader.js +471 -0
  58. package/dist/chat/tools/reader.js.map +1 -0
  59. package/dist/chat/tools.d.ts +106 -0
  60. package/dist/chat/tools.d.ts.map +1 -0
  61. package/dist/chat/tools.js +587 -0
  62. package/dist/chat/tools.js.map +1 -0
  63. package/dist/codegen/e2e.d.ts +106 -0
  64. package/dist/codegen/e2e.d.ts.map +1 -0
  65. package/dist/codegen/e2e.js +931 -0
  66. package/dist/codegen/e2e.js.map +1 -0
  67. package/dist/codegen/v3_flow_emit.d.ts +70 -0
  68. package/dist/codegen/v3_flow_emit.d.ts.map +1 -0
  69. package/dist/codegen/v3_flow_emit.js +225 -0
  70. package/dist/codegen/v3_flow_emit.js.map +1 -0
  71. package/dist/commands/_stub.d.ts +2 -0
  72. package/dist/commands/_stub.d.ts.map +1 -0
  73. package/dist/commands/_stub.js +21 -0
  74. package/dist/commands/_stub.js.map +1 -0
  75. package/dist/commands/app.d.ts +31 -0
  76. package/dist/commands/app.d.ts.map +1 -0
  77. package/dist/commands/app.js +331 -0
  78. package/dist/commands/app.js.map +1 -0
  79. package/dist/commands/chat.d.ts +18 -0
  80. package/dist/commands/chat.d.ts.map +1 -0
  81. package/dist/commands/chat.js +76 -0
  82. package/dist/commands/chat.js.map +1 -0
  83. package/dist/commands/deploy.d.ts +21 -0
  84. package/dist/commands/deploy.d.ts.map +1 -0
  85. package/dist/commands/deploy.js +121 -0
  86. package/dist/commands/deploy.js.map +1 -0
  87. package/dist/commands/doctor.d.ts +14 -0
  88. package/dist/commands/doctor.d.ts.map +1 -0
  89. package/dist/commands/doctor.js +280 -0
  90. package/dist/commands/doctor.js.map +1 -0
  91. package/dist/commands/figma.d.ts +32 -0
  92. package/dist/commands/figma.d.ts.map +1 -0
  93. package/dist/commands/figma.js +141 -0
  94. package/dist/commands/figma.js.map +1 -0
  95. package/dist/commands/gen-flow-tests.d.ts +8 -0
  96. package/dist/commands/gen-flow-tests.d.ts.map +1 -0
  97. package/dist/commands/gen-flow-tests.js +78 -0
  98. package/dist/commands/gen-flow-tests.js.map +1 -0
  99. package/dist/commands/gen-tests.d.ts +9 -0
  100. package/dist/commands/gen-tests.d.ts.map +1 -0
  101. package/dist/commands/gen-tests.js +118 -0
  102. package/dist/commands/gen-tests.js.map +1 -0
  103. package/dist/commands/license.d.ts +14 -0
  104. package/dist/commands/license.d.ts.map +1 -0
  105. package/dist/commands/license.js +182 -0
  106. package/dist/commands/license.js.map +1 -0
  107. package/dist/commands/log.d.ts +19 -0
  108. package/dist/commands/log.d.ts.map +1 -0
  109. package/dist/commands/log.js +101 -0
  110. package/dist/commands/log.js.map +1 -0
  111. package/dist/commands/migrate.d.ts +118 -0
  112. package/dist/commands/migrate.d.ts.map +1 -0
  113. package/dist/commands/migrate.js +1410 -0
  114. package/dist/commands/migrate.js.map +1 -0
  115. package/dist/commands/mobile.d.ts +27 -0
  116. package/dist/commands/mobile.d.ts.map +1 -0
  117. package/dist/commands/mobile.js +90 -0
  118. package/dist/commands/mobile.js.map +1 -0
  119. package/dist/commands/new.d.ts +32 -0
  120. package/dist/commands/new.d.ts.map +1 -0
  121. package/dist/commands/new.js +107 -0
  122. package/dist/commands/new.js.map +1 -0
  123. package/dist/commands/pilot.d.ts +8 -0
  124. package/dist/commands/pilot.d.ts.map +1 -0
  125. package/dist/commands/pilot.js +104 -0
  126. package/dist/commands/pilot.js.map +1 -0
  127. package/dist/commands/projects.d.ts +21 -0
  128. package/dist/commands/projects.d.ts.map +1 -0
  129. package/dist/commands/projects.js +238 -0
  130. package/dist/commands/projects.js.map +1 -0
  131. package/dist/commands/publish.d.ts +35 -0
  132. package/dist/commands/publish.d.ts.map +1 -0
  133. package/dist/commands/publish.js +194 -0
  134. package/dist/commands/publish.js.map +1 -0
  135. package/dist/commands/repo.d.ts +59 -0
  136. package/dist/commands/repo.d.ts.map +1 -0
  137. package/dist/commands/repo.js +178 -0
  138. package/dist/commands/repo.js.map +1 -0
  139. package/dist/commands/review-screens.d.ts +28 -0
  140. package/dist/commands/review-screens.d.ts.map +1 -0
  141. package/dist/commands/review-screens.js +345 -0
  142. package/dist/commands/review-screens.js.map +1 -0
  143. package/dist/commands/scenarios.d.ts +23 -0
  144. package/dist/commands/scenarios.d.ts.map +1 -0
  145. package/dist/commands/scenarios.js +304 -0
  146. package/dist/commands/scenarios.js.map +1 -0
  147. package/dist/commands/ship.d.ts +18 -0
  148. package/dist/commands/ship.d.ts.map +1 -0
  149. package/dist/commands/ship.js +41 -0
  150. package/dist/commands/ship.js.map +1 -0
  151. package/dist/commands/test.d.ts +29 -0
  152. package/dist/commands/test.d.ts.map +1 -0
  153. package/dist/commands/test.js +62 -0
  154. package/dist/commands/test.js.map +1 -0
  155. package/dist/commands/tunnel.d.ts +22 -0
  156. package/dist/commands/tunnel.d.ts.map +1 -0
  157. package/dist/commands/tunnel.js +77 -0
  158. package/dist/commands/tunnel.js.map +1 -0
  159. package/dist/commands/validate.d.ts +14 -0
  160. package/dist/commands/validate.d.ts.map +1 -0
  161. package/dist/commands/validate.js +51 -0
  162. package/dist/commands/validate.js.map +1 -0
  163. package/dist/commands/vault.d.ts +32 -0
  164. package/dist/commands/vault.d.ts.map +1 -0
  165. package/dist/commands/vault.js +489 -0
  166. package/dist/commands/vault.js.map +1 -0
  167. package/dist/commands/voice.d.ts +16 -0
  168. package/dist/commands/voice.d.ts.map +1 -0
  169. package/dist/commands/voice.js +69 -0
  170. package/dist/commands/voice.js.map +1 -0
  171. package/dist/core/cascade_router.d.ts +90 -0
  172. package/dist/core/cascade_router.d.ts.map +1 -0
  173. package/dist/core/cascade_router.js +131 -0
  174. package/dist/core/cascade_router.js.map +1 -0
  175. package/dist/core/cf_tunnel.d.ts +52 -0
  176. package/dist/core/cf_tunnel.d.ts.map +1 -0
  177. package/dist/core/cf_tunnel.js +134 -0
  178. package/dist/core/cf_tunnel.js.map +1 -0
  179. package/dist/core/gha_dispatcher.d.ts +48 -0
  180. package/dist/core/gha_dispatcher.d.ts.map +1 -0
  181. package/dist/core/gha_dispatcher.js +198 -0
  182. package/dist/core/gha_dispatcher.js.map +1 -0
  183. package/dist/core/logger.d.ts +89 -0
  184. package/dist/core/logger.d.ts.map +1 -0
  185. package/dist/core/logger.js +245 -0
  186. package/dist/core/logger.js.map +1 -0
  187. package/dist/core/mode.d.ts +26 -0
  188. package/dist/core/mode.d.ts.map +1 -0
  189. package/dist/core/mode.js +122 -0
  190. package/dist/core/mode.js.map +1 -0
  191. package/dist/core/pairing.d.ts +40 -0
  192. package/dist/core/pairing.d.ts.map +1 -0
  193. package/dist/core/pairing.js +145 -0
  194. package/dist/core/pairing.js.map +1 -0
  195. package/dist/core/pilot_setup.d.ts +29 -0
  196. package/dist/core/pilot_setup.d.ts.map +1 -0
  197. package/dist/core/pilot_setup.js +119 -0
  198. package/dist/core/pilot_setup.js.map +1 -0
  199. package/dist/core/polar.d.ts +81 -0
  200. package/dist/core/polar.d.ts.map +1 -0
  201. package/dist/core/polar.js +175 -0
  202. package/dist/core/polar.js.map +1 -0
  203. package/dist/core/project_picker.d.ts +56 -0
  204. package/dist/core/project_picker.d.ts.map +1 -0
  205. package/dist/core/project_picker.js +86 -0
  206. package/dist/core/project_picker.js.map +1 -0
  207. package/dist/core/projects.d.ts +58 -0
  208. package/dist/core/projects.d.ts.map +1 -0
  209. package/dist/core/projects.js +146 -0
  210. package/dist/core/projects.js.map +1 -0
  211. package/dist/core/projects_sync.d.ts +80 -0
  212. package/dist/core/projects_sync.d.ts.map +1 -0
  213. package/dist/core/projects_sync.js +278 -0
  214. package/dist/core/projects_sync.js.map +1 -0
  215. package/dist/core/remote_runner.d.ts +70 -0
  216. package/dist/core/remote_runner.d.ts.map +1 -0
  217. package/dist/core/remote_runner.js +133 -0
  218. package/dist/core/remote_runner.js.map +1 -0
  219. package/dist/core/repo_state.d.ts +24 -0
  220. package/dist/core/repo_state.d.ts.map +1 -0
  221. package/dist/core/repo_state.js +109 -0
  222. package/dist/core/repo_state.js.map +1 -0
  223. package/dist/core/target.d.ts +31 -0
  224. package/dist/core/target.d.ts.map +1 -0
  225. package/dist/core/target.js +121 -0
  226. package/dist/core/target.js.map +1 -0
  227. package/dist/deploy/aws.d.ts +43 -0
  228. package/dist/deploy/aws.d.ts.map +1 -0
  229. package/dist/deploy/aws.js +173 -0
  230. package/dist/deploy/aws.js.map +1 -0
  231. package/dist/figma/api.d.ts +35 -0
  232. package/dist/figma/api.d.ts.map +1 -0
  233. package/dist/figma/api.js +40 -0
  234. package/dist/figma/api.js.map +1 -0
  235. package/dist/figma/decorator.d.ts +74 -0
  236. package/dist/figma/decorator.d.ts.map +1 -0
  237. package/dist/figma/decorator.js +210 -0
  238. package/dist/figma/decorator.js.map +1 -0
  239. package/dist/figma/heuristics.d.ts +29 -0
  240. package/dist/figma/heuristics.d.ts.map +1 -0
  241. package/dist/figma/heuristics.js +110 -0
  242. package/dist/figma/heuristics.js.map +1 -0
  243. package/dist/figma/normalize.d.ts +33 -0
  244. package/dist/figma/normalize.d.ts.map +1 -0
  245. package/dist/figma/normalize.js +101 -0
  246. package/dist/figma/normalize.js.map +1 -0
  247. package/dist/figma/tokens.d.ts +23 -0
  248. package/dist/figma/tokens.d.ts.map +1 -0
  249. package/dist/figma/tokens.js +111 -0
  250. package/dist/figma/tokens.js.map +1 -0
  251. package/dist/figma/types.d.ts +118 -0
  252. package/dist/figma/types.d.ts.map +1 -0
  253. package/dist/figma/types.js +12 -0
  254. package/dist/figma/types.js.map +1 -0
  255. package/dist/i18n/index.d.ts +48 -0
  256. package/dist/i18n/index.d.ts.map +1 -0
  257. package/dist/i18n/index.js +135 -0
  258. package/dist/i18n/index.js.map +1 -0
  259. package/dist/i18n/types.d.ts +52 -0
  260. package/dist/i18n/types.d.ts.map +1 -0
  261. package/dist/i18n/types.js +85 -0
  262. package/dist/i18n/types.js.map +1 -0
  263. package/dist/index.d.ts +12 -0
  264. package/dist/index.d.ts.map +1 -0
  265. package/dist/index.js +11 -0
  266. package/dist/index.js.map +1 -0
  267. package/dist/lan/mdns_packet.d.ts +74 -0
  268. package/dist/lan/mdns_packet.d.ts.map +1 -0
  269. package/dist/lan/mdns_packet.js +247 -0
  270. package/dist/lan/mdns_packet.js.map +1 -0
  271. package/dist/lan/mdns_service.d.ts +102 -0
  272. package/dist/lan/mdns_service.d.ts.map +1 -0
  273. package/dist/lan/mdns_service.js +206 -0
  274. package/dist/lan/mdns_service.js.map +1 -0
  275. package/dist/license/activate.d.ts +33 -0
  276. package/dist/license/activate.d.ts.map +1 -0
  277. package/dist/license/activate.js +135 -0
  278. package/dist/license/activate.js.map +1 -0
  279. package/dist/license/fingerprint.d.ts +2 -0
  280. package/dist/license/fingerprint.d.ts.map +1 -0
  281. package/dist/license/fingerprint.js +29 -0
  282. package/dist/license/fingerprint.js.map +1 -0
  283. package/dist/license/hito4_client.d.ts +24 -0
  284. package/dist/license/hito4_client.d.ts.map +1 -0
  285. package/dist/license/hito4_client.js +103 -0
  286. package/dist/license/hito4_client.js.map +1 -0
  287. package/dist/license/index.d.ts +22 -0
  288. package/dist/license/index.d.ts.map +1 -0
  289. package/dist/license/index.js +125 -0
  290. package/dist/license/index.js.map +1 -0
  291. package/dist/license/types.d.ts +38 -0
  292. package/dist/license/types.d.ts.map +1 -0
  293. package/dist/license/types.js +9 -0
  294. package/dist/license/types.js.map +1 -0
  295. package/dist/migrate/ai-apply.d.ts +198 -0
  296. package/dist/migrate/ai-apply.d.ts.map +1 -0
  297. package/dist/migrate/ai-apply.js +833 -0
  298. package/dist/migrate/ai-apply.js.map +1 -0
  299. package/dist/migrate/ai-decorator.d.ts +87 -0
  300. package/dist/migrate/ai-decorator.d.ts.map +1 -0
  301. package/dist/migrate/ai-decorator.js +203 -0
  302. package/dist/migrate/ai-decorator.js.map +1 -0
  303. package/dist/migrate/apply.d.ts +28 -0
  304. package/dist/migrate/apply.d.ts.map +1 -0
  305. package/dist/migrate/apply.js +119 -0
  306. package/dist/migrate/apply.js.map +1 -0
  307. package/dist/migrate/audit.d.ts +9 -0
  308. package/dist/migrate/audit.d.ts.map +1 -0
  309. package/dist/migrate/audit.js +197 -0
  310. package/dist/migrate/audit.js.map +1 -0
  311. package/dist/migrate/diff.d.ts +28 -0
  312. package/dist/migrate/diff.d.ts.map +1 -0
  313. package/dist/migrate/diff.js +154 -0
  314. package/dist/migrate/diff.js.map +1 -0
  315. package/dist/migrate/html-orchestrator.d.ts +81 -0
  316. package/dist/migrate/html-orchestrator.d.ts.map +1 -0
  317. package/dist/migrate/html-orchestrator.js +233 -0
  318. package/dist/migrate/html-orchestrator.js.map +1 -0
  319. package/dist/migrate/html-walker.d.ts +93 -0
  320. package/dist/migrate/html-walker.d.ts.map +1 -0
  321. package/dist/migrate/html-walker.js +288 -0
  322. package/dist/migrate/html-walker.js.map +1 -0
  323. package/dist/migrate/js-template-walker.d.ts +118 -0
  324. package/dist/migrate/js-template-walker.d.ts.map +1 -0
  325. package/dist/migrate/js-template-walker.js +644 -0
  326. package/dist/migrate/js-template-walker.js.map +1 -0
  327. package/dist/migrate/manifest-validator.d.ts +30 -0
  328. package/dist/migrate/manifest-validator.d.ts.map +1 -0
  329. package/dist/migrate/manifest-validator.js +261 -0
  330. package/dist/migrate/manifest-validator.js.map +1 -0
  331. package/dist/migrate/overrides.d.ts +58 -0
  332. package/dist/migrate/overrides.d.ts.map +1 -0
  333. package/dist/migrate/overrides.js +193 -0
  334. package/dist/migrate/overrides.js.map +1 -0
  335. package/dist/migrate/plugin-scope.d.ts +42 -0
  336. package/dist/migrate/plugin-scope.d.ts.map +1 -0
  337. package/dist/migrate/plugin-scope.js +94 -0
  338. package/dist/migrate/plugin-scope.js.map +1 -0
  339. package/dist/migrate/types.d.ts +45 -0
  340. package/dist/migrate/types.d.ts.map +1 -0
  341. package/dist/migrate/types.js +9 -0
  342. package/dist/migrate/types.js.map +1 -0
  343. package/dist/migrate/verb-inference.d.ts +37 -0
  344. package/dist/migrate/verb-inference.d.ts.map +1 -0
  345. package/dist/migrate/verb-inference.js +274 -0
  346. package/dist/migrate/verb-inference.js.map +1 -0
  347. package/dist/nac3/attrs.d.ts +87 -0
  348. package/dist/nac3/attrs.d.ts.map +1 -0
  349. package/dist/nac3/attrs.js +134 -0
  350. package/dist/nac3/attrs.js.map +1 -0
  351. package/dist/nac3/scenario_dsl.d.ts +71 -0
  352. package/dist/nac3/scenario_dsl.d.ts.map +1 -0
  353. package/dist/nac3/scenario_dsl.js +191 -0
  354. package/dist/nac3/scenario_dsl.js.map +1 -0
  355. package/dist/nac3/tokens.d.ts +126 -0
  356. package/dist/nac3/tokens.d.ts.map +1 -0
  357. package/dist/nac3/tokens.js +138 -0
  358. package/dist/nac3/tokens.js.map +1 -0
  359. package/dist/reader/parsers/csv.d.ts +42 -0
  360. package/dist/reader/parsers/csv.d.ts.map +1 -0
  361. package/dist/reader/parsers/csv.js +221 -0
  362. package/dist/reader/parsers/csv.js.map +1 -0
  363. package/dist/reader/parsers/docx.d.ts +31 -0
  364. package/dist/reader/parsers/docx.d.ts.map +1 -0
  365. package/dist/reader/parsers/docx.js +51 -0
  366. package/dist/reader/parsers/docx.js.map +1 -0
  367. package/dist/reader/parsers/epub.d.ts +39 -0
  368. package/dist/reader/parsers/epub.d.ts.map +1 -0
  369. package/dist/reader/parsers/epub.js +265 -0
  370. package/dist/reader/parsers/epub.js.map +1 -0
  371. package/dist/reader/parsers/html.d.ts +40 -0
  372. package/dist/reader/parsers/html.d.ts.map +1 -0
  373. package/dist/reader/parsers/html.js +386 -0
  374. package/dist/reader/parsers/html.js.map +1 -0
  375. package/dist/reader/parsers/md.d.ts +30 -0
  376. package/dist/reader/parsers/md.d.ts.map +1 -0
  377. package/dist/reader/parsers/md.js +199 -0
  378. package/dist/reader/parsers/md.js.map +1 -0
  379. package/dist/reader/parsers/pdf.d.ts +39 -0
  380. package/dist/reader/parsers/pdf.d.ts.map +1 -0
  381. package/dist/reader/parsers/pdf.js +220 -0
  382. package/dist/reader/parsers/pdf.js.map +1 -0
  383. package/dist/reader/parsers/rtf.d.ts +37 -0
  384. package/dist/reader/parsers/rtf.d.ts.map +1 -0
  385. package/dist/reader/parsers/rtf.js +347 -0
  386. package/dist/reader/parsers/rtf.js.map +1 -0
  387. package/dist/reader/parsers/source.d.ts +32 -0
  388. package/dist/reader/parsers/source.d.ts.map +1 -0
  389. package/dist/reader/parsers/source.js +122 -0
  390. package/dist/reader/parsers/source.js.map +1 -0
  391. package/dist/reader/parsers/txt.d.ts +25 -0
  392. package/dist/reader/parsers/txt.d.ts.map +1 -0
  393. package/dist/reader/parsers/txt.js +56 -0
  394. package/dist/reader/parsers/txt.js.map +1 -0
  395. package/dist/reader/parsers/xlsx.d.ts +33 -0
  396. package/dist/reader/parsers/xlsx.d.ts.map +1 -0
  397. package/dist/reader/parsers/xlsx.js +143 -0
  398. package/dist/reader/parsers/xlsx.js.map +1 -0
  399. package/dist/reader/registry.d.ts +39 -0
  400. package/dist/reader/registry.d.ts.map +1 -0
  401. package/dist/reader/registry.js +172 -0
  402. package/dist/reader/registry.js.map +1 -0
  403. package/dist/reader/search.d.ts +27 -0
  404. package/dist/reader/search.d.ts.map +1 -0
  405. package/dist/reader/search.js +77 -0
  406. package/dist/reader/search.js.map +1 -0
  407. package/dist/reader/state.d.ts +56 -0
  408. package/dist/reader/state.d.ts.map +1 -0
  409. package/dist/reader/state.js +179 -0
  410. package/dist/reader/state.js.map +1 -0
  411. package/dist/reader/types.d.ts +119 -0
  412. package/dist/reader/types.d.ts.map +1 -0
  413. package/dist/reader/types.js +23 -0
  414. package/dist/reader/types.js.map +1 -0
  415. package/dist/ship/run.d.ts +26 -0
  416. package/dist/ship/run.d.ts.map +1 -0
  417. package/dist/ship/run.js +123 -0
  418. package/dist/ship/run.js.map +1 -0
  419. package/dist/template/index.d.ts +50 -0
  420. package/dist/template/index.d.ts.map +1 -0
  421. package/dist/template/index.js +140 -0
  422. package/dist/template/index.js.map +1 -0
  423. package/dist/ui/colors.d.ts +13 -0
  424. package/dist/ui/colors.d.ts.map +1 -0
  425. package/dist/ui/colors.js +26 -0
  426. package/dist/ui/colors.js.map +1 -0
  427. package/dist/validate/index.d.ts +19 -0
  428. package/dist/validate/index.d.ts.map +1 -0
  429. package/dist/validate/index.js +181 -0
  430. package/dist/validate/index.js.map +1 -0
  431. package/dist/vault/catalog.d.ts +55 -0
  432. package/dist/vault/catalog.d.ts.map +1 -0
  433. package/dist/vault/catalog.js +424 -0
  434. package/dist/vault/catalog.js.map +1 -0
  435. package/dist/vault/crypto.d.ts +82 -0
  436. package/dist/vault/crypto.d.ts.map +1 -0
  437. package/dist/vault/crypto.js +173 -0
  438. package/dist/vault/crypto.js.map +1 -0
  439. package/dist/vault/git_askpass.d.ts +26 -0
  440. package/dist/vault/git_askpass.d.ts.map +1 -0
  441. package/dist/vault/git_askpass.js +104 -0
  442. package/dist/vault/git_askpass.js.map +1 -0
  443. package/dist/vault/migrator.d.ts +57 -0
  444. package/dist/vault/migrator.d.ts.map +1 -0
  445. package/dist/vault/migrator.js +204 -0
  446. package/dist/vault/migrator.js.map +1 -0
  447. package/dist/vault/redactor.d.ts +73 -0
  448. package/dist/vault/redactor.d.ts.map +1 -0
  449. package/dist/vault/redactor.js +182 -0
  450. package/dist/vault/redactor.js.map +1 -0
  451. package/dist/vault/store.d.ts +132 -0
  452. package/dist/vault/store.d.ts.map +1 -0
  453. package/dist/vault/store.js +335 -0
  454. package/dist/vault/store.js.map +1 -0
  455. package/dist/version.d.ts +8 -0
  456. package/dist/version.d.ts.map +1 -0
  457. package/dist/version.js +8 -0
  458. package/dist/version.js.map +1 -0
  459. package/dist/voice/chunker.d.ts +43 -0
  460. package/dist/voice/chunker.d.ts.map +1 -0
  461. package/dist/voice/chunker.js +133 -0
  462. package/dist/voice/chunker.js.map +1 -0
  463. package/dist/voice/config.d.ts +14 -0
  464. package/dist/voice/config.d.ts.map +1 -0
  465. package/dist/voice/config.js +51 -0
  466. package/dist/voice/config.js.map +1 -0
  467. package/dist/voice/intents.d.ts +71 -0
  468. package/dist/voice/intents.d.ts.map +1 -0
  469. package/dist/voice/intents.js +0 -0
  470. package/dist/voice/intents.js.map +1 -0
  471. package/dist/voice/providers/elevenlabs.d.ts +53 -0
  472. package/dist/voice/providers/elevenlabs.d.ts.map +1 -0
  473. package/dist/voice/providers/elevenlabs.js +159 -0
  474. package/dist/voice/providers/elevenlabs.js.map +1 -0
  475. package/dist/voice/providers/google.d.ts +56 -0
  476. package/dist/voice/providers/google.d.ts.map +1 -0
  477. package/dist/voice/providers/google.js +253 -0
  478. package/dist/voice/providers/google.js.map +1 -0
  479. package/dist/voice/providers/whisper.d.ts +44 -0
  480. package/dist/voice/providers/whisper.d.ts.map +1 -0
  481. package/dist/voice/providers/whisper.js +179 -0
  482. package/dist/voice/providers/whisper.js.map +1 -0
  483. package/dist/voice/registry.d.ts +35 -0
  484. package/dist/voice/registry.d.ts.map +1 -0
  485. package/dist/voice/registry.js +48 -0
  486. package/dist/voice/registry.js.map +1 -0
  487. package/dist/voice/router.d.ts +62 -0
  488. package/dist/voice/router.d.ts.map +1 -0
  489. package/dist/voice/router.js +175 -0
  490. package/dist/voice/router.js.map +1 -0
  491. package/dist/voice/types.d.ts +116 -0
  492. package/dist/voice/types.d.ts.map +1 -0
  493. package/dist/voice/types.js +22 -0
  494. package/dist/voice/types.js.map +1 -0
  495. package/dist/voice/voiceprint/enrollment.d.ts +36 -0
  496. package/dist/voice/voiceprint/enrollment.d.ts.map +1 -0
  497. package/dist/voice/voiceprint/enrollment.js +71 -0
  498. package/dist/voice/voiceprint/enrollment.js.map +1 -0
  499. package/dist/voice/voiceprint/identify.d.ts +16 -0
  500. package/dist/voice/voiceprint/identify.d.ts.map +1 -0
  501. package/dist/voice/voiceprint/identify.js +20 -0
  502. package/dist/voice/voiceprint/identify.js.map +1 -0
  503. package/dist/voice/voiceprint/liveness.d.ts +90 -0
  504. package/dist/voice/voiceprint/liveness.d.ts.map +1 -0
  505. package/dist/voice/voiceprint/liveness.js +251 -0
  506. package/dist/voice/voiceprint/liveness.js.map +1 -0
  507. package/dist/voice/voiceprint/match.d.ts +54 -0
  508. package/dist/voice/voiceprint/match.d.ts.map +1 -0
  509. package/dist/voice/voiceprint/match.js +88 -0
  510. package/dist/voice/voiceprint/match.js.map +1 -0
  511. package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts +44 -0
  512. package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts.map +1 -0
  513. package/dist/voice/voiceprint/providers/local-mfcc-stub.js +92 -0
  514. package/dist/voice/voiceprint/providers/local-mfcc-stub.js.map +1 -0
  515. package/dist/voice/voiceprint/store.d.ts +60 -0
  516. package/dist/voice/voiceprint/store.d.ts.map +1 -0
  517. package/dist/voice/voiceprint/store.js +155 -0
  518. package/dist/voice/voiceprint/store.js.map +1 -0
  519. package/dist/voice/voiceprint/trust.d.ts +90 -0
  520. package/dist/voice/voiceprint/trust.d.ts.map +1 -0
  521. package/dist/voice/voiceprint/trust.js +150 -0
  522. package/dist/voice/voiceprint/trust.js.map +1 -0
  523. package/dist/voice/voiceprint/types.d.ts +100 -0
  524. package/dist/voice/voiceprint/types.d.ts.map +1 -0
  525. package/dist/voice/voiceprint/types.js +23 -0
  526. package/dist/voice/voiceprint/types.js.map +1 -0
  527. package/dist/voice/wake.d.ts +64 -0
  528. package/dist/voice/wake.d.ts.map +1 -0
  529. package/dist/voice/wake.js +143 -0
  530. package/dist/voice/wake.js.map +1 -0
  531. package/docs/manuals/manual.ar.html +91 -0
  532. package/docs/manuals/manual.de.html +100 -0
  533. package/docs/manuals/manual.en.html +118 -0
  534. package/docs/manuals/manual.es.html +120 -0
  535. package/docs/manuals/manual.fr.html +102 -0
  536. package/docs/manuals/manual.hi.html +93 -0
  537. package/docs/manuals/manual.it.html +93 -0
  538. package/docs/manuals/manual.ja.html +97 -0
  539. package/docs/manuals/manual.pt.html +103 -0
  540. package/docs/manuals/manual.zh.html +89 -0
  541. package/package.json +94 -0
  542. package/src/i18n/catalogs/ar.json +86 -0
  543. package/src/i18n/catalogs/de.json +86 -0
  544. package/src/i18n/catalogs/en.json +86 -0
  545. package/src/i18n/catalogs/es.json +86 -0
  546. package/src/i18n/catalogs/fr.json +86 -0
  547. package/src/i18n/catalogs/hi.json +86 -0
  548. package/src/i18n/catalogs/it.json +86 -0
  549. package/src/i18n/catalogs/ja.json +86 -0
  550. package/src/i18n/catalogs/pt.json +86 -0
  551. package/src/i18n/catalogs/zh.json +86 -0
  552. package/templates/react-app/README.md +43 -0
  553. package/templates/react-app/index.html +12 -0
  554. package/templates/react-app/package.json +35 -0
  555. package/templates/react-app/src/App.tsx +106 -0
  556. package/templates/react-app/src/main.tsx +21 -0
  557. package/templates/react-app/src/nac/manifest.ts +46 -0
  558. package/templates/react-app/src/styles.css +68 -0
  559. package/templates/react-app/tsconfig.json +19 -0
  560. package/templates/react-app/vite.config.ts +12 -0
  561. package/templates/react-app/yujin.forge.json +15 -0
@@ -0,0 +1,644 @@
1
+ /**
2
+ * Yujin Forge -- JS-template walker.
3
+ *
4
+ * Many real-world apps render HTML via JS string templates rather
5
+ * than authoring it in static HTML. Common patterns:
6
+ *
7
+ * var html = '<button class="cta save" aria-label="Save invoice '
8
+ * + escapeHtml(inv.id) + '">Save</button>';
9
+ *
10
+ * var html = `<tr data-id="${row.id}">
11
+ * <td>${row.name}</td>
12
+ * <td><button class="del" aria-label="Delete row ${row.id}">Delete</button></td>
13
+ * </tr>`;
14
+ *
15
+ * The HTML walker (html-walker.ts) operates on parsed DOM trees and
16
+ * misses these because the elements only materialise at runtime when
17
+ * the JS executes. This walker scans .js / .ts source as text, finds
18
+ * HTML opening tags inside string literals (single-quote concat OR
19
+ * template literal), classifies each one, identifies the *dynamic
20
+ * id expression* (typically the JS expression that wraps the row's
21
+ * unique identifier and appears inside the aria-label), and rewrites
22
+ * the source by inserting `data-nac-id=` / `data-nac-role=` /
23
+ * `data-nac-action=` attributes -- with the same JS expression
24
+ * woven into the nac_id so each rendered row gets a unique id.
25
+ *
26
+ * The walker is deliberately scoped to recognise patterns we see in
27
+ * production codebases. Patterns we cannot decode (heavily computed
28
+ * tags, dynamic role assignment, JSX in .js without typescript
29
+ * tooling) are flagged low-confidence and reported -- never
30
+ * silently mis-decorated.
31
+ *
32
+ * ASCII-only.
33
+ */
34
+ import { promises as fs } from 'node:fs';
35
+ import path from 'node:path';
36
+ import crypto from 'node:crypto';
37
+ import { inferVerb } from './verb-inference.js';
38
+ import { parse } from 'node-html-parser';
39
+ /** Convert UTF-16 offset to {line, col} (both 1-based). */
40
+ function offsetToLineCol(source, off) {
41
+ let line = 1, col = 1;
42
+ for (let i = 0; i < off && i < source.length; i++) {
43
+ if (source.charCodeAt(i) === 10) {
44
+ line++;
45
+ col = 1;
46
+ }
47
+ else
48
+ col++;
49
+ }
50
+ return { line, col };
51
+ }
52
+ const ELIGIBLE_TAGS = new Set([
53
+ 'button', 'input', 'textarea', 'select', 'a', 'form',
54
+ 'main', 'section', 'aside', 'nav', 'article', 'header', 'footer',
55
+ ]);
56
+ /**
57
+ * Find every <tag ...> opening that appears inside a JS string
58
+ * literal (single, double, or template). Returns the structural
59
+ * extraction with whatever we could parse statically.
60
+ *
61
+ * The matcher is tolerant: it does not require a closing tag in the
62
+ * same string (real templates often split a single element across
63
+ * many concatenations). It looks at the opening tag + the immediate
64
+ * concatenation neighbourhood for the dynamic-id expression.
65
+ */
66
+ export function scanJsTemplates(filePath, source) {
67
+ const candidates = [];
68
+ /* Regex: opening tag inside ANY string-quote context. We find the
69
+ tag via opening `<word` and then capture attributes up to `>`. */
70
+ /* tag: alpha, 1+; attrs: anything up to a closing `>` that is not
71
+ inside a string. We accept multi-line tags (the `s` flag). */
72
+ const tagRe = /<([a-zA-Z][a-zA-Z0-9]*)(\s[^>]*?)?(\/?)\s*>/gs;
73
+ /* JS string literal detector: we want to skip tags that appear in
74
+ code (outside strings) and only consider those inside a quote.
75
+ Heuristic: walk back to the nearest UNCLOSED quote on the same
76
+ enclosed scope. We use a lightweight state machine. */
77
+ const inString = computeStringScopes(source);
78
+ let m;
79
+ while ((m = tagRe.exec(source)) !== null) {
80
+ const offset = m.index;
81
+ const stringScope = inString[offset];
82
+ if (!stringScope)
83
+ continue;
84
+ const tagName = m[1] ?? '';
85
+ if (!tagName)
86
+ continue;
87
+ const tag = tagName.toLowerCase();
88
+ if (!ELIGIBLE_TAGS.has(tag))
89
+ continue;
90
+ const attrsRaw = (m[2] ?? '');
91
+ const openingTagText = m[0];
92
+ /* Skip elements that ALREADY carry data-nac-id literal in the
93
+ attrs region of THIS opening tag. We check the literal text;
94
+ interpolated decoration is rare. */
95
+ const alreadyDecorated = /data-nac-id\s*=/.test(attrsRaw);
96
+ /* Skip <a> without onclick / role=button -- bare navigation. */
97
+ if (tag === 'a' && !/onclick=|role\s*=\s*['"]button['"]/.test(attrsRaw))
98
+ continue;
99
+ /* Skip <input type="hidden"> */
100
+ if (tag === 'input' && /type\s*=\s*['"]hidden['"]/.test(attrsRaw))
101
+ continue;
102
+ const role = classifyRole(tag, attrsRaw);
103
+ const ariaStatic = extractStaticAriaLabel(attrsRaw);
104
+ const textStatic = extractStaticText(source, offset, openingTagText, m[3] === '/');
105
+ const verb = inferVerbFromAttrs(role, tag, ariaStatic, textStatic, attrsRaw);
106
+ const dynamicIdExpr = detectDynamicIdExpr(source, offset, openingTagText);
107
+ const plugin = derivePluginSlug(filePath, source, offset);
108
+ const proposedId = buildProposedIdTemplate(plugin, role, verb, tag, dynamicIdExpr, ariaStatic, textStatic);
109
+ const conf = computeConfidence({
110
+ role, verb, ariaStatic, textStatic, dynamicIdExpr,
111
+ });
112
+ const { line } = offsetToLineCol(source, offset);
113
+ const fp = computeFingerprint(filePath, tag, role, ariaStatic, textStatic, dynamicIdExpr);
114
+ candidates.push({
115
+ fingerprint: fp,
116
+ filePath,
117
+ offset,
118
+ line,
119
+ tag,
120
+ static_attrs: attrsRaw,
121
+ dynamic_id_expr: dynamicIdExpr,
122
+ role,
123
+ verb,
124
+ already_decorated: alreadyDecorated,
125
+ plugin,
126
+ proposed_id_template: proposedId,
127
+ confidence: conf,
128
+ text_static: textStatic,
129
+ aria_label_static: ariaStatic,
130
+ opening_tag_text: openingTagText,
131
+ });
132
+ }
133
+ return { filePath, candidates };
134
+ }
135
+ /* ----------------------------------------------------------------
136
+ JS string-scope detection.
137
+
138
+ We classify every character offset as "inside a string?" yes/no.
139
+ The marker is conservative: we only flag clear string regions
140
+ (single / double / backtick quoted) and treat anything we are
141
+ unsure about as NOT a string. The tradeoff is occasional missed
142
+ decoration vs accidentally rewriting non-string code; we always
143
+ prefer the safe side.
144
+
145
+ Caveat: template literals can contain ${expr} which is JS code.
146
+ We treat the entire template literal as a string scope for the
147
+ purpose of "is this a string?" -- the resulting HTML attr
148
+ injection inside a ${} would be syntactically wrong, but in
149
+ practice template literals carry the entire HTML in the literal
150
+ region, not in ${}.
151
+ ---------------------------------------------------------------- */
152
+ function computeStringScopes(source) {
153
+ const len = source.length;
154
+ const inStr = new Uint8Array(len);
155
+ /* Track the last non-whitespace, non-comment token to disambiguate
156
+ `/` as division vs regex literal. After certain tokens (= ( , [
157
+ { ; ! & | ? : return etc.) a `/` starts a regex; after others
158
+ (identifier, ) ] number, etc.) it's division. */
159
+ let lastSignificant = '';
160
+ const regexPreceders = new Set([
161
+ '', '=', '(', ',', '[', '{', ';', '!', '&', '|', '?', ':', '+',
162
+ '-', '*', '/', '%', '<', '>', '~', '^',
163
+ 'return', 'typeof', 'delete', 'void', 'in', 'of', 'new', 'throw',
164
+ 'instanceof', 'yield', 'await', 'else', 'do', 'case',
165
+ ]);
166
+ let i = 0;
167
+ while (i < len) {
168
+ const c = source.charCodeAt(i);
169
+ /* Skip single-line comments */
170
+ if (c === 47 /* / */ && i + 1 < len && source.charCodeAt(i + 1) === 47) {
171
+ while (i < len && source.charCodeAt(i) !== 10)
172
+ i++;
173
+ continue;
174
+ }
175
+ /* Skip block comments */
176
+ if (c === 47 && i + 1 < len && source.charCodeAt(i + 1) === 42) {
177
+ i += 2;
178
+ while (i < len - 1 && !(source.charCodeAt(i) === 42 && source.charCodeAt(i + 1) === 47))
179
+ i++;
180
+ i += 2;
181
+ continue;
182
+ }
183
+ /* Regex literal? `/` not part of `//` or `/*` -- already
184
+ handled above. Disambiguate by the last significant token. */
185
+ if (c === 47 && regexPreceders.has(lastSignificant)) {
186
+ /* Walk forward until the closing `/` (not in a char class,
187
+ not escaped). */
188
+ i++;
189
+ let inClass = false;
190
+ while (i < len) {
191
+ const cc = source.charCodeAt(i);
192
+ if (cc === 92 /* \ */) {
193
+ i += 2;
194
+ continue;
195
+ }
196
+ if (cc === 91 /* [ */) {
197
+ inClass = true;
198
+ i++;
199
+ continue;
200
+ }
201
+ if (cc === 93 /* ] */) {
202
+ inClass = false;
203
+ i++;
204
+ continue;
205
+ }
206
+ if (cc === 47 && !inClass) {
207
+ i++;
208
+ break;
209
+ }
210
+ if (cc === 10 /* newline */)
211
+ break; /* regex can't span lines */
212
+ i++;
213
+ }
214
+ /* Optional flags */
215
+ while (i < len && /[gimsuy]/.test(source[i] || ''))
216
+ i++;
217
+ lastSignificant = '/regex/';
218
+ continue;
219
+ }
220
+ /* String quote? */
221
+ if (c === 34 /* " */ || c === 39 /* ' */ || c === 96 /* ` */) {
222
+ const quote = c;
223
+ const start = i;
224
+ i++;
225
+ while (i < len) {
226
+ const cc = source.charCodeAt(i);
227
+ if (cc === 92 /* \ */) {
228
+ i += 2;
229
+ continue;
230
+ }
231
+ if (cc === quote) {
232
+ i++;
233
+ break;
234
+ }
235
+ if (quote === 96 && cc === 36 /* $ */ && i + 1 < len && source.charCodeAt(i + 1) === 123 /* { */) {
236
+ let depth = 1;
237
+ i += 2;
238
+ while (i < len && depth > 0) {
239
+ const cd = source.charCodeAt(i);
240
+ if (cd === 123)
241
+ depth++;
242
+ else if (cd === 125)
243
+ depth--;
244
+ i++;
245
+ }
246
+ continue;
247
+ }
248
+ i++;
249
+ }
250
+ for (let k = start; k < i; k++)
251
+ inStr[k] = 1;
252
+ lastSignificant = 'string';
253
+ continue;
254
+ }
255
+ /* Track the last significant token for regex disambiguation.
256
+ Whitespace + newlines do NOT reset it. */
257
+ if (c > 32) {
258
+ /* Identifier or keyword? Walk to capture full word. */
259
+ if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 95 || c === 36) {
260
+ let j = i;
261
+ while (j < len) {
262
+ const cj = source.charCodeAt(j);
263
+ if ((cj >= 65 && cj <= 90) || (cj >= 97 && cj <= 122) ||
264
+ (cj >= 48 && cj <= 57) || cj === 95 || cj === 36)
265
+ j++;
266
+ else
267
+ break;
268
+ }
269
+ lastSignificant = source.slice(i, j);
270
+ i = j;
271
+ continue;
272
+ }
273
+ /* Number? */
274
+ if (c >= 48 && c <= 57) {
275
+ while (i < len) {
276
+ const ci = source.charCodeAt(i);
277
+ if ((ci >= 48 && ci <= 57) || ci === 46)
278
+ i++;
279
+ else
280
+ break;
281
+ }
282
+ lastSignificant = '0';
283
+ continue;
284
+ }
285
+ /* Punctuation: record the single char. */
286
+ lastSignificant = source[i] || '';
287
+ }
288
+ i++;
289
+ }
290
+ return inStr;
291
+ }
292
+ /* ---- classification + inference helpers ---- */
293
+ function classifyRole(tag, attrsRaw) {
294
+ if (tag === 'input' || tag === 'textarea' || tag === 'select')
295
+ return 'field';
296
+ if (['main', 'section', 'aside', 'nav', 'article', 'header', 'footer', 'form'].includes(tag))
297
+ return 'region';
298
+ const role = /(?:^|\s)role\s*=\s*["']([^"']+)["']/.exec(attrsRaw)?.[1]?.toLowerCase();
299
+ if (role === 'tab')
300
+ return 'tab';
301
+ if (role === 'option')
302
+ return 'option';
303
+ return 'action';
304
+ }
305
+ function extractStaticAriaLabel(attrsRaw) {
306
+ /* Grab the aria-label value as a literal string up to the first
307
+ interpolation marker. We accept aria-label="..." and
308
+ aria-label='...'. */
309
+ const m = /aria-label\s*=\s*(["'])((?:\\.|(?!\1).)*)\1/.exec(attrsRaw);
310
+ if (!m || typeof m[2] !== 'string')
311
+ return null;
312
+ return m[2].trim() || null;
313
+ }
314
+ function extractStaticText(source, openTagOffset, openingTagText, isSelfClosing) {
315
+ if (isSelfClosing)
316
+ return null;
317
+ /* Find the matching `</tag>` in the rest of the source. We only
318
+ pull the LITERAL text between the open + close tags if the
319
+ close tag exists in the same string scope and no interpolation
320
+ splits the inner. This is best-effort. */
321
+ const tagMatch = /^<([a-zA-Z][a-zA-Z0-9]*)/.exec(openingTagText);
322
+ if (!tagMatch || !tagMatch[1])
323
+ return null;
324
+ const tag = tagMatch[1].toLowerCase();
325
+ const start = openTagOffset + openingTagText.length;
326
+ const closeRe = new RegExp('</' + tag + '\\s*>', 'gi');
327
+ closeRe.lastIndex = start;
328
+ const cm = closeRe.exec(source);
329
+ if (!cm)
330
+ return null;
331
+ const innerRaw = source.slice(start, cm.index);
332
+ /* If inner has unbalanced quotes or string-boundary chars + JS
333
+ concatenation operators, bail. */
334
+ if (/['"`]\s*\+|\+\s*['"`]/.test(innerRaw)) {
335
+ /* Has concatenation -- the text is dynamic. Extract the
336
+ leading literal portion only. */
337
+ const leading = innerRaw.split(/['"`]\s*\+/)[0] ?? '';
338
+ return leading.replace(/[<>]/g, '').trim().slice(0, 80) || null;
339
+ }
340
+ return innerRaw.replace(/[<>]/g, '').trim().slice(0, 80) || null;
341
+ }
342
+ function inferVerbFromAttrs(role, tag, aria, text, attrsRaw) {
343
+ if (role !== 'action' && role !== 'tab')
344
+ return null;
345
+ /* Build a minimal DOM stub so we can reuse the same L1-L5
346
+ classifier the HTML walker uses. */
347
+ const stub = parse('<' + tag + ' '
348
+ + (attrsRaw.replace(/\$\{[^}]*\}/g, '*').replace(/['"]\s*\+\s*[^+]*\+\s*['"]/g, '*'))
349
+ + '>' + (text ?? aria ?? '') + '</' + tag + '>');
350
+ const el = stub.firstChild;
351
+ if (!el)
352
+ return null;
353
+ const hit = inferVerb(el);
354
+ return hit?.verb ?? null;
355
+ }
356
+ function detectDynamicIdExpr(source, openTagOffset, openingTagText) {
357
+ /* Layered detection. Each layer scans the opening tag (+ a bit
358
+ of slack) for an interpolation pattern. First hit wins.
359
+ Layers in priority order:
360
+ L1 aria-label="...${EXPR}..." (strongest signal)
361
+ L2 data-*-id / data-*-key="...EXPR..."
362
+ L3 id="...EXPR..."
363
+ L4 most-frequent expression in opening tag (fallback) */
364
+ /* L1: aria-label interpolation */
365
+ const fromAria = extractInterpolationInAttr(source, openTagOffset, openingTagText, /aria-label/);
366
+ if (fromAria)
367
+ return fromAria;
368
+ /* L2: data-*-id / data-key / data-row-id / etc. */
369
+ const fromDataId = extractInterpolationInAttr(source, openTagOffset, openingTagText, /data-([a-z0-9_-]*)(id|key|row-id|item-id|line-id|invoice-id|order-id|user-id)/i);
370
+ if (fromDataId)
371
+ return fromDataId;
372
+ /* L3: id="...EXPR..." */
373
+ const fromId = extractInterpolationInAttr(source, openTagOffset, openingTagText, /\bid\b/);
374
+ if (fromId)
375
+ return fromId;
376
+ /* L4: most-frequent JS interpolation in the opening tag.
377
+ If the row identity isn't tagged in any attr, we look at every
378
+ `'..' + EXPR + '..'` chunk inside the opening tag and pick the
379
+ EXPR that appears most often. Tied counts break in favour of
380
+ the shortest expression (heuristic: `inv.id` beats
381
+ `escapeHtml(inv.client_name)`).
382
+
383
+ CRITICAL: window stays WITHIN the opening tag. Going past the
384
+ `>` includes interpolations from sibling tags and ends up
385
+ picking the wrong dynamic id. */
386
+ const exprs = collectInterpolations(openingTagText);
387
+ if (exprs.length > 0) {
388
+ const counts = new Map();
389
+ for (const e of exprs)
390
+ counts.set(e, (counts.get(e) || 0) + 1);
391
+ const ranked = [...counts.entries()].sort((a, b) => {
392
+ if (b[1] !== a[1])
393
+ return b[1] - a[1];
394
+ return a[0].length - b[0].length;
395
+ });
396
+ const winner = ranked[0];
397
+ if (winner && winner[1] >= 1)
398
+ return winner[0];
399
+ }
400
+ return null;
401
+ }
402
+ /**
403
+ * Find the first JS expression interpolated inside the value of the
404
+ * first attribute whose name matches `attrPattern`. Returns null if
405
+ * the attribute is absent or has no interpolation.
406
+ *
407
+ * The interpolation can be either string-concat (`'..' + EXPR + '..'`
408
+ * OR `".." + EXPR + ".."`, possibly with mismatched HTML/JS quotes)
409
+ * or template-literal (`${EXPR}`).
410
+ *
411
+ * Critical detail: the HTML attribute quote and the JS-string quote
412
+ * may differ. Common case: JS string uses `'` (single) and HTML
413
+ * attribute uses `"` (double). The detector must not assume they
414
+ * match.
415
+ */
416
+ function extractInterpolationInAttr(source, openTagOffset, openingTagText, attrPattern) {
417
+ const re = new RegExp(`(${attrPattern.source})\\s*=\\s*['"]`, attrPattern.flags || 'i');
418
+ const m = re.exec(openingTagText);
419
+ if (!m)
420
+ return null;
421
+ const attrStartRel = m.index;
422
+ const valStartRel = attrStartRel + m[0].length - 1; /* index of the opening HTML-attr quote */
423
+ const htmlQuote = openingTagText[valStartRel] || '"';
424
+ /* Find the matching closing HTML-attr quote in openingTagText.
425
+ We do NOT respect JS-string boundaries here -- we just look
426
+ for the next char === htmlQuote that is not preceded by `\`. */
427
+ let valEndRel = valStartRel + 1;
428
+ while (valEndRel < openingTagText.length) {
429
+ const ch = openingTagText[valEndRel];
430
+ if (ch === htmlQuote && openingTagText[valEndRel - 1] !== '\\')
431
+ break;
432
+ valEndRel++;
433
+ }
434
+ if (valEndRel >= openingTagText.length)
435
+ return null;
436
+ /* The attribute value region spans [valStartRel+1, valEndRel)
437
+ in openingTagText. Within this region, look for any concat
438
+ or template interpolation. */
439
+ const valRegion = openingTagText.slice(valStartRel + 1, valEndRel);
440
+ /* concat interpolation: '<quote> + EXPR + <quote>' where
441
+ <quote> is either ' or ". The JS string could have been
442
+ opened with EITHER. We accept either inside the value. */
443
+ const concatRe = /(['"`])\s*\+\s*([^+]+?)\s*\+\s*\1/;
444
+ const cm = concatRe.exec(valRegion);
445
+ if (cm && cm[2])
446
+ return cm[2].trim();
447
+ /* template literal interpolation */
448
+ const tplRe = /\$\{([^}]+)\}/;
449
+ const tm = tplRe.exec(valRegion);
450
+ if (tm && tm[1])
451
+ return tm[1].trim();
452
+ return null;
453
+ }
454
+ /**
455
+ * Collect every JS expression that appears as an interpolation
456
+ * (either `' + EXPR + '` style concat OR `${EXPR}` template) within
457
+ * the given source slice. Used by the L4 fallback heuristic to
458
+ * pick the row identity by frequency.
459
+ */
460
+ function collectInterpolations(slice) {
461
+ const out = [];
462
+ /* concat pattern */
463
+ const concatRe = /['"]\s*\+\s*([^+'"]+?)\s*\+\s*['"]/g;
464
+ let cm;
465
+ while ((cm = concatRe.exec(slice)) !== null) {
466
+ const e = (cm[1] ?? '').trim();
467
+ if (e && e.length < 100)
468
+ out.push(e);
469
+ }
470
+ /* template literal pattern */
471
+ const tplRe = /\$\{([^}]+)\}/g;
472
+ let tm;
473
+ while ((tm = tplRe.exec(slice)) !== null) {
474
+ const e = (tm[1] ?? '').trim();
475
+ if (e && e.length < 100)
476
+ out.push(e);
477
+ }
478
+ return out;
479
+ }
480
+ function derivePluginSlug(filePath, source, openTagOffset) {
481
+ /* Look backward for a function name + try to derive a slug from
482
+ it OR from filename. */
483
+ const fnRe = /function\s+(render[A-Z][a-zA-Z0-9_]*)\s*\(/g;
484
+ let lastFn = null;
485
+ let fm;
486
+ while ((fm = fnRe.exec(source)) !== null) {
487
+ if (fm.index >= openTagOffset)
488
+ break;
489
+ lastFn = fm[1] ?? null;
490
+ }
491
+ if (lastFn) {
492
+ const slug = lastFn
493
+ .replace(/^render/, '')
494
+ .replace(/([A-Z])/g, '_$1')
495
+ .toLowerCase()
496
+ .replace(/^_+/, '');
497
+ if (slug)
498
+ return slug;
499
+ }
500
+ return path.basename(filePath)
501
+ .replace(/\.(js|jsx|ts|tsx|mjs)$/, '')
502
+ .toLowerCase()
503
+ .replace(/[^a-z0-9_]+/g, '_')
504
+ .replace(/^_+|_+$/g, '') || 'page';
505
+ }
506
+ function buildProposedIdTemplate(plugin, role, verb, tag, dynamicIdExpr, aria, text) {
507
+ const stem = (aria ?? text ?? verb ?? tag)
508
+ .toLowerCase()
509
+ .replace(/[^a-z0-9]+/g, '_')
510
+ .replace(/^_+|_+$/g, '')
511
+ .slice(0, 24);
512
+ const base = plugin + '.' + role + '_' + (verb ?? tag);
513
+ if (dynamicIdExpr) {
514
+ /* Encode the dynamic id as a template marker {{EXPR}}. The
515
+ rewriter weaves it back into the source as a real JS concat. */
516
+ return base + '.{{' + dynamicIdExpr + '}}';
517
+ }
518
+ if (stem && stem !== (verb ?? tag))
519
+ return base + '.' + stem;
520
+ return base;
521
+ }
522
+ function computeConfidence(args) {
523
+ let conf = 0.4; // base
524
+ if (args.role === 'field' || args.role === 'region')
525
+ conf += 0.35;
526
+ if (args.verb)
527
+ conf += 0.25;
528
+ if (args.ariaStatic)
529
+ conf += 0.15;
530
+ if (args.dynamicIdExpr)
531
+ conf += 0.10; // unique-per-row
532
+ return Math.min(1, conf);
533
+ }
534
+ function computeFingerprint(filePath, tag, role, aria, text, dynamicIdExpr) {
535
+ const seed = JSON.stringify({
536
+ file: filePath, tag, role,
537
+ aria: (aria ?? '').slice(0, 60),
538
+ text: (text ?? '').slice(0, 60),
539
+ dyn: dynamicIdExpr ?? '',
540
+ });
541
+ return crypto.createHash('sha256').update(seed).digest('hex').slice(0, 16);
542
+ }
543
+ /**
544
+ * Rewrite a JS source string by injecting NAC attrs into the
545
+ * opening tags identified by `decisions`. Decisions must reference
546
+ * the SAME source you read (offsets are absolute).
547
+ *
548
+ * For dynamic id templates of the form "<base>.{{EXPR}}", the
549
+ * inserted attrs use JS string-concatenation that weaves EXPR back
550
+ * into the rendered HTML:
551
+ *
552
+ * ' data-nac-id="<base>.' + escapeHtml(EXPR) + '" '
553
+ *
554
+ * (We use escapeHtml when the source defines such a helper; we
555
+ * fall back to inline `String(...)` otherwise. The detection runs
556
+ * once per file.)
557
+ */
558
+ export function applyJsDecisions(source, decisions) {
559
+ if (decisions.length === 0)
560
+ return source;
561
+ /* Determine helper name */
562
+ const hasEscapeHtml = /\bfunction\s+escapeHtml\b|escapeHtml\s*=/.test(source);
563
+ const escape = hasEscapeHtml ? 'escapeHtml' : 'String';
564
+ /* Sort decisions DESC by offset so earlier injections do not
565
+ shift later positions. */
566
+ const sorted = [...decisions].sort((a, b) => b.offset - a.offset);
567
+ let out = source;
568
+ for (const d of sorted) {
569
+ const opening = out.slice(d.offset, d.offset + d.opening_tag_text.length);
570
+ if (opening !== d.opening_tag_text) {
571
+ /* The source has changed under us -- skip this decision. */
572
+ continue;
573
+ }
574
+ /* The opening text ends with `>` (or `/>`). Insert before that. */
575
+ const last = opening.lastIndexOf('>');
576
+ const isSelfClose = opening[last - 1] === '/';
577
+ const insertAt = d.offset + (isSelfClose ? last - 1 : last);
578
+ /* Compose the attr injection. */
579
+ const inj = composeAttrInjection(d, escape);
580
+ out = out.slice(0, insertAt) + inj + out.slice(insertAt);
581
+ }
582
+ return out;
583
+ }
584
+ function composeAttrInjection(d, escape) {
585
+ /* Detect the JS-string kind of the surrounding context by
586
+ inspecting the opening_tag_text. */
587
+ const inConcatString = /['"]\s*\+\s*[^+]+\+\s*['"]/.test(d.opening_tag_text);
588
+ const inTemplateString = /\$\{[^}]+\}/.test(d.opening_tag_text);
589
+ const idTemplate = d.nac_id_template;
590
+ const m = /^(.+?)\.\{\{(.+)\}\}$/.exec(idTemplate);
591
+ if (m) {
592
+ const base = m[1] ?? '';
593
+ const expr = m[2] ?? '';
594
+ /* If the expression already includes a function call (looks like
595
+ `escapeHtml(...)`, `String(...)`, `Number(...)`, etc.), do NOT
596
+ wrap again -- double-wrapping produces nonsense like
597
+ `escapeHtml(escapeHtml(x))`. We detect a leading identifier
598
+ followed by `(`. */
599
+ const exprIsCall = /^[A-Za-z_$][\w$]*\s*\(/.test(expr);
600
+ const safeExpr = exprIsCall ? expr : `${escape}(${expr})`;
601
+ if (inTemplateString || (!inConcatString && /`/.test(d.opening_tag_text))) {
602
+ /* Template literal form: ` data-nac-id="<base>.${EXPR}" data-nac-role="<role>"...` */
603
+ let inj = ` data-nac-id="${base}.\${${expr}}" data-nac-role="${d.role}"`;
604
+ if (d.verb)
605
+ inj += ` data-nac-action="${d.verb}"`;
606
+ return inj;
607
+ }
608
+ /* Default: single-quote string concat. Detect the surrounding
609
+ JS-quote (the JS-string this opening tag lives in) by
610
+ inspecting how the existing string is composed. We use `'`
611
+ by default since invoice-app + most jQuery-era code uses
612
+ single-quoted JS strings. */
613
+ let inj = ' data-nac-id="' + base + '.\' + ' + safeExpr + ' + \'" data-nac-role="' + d.role + '"';
614
+ if (d.verb)
615
+ inj += ' data-nac-action="' + d.verb + '"';
616
+ return inj;
617
+ }
618
+ /* Static id */
619
+ if (inTemplateString) {
620
+ let inj = ` data-nac-id="${idTemplate}" data-nac-role="${d.role}"`;
621
+ if (d.verb)
622
+ inj += ` data-nac-action="${d.verb}"`;
623
+ return inj;
624
+ }
625
+ let inj = ' data-nac-id="' + idTemplate + '" data-nac-role="' + d.role + '"';
626
+ if (d.verb)
627
+ inj += ' data-nac-action="' + d.verb + '"';
628
+ return inj;
629
+ }
630
+ /* ---- File-level helpers ---- */
631
+ export async function scanJsFile(filePath) {
632
+ const source = await fs.readFile(filePath, 'utf-8');
633
+ return scanJsTemplates(filePath, source);
634
+ }
635
+ export async function applyJsDecisionsToFile(filePath, decisions, options = {}) {
636
+ const source = await fs.readFile(filePath, 'utf-8');
637
+ const out = applyJsDecisions(source, decisions);
638
+ if (!options.dryRun && out !== source) {
639
+ await fs.writeFile(filePath, out, 'utf-8');
640
+ return { source: out, wrote: true };
641
+ }
642
+ return { source: out, wrote: false };
643
+ }
644
+ //# sourceMappingURL=js-template-walker.js.map