# Generated packages

The CUE packages that pravo init writes under cue.mod/gen, one per provider and one for pravo itself.

`pravo init` writes no file into the root. It writes CUE packages under `cue.mod/gen/`, and the root imports them.

| Import path | Contents |
|---|---|
| `pravo.dev/pravo` | `#Settings`, `#Output`, `#Env`, `#SecretEnv`, `#RemoteOutputs`, `#Movable` and the types of the `state` setting. |
| `pravo.dev/providers/<namespace>/<type>` | One provider: `#Provider`, with `#Resource`, `#Data`, `#Ephemeral` and `#Function` as members, and `#Lifecycle`. |
| `pravo.dev/providers/<host>/<namespace>/<type>` | A provider from a registry other than the default one. |

Work in an empty directory.

```cue file=main.cue
package demo

import (
	rnd "pravo.dev/providers/hashicorp/random"
	nul "pravo.dev/providers/hashicorp/null:null_"
)

$random: rnd.#Provider
$null:   nul.#Provider

pet:    $random.#Resource.random_pet & {length: 2}
marker: $null.#Resource.null_resource & {triggers: build: "1"}
```

```sh run
pravo init
find cue.mod -type f | sort
```

```text out
Configuration does not load yet; generating schemas for the declared providers first.
Created cue.mod/module.cue
Providers:
  null = hashicorp/null v3.3.2
  random = hashicorp/random v3.9.1
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/null (1 resource types, 1 data sources, 0 ephemeral, 0 functions)
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)

pravo has been initialised. Run "pravo plan" to see what it would do.
cue.mod/gen/pravo.dev/pravo/settings_gen.cue
cue.mod/gen/pravo.dev/providers/hashicorp/null/null__gen.cue
cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
cue.mod/module.cue
```

Each provider package holds every type the provider offers. The first line records the provider version it was made from:

```sh run
head -n 4 cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
```

```text out
// Provider registry.opentofu.org/hashicorp/random v3.9.1
// Code generated by pravo. DO NOT EDIT.

package random
```

Run `pravo init` before the first `plan`. Commit `cue.mod/gen` and `pravo.lock.cue`, or run `pravo init` in CI, so that a clean checkout behaves the same.

## The pravo package

