Skip to content

Commit 9075378

Browse files
authored
Merge pull request #3179 from itowlson/schema-moar-docs
Fuller and more explicit docs in manifest schema
2 parents c51984b + 8b3f38e commit 9075378

File tree

3 files changed

+415
-58
lines changed

3 files changed

+415
-58
lines changed

crates/manifest/src/schema/common.rs

Lines changed: 112 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,96 @@ use serde::{Deserialize, Serialize};
55

66
use wasm_pkg_common::{package::PackageRef, registry::Registry};
77

8-
/// Variable definition
8+
use super::json_schema;
9+
10+
/// The name of the application variable.
911
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1012
#[serde(deny_unknown_fields)]
1113
pub struct Variable {
12-
/// `required = true`
14+
/// Whether a value must be supplied at runtime. If not specified, required defaults
15+
/// to `false`, and `default` must be provided.
16+
///
17+
/// Example: `required = true`
18+
///
19+
/// Learn more: https://spinframework.dev/variables#adding-variables-to-your-applications
1320
#[serde(default, skip_serializing_if = "is_false")]
1421
pub required: bool,
15-
/// `default = "default value"`
22+
/// The value of the variable if no value is supplied at runtime. If specified,
23+
/// the value must be a string. If not specified, `required`` must be `true`.
24+
///
25+
/// Example: `default = "default value"`
26+
///
27+
/// Learn more: https://spinframework.dev/variables#adding-variables-to-your-applications
1628
#[serde(default, skip_serializing_if = "Option::is_none")]
1729
pub default: Option<String>,
18-
/// `secret = true`
30+
/// If set, this variable should be treated as sensitive.
31+
///
32+
/// Example: `secret = true`
33+
///
34+
/// Learn more: https://spinframework.dev/variables#adding-variables-to-your-applications
1935
#[serde(default, skip_serializing_if = "is_false")]
2036
pub secret: bool,
2137
}
2238

23-
/// Component source
39+
/// The file, package, or URL containing the component Wasm binary. This may be:
40+
///
41+
/// - The path to a Wasm file (relative to the manifest file)
42+
///
43+
/// Example: `source = "bin/cart.wasm"`
44+
///
45+
/// - The URL of a Wasm file downloadable over HTTP, accompanied by a digest to ensure integrity
46+
///
47+
/// Example: `source = { url = "https://example.com/example.wasm", digest = "sha256:6503...2375" }`
48+
///
49+
/// - The registry, package and version of a component from a registry
50+
///
51+
/// Example: `source = { registry = "ttl.sh", package = "user:registrytest", version="1.0.0" }`
52+
///
53+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
2454
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2555
#[serde(deny_unknown_fields, untagged)]
2656
pub enum ComponentSource {
27-
/// `"local.wasm"`
57+
/// `source = "bin/cart.wasm"`
58+
#[schemars(description = "")] // schema docs are on the parent
2859
Local(String),
29-
/// `{ ... }`
60+
/// `source = { url = "https://example.com/example.wasm", digest = "sha256:6503...2375" }`
61+
#[schemars(description = "")] // schema docs are on the parent
3062
Remote {
31-
/// `url = "https://example.test/remote.wasm"`
63+
/// The URL of the Wasm component binary.
64+
///
65+
/// Example: `url = "https://example.test/remote.wasm"`
66+
///
67+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
3268
url: String,
33-
/// `digest = `"sha256:abc123..."`
69+
/// The SHA256 digest of the Wasm component binary. This must be prefixed with `sha256:`.
70+
///
71+
/// Example: `digest = `"sha256:abc123..."`
72+
///
73+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
3474
digest: String,
3575
},
36-
/// `{ ... }`
76+
/// `source = { registry = "ttl.sh", package = "user:registrytest", version="1.0.0" }`
77+
#[schemars(description = "")] // schema docs are on the parent
3778
Registry {
38-
/// `registry = "example.com"`
79+
/// The registry containing the Wasm component binary.
80+
///
81+
/// Example: `registry = "example.com"`
82+
///
83+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
3984
#[schemars(with = "Option<String>")]
4085
registry: Option<Registry>,
41-
/// `package = "example:component"`
86+
/// The package containing the Wasm component binary.
87+
///
88+
/// Example: `package = "example:component"`
89+
///
90+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
4291
#[schemars(with = "String")]
4392
package: PackageRef,
44-
/// `version = "1.2.3"`
93+
/// The version of the package containing the Wasm component binary.
94+
///
95+
/// Example: `version = "1.2.3"`
96+
///
97+
/// Learn more: https://spinframework.dev/writing-apps#the-component-source
4598
version: String,
4699
},
47100
}
@@ -66,17 +119,33 @@ impl Display for ComponentSource {
66119
}
67120
}
68121

