@greenpandastudios/aug-cli 0.19.0 → 0.20.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 (459) hide show
  1. package/README.md +9 -6
  2. package/THIRD_PARTY_NOTICES.md +4 -0
  3. package/bin/aug.mjs +12 -2
  4. package/docs/about.md +27 -0
  5. package/docs/api/crypto.md +103 -69
  6. package/docs/api/io.md +35 -33
  7. package/docs/api/json.md +3 -3
  8. package/docs/api/memory.md +23 -19
  9. package/docs/api/time.md +10 -9
  10. package/docs/api/web.md +33 -38
  11. package/docs/compatibility.md +3 -3
  12. package/docs/contributing-benchmarks.md +38 -0
  13. package/docs/dev-containers.md +95 -0
  14. package/docs/diagnostics.md +15 -5
  15. package/docs/docker.md +174 -12
  16. package/docs/editor.md +35 -0
  17. package/docs/example-projects.json +206 -24
  18. package/docs/examples/approved-design/counters.md +34 -126
  19. package/docs/examples/approved-design/dependencies/august/0.20.1/io/contracts.md +178 -0
  20. package/docs/examples/approved-design/domain/app.md +13 -77
  21. package/docs/examples/approved-design/domain/export.md +5 -19
  22. package/docs/examples/approved-design/domain/models.md +4 -23
  23. package/docs/examples/approved-design/domain/numbers.md +24 -114
  24. package/docs/examples/approved-design/index.md +16 -7
  25. package/docs/examples/approved-design/main.md +19 -96
  26. package/docs/examples/benchmark/index.md +6 -5
  27. package/docs/examples/benchmark/main.md +7 -35
  28. package/docs/examples/cli-args/index.md +6 -5
  29. package/docs/examples/cli-args/main.md +6 -31
  30. package/docs/examples/collections/index.md +6 -5
  31. package/docs/examples/collections/main.md +7 -35
  32. package/docs/examples/collections-benchmark/index.md +6 -5
  33. package/docs/examples/collections-benchmark/main.md +7 -35
  34. package/docs/examples/cpu-benchmark/index.md +6 -5
  35. package/docs/examples/cpu-benchmark/main.md +5 -24
  36. package/docs/examples/developer-workflow/calculator.md +39 -186
  37. package/docs/examples/developer-workflow/dependencies/august/0.20.1/io/contracts.md +178 -0
  38. package/docs/examples/developer-workflow/index.md +16 -7
  39. package/docs/examples/developer-workflow/logging/console.md +10 -56
  40. package/docs/examples/developer-workflow/logging/export.md +4 -14
  41. package/docs/examples/developer-workflow/logging/logger.md +7 -43
  42. package/docs/examples/developer-workflow/main.md +17 -69
  43. package/docs/examples/drop/index.md +6 -5
  44. package/docs/examples/drop/main.md +7 -27
  45. package/docs/examples/drop/resource.md +7 -30
  46. package/docs/examples/errors/errors.md +7 -27
  47. package/docs/examples/errors/index.md +6 -5
  48. package/docs/examples/errors/main.md +7 -28
  49. package/docs/examples/ffi/index.md +6 -5
  50. package/docs/examples/ffi/main.md +6 -20
  51. package/docs/examples/ffi/native.md +8 -34
  52. package/docs/examples/generic-di/dependencies/august/0.20.1/io/contracts.md +178 -0
  53. package/docs/examples/generic-di/index.md +6 -5
  54. package/docs/examples/generic-di/main.md +9 -39
  55. package/docs/examples/generic-di/types.md +23 -92
  56. package/docs/examples/generics/index.md +6 -5
  57. package/docs/examples/generics/main.md +10 -47
  58. package/docs/examples/generics/types.md +25 -100
  59. package/docs/examples/hello/app/export.md +4 -12
  60. package/docs/examples/hello/app/greeter.md +13 -91
  61. package/docs/examples/hello/dependencies/august/0.20.1/io/contracts.md +178 -0
  62. package/docs/examples/hello/index.md +17 -6
  63. package/docs/examples/hello/logging/console.md +10 -54
  64. package/docs/examples/hello/logging/export.md +4 -14
  65. package/docs/examples/hello/logging/logger.md +7 -45
  66. package/docs/examples/hello/main.md +9 -39
  67. package/docs/examples/http-benchmark/index.md +6 -5
  68. package/docs/examples/http-benchmark/main.md +6 -20
  69. package/docs/examples/http-benchmark/routes.md +9 -31
  70. package/docs/examples/index.md +46 -29
  71. package/docs/examples/interceptors/app.md +20 -139
  72. package/docs/examples/interceptors/dependencies/august/0.20.1/io/contracts.md +178 -0
  73. package/docs/examples/interceptors/index.md +6 -5
  74. package/docs/examples/interceptors/interceptors.md +24 -148
  75. package/docs/examples/interceptors/logging.md +13 -76
  76. package/docs/examples/interceptors/main.md +10 -65
  77. package/docs/examples/json-benchmark/data.md +4 -20
  78. package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  79. package/docs/examples/json-benchmark/index.md +7 -5
  80. package/docs/examples/json-benchmark/main-yaml.md +20 -0
  81. package/docs/examples/json-benchmark/main.md +10 -49
  82. package/docs/examples/new-syntax/console.md +10 -52
  83. package/docs/examples/new-syntax/dependencies/august/0.20.1/io/contracts.md +178 -0
  84. package/docs/examples/new-syntax/greeter.md +13 -71
  85. package/docs/examples/new-syntax/index.md +6 -5
  86. package/docs/examples/new-syntax/logger.md +7 -43
  87. package/docs/examples/new-syntax/main.md +10 -53
  88. package/docs/examples/new-syntax/math.md +6 -24
  89. package/docs/examples/oidc-login/client/contracts.md +10 -61
  90. package/docs/examples/oidc-login/client/endpoints.md +32 -154
  91. package/docs/examples/oidc-login/client/export.md +5 -23
  92. package/docs/examples/oidc-login/client/login.md +234 -344
  93. package/docs/examples/oidc-login/client/logout.md +38 -143
  94. package/docs/examples/oidc-login/client/protocol.md +183 -304
  95. package/docs/examples/oidc-login/client/session.md +41 -149
  96. package/docs/examples/oidc-login/client/views.md +13 -58
  97. package/docs/examples/oidc-login/common/export.md +6 -26
  98. package/docs/examples/oidc-login/common/headers.md +42 -72
  99. package/docs/examples/oidc-login/common/keys.md +40 -164
  100. package/docs/examples/oidc-login/common/settings.md +24 -40
  101. package/docs/examples/oidc-login/common/views.md +7 -28
  102. package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
  103. package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  104. package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
  105. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
  106. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
  107. package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
  108. package/docs/examples/oidc-login/index.md +8 -7
  109. package/docs/examples/oidc-login/main-yaml.md +7 -0
  110. package/docs/examples/oidc-login/main.md +26 -153
  111. package/docs/examples/oidc-login/provider/authorization.md +232 -275
  112. package/docs/examples/oidc-login/provider/contracts.md +24 -146
  113. package/docs/examples/oidc-login/provider/credentials.md +24 -57
  114. package/docs/examples/oidc-login/provider/discovery.md +48 -122
  115. package/docs/examples/oidc-login/provider/export.md +11 -37
  116. package/docs/examples/oidc-login/provider/token.md +159 -237
  117. package/docs/examples/oidc-login/provider/userinfo.md +47 -102
  118. package/docs/examples/oidc-login/provider/views.md +13 -53
  119. package/docs/examples/ownership/counter.md +17 -63
  120. package/docs/examples/ownership/index.md +6 -5
  121. package/docs/examples/ownership/main.md +7 -30
  122. package/docs/examples/ownership-transfer/dependencies/august/0.20.1/io/contracts.md +178 -0
  123. package/docs/examples/ownership-transfer/index.md +6 -5
  124. package/docs/examples/ownership-transfer/main.md +10 -52
  125. package/docs/examples/ownership-transfer/resource.md +15 -67
  126. package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
  127. package/docs/examples/packages-app/index.md +7 -6
  128. package/docs/examples/packages-app/main.md +7 -25
  129. package/docs/examples/packages-math/aug-package-json.md +1 -1
  130. package/docs/examples/packages-math/index.md +7 -6
  131. package/docs/examples/packages-math/src/arithmetic.md +12 -50
  132. package/docs/examples/packages-math/src/export.md +4 -12
  133. package/docs/examples/startup-benchmark/index.md +6 -5
  134. package/docs/examples/startup-benchmark/main.md +5 -17
  135. package/docs/examples/visibility/counter.md +19 -67
  136. package/docs/examples/visibility/index.md +6 -5
  137. package/docs/examples/visibility/main.md +7 -31
  138. package/docs/examples/weather-api/forecasts.md +168 -0
  139. package/docs/examples/weather-api/index.md +42 -0
  140. package/docs/examples/weather-api/main-yaml.md +21 -0
  141. package/docs/examples/weather-api/main.md +65 -0
  142. package/docs/examples.json +10 -0
  143. package/docs/getting-started.md +105 -2
  144. package/docs/grammar.md +6 -4
  145. package/docs/guides/change-a-module.md +64 -0
  146. package/docs/guides/index.md +27 -0
  147. package/docs/index.md +51 -29
  148. package/docs/language-conformance.md +1 -1
  149. package/docs/language-constructs.md +22 -22
  150. package/docs/language-design-audit.md +1 -1
  151. package/docs/learn/data-and-errors.md +77 -0
  152. package/docs/learn/index.md +30 -0
  153. package/docs/learn/modules-and-dependencies.md +73 -0
  154. package/docs/learn/state-and-tests.md +71 -0
  155. package/docs/learn/values-and-functions.md +62 -0
  156. package/docs/lesson-failures.json +8 -0
  157. package/docs/maintaining-docs.md +16 -4
  158. package/docs/packages.md +72 -126
  159. package/docs/performance.md +13 -41
  160. package/docs/production-readiness.md +5 -4
  161. package/docs/public/downloads/approved-design.zip +0 -0
  162. package/docs/public/downloads/benchmark.zip +0 -0
  163. package/docs/public/downloads/cli-args.zip +0 -0
  164. package/docs/public/downloads/collections-benchmark.zip +0 -0
  165. package/docs/public/downloads/collections.zip +0 -0
  166. package/docs/public/downloads/cpu-benchmark.zip +0 -0
  167. package/docs/public/downloads/developer-workflow.zip +0 -0
  168. package/docs/public/downloads/drop.zip +0 -0
  169. package/docs/public/downloads/errors.zip +0 -0
  170. package/docs/public/downloads/ffi.zip +0 -0
  171. package/docs/public/downloads/generic-di.zip +0 -0
  172. package/docs/public/downloads/generics.zip +0 -0
  173. package/docs/public/downloads/hello.zip +0 -0
  174. package/docs/public/downloads/http-benchmark.zip +0 -0
  175. package/docs/public/downloads/interceptors.zip +0 -0
  176. package/docs/public/downloads/json-benchmark.zip +0 -0
  177. package/docs/public/downloads/new-syntax.zip +0 -0
  178. package/docs/public/downloads/oidc-login.zip +0 -0
  179. package/docs/public/downloads/ownership-transfer.zip +0 -0
  180. package/docs/public/downloads/ownership.zip +0 -0
  181. package/docs/public/downloads/packages-app.zip +0 -0
  182. package/docs/public/downloads/packages-math.zip +0 -0
  183. package/docs/public/downloads/startup-benchmark.zip +0 -0
  184. package/docs/public/downloads/visibility.zip +0 -0
  185. package/docs/public/downloads/weather-api.zip +0 -0
  186. package/docs/reference.md +23 -17
  187. package/docs/releasing.md +29 -15
  188. package/docs/research/code-to-natural-language.md +108 -0
  189. package/docs/research/ecosystem-workflow.md +41 -0
  190. package/docs/research/wiki-editorial-design.md +71 -0
  191. package/docs/roadmap.md +1 -1
  192. package/docs/specifications.md +27 -11
  193. package/docs/testing.md +19 -5
  194. package/docs/tooling.md +25 -12
  195. package/docs/weather-api.md +65 -0
  196. package/docs/web.md +50 -18
  197. package/docs/writing-docs.md +49 -0
  198. package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  199. package/examples/approved-design/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  200. package/examples/approved-design/.aug-spec/manifest.json +3 -3
  201. package/examples/approved-design/counters.aug +5 -4
  202. package/examples/approved-design/counters.aug.md +25 -132
  203. package/examples/approved-design/domain/app.aug +2 -1
  204. package/examples/approved-design/domain/app.aug.md +10 -80
  205. package/examples/approved-design/domain/export.aug +1 -0
  206. package/examples/approved-design/domain/export.aug.md +4 -20
  207. package/examples/approved-design/domain/models.aug +1 -0
  208. package/examples/approved-design/domain/models.aug.md +3 -25
  209. package/examples/approved-design/domain/numbers.aug +3 -2
  210. package/examples/approved-design/domain/numbers.aug.md +19 -116
  211. package/examples/approved-design/main.aug +1 -0
  212. package/examples/approved-design/main.aug.md +12 -95
  213. package/examples/benchmark/.aug-spec/manifest.json +1 -1
  214. package/examples/benchmark/main.aug +1 -0
  215. package/examples/benchmark/main.aug.md +6 -36
  216. package/examples/cli-args/.aug-spec/manifest.json +1 -1
  217. package/examples/cli-args/main.aug +1 -0
  218. package/examples/cli-args/main.aug.md +5 -32
  219. package/examples/collections/.aug-spec/manifest.json +1 -1
  220. package/examples/collections/main.aug +1 -0
  221. package/examples/collections/main.aug.md +6 -36
  222. package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  223. package/examples/developer-workflow/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  224. package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
  225. package/examples/developer-workflow/calculator.aug +3 -2
  226. package/examples/developer-workflow/calculator.aug.md +28 -189
  227. package/examples/developer-workflow/logging/console.aug +2 -1
  228. package/examples/developer-workflow/logging/console.aug.md +7 -57
  229. package/examples/developer-workflow/logging/export.aug +1 -0
  230. package/examples/developer-workflow/logging/export.aug.md +3 -15
  231. package/examples/developer-workflow/logging/logger.aug +1 -0
  232. package/examples/developer-workflow/logging/logger.aug.md +6 -46
  233. package/examples/developer-workflow/main.aug +1 -0
  234. package/examples/developer-workflow/main.aug.md +10 -68
  235. package/examples/drop/.aug-spec/manifest.json +1 -1
  236. package/examples/drop/main.aug +1 -0
  237. package/examples/drop/main.aug.md +6 -28
  238. package/examples/drop/resource.aug +1 -0
  239. package/examples/drop/resource.aug.md +6 -34
  240. package/examples/errors/.aug-spec/manifest.json +1 -1
  241. package/examples/errors/errors.aug +2 -1
  242. package/examples/errors/errors.aug.md +4 -27
  243. package/examples/errors/main.aug +1 -0
  244. package/examples/errors/main.aug.md +6 -29
  245. package/examples/ffi/.aug-spec/manifest.json +1 -1
  246. package/examples/ffi/main.aug +1 -0
  247. package/examples/ffi/main.aug.md +5 -21
  248. package/examples/ffi/native.aug +2 -1
  249. package/examples/ffi/native.aug.md +5 -35
  250. package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  251. package/examples/generic-di/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  252. package/examples/generic-di/.aug-spec/manifest.json +3 -3
  253. package/examples/generic-di/main.aug +1 -0
  254. package/examples/generic-di/main.aug.md +8 -40
  255. package/examples/generic-di/types.aug +3 -2
  256. package/examples/generic-di/types.aug.md +18 -97
  257. package/examples/generics/.aug-spec/manifest.json +1 -1
  258. package/examples/generics/main.aug +1 -0
  259. package/examples/generics/main.aug.md +9 -48
  260. package/examples/generics/types.aug +4 -3
  261. package/examples/generics/types.aug.md +18 -104
  262. package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
  263. package/examples/hello/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  264. package/examples/hello/.aug-spec/manifest.json +3 -3
  265. package/examples/hello/app/export.aug +1 -0
  266. package/examples/hello/app/export.aug.md +3 -13
  267. package/examples/hello/app/greeter.aug +2 -1
  268. package/examples/hello/app/greeter.aug.md +10 -94
  269. package/examples/hello/logging/console.aug +2 -1
  270. package/examples/hello/logging/console.aug.md +7 -55
  271. package/examples/hello/logging/export.aug +1 -0
  272. package/examples/hello/logging/export.aug.md +3 -15
  273. package/examples/hello/logging/logger.aug +1 -0
  274. package/examples/hello/logging/logger.aug.md +6 -48
  275. package/examples/hello/main.aug +1 -0
  276. package/examples/hello/main.aug.md +8 -40
  277. package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  278. package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  279. package/examples/interceptors/.aug-spec/manifest.json +3 -3
  280. package/examples/interceptors/app.aug +3 -2
  281. package/examples/interceptors/app.aug.md +15 -141
  282. package/examples/interceptors/interceptors.aug +3 -2
  283. package/examples/interceptors/interceptors.aug.md +19 -152
  284. package/examples/interceptors/logging.aug +2 -1
  285. package/examples/interceptors/logging.aug.md +10 -79
  286. package/examples/interceptors/main.aug +1 -0
  287. package/examples/interceptors/main.aug.md +9 -66
  288. package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  289. package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  290. package/examples/new-syntax/.aug-spec/manifest.json +3 -3
  291. package/examples/new-syntax/console.aug +2 -1
  292. package/examples/new-syntax/console.aug.md +7 -53
  293. package/examples/new-syntax/greeter.aug +2 -1
  294. package/examples/new-syntax/greeter.aug.md +10 -74
  295. package/examples/new-syntax/logger.aug +1 -0
  296. package/examples/new-syntax/logger.aug.md +6 -46
  297. package/examples/new-syntax/main.aug +1 -0
  298. package/examples/new-syntax/main.aug.md +9 -54
  299. package/examples/new-syntax/math.aug +2 -1
  300. package/examples/new-syntax/math.aug.md +3 -24
  301. package/examples/oidc-login/.aug-spec/manifest.json +13 -13
  302. package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
  303. package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
  304. package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
  305. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
  306. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
  307. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
  308. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
  309. package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
  310. package/examples/oidc-login/aug.lock.json +100 -0
  311. package/examples/oidc-login/client/contracts.aug +1 -0
  312. package/examples/oidc-login/client/contracts.aug.md +9 -66
  313. package/examples/oidc-login/client/endpoints.aug +6 -5
  314. package/examples/oidc-login/client/endpoints.aug.md +13 -145
  315. package/examples/oidc-login/client/export.aug +1 -0
  316. package/examples/oidc-login/client/export.aug.md +4 -24
  317. package/examples/oidc-login/client/login.aug +7 -6
  318. package/examples/oidc-login/client/login.aug.md +25 -303
  319. package/examples/oidc-login/client/logout.aug +5 -4
  320. package/examples/oidc-login/client/logout.aug.md +13 -135
  321. package/examples/oidc-login/client/protocol.aug +7 -6
  322. package/examples/oidc-login/client/protocol.aug.md +36 -283
  323. package/examples/oidc-login/client/session.aug +5 -4
  324. package/examples/oidc-login/client/session.aug.md +12 -139
  325. package/examples/oidc-login/client/views.aug +3 -2
  326. package/examples/oidc-login/client/views.aug.md +8 -57
  327. package/examples/oidc-login/common/export.aug +1 -0
  328. package/examples/oidc-login/common/export.aug.md +5 -27
  329. package/examples/oidc-login/common/headers.aug +4 -3
  330. package/examples/oidc-login/common/headers.aug.md +9 -67
  331. package/examples/oidc-login/common/keys.aug +6 -5
  332. package/examples/oidc-login/common/keys.aug.md +29 -165
  333. package/examples/oidc-login/common/settings.aug +2 -1
  334. package/examples/oidc-login/common/settings.aug.md +5 -39
  335. package/examples/oidc-login/common/views.aug +2 -1
  336. package/examples/oidc-login/common/views.aug.md +4 -28
  337. package/examples/oidc-login/main.aug +6 -16
  338. package/examples/oidc-login/main.aug.md +17 -146
  339. package/examples/oidc-login/main.yaml +7 -0
  340. package/examples/oidc-login/provider/authorization.aug +7 -6
  341. package/examples/oidc-login/provider/authorization.aug.md +23 -238
  342. package/examples/oidc-login/provider/contracts.aug +1 -0
  343. package/examples/oidc-login/provider/contracts.aug.md +23 -158
  344. package/examples/oidc-login/provider/credentials.aug +3 -2
  345. package/examples/oidc-login/provider/credentials.aug.md +9 -53
  346. package/examples/oidc-login/provider/discovery.aug +4 -3
  347. package/examples/oidc-login/provider/discovery.aug.md +11 -118
  348. package/examples/oidc-login/provider/export.aug +1 -0
  349. package/examples/oidc-login/provider/export.aug.md +6 -34
  350. package/examples/oidc-login/provider/token.aug +6 -5
  351. package/examples/oidc-login/provider/token.aug.md +16 -204
  352. package/examples/oidc-login/provider/userinfo.aug +4 -3
  353. package/examples/oidc-login/provider/userinfo.aug.md +10 -92
  354. package/examples/oidc-login/provider/views.aug +3 -2
  355. package/examples/oidc-login/provider/views.aug.md +8 -52
  356. package/examples/ownership/.aug-spec/manifest.json +1 -1
  357. package/examples/ownership/counter.aug +3 -2
  358. package/examples/ownership/counter.aug.md +12 -66
  359. package/examples/ownership/main.aug +1 -0
  360. package/examples/ownership/main.aug.md +6 -31
  361. package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
  362. package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
  363. package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
  364. package/examples/ownership-transfer/main.aug +1 -0
  365. package/examples/ownership-transfer/main.aug.md +9 -53
  366. package/examples/ownership-transfer/resource.aug +2 -1
  367. package/examples/ownership-transfer/resource.aug.md +12 -71
  368. package/examples/packages/app/.aug-spec/manifest.json +1 -1
  369. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
  370. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
  371. package/examples/packages/app/main.aug +1 -0
  372. package/examples/packages/app/main.aug.md +6 -26
  373. package/examples/packages/math/.aug-spec/manifest.json +1 -1
  374. package/examples/packages/math/aug-package.json +1 -1
  375. package/examples/packages/math/src/arithmetic.aug +2 -1
  376. package/examples/packages/math/src/arithmetic.aug.md +9 -51
  377. package/examples/packages/math/src/export.aug +1 -0
  378. package/examples/packages/math/src/export.aug.md +3 -13
  379. package/examples/visibility/.aug-spec/manifest.json +1 -1
  380. package/examples/visibility/counter.aug +4 -3
  381. package/examples/visibility/counter.aug.md +12 -68
  382. package/examples/visibility/main.aug +1 -0
  383. package/examples/visibility/main.aug.md +6 -32
  384. package/examples/weather-api/.aug-spec/manifest.json +8 -0
  385. package/examples/weather-api/AGENTS.md +17 -0
  386. package/examples/weather-api/README.md +19 -0
  387. package/examples/weather-api/forecasts.aug +47 -0
  388. package/examples/weather-api/forecasts.aug.md +32 -0
  389. package/examples/weather-api/main.aug +4 -0
  390. package/examples/weather-api/main.aug.md +15 -0
  391. package/examples/weather-api/main.yaml +5 -0
  392. package/examples/weather-api/weather.http +5 -0
  393. package/package.json +3 -4
  394. package/scripts/bootstrap-native.mjs +181 -106
  395. package/scripts/native-setup.mjs +98 -0
  396. package/scripts/native-toolchain.mjs +28 -0
  397. package/src/builtins.js +1 -1
  398. package/src/checker.js +259 -72
  399. package/src/cli.js +114 -20
  400. package/src/codegen.js +1 -1
  401. package/src/config.js +1 -1
  402. package/src/contracts.js +10 -0
  403. package/src/editor.js +71 -16
  404. package/src/fixes.js +90 -2
  405. package/src/formatter.js +19 -8
  406. package/src/git-packages.js +110 -0
  407. package/src/help.js +24 -23
  408. package/src/http-contracts.js +14 -0
  409. package/src/http-policies.js +5 -5
  410. package/src/libraries.js +1 -1
  411. package/src/lsp.js +14 -5
  412. package/src/native.js +19 -13
  413. package/src/navigation.js +4 -2
  414. package/src/openapi.js +5 -4
  415. package/src/package-locking.js +45 -0
  416. package/src/package-manager.js +251 -67
  417. package/src/parser.js +13 -5
  418. package/src/policies.js +3 -3
  419. package/src/project-init.js +78 -4
  420. package/src/project.js +9 -7
  421. package/src/semantic.js +46 -2
  422. package/src/snippets.js +59 -0
  423. package/src/spec-hints.js +56 -0
  424. package/src/spec-tree.js +241 -0
  425. package/src/spec.js +626 -303
  426. package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
  427. package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
  428. package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
  429. package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
  430. package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
  431. package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
  432. package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
  433. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
  434. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
  435. package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
  436. package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
  437. package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
  438. package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
  439. package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
  440. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  441. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  442. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  443. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  444. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  445. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  446. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  447. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  448. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
  449. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
  450. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
  451. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
  452. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
  453. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
  454. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  455. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  456. /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
  457. /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  458. /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  459. /package/examples/oidc-login/.aug-spec/{august/0.19.0/time → packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
package/src/formatter.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { typeName } from "./ast.js";
2
2
  import { lex } from "./lexer.js";
3
3
  import { parse } from "./parser.js";
4
+ import { importSource } from "./git-packages.js";
4
5
  /** Canonical syntax comes from the parsed program; comments stay with their lexical owner. */
5
6
  export function formatFile(project, file) {
6
7
  return printFile(project, file, false);
@@ -43,7 +44,7 @@ function printFile(project, file, migrate) {
43
44
  if (!value || typeof value !== 'object')
44
45
  return value;
45
46
  const node = value;
46
- return Object.fromEntries(Object.entries(node).filter(([key, value]) => !['span', 'nameSpan', 'sourceSpan'].includes(key) && value !== undefined)
47
+ return Object.fromEntries(Object.entries(node).filter(([key, value]) => !['span', 'nameSpan', 'sourceSpan', 'headerEnd'].includes(key) && value !== undefined)
47
48
  .sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => [key, shape(value)]));
48
49
  };
49
50
  if (JSON.stringify(shape(parsed.file.items)) !== JSON.stringify(shape(verified.file.items)))
@@ -67,7 +68,15 @@ class Printer {
67
68
  this.indent = project.config.block_style === 'indent';
68
69
  this.assign = project.config.assignment === 'to' ? 'to' : '=';
69
70
  }
70
- line(text = '') { this.lines.push(text ? this.step.repeat(this.level) + text : ''); }
71
+ line(text = '') {
72
+ this.lines.push(...text.split('\n').map(line => line ? this.step.repeat(this.level) + line : ''));
73
+ }
74
+ delimited(open, values, close, trailing = '') {
75
+ const flat = open + values.join(', ') + trailing + close;
76
+ if (!values.length || (!flat.includes('\n') && flat.length <= 80 - this.level * 4))
77
+ return flat;
78
+ return open + '\n' + values.map(value => this.step + value.replaceAll('\n', '\n' + this.step)).join(',\n') + trailing + '\n' + close;
79
+ }
71
80
  before(offset, parentColumn) {
72
81
  while (this.comments[0]?.span.start < offset) {
73
82
  if (parentColumn !== undefined && this.comments[0].span.column <= parentColumn)
@@ -123,7 +132,7 @@ class Printer {
123
132
  this.annotations(method.annotations);
124
133
  const header = `${method.endpoint ? `endpoint ${method.endpoint.method} ${JSON.stringify(method.endpoint.path)} as ` : ''}${method.fixture ? 'fixture ' : ''}${method.externC ? 'extern C ' + (method.valueAbi ? 'value ' : '') + (method.nativePure ? 'pure ' : '') : ''}${method.name}${this.generics(method)}` +
125
134
  `(${method.params.map(param => this.param(param)).join(', ')})` +
126
- (method.returns.name !== 'void' ? ` ${method.endpoint?.streams ? 'streams' : 'returns'} ${method.returnOwnership === 'own' ? 'own ' : ''}${typeName(method.returns)}` : '') +
135
+ (method.returns.name !== 'void' || method.declared?.returns ? ` ${method.endpoint?.streams ? 'streams' : 'returns'} ${method.returnOwnership === 'own' ? 'own ' : ''}${typeName(method.returns)}` : '') +
127
136
  (method.endpoint && method.endpoint.status !== 200 ? ` with status ${method.endpoint.status}` : '') +
128
137
  (method.changes?.length ? ` changes ${method.changes.join(' and ')}` : '') +
129
138
  (method.uses?.length ? ` uses ${method.uses.map(use => `${use.source}.${use.operation}`).join(' and ')}` : '') +
@@ -159,14 +168,16 @@ class Printer {
159
168
  value = `resolve ${expr.name}` + (expr.typeArgs.length ? '<' + expr.typeArgs.map(typeName).join(', ') + '>' : '');
160
169
  else if (expr.kind === 'member')
161
170
  value = `${this.expression(expr.object, 8)}.${expr.name}`;
162
- else if (expr.kind === 'call')
163
- value = this.expression(expr.callee, 8) + (expr.typeArgs.length ? '<' + expr.typeArgs.map(typeName).join(', ') + '>' : '') +
164
- '(' + expr.args.map((arg, index) => (expr.argLabels[index] ? expr.argLabels[index] + '=' : '') + this.expression(arg)).join(', ') + this.inline(expr.span.end) + ')';
171
+ else if (expr.kind === 'call') {
172
+ const open = this.expression(expr.callee, 8) + (expr.typeArgs.length ? '<' + expr.typeArgs.map(typeName).join(', ') + '>' : '') + '(';
173
+ const values = expr.args.map((arg, index) => (expr.argLabels[index] ? expr.argLabels[index] + '=' : '') + this.expression(arg));
174
+ value = this.delimited(open, values, ')', this.inline(expr.span.end));
175
+ }
165
176
  else if (expr.kind === 'collection') {
166
177
  const open = expr.collection === 'List' ? '[' : expr.collection === 'Tuple' ? '(' : '{';
167
178
  const close = open === '[' ? ']' : open === '(' ? ')' : '}';
168
179
  const values = expr.collection === 'Map' ? expr.items.filter((_, index) => index % 2 === 0).map((item, index) => `${this.expression(item)}: ${this.expression(expr.items[index * 2 + 1])}`) : expr.items.map(item => this.expression(item));
169
- value = open + values.join(', ') + (expr.collection === 'Tuple' && values.length === 1 ? ',' : '') + this.inline(expr.span.end) + close;
180
+ value = this.delimited(open, values, close, (expr.collection === 'Tuple' && values.length === 1 ? ',' : '') + this.inline(expr.span.end));
170
181
  }
171
182
  else if (expr.kind === 'unary') {
172
183
  const power = expr.op === '!' ? 2.5 : 7;
@@ -232,7 +243,7 @@ class Printer {
232
243
  item(item) {
233
244
  this.before('annotations' in item ? item.annotations?.[0]?.span.start ?? item.span.start : item.span.start);
234
245
  if (item.kind === 'import') {
235
- this.line(`import ${item.everything ? 'everything' : item.names.join(' and ')} from ${item.from.join('.')}`);
246
+ this.line(`import ${item.everything ? 'everything' : item.names.join(' and ')} from ${importSource(item.from)}`);
236
247
  }
237
248
  else if (item.kind === 'export')
238
249
  this.line('export ' + (item.folder ? 'folder ' + item.name : `${item.name} from ${item.from}`));
@@ -0,0 +1,110 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { spawnSync } from 'node:child_process';
6
+ import { withPackageLock } from "./package-locking.js";
7
+ export const isGitSource = (value) => /^(?:https:\/\/|git\+(?:https|file):\/\/)/.test(value);
8
+ export const sourceAlias = (value) => 'url_' + createHash('sha256').update(value).digest('hex').slice(0, 20);
9
+ export const importSource = (parts) => (isGitSource(parts[0]) ? JSON.stringify(parts[0]) : parts[0]) + parts.slice(1).map(part => '.' + part).join('');
10
+ /** A repository URL can select a tag and, on GitHub, a folder within the repository. */
11
+ export function gitReference(request) {
12
+ try {
13
+ if (decodeURIComponent(request.split('#')[0]).split(/[\\/]/).some(part => part === '.' || part === '..'))
14
+ throw new Error('Repository URLs cannot contain path traversal.');
15
+ }
16
+ catch {
17
+ throw new Error('Invalid repository URL or path traversal.');
18
+ }
19
+ let url;
20
+ try {
21
+ url = new URL(request.replace(/^git\+/, ''));
22
+ }
23
+ catch {
24
+ throw new Error(`Invalid package repository URL: ${request}`);
25
+ }
26
+ if (!['https:', 'file:'].includes(url.protocol) || url.username || url.password || url.search ||
27
+ url.protocol === 'file:' && !request.startsWith('git+file:'))
28
+ throw new Error('Use a public HTTPS repository URL without credentials, or git+file:///PATH for a local Git repository.');
29
+ const revision = decodeURIComponent(url.hash.slice(1)) || 'HEAD';
30
+ url.hash = '';
31
+ let folder = '', ref = revision;
32
+ if (url.hostname === 'github.com') {
33
+ const parts = url.pathname.split('/').filter(Boolean).map(decodeURIComponent);
34
+ if (parts.length < 2)
35
+ throw new Error('A GitHub package URL needs an owner and repository.');
36
+ if (parts[2] === 'tree') {
37
+ if (!parts[3] || revision !== 'HEAD')
38
+ throw new Error('Choose the revision with /tree/TAG/FOLDER or #TAG, not both.');
39
+ ref = parts[3];
40
+ folder = parts.slice(4).join('/');
41
+ }
42
+ else
43
+ folder = parts.slice(2).join('/');
44
+ url.pathname = '/' + parts.slice(0, 2).join('/').replace(/\.git$/, '') + '.git';
45
+ }
46
+ if (!/^[A-Za-z0-9][A-Za-z0-9._/+-]*$/.test(ref) || ref.includes('..') || ref.endsWith('/'))
47
+ throw new Error('Package revision must be a commit, tag, or branch name.');
48
+ if (folder.split('/').some(part => part === '..' || part === '.' || part.startsWith('_')) || folder.includes('\\'))
49
+ throw new Error('Package folders must stay inside the repository and cannot be private.');
50
+ return { request, repository: url.href, revision: ref, folder };
51
+ }
52
+ function git(args, cwd) {
53
+ const result = spawnSync(process.env.AUG_GIT ?? 'git', ['-c', 'core.hooksPath=/dev/null', ...args], {
54
+ cwd, timeout: 120000, maxBuffer: 32 * 1024 * 1024, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' }
55
+ });
56
+ if (result.error)
57
+ throw new Error(`Cannot read a Git package: ${result.error.message}. Install Git or set AUG_GIT to its executable.`);
58
+ if (result.status !== 0)
59
+ throw new Error(`Cannot read a Git package: ${result.stderr.toString().trim()}. Check the repository URL and revision; private repositories are outside this workflow.`);
60
+ return result.stdout;
61
+ }
62
+ /** Read source blobs without checking out files, executing hooks, or following repository symlinks. */
63
+ export function materializeGit(request, destination, offline, locked) {
64
+ const reference = gitReference(request);
65
+ if (locked && (locked.repository !== reference.repository || locked.folder !== reference.folder || locked.revision !== reference.revision ||
66
+ !/^[a-f0-9]{40,64}$/.test(locked.commit)))
67
+ throw new Error('Git package lock has an invalid repository, folder, or commit.');
68
+ const cache = resolve(process.env.AUG_PACKAGE_CACHE ?? join(homedir(), '.cache', 'augscript', 'packages'));
69
+ const repository = join(cache, sourceAlias(reference.repository));
70
+ mkdirSync(cache, { recursive: true });
71
+ return withPackageLock(repository + '.lock', () => {
72
+ if (!existsSync(repository)) {
73
+ if (offline)
74
+ throw new Error(`Git package is not cached: ${request}. Run aug run online once before using --offline.`);
75
+ git(['init', '--bare', repository]);
76
+ }
77
+ let commit = locked?.commit;
78
+ const objectExists = commit && spawnSync(process.env.AUG_GIT ?? 'git', ['--git-dir', repository, 'cat-file', '-e', commit + '^{commit}']).status === 0;
79
+ if (!objectExists) {
80
+ if (offline)
81
+ throw new Error(`Git revision is not cached: ${commit ?? request}. Restore the package cache or run aug run online.`);
82
+ git(['--git-dir', repository, 'fetch', '--no-tags', '--depth=1', '--', reference.repository, commit ?? reference.revision]);
83
+ commit = git(['--git-dir', repository, 'rev-parse', 'FETCH_HEAD^{commit}']).toString().trim();
84
+ }
85
+ const result = { ...reference, commit: commit };
86
+ const prefix = reference.folder ? reference.folder + '/' : '';
87
+ const listing = git(['--git-dir', repository, 'ls-tree', '-rz', '--full-tree', result.commit, '--', prefix || '.']).toString();
88
+ let bytes = 0, count = 0;
89
+ for (const entry of listing.split('\0').filter(Boolean)) {
90
+ const match = /^(\d+) blob ([a-f0-9]+)\t([\s\S]+)$/.exec(entry);
91
+ if (!match || !match[3].startsWith(prefix))
92
+ continue;
93
+ const file = match[3].slice(prefix.length);
94
+ if (!file.endsWith('.aug') && !['aug-package.json', 'package.json', 'main.yaml', 'README.md', 'LICENSE'].includes(file))
95
+ continue;
96
+ if (!['100644', '100755'].includes(match[1]) || file.includes('\\') || file.split('/').some(part => !part || part === '..' || part.startsWith('.')))
97
+ throw new Error(`Git package source must be regular files inside its folder: ${file}`);
98
+ const contents = git(['--git-dir', repository, 'cat-file', 'blob', match[2]]);
99
+ bytes += contents.length;
100
+ if (++count > 10000 || bytes > 32 * 1024 * 1024)
101
+ throw new Error('Git source package exceeds 10,000 files or 32 MiB.');
102
+ const path = join(destination, file);
103
+ mkdirSync(dirname(path), { recursive: true });
104
+ writeFileSync(path, contents);
105
+ }
106
+ if (!count)
107
+ throw new Error(`No August source at ${request}. Choose the folder containing export.aug or aug-package.json.`);
108
+ return result;
109
+ });
110
+ }
package/src/help.js CHANGED
@@ -4,9 +4,9 @@ const type = (detail, documentation) => ({ detail, documentation, category: 'typ
4
4
  const fn = (detail, documentation) => ({ detail, documentation, category: 'function' });
5
5
  const operator = (detail, documentation) => ({ detail, documentation, category: 'operator' });
6
6
  export const languageHelp = {
7
- RequireLogin: { category: 'tag', detail: '[RequireLogin(authentication=auth)]', documentation: 'Verify credentials before typed body decoding. Map auth to an explicit resolve Authentication parameter and declare uses auth.authenticate. null produces 401; the adapter validates the credential. HTTP policies precede custom parameter interceptors.' },
7
+ RequireLogin: { category: 'tag', detail: '[RequireLogin(authentication=auth)]', documentation: 'Verify credentials before typed body decoding. Map auth to an explicit resolve Authentication parameter and infer its authenticate operation. null produces 401; the adapter validates the credential. HTTP policies precede custom parameter interceptors.' },
8
8
  RequirePermission: { category: 'tag', detail: '[RequirePermission(authentication=auth, authorization=permissions, permission="users.read")]', documentation: 'Authenticate the request and authorize one literal permission before decoding. Both dependencies are explicit resolve parameters; declare their authenticate and authorize effects. Missing credentials produce 401 and a denied permission produces 403.' },
9
- LogRequest: { category: 'tag', detail: '[LogRequest(logger=logger)]', documentation: 'Map a resolve RequestLogger parameter and declare uses logger.complete. Observe the final status and monotonic duration after output finishes, or status 499 on disconnect. Layers complete in reverse written order.' },
9
+ LogRequest: { category: 'tag', detail: '[LogRequest(logger=logger)]', documentation: 'Map a resolve RequestLogger parameter and infer its complete operation. Observe the final status and monotonic duration after output finishes, or status 499 on disconnect. Layers complete in reverse written order.' },
10
10
  RateLimit: { category: 'tag', detail: '[RateLimit(requests=100, seconds=60)]', documentation: 'A bounded per-endpoint, per-peer fixed-window request limit. Uses the transport peer address, never an untrusted forwarding header. Rejected requests return 429 before body decoding. The table has 2048 entries and rejects new identities when full.' },
11
11
  Timeout: { category: 'tag', detail: '[Timeout(milliseconds=5000)]', documentation: 'Bound the request and its streaming producer with a monotonic deadline. Before output, return 504. After headers, terminate the stream. Cancellation joins children and runs always cleanup; native C operations finish before cancellation can be observed.' },
12
12
  Cors: { category: 'tag', detail: '[Cors(origins=["https://example.test"], headers=["content-type"], credentials=true)]', documentation: 'Allow exact literal HTTP(S) origins and explicit request header names. OPTIONS preflight checks the selected method and headers. Wildcard origins cannot use credentials. Valid responses include CORS and Vary headers; disallowed origins return 403.' },
@@ -38,15 +38,15 @@ export const languageHelp = {
38
38
  Task: type('Task<T>', 'A child computation owned by a scope. wait for reads its result; the scope joins children before releasing dependencies.'),
39
39
  Shared: type('Shared<T>', 'Synchronized mutable state. Construction takes a fresh or owned value. Read and mutate the value only through lock shared as state. A child borrowing an owned Shared<T> pins the wrapper until it finishes; the parent cannot move it into another owner while the child uses it.'),
40
40
  Bytes: type('Bytes', 'Immutable length-aware binary data. text() validates UTF-8; base64url() emits canonical unpadded URL-safe base64.'),
41
- Json: type('Json', 'Immutable JSON data. Parse with august.json, decode concrete records with decode<T>(), and stringify with lossless integer handling.'),
41
+ Json: type('Json', 'Immutable JSON data. Import parse from the JSON source package, decode concrete records with decode<T>(), and stringify with lossless integer handling.'),
42
42
  Html: type('Html', 'Checked server markup produced with JSX elements and components. Interpolated text and attributes are escaped automatically.'),
43
43
  HttpAction: type('HttpAction', 'An immutable deferred HTTP call created with handle endpoint(...). Bind it to a form onSubmit or button onClick. The browser sends the request; endpoint dependencies and application logic run on the server.'),
44
44
  ServerEvent: type('ServerEvent<T>', 'One SSE event containing concrete JSON data, plus optional id, event, and retry milliseconds. CR, LF and NUL are rejected in metadata. The endpoint streams ServerEvent<T> and yields each event under transport backpressure.'),
45
45
  Headers: type('Headers', 'Immutable HTTP fields. with adds a checked field; get and all read case-insensitively. Duplicate Set-Cookie values remain separate.'),
46
46
  HttpRequest: type('HttpRequest', 'A request supplied through from request. Its method, path, headers and bounded body are explicit. form<T>() allows protocol-specific form errors.'),
47
47
  HttpResponse: type('HttpResponse<T>', 'A typed HTTP body with explicit status and headers. HttpResponse(body=value, status=201, headers=headers) constructs a response. Status literals range from 200 to 599; a dynamic status requires handling or declaring HttpError.'),
48
- record: keyword('record Point(int x, int y)', 'Declare deeply immutable data with labeled construction and structural equality/hashing. Records contain primitives, tuples and other records. An initialize block validates inputs; declare rejected inputs with unless ErrorType.'),
49
- initialize: keyword('initialize: ...', 'Run constructor work once after header inputs and local fields are initialized, before returning the class or record. Put this block inside the declaration, before class methods. Construction stays pure. Records can validate inputs and raise declared unless errors, but cannot replace immutable fields.'),
48
+ record: keyword('record Point(int x, int y)', 'Declare deeply immutable data with labeled construction and structural equality/hashing. Records contain primitives, tuples and other records. An initialize block validates inputs; validation infers rejected inputs; an explicit unless ErrorType limits permitted failures.'),
49
+ initialize: keyword('initialize: ...', 'Run constructor work once after header inputs and local fields are initialized, before returning the class or record. Put this block inside the declaration, before class methods. Construction stays pure. Records can validate inputs and raise checked errors, but cannot replace immutable fields.'),
50
50
  fixture: keyword('fixture example() returns Data: ...', 'Declare reusable test data through an ordinary checked function. Other files must import the fixture explicitly. Its dependencies and capabilities follow the same header contract rules as other functions.'),
51
51
  for: keyword('for item in items: ...', 'Traverse a List, Set, homogeneous Tuple, or Map. Map entries are tuples, so for (key, value) in map unpacks them. Iteration snapshots the collection in insertion order and gives elements read-only access.'),
52
52
  match: keyword('match value: when ...', 'Choose a checked case. Cover true and false for bool, null and some for nullable values, or add else. Concrete class cases narrow the named value. Duplicate and unreachable cases are rejected.'),
@@ -57,14 +57,14 @@ export const languageHelp = {
57
57
  scope: keyword('scope: ...', 'Create a local DI and child-task lifetime. Children join before dependencies are reclaimed; unhandled failures cancel siblings. Scoped references cannot escape. Nested scopes have independent caches.'),
58
58
  composition: keyword('composition Services: implement Logger with Adapter', 'Group static bindings behind an explicitly imported module declaration. Include the composition in main before executable statements; its own file must import every referenced contract and implementation.'),
59
59
  include: keyword('include Services', 'Expand an explicitly imported composition into the application root. Duplicate bindings and dependency cycles are checked after all includes are collected.'),
60
- IndexError: type('IndexError implements Error', 'Checked failure for an invalid List.get position. Catch it, declare unless IndexError, or use List.at for a nullable lookup.'),
60
+ IndexError: type('IndexError implements Error', 'Checked failure for an invalid List.get position. Catch it or let it propagate. List.at returns a value or null instead.'),
61
61
  ArithmeticError: type('ArithmeticError implements Error', 'Checked failure for division by zero. int arithmetic otherwise wraps in the signed 64-bit range.'),
62
- ConversionError: type('ConversionError implements Error', 'Checked failure when c_int(value=number) cannot fit the signed 32-bit C int range. Catch it or declare unless ConversionError.'),
62
+ ConversionError: type('ConversionError implements Error', 'Checked failure when c_int(value=number) cannot fit the signed 32-bit C int range. Catch it or let it propagate.'),
63
63
  c_int: type('c_int', 'Signed 32-bit C int. Convert explicitly with c_int(value=number), which raises ConversionError on overflow. It widens to int without loss. AugScript int maps to int64_t at the C boundary.'),
64
64
  interceptor: keyword('interceptor Name<T>(resolve Dependency dependency) { around(...) returns T { ... } }', 'Declare a reusable wrapper for functions, methods, or class construction. Apply it with `[Name]` or `[Name(y=x)]`. Inputs match target labels automatically; explicit mappings rename them. Tags enter in written order and results unwind in reverse. Each layer creates a fresh instance; dependencies are forwarded from the target header. Effective contracts include every layer\u2019s changes, capabilities, errors, and dependencies. Generic types are inferred from the target. Interceptors follow normal imports, exports, and underscore privacy.'),
65
- around: fn('around(Type input) returns Type { return next(); }', 'The required entry point of an interceptor. Its parameters select target arguments, and its result must fit the target return type. Omit `returns` for void. It may validate, override mapped arguments, inspect the result, throw a checked error, or return early. Declare generic parameters on the interceptor header. Helper methods can be declared alongside around.'),
65
+ around: fn('around(Type input) returns Type { return next(); }', 'The required entry point of an interceptor. Its parameters select target arguments, and its result must fit the target return type. A forwarding body can omit returns and inherit the target result. It may validate, override mapped arguments, inspect the result, throw a checked error, or return early. Declare generic parameters on the interceptor header. Helper methods can be declared alongside around.'),
66
66
  next: fn('next(mappedLabel=value) returns TargetResult', 'Continue to the next interceptor layer or the original function/constructor. Available only inside an interceptor around body. `next()` forwards original arguments unchanged; optional labeled overrides use the interceptor parameter names and map back to the target. Unselected arguments are forwarded automatically. The compiler requires at most one next call on each execution path. Target errors propagate through the chain; additional errors declared by around become checked errors of the tagged callable.'),
67
- import: keyword('import Logger and ConsoleLogger from logging', 'Bring public declarations into this file. Use `and` for several names, or `import everything from logging` for all public sibling declarations or folder exports. Imported dependencies are never re-exported implicitly. Names or modules starting with `_` stay private. A sibling module uses its filename without `.aug`; a folder exposes only names listed in `export.aug`.'),
67
+ import: keyword('import Logger and ConsoleLogger from logging', 'Bring public declarations into this file. Use `and` for several names, or `import everything from logging` for all public sibling declarations or folder exports. Imported dependencies are never re-exported implicitly. Names or modules starting with `_` stay private. A sibling module uses its filename without `.aug`; a folder exposes only names listed in `export.aug`. A quoted public repository URL declares a source dependency; `aug run` installs it and locks its commit. Use `aug add URL --as NAME` for a shorter import alias.'),
68
68
  and: keyword('left and right', 'Logical AND on bool values. Skip the right operand when the left operand is false. Also join named imports, checked errors, contracts, and grouped task waits. Comparisons and not bind before and; and binds before or.'),
69
69
  or: keyword('left or right', 'Logical OR on bool values. Skip the right operand when the left operand is true. This is the lowest-precedence boolean operator. Symbolic || is rejected.'),
70
70
  not: keyword('not count == 0', 'Negate a bool expression. Comparisons bind before not, so not count == 0 means not (count == 0). not binds before and and or. Use parentheses to negate only one comparison operand. Symbolic ! is rejected; != remains inequality.'),
@@ -75,10 +75,10 @@ export const languageHelp = {
75
75
  pass: keyword('pass', 'An empty body. Use it inside an indented interface, class, function, or statement block. It performs no operation. Empty braced blocks may use {} instead.'),
76
76
  in: keyword('interface Consumer<in T>', 'Declare a contravariant interface type parameter. It may occur only in checked input positions. User-defined types are otherwise invariant. The same word is used by for iteration.'),
77
77
  out: keyword('interface Producer<out T>', 'Declare a covariant interface type parameter. It may occur only in checked output positions. Mutable containers are invariant; classes and interceptors cannot declare variance.'),
78
- changes: keyword('increment() changes self', 'Declare observable mutation of self or a borrowed input. Callers must provide mutable access. Ordinary functions and methods are pure by default; changing a local variable or a fresh local object does not change caller-owned state.'),
79
- uses: keyword('save(resolve FileWriter files, string path) uses files.write unless FileError', 'Declare the external capability operations this callable may use. Interfaces, public standalone functions, default methods and interceptor around methods keep explicit contracts. Class implementations and private helpers infer uses when omitted; hover, explain and API docs show the result. An explicit uses clause remains an upper bound. Effects are checked through calls and interceptor layers; implementations cannot exceed their interface contract. changes and unless remain explicit, and construction stays pure.'),
80
- mutable: keyword('Counter(mutable int initial to _count)', 'Declare mutable class storage. Header fields are otherwise read-only after construction. An explicit public argument label can initialize private storage with Type label to _field. Mutating methods declare changes self and callers provide mutable access.'),
81
- capability: keyword('capability Console { write(string value) uses Console.write }', 'Declare an interface for an external effect. Import the standard Console, FileReader, FileWriter and Arguments contracts from august.io, select adapters in main, and receive them through resolve parameters. Operations remain visible in uses clauses and can be replaced in tests.'),
78
+ changes: keyword('increment() changes self', 'Describe observable mutation of self or a borrowed input. Bodies infer changes when omitted; callers still need mutable access. Bodyless interface contracts declare permitted mutation. Local variables and fresh local objects do not change caller-owned state. An explicit clause limits the body.'),
79
+ uses: keyword('save(resolve FileWriter files, string path)', 'Bodies infer external capability operations when uses is omitted, including public functions, default methods and interceptor around methods. The editor shows non-editable inline hints; hover, explain, API docs and compiled specs expose checked contracts. Bodyless interfaces and extern declarations keep explicit contracts. An explicit uses clause remains an upper bound. Implementations cannot exceed their interface contract; construction and cleanup stay pure.'),
80
+ mutable: keyword('Counter(mutable int initial to _count)', 'Declare mutable class storage. Header fields are otherwise read-only after construction. An explicit public argument label can initialize private storage with Type label to _field. Bodies infer changes self; callers provide mutable access.'),
81
+ capability: keyword('capability Console { write(string value) uses Console.write }', 'Declare an interface for an external effect. Import the standard Console, FileReader, FileWriter and Arguments contracts from august.io, select adapters in main, and receive them through resolve parameters. Operations stay visible in inferred hints, hover and specs and can be replaced in tests.'),
82
82
  from: keyword('import Name from module;', 'Names the source of an import or export. Dotted paths cross folders; each crossed folder must expose the next one with `export folder child;`. A module starting with `_` is private.'),
83
83
  export: keyword('export Name from sibling;', 'Expose a public sibling declaration to other folders. Names, modules, and folders starting with `_` are private and cannot be exported. Export declarations belong only in `export.aug`.\n\n```aug\nexport Logger from logger;\n```'),
84
84
  folder: keyword('export folder child;', 'Expose a public child folder through the current folder’s `export.aug`. A folder starting with `_` cannot be exported.'),
@@ -91,12 +91,12 @@ export const languageHelp = {
91
91
  interface: keyword('interface Name extends Parent { ... }', 'Declare a contract. Interfaces may extend several interfaces and may provide default method bodies. A class must implement every method without a default. Method signatures start with their name, for example `log(string message);`.'),
92
92
  implements: keyword('Name() implements Interface { ... }', 'Marks a declaration as a class and lists the interfaces it satisfies. Every class needs at least one interface. Method signatures must match. Conflicting default implementations require an override. Put constructor work in an initialize block inside the class.'),
93
93
  extends: keyword('interface Child extends Parent, Other { ... }', 'Inherit methods from one or more interfaces. Class inheritance is not supported.'),
94
- function: keyword('No function keyword', 'Functions and methods start with their name: `greet(string name) { ... }` or `greet(string name) returns string;`. Remove the old `function` prefix. Parameters use `Type name` order and callers use labels. Omit `returns` for a `void` result.'),
95
- returns: keyword('name() returns Type', 'Specify a function or method return type. Without this clause, the result is `void`; the body may end without `return` or use `return;`. Returning a value requires a declared return type. `returns own Type` transfers ownership to the caller.'),
94
+ function: keyword('No function keyword', 'Functions and methods start with their name: greet(string name) { ... }. Remove the old function prefix. Parameters use Type name order and callers use labels. Bodies infer omitted returns, changes, uses and unless clauses; declarations without a body keep explicit contracts.'),
95
+ returns: keyword('name() returns Type', 'Bodies infer their result from return expressions or their implemented interface when this clause is omitted. No returned value means void. Bodyless signatures still need non-void result types. Explicit result types are checked assertions; returns own Type explicitly transfers ownership. Recursive or ambiguous results may require a type anchor.'),
96
96
  return: keyword('return expression;', 'Finish the current function or method and give its result to the caller. A `void` function can use `return;`.'),
97
- unless: keyword('load(bool fail) returns string unless FileError', 'Declare checked failures a function may raise instead of returning its result. Callers must catch the failures or declare them with unless too. Separate several types with `and` or commas; `unless Error` accepts any error type. The statement that raises an error remains `throw`.'),
97
+ unless: keyword('load(bool fail) unless FileError', 'Describe checked failures that escape a call. Bodies infer uncaught errors when unless is omitted; catch blocks remove handled errors. Main must handle escaping errors. Bodyless interfaces declare permitted failures. Explicit unless remains an upper bound; unless Error accepts any error type. Record validation can infer its failures too.'),
98
98
  throws: keyword('Use unless', 'This old error-contract spelling is rejected. Replace `throws FileError` with `unless FileError`. Javadoc `@throws` remains supported.'),
99
- throw: keyword('throw error;', 'Raise a value whose class implements `Error`. The enclosing function must declare the error or the call must be handled by a matching `catch`.'),
99
+ throw: keyword('throw error;', 'Raise a value whose class implements `Error`. An executable body infers uncaught errors; main must handle them with a matching catch.'),
100
100
  try: keyword('try { ... } catch Error error { ... }', 'Run statements that may throw checked errors. Add a `catch` for each error, or use `catch Error` for any throwable error.'),
101
101
  catch: keyword('catch Error error { ... }', 'Handle a thrown error from the preceding `try` block. The caught value is available under the name after its type.'),
102
102
  if: keyword('if condition: ...', 'Run a block when its condition is bool. Use braces or a trailing colon and an indented body. Tabs or spaces are accepted; mixed indentation prefixes are rejected.'),
@@ -105,7 +105,7 @@ export const languageHelp = {
105
105
  own: keyword('own Type name to expression;', 'Give a value exclusive ownership and deterministic cleanup at scope exit. Owned values cannot be copied; they can move into `own` parameters, fields, or returns. `=` is also accepted.\n\n```aug\nown Resource resource to Resource();\n```'),
106
106
  borrow: keyword('borrow value { ... }', 'Take exclusive mutable access for the duration of this block. Ordinary reads need no borrow. Managed List, Set, and Map mutations require one. Starting a child that reads the value suspends this mutation right until wait for the child.\n\n```aug\nborrow items { items.append(value=1) }\n```'),
107
107
  unsafe: keyword('unsafe { ... }', 'Permit calls to declared `extern C` functions within this block. The compiler does not verify the safety of foreign code.'),
108
- extern: keyword('extern C name(Type arg) returns Type', 'Declare a C function. Calls require unsafe and external callables declare uses C.name. int maps to int64_t, c_int to signed 32-bit int, float to double, bool to C bool, and string to a temporary UTF-8 const char pointer. Foreign code must respect the declared ABI and cannot retain managed pointers.'),
108
+ extern: keyword('extern C name(Type arg) returns Type', 'Declare a C function. Calls require unsafe and executable callers infer uses C.name. int maps to int64_t, c_int to signed 32-bit int, float to double, bool to C bool, and string to a temporary UTF-8 const char pointer. Foreign code must respect the declared ABI and cannot retain managed pointers.'),
109
109
  C: keyword('extern C name(...);', 'Selects C as the foreign function interface for an `extern` declaration.'),
110
110
  true: keyword('true', 'Boolean true. Conditions and logical operators require `bool`.'),
111
111
  false: keyword('false', 'Boolean false. and and or evaluate the right side only when needed. Conditions require bool values.'),
@@ -116,7 +116,7 @@ export const languageHelp = {
116
116
  string: type('string', 'Immutable valid Unicode encoded as UTF-8, without embedded NUL. Invalid literals are compile errors and invalid text files raise FileError. The + operator joins strings. C string pointers live only for the unsafe call.'),
117
117
  void: type('void', 'No return value. A function can omit `returns void`.'),
118
118
  Error: type('Error', 'Root throwable interface. User defined error classes implement `Error`; `catch Error` handles any throwable type.'),
119
- FileError: type('FileError', 'Built in checked error from text file operations. Catch it or declare `unless FileError`.'),
119
+ FileError: type('FileError', 'Checked failure from text file operations. Catch it or let it propagate.'),
120
120
  List: type('List<T>', 'Ordered collection: `[1, 2]` infers List<int>. A typed declaration supplies empty or nested literal types: `List<int> numbers = []`. `List<T>(...)` also accepts positional elements. `append(value=...)` requires mutable access; `get(index=...)` reads; `length()` returns its size.'),
121
121
  Set: type('Set<T>', 'Hash set of unique values: `{1, 2, 1}` infers Set<int> with two items. Use `Set<int> numbers = {}` or `Set<int>()` for an empty set. `add(value=...)` requires mutable access; `contains(value=...)` and `length()` read. Primitive values and immutable tuples use value equality; other objects use identity.'),
122
122
  Tuple: type('Tuple<T1, T2, ...>', 'Fixed immutable positions: `(1, 2)` infers Tuple<int, int>, `(1, "apple")` infers Tuple<int, string>. `(1)` is grouping, `(1,)` is a singleton tuple, and `()` is empty. `get(index=0)` requires a constant index so its result type is known. `length()` reads its size. Tuples compare by their items; contained objects remain managed references.'),
@@ -170,9 +170,9 @@ for (const operation of builtinFunctions)
170
170
  (operation.errors?.length ? ` unless ${operation.errors.join(' and ')}` : ''), operation.documentation);
171
171
  export const diagnosticHelp = {
172
172
  SYNTAX: 'Use word boolean operators, initialize blocks, optional Type, implement with, and resolve Key to name. The editor migration fix or aug migrate --write upgrades rejected legacy spellings while preserving grouping.',
173
- NATIVE: 'The native C toolchain reported an error at this AugScript source location. Check the external C declaration, linker configuration, and generated .aug-build/program.c; debug builds retain source line mapping.',
173
+ NATIVE: 'The C compiler reported an error at this August location. Check the external C declaration and main.yaml libraries/library_paths. Native commands prepare required pinned libraries automatically. Missing system tools include installation help. If valid August code fails without an external C boundary, report the compiler output and generated .aug-build/program.c.',
174
174
  CONFIG: 'main.yaml uses the documented scalar settings and list settings. Duplicate keys, unsupported values, and unknown lint rules are errors during check.',
175
- PACKAGE: 'Declare an import alias in main.yaml packages (or aug-package.json dependencies for a library), then run aug install. Commit aug.lock.json; use --frozen in CI. Imports cross only export.aug boundaries. Installed sources and compiler versions must match the lock; build/check never fetch packages.',
175
+ PACKAGE: 'Import directly from a quoted public repository URL, or use aug add URL --as NAME to declare an alias in main.yaml. aug run prepares declared application packages; aug install prepares them explicitly. Commit aug.lock.json and use aug install --frozen in CI. Changed installed sources require an explicit reinstall. Imports cross only export.aug boundaries. Installed sources and compiler versions must match the lock; build/check never fetch source packages.',
176
176
  MODULE: 'Keep imports acyclic and follow main.yaml module_dependencies. strict_modules also requires sibling public imports to appear in export.aug.',
177
177
  LINT: 'Optional project policies point out hidden dependencies, discarded errors, and growing public surfaces. Enable individual rules in main.yaml lint.',
178
178
  DOC: 'Javadoc @param names use public input labels. @return requires a value-returning callable; @throws names an unless error. Enable public_docs for missing-documentation warnings.',
@@ -182,8 +182,9 @@ export const diagnosticHelp = {
182
182
  ITERATION: 'for traverses a List, Set, Map, or homogeneous Tuple. Use tuple destructuring for map entries and heterogeneous tuples.',
183
183
  NUMBER: 'int is signed 64-bit with defined wrapping arithmetic. Integer literal spelling is exact. Float literals must be finite.',
184
184
  TEXT: 'Strings contain valid Unicode encoded as UTF-8, without NUL. Binary data needs an explicit unsafe adapter.',
185
- EFFECT: 'Public function and interface contracts explicitly declare uses capability.operation. Implementations and private helpers infer omitted uses, while explicit clauses remain upper bounds. Declare changes for mutation and unless for errors. Receive dependencies in resolve header parameters; constructors and cleanup remain pure. Inferred effects cannot exceed an implemented interface or hold a lock during I/O.',
186
- MUTABILITY: 'Class storage is read-only after construction unless marked mutable. Managed function inputs grant reading; use a borrow parameter and a changes contract to mutate them. Public read-only fields do not grant mutable access through aliases.',
185
+ EFFECT: 'Bodies infer capability use and mutation. Bodyless interfaces declare permitted effects; explicit clauses remain upper bounds. Receive dependencies in resolve header parameters. Inferred effects cannot exceed an implemented interface, grant mutation of managed inputs, add constructor I/O, or hold a lock during I/O.',
186
+ INFERENCE: 'Add a result or effect type anchor when recursion has no evidence or keeps expanding generic types. Bodies infer omitted contracts; bodyless and foreign declarations describe them explicitly.',
187
+ MUTABILITY: 'Class storage is read-only after construction unless marked mutable. Managed function inputs grant reading; use a borrow parameter to mutate them; bodies infer the changes contract. Public read-only fields do not grant mutable access through aliases.',
187
188
  GENERIC: 'Type arguments must be concrete at a call and consistent across labeled inputs. Mutable and user-defined types are invariant by default. Supply explicit type arguments when inputs do not determine them.',
188
189
  INDENT: 'Put the body after a trailing colon on the next line. Indent beyond its header, keep each block level consistent, and use tabs or spaces without mixing them in a prefix. Dedent to an enclosing level; use pass for an empty body.',
189
190
  COLLECTION: 'Use compatible item types or a declared collection type. Empty [] and {} need a contextual type. A tuple may contain different types; tuple.get needs a constant index.',
@@ -0,0 +1,14 @@
1
+ import { parse } from "./parser.js";
2
+ // These declarations describe the native policy ABI. Package names do not determine compatibility.
3
+ // Keep this schema aligned with the capabilities exported by the web library.
4
+ const source = `record Principal(string subject, List<string> permissions)
5
+ capability Authentication:
6
+ authenticate(HttpRequest request) returns optional Principal uses Authentication.authenticate unless HttpError
7
+ capability Authorization:
8
+ authorize(Principal identity, string permission) returns bool uses Authorization.authorize unless HttpError
9
+ capability RequestLogger:
10
+ complete(string method, string path, int status, int milliseconds) uses RequestLogger.complete
11
+ `;
12
+ export const nativeHttpContracts = new Map(parse('<native-http-contracts>', source).file.items
13
+ .filter(item => item.kind === 'interface' || item.kind === 'class')
14
+ .map(item => [item.name, item]));
@@ -10,10 +10,10 @@ export const httpPolicyOptions = {
10
10
  Cors: { origins: 'strings', headers: 'optional strings', credentials: 'optional bool' }, Compress: {},
11
11
  };
12
12
  export const httpPolicyOptionHelp = {
13
- authentication: 'Map an explicit resolve Authentication input. Declare uses input.authenticate. Missing identity returns 401 before wire decoding.',
14
- authorization: 'Map an explicit resolve Authorization input. Declare uses input.authorize. Denied permission returns 403.',
13
+ authentication: 'Map an explicit resolve Authentication input. The compiler infers input.authenticate. Missing identity returns 401 before wire decoding.',
14
+ authorization: 'Map an explicit resolve Authorization input. The compiler infers input.authorize. Denied permission returns 403.',
15
15
  permission: 'Literal nonempty permission checked by the authorization adapter.',
16
- logger: 'Map an explicit resolve RequestLogger input. Declare uses input.complete. The logger runs after completion or disconnect; put LogRequest first to observe rejected requests.',
16
+ logger: 'Map an explicit resolve RequestLogger input. The compiler infers input.complete. The logger runs after completion or disconnect; put LogRequest first to observe rejected requests.',
17
17
  requests: 'Literal request count per trusted transport peer and endpoint, from 1 to 1000000. Excess returns 429.',
18
18
  seconds: 'Literal fixed-window duration, from 1 to 86400 seconds.',
19
19
  milliseconds: 'Literal deadline from 1 to 3600000 milliseconds, covering handler, child tasks and response transport. Before output it returns 504; after output it closes the stream.',
@@ -44,10 +44,10 @@ export function checkHttpPolicy(annotation, fn, diagnostics, canonical) {
44
44
  if (entry.value || !param?.injected || param.type.name !== type || param.type.nullable || param.type.optional)
45
45
  report(`${name}.${entry.name} maps an explicit resolve ${type} endpoint parameter`);
46
46
  else if (!canonical(param, type))
47
- report(`${name}.${entry.name} requires the august.web ${type} capability`);
47
+ report(`${name}.${entry.name} requires a compatible ${type} capability from the web library`);
48
48
  else {
49
49
  dependencies[Object.keys(specs[name]).filter(key => specs[name][key].startsWith('dependency:')).indexOf(entry.name)] = index;
50
- if (!fn.uses?.some(effect => effect.source === param.name && effect.operation === operation))
50
+ if (fn.uses?.length && !fn.uses.some(effect => effect.source === param.name && effect.operation === operation))
51
51
  report(`Declare uses ${param.name}.${operation} for ${name}`);
52
52
  }
53
53
  continue;
package/src/libraries.js CHANGED
@@ -15,7 +15,7 @@ export function standardLibraries() {
15
15
  throw new Error(`August ${name} must match compiler ${version}; reinstall the CLI and its pinned libraries.`);
16
16
  return join(dirname(file), manifest.source);
17
17
  };
18
- return { root: load('stdlib'), modules: new Map([['web', load('web')], ['crypto', load('crypto')]]) };
18
+ return { root: load('stdlib'), modules: new Map() };
19
19
  }
20
20
  export function libraryChild(libraries, folder, name) {
21
21
  return folder === libraries.root ? libraries.modules.get(name) ?? join(folder, name) : join(folder, name);
package/src/lsp.js CHANGED
@@ -49,7 +49,7 @@ export async function runLanguageServer(root) {
49
49
  if (message.method === 'initialize')
50
50
  result = { capabilities: {
51
51
  textDocumentSync: { openClose: true, change: 1 }, hoverProvider: true, completionProvider: { triggerCharacters: ['.', '(', '=', ' '] },
52
- definitionProvider: true, documentFormattingProvider: true, codeActionProvider: true,
52
+ definitionProvider: true, documentFormattingProvider: true, codeActionProvider: true, inlayHintProvider: true,
53
53
  semanticTokensProvider: { legend: { tokenTypes, tokenModifiers: ['declaration'] }, full: true },
54
54
  }, serverInfo: { name: 'AugScript', version: compilerVersion() } };
55
55
  else if (message.method === 'shutdown')
@@ -92,7 +92,8 @@ export async function runLanguageServer(root) {
92
92
  const view = document(uri), offset = params.offset ?? 0;
93
93
  result = params.command === 'hover' ? view.hover(offset) ?? null : params.command === 'complete' ? view.complete(offset) :
94
94
  params.command === 'fixes' ? view.fixes() : params.command === 'semantic-tokens' ? view.tokens() :
95
- params.command === 'format' ? view.format() : params.command === 'definition' ? view.definition(offset) ?? null : params.command === 'diagnostics' ? view.diagnostics.map(issue => ({ ...issue, help: diagnosticHelp[issue.code] })) : view.describe(params.options);
95
+ params.command === 'inlay-hints' ? view.inlayHints(params.options?.start, params.options?.end) :
96
+ params.command === 'format' ? view.format() : params.command === 'definition' ? view.definition(offset) ?? null : params.command === 'diagnostics' ? view.diagnostics.map(issue => ({ ...issue, help: diagnosticHelp[issue.code] })) : view.describe(params.options);
96
97
  }
97
98
  else if (message.method.startsWith('textDocument/')) {
98
99
  const view = document(params.textDocument.uri);
@@ -101,11 +102,18 @@ export async function runLanguageServer(root) {
101
102
  const hover = view.hover(offset);
102
103
  result = hover ? { contents: { kind: 'markdown', value: `\`\`\`augscript\n${hover.detail}\n\`\`\`\n\n${hover.documentation ?? ''}` } } : null;
103
104
  }
105
+ else if (message.method === 'textDocument/inlayHint')
106
+ result = view.inlayHints(params.range ? offsetAt(view.source, params.range.start) : undefined, params.range ? offsetAt(view.source, params.range.end) : undefined).map(hint => ({
107
+ position: positionAt(view.source, hint.offset), label: hint.label, kind: 1,
108
+ paddingLeft: true, tooltip: { kind: 'markdown', value: hint.tooltip },
109
+ }));
104
110
  else if (message.method === 'textDocument/completion')
105
111
  result = view.complete(offset).map(item => ({ label: item.label,
106
112
  kind: { method: 2, function: 3, variable: 6, class: 7, interface: 8, property: 10, keyword: 14, snippet: 15, type: 25 }[item.kind] ?? 6,
107
113
  detail: item.detail, documentation: { kind: 'markdown', value: item.documentation ?? '' }, insertText: item.insertText ?? item.label,
108
- insertTextFormat: item.kind === 'snippet' ? 2 : 1 }));
114
+ insertTextFormat: item.insertText ? 2 : 1, sortText: item.sortText,
115
+ textEdit: item.replacement ? { range: { start: positionAt(view.source, item.replacement.start), end: positionAt(view.source, item.replacement.end) }, newText: item.insertText ?? item.label } : undefined,
116
+ additionalTextEdits: item.additionalEdits?.map(edit => ({ range: { start: positionAt(view.source, edit.start), end: positionAt(view.source, edit.end) }, newText: edit.text })) }));
109
117
  else if (message.method === 'textDocument/definition') {
110
118
  const target = view.definition(offset);
111
119
  result = target ? { uri: pathToFileURL(target.file).href,
@@ -114,13 +122,14 @@ export async function runLanguageServer(root) {
114
122
  else if (message.method === 'textDocument/formatting')
115
123
  result = [{ range: { start: { line: 0, character: 0 }, end: positionAt(view.source, view.source.length) }, newText: view.format() }];
116
124
  else if (message.method === 'textDocument/codeAction')
117
- result = view.fixes().map(fix => {
125
+ result = view.fixes().filter(fix => !params.range || fix.issue.line - 1 >= params.range.start.line && fix.issue.line - 1 <= params.range.end.line).map(fix => {
118
126
  const changes = {};
119
127
  for (const edit of fix.edits) {
120
128
  const source = workspace.document(edit.file).source, uri = pathToFileURL(edit.file).href;
121
129
  (changes[uri] ??= []).push({ range: { start: positionAt(source, edit.start), end: positionAt(source, edit.end) }, newText: edit.text });
122
130
  }
123
- return { title: fix.title, kind: 'quickfix', edit: { changes } };
131
+ return { title: fix.title, kind: 'quickfix', isPreferred: fix.preferred, diagnostics: [{ code: fix.issue.code, message: fix.issue.message,
132
+ range: { start: { line: fix.issue.line - 1, character: fix.issue.column - 1 }, end: { line: fix.issue.line - 1, character: fix.issue.column } } }], edit: { changes } };
124
133
  });
125
134
  else if (message.method === 'textDocument/semanticTokens/full') {
126
135
  let line = 0, column = 0;
package/src/native.js CHANGED
@@ -6,6 +6,8 @@ import { createHash } from 'node:crypto';
6
6
  import { loadConfig } from "./config.js";
7
7
  import { generateOpenApi } from "./openapi.js";
8
8
  import { nativeHome } from '../scripts/native-home.mjs';
9
+ import { nativeRequirements } from '../scripts/native-setup.mjs';
10
+ import { cCompiler, compilerHelp } from '../scripts/native-toolchain.mjs';
9
11
  export function compileNative(root, generated, options = {}) {
10
12
  const config = loadConfig(root).config;
11
13
  const buildDir = join(root, '.aug-build', ...(options.testIndex === undefined ? [] : ['tests']));
@@ -27,38 +29,38 @@ export function compileNative(root, generated, options = {}) {
27
29
  copyFileSync(join(runtimeDir, 'aug_values.c'), valuesPath);
28
30
  const outputName = options.testIndex === undefined ? options.output ?? config.output ?? basename(root) : name;
29
31
  const output = isAbsolute(outputName) ? outputName : join(buildDir, outputName);
30
- const cc = process.env.CC ?? (existsSync('/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang') ?
31
- '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang' : 'clang');
32
+ mkdirSync(dirname(output), { recursive: true });
33
+ const cc = cCompiler();
32
34
  const release = options.release ?? config.optimization === 'release';
33
35
  const args = [release ? '-O2' : '-O0', '-g', '-std=c11', '-D_POSIX_C_SOURCE=200809L', '-Wall', '-Wextra',
34
36
  '-pthread',
35
37
  cPath, runtimePath, valuesPath, ...config.library_paths.map(path => `-L${resolve(root, path)}`), ...config.libraries.map(name => `-l${name}`), '-o', output];
36
- const web = generated.includes('aug_http_') || generated.includes('_aug_http_') || generated.includes('aug_headers_');
38
+ const needs = nativeRequirements(generated), web = needs.web;
37
39
  if (web)
38
40
  args.push('-DAUG_HTTP_RUNTIME');
39
- if (generated.includes('aug_html_') || web) {
41
+ if (needs.html) {
40
42
  const htmlSource = join(buildDir, 'aug_html.c');
41
43
  copyFileSync(join(runtimeDir, 'aug_html.c'), htmlSource);
42
44
  args.push(htmlSource);
43
45
  }
44
- if (generated.includes('_aug_time_')) {
46
+ if (needs.time) {
45
47
  const timeSource = join(buildDir, 'aug_time.c');
46
48
  copyFileSync(join(runtimeDir, 'aug_time.c'), timeSource);
47
49
  args.push(timeSource);
48
50
  }
49
- if (web || generated.includes('aug_task_')) {
51
+ if (needs.tasks) {
50
52
  const taskSource = join(buildDir, 'aug_tasks.c');
51
53
  copyFileSync(join(runtimeDir, 'aug_tasks.c'), taskSource);
52
54
  const minicoro = join(nativeRoot, 'sources', 'minicoro');
53
55
  if (!existsSync(join(minicoro, 'minicoro.h')))
54
- throw new Error('Task dependency is missing. Run the compiler scripts/bootstrap-native.mjs with --extract-only; AUG_NATIVE_HOME selects its directory.');
56
+ throw new Error('Task dependencies are missing. Run aug run to prepare them automatically, or use aug-native --extract-only --only minicoro to prewarm the cache.');
55
57
  args.push(taskSource, '-I' + minicoro, process.platform === 'darwin' ? '-D_DARWIN_C_SOURCE' : '-D_DEFAULT_SOURCE');
56
58
  }
57
- if (generated.includes('_aug_crypto_') || web) {
59
+ if (needs.crypto) {
58
60
  const prefix = join(nativeRoot, 'prefix');
59
61
  const manifestPath = join(prefix, 'aug-native-manifest.json');
60
62
  if (!existsSync(manifestPath))
61
- throw new Error('Native libraries are not ready. Run node scripts/bootstrap-native.mjs in the compiler directory; AUG_NATIVE_HOME selects its directory.');
63
+ throw new Error('Native libraries are not ready. Run aug run to prepare them automatically, or use aug-native to prewarm the cache.');
62
64
  const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
63
65
  if (manifest.platform !== process.platform || manifest.architecture !== process.arch)
64
66
  throw new Error(`Native dependencies target ${manifest.platform}/${manifest.architecture}; this compiler runs on ${process.platform}/${process.arch}. Build dependencies on this host.`);
@@ -74,12 +76,12 @@ export function compileNative(root, generated, options = {}) {
74
76
  args.push('-framework', 'CoreFoundation', '-framework', 'SystemConfiguration');
75
77
  }
76
78
  }
77
- if (generated.includes('_aug_json_') || generated.includes('aug_json_') || web) {
79
+ if (needs.json) {
78
80
  const jsonSource = join(buildDir, 'aug_json.c');
79
81
  copyFileSync(join(runtimeDir, 'aug_json.c'), jsonSource);
80
82
  const yyjson = join(nativeRoot, 'sources', 'yyjson', 'src');
81
83
  if (!existsSync(join(yyjson, 'yyjson.c')))
82
- throw new Error('JSON dependency is missing. Run node scripts/bootstrap-native.mjs --extract-only.');
84
+ throw new Error('JSON dependencies are missing. Run aug run to prepare them automatically, or use aug-native --extract-only --only yyjson to prewarm the cache.');
83
85
  args.push(jsonSource, join(yyjson, 'yyjson.c'), '-I' + yyjson);
84
86
  }
85
87
  const sdk = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk';
@@ -87,8 +89,12 @@ export function compileNative(root, generated, options = {}) {
87
89
  args.unshift('-isysroot', sdk);
88
90
  const compile = spawnSync(cc, args, { encoding: 'utf8', cwd: root });
89
91
  if (compile.error)
90
- throw compile.error;
91
- const error = compile.status === 0 ? '' : compile.stderr || compile.stdout || 'C compiler failed';
92
+ throw new Error(`Cannot compile the program with ${cc}: ${compile.error.message}.\n${compilerHelp()}`);
93
+ const detail = (compile.stderr || compile.stdout || (compile.signal ? `Compiler stopped by ${compile.signal}` : 'C compiler failed')).trim();
94
+ const error = compile.status === 0 ? '' : `Native compilation failed with ${cc}.\n${detail}\n` +
95
+ (/cannot find -l|library not found|file not found|No such file/.test(detail) ?
96
+ 'Check main.yaml libraries/library_paths and the named header or library. On Linux, HTTP also needs zlib development headers.\n' : '') +
97
+ `Generated C: ${cPath}\nIf this is valid August code without external C declarations, please report it with this compiler output.`;
92
98
  const diagnostics = [];
93
99
  for (const match of error.matchAll(/^(.+\.aug):(\d+):(\d+):\s*(?:fatal )?error:\s*(.+)$/gm))
94
100
  diagnostics.push({ file: match[1], line: Number(match[2]), column: Number(match[3]), code: 'NATIVE', message: match[4] });
package/src/navigation.js CHANGED
@@ -2,6 +2,7 @@ import { statSync } from 'node:fs';
2
2
  import { basename, dirname, join, resolve } from 'node:path';
3
3
  import { lex } from "./lexer.js";
4
4
  import { libraryChild } from "./libraries.js";
5
+ import { isGitSource, sourceAlias } from "./git-packages.js";
5
6
  function definitionTarget(def) {
6
7
  const span = def.node.kind === 'interceptor' ? def.node.nameSpan : def.node.span;
7
8
  return { name: def.name, file: def.file, line: span.line,
@@ -41,7 +42,8 @@ function importPathTarget(project, importer, from, name, segment) {
41
42
  return exportTarget(project, folder, name, segment < from.length - 1 ? from[segment + 1] : undefined);
42
43
  }
43
44
  const owner = importer.package ? project.packages.scopes.get(importer.package) : undefined;
44
- const dependency = owner ? project.packages.scopes.get(owner.dependencies[from[0]]) : project.packages.roots.get(from[0]);
45
+ const alias = isGitSource(from[0]) ? sourceAlias(from[0]) : from[0];
46
+ const dependency = owner ? project.packages.scopes.get(owner.dependencies[alias]) : project.packages.roots.get(alias);
45
47
  if (dependency) {
46
48
  const folder = join(dependency.sourceRoot, ...from.slice(1, segment + 1));
47
49
  return exportTarget(project, folder, name, segment < from.length - 1 ? from[segment + 1] : undefined);
@@ -128,7 +130,7 @@ export function definitionAt(project, fileName, offset) {
128
130
  entry.span.end <= item.span.end);
129
131
  const fromIndex = declarationTokens.findIndex(entry => entry.kind === 'from');
130
132
  const sourceTokens = declarationTokens.slice(fromIndex + 1)
131
- .filter(entry => entry.kind === 'identifier');
133
+ .filter(entry => entry.kind === 'identifier' || entry.kind === 'string');
132
134
  const segments = item.kind === 'import' ? item.from : [item.from];
133
135
  const selected = token.kind === 'from' ? segments.length - 1 :
134
136
  sourceTokens.findIndex((entry) => entry === token);