aws-iam-ls 0.0.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 (522) hide show
  1. package/.direnv/bin/nix-direnv-reload +19 -0
  2. package/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc +2156 -0
  3. package/.github/workflows/publish.yml +37 -0
  4. package/.github/workflows/test.yml +16 -0
  5. package/.vscodeignore +17 -0
  6. package/LICENSE +21 -0
  7. package/package.json +53 -0
  8. package/readme.md +25 -0
  9. package/src/data/condition-keys/global.json +362 -0
  10. package/src/data/servicereference/actions.json +1 -0
  11. package/src/data/servicereference/service-principals.json +1 -0
  12. package/src/data/servicereference/services/a2c.json +1 -0
  13. package/src/data/servicereference/services/a4b.json +1 -0
  14. package/src/data/servicereference/services/access-analyzer.json +1 -0
  15. package/src/data/servicereference/services/account.json +1 -0
  16. package/src/data/servicereference/services/acm-pca.json +1 -0
  17. package/src/data/servicereference/services/acm.json +1 -0
  18. package/src/data/servicereference/services/aco-automation.json +1 -0
  19. package/src/data/servicereference/services/action-recommendations.json +1 -0
  20. package/src/data/servicereference/services/activate.json +1 -0
  21. package/src/data/servicereference/services/aidevops.json +1 -0
  22. package/src/data/servicereference/services/aiops.json +1 -0
  23. package/src/data/servicereference/services/airflow-serverless.json +1 -0
  24. package/src/data/servicereference/services/airflow.json +1 -0
  25. package/src/data/servicereference/services/amplify.json +1 -0
  26. package/src/data/servicereference/services/amplifybackend.json +1 -0
  27. package/src/data/servicereference/services/amplifyuibuilder.json +1 -0
  28. package/src/data/servicereference/services/aoss.json +1 -0
  29. package/src/data/servicereference/services/apigateway.json +1 -0
  30. package/src/data/servicereference/services/app-integrations.json +1 -0
  31. package/src/data/servicereference/services/appconfig.json +1 -0
  32. package/src/data/servicereference/services/appfabric.json +1 -0
  33. package/src/data/servicereference/services/appflow.json +1 -0
  34. package/src/data/servicereference/services/application-autoscaling.json +1 -0
  35. package/src/data/servicereference/services/application-signals.json +1 -0
  36. package/src/data/servicereference/services/application-transformation.json +1 -0
  37. package/src/data/servicereference/services/applicationinsights.json +1 -0
  38. package/src/data/servicereference/services/appmesh-preview.json +1 -0
  39. package/src/data/servicereference/services/appmesh.json +1 -0
  40. package/src/data/servicereference/services/apprunner.json +1 -0
  41. package/src/data/servicereference/services/appstream.json +1 -0
  42. package/src/data/servicereference/services/appstudio.json +1 -0
  43. package/src/data/servicereference/services/appsync.json +1 -0
  44. package/src/data/servicereference/services/apptest.json +1 -0
  45. package/src/data/servicereference/services/aps.json +1 -0
  46. package/src/data/servicereference/services/arc-region-switch.json +1 -0
  47. package/src/data/servicereference/services/arc-zonal-shift.json +1 -0
  48. package/src/data/servicereference/services/arsenal.json +1 -0
  49. package/src/data/servicereference/services/artifact.json +1 -0
  50. package/src/data/servicereference/services/athena.json +1 -0
  51. package/src/data/servicereference/services/auditmanager.json +1 -0
  52. package/src/data/servicereference/services/autoscaling-plans.json +1 -0
  53. package/src/data/servicereference/services/autoscaling.json +1 -0
  54. package/src/data/servicereference/services/aws-marketplace-management.json +1 -0
  55. package/src/data/servicereference/services/aws-marketplace.json +1 -0
  56. package/src/data/servicereference/services/aws-mcp.json +1 -0
  57. package/src/data/servicereference/services/aws-portal.json +1 -0
  58. package/src/data/servicereference/services/awsconnector.json +1 -0
  59. package/src/data/servicereference/services/b2bi.json +1 -0
  60. package/src/data/servicereference/services/backup-gateway.json +1 -0
  61. package/src/data/servicereference/services/backup-search.json +1 -0
  62. package/src/data/servicereference/services/backup-storage.json +1 -0
  63. package/src/data/servicereference/services/backup.json +1 -0
  64. package/src/data/servicereference/services/batch.json +1 -0
  65. package/src/data/servicereference/services/bcm-dashboards.json +1 -0
  66. package/src/data/servicereference/services/bcm-data-exports.json +1 -0
  67. package/src/data/servicereference/services/bcm-pricing-calculator.json +1 -0
  68. package/src/data/servicereference/services/bcm-recommended-actions.json +1 -0
  69. package/src/data/servicereference/services/bedrock-agentcore.json +1 -0
  70. package/src/data/servicereference/services/bedrock-mantle.json +1 -0
  71. package/src/data/servicereference/services/bedrock.json +1 -0
  72. package/src/data/servicereference/services/billing.json +1 -0
  73. package/src/data/servicereference/services/billingconductor.json +1 -0
  74. package/src/data/servicereference/services/braket.json +1 -0
  75. package/src/data/servicereference/services/budgets.json +1 -0
  76. package/src/data/servicereference/services/bugbust.json +1 -0
  77. package/src/data/servicereference/services/cases.json +1 -0
  78. package/src/data/servicereference/services/cassandra.json +1 -0
  79. package/src/data/servicereference/services/ce.json +1 -0
  80. package/src/data/servicereference/services/chatbot.json +1 -0
  81. package/src/data/servicereference/services/chime.json +1 -0
  82. package/src/data/servicereference/services/cleanrooms-ml.json +1 -0
  83. package/src/data/servicereference/services/cleanrooms.json +1 -0
  84. package/src/data/servicereference/services/cloud9.json +1 -0
  85. package/src/data/servicereference/services/clouddirectory.json +1 -0
  86. package/src/data/servicereference/services/cloudformation.json +1 -0
  87. package/src/data/servicereference/services/cloudfront-keyvaluestore.json +1 -0
  88. package/src/data/servicereference/services/cloudfront.json +1 -0
  89. package/src/data/servicereference/services/cloudhsm.json +1 -0
  90. package/src/data/servicereference/services/cloudsearch.json +1 -0
  91. package/src/data/servicereference/services/cloudshell.json +1 -0
  92. package/src/data/servicereference/services/cloudtrail-data.json +1 -0
  93. package/src/data/servicereference/services/cloudtrail.json +1 -0
  94. package/src/data/servicereference/services/cloudwatch.json +1 -0
  95. package/src/data/servicereference/services/codeartifact.json +1 -0
  96. package/src/data/servicereference/services/codebuild.json +1 -0
  97. package/src/data/servicereference/services/codecatalyst.json +1 -0
  98. package/src/data/servicereference/services/codecommit.json +1 -0
  99. package/src/data/servicereference/services/codeconnections.json +1 -0
  100. package/src/data/servicereference/services/codedeploy-commands-secure.json +1 -0
  101. package/src/data/servicereference/services/codedeploy.json +1 -0
  102. package/src/data/servicereference/services/codeguru-profiler.json +1 -0
  103. package/src/data/servicereference/services/codeguru-reviewer.json +1 -0
  104. package/src/data/servicereference/services/codeguru-security.json +1 -0
  105. package/src/data/servicereference/services/codeguru.json +1 -0
  106. package/src/data/servicereference/services/codepipeline.json +1 -0
  107. package/src/data/servicereference/services/codestar-connections.json +1 -0
  108. package/src/data/servicereference/services/codestar-notifications.json +1 -0
  109. package/src/data/servicereference/services/codestar.json +1 -0
  110. package/src/data/servicereference/services/codewhisperer.json +1 -0
  111. package/src/data/servicereference/services/cognito-identity.json +1 -0
  112. package/src/data/servicereference/services/cognito-idp.json +1 -0
  113. package/src/data/servicereference/services/cognito-sync.json +1 -0
  114. package/src/data/servicereference/services/comprehend.json +1 -0
  115. package/src/data/servicereference/services/comprehendmedical.json +1 -0
  116. package/src/data/servicereference/services/compute-optimizer.json +1 -0
  117. package/src/data/servicereference/services/config.json +1 -0
  118. package/src/data/servicereference/services/connect-campaigns.json +1 -0
  119. package/src/data/servicereference/services/connect.json +1 -0
  120. package/src/data/servicereference/services/consoleapp.json +1 -0
  121. package/src/data/servicereference/services/consolidatedbilling.json +1 -0
  122. package/src/data/servicereference/services/controlcatalog.json +1 -0
  123. package/src/data/servicereference/services/controltower.json +1 -0
  124. package/src/data/servicereference/services/cost-optimization-hub.json +1 -0
  125. package/src/data/servicereference/services/cur.json +1 -0
  126. package/src/data/servicereference/services/customer-verification.json +1 -0
  127. package/src/data/servicereference/services/databrew.json +1 -0
  128. package/src/data/servicereference/services/dataexchange.json +1 -0
  129. package/src/data/servicereference/services/datapipeline.json +1 -0
  130. package/src/data/servicereference/services/datasync.json +1 -0
  131. package/src/data/servicereference/services/datazone.json +1 -0
  132. package/src/data/servicereference/services/dax.json +1 -0
  133. package/src/data/servicereference/services/dbqms.json +1 -0
  134. package/src/data/servicereference/services/deadline.json +1 -0
  135. package/src/data/servicereference/services/detective.json +1 -0
  136. package/src/data/servicereference/services/devicefarm.json +1 -0
  137. package/src/data/servicereference/services/devops-guru.json +1 -0
  138. package/src/data/servicereference/services/directconnect.json +1 -0
  139. package/src/data/servicereference/services/discovery.json +1 -0
  140. package/src/data/servicereference/services/dlm.json +1 -0
  141. package/src/data/servicereference/services/dms.json +1 -0
  142. package/src/data/servicereference/services/docdb-elastic.json +1 -0
  143. package/src/data/servicereference/services/drs.json +1 -0
  144. package/src/data/servicereference/services/ds-data.json +1 -0
  145. package/src/data/servicereference/services/ds.json +1 -0
  146. package/src/data/servicereference/services/dsql.json +1 -0
  147. package/src/data/servicereference/services/dynamodb.json +1 -0
  148. package/src/data/servicereference/services/ebs.json +1 -0
  149. package/src/data/servicereference/services/ec2-instance-connect.json +1 -0
  150. package/src/data/servicereference/services/ec2.json +1 -0
  151. package/src/data/servicereference/services/ec2messages.json +1 -0
  152. package/src/data/servicereference/services/ecr-public.json +1 -0
  153. package/src/data/servicereference/services/ecr.json +1 -0
  154. package/src/data/servicereference/services/ecs-mcp.json +1 -0
  155. package/src/data/servicereference/services/ecs.json +1 -0
  156. package/src/data/servicereference/services/eks-auth.json +1 -0
  157. package/src/data/servicereference/services/eks-mcp.json +1 -0
  158. package/src/data/servicereference/services/eks.json +1 -0
  159. package/src/data/servicereference/services/elasticache.json +1 -0
  160. package/src/data/servicereference/services/elasticbeanstalk.json +1 -0
  161. package/src/data/servicereference/services/elasticfilesystem.json +1 -0
  162. package/src/data/servicereference/services/elasticloadbalancing.json +1 -0
  163. package/src/data/servicereference/services/elasticmapreduce.json +1 -0
  164. package/src/data/servicereference/services/elastictranscoder.json +1 -0
  165. package/src/data/servicereference/services/elemental-activations.json +1 -0
  166. package/src/data/servicereference/services/elemental-appliances-software.json +1 -0
  167. package/src/data/servicereference/services/elemental-inference.json +1 -0
  168. package/src/data/servicereference/services/elemental-support-cases.json +1 -0
  169. package/src/data/servicereference/services/elemental-support-content.json +1 -0
  170. package/src/data/servicereference/services/emr-containers.json +1 -0
  171. package/src/data/servicereference/services/emr-serverless.json +1 -0
  172. package/src/data/servicereference/services/entityresolution.json +1 -0
  173. package/src/data/servicereference/services/es.json +1 -0
  174. package/src/data/servicereference/services/events.json +1 -0
  175. package/src/data/servicereference/services/evidently.json +1 -0
  176. package/src/data/servicereference/services/evs.json +1 -0
  177. package/src/data/servicereference/services/execute-api.json +1 -0
  178. package/src/data/servicereference/services/finspace-api.json +1 -0
  179. package/src/data/servicereference/services/finspace.json +1 -0
  180. package/src/data/servicereference/services/firehose.json +1 -0
  181. package/src/data/servicereference/services/fis.json +1 -0
  182. package/src/data/servicereference/services/fms.json +1 -0
  183. package/src/data/servicereference/services/forecast.json +1 -0
  184. package/src/data/servicereference/services/frauddetector.json +1 -0
  185. package/src/data/servicereference/services/freertos.json +1 -0
  186. package/src/data/servicereference/services/freetier.json +1 -0
  187. package/src/data/servicereference/services/fsx.json +1 -0
  188. package/src/data/servicereference/services/gamelift.json +1 -0
  189. package/src/data/servicereference/services/gameliftstreams.json +1 -0
  190. package/src/data/servicereference/services/geo-maps.json +1 -0
  191. package/src/data/servicereference/services/geo-places.json +1 -0
  192. package/src/data/servicereference/services/geo-routes.json +1 -0
  193. package/src/data/servicereference/services/geo.json +1 -0
  194. package/src/data/servicereference/services/glacier.json +1 -0
  195. package/src/data/servicereference/services/globalaccelerator.json +1 -0
  196. package/src/data/servicereference/services/glue.json +1 -0
  197. package/src/data/servicereference/services/grafana.json +1 -0
  198. package/src/data/servicereference/services/greengrass.json +1 -0
  199. package/src/data/servicereference/services/groundstation.json +1 -0
  200. package/src/data/servicereference/services/groundtruthlabeling.json +1 -0
  201. package/src/data/servicereference/services/guardduty.json +1 -0
  202. package/src/data/servicereference/services/health-agent.json +1 -0
  203. package/src/data/servicereference/services/health.json +1 -0
  204. package/src/data/servicereference/services/healthlake.json +1 -0
  205. package/src/data/servicereference/services/honeycode.json +1 -0
  206. package/src/data/servicereference/services/iam.json +1 -0
  207. package/src/data/servicereference/services/identity-sync.json +1 -0
  208. package/src/data/servicereference/services/identitystore-auth.json +1 -0
  209. package/src/data/servicereference/services/identitystore.json +1 -0
  210. package/src/data/servicereference/services/imagebuilder.json +1 -0
  211. package/src/data/servicereference/services/importexport.json +1 -0
  212. package/src/data/servicereference/services/inspector-scan.json +1 -0
  213. package/src/data/servicereference/services/inspector.json +1 -0
  214. package/src/data/servicereference/services/inspector2-telemetry.json +1 -0
  215. package/src/data/servicereference/services/inspector2.json +1 -0
  216. package/src/data/servicereference/services/interconnect.json +1 -0
  217. package/src/data/servicereference/services/internetmonitor.json +1 -0
  218. package/src/data/servicereference/services/invoicing.json +1 -0
  219. package/src/data/servicereference/services/iot-device-tester.json +1 -0
  220. package/src/data/servicereference/services/iot.json +1 -0
  221. package/src/data/servicereference/services/iotanalytics.json +1 -0
  222. package/src/data/servicereference/services/iotdeviceadvisor.json +1 -0
  223. package/src/data/servicereference/services/iotevents.json +1 -0
  224. package/src/data/servicereference/services/iotfleethub.json +1 -0
  225. package/src/data/servicereference/services/iotfleetwise.json +1 -0
  226. package/src/data/servicereference/services/iotjobsdata.json +1 -0
  227. package/src/data/servicereference/services/iotmanagedintegrations.json +1 -0
  228. package/src/data/servicereference/services/iotsitewise.json +1 -0
  229. package/src/data/servicereference/services/iottwinmaker.json +1 -0
  230. package/src/data/servicereference/services/iotwireless.json +1 -0
  231. package/src/data/servicereference/services/iq-permission.json +1 -0
  232. package/src/data/servicereference/services/iq.json +1 -0
  233. package/src/data/servicereference/services/ivs.json +1 -0
  234. package/src/data/servicereference/services/ivschat.json +1 -0
  235. package/src/data/servicereference/services/kafka-cluster.json +1 -0
  236. package/src/data/servicereference/services/kafka.json +1 -0
  237. package/src/data/servicereference/services/kafkaconnect.json +1 -0
  238. package/src/data/servicereference/services/kendra-ranking.json +1 -0
  239. package/src/data/servicereference/services/kendra.json +1 -0
  240. package/src/data/servicereference/services/kinesis.json +1 -0
  241. package/src/data/servicereference/services/kinesisanalytics.json +1 -0
  242. package/src/data/servicereference/services/kinesisvideo.json +1 -0
  243. package/src/data/servicereference/services/kms.json +1 -0
  244. package/src/data/servicereference/services/lakeformation.json +1 -0
  245. package/src/data/servicereference/services/lambda.json +1 -0
  246. package/src/data/servicereference/services/launchwizard.json +1 -0
  247. package/src/data/servicereference/services/lex.json +1 -0
  248. package/src/data/servicereference/services/license-manager-linux-subscriptions.json +1 -0
  249. package/src/data/servicereference/services/license-manager-user-subscriptions.json +1 -0
  250. package/src/data/servicereference/services/license-manager.json +1 -0
  251. package/src/data/servicereference/services/lightsail.json +1 -0
  252. package/src/data/servicereference/services/logs.json +1 -0
  253. package/src/data/servicereference/services/lookoutequipment.json +1 -0
  254. package/src/data/servicereference/services/lookoutmetrics.json +1 -0
  255. package/src/data/servicereference/services/lookoutvision.json +1 -0
  256. package/src/data/servicereference/services/m2.json +1 -0
  257. package/src/data/servicereference/services/machinelearning.json +1 -0
  258. package/src/data/servicereference/services/macie2.json +1 -0
  259. package/src/data/servicereference/services/managedblockchain-query.json +1 -0
  260. package/src/data/servicereference/services/managedblockchain.json +1 -0
  261. package/src/data/servicereference/services/mapcredits.json +1 -0
  262. package/src/data/servicereference/services/marketplacecommerceanalytics.json +1 -0
  263. package/src/data/servicereference/services/mechanicalturk.json +1 -0
  264. package/src/data/servicereference/services/mediaconnect.json +1 -0
  265. package/src/data/servicereference/services/mediaconvert.json +1 -0
  266. package/src/data/servicereference/services/mediaimport.json +1 -0
  267. package/src/data/servicereference/services/medialive.json +1 -0
  268. package/src/data/servicereference/services/mediapackage-vod.json +1 -0
  269. package/src/data/servicereference/services/mediapackage.json +1 -0
  270. package/src/data/servicereference/services/mediapackagev2.json +1 -0
  271. package/src/data/servicereference/services/mediastore.json +1 -0
  272. package/src/data/servicereference/services/mediatailor.json +1 -0
  273. package/src/data/servicereference/services/medical-imaging.json +1 -0
  274. package/src/data/servicereference/services/memorydb.json +1 -0
  275. package/src/data/servicereference/services/mgh.json +1 -0
  276. package/src/data/servicereference/services/mgn.json +1 -0
  277. package/src/data/servicereference/services/migrationhub-orchestrator.json +1 -0
  278. package/src/data/servicereference/services/migrationhub-strategy.json +1 -0
  279. package/src/data/servicereference/services/mobileanalytics.json +1 -0
  280. package/src/data/servicereference/services/mobiletargeting.json +1 -0
  281. package/src/data/servicereference/services/monitron.json +1 -0
  282. package/src/data/servicereference/services/mpa.json +1 -0
  283. package/src/data/servicereference/services/mq.json +1 -0
  284. package/src/data/servicereference/services/neptune-db.json +1 -0
  285. package/src/data/servicereference/services/neptune-graph.json +1 -0
  286. package/src/data/servicereference/services/network-firewall.json +1 -0
  287. package/src/data/servicereference/services/network-security-director.json +1 -0
  288. package/src/data/servicereference/services/networkflowmonitor.json +1 -0
  289. package/src/data/servicereference/services/networkmanager-chat.json +1 -0
  290. package/src/data/servicereference/services/networkmanager.json +1 -0
  291. package/src/data/servicereference/services/networkmonitor.json +1 -0
  292. package/src/data/servicereference/services/nimble.json +1 -0
  293. package/src/data/servicereference/services/notifications-contacts.json +1 -0
  294. package/src/data/servicereference/services/notifications.json +1 -0
  295. package/src/data/servicereference/services/nova-act.json +1 -0
  296. package/src/data/servicereference/services/oam.json +1 -0
  297. package/src/data/servicereference/services/observabilityadmin.json +1 -0
  298. package/src/data/servicereference/services/odb.json +1 -0
  299. package/src/data/servicereference/services/omics.json +1 -0
  300. package/src/data/servicereference/services/one.json +1 -0
  301. package/src/data/servicereference/services/opensearch.json +1 -0
  302. package/src/data/servicereference/services/opsworks-cm.json +1 -0
  303. package/src/data/servicereference/services/opsworks.json +1 -0
  304. package/src/data/servicereference/services/organizations.json +1 -0
  305. package/src/data/servicereference/services/osis.json +1 -0
  306. package/src/data/servicereference/services/outposts.json +1 -0
  307. package/src/data/servicereference/services/panorama.json +1 -0
  308. package/src/data/servicereference/services/partnercentral-account-management.json +1 -0
  309. package/src/data/servicereference/services/partnercentral.json +1 -0
  310. package/src/data/servicereference/services/payment-cryptography.json +1 -0
  311. package/src/data/servicereference/services/payments.json +1 -0
  312. package/src/data/servicereference/services/pca-connector-ad.json +1 -0
  313. package/src/data/servicereference/services/pca-connector-scep.json +1 -0
  314. package/src/data/servicereference/services/pcs.json +1 -0
  315. package/src/data/servicereference/services/personalize.json +1 -0
  316. package/src/data/servicereference/services/pi.json +1 -0
  317. package/src/data/servicereference/services/pipes.json +1 -0
  318. package/src/data/servicereference/services/polly.json +1 -0
  319. package/src/data/servicereference/services/pricing.json +1 -0
  320. package/src/data/servicereference/services/pricingplanmanager.json +1 -0
  321. package/src/data/servicereference/services/private-networks.json +1 -0
  322. package/src/data/servicereference/services/profile.json +1 -0
  323. package/src/data/servicereference/services/proton.json +1 -0
  324. package/src/data/servicereference/services/purchase-orders.json +1 -0
  325. package/src/data/servicereference/services/q.json +1 -0
  326. package/src/data/servicereference/services/qapps.json +1 -0
  327. package/src/data/servicereference/services/qbusiness.json +1 -0
  328. package/src/data/servicereference/services/qdeveloper.json +1 -0
  329. package/src/data/servicereference/services/qldb.json +1 -0
  330. package/src/data/servicereference/services/quicksight.json +1 -0
  331. package/src/data/servicereference/services/ram.json +1 -0
  332. package/src/data/servicereference/services/rbin.json +1 -0
  333. package/src/data/servicereference/services/rds-data.json +1 -0
  334. package/src/data/servicereference/services/rds-db.json +1 -0
  335. package/src/data/servicereference/services/rds.json +1 -0
  336. package/src/data/servicereference/services/redshift-data.json +1 -0
  337. package/src/data/servicereference/services/redshift-serverless.json +1 -0
  338. package/src/data/servicereference/services/redshift.json +1 -0
  339. package/src/data/servicereference/services/refactor-spaces.json +1 -0
  340. package/src/data/servicereference/services/rekognition.json +1 -0
  341. package/src/data/servicereference/services/repostspace.json +1 -0
  342. package/src/data/servicereference/services/resiliencehub.json +1 -0
  343. package/src/data/servicereference/services/resource-explorer-2.json +1 -0
  344. package/src/data/servicereference/services/resource-explorer.json +1 -0
  345. package/src/data/servicereference/services/resource-groups.json +1 -0
  346. package/src/data/servicereference/services/rhelkb.json +1 -0
  347. package/src/data/servicereference/services/robomaker.json +1 -0
  348. package/src/data/servicereference/services/rolesanywhere.json +1 -0
  349. package/src/data/servicereference/services/route53-recovery-cluster.json +1 -0
  350. package/src/data/servicereference/services/route53-recovery-control-config.json +1 -0
  351. package/src/data/servicereference/services/route53-recovery-readiness.json +1 -0
  352. package/src/data/servicereference/services/route53.json +1 -0
  353. package/src/data/servicereference/services/route53domains.json +1 -0
  354. package/src/data/servicereference/services/route53globalresolver.json +1 -0
  355. package/src/data/servicereference/services/route53profiles.json +1 -0
  356. package/src/data/servicereference/services/route53resolver.json +1 -0
  357. package/src/data/servicereference/services/rtbfabric.json +1 -0
  358. package/src/data/servicereference/services/rum.json +1 -0
  359. package/src/data/servicereference/services/s3-object-lambda.json +1 -0
  360. package/src/data/servicereference/services/s3-outposts.json +1 -0
  361. package/src/data/servicereference/services/s3.json +1 -0
  362. package/src/data/servicereference/services/s3express.json +1 -0
  363. package/src/data/servicereference/services/s3tables.json +1 -0
  364. package/src/data/servicereference/services/s3vectors.json +1 -0
  365. package/src/data/servicereference/services/sagemaker-data-science-assistant.json +1 -0
  366. package/src/data/servicereference/services/sagemaker-geospatial.json +1 -0
  367. package/src/data/servicereference/services/sagemaker-mlflow.json +1 -0
  368. package/src/data/servicereference/services/sagemaker-unified-studio-mcp.json +1 -0
  369. package/src/data/servicereference/services/sagemaker.json +1 -0
  370. package/src/data/servicereference/services/savingsplans.json +1 -0
  371. package/src/data/servicereference/services/scheduler.json +1 -0
  372. package/src/data/servicereference/services/schemas.json +1 -0
  373. package/src/data/servicereference/services/scn.json +1 -0
  374. package/src/data/servicereference/services/sdb.json +1 -0
  375. package/src/data/servicereference/services/secretsmanager.json +1 -0
  376. package/src/data/servicereference/services/security-ir.json +1 -0
  377. package/src/data/servicereference/services/securityagent.json +1 -0
  378. package/src/data/servicereference/services/securityhub.json +1 -0
  379. package/src/data/servicereference/services/securitylake.json +1 -0
  380. package/src/data/servicereference/services/serverlessrepo.json +1 -0
  381. package/src/data/servicereference/services/servicecatalog.json +1 -0
  382. package/src/data/servicereference/services/servicediscovery.json +1 -0
  383. package/src/data/servicereference/services/serviceextract.json +1 -0
  384. package/src/data/servicereference/services/servicequotas.json +1 -0
  385. package/src/data/servicereference/services/ses.json +1 -0
  386. package/src/data/servicereference/services/shield.json +1 -0
  387. package/src/data/servicereference/services/signer.json +1 -0
  388. package/src/data/servicereference/services/signin.json +1 -0
  389. package/src/data/servicereference/services/simspaceweaver.json +1 -0
  390. package/src/data/servicereference/services/sms-voice.json +1 -0
  391. package/src/data/servicereference/services/sms.json +1 -0
  392. package/src/data/servicereference/services/snow-device-management.json +1 -0
  393. package/src/data/servicereference/services/snowball.json +1 -0
  394. package/src/data/servicereference/services/sns.json +1 -0
  395. package/src/data/servicereference/services/social-messaging.json +1 -0
  396. package/src/data/servicereference/services/sqlworkbench.json +1 -0
  397. package/src/data/servicereference/services/sqs.json +1 -0
  398. package/src/data/servicereference/services/ssm-contacts.json +1 -0
  399. package/src/data/servicereference/services/ssm-guiconnect.json +1 -0
  400. package/src/data/servicereference/services/ssm-incidents.json +1 -0
  401. package/src/data/servicereference/services/ssm-quicksetup.json +1 -0
  402. package/src/data/servicereference/services/ssm-sap.json +1 -0
  403. package/src/data/servicereference/services/ssm.json +1 -0
  404. package/src/data/servicereference/services/ssmmessages.json +1 -0
  405. package/src/data/servicereference/services/sso-directory.json +1 -0
  406. package/src/data/servicereference/services/sso-oauth.json +1 -0
  407. package/src/data/servicereference/services/sso.json +1 -0
  408. package/src/data/servicereference/services/states.json +1 -0
  409. package/src/data/servicereference/services/storagegateway.json +1 -0
  410. package/src/data/servicereference/services/sts.json +1 -0
  411. package/src/data/servicereference/services/support-console.json +1 -0
  412. package/src/data/servicereference/services/support.json +1 -0
  413. package/src/data/servicereference/services/supportapp.json +1 -0
  414. package/src/data/servicereference/services/supportplans.json +1 -0
  415. package/src/data/servicereference/services/sustainability.json +1 -0
  416. package/src/data/servicereference/services/swf.json +1 -0
  417. package/src/data/servicereference/services/synthetics.json +1 -0
  418. package/src/data/servicereference/services/tag.json +1 -0
  419. package/src/data/servicereference/services/tax.json +1 -0
  420. package/src/data/servicereference/services/textract.json +1 -0
  421. package/src/data/servicereference/services/thinclient.json +1 -0
  422. package/src/data/servicereference/services/timestream-influxdb.json +1 -0
  423. package/src/data/servicereference/services/timestream.json +1 -0
  424. package/src/data/servicereference/services/tiros.json +1 -0
  425. package/src/data/servicereference/services/tnb.json +1 -0
  426. package/src/data/servicereference/services/transcribe.json +1 -0
  427. package/src/data/servicereference/services/transfer.json +1 -0
  428. package/src/data/servicereference/services/transform-custom.json +1 -0
  429. package/src/data/servicereference/services/transform.json +1 -0
  430. package/src/data/servicereference/services/translate.json +1 -0
  431. package/src/data/servicereference/services/trustedadvisor.json +1 -0
  432. package/src/data/servicereference/services/ts.json +1 -0
  433. package/src/data/servicereference/services/user-subscriptions.json +1 -0
  434. package/src/data/servicereference/services/uxc.json +1 -0
  435. package/src/data/servicereference/services/vendor-insights.json +1 -0
  436. package/src/data/servicereference/services/verified-access.json +1 -0
  437. package/src/data/servicereference/services/verifiedpermissions.json +1 -0
  438. package/src/data/servicereference/services/voiceid.json +1 -0
  439. package/src/data/servicereference/services/vpc-lattice-svcs.json +1 -0
  440. package/src/data/servicereference/services/vpc-lattice.json +1 -0
  441. package/src/data/servicereference/services/vpce.json +1 -0
  442. package/src/data/servicereference/services/waf-regional.json +1 -0
  443. package/src/data/servicereference/services/waf.json +1 -0
  444. package/src/data/servicereference/services/wafv2.json +1 -0
  445. package/src/data/servicereference/services/wam.json +1 -0
  446. package/src/data/servicereference/services/wellarchitected.json +1 -0
  447. package/src/data/servicereference/services/wickr.json +1 -0
  448. package/src/data/servicereference/services/wisdom.json +1 -0
  449. package/src/data/servicereference/services/workdocs.json +1 -0
  450. package/src/data/servicereference/services/worklink.json +1 -0
  451. package/src/data/servicereference/services/workmail.json +1 -0
  452. package/src/data/servicereference/services/workmailmessageflow.json +1 -0
  453. package/src/data/servicereference/services/workspaces-instances.json +1 -0
  454. package/src/data/servicereference/services/workspaces-web.json +1 -0
  455. package/src/data/servicereference/services/workspaces.json +1 -0
  456. package/src/data/servicereference/services/xray.json +1 -0
  457. package/src/data/servicereference/services.json +1 -0
  458. package/src/extension.d.ts +3 -0
  459. package/src/extension.js +23 -0
  460. package/src/grammars/tree-sitter-hcl.wasm +0 -0
  461. package/src/grammars/tree-sitter-json.wasm +0 -0
  462. package/src/grammars/tree-sitter-yaml.wasm +0 -0
  463. package/src/handlers/completion/action-value.d.ts +4 -0
  464. package/src/handlers/completion/action-value.js +46 -0
  465. package/src/handlers/completion/condition-block.d.ts +4 -0
  466. package/src/handlers/completion/condition-block.js +31 -0
  467. package/src/handlers/completion/condition-key.d.ts +4 -0
  468. package/src/handlers/completion/condition-key.js +80 -0
  469. package/src/handlers/completion/condition-operator.d.ts +4 -0
  470. package/src/handlers/completion/condition-operator.js +22 -0
  471. package/src/handlers/completion/effect-value.d.ts +4 -0
  472. package/src/handlers/completion/effect-value.js +14 -0
  473. package/src/handlers/completion/index.d.ts +14 -0
  474. package/src/handlers/completion/index.js +96 -0
  475. package/src/handlers/completion/principal-block-identifier.d.ts +4 -0
  476. package/src/handlers/completion/principal-block-identifier.js +4 -0
  477. package/src/handlers/completion/principal-block-type.d.ts +4 -0
  478. package/src/handlers/completion/principal-block-type.js +24 -0
  479. package/src/handlers/completion/principal-block.d.ts +4 -0
  480. package/src/handlers/completion/principal-block.js +28 -0
  481. package/src/handlers/completion/principal-identifier-completions.d.ts +2 -0
  482. package/src/handlers/completion/principal-identifier-completions.js +131 -0
  483. package/src/handlers/completion/principal-type.d.ts +4 -0
  484. package/src/handlers/completion/principal-type.js +23 -0
  485. package/src/handlers/completion/principal-typed-value.d.ts +4 -0
  486. package/src/handlers/completion/principal-typed-value.js +4 -0
  487. package/src/handlers/completion/principal-value.d.ts +4 -0
  488. package/src/handlers/completion/principal-value.js +18 -0
  489. package/src/handlers/completion/resource-value.d.ts +4 -0
  490. package/src/handlers/completion/resource-value.js +144 -0
  491. package/src/handlers/completion/statement-block.d.ts +10 -0
  492. package/src/handlers/completion/statement-block.js +51 -0
  493. package/src/handlers/completion/statement-key.d.ts +4 -0
  494. package/src/handlers/completion/statement-key.js +41 -0
  495. package/src/lib/iam-policy/condition-operators.d.ts +317 -0
  496. package/src/lib/iam-policy/condition-operators.js +129 -0
  497. package/src/lib/iam-policy/location.d.ts +71 -0
  498. package/src/lib/iam-policy/location.js +82 -0
  499. package/src/lib/iam-policy/partitions.d.ts +116 -0
  500. package/src/lib/iam-policy/partitions.js +51 -0
  501. package/src/lib/iam-policy/principals.d.ts +21 -0
  502. package/src/lib/iam-policy/principals.js +37 -0
  503. package/src/lib/iam-policy/reference/services.d.ts +22 -0
  504. package/src/lib/iam-policy/reference/services.js +99 -0
  505. package/src/lib/iam-policy/reference/types.d.ts +71 -0
  506. package/src/lib/iam-policy/reference/types.js +1 -0
  507. package/src/lib/iam-policy/statement-keys.d.ts +8 -0
  508. package/src/lib/iam-policy/statement-keys.js +159 -0
  509. package/src/lib/iam-policy/wildcard.d.ts +2 -0
  510. package/src/lib/iam-policy/wildcard.js +14 -0
  511. package/src/lib/treesitter/base.d.ts +35 -0
  512. package/src/lib/treesitter/base.js +50 -0
  513. package/src/lib/treesitter/hcl.d.ts +9 -0
  514. package/src/lib/treesitter/hcl.js +888 -0
  515. package/src/lib/treesitter/json.d.ts +9 -0
  516. package/src/lib/treesitter/json.js +376 -0
  517. package/src/lib/treesitter/manager.d.ts +9 -0
  518. package/src/lib/treesitter/manager.js +66 -0
  519. package/src/lib/treesitter/yaml.d.ts +9 -0
  520. package/src/lib/treesitter/yaml.js +878 -0
  521. package/src/server.d.ts +2 -0
  522. package/src/server.js +26 -0
