# Author

> Talos next · Since 0.6

The one capability an authoring script has.

## Signature

```ts
export interface Author {
  /** The script's file name, the prefix of every id it makes. */
  readonly owner: string;
  /** The seed {@link Author.random} and `Math.random` draw from: the same on every run. */
  readonly seed: number;
  /** The target scene as it is written now, read-only. */
  readonly scene: { readonly entities: ReadonlyArray<{ readonly id: string; readonly [field: string]: unknown }>; readonly [field: string]: unknown };
  /** A project file's text, by its project-relative path (`data/level.json`). Nothing outside the project. */
  read(path: string): string;
  /** A project file parsed as JSON. */
  json<T = unknown>(path: string): T;
  /**
   * A CSV file as one object per row, keyed by the header. A field that is a number becomes one
   * unless `raw` is true or it was quoted.
   */
  csv<T = Record<string, string | number>>(path: string, options?: { raw?: boolean }): T[];
  /** A number in [0, 1) from the script's own seeded stream (as `Math.random` is here). */
  random(): number;
  /** Makes the entity `"<owner>:<key>"`. A key is 1 to 128 characters with no "/", unique in the run. */
  entity(key: string | number, spec?: AuthorEntitySpec): AuthorHandle;
  /** Places the prefab (`prefabs/goblin.prefab.json`) as the entity `"<owner>:<key>"`. */
  instance(key: string | number, prefab: string, spec?: AuthorInstanceSpec): AuthorHandle;
  /** Declares an asset entry of the scene, as its `assets` map writes it: `{ kind: "glb", path: "models/x.glb" }`. */
  asset(id: string, ref: { kind: string; path: string; [field: string]: unknown }): string;
  /**
   * Imports a model, sound or font of the project (a project-relative path; never one outside it,
   * links resolved) as the asset `id`, through the importer `asset.import` uses, in the same change.
   * A file already in the scene's folder (where `asset.import` puts what it brings in from outside)
   * is named where it is; any other is copied in. A later run with the same file and settings
   * copies nothing.
   */
  importAsset(id: string, path: string, settings?: AuthorImportSettings): string;
  /** A line for the run's answer: counts, what was skipped, anything worth saying. */
  report(line: string): void;
}
```

Import: `import type { Author } from "@argus/api"`

## Members

| Member | Signature | Description |
|---|---|---|
| `owner` | `readonly owner: string` | The script's file name, the prefix of every id it makes. |
| `seed` | `readonly seed: number` | The seed {@link Author.random} and `Math.random` draw from: the same on every run. |
| `scene` | `readonly scene: { readonly entities: ReadonlyArray<{ readonly id: string; readonly [field: string]: unknown }>; readonly [field: string]: unknown }` | The target scene as it is written now, read-only. |
| `read` | `read(path: string): string` | A project file's text, by its project-relative path (`data/level.json`). Nothing outside the project. |
| `json` | `json<T = unknown>(path: string): T` | A project file parsed as JSON. |
| `csv` | `csv<T = Record<string, string \| number>>(path: string, options?: { raw?: boolean }): T[]` | A CSV file as one object per row, keyed by the header. A field that is a number becomes one unless `raw` is true or it was quoted. |
| `random` | `random(): number` | A number in [0, 1) from the script's own seeded stream (as `Math.random` is here). |
| `entity` | `entity(key: string \| number, spec?: AuthorEntitySpec): AuthorHandle` | Makes the entity `"<owner>:<key>"`. A key is 1 to 128 characters with no "/", unique in the run. |
| `instance` | `instance(key: string \| number, prefab: string, spec?: AuthorInstanceSpec): AuthorHandle` | Places the prefab (`prefabs/goblin.prefab.json`) as the entity `"<owner>:<key>"`. |
| `asset` | `asset(id: string, ref: { kind: string; path: string; [field: string]: unknown }): string` | Declares an asset entry of the scene, as its `assets` map writes it: `{ kind: "glb", path: "models/x.glb" }`. |
| `importAsset` | `importAsset(id: string, path: string, settings?: AuthorImportSettings): string` | Imports a model, sound or font of the project (a project-relative path; never one outside it, links resolved) as the asset `id`, through the importer `asset.import` uses, in the same change. A file already in the scene's folder (where `asset.import` puts what it brings in from outside) is named where it is; any other is copied in. A later run with the same file and settings copies nothing. |
| `report` | `report(line: string): void` | A line for the run's answer: counts, what was skipped, anything worth saying. |

## Example

The tested fixture `fixtures/app/agent.ts`.

```ts
import type { Behavior } from "@argus/api"

// Sends a nav agent to `props.target` once, then reports arrival through ctx.state so the
// test can read it without polling the crowd directly.
export default {
  init(ctx) {
    ctx.state.arrived = false
    ctx.nav?.goTo(ctx.props.target as [number, number, number])
  },
  update(ctx) {
    if (ctx.nav?.arrived) ctx.state.arrived = true
  },
} satisfies Behavior
```
