diff --git a/docs/src/content/docs/structure.md b/docs/src/content/docs/structure.md index 14b6841..e0d74ab 100644 --- a/docs/src/content/docs/structure.md +++ b/docs/src/content/docs/structure.md @@ -2,37 +2,410 @@ title: Bindings Structure prev: false next: false +head: + - tag: style + content: | + .code-comparison { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto 0.5rem auto; + column-gap: 1rem; + } + + .code-comparison > div { + margin: 0; + overflow-x: hidden; + } + + .code-comparison .title-left { + grid-column: 1; + grid-row: 1; + font-weight: bold; + } + + .code-comparison .title-right { + grid-column: 2; + grid-row: 1; + font-weight: bold; + } + + .code-comparison .code-left { + grid-column: 1; + grid-row: 3; + } + + .code-comparison .code-right { + grid-column: 2; + grid-row: 3; + } + + @media (max-width: 768px) { + .code-comparison { + grid-template-columns: 1fr; + grid-template-rows: auto auto 0.5rem auto auto; + } + + .code-comparison .title-left { + grid-column: 1; + grid-row: 1; + } + + .code-comparison .title-right { + grid-column: 1; + grid-row: 4; + } + + .code-comparison .code-left { + grid-column: 1; + grid-row: 2; + } + + .code-comparison .code-right { + grid-column: 1; + grid-row: 5; + } + } --- The tool writes the files in the specified output directory with the following structure. Assuming you have a `.did` file, `` is used for the generated files. -> Note: Generated code references `@icp-sdk/core` (agents, candid, principals). Install it in your app if you plan to compile/run the generated code. See `https://js.icp.build/core`. +> Note: The generated code imports elements from `@icp-sdk/core`. You must install it, see [js.icp.build/core](https://js.icp.build/core). -## `declarations/` +## `.ts` -This folder contains the actual Candid JS bindings. It generates the same bindings that the [`dfx generate`](https://internetcomputer.org/docs/building-apps/developer-tools/dfx/dfx-generate) command was generating. +This file contains the TypeScript wrapper for the Candid JS bindings generated in [`declarations/.did.js`](#declarationsservice-namedidjs). It offers a more idiomatic and type-safe TypeScript interface over the Candid JS bindings. -### `declarations/.did.d.ts` +Set the [`output.actor.disabled`](./core/api/type-aliases/GenerateOutputOptions.md#disabled) option to `true` to skip generating this file. -This file is used in TypeScript projects to type the Candid JS bindings generated in [`declarations/.did.js`](#declarationsservice-namedidjs). +The generated file exposes: -### `declarations/.did.js` +- The [types](#types), that is the TypeScript representation of the Candid types. +- The [`Interface` type](#service-nameinterface-type), that is the TypeScript interface for the service. +- The [`` class](#service-name-class), that is the TypeScript class for the service. +- The [`createActor` function](#createactor-function), that creates a new instance of the actor. -This file contains the actual Candid JS bindings, that allow encoding and decoding JS objects to and from Candid. +### Types -## `.ts` +This section contains the TypeScript representation of the Candid types. It contains all the types that are defined as Candid types in the `.did` file. To make the generated types more idiomatic, some types are transformed into more TypeScript-friendly types. + +#### Options + +Candid [options](https://github.com/dfinity/candid/blob/master/spec/Candid.md#options) are represented as a union of the inner option type and `null`: + +
+ +
Candid
+ +
+ +``` +type MyType = opt text; +``` + +
+ +
TypeScript
+ +
+ +```typescript +type MyType = string | null; +``` + +
+ +
+ +#### Nested/Recursive Options + +Nested or recursive options are represented as union of the `Some` and `None` types, where `Some` and `None` are defined as: + +```typescript +interface Some { + __kind__: "Some"; + value: T; +} +interface None { + __kind__: "None"; +} +``` + +##### Nested + +
+ +
Candid
+ +
+ +``` +type MyType = opt opt text; +type MyType2 = opt opt opt text; +``` + +
+ +
TypeScript
+ +
+ +```typescript +type MyType = Some | None; +type MyType2 = Some | None> | None; +``` + +
+ +
+ +##### Recursive + +
+ +
Candid
+ +
+ +``` +type A = B; +type B = opt A; +``` + +
+ +
TypeScript
+ +
+ +```typescript +type A = B; +type B = Some | None +``` + +
+ +
+ +#### Record Fields with Options + +Record fields that have an option type are optional fields in the TypeScript type: + +
+ +
Candid
+ +
+ +``` +type MyType = record { + my_field : opt text; +} +``` + +
+ +
TypeScript
+ +
+ +```typescript +type MyType = { + my_field?: string; +}; +``` + +
+ +
-This file contains the TypeScript wrapper for the Candid JS bindings generated in [`declarations/.did.js`](#declarationsservice-namedidjs). It offers a more idiomatic and type-safe TypeScript interface over the Candid JS bindings. Set the [`output.actor.disabled`](./core/api/type-aliases/GenerateOutputOptions.md#disabled) option to `true` to skip generating this file. +#### Variants + +Candid [variants](https://github.com/dfinity/candid/blob/master/spec/Candid.md#variants) without type parameters are represented as TypeScript enums: + +
+ +
Candid
+ +
+ +``` +type MyType = variant { + A; + B; +} +``` + +
+ +
TypeScript
+ +
+ +```typescript +enum MyType { + A, + B, +} +``` + +
+ +
+ +#### Variants with Types + +Variants that contain types in their fields are represented as TypeScript unions: + +
+ +
Candid
+ +
+ +``` +type MyType = variant { + A : text; + B; + C : record { + my_field : text; + }; +} +``` + +
+ +
TypeScript
+ +
+ +```typescript +type MyType = + | { __kind__: "A"; A: string } + | { __kind__: "B"; B: null } + | { __kind__: "C"; C: { my_field: string } }; +``` + +
+ +
+ +### `Interface` type + +This type is the TypeScript interface for the service. It contains all the methods that are defined in the [Candid service](https://github.com/dfinity/candid/blob/master/spec/Candid.md#services) in the `.did` file. + +For example, a Candid service will be represented as: + +
+ +
Candid
+ +
+ +```txt title="hello_world.did" +service : () -> { + greet : (name : text) -> text; +}; +``` + +
+ +
TypeScript
+ +
+ +```typescript title="hello_world.ts" +interface helloWorldInterface = { + greet: (name: string) => Promise; +}; +``` + +
+ +
+ +### `` class + +This class implements the [`Interface` type](#service-nameinterface-type). It can be instantiated with the [`createActor` function](#createactor-function). + +For example, a Candid service will be represented as: + +
+ +
Candid
+ +
+ +```txt title="hello_world.did" +service : () -> { + greet : (name : text) -> text; +}; +``` + +
+ +
TypeScript
+ +
+ +```typescript title="hello_world.ts" +class HelloWorld implements helloWorldInterface { + constructor( + private actor: ActorSubclass<_SERVICE>, + ) {} + async greet(arg0: string): Promise { + const result = await this.actor.greet(arg0); + return result; + } +} +``` + +
+ +
+ +Where the `_SERVICE` type is imported from the [`declarations/.did.d.ts`](#declarationsservice-namediddts) file and the [`ActorSubclass`](https://js.icp.build/core/latest/libs/agent/api/type-aliases/actorsubclass/) type is imported from the [`@icp-sdk/core/agent`](https://js.icp.build/core/latest/libs/agent/) module. + +### `createActor` function + +Creates an instance of the [`` class](#service-name-class). Here's an example of how to use the generated client: -```ts -import { createActor } from './bindings/hello_world'; +```typescript +import { createActor } from "./bindings/hello_world"; + +const actor = createActor("your-canister-id"); +const greeting = await actor.greet("World"); +``` + +The signature of the `createActor` function is: -const actor = createActor('your-canister-id'); -const greeting = await actor.greet('World'); +```typescript +interface CreateActorOptions { + agent?: Agent; + agentOptions?: HttpAgentOptions; + actorOptions?: ActorConfig; +} + +function createActor(canisterId: string, options: CreateActorOptions = {}): Interface; ``` +If both the `agent` and `agentOptions` are provided, the `agentOptions` will be ignored and the `agent` will be used. Otherwise, a new [`HttpAgent`](https://js.icp.build/core/latest/libs/agent/api/classes/httpagent/) will be created using the `agentOptions` if provided. + +If provided, the `actorOptions` will be passed to the [`Actor.createActor`](https://js.icp.build/core/latest/libs/agent/api/classes/actor/#createactor) function. Otherwise, the default options will be used. + +## `declarations/` + +This folder contains the actual Candid JS bindings. It generates the same bindings that the [`dfx generate`](https://internetcomputer.org/docs/building-apps/developer-tools/dfx/dfx-generate) command was generating. + +### `declarations/.did.d.ts` + +This file is used in TypeScript projects to type the Candid JS bindings generated in [`declarations/.did.js`](#declarationsservice-namedidjs). + +### `declarations/.did.js` + +This file contains the actual Candid JS bindings, that allow encoding and decoding JS objects to and from Candid. + ## Optional files ### `.d.ts`