@@ -0,0 +1,888 @@
1
+ import { resolve } from 'node:path';
2
+ import { Language } from 'web-tree-sitter';
3
+ import { TreeBase } from "./base.js";
4
+ export class TreeHcl extends TreeBase {
5
+ static async init() {
6
+ const grammarDir = resolve(import.meta.dirname, '../../grammars');
7
+ const language = await Language.load(resolve(grammarDir, 'tree-sitter-hcl.wasm'));
8
+ return new TreeHcl(language);
9
+ }
10
+ getCursorContext(uri, position) {
11
+ const node = this.getNodeAtPosition(uri, position);
12
+ if (!node)
13
+ return null;
14
+ const nodeBefore = position.column > 0 ? this.getNodeAtPosition(uri, { line: position.line, column: position.column - 1 }) : null;
15
+ // Try jsonencode mode first (more specific structure)
16
+ const jsonencodeContext = this.#tryJsonencodeMode(node, nodeBefore, position);
17
+ if (jsonencodeContext)
18
+ return jsonencodeContext;
19
+ // Try block mode
20
+ const blockContext = this.#tryBlockMode(node, nodeBefore, position);
21
+ if (blockContext)
22
+ return blockContext;
23
+ // Try error recovery (unterminated strings break the tree)
24
+ return this.#tryRecoverFromError(node, nodeBefore, position);
25
+ }
26
+ getStatementContext(uri, position) {
27
+ const node = this.getNodeAtPosition(uri, position);
28
+ if (!node)
29
+ return null;
30
+ // Try jsonencode mode
31
+ const statementObject = this.#findJsonencodeStatementObject(node);
32
+ if (statementObject)
33
+ return this.#extractJsonencodeStatementContext(statementObject);
34
+ // Try block mode
35
+ const statementBlock = this.#findStatementBlock(node);
36
+ if (statementBlock) {
37
+ const statementBody = statementBlock.namedChildren.find((child) => child.type === 'body') ?? null;
38
+ if (statementBody)
39
+ return this.#extractBlockStatementContext(statementBody);
40
+ }
41
+ return null;
42
+ }
43
+ getSiblingKeys(uri, position) {
44
+ const node = this.getNodeAtPosition(uri, position);
45
+ if (!node)
46
+ return [];
47
+ // Try jsonencode mode
48
+ const statementObject = this.#findJsonencodeStatementObject(node);
49
+ if (statementObject)
50
+ return this.#collectObjectExistingKeys(this.#findInnermostObject(node, statementObject));
51
+ // Try block mode
52
+ const statementBlock = this.#findStatementBlock(node);
53
+ if (statementBlock) {
54
+ const statementBody = statementBlock.namedChildren.find((child) => child.type === 'body') ?? null;
55
+ if (!statementBody)
56
+ return [];
57
+ let keysBody = this.#findInnermostBody(node, statementBody);
58
+ // When cursor lands on a sub-block node, use that block's body
59
+ if (node.type === 'block') {
60
+ const subBody = node.namedChildren.find((child) => child.type === 'body');
61
+ if (subBody)
62
+ keysBody = subBody;
63
+ }
64
+ return this.#collectBodyExistingKeys(keysBody);
65
+ }
66
+ return [];
67
+ }
68
+ // ---------------------------------------------------------------------------
69
+ // Jsonencode mode — object/object_elem/tuple, PascalCase keys, same as JSON
70
+ // ---------------------------------------------------------------------------
71
+ #tryJsonencodeMode(node, nodeBefore, position) {
72
+ let statementObject = this.#findJsonencodeStatementObject(node);
73
+ if (!statementObject && nodeBefore)
74
+ statementObject = this.#findJsonencodeStatementObject(nodeBefore);
75
+ if (!statementObject)
76
+ return null;
77
+ const context1 = this.#resolveJsonencodeCursorContext(node, statementObject, position);
78
+ const context2 = nodeBefore ? this.#resolveJsonencodeCursorContext(nodeBefore, statementObject, position) : null;
79
+ return this.#pickBestCursorContext(context1, context2);
80
+ }
81
+ #resolveJsonencodeCursorContext(node, statementObject, position) {
82
+ const cursorPath = this.#buildJsonencodeCursorPath(node, statementObject, position);
83
+ if (cursorPath.role === 'value' && !this.#isInsideQuote(node))
84
+ return null;
85
+ return { ...cursorPath, policyFormat: 'standard' };
86
+ }
87
+ #findJsonencodeStatementObject(node) {
88
+ let current = node;
89
+ while (current) {
90
+ if (current.type === 'object' && this.#isInsideStatementTuple(current)) {
91
+ return current;
92
+ }
93
+ current = current.parent;
94
+ }
95
+ return null;
96
+ }
97
+ /**
98
+ * Check that an object is an element of a tuple whose enclosing object_elem
99
+ * has the key "Statement".
100
+ */
101
+ #isInsideStatementTuple(object) {
102
+ // Walk up through expression/collection_value wrappers to reach the tuple
103
+ let current = object.parent;
104
+ while (current && (current.type === 'collection_value' || current.type === 'expression')) {
105
+ current = current.parent;
106
+ }
107
+ if (current?.type !== 'tuple')
108
+ return false;
109
+ // Walk up from tuple through wrappers to reach the object_elem
110
+ current = current.parent;
111
+ while (current && (current.type === 'collection_value' || current.type === 'expression')) {
112
+ current = current.parent;
113
+ }
114
+ if (current?.type !== 'object_elem')
115
+ return false;
116
+ return this.#getObjectElemKey(current) === 'Statement';
117
+ }
118
+ #buildJsonencodeCursorPath(cursorNode, statementObject, position) {
119
+ const keys = [];
120
+ let role = null;
121
+ let previous = null;
122
+ let current = cursorNode;
123
+ while (current && current.id !== statementObject.id) {
124
+ if (current.type === 'object' && role === null) {
125
+ role = 'key';
126
+ }
127
+ if (current.type === 'object_elem') {
128
+ const elementKey = this.#getObjectElemKey(current);
129
+ const keyExpression = current.namedChildren.find((child) => child.type === 'expression');
130
+ if (role === null) {
131
+ if (previous && keyExpression && previous.id === keyExpression.id) {
132
+ role = 'key';
133
+ }
134
+ else {
135
+ role = 'value';
136
+ if (elementKey)
137
+ keys.unshift(elementKey);
138
+ }
139
+ }
140
+ else {
141
+ if (elementKey)
142
+ keys.unshift(elementKey);
143
+ }
144
+ }
145
+ previous = current;
146
+ current = current.parent;
147
+ }
148
+ // When cursor falls on the statementObject (e.g., after an incomplete elem like
149
+ // "Effect = "), check if a child elem or ERROR node is on the same line.
150
+ if (role === null && cursorNode.id === statementObject.id) {
151
+ for (const child of statementObject.namedChildren) {
152
+ if (child.startPosition.row !== position.line)
153
+ continue;
154
+ if (child.type === 'object_elem' || child.type === 'ERROR') {
155
+ const elementKey = this.#getObjectElemKey(child);
156
+ if (elementKey) {
157
+ keys.unshift(elementKey);
158
+ role = 'value';
159
+ break;
160
+ }
161
+ }
162
+ }
163
+ }
164
+ if (role === null)
165
+ role = 'key';
166
+ const partial = this.#extractJsonencodePartial(cursorNode, position);
167
+ return { keys, role, partial };
168
+ }
169
+ #getObjectElemKey(element) {
170
+ const keyExpression = element.namedChildren.find((child) => child.type === 'expression');
171
+ if (!keyExpression)
172
+ return null;
173
+ const variableExpression = keyExpression.namedChildren.find((child) => child.type === 'variable_expr');
174
+ if (!variableExpression)
175
+ return null;
176
+ const id = variableExpression.namedChildren.find((child) => child.type === 'identifier');
177
+ return id?.text ?? null;
178
+ }
179
+ #findInnermostObject(node, statementObject) {
180
+ let current = node;
181
+ while (current && current.id !== statementObject.id) {
182
+ if (current.type === 'object')
183
+ return current;
184
+ current = current.parent;
185
+ }
186
+ return statementObject;
187
+ }
188
+ #collectObjectExistingKeys(object) {
189
+ return object.namedChildren
190
+ .filter((child) => child.type === 'object_elem')
191
+ .map((element) => this.#getObjectElemKey(element))
192
+ .filter((key) => key !== null);
193
+ }
194
+ #extractJsonencodePartial(node, position) {
195
+ let current = node;
196
+ while (current) {
197
+ if (current.type === 'identifier' || current.type === 'template_literal') {
198
+ if (position.line === current.startPosition.row) {
199
+ return current.text.slice(0, position.column - current.startPosition.column);
200
+ }
201
+ return current.text;
202
+ }
203
+ if (current.type === 'object' || current.type === 'object_elem')
204
+ break;
205
+ current = current.parent;
206
+ }
207
+ return '';
208
+ }
209
+ // ---------------------------------------------------------------------------
210
+ // Block mode — block/body/attribute, snake_case keys
211
+ // ---------------------------------------------------------------------------
212
+ #tryBlockMode(node, nodeBefore, position) {
213
+ let statementBlock = this.#findStatementBlock(node);
214
+ if (!statementBlock && nodeBefore)
215
+ statementBlock = this.#findStatementBlock(nodeBefore);
216
+ if (!statementBlock)
217
+ return null;
218
+ const statementBody = statementBlock.namedChildren.find((child) => child.type === 'body') ?? null;
219
+ // If cursor is inside the body, do normal cursor path walk
220
+ if (statementBody && this.#isDescendantOf(node, statementBody)) {
221
+ // Cursor right after a closing quote — no completions
222
+ if (nodeBefore?.type === 'quoted_template_end')
223
+ return null;
224
+ const context1 = this.#resolveBlockCursorContext(node, statementBody, position);
225
+ const context2 = nodeBefore ? this.#resolveBlockCursorContext(nodeBefore, statementBody, position) : null;
226
+ return this.#pickBestCursorContext(context1, context2);
227
+ }
228
+ // Cursor is on the block itself (outside body span) — statement-key level
229
+ const partial = this.#extractBlockPartial(node, position);
230
+ // Check for incomplete attributes on the same line (may be in ERROR nodes
231
+ // when tree-sitter can't parse the body due to a missing value)
232
+ const searchParent = statementBody ?? statementBlock;
233
+ for (const child of searchParent.namedChildren) {
234
+ if (child.startPosition.row !== position.line)
235
+ continue;
236
+ if (child.type === 'attribute' || child.type === 'ERROR') {
237
+ const id = child.namedChildren.find((namedChild) => namedChild.type === 'identifier');
238
+ if (id) {
239
+ if (!this.#isInsideQuote(node) && (!nodeBefore || !this.#isInsideQuote(nodeBefore)))
240
+ return null;
241
+ return {
242
+ keys: [id.text],
243
+ role: 'value',
244
+ partial: '',
245
+ policyFormat: 'hcl-block',
246
+ };
247
+ }
248
+ }
249
+ }
250
+ return {
251
+ keys: [],
252
+ role: 'key',
253
+ partial,
254
+ policyFormat: 'hcl-block',
255
+ };
256
+ }
257
+ #resolveBlockCursorContext(node, statementBody, position) {
258
+ const cursorPath = this.#buildBlockCursorPath(node, statementBody, position);
259
+ if (cursorPath.role === 'value' && !this.#isInsideQuote(node))
260
+ return null;
261
+ // When inside a principals block's identifiers attribute, read the sibling
262
+ // type attribute and append its value to the cursor path keys so the location
263
+ // resolver can emit principal-block-identifier with the correct type.
264
+ if ((cursorPath.keys[0] === 'principals' || cursorPath.keys[0] === 'not_principals') &&
265
+ cursorPath.keys[1] === 'identifiers' &&
266
+ cursorPath.role === 'value') {
267
+ const principalsBlock = this.#findEnclosingBlock(node, cursorPath.keys[0], statementBody);
268
+ if (principalsBlock) {
269
+ const blockBody = principalsBlock.namedChildren.find((child) => child.type === 'body');
270
+ const typeValue = blockBody ? this.#readAttributeStringValue(blockBody, 'type') : null;
271
+ if (typeValue)
272
+ cursorPath.keys.push(typeValue);
273
+ }
274
+ }
275
+ return { ...cursorPath, policyFormat: 'hcl-block' };
276
+ }
277
+ #findStatementBlock(node) {
278
+ let current = node;
279
+ while (current) {
280
+ if (current.type === 'block' && this.#getBlockIdentifier(current) === 'statement') {
281
+ return current;
282
+ }
283
+ current = current.parent;
284
+ }
285
+ return null;
286
+ }
287
+ #getBlockIdentifier(block) {
288
+ const id = block.namedChildren.find((child) => child.type === 'identifier');
289
+ return id?.text ?? null;
290
+ }
291
+ #isDescendantOf(node, ancestor) {
292
+ let current = node;
293
+ while (current) {
294
+ if (current.id === ancestor.id)
295
+ return true;
296
+ current = current.parent;
297
+ }
298
+ return false;
299
+ }
300
+ #buildBlockCursorPath(cursorNode, statementBody, position) {
301
+ const keys = [];
302
+ let role = null;
303
+ let previous = null;
304
+ let current = cursorNode;
305
+ while (current && current.id !== statementBody.id) {
306
+ if (current.type === 'body' && role === null) {
307
+ role = 'key';
308
+ }
309
+ if (current.type === 'attribute') {
310
+ const attrKey = current.namedChildren.find((child) => child.type === 'identifier');
311
+ if (role === null) {
312
+ if (previous && attrKey && previous.id === attrKey.id) {
313
+ role = 'key';
314
+ }
315
+ else {
316
+ role = 'value';
317
+ if (attrKey)
318
+ keys.unshift(attrKey.text);
319
+ }
320
+ }
321
+ else {
322
+ if (attrKey)
323
+ keys.unshift(attrKey.text);
324
+ }
325
+ }
326
+ // Sub-blocks (e.g. condition, principals) contribute their identifier as a key
327
+ if (current.type === 'block') {
328
+ const blockIdentifier = this.#getBlockIdentifier(current);
329
+ if (blockIdentifier === 'condition' ||
330
+ blockIdentifier === 'principals' ||
331
+ blockIdentifier === 'not_principals') {
332
+ if (role === null)
333
+ role = 'key';
334
+ keys.unshift(blockIdentifier);
335
+ }
336
+ }
337
+ previous = current;
338
+ current = current.parent;
339
+ }
340
+ if (role === null)
341
+ role = 'key';
342
+ const partial = this.#extractBlockPartial(cursorNode, position);
343
+ return { keys, role, partial };
344
+ }
345
+ #findEnclosingBlock(node, blockName, statementBody) {
346
+ let current = node;
347
+ while (current && current.id !== statementBody.id) {
348
+ if (current.type === 'block' && this.#getBlockIdentifier(current) === blockName)
349
+ return current;
350
+ current = current.parent;
351
+ }
352
+ return null;
353
+ }
354
+ #readAttributeStringValue(body, name) {
355
+ for (const child of body.namedChildren) {
356
+ if (child.type !== 'attribute')
357
+ continue;
358
+ const id = child.namedChildren.find((namedChild) => namedChild.type === 'identifier');
359
+ if (id?.text !== name)
360
+ continue;
361
+ const expression = child.namedChildren.find((namedChild) => namedChild.type === 'expression');
362
+ const literal = expression?.namedChildren.find((child) => child.type === 'literal_value');
363
+ const string = literal?.namedChildren.find((child) => child.type === 'string_lit');
364
+ const template = string?.namedChildren.find((child) => child.type === 'template_literal');
365
+ return template?.text ?? null;
366
+ }
367
+ return null;
368
+ }
369
+ #findInnermostBody(node, statementBody) {
370
+ let current = node;
371
+ while (current && current.id !== statementBody.id) {
372
+ if (current.type === 'body')
373
+ return current;
374
+ current = current.parent;
375
+ }
376
+ return statementBody;
377
+ }
378
+ #collectBodyExistingKeys(body) {
379
+ const keys = [];
380
+ for (const child of body.namedChildren) {
381
+ if (child.type === 'attribute') {
382
+ const id = child.namedChildren.find((namedChild) => namedChild.type === 'identifier');
383
+ if (id)
384
+ keys.push(id.text);
385
+ }
386
+ // Sub-blocks (e.g. condition) are not included — HCL allows multiples
387
+ }
388
+ return keys;
389
+ }
390
+ #hasBodyAttribute(body, name) {
391
+ return body.namedChildren.some((child) => child.type === 'attribute' && child.namedChildren.some((id) => id.type === 'identifier' && id.text === name));
392
+ }
393
+ #extractBlockPartial(node, position) {
394
+ let current = node;
395
+ while (current) {
396
+ if (current.type === 'identifier' || current.type === 'template_literal') {
397
+ if (position.line === current.startPosition.row) {
398
+ return current.text.slice(0, position.column - current.startPosition.column);
399
+ }
400
+ return current.text;
401
+ }
402
+ if (current.type === 'body' || current.type === 'attribute' || current.type === 'block')
403
+ break;
404
+ current = current.parent;
405
+ }
406
+ return '';
407
+ }
408
+ // ---------------------------------------------------------------------------
409
+ // Shared
410
+ // ---------------------------------------------------------------------------
411
+ #isInsideQuote(node) {
412
+ let current = node;
413
+ while (current) {
414
+ // The closing quote is part of string_lit but the cursor is past the string content
415
+ if (current.type === 'quoted_template_end')
416
+ return false;
417
+ if (current.type === 'quoted_template' ||
418
+ current.type === 'template_literal' ||
419
+ current.type === 'string_lit' ||
420
+ current.type === 'quoted_template_start')
421
+ return true;
422
+ if (current.type === 'attribute' ||
423
+ current.type === 'object_elem' ||
424
+ current.type === 'body' ||
425
+ current.type === 'object')
426
+ return false;
427
+ current = current.parent;
428
+ }
429
+ return false;
430
+ }
431
+ /**
432
+ * When tree-sitter produces a root-level ERROR (e.g., unterminated quote in
433
+ * a value like `actions = ["`), scan the ERROR children for statement context.
434
+ */
435
+ #tryRecoverFromError(node, nodeBefore, position) {
436
+ let errorNode = node;
437
+ while (errorNode && errorNode.type !== 'ERROR') {
438
+ errorNode = errorNode.parent;
439
+ }
440
+ if (!errorNode)
441
+ return null;
442
+ // Cursor must be inside a quote. In ERROR recovery, the cursor node is the
443
+ // ERROR itself so isInsideQuote won't find an ancestor. Check for a
444
+ // quoted_template_start child on the cursor line before the cursor position.
445
+ const hasQuoteOnLine = this.#isInsideQuote(node) ||
446
+ (nodeBefore && this.#isInsideQuote(nodeBefore)) ||
447
+ errorNode.children.some((child) => child.type === 'quoted_template_start' &&
448
+ child.startPosition.row === position.line &&
449
+ child.endPosition.column <= position.column);
450
+ if (!hasQuoteOnLine)
451
+ return null;
452
+ let foundStatement = false;
453
+ let policyFormat = null;
454
+ let lastKey = null;
455
+ let lastKeyFromAttribute = false;
456
+ // Sub-block tracking (principals, not_principals, condition)
457
+ const subBlockNames = new Set(['principals', 'not_principals', 'condition']);
458
+ let pendingSubBlockId = null;
459
+ let subBlockKey = null;
460
+ let subBlockTypeValue = null;
461
+ for (const child of errorNode.children) {
462
+ // Stop at children past the cursor
463
+ if (child.startPosition.row > position.line)
464
+ break;
465
+ // Detect statement marker: `identifier "statement"` (block) or
466
+ // `expression > variable_expr > identifier "Statement"` (jsonencode)
467
+ if (!foundStatement) {
468
+ if (child.type === 'identifier' && child.text === 'statement') {
469
+ foundStatement = true;
470
+ policyFormat = 'hcl-block';
471
+ }
472
+ else if (child.type === 'expression') {
473
+ const id = this.#getExpressionIdentifier(child);
474
+ if (id === 'Statement') {
475
+ foundStatement = true;
476
+ policyFormat = 'standard';
477
+ }
478
+ }
479
+ continue;
480
+ }
481
+ // Confirm sub-block entry when we see block_start after a known sub-block identifier
482
+ if (child.type === 'block_start' && pendingSubBlockId) {
483
+ subBlockKey = pendingSubBlockId;
484
+ subBlockTypeValue = null;
485
+ pendingSubBlockId = null;
486
+ continue;
487
+ }
488
+ pendingSubBlockId = null;
489
+ // Exit sub-block on block_end
490
+ if (child.type === 'block_end' && subBlockKey) {
491
+ subBlockKey = null;
492
+ subBlockTypeValue = null;
493
+ continue;
494
+ }
495
+ // Track key identifiers after statement marker
496
+ if (child.type === 'identifier') {
497
+ lastKey = child.text;
498
+ lastKeyFromAttribute = false;
499
+ if (subBlockNames.has(child.text)) {
500
+ pendingSubBlockId = child.text;
501
+ }
502
+ }
503
+ else if (child.type === 'expression') {
504
+ const id = this.#getExpressionIdentifier(child);
505
+ if (id) {
506
+ lastKey = id;
507
+ lastKeyFromAttribute = false;
508
+ }
509
+ }
510
+ else if (child.type === 'object_elem') {
511
+ const key = this.#getObjectElemKey(child);
512
+ if (key) {
513
+ lastKey = key;
514
+ lastKeyFromAttribute = true;
515
+ }
516
+ }
517
+ else if (child.type === 'attribute') {
518
+ const id = child.namedChildren.find((namedChild) => namedChild.type === 'identifier');
519
+ if (id) {
520
+ lastKey = id.text;
521
+ lastKeyFromAttribute = true;
522
+ // Read type attribute value inside a principals sub-block
523
+ if (subBlockKey && (subBlockKey === 'principals' || subBlockKey === 'not_principals') && id.text === 'type') {
524
+ const expression = child.namedChildren.find((namedChild) => namedChild.type === 'expression');
525
+ const literal = expression?.namedChildren.find((child) => child.type === 'literal_value');
526
+ const string = literal?.namedChildren.find((child) => child.type === 'string_lit');
527
+ const template = string?.namedChildren.find((child) => child.type === 'template_literal');
528
+ if (template)
529
+ subBlockTypeValue = template.text;
530
+ }
531
+ }
532
+ }
533
+ }
534
+ if (!foundStatement || !lastKey || !policyFormat)
535
+ return null;
536
+ // Extract partial: when the key came from an attribute/object_elem that
537
+ // contains the quote (e.g., `effect = "`), it's empty. When the cursor node
538
+ // is inside a string (open quote slurped subsequent lines), extract from the
539
+ // template_literal. Otherwise extract from ERROR node text.
540
+ let partial = '';
541
+ if (!lastKeyFromAttribute) {
542
+ if (this.#isInsideQuote(node)) {
543
+ partial = this.#extractQuotedPartial(node, position);
544
+ }
545
+ else if (nodeBefore && this.#isInsideQuote(nodeBefore)) {
546
+ partial = this.#extractQuotedPartial(nodeBefore, position);
547
+ }
548
+ else {
549
+ partial = this.#extractPartialFromErrorNode(errorNode, position);
550
+ }
551
+ }
552
+ // Build keys with sub-block prefix when inside a sub-block
553
+ const keys = subBlockKey ? [subBlockKey, lastKey] : [lastKey];
554
+ if (subBlockKey &&
555
+ (subBlockKey === 'principals' || subBlockKey === 'not_principals') &&
556
+ lastKey === 'identifiers' &&
557
+ subBlockTypeValue) {
558
+ keys.push(subBlockTypeValue);
559
+ }
560
+ return {
561
+ keys,
562
+ role: 'value',
563
+ partial,
564
+ policyFormat,
565
+ };
566
+ }
567
+ /**
568
+ * Extract partial from inside a quoted string (when the open quote caused
569
+ * tree-sitter to slurp subsequent lines into a string_lit).
570
+ */
571
+ #extractQuotedPartial(node, position) {
572
+ let current = node;
573
+ while (current) {
574
+ if (current.type === 'template_literal') {
575
+ if (position.line === current.startPosition.row) {
576
+ return current.text.slice(0, position.column - current.startPosition.column);
577
+ }
578
+ return '';
579
+ }
580
+ if (current.type === 'quoted_template_start')
581
+ return '';
582
+ if (current.type === 'string_lit') {
583
+ // Cursor is right after the opening quote, no template_literal yet
584
+ return '';
585
+ }
586
+ current = current.parent;
587
+ }
588
+ return '';
589
+ }
590
+ #extractPartialFromErrorNode(errorNode, position) {
591
+ let afterColumn = 0;
592
+ for (const child of errorNode.children) {
593
+ if (child.startPosition.row !== position.line)
594
+ continue;
595
+ // Only consider children that end on the same line (multi-line children
596
+ // like attributes have endPosition from a different row)
597
+ if (child.endPosition.row !== position.line)
598
+ continue;
599
+ if (child.endPosition.column <= position.column) {
600
+ afterColumn = child.endPosition.column;
601
+ }
602
+ }
603
+ const lines = errorNode.text.split('\n');
604
+ const lineIndex = position.line - errorNode.startPosition.row;
605
+ if (lineIndex < 0 || lineIndex >= lines.length)
606
+ return '';
607
+ const line = lines[lineIndex];
608
+ const startColumn = lineIndex === 0 ? errorNode.startPosition.column : 0;
609
+ return line.slice(afterColumn - startColumn, position.column - startColumn);
610
+ }
611
+ #getExpressionIdentifier(expression) {
612
+ const variableExpression = expression.namedChildren.find((child) => child.type === 'variable_expr');
613
+ if (!variableExpression)
614
+ return null;
615
+ const id = variableExpression.namedChildren.find((child) => child.type === 'identifier');
616
+ return id?.text ?? null;
617
+ }
618
+ #pickBestCursorContext(a, b) {
619
+ if (!a)
620
+ return b;
621
+ if (!b)
622
+ return a;
623
+ if (a.partial === '' && b.partial !== '')
624
+ return b;
625
+ if (a.partial === '' && b.partial === '' && b.keys.length > a.keys.length)
626
+ return b;
627
+ return a;
628
+ }
629
+ /**
630
+ * Read all string values from an attribute in an HCL body.
631
+ * Handles both single string (`actions = "s3:GetObject"`) and
632
+ * tuple (`actions = ["s3:GetObject", "s3:PutObject"]`) forms.
633
+ */
634
+ #readAttributeStringValues(body, name) {
635
+ for (const child of body.namedChildren) {
636
+ if (child.type !== 'attribute')
637
+ continue;
638
+ const id = child.namedChildren.find((namedChild) => namedChild.type === 'identifier');
639
+ if (id?.text !== name)
640
+ continue;
641
+ const expression = child.namedChildren.find((namedChild) => namedChild.type === 'expression');
642
+ if (!expression)
643
+ return [];
644
+ // Single string literal
645
+ const literal = expression.namedChildren.find((child) => child.type === 'literal_value');
646
+ if (literal) {
647
+ const string = literal.namedChildren.find((child) => child.type === 'string_lit');
648
+ const template = string?.namedChildren.find((child) => child.type === 'template_literal');
649
+ return template?.text ? [template.text] : [];
650
+ }
651
+ // Tuple of strings
652
+ let tuple = expression.namedChildren.find((child) => child.type === 'tuple');
653
+ if (!tuple) {
654
+ const collectionValue = expression.namedChildren.find((child) => child.type === 'collection_value');
655
+ tuple = collectionValue?.namedChildren.find((child) => child.type === 'tuple') ?? undefined;
656
+ }
657
+ if (tuple) {
658
+ const values = [];
659
+ for (const element of tuple.namedChildren) {
660
+ const elementExpression = element.type === 'expression' ? element : null;
661
+ const elementLiteral = elementExpression?.namedChildren.find((child) => child.type === 'literal_value');
662
+ const elementString = elementLiteral?.namedChildren.find((child) => child.type === 'string_lit');
663
+ const elementTemplate = elementString?.namedChildren.find((child) => child.type === 'template_literal');
664
+ if (elementTemplate?.text)
665
+ values.push(elementTemplate.text);
666
+ }
667
+ return values;
668
+ }
669
+ }
670
+ return [];
671
+ }
672
+ /**
673
+ * Read string values from an HCL expression (string literal or tuple of strings).
674
+ */
675
+ #readExpressionStringValues(expression) {
676
+ const literal = expression.namedChildren.find((child) => child.type === 'literal_value');
677
+ if (literal) {
678
+ const string = literal.namedChildren.find((child) => child.type === 'string_lit');
679
+ const template = string?.namedChildren.find((child) => child.type === 'template_literal');
680
+ return template?.text ? [template.text] : [];
681
+ }
682
+ let tuple = expression.namedChildren.find((child) => child.type === 'tuple');
683
+ if (!tuple) {
684
+ const collectionValue = expression.namedChildren.find((child) => child.type === 'collection_value');
685
+ tuple = collectionValue?.namedChildren.find((child) => child.type === 'tuple') ?? undefined;
686
+ }
687
+ if (tuple) {
688
+ const values = [];
689
+ for (const element of tuple.namedChildren) {
690
+ const elementExpression = element.type === 'expression' ? element : null;
691
+ const elementLiteral = elementExpression?.namedChildren.find((child) => child.type === 'literal_value');
692
+ const elementString = elementLiteral?.namedChildren.find((child) => child.type === 'string_lit');
693
+ const elementTemplate = elementString?.namedChildren.find((child) => child.type === 'template_literal');
694
+ if (elementTemplate?.text)
695
+ values.push(elementTemplate.text);
696
+ }
697
+ return values;
698
+ }
699
+ return [];
700
+ }
701
+ /**
702
+ * Extract statement structure from an HCL block body (snake_case attributes).
703
+ */
704
+ #extractBlockStatementContext(statementBody) {
705
+ const context = {};
706
+ const sid = this.#readAttributeStringValue(statementBody, 'sid');
707
+ if (sid)
708
+ context.Sid = sid;
709
+ const effect = this.#readAttributeStringValue(statementBody, 'effect');
710
+ if (effect)
711
+ context.Effect = effect;
712
+ if (this.#hasBodyAttribute(statementBody, 'actions'))
713
+ context.Action = this.#readAttributeStringValues(statementBody, 'actions');
714
+ if (this.#hasBodyAttribute(statementBody, 'not_actions'))
715
+ context.NotAction = this.#readAttributeStringValues(statementBody, 'not_actions');
716
+ if (this.#hasBodyAttribute(statementBody, 'resources'))
717
+ context.Resource = this.#readAttributeStringValues(statementBody, 'resources');
718
+ if (this.#hasBodyAttribute(statementBody, 'not_resources'))
719
+ context.NotResource = this.#readAttributeStringValues(statementBody, 'not_resources');
720
+ // Read condition sub-blocks: condition { test = "Op" variable = "key" values = [...] }
721
+ const condition = {};
722
+ for (const child of statementBody.namedChildren) {
723
+ if (child.type !== 'block' || this.#getBlockIdentifier(child) !== 'condition')
724
+ continue;
725
+ const blockBody = child.namedChildren.find((namedChild) => namedChild.type === 'body');
726
+ if (!blockBody)
727
+ continue;
728
+ const test = this.#readAttributeStringValue(blockBody, 'test');
729
+ const variable = this.#readAttributeStringValue(blockBody, 'variable');
730
+ const values = this.#readAttributeStringValues(blockBody, 'values');
731
+ if (test) {
732
+ if (!condition[test])
733
+ condition[test] = {};
734
+ if (variable)
735
+ condition[test][variable] = values;
736
+ }
737
+ }
738
+ if (Object.keys(condition).length > 0)
739
+ context.Condition = condition;
740
+ // Read principals/not_principals sub-blocks
741
+ for (const blockName of ['principals', 'not_principals']) {
742
+ const principals = {};
743
+ for (const child of statementBody.namedChildren) {
744
+ if (child.type !== 'block' || this.#getBlockIdentifier(child) !== blockName)
745
+ continue;
746
+ const blockBody = child.namedChildren.find((namedChild) => namedChild.type === 'body');
747
+ if (!blockBody)
748
+ continue;
749
+ const type = this.#readAttributeStringValue(blockBody, 'type');
750
+ const identifiers = this.#readAttributeStringValues(blockBody, 'identifiers');
751
+ if (type) {
752
+ if (type === '*') {
753
+ if (blockName === 'principals')
754
+ context.Principal = '*';
755
+ else
756
+ context.NotPrincipal = '*';
757
+ break;
758
+ }
759
+ principals[type] = identifiers;
760
+ }
761
+ }
762
+ if (Object.keys(principals).length > 0) {
763
+ if (blockName === 'principals')
764
+ context.Principal = principals;
765
+ else
766
+ context.NotPrincipal = principals;
767
+ }
768
+ }
769
+ return context;
770
+ }
771
+ /**
772
+ * Extract statement structure from an HCL jsonencode object (PascalCase keys).
773
+ */
774
+ #extractJsonencodeStatementContext(statementObject) {
775
+ const context = {};
776
+ for (const child of statementObject.namedChildren) {
777
+ if (child.type !== 'object_elem')
778
+ continue;
779
+ const key = this.#getObjectElemKey(child);
780
+ const expressions = child.namedChildren.filter((namedChild) => namedChild.type === 'expression');
781
+ const valueExpression = expressions.length >= 2 ? expressions[1] : null;
782
+ if (!valueExpression)
783
+ continue;
784
+ if (key === 'Sid') {
785
+ const values = this.#readExpressionStringValues(valueExpression);
786
+ if (values.length > 0)
787
+ context.Sid = values[0];
788
+ }
789
+ else if (key === 'Effect') {
790
+ const values = this.#readExpressionStringValues(valueExpression);
791
+ if (values.length > 0)
792
+ context.Effect = values[0];
793
+ }
794
+ else if (key === 'Action') {
795
+ context.Action = this.#readExpressionStringValues(valueExpression);
796
+ }
797
+ else if (key === 'NotAction') {
798
+ context.NotAction = this.#readExpressionStringValues(valueExpression);
799
+ }
800
+ else if (key === 'Resource') {
801
+ context.Resource = this.#readExpressionStringValues(valueExpression);
802
+ }
803
+ else if (key === 'NotResource') {
804
+ context.NotResource = this.#readExpressionStringValues(valueExpression);
805
+ }
806
+ else if (key === 'Principal' || key === 'NotPrincipal') {
807
+ const value = this.#readJsonencodePrincipalValue(valueExpression);
808
+ if (value) {
809
+ if (key === 'Principal')
810
+ context.Principal = value;
811
+ else
812
+ context.NotPrincipal = value;
813
+ }
814
+ }
815
+ else if (key === 'Condition') {
816
+ context.Condition = this.#readJsonencodeConditionValue(valueExpression);
817
+ }
818
+ }
819
+ return context;
820
+ }
821
+ #readJsonencodePrincipalValue(expression) {
822
+ const values = this.#readExpressionStringValues(expression);
823
+ if (values.length === 1 && values[0] === '*')
824
+ return '*';
825
+ let object = expression.namedChildren.find((child) => child.type === 'object');
826
+ if (!object) {
827
+ const collectionValue = expression.namedChildren.find((child) => child.type === 'collection_value');
828
+ object = collectionValue?.namedChildren.find((child) => child.type === 'object') ?? undefined;
829
+ }
830
+ if (!object)
831
+ return null;
832
+ const result = {};
833
+ for (const child of object.namedChildren) {
834
+ if (child.type !== 'object_elem')
835
+ continue;
836
+ const typeKey = this.#getObjectElemKey(child);
837
+ const expressions = child.namedChildren.filter((namedChild) => namedChild.type === 'expression');
838
+ const valueExpressionession = expressions.length >= 2 ? expressions[1] : null;
839
+ if (typeKey && valueExpressionession)
840
+ result[typeKey] = this.#readExpressionStringValues(valueExpressionession);
841
+ }
842
+ return Object.keys(result).length > 0 ? result : null;
843
+ }
844
+ #readJsonencodeConditionValue(expression) {
845
+ const result = {};
846
+ let object = expression.namedChildren.find((child) => child.type === 'object');
847
+ if (!object) {
848
+ const collectionValue = expression.namedChildren.find((child) => child.type === 'collection_value');
849
+ object = collectionValue?.namedChildren.find((child) => child.type === 'object') ?? undefined;
850
+ }
851
+ if (!object)
852
+ return result;
853
+ for (const operatorElement of object.namedChildren) {
854
+ if (operatorElement.type !== 'object_elem')
855
+ continue;
856
+ const operator = this.#getObjectElemKey(operatorElement);
857
+ if (!operator)
858
+ continue;
859
+ const expressions = operatorElement.namedChildren.filter((child) => child.type === 'expression');
860
+ const valueExpressionession = expressions.length >= 2 ? expressions[1] : null;
861
+ if (!valueExpressionession) {
862
+ result[operator] = {};
863
+ continue;
864
+ }
865
+ let innerObject = valueExpressionession.namedChildren.find((child) => child.type === 'object');
866
+ if (!innerObject) {
867
+ const collectionValue = valueExpressionession.namedChildren.find((child) => child.type === 'collection_value');
868
+ innerObject = collectionValue?.namedChildren.find((child) => child.type === 'object') ?? undefined;
869
+ }
870
+ if (!innerObject) {
871
+ result[operator] = {};
872
+ continue;
873
+ }
874
+ const keys = {};
875
+ for (const keyElement of innerObject.namedChildren) {
876
+ if (keyElement.type !== 'object_elem')
877
+ continue;
878
+ const conditionKey = this.#getObjectElemKey(keyElement);
879
+ const keyExpressionessions = keyElement.namedChildren.filter((child) => child.type === 'expression');
880
+ const keyValueExpression = keyExpressionessions.length >= 2 ? keyExpressionessions[1] : null;
881
+ if (conditionKey && keyValueExpression)
882
+ keys[conditionKey] = this.#readExpressionStringValues(keyValueExpression);
883
+ }
884
+ result[operator] = keys;
885
+ }
886
+ return result;
887
+ }
888
+ }