From f1e42615244812ffb4ef1322c2b7c594942a8e87 Mon Sep 17 00:00:00 2001 From: Chris Rybicki Date: Wed, 8 May 2024 17:40:31 -0400 Subject: [PATCH] chore: fix missing docs for sim APIs (#6444) Fixes #6407 ## Checklist - [ ] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted) - [ ] Description explains motivation and solution - [ ] Tests added (always) - [ ] Docs updated (only required for features) - [ ] Added `pr/e2e-full` label if this feature requires end-to-end testing *By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*. --- .../docs/04-standard-library/sim/container.md | 338 ++++++++++++++++++ docs/docs/04-standard-library/sim/state.md | 264 ++++++++++++++ libs/wingsdk/scripts/docgen.mts | 54 ++- 3 files changed, 646 insertions(+), 10 deletions(-) create mode 100644 docs/docs/04-standard-library/sim/container.md create mode 100644 docs/docs/04-standard-library/sim/state.md diff --git a/docs/docs/04-standard-library/sim/container.md b/docs/docs/04-standard-library/sim/container.md new file mode 100644 index 00000000000..ba20fb021ad --- /dev/null +++ b/docs/docs/04-standard-library/sim/container.md @@ -0,0 +1,338 @@ +--- +title: Container +id: container +description: Runs a container in the Wing Simulator +keywords: + [ + Wing reference, + Wing language, + language, + Wing standard library, + Wing programming language, + docker, + container, + docker compose, + simulator + ] +--- + +The `sim.Container` resource allows running containers in the Wing Simulator: + +```js +bring sim; +bring http; + +let c = new sim.Container( + name: "http-echo", + image: "hashicorp/http-echo", + containerPort: 5678, + args: ["-text=bang"], +); + +test "send request" { + http.get("http://localhost:{c.hostPort}"); +} +``` + +There is also support for building containers from a local directory with a `Dockerfile`: + +```js +new sim.Container( + name: "my-service", + image: "./my-service", + containerPort: 8080, +); +``` + +### Retaining state + +When the Wing Console is closed, all containers are stopped and removed. +To retain the state of a container across console restarts, you can mount an anonymous volume: + +```js +new sim.Container( + name: "my-service", + image: "./my-service", + containerPort: 8080, + volumes: ["/var/data"], +); +``` + +Wing will automatically name each unnamed volume in `volumes`, and reuse the named +volumes across console restarts. + +## API + +* `name` - a name for the container. +* `image` - a name of a public Docker image to pull and run or a path to a local directory with a + `Dockerfile`. +* `containerPort` - a TCP port to expose from the container (optional). +* `env` - environment variables to set in the container. +* `args` - container entrypoint arguments +* `sourcePattern` - a glob pattern to use to match the files for calculating the source hash when + determining if a rebuild is needed. By default this is all the files in the docker build context + directory (and below). +* `sourceHash` - An explicit source hash that represents the container source. if not set, and + `sourcePattern` is set, the hash will be calculated based on the content of the source files. + +# API Reference + +## Resources + +### Container + +- *Implements:* ISimulatorResource + +Represents a container running in the Wing Simulator. + +#### Initializers + +```wing +bring sim; + +new sim.Container(props: ContainerProps); +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| props | ContainerProps | *No description.* | + +--- + +##### `props`Required + +- *Type:* ContainerProps + +--- + +#### Methods + +##### Preflight Methods + +| **Name** | **Description** | +| --- | --- | +| toSimulator | Convert this resource to a resource schema for the simulator. | + +--- + +##### `toSimulator` + +```wing +toSimulator(): ToSimulatorOutput +``` + +Convert this resource to a resource schema for the simulator. + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| onLiftType | A hook called by the Wing compiler once for each inflight host that needs to use this type inflight. | + +--- + +##### `onLiftType` + +```wing +bring sim; + +sim.Container.onLiftType(host: IInflightHost, ops: MutArray); +``` + +A hook called by the Wing compiler once for each inflight host that needs to use this type inflight. + +The list of requested inflight methods +needed by the inflight host are given by `ops`. + +This method is commonly used for adding permissions, environment variables, or +other capabilities to the inflight host. + +###### `host`Required + +- *Type:* IInflightHost + +--- + +###### `ops`Required + +- *Type:* MutArray<str> + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| hostPort | str | A token that resolves to the host port of this container. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `hostPort`Optional + +```wing +hostPort: str; +``` + +- *Type:* str + +A token that resolves to the host port of this container. + +--- + + + +## Structs + +### ContainerProps + +Initialization properties for `sim.Container`. + +#### Initializer + +```wing +bring sim; + +let ContainerProps = sim.ContainerProps{ ... }; +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| image | str | A name of a public Docker image to pull and run or a path to a local directory with a `Dockerfile`. | +| name | str | A name for the container. | +| args | MutArray<str> | Container arguments. | +| containerPort | num | Internal container port to expose. | +| env | MutMap<str> | Environment variables to set in the container. | +| sourceHash | str | An explicit source hash that represents the container source. | +| sourcePattern | str | A glob of local files to consider as input sources for the container, relative to the build context directory. | +| volumes | MutArray<str> | Volume mount points. | + +--- + +##### `image`Required + +```wing +image: str; +``` + +- *Type:* str + +A name of a public Docker image to pull and run or a path to a local directory with a `Dockerfile`. + +--- + +##### `name`Required + +```wing +name: str; +``` + +- *Type:* str + +A name for the container. + +--- + +##### `args`Optional + +```wing +args: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +Container arguments. + +--- + +##### `containerPort`Optional + +```wing +containerPort: num; +``` + +- *Type:* num +- *Default:* no port exposed + +Internal container port to expose. + +--- + +##### `env`Optional + +```wing +env: MutMap; +``` + +- *Type:* MutMap<str> +- *Default:* {} + +Environment variables to set in the container. + +--- + +##### `sourceHash`Optional + +```wing +sourceHash: str; +``` + +- *Type:* str +- *Default:* calculated based on the source files + +An explicit source hash that represents the container source. + +if not set, and `sourcePattern` +is set, the hash will be calculated based on the content of the source files. + +--- + +##### `sourcePattern`Optional + +```wing +sourcePattern: str; +``` + +- *Type:* str +- *Default:* all files + +A glob of local files to consider as input sources for the container, relative to the build context directory. + +--- + +##### `volumes`Optional + +```wing +volumes: MutArray; +``` + +- *Type:* MutArray<str> +- *Default:* [] + +Volume mount points. + +--- + +*Example* + +```wing +['/host:/container'] +``` + + + diff --git a/docs/docs/04-standard-library/sim/state.md b/docs/docs/04-standard-library/sim/state.md new file mode 100644 index 00000000000..7c908d57fd2 --- /dev/null +++ b/docs/docs/04-standard-library/sim/state.md @@ -0,0 +1,264 @@ +--- +title: State +id: state +description: Key/value in-memory state for the simulator. +keywords: + [ + Wing reference, + Wing language, + language, + Wing standard library, + Wing programming language, + In-memory state, + State, + Simulator + ] +--- + +The `sim.State` is a simple key/value in-memory store for the simulator with support for lazy +tokens. + +Consider a use case where there is an attribute of a simulated service that only gets resolved during initialization (e.g. the exposed port of a container). In order to create such resources, we need a way to obtain a lazy token that gets resolved during simulator initialization. It just so happens that we already have a mechanism like this, but it was not exposed as a public API. + +Use the preflight method `state.token(key)` to obtain a token that can be used to reference the +value of the state at runtime. + +During simulator app initialization (i.e. `cloud.OnDeploy` or `cloud.Service` startup), you must +call the inflight method `state.set(key, value)` to set the runtime value. The value will be +available at runtime through the inflight method `state.get(key)`, or via a resolved token. + +## Usage + +Let's say I want to create a simulated service that has property called `startTime` which returns +the time the service was started. This information is also known when the service is actually +initialized. + +```js +bring cloud; +bring sim; + +class MyService { + startTime: str; + + new() { + let state = new sim.State(); + + new cloud.Service(inflight () => { + state.set("start", std.Datetime.utcNow().toIso()); + }); + + this.startTime = state.token("start"); + } +} +``` + +In this example, the `startTime` property will resolve to a *simulator token* (something like +`${root/MyService/State#attrs.start)}`) which can be referenced ("lifted") into inflight context +naturally: + +```js +let s = new MyService(); + +new cloud.Function(inflight () => { + log("service start time is {s}"); +}); +``` + +This creates an implicit dependency between the `cloud.Function` and `MyService` such that only when +the state `start` is set, the `cloud.Function` will be initialized with the actual value. +# API Reference + +## Resources + +### State + +- *Implements:* ISimulatorResource + +Key/value in-memory state for the simulator. + +Use the preflight method `token(key)` to obtain a token that can be used to reference the value +of the state at runtime. + +During deployment (i.e. `cloud.OnDeploy` or `cloud.Service` startup), you must call the inflight +method `set(key, value)` to set the runtime value. The value will be available at runtime through +the inflight method `get(key)` (or resolved as a token). + +See tests for examples. + +#### Initializers + +```wing +bring sim; + +new sim.State(); +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | + +--- + +#### Methods + +##### Preflight Methods + +| **Name** | **Description** | +| --- | --- | +| token | Returns a token that can be used to retrieve the value of the state after the simulation has run. | +| toSimulator | Convert this resource to a resource schema for the simulator. | + +##### Inflight Methods + +| **Name** | **Description** | +| --- | --- | +| get | Gets the runtime state of this object. | +| set | Sets the state of runtime a runtime object. | +| tryGet | Checks if runtime state exists for this object and returns it's value. | + +--- + +##### `token` + +```wing +token(key: str): str +``` + +Returns a token that can be used to retrieve the value of the state after the simulation has run. + +###### `key`Required + +- *Type:* str + +The object key retrieved through the inflight `state.get()`. + +--- + +##### `toSimulator` + +```wing +toSimulator(): ToSimulatorOutput +``` + +Convert this resource to a resource schema for the simulator. + +##### `get` + +```wing +inflight get(key: str): Json +``` + +Gets the runtime state of this object. + +Throws if there is no value for the given key. + +###### `key`Required + +- *Type:* str + +The object's key. + +--- + +##### `set` + +```wing +inflight set(key: str, value: Json): void +``` + +Sets the state of runtime a runtime object. + +###### `key`Required + +- *Type:* str + +The object's key. + +--- + +###### `value`Required + +- *Type:* Json + +The object's value. + +--- + +##### `tryGet` + +```wing +inflight tryGet(key: str): Json? +``` + +Checks if runtime state exists for this object and returns it's value. + +If no value exists, +returns `nil`. + +###### `key`Required + +- *Type:* str + +The object's key. + +--- + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| onLiftType | A hook called by the Wing compiler once for each inflight host that needs to use this type inflight. | + +--- + +##### `onLiftType` + +```wing +bring sim; + +sim.State.onLiftType(host: IInflightHost, ops: MutArray); +``` + +A hook called by the Wing compiler once for each inflight host that needs to use this type inflight. + +The list of requested inflight methods +needed by the inflight host are given by `ops`. + +This method is commonly used for adding permissions, environment variables, or +other capabilities to the inflight host. + +###### `host`Required + +- *Type:* IInflightHost + +--- + +###### `ops`Required + +- *Type:* MutArray<str> + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | + +--- + +##### `node`Required + +```wing +node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + + + + + diff --git a/libs/wingsdk/scripts/docgen.mts b/libs/wingsdk/scripts/docgen.mts index c0e255f68d8..ed55c71c5ec 100644 --- a/libs/wingsdk/scripts/docgen.mts +++ b/libs/wingsdk/scripts/docgen.mts @@ -82,16 +82,32 @@ async function runDocgen( docCounter++; } +enum DocumentationFilter { + /** + * Generate docs for all modules, and require they all have .md files + */ + ALL_REQUIRE_MD, + /** + * Generate docs for all modules (even if they don't have .md files) + */ + ALL, + /** + * Generate docs only for modules with .md files + */ + ONLY_WITH_MD, +} + async function generateResourceApiDocs( - module: string, + folder: string, options: { docsPath: string; excludedFiles?: string[]; - allowUndocumented?: boolean; + jsiiModule?: string; + filter: DocumentationFilter; } ) { - const pathToFolder = join(rootDir, "src", module); - const { docsPath, excludedFiles = [], allowUndocumented = false } = options; + const pathToFolder = join(rootDir, "src", folder); + const { docsPath, excludedFiles = [], filter, jsiiModule = folder } = options; const cloudFiles = await readdir(pathToFolder); @@ -105,7 +121,10 @@ async function generateResourceApiDocs( (file) => !cloudFiles.includes(`${file}.md`) ); - if (undocumentedResources.length && !allowUndocumented) { + if ( + undocumentedResources.length && + filter === DocumentationFilter.ALL_REQUIRE_MD + ) { throw new Error( `Detected undocumented resources: ${undocumentedResources.join( ", " @@ -116,7 +135,15 @@ async function generateResourceApiDocs( // generate api reference for each cloud/submodule and append it to the doc file for (const subResource of cloudResources) { let header = ""; - if (undocumentedResources.includes(subResource)) { + + const hasMd = !undocumentedResources.includes(subResource); + if (!hasMd && filter === DocumentationFilter.ONLY_WITH_MD) { + continue; + } + + if (hasMd) { + header = await readFile(join(pathToFolder, `${subResource}.md`), "utf-8"); + } else { header = `\ --- title: ${toCamelCase(subResource)} @@ -124,11 +151,9 @@ id: ${toCamelCase(subResource)} --- `; - } else { - header = await readFile(join(pathToFolder, `${subResource}.md`), "utf-8"); } await runDocgen( - `${module}/${subResource}`, + `${jsiiModule}/${subResource}`, header, join(docsPath, `${subResource}.md`) ); @@ -147,16 +172,25 @@ for (const mod of publicModules) { await generateResourceApiDocs("cloud", { docsPath: getStdlibDocsDir("cloud"), excludedFiles: UNDOCUMENTED_CLOUD_FILES, + filter: DocumentationFilter.ALL_REQUIRE_MD, }); + await generateResourceApiDocs("ex", { docsPath: getStdlibDocsDir("ex"), excludedFiles: UNDOCUMENTED_EX_FILES, + filter: DocumentationFilter.ALL_REQUIRE_MD, }); await generateResourceApiDocs("std", { docsPath: getStdlibDocsDir("std"), excludedFiles: UNDOCUMENTED_STD_FILES, - allowUndocumented: true, + filter: DocumentationFilter.ALL, +}); + +await generateResourceApiDocs("target-sim", { + docsPath: getStdlibDocsDir("sim"), + filter: DocumentationFilter.ONLY_WITH_MD, + jsiiModule: "sim", }); console.log(