@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
@@ -0,0 +1,32 @@
1
+ <!-- Generated by aug spec. Edit the August source, then regenerate. -->
2
+
3
+ # `forecasts.aug`
4
+
5
+ Plain handler results default to HTTP 200 unless another status is declared. HttpResponse values choose their own status. Unhandled request failures return HTTP 500 and cancel the request tasks.
6
+
7
+ <a id="symbol-WeatherForecast"></a>
8
+ ## `WeatherForecast` · immutable record · [source](forecasts.aug#L3)
9
+
10
+ The JSON shape returned by the forecast endpoint. Temperatures use whole degrees. It takes `date` as a string, kept read-only, `temperatureC` and `temperatureF` as integers, kept read-only, and `summary` as a string, kept read-only.
11
+
12
+ <a id="symbol-weatherForecast"></a>
13
+ ## `weatherForecast` · [source](forecasts.aug#L6)
14
+
15
+ `weatherForecast` handles `GET /weatherforecast`. Return five simulated forecasts. Fixed data keeps the example and its tests reproducible. It returns a list of 5 [`WeatherForecast`](forecasts.aug.md#symbol-WeatherForecast) records, with `(date, temperatureC, temperatureF, summary)` values of `("2026-01-01", 0, 32, "Freezing")`, `("2026-01-02", 10, 50, "Cool")`, `("2026-01-03", 20, 68, "Mild")`, `("2026-01-04", 30, 86, "Warm")`, and `("2026-01-05", 35, 95, "Hot")`, in that order.
16
+
17
+ <a id="symbol-test weatherForecast client"></a>
18
+ ## `test weatherForecast client` · [source](forecasts.aug#L40)
19
+
20
+ Tests [`weatherForecast`](forecasts.aug.md#symbol-weatherForecast). Each case gets fresh setup and dependencies.
21
+
22
+ ### `forecasts`
23
+
24
+ #### `returns_json` · [source](forecasts.aug#L42)
25
+
26
+ It sets `response` to `client.request` with `method` `"GET"` and `path` `"/weatherforecast"`. The test requires `response.status` equals `200`.
27
+
28
+ #### `rejects_other_methods` · [source](forecasts.aug#L45)
29
+
30
+ It sets `response` to `client.request` with `method` `"POST"` and `path` `"/weatherforecast"`. The test requires `response.status` equals `405`.
31
+
32
+ Built-in operations follow the [language reference](https://greenpandastudios.github.io/augscript/language-constructs).
@@ -0,0 +1,4 @@
1
+ // aug-spec: "main.aug.md" explains this file. Read it before changes; refresh with aug spec.
2
+ import weatherForecast from forecasts
3
+
4
+ serve weatherForecast on port 8787
@@ -0,0 +1,15 @@
1
+ <!-- Generated by aug spec. Edit the August source, then regenerate. -->
2
+
3
+ # `main.aug`
4
+
5
+ ## HTTP configuration
6
+
7
+ Listen on `127.0.0.1`. Limit request bodies to 1048576 bytes and buffered responses to 4194304 bytes. Serve OpenAPI at `/openapi.json` and API docs at `/docs`.
8
+
9
+ ## Startup
10
+
11
+ It serves [`weatherForecast`](forecasts.aug.md#symbol-weatherForecast) on port `8787`.
12
+
13
+ ## Dependencies
14
+
15
+ It uses [`weatherForecast`](forecasts.aug.md#symbol-weatherForecast) from `forecasts`.
@@ -0,0 +1,5 @@
1
+ block_style: indent
2
+ openapi:
3
+ enabled: true
4
+ title: "Weather forecast API"
5
+ version: "0.1.0"
@@ -0,0 +1,5 @@
1
+ ### Five simulated forecasts
2
+ GET http://127.0.0.1:8787/weatherforecast
3
+
4
+ ### Generated OpenAPI document
5
+ GET http://127.0.0.1:8787/openapi.json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greenpandastudios/aug-cli",
3
- "version": "0.19.0",
3
+ "version": "0.20.1",
4
4
  "description": "August compiler, native build CLI, tests and language server",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,9 +23,8 @@
23
23
  "THIRD_PARTY_NOTICES.md"
24
24
  ],
25
25
  "dependencies": {
26
- "@greenpandastudios/aug-stdlib": "0.19.0",
27
- "@greenpandastudios/aug-web": "0.19.0",
28
- "@greenpandastudios/aug-crypto": "0.19.0"
26
+ "@greenpandastudios/aug-stdlib": "0.20.1",
27
+ "tar": "7.5.22"
29
28
  },
30
29
  "publishConfig": {
31
30
  "access": "public",
@@ -1,121 +1,196 @@
1
1
  #!/usr/bin/env node
2
2
  /** Build the pinned C dependencies privately; never install into system directories. */
3
3
  import { createHash } from 'node:crypto';
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync, openSync, closeSync } from 'node:fs';
5
- import { dirname, join, resolve } from 'node:path';
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, openSync, closeSync, renameSync, rmSync, statSync } from 'node:fs';
5
+ import { join, resolve } from 'node:path';
6
6
  import { spawnSync } from 'node:child_process';
7
7
  import { availableParallelism } from 'node:os';
8
8
  import { nativeHome } from './native-home.mjs';
9
+ import { cCompiler, requireBuildTool } from './native-toolchain.mjs';
10
+ import { dependencyArtifacts, dependencyReady } from './native-setup.mjs';
9
11
 
10
- const root = resolve(import.meta.dirname, '..');
11
- const lock = JSON.parse(readFileSync(join(import.meta.dirname, 'native-dependencies.lock.json'), 'utf8'));
12
- const extractOnly = process.argv.includes('--extract-only');
13
- const onlyIndex = process.argv.indexOf('--only');
14
- const selected = onlyIndex >= 0 ? process.argv[onlyIndex + 1]?.split(',') : undefined;
15
- if (onlyIndex >= 0 && (!extractOnly || !selected?.length || selected.some(name => !lock.dependencies.some(dependency => dependency.name === name))))
16
- throw new Error('--only requires --extract-only and comma-separated names from native-dependencies.lock.json.');
17
- const directory = nativeHome(root);
18
- const prefix = join(directory, 'prefix');
19
- const downloads = join(directory, 'downloads');
20
- const sources = join(directory, 'sources');
21
- const logs = join(directory, 'logs');
22
- for (const path of [prefix, downloads, sources, logs]) mkdirSync(path, { recursive: true });
23
- if (!extractOnly && !lock.platforms.includes(process.platform)) throw new Error(`Full native bootstrap supports ${lock.platforms.join(' and ')}; this host is ${process.platform}. Use --extract-only --only minicoro,yyjson for portable source dependencies.`);
24
-
25
- function run(command, args, cwd, label, env = process.env) {
26
- const path = join(logs, label + '.log');
27
- const descriptor = openSync(path, 'w');
28
- let result;
29
- try { result = spawnSync(command, args, { cwd, env, stdio: ['ignore', descriptor, descriptor] }); }
30
- finally { closeSync(descriptor); }
31
- if (result.error || result.status !== 0) throw new Error(`${label} failed: ${result.error?.message ?? result.status}. See ${path}\n` + readFileSync(path, 'utf8').split('\n').slice(-24).join('\n'));
32
- }
33
-
34
- const dependencies = lock.dependencies.filter(dependency => (!dependency.platforms || dependency.platforms.includes(process.platform)) && (!selected || selected.includes(dependency.name)));
35
- if (selected?.some(name => !dependencies.some(dependency => dependency.name === name)))
36
- throw new Error(`One or more selected dependencies do not support ${process.platform}.`);
37
- for (const dependency of dependencies) {
38
- const archive = join(downloads, dependency.archive);
39
- if (!existsSync(archive)) {
40
- process.stdout.write(`Downloading ${dependency.name} ${dependency.version}\n`);
41
- const response = await fetch(dependency.url);
42
- if (!response.ok) throw new Error(`${dependency.name}: HTTP ${response.status}`);
43
- writeFileSync(archive, Buffer.from(await response.arrayBuffer()));
12
+ async function setup() {
13
+ if (Number(process.versions.node.split('.')[0]) < 24) throw new Error(`August native setup needs Node.js 24 or newer; this is ${process.versions.node}.`);
14
+ if (process.argv.includes('--help')) {
15
+ process.stdout.write('Usage: aug-native [--profile crypto|web] [--offline]\n aug-native --extract-only [--only minicoro,yyjson] [--offline]\n\nNative commands prepare dependencies automatically. Use this command to prewarm a cache without running a program.\nAUG_NATIVE_HOME selects the cache; system build tools remain prerequisites.\n');
16
+ return;
44
17
  }
45
- const hash = createHash('sha256').update(readFileSync(archive)).digest('hex');
46
- if (hash !== dependency.sha256) throw new Error(`${dependency.name}: archive checksum mismatch`);
47
- const source = join(sources, dependency.name);
48
- if (!existsSync(join(source, '.archive-sha256'))) {
49
- mkdirSync(source, { recursive: true });
50
- run('/usr/bin/tar', ['-xf', archive, '-C', source, '--strip-components=1'], directory, 'extract-' + dependency.name);
51
- writeFileSync(join(source, '.archive-sha256'), hash + '\n');
52
- } else if (readFileSync(join(source, '.archive-sha256'), 'utf8').trim() !== hash) {
53
- throw new Error(`${dependency.name}: source tree differs from the dependency lock; choose a new build directory.`);
18
+ for (let index = 2; index < process.argv.length; index++) {
19
+ const option = process.argv[index];
20
+ if (['--only', '--profile'].includes(option)) {
21
+ if (!process.argv[index + 1] || process.argv[index + 1].startsWith('--')) throw new Error(`${option} needs a value. See aug-native --help.`);
22
+ index++;
23
+ } else if (!['--extract-only', '--offline'].includes(option)) throw new Error(`Unknown option ${option}. See aug-native --help.`);
54
24
  }
25
+ const root = resolve(import.meta.dirname, '..');
26
+ const lock = JSON.parse(readFileSync(join(import.meta.dirname, 'native-dependencies.lock.json'), 'utf8'));
27
+ const extractOnly = process.argv.includes('--extract-only');
28
+ const onlyIndex = process.argv.indexOf('--only');
29
+ const selected = onlyIndex >= 0 ? process.argv[onlyIndex + 1]?.split(',') : undefined;
30
+ const profileIndex = process.argv.indexOf('--profile');
31
+ const profile = profileIndex >= 0 ? process.argv[profileIndex + 1] : 'web';
32
+ const offline = process.argv.includes('--offline');
33
+ if (!['crypto', 'web'].includes(profile)) throw new Error('Use --profile crypto or --profile web.');
34
+ if (onlyIndex >= 0 && (!extractOnly || !selected?.length || selected.some(name => !lock.dependencies.some(dependency => dependency.name === name))))
35
+ throw new Error('--only requires --extract-only and comma-separated names from native-dependencies.lock.json.');
36
+ const directory = nativeHome(root);
37
+ const prefix = join(directory, 'prefix');
38
+ const downloads = join(directory, 'downloads');
39
+ const sources = join(directory, 'sources');
40
+ const logs = join(directory, 'logs');
41
+ for (const path of [prefix, downloads, sources, logs]) mkdirSync(path, { recursive: true });
42
+ if (!extractOnly && !lock.platforms.includes(process.platform)) throw new Error(`Full native bootstrap supports ${lock.platforms.join(' and ')}; this host is ${process.platform}. Use --extract-only --only minicoro,yyjson for portable source dependencies.`);
43
+ const cc = extractOnly ? undefined : cCompiler();
44
+ requireBuildTool('tar');
45
+ if (!extractOnly) { requireBuildTool('make'); requireBuildTool('m4'); if (profile === 'web' && process.platform !== 'darwin') requireBuildTool('cmake'); }
46
+ const release = await acquireLock(directory);
47
+ try {
48
+
49
+ function run(command, args, cwd, label, env = process.env) {
50
+ const path = join(logs, label + '.log');
51
+ const descriptor = openSync(path, 'w');
52
+ let result;
53
+ try { result = spawnSync(command, args, { cwd, env, stdio: ['ignore', descriptor, descriptor] }); }
54
+ finally { closeSync(descriptor); }
55
+ if (result.error || result.status !== 0) throw new Error(`${label} failed: ${result.error?.message ?? result.status}. See ${path}\n` + readFileSync(path, 'utf8').split('\n').slice(-24).join('\n'));
56
+ }
57
+
58
+ const dependencies = lock.dependencies.filter(dependency => (!dependency.platforms || dependency.platforms.includes(process.platform)) &&
59
+ (!selected || selected.includes(dependency.name)) && (extractOnly || profile === 'web' || ['pkgconf', 'gmp', 'nettle', 'gnutls'].includes(dependency.name)));
60
+ if (selected?.some(name => !dependencies.some(dependency => dependency.name === name)))
61
+ throw new Error(`One or more selected dependencies do not support ${process.platform}.`);
62
+ for (const dependency of dependencies) {
63
+ const archive = join(downloads, dependency.archive);
64
+ if (!existsSync(archive)) {
65
+ if (offline) throw new Error(`Offline setup cannot find the cached ${dependency.name} archive at ${archive}.\nRun aug run once with network access, then retry aug run --offline.`);
66
+ process.stdout.write(`Downloading ${dependency.name} ${dependency.version}\n`);
67
+ let bytes;
68
+ try {
69
+ const response = await fetch(dependency.url, { signal: AbortSignal.timeout(120000) });
70
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
71
+ bytes = Buffer.from(await response.arrayBuffer());
72
+ } catch (error) { throw new Error(`Could not download ${dependency.name}: ${error.message}.\nCheck your internet/proxy connection and retry aug run. URL: ${dependency.url}`); }
73
+ if (createHash('sha256').update(bytes).digest('hex') !== dependency.sha256)
74
+ throw new Error(`Downloaded ${dependency.name} failed its checksum. No files were installed. Check your connection and retry aug run.`);
75
+ const temporary = archive + '.tmp';
76
+ try { writeFileSync(temporary, bytes); renameSync(temporary, archive); }
77
+ finally { rmSync(temporary, { force: true }); }
78
+ }
79
+ const hash = createHash('sha256').update(readFileSync(archive)).digest('hex');
80
+ if (hash !== dependency.sha256) throw new Error(`${dependency.name}: cached archive checksum mismatch at ${archive}.\nRemove that archive and retry aug run to download the verified copy.`);
81
+ const source = join(sources, dependency.name);
82
+ if (existsSync(join(source, '.archive-sha256')) && readFileSync(join(source, '.archive-sha256'), 'utf8').trim() !== hash)
83
+ throw new Error(`${dependency.name}: source tree differs from the dependency lock. Set AUG_NATIVE_HOME to an empty directory and retry aug run.`);
84
+ if (!existsSync(join(source, '.archive-sha256')) || dependencyArtifacts(dependency.name).filter(file => file.startsWith('sources/')).some(file => !existsSync(join(directory, file)))) {
85
+ mkdirSync(source, { recursive: true });
86
+ run('tar', ['-xf', archive, '-C', source, '--strip-components=1'], directory, 'extract-' + dependency.name);
87
+ writeFileSync(join(source, '.archive-sha256'), hash + '\n');
88
+ }
89
+ }
90
+ if (extractOnly) return;
91
+
92
+ const sdk = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk';
93
+ const mac = process.platform === 'darwin';
94
+ const sysroot = mac && existsSync(sdk) ? ' -isysroot ' + sdk : '';
95
+ const environment = { ...process.env, ...(mac && existsSync(sdk) && !process.env.SDKROOT ? { SDKROOT: sdk } : {}), CC: cc, CC_FOR_BUILD: cc, CXX: process.env.CXX ?? cc.replace(/clang$/, 'clang++').replace(/gcc$/, 'g++').replace(/^cc$/, 'c++'),
96
+ CFLAGS: `-O2 -fPIC${sysroot}`,
97
+ CXXFLAGS: `-O2 -fPIC${sysroot}`,
98
+ CPPFLAGS: `-I${prefix}/include${sysroot}`, LDFLAGS: `-L${prefix}/lib -Wl,-rpath,${prefix}/lib`,
99
+ PKG_CONFIG: join(prefix, 'bin', 'pkgconf'), PKG_CONFIG_PATH: join(prefix, 'lib', 'pkgconfig'),
100
+ LD_LIBRARY_PATH: `${prefix}/lib${process.env.LD_LIBRARY_PATH ? ':' + process.env.LD_LIBRARY_PATH : ''}`,
101
+ PATH: join(prefix, 'bin') + ':' + process.env.PATH,
102
+ };
103
+ const parallel = String(Math.min(8, availableParallelism()));
104
+ for (const name of ['pkgconf', 'gmp', 'nettle', 'gnutls']) {
105
+ const marker = join(prefix, '.built-' + name);
106
+ const checksum = lock.dependencies.find(dependency => dependency.name === name).sha256;
107
+ if (existsSync(marker)) {
108
+ if (readFileSync(marker, 'utf8').trim() !== checksum) throw new Error(`${name}: installed build differs from the dependency lock; choose a new build directory.`);
109
+ if (dependencyArtifacts(name).every(file => existsSync(join(directory, file)))) continue;
110
+ }
111
+ const source = join(sources, name);
112
+ const extra = name === 'gmp' ? ['--disable-cxx', '--with-pic'] : name === 'nettle' ? ['--disable-documentation'] : name === 'gnutls' ? [
113
+ '--disable-doc', '--disable-tests', '--disable-tools', '--disable-cxx', '--disable-guile',
114
+ '--disable-nls', '--disable-idn', '--without-p11-kit', '--without-brotli', '--without-zstd',
115
+ '--with-included-libtasn1', '--with-included-unistring', '--disable-libdane',
116
+ ] : [];
117
+ // GnuTLS 3.8.13's audit header does not define this diagnostic-only macro
118
+ // when Clang 14 reports __has_c_attribute but lacks [[maybe_unused]].
119
+ const buildEnvironment = name === 'gnutls' && !mac ?
120
+ {...environment, CFLAGS: environment.CFLAGS + ' -DCRAU_MAYBE_UNUSED='} : environment;
121
+ process.stdout.write(`Building ${name}; logs: ${logs}\n`);
122
+ // A relative invocation keeps Autoconf's srcdir local. An absolute alias (e.g. /var -> /private/var)
123
+ // can make GnuTLS treat this as a VPATH build and replace GNUmakefile with a link to itself.
124
+ run('./configure', ['--prefix=' + prefix, '--libdir=' + join(prefix, 'lib'), '--enable-shared', '--disable-static', ...extra], source, name + '-configure', buildEnvironment);
125
+ run('make', ['-j' + parallel], source, name + '-build', buildEnvironment);
126
+ run('make', ['install'], source, name + '-install', buildEnvironment);
127
+ if (name === 'nettle') run(join(prefix, 'bin', 'pkgconf'), ['--modversion', 'nettle', 'hogweed'], root, 'nettle-pkgconf', environment);
128
+ writeFileSync(marker, checksum + '\n');
129
+ }
130
+
131
+ if (profile === 'web') {
132
+ const cmake = mac ? join(sources, 'cmake', 'CMake.app', 'Contents', 'bin', 'cmake') : 'cmake';
133
+ const build = join(directory, 'build-libwebsockets');
134
+ const webMarker = join(prefix, '.built-libwebsockets');
135
+ const webChecksum = lock.dependencies.find(dependency => dependency.name === 'libwebsockets').sha256;
136
+ if (existsSync(webMarker) && readFileSync(webMarker, 'utf8').trim() !== webChecksum)
137
+ throw new Error('libwebsockets: installed build differs from the dependency lock; choose a new build directory.');
138
+ if (!existsSync(webMarker) || !dependencyArtifacts('libwebsockets').every(file => existsSync(join(directory, file)))) {
139
+ process.stdout.write(`Building libwebsockets with GnuTLS, HTTP/2 and HTTP/3\n`);
140
+ run(cmake, ['-S', join(sources, 'libwebsockets'), '-B', build,
141
+ '-DCMAKE_BUILD_TYPE=Release', '-DCMAKE_INSTALL_PREFIX=' + prefix, '-DCMAKE_INSTALL_LIBDIR=lib', '-DCMAKE_PREFIX_PATH=' + prefix,
142
+ '-DCMAKE_C_COMPILER=' + cc, ...(mac && existsSync(sdk) && !process.env.SDKROOT ? ['-DCMAKE_OSX_SYSROOT=' + sdk] : []),
143
+ '-DLWS_GNUTLS_LIBRARIES=' + join(prefix, 'lib', mac ? 'libgnutls.dylib' : 'libgnutls.so'),
144
+ '-DLWS_GNUTLS_INCLUDE_DIRS=' + join(prefix, 'include'),
145
+ '-DLWS_WITH_GNUTLS=ON', '-DLWS_WITH_HTTP2=ON', '-DLWS_WITH_HTTP3=ON',
146
+ '-DLWS_WITH_STATIC=ON', '-DLWS_WITH_SHARED=OFF', '-DLWS_WITHOUT_TESTAPPS=ON',
147
+ '-DLWS_WITHOUT_TEST_SERVER=ON', '-DLWS_WITHOUT_TEST_CLIENT=ON',
148
+ '-DLWS_WITH_LIBUV=OFF', '-DLWS_WITH_LIBEVENT=OFF', '-DLWS_WITH_LIBEV=OFF',
149
+ '-DLWS_WITH_GLIB=OFF', '-DLWS_WITHOUT_EXTENSIONS=ON', '-DLWS_WITH_ZLIB=OFF',
150
+ ], root, 'libwebsockets-configure', environment);
151
+ run(cmake, ['--build', build, '--parallel', parallel], root, 'libwebsockets-build', environment);
152
+ run(cmake, ['--install', build], root, 'libwebsockets-install', environment);
153
+ writeFileSync(webMarker, webChecksum + '\n');
154
+ }
155
+ }
156
+ writeFileSync(join(prefix, 'aug-native-manifest.json'), JSON.stringify({ platform: process.platform, architecture: process.arch,
157
+ dependencies: lock.dependencies.filter(dependency => dependencyReady(directory, dependency)).map(({name, version, revision, sha256}) => ({name, version, revision, sha256})) }, null, 2) + '\n');
158
+ process.stdout.write(`Native dependencies ready at ${prefix}\n`);
159
+ } finally { release(); }
55
160
  }
56
- if (extractOnly) process.exit(0);
57
161
 
58
- const sdk = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk';
59
- const mac = process.platform === 'darwin';
60
- const cc = process.env.CC ?? (mac ? '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang' : 'clang');
61
- const sysroot = mac && existsSync(sdk) ? ' -isysroot ' + sdk : '';
62
- const environment = { ...process.env, ...(mac ? { SDKROOT: sdk } : {}), CC: cc, CC_FOR_BUILD: cc, CXX: process.env.CXX ?? cc.replace(/clang$/, 'clang++'),
63
- CFLAGS: `-O2 -fPIC${sysroot}`,
64
- CXXFLAGS: `-O2 -fPIC${sysroot}`,
65
- CPPFLAGS: `-I${prefix}/include${sysroot}`, LDFLAGS: `-L${prefix}/lib -Wl,-rpath,${prefix}/lib`,
66
- PKG_CONFIG: join(prefix, 'bin', 'pkgconf'), PKG_CONFIG_PATH: join(prefix, 'lib', 'pkgconfig'),
67
- LD_LIBRARY_PATH: `${prefix}/lib${process.env.LD_LIBRARY_PATH ? ':' + process.env.LD_LIBRARY_PATH : ''}`,
68
- PATH: join(prefix, 'bin') + ':' + process.env.PATH,
69
- };
70
- const parallel = String(Math.min(8, availableParallelism()));
71
- for (const name of ['pkgconf', 'gmp', 'nettle', 'gnutls']) {
72
- const marker = join(prefix, '.built-' + name);
73
- const checksum = lock.dependencies.find(dependency => dependency.name === name).sha256;
74
- if (existsSync(marker)) {
75
- if (readFileSync(marker, 'utf8').trim() !== checksum) throw new Error(`${name}: installed build differs from the dependency lock; choose a new build directory.`);
76
- continue;
162
+ /** One writer per cache. An interrupted setup leaves a recoverable PID lock. */
163
+ async function acquireLock(directory) {
164
+ const path = join(directory, '.setup-lock');
165
+ const started = Date.now(); let announced = false;
166
+ while (true) {
167
+ try {
168
+ const descriptor = openSync(path, 'wx');
169
+ try { writeFileSync(descriptor, JSON.stringify({ pid: process.pid })); }
170
+ finally { closeSync(descriptor); }
171
+ return () => rmSync(path, { force: true });
172
+ } catch (error) {
173
+ if (error.code !== 'EEXIST') throw error;
174
+ try {
175
+ const owner = JSON.parse(readFileSync(path, 'utf8'));
176
+ if (Number.isInteger(owner.pid) && owner.pid > 0) {
177
+ try { process.kill(owner.pid, 0); }
178
+ catch (error) { if (error.code === 'ESRCH') { rmSync(path, { force: true }); continue; } }
179
+ } else if (Date.now() - statSync(path).mtimeMs > 30000) { rmSync(path, { force: true }); continue; }
180
+ } catch (error) {
181
+ if (error.code === 'ENOENT') continue;
182
+ if (error instanceof SyntaxError && Date.now() - statSync(path).mtimeMs > 30000) { rmSync(path, { force: true }); continue; }
183
+ }
184
+ if (!announced) { process.stdout.write('Waiting for another August process to prepare the native cache.\n'); announced = true; }
185
+ if (Date.now() - started > 600000) throw new Error(`Another native setup still holds ${path}. Wait for it to finish, then retry aug run.`);
186
+ await new Promise(accept => setTimeout(accept, 500));
187
+ }
77
188
  }
78
- const source = join(sources, name);
79
- const extra = name === 'gmp' ? ['--disable-cxx', '--with-pic'] : name === 'nettle' ? ['--disable-documentation'] : name === 'gnutls' ? [
80
- '--disable-doc', '--disable-tests', '--disable-tools', '--disable-cxx', '--disable-guile',
81
- '--disable-nls', '--disable-idn', '--without-p11-kit', '--without-brotli', '--without-zstd',
82
- '--with-included-libtasn1', '--with-included-unistring', '--disable-libdane',
83
- ] : [];
84
- // GnuTLS 3.8.13's audit header does not define this diagnostic-only macro
85
- // when Clang 14 reports __has_c_attribute but lacks [[maybe_unused]].
86
- const buildEnvironment = name === 'gnutls' && !mac ?
87
- {...environment, CFLAGS: environment.CFLAGS + ' -DCRAU_MAYBE_UNUSED='} : environment;
88
- process.stdout.write(`Building ${name}; logs: ${logs}\n`);
89
- run(join(source, 'configure'), ['--prefix=' + prefix, '--libdir=' + join(prefix, 'lib'), '--enable-shared', '--disable-static', ...extra], source, name + '-configure', buildEnvironment);
90
- run('/usr/bin/make', ['-j' + parallel], source, name + '-build', buildEnvironment);
91
- run('/usr/bin/make', ['install'], source, name + '-install', buildEnvironment);
92
- if (name === 'nettle') run(join(prefix, 'bin', 'pkgconf'), ['--modversion', 'nettle', 'hogweed'], root, 'nettle-pkgconf', environment);
93
- writeFileSync(marker, checksum + '\n');
94
189
  }
95
190
 
96
- const cmake = mac ? join(sources, 'cmake', 'CMake.app', 'Contents', 'bin', 'cmake') : 'cmake';
97
- const build = join(directory, 'build-libwebsockets');
98
- const webMarker = join(prefix, '.built-libwebsockets');
99
- const webChecksum = lock.dependencies.find(dependency => dependency.name === 'libwebsockets').sha256;
100
- if (existsSync(webMarker) && readFileSync(webMarker, 'utf8').trim() !== webChecksum)
101
- throw new Error('libwebsockets: installed build differs from the dependency lock; choose a new build directory.');
102
- if (!existsSync(webMarker)) {
103
- process.stdout.write(`Building libwebsockets with GnuTLS, HTTP/2 and HTTP/3\n`);
104
- run(cmake, ['-S', join(sources, 'libwebsockets'), '-B', build,
105
- '-DCMAKE_BUILD_TYPE=Release', '-DCMAKE_INSTALL_PREFIX=' + prefix, '-DCMAKE_INSTALL_LIBDIR=lib', '-DCMAKE_PREFIX_PATH=' + prefix,
106
- '-DCMAKE_C_COMPILER=' + cc, ...(mac ? ['-DCMAKE_OSX_SYSROOT=' + sdk] : []),
107
- '-DLWS_GNUTLS_LIBRARIES=' + join(prefix, 'lib', mac ? 'libgnutls.dylib' : 'libgnutls.so'),
108
- '-DLWS_GNUTLS_INCLUDE_DIRS=' + join(prefix, 'include'),
109
- '-DLWS_WITH_GNUTLS=ON', '-DLWS_WITH_HTTP2=ON', '-DLWS_WITH_HTTP3=ON',
110
- '-DLWS_WITH_STATIC=ON', '-DLWS_WITH_SHARED=OFF', '-DLWS_WITHOUT_TESTAPPS=ON',
111
- '-DLWS_WITHOUT_TEST_SERVER=ON', '-DLWS_WITHOUT_TEST_CLIENT=ON',
112
- '-DLWS_WITH_LIBUV=OFF', '-DLWS_WITH_LIBEVENT=OFF', '-DLWS_WITH_LIBEV=OFF',
113
- '-DLWS_WITH_GLIB=OFF', '-DLWS_WITHOUT_EXTENSIONS=ON', '-DLWS_WITH_ZLIB=OFF',
114
- ], root, 'libwebsockets-configure', environment);
115
- run(cmake, ['--build', build, '--parallel', parallel], root, 'libwebsockets-build', environment);
116
- run(cmake, ['--install', build], root, 'libwebsockets-install', environment);
117
- writeFileSync(webMarker, webChecksum + '\n');
191
+ try { await setup(); }
192
+ catch (error) {
193
+ const permission = ['EACCES', 'EPERM', 'EROFS'].includes(error.code) ? '\nChoose a writable cache: set AUG_NATIVE_HOME to a directory you own and retry aug run.' : '';
194
+ process.stderr.write(`Native setup: ${error.message}${permission}\n`);
195
+ process.exitCode = 1;
118
196
  }
119
- writeFileSync(join(prefix, 'aug-native-manifest.json'), JSON.stringify({ platform: process.platform, architecture: process.arch,
120
- dependencies: dependencies.map(({name, version, revision, sha256}) => ({name, version, revision, sha256})) }, null, 2) + '\n');
121
- process.stdout.write(`Native dependencies ready at ${prefix}\n`);
@@ -0,0 +1,98 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join, resolve } from 'node:path';
3
+ import { spawn } from 'node:child_process';
4
+ import { nativeHome } from './native-home.mjs';
5
+ import { cCompiler } from './native-toolchain.mjs';
6
+
7
+ /** Inspect C identifiers, excluding comments and string literals. Shared with the linker. */
8
+ export function nativeRequirements(generated) {
9
+ const code = generated.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'/g, ' ');
10
+ const web = /\b(?:_?aug_http_|aug_headers_)\w*/.test(code);
11
+ return { web, crypto: web || /\b_aug_crypto_\w*/.test(code),
12
+ tasks: web || /\baug_task_\w*/.test(code), json: web || /\b_?aug_json_\w*/.test(code),
13
+ html: web || /\baug_html_\w*/.test(code), time: /\b_aug_time_\w*/.test(code) };
14
+ }
15
+
16
+ const artifacts = {
17
+ minicoro: ['sources/minicoro/minicoro.h'], yyjson: ['sources/yyjson/src/yyjson.c', 'sources/yyjson/src/yyjson.h'],
18
+ pkgconf: ['prefix/bin/pkgconf'], gmp: ['prefix/include/gmp.h'],
19
+ nettle: ['prefix/include/nettle/nettle-types.h'], gnutls: ['prefix/include/gnutls/gnutls.h'],
20
+ libwebsockets: ['prefix/lib/libwebsockets.a', 'prefix/include/libwebsockets.h'],
21
+ };
22
+ export function dependencyArtifacts(name) {
23
+ const library = { gmp: ['gmp'], nettle: ['nettle', 'hogweed'], gnutls: ['gnutls'] }[name] ?? [];
24
+ return [...(artifacts[name] ?? []), ...library.map(item => `prefix/lib/lib${item}.${process.platform === 'darwin' ? 'dylib' : 'so'}`)];
25
+ }
26
+
27
+ export function dependencyReady(directory, dependency) {
28
+ const marker = join(directory, ['minicoro', 'yyjson'].includes(dependency.name) ?
29
+ `sources/${dependency.name}/.archive-sha256` : `prefix/.built-${dependency.name}`);
30
+ return existsSync(marker) && readFileSync(marker, 'utf8').trim() === dependency.sha256 &&
31
+ dependencyArtifacts(dependency.name).every(file => existsSync(join(directory, file)));
32
+ }
33
+
34
+ /** Prepare the precise native capabilities emitted by the compiler, keeping stdout for the program. */
35
+ export async function prepareNativeDependencies(generated, { offline = false, progress = message => process.stderr.write(message) } = {}) {
36
+ const needs = nativeRequirements(generated);
37
+ cCompiler(); // Fail before downloading when the host cannot compile the application.
38
+ if (!needs.json && !needs.tasks && !needs.crypto) return;
39
+ const root = resolve(import.meta.dirname, '..'), directory = nativeHome(root);
40
+ const lock = JSON.parse(readFileSync(join(import.meta.dirname, 'native-dependencies.lock.json'), 'utf8'));
41
+ const names = [...(needs.json ? ['yyjson'] : []), ...(needs.tasks ? ['minicoro'] : []),
42
+ ...(needs.crypto ? ['pkgconf', 'gmp', 'nettle', 'gnutls'] : []), ...(needs.web ? ['libwebsockets'] : [])];
43
+ const required = lock.dependencies.filter(item => names.includes(item.name));
44
+ const manifestPath = join(directory, 'prefix/aug-native-manifest.json');
45
+ let manifest;
46
+ if (needs.crypto && existsSync(manifestPath)) {
47
+ try {
48
+ manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
49
+ if (!manifest || typeof manifest.platform !== 'string' || typeof manifest.architecture !== 'string' || !Array.isArray(manifest.dependencies))
50
+ throw new Error('Invalid metadata');
51
+ }
52
+ catch { throw new Error(`Native cache metadata is unreadable: ${manifestPath}\nSet AUG_NATIVE_HOME to an empty directory and retry aug run.`); }
53
+ if (manifest.platform !== process.platform || manifest.architecture !== process.arch)
54
+ throw new Error(`Native cache targets ${manifest.platform}/${manifest.architecture}; this computer is ${process.platform}/${process.arch}.\nSet AUG_NATIVE_HOME to a cache built on this computer, or unset it and retry aug run.`);
55
+ }
56
+ const libraries = required.filter(item => !['yyjson', 'minicoro'].includes(item.name));
57
+ const manifestReady = !needs.crypto || libraries.every(item => manifest?.dependencies?.some(entry => entry.name === item.name && entry.sha256 === item.sha256));
58
+ if (manifestReady && required.every(item => dependencyReady(directory, item))) return;
59
+ const capabilities = [needs.json && 'JSON', needs.tasks && 'tasks', needs.crypto && 'crypto', needs.web && 'HTTP'].filter(Boolean).join(', ');
60
+ progress(`Preparing native dependencies for ${capabilities} (cached at ${directory}). First use may take a few minutes.\n`);
61
+ const args = needs.crypto ? ['--profile', needs.web ? 'web' : 'crypto'] : ['--extract-only', '--only', names.join(',')];
62
+ // Crypto source packages can use JSON or tasks without needing HTTP. The
63
+ // crypto profile builds libraries only, so prepare those source dependencies
64
+ // separately. The web profile already includes both.
65
+ const portable = needs.crypto && !needs.web ? required.filter(item =>
66
+ ['yyjson', 'minicoro'].includes(item.name) && !dependencyReady(directory, item)).map(item => item.name) : [];
67
+ const preparations = [...(portable.length ? [['--extract-only', '--only', portable.join(',')]] : []), args];
68
+ for (const preparation of preparations) {
69
+ if (offline) preparation.push('--offline');
70
+ await new Promise((accept, reject) => {
71
+ const child = spawn(process.execPath, [join(import.meta.dirname, 'bootstrap-native.mjs'), ...preparation], {
72
+ stdio: ['ignore', 'pipe', 'pipe'], detached: process.platform !== 'win32' });
73
+ let detail = '', interrupted;
74
+ const stop = signal => {
75
+ interrupted = signal;
76
+ try { if (process.platform !== 'win32' && child.pid) process.kill(-child.pid, signal); else child.kill(signal); }
77
+ catch (error) { if (error.code !== 'ESRCH') child.kill(signal); }
78
+ };
79
+ const interrupt = () => stop('SIGINT'), terminate = () => stop('SIGTERM');
80
+ process.once('SIGINT', interrupt); process.once('SIGTERM', terminate);
81
+ const cleanup = () => { process.off('SIGINT', interrupt); process.off('SIGTERM', terminate); };
82
+ child.stdout.on('data', data => progress(data.toString()));
83
+ child.stderr.on('data', data => { detail = (detail + data.toString()).slice(-12000); progress(data.toString()); });
84
+ child.on('error', error => { cleanup(); reject(new Error(`Cannot start native dependency setup: ${error.message}\nRetry aug run after checking your Node installation.`)); });
85
+ child.on('close', (status, signal) => {
86
+ cleanup();
87
+ if (interrupted) {
88
+ const error = new Error(`Native setup cancelled by ${interrupted}. Retry aug run to resume using the completed dependencies.`);
89
+ error.exitCode = interrupted === 'SIGINT' ? 130 : 143; reject(error);
90
+ } else if (status === 0) accept();
91
+ else reject(new Error(`Native dependency setup ${signal ? `stopped by ${signal}` : `failed (exit ${status})`}. ${detail ? 'See the error above.' : `Check the setup logs in ${join(directory, 'logs')}.`}\nRetry aug run after addressing it; completed dependencies will be reused.`));
92
+ });
93
+ });
94
+ }
95
+ const missing = required.filter(item => !dependencyReady(directory, item)).map(item => item.name);
96
+ if (missing.length)
97
+ throw new Error(`Native setup did not prepare ${missing.join(', ')} in ${directory}.\nCheck the setup logs in ${join(directory, 'logs')} and retry aug run; completed dependencies will be reused.`);
98
+ }
@@ -0,0 +1,28 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { spawnSync } from 'node:child_process';
3
+
4
+ export function compilerHelp() {
5
+ const install = process.platform === 'darwin' ? 'Install the Apple Command Line Tools with: xcode-select --install' :
6
+ process.platform === 'linux' ? 'Install a C toolchain (Debian/Ubuntu: sudo apt-get install build-essential; Fedora: sudo dnf install gcc make).' :
7
+ 'Use a Linux Dev Container or install a C11 compiler with POSIX threads support.';
8
+ return `${install}\nIf a compiler is already installed, set CC to its executable path and retry aug run.`;
9
+ }
10
+
11
+ /** Select an executable, including installations with only Apple's Command Line Tools. */
12
+ export function cCompiler() {
13
+ const xcode = '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang';
14
+ const candidates = process.env.CC ? [process.env.CC] : [...(existsSync(xcode) ? [xcode] : []), 'clang', 'cc', 'gcc'];
15
+ for (const command of candidates) {
16
+ const result = spawnSync(command, ['--version'], { encoding: 'utf8', timeout: 10000 });
17
+ if (!result.error && result.status === 0) return command;
18
+ }
19
+ throw new Error(`Cannot use a C compiler${process.env.CC ? ` from CC=${process.env.CC}` : ' on this computer'}.\n${compilerHelp()}`);
20
+ }
21
+
22
+ export function requireBuildTool(command, args = ['--version']) {
23
+ const result = spawnSync(command, args, { encoding: 'utf8', timeout: 10000 });
24
+ if (!result.error && result.status === 0) return;
25
+ const install = process.platform === 'darwin' ? 'Install the Apple Command Line Tools with xcode-select --install.' :
26
+ 'Install the build tools (Debian/Ubuntu: sudo apt-get install build-essential m4 cmake zlib1g-dev; Fedora: sudo dnf install gcc make m4 cmake zlib-devel).';
27
+ throw new Error(`Native dependency setup needs ${command}, but it could not run.\n${install}\nRetry aug run after installing it.`);
28
+ }
package/src/builtins.js CHANGED
@@ -85,7 +85,7 @@ export const builtinFunctions = [
85
85
  { name: 'exit', parameters: [{ label: 'status', type: 'int' }], returns: 'void', documentation: 'Exit from main with a status from 0 to 255 after cancellation and cleanup.', native: 'exit' },
86
86
  { name: 'c_int', parameters: [{ label: 'value', type: 'int' }], returns: 'c_int', errors: ['ConversionError'], documentation: 'Checked conversion to a signed 32-bit C int. Overflow raises ConversionError. AugScript int maps to int64_t at the C boundary.', native: 'to_c_int' },
87
87
  { name: 'int', parameters: [{ label: 'value', type: 'c_int' }], returns: 'int', documentation: 'Widen a C int to the signed 64-bit AugScript integer without loss.', native: 'to_int' },
88
- { name: 'print', parameters: [{ label: 'value', type: 'any' }], returns: 'void', documentation: 'Composition and test output. Other callables receive Console and declare uses console.write.', native: 'print' },
88
+ { name: 'print', parameters: [{ label: 'value', type: 'any' }], returns: 'void', documentation: 'Write application startup or test output. Other callables receive a Console dependency and call console.write; their bodies infer that capability use.', native: 'print' },
89
89
  { name: 'assert', parameters: [{ label: 'condition', type: 'bool' }], returns: 'void', documentation: 'Assert a bool in a test case or its setup. Catching an assertion failure cannot make the case pass; every case must execute an assertion.', native: 'assert' },
90
90
  { name: 'arguments', parameters: [], returns: 'List<string>', documentation: 'Composition arguments. Other callables receive the Arguments capability.', native: 'arguments' },
91
91
  { name: 'read_file', parameters: [{ label: 'path', type: 'string' }], returns: 'string', errors: ['FileError'], documentation: 'Root-only UTF-8 text input. Other callables receive FileReader. Invalid Unicode and NUL raise FileError.', native: 'read_file' },