69-
/// WASI files mount
122+
/// The files the component is allowed to read. Each list entry is either:
123+
///
124+
/// - a glob pattern (e.g. "assets/**/*.jpg"); or
125+
///
126+
/// - a source-destination pair indicating where a host directory should be mapped in the guest (e.g. { source = "assets", destination = "/" })
127+
///
128+
/// Learn more: https://spinframework.dev/writing-apps#including-files-with-components
70129
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
71130
#[serde(deny_unknown_fields, untagged)]
72131
pub enum WasiFilesMount {
73132
/// `"images/*.png"`
133+
#[schemars(description = "")] // schema docs are on the parent
74134
Pattern(String),
75135
/// `{ ... }`
136+
#[schemars(description = "")] // schema docs are on the parent
76137
Placement {
77-
/// `source = "content/dir"`
138+
/// The directory to be made available in the guest.
139+
///
140+
/// Example: `source = "content/dir"`
141+
///
142+
/// Learn more: https://spinframework.dev/writing-apps#including-files-with-components
78143
source: String,
144+
/// The path where the `source` directory appears in the guest. Must be absolute.
145+
///
79146
/// `destination = "/"`
147+
///
148+
/// Learn more: https://spinframework.dev/writing-apps#including-files-with-components
80149
destination: String,
81150
},
82151
}
@@ -85,13 +154,30 @@ pub enum WasiFilesMount {
85154
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
86155
#[serde(deny_unknown_fields)]
87156
pub struct ComponentBuildConfig {
88-
/// `command = "cargo build"`
157+
/// The command or commands to build the application. If multiple commands
158+
/// are specified, they are run sequentially from left to right.
159+
///
160+
/// Example: `command = "cargo build"`, `command = ["npm install", "npm run build"]`
161+
///
162+
/// Learn more: https://spinframework.dev/build#setting-up-for-spin-build
89163
pub command: Commands,
90-
/// `workdir = "components/main"
164+
/// The working directory for the build command. If omitted, the build working
165+
/// directory is the directory containing `spin.toml`.
166+
///
167+
/// Example: `workdir = "components/main"
168+
///
169+
/// Learn more: https://spinframework.dev/build#overriding-the-working-directory
91170
#[serde(default, skip_serializing_if = "Option::is_none")]
92171
pub workdir: Option<String>,
93-
/// watch = ["src/**/*.rs"]
172+
/// Source files to use in `spin watch`. This is a set of paths or glob patterns (relative
173+
/// to the build working directory). A change to any matching file causes
174+
/// `spin watch` to rebuild the application before restarting the application.
175+
///
176+
/// Example: `watch = ["src/**/*.rs"]`
177+
///
178+
/// Learn more: https://spinframework.dev/running-apps#monitoring-applications-for-changes
94179
#[serde(default, skip_serializing_if = "Vec::is_empty")]
180+
#[schemars(with = "Vec<json_schema::WatchCommand>")]
95181
pub watch: Vec<String>,
96182
}
97183

@@ -106,13 +192,20 @@ impl ComponentBuildConfig {
106192
}
107193
}
108194

109-
/// Component build command or commands
195+
/// The command or commands to build the application. If multiple commands
196+
/// are specified, they are run sequentially from left to right.
197+
///
198+
/// Example: `command = "cargo build"`, `command = ["npm install", "npm run build"]`
199+
///
200+
/// Learn more: https://spinframework.dev/build#setting-up-for-spin-build
110201
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
111202
#[serde(untagged)]
112203
pub enum Commands {
113204
/// `command = "cargo build"`
205+
#[schemars(description = "")] // schema docs are on the parent
114206
Single(String),
115207
/// `command = ["cargo build", "wac encode compose-deps.wac -d my:pkg=app.wasm --registry fermyon.com"]`
208+
#[schemars(description = "")] // schema docs are on the parent
116209
Multiple(Vec<String>),
117210
}
118211