| Definition | Used as |
|---|---|
| `#Settings` | `$settings: pravo.#Settings & {...}`. See [Settings](spec-settings.md). |
| `#StateSettings`, `#LocalState`, `#S3State`, `#StateFields` | The types of the `state` key. |
| `#Output` | `name: pravo.#Output & {value: ...}`. See [Outputs](spec-outputs.md). |
| `#Env`, `#SecretEnv` | Environment variables. See [Environment and remote outputs](spec-env.md). |
| `#RemoteOutputs` | The outputs of another root. |
| `#Movable` | Embedded in a definition so that its instances accept `$from`. See [Moves and imports](spec-moves-and-imports.md#from-on-a-group). |

```sh run
grep -E '^#[A-Za-z0-9]+:' cue.mod/gen/pravo.dev/pravo/settings_gen.cue
```

```text out
#Movable: {
#Output: {
#Env: {
#SecretEnv: {
#RemoteOutputs: {
#Settings: {
#StateSettings: #StateFields & (#LocalState | #S3State)
#StateFields: {
#LocalState: {
#S3State: {
```

## The provider package

A provider package declares:

| Definition | Contents |
|---|---|
| `#Provider` | The provider's configuration, the `$` fields and the four members below. |
| `#Provider.#Resource.<type>` | One definition per managed resource type. |
| `#Provider.#Data.<type>` | One per data source. |
| `#Provider.#Ephemeral.<type>` | One per ephemeral resource. |
| `#Provider.#Function.<name>` | One per provider-defined function: `args` and `result`. |
| `#Lifecycle` | The shape of `$lifecycle`. A specification does not use it directly. |

Every definition carries `$kind`, `$type` and `$source`, which is how pravo recognises a resource, and the [meta fields](spec-meta-fields.md). `pravo schema <type>` prints one definition with the provider's documentation. With `--required` it keeps only the attributes that must be set. The end of the definition of `random_pet`:

```sh run
pravo schema random_pet | tail -n 14
```

```text out
	// Additional dependencies, as references to other resources.
	$depends_on?: [..._]
	$lifecycle?: #Lifecycle
	// The random pet name.
	id: __string | null
	// Arbitrary map of values that, when changed, will trigger recreation of resource. See [the main provider documentation](../index.html) for more information.
	keepers?: {[string]: __string}
	// The length (in words) of the pet name. Defaults to 2
	length: __number | null
	// A string to prefix the name with.
	prefix?: __string
	// The character to separate words in the pet name. Defaults to "-"
	separator: __string | null
}
```

### Schema mapping

| Provider attribute | CUE |
|---|---|
| required | `name: T` |
| optional | `name?: T` |
| computed | `name: T \| null` |
| optional and computed | `name: T \| null` |
| `string`, `number`, `bool` | `string`, `number`, `bool` |
| `list(T)`, `set(T)` | `[...T]` |
| `map(T)` | `{[string]: T}` |
| `object({a=T})` | `{a?: T}` |
| `tuple([T1,T2])` | `[T1, T2]` |
| `dynamic` | `_` |
| nested block, single or group | `name?: {...}` |
| nested block, list or set | `name?: [...{...}]` |
| nested block, map | `name?: {[string]: {...}}` |
| nested attribute (protocol 6) | as a block, following its mode |

The generated files write the predeclared types as `__string`, `__number` and `__bool`. CUE reads them as `string`, `number` and `bool`.

A computed attribute such as `id` is a regular field, `id: string | null`, so another resource can refer to it before it is known. After the apply the concrete value fills in. If you set an attribute that is optional and computed, the value is sent. If you leave it out, it is sent as null and the provider picks the default.

`sensitive`, `deprecated` and `write_only` attributes carry a `@pravo(...)` attribute on the field. A sensitive value prints as `(sensitive)` in plans. A write-only attribute may take an ephemeral value.

### Package names

The package name is the provider type with `-` and `.` replaced by `_`. A name that is a CUE keyword gets a trailing underscore: `null`, `true`, `false`, `package`, `import`, `for`, `in`, `if` and `let`. A name that begins with a digit gets a `p` in front. Whenever the package name differs from the last element of the path, the import names it after a colon, and you choose the alias.

| Provider type | Package name | Import |
|---|---|---|
| `random` | `random` | `"pravo.dev/providers/hashicorp/random"` |
| `null` | `null_` | `"pravo.dev/providers/hashicorp/null:null_"` |
| `my-cloud` | `my_cloud` | `"pravo.dev/providers/acme/my-cloud:my_cloud"` |

Without the colon, the import cannot be resolved:

```cue file=main.cue
package demo

import nul "pravo.dev/providers/hashicorp/null"

$null: nul.#Provider
```

```sh run exit=6
pravo validate
```

```text out
Error: loading .:
pravo.local/ws@v0: import failed: cannot find package "pravo.dev/providers/hashicorp/null": no files in package directory with package name "null":
    ./main.cue:3:8


hint: a provider schema package is missing. Run "pravo init" to generate it
```

Choose an alias that differs from the provider's local name and from every field name in scope. A top-level field with the name of an import is an error, `random redeclared as imported package name`. Provider structs are named with a leading `$` for this reason. The examples use `rnd` for random, `loc` for local, `awsp` for aws, `tlsp` for tls and `k8s` for kubernetes.

## Regenerating

`pravo init` and `pravo gen` rewrite the packages from the provider schemas. A package that already has the right content is left alone.

```cue file=main.cue
package demo

import rnd "pravo.dev/providers/hashicorp/random"

$random: rnd.#Provider
```

```sh run
pravo gen
```

```text out
Up to date cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)
```

When the version in the lock file or on disk differs from the version a package was made from, `plan`, `apply`, `validate` and the other commands warn and carry on. `init` and `gen` write the package again and do not warn. An attribute that the new version added is rejected until the package is regenerated. Change the version on the first line of the package to see the warning:

```sh run
sed -i.bak '1s/v[0-9.]*$/v3.0.0/' cue.mod/gen/pravo.dev/providers/hashicorp/random/random_gen.cue
pravo validate
pravo gen
pravo validate
```

```text out
Warning: the generated schema for provider random was made from a different version than the selected v3.9.1; run "pravo init" to refresh it
Success! 0 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.
Generated cue.mod/gen/pravo.dev/providers/hashicorp/random (10 resource types, 0 data sources, 2 ephemeral, 0 functions)
Success! 0 resources, 0 data sources, 0 ephemeral, 0 function calls, 0 outputs across 1 providers.
```

## See also

- [`pravo init`](init.md) and [`pravo gen`](validate-eval-fmt-gen.md#pravo-gen) write the packages.
- [`pravo schema`](schema.md) prints one definition.
- [Providers](../concepts/providers.md) explains how a package comes from a provider schema.
