@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.
- package/README.md +9 -6
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/bin/aug.mjs +12 -2
- package/docs/about.md +27 -0
- package/docs/api/crypto.md +103 -69
- package/docs/api/io.md +35 -33
- package/docs/api/json.md +3 -3
- package/docs/api/memory.md +23 -19
- package/docs/api/time.md +10 -9
- package/docs/api/web.md +33 -38
- package/docs/compatibility.md +3 -3
- package/docs/contributing-benchmarks.md +38 -0
- package/docs/dev-containers.md +95 -0
- package/docs/diagnostics.md +15 -5
- package/docs/docker.md +174 -12
- package/docs/editor.md +35 -0
- package/docs/example-projects.json +206 -24
- package/docs/examples/approved-design/counters.md +34 -126
- package/docs/examples/approved-design/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/approved-design/domain/app.md +13 -77
- package/docs/examples/approved-design/domain/export.md +5 -19
- package/docs/examples/approved-design/domain/models.md +4 -23
- package/docs/examples/approved-design/domain/numbers.md +24 -114
- package/docs/examples/approved-design/index.md +16 -7
- package/docs/examples/approved-design/main.md +19 -96
- package/docs/examples/benchmark/index.md +6 -5
- package/docs/examples/benchmark/main.md +7 -35
- package/docs/examples/cli-args/index.md +6 -5
- package/docs/examples/cli-args/main.md +6 -31
- package/docs/examples/collections/index.md +6 -5
- package/docs/examples/collections/main.md +7 -35
- package/docs/examples/collections-benchmark/index.md +6 -5
- package/docs/examples/collections-benchmark/main.md +7 -35
- package/docs/examples/cpu-benchmark/index.md +6 -5
- package/docs/examples/cpu-benchmark/main.md +5 -24
- package/docs/examples/developer-workflow/calculator.md +39 -186
- package/docs/examples/developer-workflow/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/developer-workflow/index.md +16 -7
- package/docs/examples/developer-workflow/logging/console.md +10 -56
- package/docs/examples/developer-workflow/logging/export.md +4 -14
- package/docs/examples/developer-workflow/logging/logger.md +7 -43
- package/docs/examples/developer-workflow/main.md +17 -69
- package/docs/examples/drop/index.md +6 -5
- package/docs/examples/drop/main.md +7 -27
- package/docs/examples/drop/resource.md +7 -30
- package/docs/examples/errors/errors.md +7 -27
- package/docs/examples/errors/index.md +6 -5
- package/docs/examples/errors/main.md +7 -28
- package/docs/examples/ffi/index.md +6 -5
- package/docs/examples/ffi/main.md +6 -20
- package/docs/examples/ffi/native.md +8 -34
- package/docs/examples/generic-di/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/generic-di/index.md +6 -5
- package/docs/examples/generic-di/main.md +9 -39
- package/docs/examples/generic-di/types.md +23 -92
- package/docs/examples/generics/index.md +6 -5
- package/docs/examples/generics/main.md +10 -47
- package/docs/examples/generics/types.md +25 -100
- package/docs/examples/hello/app/export.md +4 -12
- package/docs/examples/hello/app/greeter.md +13 -91
- package/docs/examples/hello/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/hello/index.md +17 -6
- package/docs/examples/hello/logging/console.md +10 -54
- package/docs/examples/hello/logging/export.md +4 -14
- package/docs/examples/hello/logging/logger.md +7 -45
- package/docs/examples/hello/main.md +9 -39
- package/docs/examples/http-benchmark/index.md +6 -5
- package/docs/examples/http-benchmark/main.md +6 -20
- package/docs/examples/http-benchmark/routes.md +9 -31
- package/docs/examples/index.md +46 -29
- package/docs/examples/interceptors/app.md +20 -139
- package/docs/examples/interceptors/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/interceptors/index.md +6 -5
- package/docs/examples/interceptors/interceptors.md +24 -148
- package/docs/examples/interceptors/logging.md +13 -76
- package/docs/examples/interceptors/main.md +10 -65
- package/docs/examples/json-benchmark/data.md +4 -20
- package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/json-benchmark/index.md +7 -5
- package/docs/examples/json-benchmark/main-yaml.md +20 -0
- package/docs/examples/json-benchmark/main.md +10 -49
- package/docs/examples/new-syntax/console.md +10 -52
- package/docs/examples/new-syntax/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/new-syntax/greeter.md +13 -71
- package/docs/examples/new-syntax/index.md +6 -5
- package/docs/examples/new-syntax/logger.md +7 -43
- package/docs/examples/new-syntax/main.md +10 -53
- package/docs/examples/new-syntax/math.md +6 -24
- package/docs/examples/oidc-login/client/contracts.md +10 -61
- package/docs/examples/oidc-login/client/endpoints.md +32 -154
- package/docs/examples/oidc-login/client/export.md +5 -23
- package/docs/examples/oidc-login/client/login.md +234 -344
- package/docs/examples/oidc-login/client/logout.md +38 -143
- package/docs/examples/oidc-login/client/protocol.md +183 -304
- package/docs/examples/oidc-login/client/session.md +41 -149
- package/docs/examples/oidc-login/client/views.md +13 -58
- package/docs/examples/oidc-login/common/export.md +6 -26
- package/docs/examples/oidc-login/common/headers.md +42 -72
- package/docs/examples/oidc-login/common/keys.md +40 -164
- package/docs/examples/oidc-login/common/settings.md +24 -40
- package/docs/examples/oidc-login/common/views.md +7 -28
- package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
- package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
- package/docs/examples/oidc-login/index.md +8 -7
- package/docs/examples/oidc-login/main-yaml.md +7 -0
- package/docs/examples/oidc-login/main.md +26 -153
- package/docs/examples/oidc-login/provider/authorization.md +232 -275
- package/docs/examples/oidc-login/provider/contracts.md +24 -146
- package/docs/examples/oidc-login/provider/credentials.md +24 -57
- package/docs/examples/oidc-login/provider/discovery.md +48 -122
- package/docs/examples/oidc-login/provider/export.md +11 -37
- package/docs/examples/oidc-login/provider/token.md +159 -237
- package/docs/examples/oidc-login/provider/userinfo.md +47 -102
- package/docs/examples/oidc-login/provider/views.md +13 -53
- package/docs/examples/ownership/counter.md +17 -63
- package/docs/examples/ownership/index.md +6 -5
- package/docs/examples/ownership/main.md +7 -30
- package/docs/examples/ownership-transfer/dependencies/august/0.20.1/io/contracts.md +178 -0
- package/docs/examples/ownership-transfer/index.md +6 -5
- package/docs/examples/ownership-transfer/main.md +10 -52
- package/docs/examples/ownership-transfer/resource.md +15 -67
- package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
- package/docs/examples/packages-app/index.md +7 -6
- package/docs/examples/packages-app/main.md +7 -25
- package/docs/examples/packages-math/aug-package-json.md +1 -1
- package/docs/examples/packages-math/index.md +7 -6
- package/docs/examples/packages-math/src/arithmetic.md +12 -50
- package/docs/examples/packages-math/src/export.md +4 -12
- package/docs/examples/startup-benchmark/index.md +6 -5
- package/docs/examples/startup-benchmark/main.md +5 -17
- package/docs/examples/visibility/counter.md +19 -67
- package/docs/examples/visibility/index.md +6 -5
- package/docs/examples/visibility/main.md +7 -31
- package/docs/examples/weather-api/forecasts.md +168 -0
- package/docs/examples/weather-api/index.md +42 -0
- package/docs/examples/weather-api/main-yaml.md +21 -0
- package/docs/examples/weather-api/main.md +65 -0
- package/docs/examples.json +10 -0
- package/docs/getting-started.md +105 -2
- package/docs/grammar.md +6 -4
- package/docs/guides/change-a-module.md +64 -0
- package/docs/guides/index.md +27 -0
- package/docs/index.md +51 -29
- package/docs/language-conformance.md +1 -1
- package/docs/language-constructs.md +22 -22
- package/docs/language-design-audit.md +1 -1
- package/docs/learn/data-and-errors.md +77 -0
- package/docs/learn/index.md +30 -0
- package/docs/learn/modules-and-dependencies.md +73 -0
- package/docs/learn/state-and-tests.md +71 -0
- package/docs/learn/values-and-functions.md +62 -0
- package/docs/lesson-failures.json +8 -0
- package/docs/maintaining-docs.md +16 -4
- package/docs/packages.md +72 -126
- package/docs/performance.md +13 -41
- package/docs/production-readiness.md +5 -4
- package/docs/public/downloads/approved-design.zip +0 -0
- package/docs/public/downloads/benchmark.zip +0 -0
- package/docs/public/downloads/cli-args.zip +0 -0
- package/docs/public/downloads/collections-benchmark.zip +0 -0
- package/docs/public/downloads/collections.zip +0 -0
- package/docs/public/downloads/cpu-benchmark.zip +0 -0
- package/docs/public/downloads/developer-workflow.zip +0 -0
- package/docs/public/downloads/drop.zip +0 -0
- package/docs/public/downloads/errors.zip +0 -0
- package/docs/public/downloads/ffi.zip +0 -0
- package/docs/public/downloads/generic-di.zip +0 -0
- package/docs/public/downloads/generics.zip +0 -0
- package/docs/public/downloads/hello.zip +0 -0
- package/docs/public/downloads/http-benchmark.zip +0 -0
- package/docs/public/downloads/interceptors.zip +0 -0
- package/docs/public/downloads/json-benchmark.zip +0 -0
- package/docs/public/downloads/new-syntax.zip +0 -0
- package/docs/public/downloads/oidc-login.zip +0 -0
- package/docs/public/downloads/ownership-transfer.zip +0 -0
- package/docs/public/downloads/ownership.zip +0 -0
- package/docs/public/downloads/packages-app.zip +0 -0
- package/docs/public/downloads/packages-math.zip +0 -0
- package/docs/public/downloads/startup-benchmark.zip +0 -0
- package/docs/public/downloads/visibility.zip +0 -0
- package/docs/public/downloads/weather-api.zip +0 -0
- package/docs/reference.md +23 -17
- package/docs/releasing.md +29 -15
- package/docs/research/code-to-natural-language.md +108 -0
- package/docs/research/ecosystem-workflow.md +41 -0
- package/docs/research/wiki-editorial-design.md +71 -0
- package/docs/roadmap.md +1 -1
- package/docs/specifications.md +27 -11
- package/docs/testing.md +19 -5
- package/docs/tooling.md +25 -12
- package/docs/weather-api.md +65 -0
- package/docs/web.md +50 -18
- package/docs/writing-docs.md +49 -0
- package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/approved-design/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/approved-design/.aug-spec/manifest.json +3 -3
- package/examples/approved-design/counters.aug +5 -4
- package/examples/approved-design/counters.aug.md +25 -132
- package/examples/approved-design/domain/app.aug +2 -1
- package/examples/approved-design/domain/app.aug.md +10 -80
- package/examples/approved-design/domain/export.aug +1 -0
- package/examples/approved-design/domain/export.aug.md +4 -20
- package/examples/approved-design/domain/models.aug +1 -0
- package/examples/approved-design/domain/models.aug.md +3 -25
- package/examples/approved-design/domain/numbers.aug +3 -2
- package/examples/approved-design/domain/numbers.aug.md +19 -116
- package/examples/approved-design/main.aug +1 -0
- package/examples/approved-design/main.aug.md +12 -95
- package/examples/benchmark/.aug-spec/manifest.json +1 -1
- package/examples/benchmark/main.aug +1 -0
- package/examples/benchmark/main.aug.md +6 -36
- package/examples/cli-args/.aug-spec/manifest.json +1 -1
- package/examples/cli-args/main.aug +1 -0
- package/examples/cli-args/main.aug.md +5 -32
- package/examples/collections/.aug-spec/manifest.json +1 -1
- package/examples/collections/main.aug +1 -0
- package/examples/collections/main.aug.md +6 -36
- package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/developer-workflow/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
- package/examples/developer-workflow/calculator.aug +3 -2
- package/examples/developer-workflow/calculator.aug.md +28 -189
- package/examples/developer-workflow/logging/console.aug +2 -1
- package/examples/developer-workflow/logging/console.aug.md +7 -57
- package/examples/developer-workflow/logging/export.aug +1 -0
- package/examples/developer-workflow/logging/export.aug.md +3 -15
- package/examples/developer-workflow/logging/logger.aug +1 -0
- package/examples/developer-workflow/logging/logger.aug.md +6 -46
- package/examples/developer-workflow/main.aug +1 -0
- package/examples/developer-workflow/main.aug.md +10 -68
- package/examples/drop/.aug-spec/manifest.json +1 -1
- package/examples/drop/main.aug +1 -0
- package/examples/drop/main.aug.md +6 -28
- package/examples/drop/resource.aug +1 -0
- package/examples/drop/resource.aug.md +6 -34
- package/examples/errors/.aug-spec/manifest.json +1 -1
- package/examples/errors/errors.aug +2 -1
- package/examples/errors/errors.aug.md +4 -27
- package/examples/errors/main.aug +1 -0
- package/examples/errors/main.aug.md +6 -29
- package/examples/ffi/.aug-spec/manifest.json +1 -1
- package/examples/ffi/main.aug +1 -0
- package/examples/ffi/main.aug.md +5 -21
- package/examples/ffi/native.aug +2 -1
- package/examples/ffi/native.aug.md +5 -35
- package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/generic-di/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/generic-di/.aug-spec/manifest.json +3 -3
- package/examples/generic-di/main.aug +1 -0
- package/examples/generic-di/main.aug.md +8 -40
- package/examples/generic-di/types.aug +3 -2
- package/examples/generic-di/types.aug.md +18 -97
- package/examples/generics/.aug-spec/manifest.json +1 -1
- package/examples/generics/main.aug +1 -0
- package/examples/generics/main.aug.md +9 -48
- package/examples/generics/types.aug +4 -3
- package/examples/generics/types.aug.md +18 -104
- package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.20.1}/io/contracts.aug +4 -3
- package/examples/hello/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/hello/.aug-spec/manifest.json +3 -3
- package/examples/hello/app/export.aug +1 -0
- package/examples/hello/app/export.aug.md +3 -13
- package/examples/hello/app/greeter.aug +2 -1
- package/examples/hello/app/greeter.aug.md +10 -94
- package/examples/hello/logging/console.aug +2 -1
- package/examples/hello/logging/console.aug.md +7 -55
- package/examples/hello/logging/export.aug +1 -0
- package/examples/hello/logging/export.aug.md +3 -15
- package/examples/hello/logging/logger.aug +1 -0
- package/examples/hello/logging/logger.aug.md +6 -48
- package/examples/hello/main.aug +1 -0
- package/examples/hello/main.aug.md +8 -40
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/interceptors/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/interceptors/.aug-spec/manifest.json +3 -3
- package/examples/interceptors/app.aug +3 -2
- package/examples/interceptors/app.aug.md +15 -141
- package/examples/interceptors/interceptors.aug +3 -2
- package/examples/interceptors/interceptors.aug.md +19 -152
- package/examples/interceptors/logging.aug +2 -1
- package/examples/interceptors/logging.aug.md +10 -79
- package/examples/interceptors/main.aug +1 -0
- package/examples/interceptors/main.aug.md +9 -66
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/new-syntax/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/new-syntax/.aug-spec/manifest.json +3 -3
- package/examples/new-syntax/console.aug +2 -1
- package/examples/new-syntax/console.aug.md +7 -53
- package/examples/new-syntax/greeter.aug +2 -1
- package/examples/new-syntax/greeter.aug.md +10 -74
- package/examples/new-syntax/logger.aug +1 -0
- package/examples/new-syntax/logger.aug.md +6 -46
- package/examples/new-syntax/main.aug +1 -0
- package/examples/new-syntax/main.aug.md +9 -54
- package/examples/new-syntax/math.aug +2 -1
- package/examples/new-syntax/math.aug.md +3 -24
- package/examples/oidc-login/.aug-spec/manifest.json +13 -13
- package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
- package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
- package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
- package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
- package/examples/oidc-login/aug.lock.json +100 -0
- package/examples/oidc-login/client/contracts.aug +1 -0
- package/examples/oidc-login/client/contracts.aug.md +9 -66
- package/examples/oidc-login/client/endpoints.aug +6 -5
- package/examples/oidc-login/client/endpoints.aug.md +13 -145
- package/examples/oidc-login/client/export.aug +1 -0
- package/examples/oidc-login/client/export.aug.md +4 -24
- package/examples/oidc-login/client/login.aug +7 -6
- package/examples/oidc-login/client/login.aug.md +25 -303
- package/examples/oidc-login/client/logout.aug +5 -4
- package/examples/oidc-login/client/logout.aug.md +13 -135
- package/examples/oidc-login/client/protocol.aug +7 -6
- package/examples/oidc-login/client/protocol.aug.md +36 -283
- package/examples/oidc-login/client/session.aug +5 -4
- package/examples/oidc-login/client/session.aug.md +12 -139
- package/examples/oidc-login/client/views.aug +3 -2
- package/examples/oidc-login/client/views.aug.md +8 -57
- package/examples/oidc-login/common/export.aug +1 -0
- package/examples/oidc-login/common/export.aug.md +5 -27
- package/examples/oidc-login/common/headers.aug +4 -3
- package/examples/oidc-login/common/headers.aug.md +9 -67
- package/examples/oidc-login/common/keys.aug +6 -5
- package/examples/oidc-login/common/keys.aug.md +29 -165
- package/examples/oidc-login/common/settings.aug +2 -1
- package/examples/oidc-login/common/settings.aug.md +5 -39
- package/examples/oidc-login/common/views.aug +2 -1
- package/examples/oidc-login/common/views.aug.md +4 -28
- package/examples/oidc-login/main.aug +6 -16
- package/examples/oidc-login/main.aug.md +17 -146
- package/examples/oidc-login/main.yaml +7 -0
- package/examples/oidc-login/provider/authorization.aug +7 -6
- package/examples/oidc-login/provider/authorization.aug.md +23 -238
- package/examples/oidc-login/provider/contracts.aug +1 -0
- package/examples/oidc-login/provider/contracts.aug.md +23 -158
- package/examples/oidc-login/provider/credentials.aug +3 -2
- package/examples/oidc-login/provider/credentials.aug.md +9 -53
- package/examples/oidc-login/provider/discovery.aug +4 -3
- package/examples/oidc-login/provider/discovery.aug.md +11 -118
- package/examples/oidc-login/provider/export.aug +1 -0
- package/examples/oidc-login/provider/export.aug.md +6 -34
- package/examples/oidc-login/provider/token.aug +6 -5
- package/examples/oidc-login/provider/token.aug.md +16 -204
- package/examples/oidc-login/provider/userinfo.aug +4 -3
- package/examples/oidc-login/provider/userinfo.aug.md +10 -92
- package/examples/oidc-login/provider/views.aug +3 -2
- package/examples/oidc-login/provider/views.aug.md +8 -52
- package/examples/ownership/.aug-spec/manifest.json +1 -1
- package/examples/ownership/counter.aug +3 -2
- package/examples/ownership/counter.aug.md +12 -66
- package/examples/ownership/main.aug +1 -0
- package/examples/ownership/main.aug.md +6 -31
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug +37 -0
- package/examples/ownership-transfer/.aug-spec/august/0.20.1/io/contracts.aug.md +82 -0
- package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
- package/examples/ownership-transfer/main.aug +1 -0
- package/examples/ownership-transfer/main.aug.md +9 -53
- package/examples/ownership-transfer/resource.aug +2 -1
- package/examples/ownership-transfer/resource.aug.md +12 -71
- package/examples/packages/app/.aug-spec/manifest.json +1 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
- package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
- package/examples/packages/app/main.aug +1 -0
- package/examples/packages/app/main.aug.md +6 -26
- package/examples/packages/math/.aug-spec/manifest.json +1 -1
- package/examples/packages/math/aug-package.json +1 -1
- package/examples/packages/math/src/arithmetic.aug +2 -1
- package/examples/packages/math/src/arithmetic.aug.md +9 -51
- package/examples/packages/math/src/export.aug +1 -0
- package/examples/packages/math/src/export.aug.md +3 -13
- package/examples/visibility/.aug-spec/manifest.json +1 -1
- package/examples/visibility/counter.aug +4 -3
- package/examples/visibility/counter.aug.md +12 -68
- package/examples/visibility/main.aug +1 -0
- package/examples/visibility/main.aug.md +6 -32
- package/examples/weather-api/.aug-spec/manifest.json +8 -0
- package/examples/weather-api/AGENTS.md +17 -0
- package/examples/weather-api/README.md +19 -0
- package/examples/weather-api/forecasts.aug +47 -0
- package/examples/weather-api/forecasts.aug.md +32 -0
- package/examples/weather-api/main.aug +4 -0
- package/examples/weather-api/main.aug.md +15 -0
- package/examples/weather-api/main.yaml +5 -0
- package/examples/weather-api/weather.http +5 -0
- package/package.json +3 -4
- package/scripts/bootstrap-native.mjs +181 -106
- package/scripts/native-setup.mjs +98 -0
- package/scripts/native-toolchain.mjs +28 -0
- package/src/builtins.js +1 -1
- package/src/checker.js +259 -72
- package/src/cli.js +114 -20
- package/src/codegen.js +1 -1
- package/src/config.js +1 -1
- package/src/contracts.js +10 -0
- package/src/editor.js +71 -16
- package/src/fixes.js +90 -2
- package/src/formatter.js +19 -8
- package/src/git-packages.js +110 -0
- package/src/help.js +24 -23
- package/src/http-contracts.js +14 -0
- package/src/http-policies.js +5 -5
- package/src/libraries.js +1 -1
- package/src/lsp.js +14 -5
- package/src/native.js +19 -13
- package/src/navigation.js +4 -2
- package/src/openapi.js +5 -4
- package/src/package-locking.js +45 -0
- package/src/package-manager.js +251 -67
- package/src/parser.js +13 -5
- package/src/policies.js +3 -3
- package/src/project-init.js +78 -4
- package/src/project.js +9 -7
- package/src/semantic.js +46 -2
- package/src/snippets.js +59 -0
- package/src/spec-hints.js +56 -0
- package/src/spec-tree.js +241 -0
- package/src/spec.js +626 -303
- package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
- package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
- package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
- package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
- package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
- package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
- package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
- package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
- package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
- package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
- package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
- package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
- package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
- package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
- /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/openapi.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { callableResult } from "./contracts.js";
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
import { schemaType } from "./schemas.js";
|
|
3
4
|
import { callableDocumentation } from "./documentation.js";
|
|
@@ -81,7 +82,7 @@ export function generateOpenApi(checked) {
|
|
|
81
82
|
result.push({ status: fn.endpoint?.status ?? 200, type: primitive('void') });
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
|
-
const type = checked.expressionTypes.get(expr) ??
|
|
85
|
+
const type = checked.expressionTypes.get(expr) ?? callableResult(checked, fn);
|
|
85
86
|
if (expr.kind === 'call' && expr.callee.kind === 'name' && type.name === 'HttpResponse') {
|
|
86
87
|
if (expr.callee.name !== 'HttpResponse') {
|
|
87
88
|
const def = project.scopes.get(fn.span.file)?.get(expr.callee.name);
|
|
@@ -125,8 +126,8 @@ export function generateOpenApi(checked) {
|
|
|
125
126
|
}
|
|
126
127
|
result.push({ status: fn.endpoint?.status ?? 200, type });
|
|
127
128
|
});
|
|
128
|
-
if (!result.length && fn.
|
|
129
|
-
result.push({ status: fn.endpoint?.status ?? 200, type:
|
|
129
|
+
if (!result.length && callableResult(checked, fn).name !== 'HttpResponse')
|
|
130
|
+
result.push({ status: fn.endpoint?.status ?? 200, type: callableResult(checked, fn) });
|
|
130
131
|
return result;
|
|
131
132
|
};
|
|
132
133
|
const served = new Map();
|
|
@@ -152,7 +153,7 @@ export function generateOpenApi(checked) {
|
|
|
152
153
|
current.schema = { oneOf: [current.schema, value] };
|
|
153
154
|
};
|
|
154
155
|
if (endpoint.streams) {
|
|
155
|
-
const item =
|
|
156
|
+
const item = callableResult(checked, fn), sse = item.name === 'ServerEvent';
|
|
156
157
|
const itemSchema = sse ? { type: 'object', required: ['data'], properties: { data: { type: 'string', contentMediaType: 'application/json', contentSchema: schema(item.args[0], fn.span) }, id: { type: 'string' }, event: { type: 'string' }, retry: { type: 'integer', minimum: 0 } } } : schema(item, fn.span);
|
|
157
158
|
responses[endpoint.status] = { description: 'Streaming response', content: { [sse ? 'text/event-stream' : item.name === 'Html' ? 'text/html' : 'application/octet-stream']: { itemSchema } } };
|
|
158
159
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/** Serialize writers while allowing independent projects to share immutable cached Git objects. */
|
|
4
|
+
export function withPackageLock(path, action) {
|
|
5
|
+
const deadline = Date.now() + 30000;
|
|
6
|
+
while (true) {
|
|
7
|
+
try {
|
|
8
|
+
mkdirSync(path);
|
|
9
|
+
break;
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
if (!error || typeof error !== 'object' || !('code' in error) || error.code !== 'EEXIST')
|
|
13
|
+
throw error;
|
|
14
|
+
let stale = false;
|
|
15
|
+
try {
|
|
16
|
+
const pid = Number(readFileSync(join(path, 'pid'), 'utf8'));
|
|
17
|
+
if (!Number.isSafeInteger(pid) || pid < 1)
|
|
18
|
+
throw new Error('Invalid lock owner');
|
|
19
|
+
try {
|
|
20
|
+
process.kill(pid, 0);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
stale = !!error && typeof error === 'object' && 'code' in error && error.code === 'ESRCH';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
stale = existsSync(path) && Date.now() - statSync(path).mtimeMs > 180000;
|
|
28
|
+
}
|
|
29
|
+
if (stale) {
|
|
30
|
+
rmSync(path, { recursive: true, force: true });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (Date.now() >= deadline)
|
|
34
|
+
throw new Error('Another August package installation is still running. Let it finish, then retry. Lock: ' + path);
|
|
35
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
writeFileSync(join(path, 'pid'), String(process.pid));
|
|
40
|
+
return action();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
rmSync(path, { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
}
|
package/src/package-manager.js
CHANGED
|
@@ -2,9 +2,25 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import { x as extractArchive } from 'tar';
|
|
5
6
|
import { loadConfig } from "./config.js";
|
|
7
|
+
import { parse } from "./parser.js";
|
|
8
|
+
import { isGitSource, materializeGit, sourceAlias } from "./git-packages.js";
|
|
9
|
+
import { agentInstructions } from "./project-init.js";
|
|
10
|
+
import { withPackageLock } from "./package-locking.js";
|
|
6
11
|
export const compilerVersion = () => JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
7
12
|
export const packageAlias = (name) => /^[a-z][a-z0-9_]*$/.test(name) && name !== 'august';
|
|
13
|
+
/** Repository imports declare their dependencies beside the code that uses them. */
|
|
14
|
+
export function packageSpecifications(sourceRoot, declared, overrides = new Map()) {
|
|
15
|
+
const specifications = { ...declared };
|
|
16
|
+
for (const path of sourcePaths(sourceRoot)) {
|
|
17
|
+
const file = parse(path, overrides.get(path) ?? readFileSync(path, 'utf8')).file;
|
|
18
|
+
for (const item of file.items)
|
|
19
|
+
if (item.kind === 'import' && isGitSource(item.from[0]))
|
|
20
|
+
specifications[sourceAlias(item.from[0])] = item.from[0];
|
|
21
|
+
}
|
|
22
|
+
return ordered(specifications);
|
|
23
|
+
}
|
|
8
24
|
const version = /^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/;
|
|
9
25
|
const npmName = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
10
26
|
const json = (file) => JSON.parse(readFileSync(file, 'utf8'));
|
|
@@ -38,8 +54,11 @@ export function sourcePaths(root) {
|
|
|
38
54
|
if (entry.name.startsWith('.') || ['node_modules', 'dist'].includes(entry.name))
|
|
39
55
|
continue;
|
|
40
56
|
const file = join(root, entry.name);
|
|
41
|
-
if (entry.isSymbolicLink())
|
|
42
|
-
|
|
57
|
+
if (entry.isSymbolicLink()) {
|
|
58
|
+
if (entry.name.endsWith('.aug'))
|
|
59
|
+
throw new Error(`Package source cannot contain a symbolic link: ${file}`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
43
62
|
if (entry.isDirectory())
|
|
44
63
|
result.push(...sourcePaths(file));
|
|
45
64
|
else if (entry.isFile() && entry.name.endsWith('.aug'))
|
|
@@ -48,7 +67,10 @@ export function sourcePaths(root) {
|
|
|
48
67
|
return result;
|
|
49
68
|
}
|
|
50
69
|
export function readPackage(directory) {
|
|
51
|
-
const manifest = json(join(directory, 'aug-package.json'))
|
|
70
|
+
const manifest = existsSync(join(directory, 'aug-package.json')) ? json(join(directory, 'aug-package.json')) : {
|
|
71
|
+
format: 1, name: 'aug-' + sourceAlias(realpathSync(directory)), version: '0.0.0', compiler: compilerVersion(),
|
|
72
|
+
source: existsSync(join(directory, 'export.aug')) ? '.' : 'src', dependencies: {}
|
|
73
|
+
};
|
|
52
74
|
if (manifest.format !== 1 || !npmName.test(manifest.name ?? '') || !version.test(manifest.version ?? '') ||
|
|
53
75
|
manifest.compiler !== compilerVersion())
|
|
54
76
|
throw new Error(`Invalid August package or compiler mismatch in ${directory}; expected compiler ${compilerVersion()}`);
|
|
@@ -64,12 +86,14 @@ export function readPackage(directory) {
|
|
|
64
86
|
throw new Error(`Invalid package dependency ${alias}`);
|
|
65
87
|
normalizeSpecifier(spec, directory, false);
|
|
66
88
|
}
|
|
67
|
-
const published = json(join(directory, 'package.json'));
|
|
68
|
-
if (published.name !== manifest.name || published.version !== manifest.version)
|
|
89
|
+
const published = existsSync(join(directory, 'package.json')) ? json(join(directory, 'package.json')) : undefined;
|
|
90
|
+
if (published && (published.name !== manifest.name || published.version !== manifest.version))
|
|
69
91
|
throw new Error('package.json and aug-package.json names/versions must match');
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
throw new Error(
|
|
92
|
+
const configuration = loadConfig(directory);
|
|
93
|
+
if (configuration.diagnostics.length)
|
|
94
|
+
throw new Error(`Invalid package configuration in ${directory}: ${configuration.diagnostics.map(issue => issue.message).join('; ')}`);
|
|
95
|
+
manifest.dependencies = { ...configuration.config.packages, ...manifest.dependencies };
|
|
96
|
+
const declared = manifest.dependencies ?? {};
|
|
73
97
|
for (const alias of Object.keys(declared))
|
|
74
98
|
assertAlias(sourceRoot, alias);
|
|
75
99
|
return { manifest, sourceRoot };
|
|
@@ -81,6 +105,8 @@ function assertAlias(root, alias) {
|
|
|
81
105
|
throw new Error(`Package alias ${alias} conflicts with a local module`);
|
|
82
106
|
}
|
|
83
107
|
function normalizeSpecifier(spec, root, requirePath = true) {
|
|
108
|
+
if (isGitSource(spec))
|
|
109
|
+
return spec;
|
|
84
110
|
if (spec.startsWith('npm:')) {
|
|
85
111
|
const match = /^npm:((?:@[^/]+\/)?[^@]+)@(.+)$/.exec(spec);
|
|
86
112
|
if (!match || !npmName.test(match[1]) || !version.test(match[2]))
|
|
@@ -101,7 +127,7 @@ function normalizeSpecifier(spec, root, requirePath = true) {
|
|
|
101
127
|
}
|
|
102
128
|
function packageDigest(directory, sourceRoot) {
|
|
103
129
|
const hash = createHash('sha256');
|
|
104
|
-
for (const file of [join(directory, 'aug-package.json'), join(directory, 'package.json'), ...sourcePaths(sourceRoot)].sort()) {
|
|
130
|
+
for (const file of [join(directory, 'aug-package.json'), join(directory, 'package.json'), ...sourcePaths(sourceRoot)].filter(existsSync).sort()) {
|
|
105
131
|
hash.update(relative(directory, file).replaceAll('\\', '/'));
|
|
106
132
|
hash.update('\0');
|
|
107
133
|
hash.update(readFileSync(file));
|
|
@@ -111,7 +137,7 @@ function packageDigest(directory, sourceRoot) {
|
|
|
111
137
|
}
|
|
112
138
|
/** Compilation reads only a verified installed snapshot. It never fetches dependencies. */
|
|
113
139
|
export function projectPackages(root, specifications, sourceFolder = root) {
|
|
114
|
-
const result = { roots: new Map(), scopes: new Map(), diagnostics: [] };
|
|
140
|
+
const result = { roots: new Map(), scopes: new Map(), diagnostics: [], specifications };
|
|
115
141
|
if (!Object.keys(specifications).length)
|
|
116
142
|
return result;
|
|
117
143
|
try {
|
|
@@ -133,7 +159,7 @@ export function projectPackages(root, specifications, sourceFolder = root) {
|
|
|
133
159
|
if (result.scopes.has(entry.path))
|
|
134
160
|
throw new Error('Duplicate package lock path');
|
|
135
161
|
manifests.set(entry.path, manifest);
|
|
136
|
-
result.scopes.set(entry.path, { ...entry, directory, sourceRoot });
|
|
162
|
+
result.scopes.set(entry.path, { ...entry, directory, sourceRoot, specifications: manifest.dependencies ?? {} });
|
|
137
163
|
}
|
|
138
164
|
verifyIdentities(lock.packages);
|
|
139
165
|
for (const scope of result.scopes.values()) {
|
|
@@ -179,76 +205,208 @@ export function projectPackages(root, specifications, sourceFolder = root) {
|
|
|
179
205
|
}
|
|
180
206
|
function npm(args, cwd) {
|
|
181
207
|
const process = spawnSync('npm', args, { cwd, encoding: 'utf8', timeout: 120000 });
|
|
182
|
-
if (process.error
|
|
183
|
-
throw new Error(process.error
|
|
208
|
+
if (process.error)
|
|
209
|
+
throw new Error(`Cannot install August packages: ${'code' in process.error && process.error.code === 'ENOENT' ? 'npm is missing from PATH. Install Node.js 24 or newer, which includes npm.' : process.error.message}\nRetry aug run after fixing the package installer.`);
|
|
210
|
+
if (process.status !== 0)
|
|
211
|
+
throw new Error(`August package installation failed.\n${(process.stderr || process.stdout || `npm exited ${process.status}`).trim()}\nCheck the package versions and paths in main.yaml, your network connection, and npm registry configuration. Retry aug run; use aug install for an explicit installation.`);
|
|
184
212
|
return process.stdout;
|
|
185
213
|
}
|
|
186
|
-
|
|
214
|
+
/** Running an application prepares its declared packages; checking remains read-only. */
|
|
215
|
+
export function prepareRunPackages(root, offline = false) {
|
|
216
|
+
const loaded = loadConfig(root);
|
|
217
|
+
if (loaded.diagnostics.length)
|
|
218
|
+
return; // The checker renders the configuration's source diagnostics.
|
|
219
|
+
const library = isLibrary(root) ? readPackage(root) : undefined;
|
|
220
|
+
const specifications = packageSpecifications(library?.sourceRoot ?? root, library?.manifest.dependencies ?? loaded.config.packages);
|
|
221
|
+
if (!Object.keys(specifications).length)
|
|
222
|
+
return;
|
|
223
|
+
const lockPath = join(root, 'aug.lock.json');
|
|
224
|
+
let lock;
|
|
225
|
+
if (existsSync(lockPath)) {
|
|
226
|
+
try {
|
|
227
|
+
lock = json(lockPath);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
throw new Error('aug.lock.json is unreadable. Restore it from version control or run aug install to recreate it.');
|
|
231
|
+
}
|
|
232
|
+
if (lock?.format !== 1 || !Array.isArray(lock.packages) || !lock.specifications || typeof lock.specifications !== 'object')
|
|
233
|
+
throw new Error('aug.lock.json has an unsupported structure. Run aug install to recreate it.');
|
|
234
|
+
}
|
|
235
|
+
const matching = lock?.compiler === compilerVersion() && sameSpecifications(lock.specifications, specifications);
|
|
236
|
+
if (!matching) {
|
|
237
|
+
process.stderr.write('Installing August packages declared by imports and main.yaml…\n');
|
|
238
|
+
installPackages(root, false, offline);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const snapshot = resolve(root, '.aug-packages');
|
|
242
|
+
const missing = lock.packages.some(entry => {
|
|
243
|
+
if (typeof entry.path !== 'string' || isAbsolute(entry.path) || !inside(snapshot, resolve(snapshot, entry.path)))
|
|
244
|
+
throw new Error('Package lock contains a path outside its snapshot. Run aug install to recreate it.');
|
|
245
|
+
return !existsSync(resolve(snapshot, entry.path));
|
|
246
|
+
});
|
|
247
|
+
if (missing) {
|
|
248
|
+
process.stderr.write('Restoring August packages from aug.lock.json…\n');
|
|
249
|
+
installPackages(root, true, offline);
|
|
250
|
+
}
|
|
251
|
+
// projectPackages checks contents and integrity before compilation. Changed installed sources are never silently replaced.
|
|
252
|
+
}
|
|
253
|
+
export function installPackages(root, frozen = false, offline = false, update = false) {
|
|
254
|
+
return withPackageLock(join(root, '.aug-install.lock'), () => installLocked(root, frozen, offline, update));
|
|
255
|
+
}
|
|
256
|
+
function installLocked(root, frozen, offline, update) {
|
|
257
|
+
if (frozen && update)
|
|
258
|
+
throw new Error('--frozen and --update cannot be used together.');
|
|
187
259
|
const loaded = loadConfig(root);
|
|
188
260
|
if (loaded.diagnostics.length)
|
|
189
261
|
throw new Error(loaded.diagnostics.map(issue => issue.message).join('\n'));
|
|
190
|
-
const library =
|
|
191
|
-
|
|
192
|
-
preparePackage(root);
|
|
193
|
-
const specifications = ordered(library?.dependencies ?? loaded.config.packages);
|
|
262
|
+
const library = isLibrary(root) ? readPackage(root) : undefined;
|
|
263
|
+
const specifications = packageSpecifications(library?.sourceRoot ?? root, library?.manifest.dependencies ?? loaded.config.packages);
|
|
194
264
|
for (const alias of Object.keys(specifications))
|
|
195
|
-
assertAlias(library
|
|
265
|
+
assertAlias(library?.sourceRoot ?? root, alias);
|
|
196
266
|
const lockPath = join(root, 'aug.lock.json');
|
|
197
267
|
const previous = existsSync(lockPath) ? json(lockPath) : undefined;
|
|
198
|
-
const same = previous?.compiler === compilerVersion() && sameSpecifications(previous.specifications, specifications);
|
|
268
|
+
const same = !update && previous?.compiler === compilerVersion() && sameSpecifications(previous.specifications, specifications);
|
|
199
269
|
if (frozen && !same)
|
|
200
270
|
throw new Error('Frozen installation requires a matching aug.lock.json');
|
|
271
|
+
return installSourceGraph(root, specifications, frozen, offline, same ? previous : undefined);
|
|
272
|
+
}
|
|
273
|
+
const isLibrary = (root) => existsSync(join(root, 'aug-package.json')) ||
|
|
274
|
+
!existsSync(join(root, 'main.aug')) && (existsSync(join(root, 'export.aug')) || existsSync(join(root, 'src/export.aug')));
|
|
275
|
+
const selectedSource = (file) => file.endsWith('.aug') || ['aug-package.json', 'package.json', 'main.yaml', 'README.md', 'LICENSE'].includes(file);
|
|
276
|
+
function copySource(origin, destination) {
|
|
277
|
+
let bytes = 0, count = 0;
|
|
278
|
+
const copy = (folder) => {
|
|
279
|
+
for (const entry of readdirSync(folder, { withFileTypes: true })) {
|
|
280
|
+
if (entry.name.startsWith('.') || ['node_modules', 'dist'].includes(entry.name))
|
|
281
|
+
continue;
|
|
282
|
+
const file = join(folder, entry.name), name = relative(origin, file);
|
|
283
|
+
if (entry.isDirectory())
|
|
284
|
+
copy(file);
|
|
285
|
+
else if (selectedSource(name)) {
|
|
286
|
+
if (!entry.isFile())
|
|
287
|
+
throw new Error('Package source must contain regular files: ' + name);
|
|
288
|
+
const data = readFileSync(file);
|
|
289
|
+
bytes += data.length;
|
|
290
|
+
if (++count > 10000 || bytes > 32 * 1024 * 1024)
|
|
291
|
+
throw new Error('Source package exceeds 10,000 files or 32 MiB.');
|
|
292
|
+
mkdirSync(dirname(join(destination, name)), { recursive: true });
|
|
293
|
+
writeFileSync(join(destination, name), data);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
copy(origin);
|
|
298
|
+
}
|
|
299
|
+
function unpackSource(archive, destination) {
|
|
300
|
+
let bytes = 0, count = 0;
|
|
301
|
+
const paths = new Set();
|
|
302
|
+
extractArchive({ file: archive, cwd: destination, strip: 1, sync: true, strict: true, filter: (path, entry) => {
|
|
303
|
+
if (!('type' in entry))
|
|
304
|
+
throw new Error('Expected an archive entry.');
|
|
305
|
+
const parts = path.split('/');
|
|
306
|
+
if (isAbsolute(path) || path.includes('\\') || parts.some(part => part === '..'))
|
|
307
|
+
throw new Error('Package archive contains a path outside its folder.');
|
|
308
|
+
const name = parts.slice(1).join('/');
|
|
309
|
+
if (entry.type === 'Directory')
|
|
310
|
+
return false;
|
|
311
|
+
if (!selectedSource(name))
|
|
312
|
+
return false;
|
|
313
|
+
if (entry.type !== 'File' || !name || parts[0] !== 'package' || parts.slice(1).some(part => !part || part.startsWith('.')))
|
|
314
|
+
throw new Error('Package archive source must be regular files inside package/.');
|
|
315
|
+
if (paths.has(name))
|
|
316
|
+
throw new Error('Package archive repeats a source file: ' + name);
|
|
317
|
+
paths.add(name);
|
|
318
|
+
bytes += entry.size;
|
|
319
|
+
if (++count > 10000 || bytes > 32 * 1024 * 1024)
|
|
320
|
+
throw new Error('Source package exceeds 10,000 files or 32 MiB.');
|
|
321
|
+
return true;
|
|
322
|
+
} });
|
|
323
|
+
}
|
|
324
|
+
/** Git libraries use the same checked source graph as registry libraries. No remote program is executed. */
|
|
325
|
+
function installSourceGraph(root, specifications, frozen, offline, previous) {
|
|
201
326
|
const stage = realpathSync(mkdtempSync(join(root, '.aug-install-')));
|
|
327
|
+
const packages = new Map(), visited = new Map();
|
|
328
|
+
const gitSources = new Map();
|
|
329
|
+
const registry = {};
|
|
330
|
+
const locked = new Map((previous?.git ?? []).map(source => [source.request, source]));
|
|
331
|
+
const visit = (spec, owner) => {
|
|
332
|
+
const normalized = normalizeSpecifier(spec, owner);
|
|
333
|
+
if (visited.has(normalized))
|
|
334
|
+
return visited.get(normalized);
|
|
335
|
+
if (visited.size >= 1000)
|
|
336
|
+
throw new Error('Package graph exceeds 1,000 source packages.');
|
|
337
|
+
const identity = normalized.startsWith('file:') ? 'file:' + relative(root, normalized.slice(5)).replaceAll('\\', '/') : normalized;
|
|
338
|
+
const path = 'packages/' + sourceAlias(identity), directory = join(stage, path);
|
|
339
|
+
visited.set(normalized, path);
|
|
340
|
+
mkdirSync(directory, { recursive: true });
|
|
341
|
+
let origin = directory;
|
|
342
|
+
let source;
|
|
343
|
+
if (isGitSource(normalized)) {
|
|
344
|
+
source = materializeGit(normalized, directory, offline, locked.get(normalized));
|
|
345
|
+
gitSources.set(normalized, source);
|
|
346
|
+
}
|
|
347
|
+
else if (normalized.startsWith('file:') && lstatSync(normalized.slice(5)).isDirectory()) {
|
|
348
|
+
origin = normalized.slice(5);
|
|
349
|
+
copySource(origin, directory);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const transport = join(stage, 'transport', sourceAlias(normalized));
|
|
353
|
+
mkdirSync(transport, { recursive: true });
|
|
354
|
+
const request = normalized.startsWith('npm:') ? normalized.slice(4) : normalized.slice(5);
|
|
355
|
+
const packed = JSON.parse(npm(['pack', request, '--ignore-scripts', '--json', '--pack-destination', transport,
|
|
356
|
+
...(offline ? ['--offline'] : [])], transport))[0];
|
|
357
|
+
if (!packed?.filename || !/^sha512-[A-Za-z0-9+/=]+$/.test(packed.integrity ?? ''))
|
|
358
|
+
throw new Error('Package archive is missing its SHA-512 integrity.');
|
|
359
|
+
registry[normalized] = { integrity: packed.integrity, name: packed.name, version: packed.version };
|
|
360
|
+
const archive = join(transport, basename(packed.filename));
|
|
361
|
+
const actual = 'sha512-' + createHash('sha512').update(readFileSync(archive)).digest('base64');
|
|
362
|
+
if (actual !== packed.integrity)
|
|
363
|
+
throw new Error('Package archive integrity mismatch.');
|
|
364
|
+
if (frozen && JSON.stringify(previous?.npm?.[normalized]) !== JSON.stringify(registry[normalized]))
|
|
365
|
+
throw new Error('Frozen package archive changed. Publish a new version instead of replacing an archive.');
|
|
366
|
+
unpackSource(archive, directory);
|
|
367
|
+
}
|
|
368
|
+
if (!existsSync(join(directory, 'aug-package.json'))) {
|
|
369
|
+
const folder = existsSync(join(directory, 'export.aug')) ? '.' : 'src';
|
|
370
|
+
const published = existsSync(join(directory, 'package.json')) ? json(join(directory, 'package.json')) : undefined;
|
|
371
|
+
writeJson(join(directory, 'aug-package.json'), { format: 1,
|
|
372
|
+
name: published?.name ?? '@git/' + sourceAlias(source ? source.repository + '/' + source.folder : identity),
|
|
373
|
+
version: published?.version ?? (source ? '0.0.0-git.' + source.commit : '0.0.0'),
|
|
374
|
+
compiler: compilerVersion(), source: folder, dependencies: published?.dependencies ?? {} });
|
|
375
|
+
}
|
|
376
|
+
const manifest = json(join(directory, 'aug-package.json'));
|
|
377
|
+
// A Git folder owns its August manifest. npm metadata and lifecycle scripts have no role here.
|
|
378
|
+
const dependencies = packageSpecifications(resolve(directory, manifest.source), { ...loadConfig(directory).config.packages, ...manifest.dependencies });
|
|
379
|
+
manifest.dependencies = dependencies;
|
|
380
|
+
writeJson(join(directory, 'aug-package.json'), manifest);
|
|
381
|
+
writeJson(join(directory, 'package.json'), { name: manifest.name, version: manifest.version, private: true, dependencies });
|
|
382
|
+
const { sourceRoot } = readPackage(directory);
|
|
383
|
+
const entry = { path, name: manifest.name, version: manifest.version, source: manifest.source,
|
|
384
|
+
digest: packageDigest(directory, sourceRoot), dependencies: {} };
|
|
385
|
+
packages.set(path, entry);
|
|
386
|
+
for (const [alias, request] of Object.entries(dependencies)) {
|
|
387
|
+
entry.dependencies[alias] = visit(request, origin);
|
|
388
|
+
verifyReference(request, packages.get(entry.dependencies[alias]));
|
|
389
|
+
}
|
|
390
|
+
return path;
|
|
391
|
+
};
|
|
202
392
|
try {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
...(offline ? ['--offline'] : [])], stage);
|
|
212
|
-
const packages = new Map();
|
|
213
|
-
const visit = (directory) => {
|
|
214
|
-
const actual = realpathSync(directory);
|
|
215
|
-
if (!inside(stage, actual))
|
|
216
|
-
throw new Error('Package installer did not create a self-contained snapshot');
|
|
217
|
-
const path = relative(stage, actual).replaceAll('\\', '/');
|
|
218
|
-
if (packages.has(path))
|
|
219
|
-
return path;
|
|
220
|
-
const { manifest, sourceRoot } = readPackage(actual);
|
|
221
|
-
const entry = { path, name: manifest.name, version: manifest.version, source: manifest.source,
|
|
222
|
-
digest: packageDigest(actual, sourceRoot), dependencies: {} };
|
|
223
|
-
packages.set(path, entry);
|
|
224
|
-
for (const alias of Object.keys(manifest.dependencies ?? {})) {
|
|
225
|
-
let owner = actual;
|
|
226
|
-
while (inside(stage, owner) && !existsSync(join(owner, 'node_modules', alias, 'aug-package.json')))
|
|
227
|
-
owner = dirname(owner);
|
|
228
|
-
if (!inside(stage, owner))
|
|
229
|
-
throw new Error(`${manifest.name} is missing dependency ${alias}`);
|
|
230
|
-
entry.dependencies[alias] = visit(join(owner, 'node_modules', alias));
|
|
231
|
-
verifyReference(manifest.dependencies[alias], packages.get(entry.dependencies[alias]));
|
|
232
|
-
}
|
|
233
|
-
return path;
|
|
234
|
-
};
|
|
235
|
-
const roots = Object.fromEntries(Object.keys(specifications).map(alias => [alias, visit(join(stage, 'node_modules', alias))]));
|
|
236
|
-
const lock = { format: 1, compiler: compilerVersion(), specifications, roots,
|
|
237
|
-
packages: [...packages.values()].sort((a, b) => a.path.localeCompare(b.path)), npm: json(join(stage, 'package-lock.json')) };
|
|
238
|
-
verifyIdentities(lock.packages);
|
|
239
|
-
for (const [alias, path] of Object.entries(roots))
|
|
240
|
-
verifyReference(specifications[alias], packages.get(path));
|
|
241
|
-
if (frozen && JSON.stringify(lock.packages) !== JSON.stringify(previous.packages))
|
|
242
|
-
throw new Error('Frozen package contents changed; update the lock explicitly with aug install');
|
|
393
|
+
const roots = Object.fromEntries(Object.entries(specifications).map(([alias, request]) => [alias, visit(request, root)]));
|
|
394
|
+
verifyIdentities(packages.values());
|
|
395
|
+
const lock = { format: 1, compiler: compilerVersion(), specifications, roots, npm: registry,
|
|
396
|
+
git: [...gitSources.values()].sort((a, b) => a.request.localeCompare(b.request)),
|
|
397
|
+
packages: [...packages.values()].sort((a, b) => a.path.localeCompare(b.path)) };
|
|
398
|
+
if (frozen && JSON.stringify(lock.packages) !== JSON.stringify(previous?.packages))
|
|
399
|
+
throw new Error('Frozen package contents changed; use aug install --update to choose new revisions.');
|
|
400
|
+
rmSync(join(stage, 'transport'), { recursive: true, force: true });
|
|
243
401
|
const cache = join(root, '.aug-packages'), backup = join(root, '.aug-packages-old');
|
|
244
402
|
if (existsSync(backup))
|
|
245
|
-
throw new Error('Previous package install backup exists; inspect .aug-packages-old before installing');
|
|
403
|
+
throw new Error('Previous package install backup exists; inspect .aug-packages-old before installing.');
|
|
246
404
|
if (existsSync(cache))
|
|
247
405
|
renameSync(cache, backup);
|
|
248
406
|
try {
|
|
249
407
|
renameSync(stage, cache);
|
|
250
|
-
writeJson(
|
|
251
|
-
renameSync(
|
|
408
|
+
writeJson(join(root, 'aug.lock.json.tmp'), lock);
|
|
409
|
+
renameSync(join(root, 'aug.lock.json.tmp'), join(root, 'aug.lock.json'));
|
|
252
410
|
}
|
|
253
411
|
catch (error) {
|
|
254
412
|
rmSync(cache, { recursive: true, force: true });
|
|
@@ -263,16 +421,18 @@ export function installPackages(root, frozen = false, offline = false) {
|
|
|
263
421
|
rmSync(stage, { recursive: true, force: true });
|
|
264
422
|
}
|
|
265
423
|
}
|
|
266
|
-
export function initPackage(directory, name) {
|
|
424
|
+
export function initPackage(directory, name, npmMetadata = false) {
|
|
267
425
|
if (!npmName.test(name))
|
|
268
426
|
throw new Error('Package name must be an npm name, for example @owner/aug-math');
|
|
269
427
|
if (existsSync(directory) && readdirSync(directory).length)
|
|
270
428
|
throw new Error('Package init requires a new or empty directory');
|
|
271
429
|
mkdirSync(join(directory, 'src'), { recursive: true });
|
|
430
|
+
writeFileSync(join(directory, 'AGENTS.md'), agentInstructions);
|
|
272
431
|
const manifest = { format: 1, name, version: '0.1.0', compiler: compilerVersion(), source: 'src', dependencies: {} };
|
|
273
432
|
writeJson(join(directory, 'aug-package.json'), manifest);
|
|
274
|
-
|
|
275
|
-
|
|
433
|
+
if (npmMetadata)
|
|
434
|
+
writeJson(join(directory, 'package.json'), { name, version: manifest.version, description: 'An August source library',
|
|
435
|
+
files: ['src', '.aug-spec', 'aug-package.json', 'README.md', 'LICENSE'], exports: { './aug-package.json': './aug-package.json' }, dependencies: {} });
|
|
276
436
|
writeFileSync(join(directory, 'src/export.aug'), 'export add from arithmetic\n');
|
|
277
437
|
writeFileSync(join(directory, 'src/arithmetic.aug'), '/** Add two integers. @param left First value. @param right Second value. @return Their sum. */\nadd(int left, int right) returns int {\n return left + right\n}\n\ntest add {\n when addition {\n it adds_two_integers {\n assert(add(left=2, right=3) == 5)\n }\n }\n}\n');
|
|
278
438
|
writeFileSync(join(directory, 'README.md'), `# ${name}\n\nAugust ${compilerVersion()} source library. Public exports live in src/export.aug.\n`);
|
|
@@ -281,7 +441,7 @@ export function initPackage(directory, name) {
|
|
|
281
441
|
/** Synchronize transport metadata; August's manifest owns dependency aliases. */
|
|
282
442
|
export function preparePackage(root) {
|
|
283
443
|
const manifest = json(join(root, 'aug-package.json'));
|
|
284
|
-
const transport = json(join(root, 'package.json'));
|
|
444
|
+
const transport = existsSync(join(root, 'package.json')) ? json(join(root, 'package.json')) : {};
|
|
285
445
|
transport.name = manifest.name;
|
|
286
446
|
transport.version = manifest.version;
|
|
287
447
|
transport.dependencies = manifest.dependencies ?? {};
|
|
@@ -297,3 +457,27 @@ export function packPackage(root) {
|
|
|
297
457
|
throw new Error('npm pack returned no archive');
|
|
298
458
|
return join(destination, basename(result.filename));
|
|
299
459
|
}
|
|
460
|
+
/** Give a source package a short import name and install its verified dependency graph. */
|
|
461
|
+
export function addPackage(root, request, alias, offline = false) {
|
|
462
|
+
const loaded = loadConfig(root);
|
|
463
|
+
if (loaded.diagnostics.length)
|
|
464
|
+
throw new Error(loaded.diagnostics.map(issue => issue.message).join('\n'));
|
|
465
|
+
assertAlias(isLibrary(root) ? readPackage(root).sourceRoot : root, alias);
|
|
466
|
+
normalizeSpecifier(request, root);
|
|
467
|
+
const path = join(root, 'main.yaml'), existed = existsSync(path), before = existed ? readFileSync(path, 'utf8') : '';
|
|
468
|
+
const dependencies = { ...loaded.config.packages, [alias]: request };
|
|
469
|
+
const block = 'packages:\n' + Object.entries(ordered(dependencies)).map(([name, value]) => ' ' + name + ': ' + JSON.stringify(value)).join('\n') + '\n';
|
|
470
|
+
const expression = /^packages:[^\n]*(?:\n|$)(?:[ \t][^\n]*(?:\n|$)|\n)*/m;
|
|
471
|
+
const after = expression.test(before) ? before.replace(expression, block) : before.trimEnd() + (before.trim() ? '\n\n' : '') + block;
|
|
472
|
+
writeFileSync(path, after);
|
|
473
|
+
try {
|
|
474
|
+
return installPackages(root, false, offline);
|
|
475
|
+
}
|
|
476
|
+
catch (error) {
|
|
477
|
+
if (existed)
|
|
478
|
+
writeFileSync(path, before);
|
|
479
|
+
else
|
|
480
|
+
rmSync(path, { force: true });
|
|
481
|
+
throw error;
|
|
482
|
+
}
|
|
483
|
+
}
|
package/src/parser.js
CHANGED
|
@@ -416,7 +416,9 @@ class Parser {
|
|
|
416
416
|
while (!everything && this.match('and'))
|
|
417
417
|
names.push(this.expect('identifier').value);
|
|
418
418
|
this.expect('from');
|
|
419
|
-
const from = [this.expect('identifier').value];
|
|
419
|
+
const from = [this.at('string') ? this.take().value : this.expect('identifier').value];
|
|
420
|
+
if (!/^(?:https:\/\/|git\+(?:https|file):\/\/)/.test(from[0]) && this.tokens[this.position - 1].kind === 'string')
|
|
421
|
+
throw new ParseFailure({ ...start, code: 'IMPORT', message: 'A quoted import source must be a public repository URL' });
|
|
420
422
|
while (this.match('.'))
|
|
421
423
|
from.push(this.expect('identifier').value);
|
|
422
424
|
this.endStatement();
|
|
@@ -462,11 +464,13 @@ class Parser {
|
|
|
462
464
|
const header = this.parseTypeParams();
|
|
463
465
|
const fields = this.parseParams(true);
|
|
464
466
|
const validationErrors = [];
|
|
465
|
-
|
|
467
|
+
const validationDeclared = !!this.match('unless');
|
|
468
|
+
if (validationDeclared) {
|
|
466
469
|
validationErrors.push(this.parseType());
|
|
467
470
|
while (this.match('and') || this.match(','))
|
|
468
471
|
validationErrors.push(this.parseType());
|
|
469
472
|
}
|
|
473
|
+
const headerEnd = this.current().span.start;
|
|
470
474
|
let constructorBody = this.match('=>') ? this.parseBlock(start) : undefined;
|
|
471
475
|
let hasBody = !!constructorBody;
|
|
472
476
|
if (!constructorBody && (this.at('{') || this.at(':'))) {
|
|
@@ -486,7 +490,7 @@ class Parser {
|
|
|
486
490
|
if (!hasBody)
|
|
487
491
|
this.endStatement();
|
|
488
492
|
return { kind: 'class', record: true, name, ...header, fields, constructorBody,
|
|
489
|
-
validationErrors, implements: [], methods: [], span: this.span(start) };
|
|
493
|
+
validationErrors, validationDeclared, headerEnd, implements: [], methods: [], span: this.span(start) };
|
|
490
494
|
}
|
|
491
495
|
parseClass() {
|
|
492
496
|
const start = this.current().span;
|
|
@@ -502,6 +506,7 @@ class Parser {
|
|
|
502
506
|
implemented.push(this.parseType());
|
|
503
507
|
while (this.match(','))
|
|
504
508
|
implemented.push(this.parseType());
|
|
509
|
+
const headerEnd = this.current().span.start;
|
|
505
510
|
this.openBlock(start);
|
|
506
511
|
const methods = [];
|
|
507
512
|
const stateFields = [];
|
|
@@ -537,7 +542,7 @@ class Parser {
|
|
|
537
542
|
}
|
|
538
543
|
this.closeBrace();
|
|
539
544
|
return { kind: 'class', name, typeParams, typeConstraints, typeVariance, fields, stateFields, constructorBody,
|
|
540
|
-
implements: implemented, methods, span: this.span(start) };
|
|
545
|
+
implements: implemented, methods, headerEnd, span: this.span(start) };
|
|
541
546
|
}
|
|
542
547
|
parseInterface() {
|
|
543
548
|
const keyword = this.take();
|
|
@@ -638,13 +643,16 @@ class Parser {
|
|
|
638
643
|
} while (this.match(',') || this.match('and'));
|
|
639
644
|
}
|
|
640
645
|
}
|
|
646
|
+
const headerEnd = this.current().span.start;
|
|
641
647
|
const body = this.at('{') || this.at(':') ? this.parseBlock(start) : (this.endStatement(), undefined);
|
|
642
648
|
if (externC && body) {
|
|
643
649
|
throw new ParseFailure({ file: start.file, line: start.line, column: start.column,
|
|
644
650
|
message: 'extern C functions cannot have a body', code: 'PARSE' });
|
|
645
651
|
}
|
|
646
652
|
return { kind: 'function', name, typeParams, typeConstraints, typeVariance, params, returns, returnOwnership,
|
|
647
|
-
throws, changes, uses, body, externC, valueAbi, nativePure, endpoint, annotations,
|
|
653
|
+
throws, changes, uses, body, externC, valueAbi, nativePure, endpoint, annotations,
|
|
654
|
+
declared: { returns: clauses.has('returns') || clauses.has('streams'), errors: clauses.has('unless'),
|
|
655
|
+
changes: clauses.has('changes'), uses: clauses.has('uses') }, headerEnd, span: this.span(start) };
|
|
648
656
|
}
|
|
649
657
|
parseTypeParams() {
|
|
650
658
|
if (!this.match('<'))
|
package/src/policies.js
CHANGED
|
@@ -85,11 +85,11 @@ export function projectPolicies(project) {
|
|
|
85
85
|
if (!params.some(param => (param.label ?? param.name) === label))
|
|
86
86
|
report(node.span, `@param ${label} does not name a public input of ${node.name}`, 'DOC');
|
|
87
87
|
for (const tag of doc.tags ?? []) {
|
|
88
|
-
if (['return', 'returns'].includes(tag.name)
|
|
88
|
+
if (node.kind !== 'function' && ['return', 'returns'].includes(tag.name))
|
|
89
89
|
report(node.span, `@${tag.name} requires a value-returning callable`, 'DOC');
|
|
90
|
-
if (['throws', 'exception'].includes(tag.name)) {
|
|
90
|
+
if (node.kind !== 'function' && !(node.kind === 'class' && node.record && node.validationDeclared === false) && ['throws', 'exception'].includes(tag.name)) {
|
|
91
91
|
const name = tag.value.split(/\s/)[0];
|
|
92
|
-
const errors =
|
|
92
|
+
const errors = node.kind === 'class' ? node.validationErrors ?? [] : [];
|
|
93
93
|
if (!('annotations' in node && node.annotations?.length) && !errors.some(error => error.name === name))
|
|
94
94
|
report(node.span, `@${tag.name} ${name} is absent from ${node.name}'s unless contract`, 'DOC');
|
|
95
95
|
}
|