crates/manifest/src/schema/json_schema.rs

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,25 @@ pub struct HttpTriggerSchema {
3939
#[derive(JsonSchema)]
4040
#[schemars(untagged)]
4141
pub enum HttpRouteSchema {
42-
/// `route = "/user/:name/..."`
42+
/// The HTTP route that the trigger accepts. The route must begin with a `/``.
43+
/// The route may contain:
44+
///
45+
/// - Any number of single-segment wildcards, using the syntax `:name`. It matches only a single segment of a path, and allows further matching on segments beyond it.
46+
///
47+
/// - A trailing wildcard, using the syntax `/...`. This matches the given route and any route under it.
48+
///
49+
/// In particular, the route `/...` matches _all_ paths.
50+
///
51+
/// Example: `route = "/user/:name/..."`
52+
///
53+
/// Learn more: https://spinframework.dev/v3/http-trigger#http-trigger-routes
4354
Route(String),
44-
/// `route = { private = true }`
55+
/// The trigger does not response to any external HTTP request, but only to requests
56+
/// via local service chaining.
57+
///
58+
/// Example: `route = { private = true }`
59+
///
60+
/// Learn more: https://spinframework.dev/v3/http-trigger#private-endpoints
4561
Private(HttpPrivateEndpoint),
4662
}
4763

@@ -73,6 +89,80 @@ pub struct RedisTriggerSchema {
7389
address: Option<String>,
7490
}
7591

92+
/// The SQLite databases which the component is allowed to access. Databases are identified
93+
/// by label e.g. "default" or "analytics". Databases other than "default" must be mapped
94+
/// to a backing store in the runtime config. Use "spin up --sqlite" to run database setup scripts.
95+
///
96+
/// Example: `sqlite_databases = ["default", "my-database"]`
97+
///
98+
/// Learn more: https://spinframework.dev/sqlite-api-guide#preparing-an-sqlite-database
99+
#[allow(dead_code)]
100+
#[derive(JsonSchema)]
101+
#[serde(untagged)]
102+
pub enum SqliteDatabase {
103+
Label(String),
104+
}
105+
106+
/// The key-value stores which the component is allowed to access. Stores are identified
107+
/// by label e.g. "default" or "customer". Stores other than "default" must be mapped
108+
/// to a backing store in the runtime config.
109+
///
110+
/// Example: `key_value_stores = ["default", "my-store"]`
111+
///
112+
/// Learn more: https://spinframework.dev/kv-store-api-guide#custom-key-value-stores
113+
#[allow(dead_code)]
114+
#[derive(JsonSchema)]
115+
#[serde(untagged)]
116+
pub enum KeyValueStore {
117+
Label(String),
118+
}
119+
120+
/// The network destinations which the component is allowed to access.
121+
/// Each entry is in the form "(scheme)://(host)[:port]". Each element
122+
/// allows * as a wildcard e.g. "https://\*" (HTTPS on the default port
123+
/// to any destination) or "\*://localhost:\*" (any protocol to any port on
124+
/// localhost). The host part allows segment wildcards for subdomains
125+
/// e.g. "https://\*.example.com". Application variables are allowed using
126+
/// `{{ my_var }}`` syntax.
127+
///
128+
/// Example: `allowed_outbound_hosts = ["redis://myredishost.com:6379"]`
129+
///
130+
/// Learn more: https://spinframework.dev/http-outbound#granting-http-permissions-to-components
131+
#[allow(dead_code)]
132+
#[derive(JsonSchema)]
133+
#[serde(untagged)]
134+
pub enum AllowedOutboundHost {
135+
Host(String),
136+
}
137+
138+
/// The AI models which the component is allowed to access. For local execution, you must
139+
/// download all models; for hosted execution, you should check which models are available
140+
/// in your target environment.
141+
///
142+
/// Example: `ai_models = ["llama2-chat"]`
143+
///
144+
/// Learn more: https://spinframework.dev/serverless-ai-api-guide#using-serverless-ai-from-applications
145+
#[allow(dead_code)]
146+
#[derive(JsonSchema)]
147+
#[serde(untagged)]
148+
pub enum AIModel {
149+
Label(String),
150+
}
151+
152+
/// Source files to use in `spin watch`. This is a set of paths or glob patterns (relative
153+
/// to the build working directory). A change to any matching file causes
154+
/// `spin watch` to rebuild the application before restarting the application.
155+
///
156+
/// Example: `watch = ["src/**/*.rs"]`
157+
///
158+
/// Learn more: https://spinframework.dev/running-apps#monitoring-applications-for-changes
159+
#[allow(dead_code)]
160+
#[derive(JsonSchema)]
161+
#[serde(untagged)]
162+
pub enum WatchCommand {
163+
Command(String),
164+
}
165+
76166
pub fn toml_table(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
77167
schemars::schema::Schema::Object(schemars::schema::SchemaObject {
78168
instance_type: Some(schemars::schema::SingleOrVec::Single(Box::new(

0 commit comments

Comments
 (0)