Smithy build projections and plugins
{
"version": "2.0",
"sources": [{
"path": "module.zip",
"root": "models",
"paths": [{"path": "service.smithy", "name": "public/service.smithy"}],
"globs": ["shared/**/*.json"]
}]
}{"url":"https://example.org/models.zip","format":"zip","root":"models","paths":["service.smithy"]}///|
test {
let model = @smithy.Loader::new()
.add_idl(
"forecast.smithy",
(
#|$version: "2"
#|
#|namespace example
#|
#|service Weather {
#| version: "2024-01-01"
#| operations: [GetForecast, GetDebugInfo]
#|}
#|
#|@readonly
#|operation GetForecast {}
#|
#|@internal
#|@readonly
#|operation GetDebugInfo {}
),
)
.assemble().model.unwrap()
let config = @build.BuildConfig::parse(
(
#|{
#| "version": "1.0",
#| "projections": {
#| "public": {
#| "transforms": [
#| {"name": "excludeShapesByTrait", "args": {"traits": ["internal"]}}
#| ]
#| }
#| }
#|}
),
)
let artifacts = @build.BuildRunner::new(config).run(model)
let public = @smithy.Loader::new()
.add_json("public.json", artifacts["public/model/model.json"])
.assemble().model.unwrap()
assert_eq(@smithy.Selector::parse("operation").select_ids(public), [
"example#GetForecast",
])
}{
"github": {
"repository": "owner/models",
"tag": "v1.2.3",
"asset": "models.tar.gz"
},
"format": "tgz",
"root": "package/models",
"globs": ["**/*.smithy"]
}{
"npm": { "package": "@scope/models", "version": "1.2.3" },
"root": "package/models",
"globs": ["**/*.smithy"]
}{
"maven": {
"repository": "https://repo.maven.apache.org/maven2",
"group": "software.amazon.smithy",
"artifact": "smithy-aws-traits",
"version": "1.72.0",
"checksum": "sha1"
}
}///|
test "read npm, Maven and GitHub inputs" {
let config = @build.BuildConfig::parse(
(
#|{
#| "version": "1.0",
#| "sources": [
#| {
#| "npm": { "package": "@example/weather-models", "version": "1.2.3" },
#| "root": "package/models",
#| "globs": ["**/*.smithy"]
#| },
#| {
#| "maven": {
#| "group": "software.amazon.smithy",
#| "artifact": "smithy-aws-traits",
#| "version": "1.72.0"
#| }
#| },
#| {
#| "github": {
#| "repository": "example/weather-models",
#| "tag": "v1.2.3",
#| "asset": "models.tar.gz"
#| },
#| "format": "tgz",
#| "root": "package/models",
#| "globs": ["**/*.smithy"]
#| }
#| ]
#|}
),
)
let kinds = config.sources.map(input => {
match input {
Npm(_) => "npm"
Maven(_) => "maven"
GitHub(_) => "github"
_ => "other"
}
})
assert_eq(kinds, ["npm", "maven", "github"])
let locations = config.sources.map(input => input.location().to_string())
assert_eq(locations[0], "https://registry.npmjs.org")
assert_eq(locations[1], "https://repo.maven.apache.org/maven2")
assert_eq(locations[2], "example/weather-models")
let range =
#|{
#| "version": "1.0",
#| "sources": [
#| {
#| "npm": { "package": "@example/weather-models", "version": "^1.2.0" },
#| "root": "package/models",
#| "globs": ["**/*.smithy"]
#| }
#| ]
#|}
try @build.BuildConfig::parse(range) catch {
@build.InvalidBuildConfig(message) => {
let expected = "npm requires a public registry base, package name and exact semantic version"
assert_eq(message, expected)
}
} noraise {
_ => fail("I expected the version range to fail")
}
}pub(all) struct BuildConfig {
version : String
sources : Array[BuildInput]
imports : Array[BuildInput]
cache_directory : CacheDirectory
credentials : Array[CredentialBinding]
offline : Bool
output_directory : String
projections : Array[ProjectionConfig]
plugins : Map[String, Json]
ignore_missing_plugins : Bool
} derive(Eq, Debug)fn BuildConfig::parse(source : String, environment? : Map[String, String]) -> BuildConfig raise BuildErrorfn BuildConfig::resolve_credentials(self : BuildConfig, environment : Map[String, String]) -> Credentials raise BuildErrorpub(all) enum BuildInput {
Npm(NpmArchive, Selection)
Maven(MavenArchive, Selection?)
GitHub(GitHubArchive, Selection, HttpUrl)
Remote(PublicArchive, Selection)
Local(RepositoryLocation)
Selected(RepositoryLocation, Selection)
} derive(Eq, Debug)fn BuildInput::with_location(self : BuildInput, location : RepositoryLocation) -> BuildInput raise BuildErrorpub struct BuildRunner {
config : BuildConfig
plugins : Map[String, (Model, Json) -> Map[String, String] raise BuildError]
sources : Map[String, String]
source_conflicts : Array[String]
source_origins : Set[String]
source_metadata : Set[String]
projection_imports : Map[String, Array[ModelInput]]
loader : () -> Loader
}fn BuildRunner::add_projection_import(self : BuildRunner, projection : String, input : ModelInput) -> BuildRunnerfn BuildRunner::add_source(self : BuildRunner, name : String, content : String, source_file? : String?) -> BuildRunnerfn BuildRunner::register_plugin(self : BuildRunner, name : String, execute : (Model, Json) -> Map[String, String] raise BuildError) -> BuildRunnerpub(all) struct CredentialBinding {
origin : HttpOrigin
source : CredentialSource
} derive(Eq, Debug)pub(all) enum CredentialSource {
BearerEnvironment(CredentialVariable)
BasicEnvironment(CredentialVariable, CredentialVariable)
} derive(Eq, Debug)pub(all) struct ProjectionConfig {
name : String
is_abstract : Bool
imports : Array[BuildInput]
transforms : Array[TransformConfig]
plugins : Map[String, Json]
} derive(Eq, Debug)