Forráskód Böngészése

Add package documentation — Part 1: errors, library and nodes (#104)

Loris Leiva 1 éve
szülő
commit
c4207cb582

+ 81 - 1
packages/errors/README.md

@@ -1,3 +1,83 @@
 # Kinobi ➤ Errors
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/errors.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/errors.svg?style=flat&label=%40kinobi-so%2Ferrors
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/errors
+
+This package defines a `KinobiError` class that accepts a specific error code and a context object based on that code. It enables us to catch and handle errors in a more structured way.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/errors
+```
+
+> [!NOTE]
+> This package is included in the main [`kinobi`](../library) package. Meaning, you already have access to its content if you are installing Kinobi this way.
+>
+> ```sh
+> pnpm install kinobi
+> ```
+
+## Reading error messages
+
+### In development mode
+
+When the `NODE_ENV` environment variable is not set to `"production"`, every error message will be included in the bundle. As such, you will be able to read them in plain language wherever they appear.
+
+### In production mode
+
+On the other hand, when `NODE_ENV` is set to `"production"`, error messages will be stripped from the bundle to save space. Only the error code will appear when an error is encountered. Follow the instructions in the error message to convert the error code back to the human-readable error message.
+
+For instance, to recover the error text for the error with code `123`:
+
+```shell
+npx @kinobi-so/errors decode -- 123
+```
+
+## Catching errors
+
+When you catch a `KinobiError` and assert its error code using `isKinobiError()`, TypeScript will refine the error's context to the type associated with that error code. You can use that context to render useful error messages, or to make context-aware decisions that help your application to recover from the error.
+
+```ts
+import { KINOBI_ERROR__UNEXPECTED_NODE_KIND, isKinobiError } from '@kinobi-so/errors';
+
+try {
+    const kinobi = createFromJson(jsonIdl);
+} catch (e) {
+    if (isKinobiError(e, KINOBI_ERROR__UNEXPECTED_NODE_KIND)) {
+        const { expectedKinds, kind, node } = e.context;
+        // ...
+    } else if (isKinobiError(e, KINOBI_ERROR__VERSION_MISMATCH)) {
+        const { kinobiVersion, rootVersion } = e.context;
+        // ...
+    } else {
+        throw e;
+    }
+}
+```
+
+## Contributing
+
+### Adding a new error
+
+To add a new error in Kinobi, follow these steps:
+
+1. Add a new exported error code constant to `src/codes.ts`. Find the most appropriate group for your error and ensure it is appended to the end of that group.
+2. Add that new constant to the `KinobiErrorCode` union in `src/codes.ts`.
+3. If you would like the new error to encapsulate context about the error itself define that context in `src/context.ts`.
+4. Add the error's message to `src/messages.ts`. Any context values that you defined above will be interpolated into the message wherever you write `$key`, where `key` is the index of a value in the context (eg. ``'Unrecognized node `$kind`.'``).
+5. Publish a new version of `@kinobi-so/errors` using changesets — maintainers will handle this via tha changesets CI workflow.
+6. Bump the version of `@kinobi-so/errors` or `kinobi` in the consumer package from which the error is thrown.
+
+### Removing an error message
+
+-   Don't remove errors.
+-   Don't change the meaning of an error message.
+-   Don't change or reorder error codes.
+-   Don't change or remove members of an error's context.
+
+When an older client throws an error, we want to make sure that they can always decode the error. If you make any of the changes above, old clients will, by definition, not have received your changes. This could make the errors that they throw impossible to decode going forward.

+ 96 - 1
packages/library/README.md

@@ -1,3 +1,98 @@
 # Kinobi ➤ Main Library
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/kinobi.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/kinobi.svg?style=flat&label=%40kinobi-so%2Fnodes
+[npm-url]: https://www.npmjs.com/package/kinobi
+
+This package is the main library for Kinobi. It re-exports most of the other packages in the Kinobi monorepo and offers a `Kinobi` type with a few helpers to help bind everything together.
+
+## Installation
+
+```sh
+pnpm install kinobi
+```
+
+## Packages included
+
+This package includes the following packages. Note that some of them also re-export other packages.
+
+-   [`@kinobi-so/errors`](../errors)
+-   [`@kinobi-so/nodes`](../nodes)
+    -   [`@kinobi-so/node-types`](../node-types)
+-   [`@kinobi-so/validators`](../validators)
+-   [`@kinobi-so/visitors`](../visitors)
+    -   [`@kinobi-so/visitor-core`](../visitor-core)
+
+## The Kinobi helper
+
+Additionally, this package offers a `Kinobi` type and a few helper functions to help you work with Kinobi IDLs.
+
+### `Kinobi`
+
+The `Kinobi` interface wraps a `RootNode` and offers some helper methods to work with it.
+
+```ts
+export interface Kinobi {
+    accept<T>(visitor: Visitor<T>): T;
+    clone(): Kinobi;
+    getJson(): string;
+    getRoot(): RootNode;
+    update(visitor: Visitor<Node | null>): void;
+}
+```
+
+The `accept` function allows us to visit the wrapped `RootNode` using the provided visitor.
+
+```ts
+// Log the Kinobi IDL in the console.
+kinobi.accept(consoleLogVisitor(getDebugStringVisitor({ indent: true })));
+```
+
+The `update` function also accepts a visitor, but it uses the return value of that visitor to update the wrapped `RootNode`. This means that, given a `RootNode`, the provided visitor should also return a `RootNode`. An error will be thrown otherwise.
+
+```ts
+// Delete account nodes named "mint".
+kinobi.update(deleteNodesVisitor(['[accountNode]mint']));
+
+// Transform all number nodes into u64 number nodes.
+kinobi.update(
+    bottomUpTransformerVisitor([
+        {
+            select: '[numberTypeNode]',
+            transform: () => numberTypeNode(u64),
+        },
+    ]),
+);
+```
+
+Other helper functions include:
+
+-   `clone()`: Creates a new instance of the `Kinobi` interface with a deep copy of the wrapped `RootNode`.
+-   `getJson()`: Returns the JSON representation of the Kinobi IDL.
+-   `getRoot()`: Returns the wrapped `RootNode`.
+
+```ts
+const clonedKinobi = kinobi.clone();
+const jsonIdl = kinobi.getJson();
+const rootNode = kinobi.getRoot();
+```
+
+### `createFromRoot(rootNode)`
+
+The `createFromRoot` function creates a new instance of the `Kinobi` interface from a `RootNode`.
+
+```ts
+const kinobi = createFromRoot(rootNode(programNode({ ... })));
+```
+
+### `createFromJson(jsonIdl)`
+
+The `createFromJson` function creates a new instance of the `Kinobi` interface from a JSON representation of a `RootNode`.
+
+```ts
+const json: string = fs.readFileSync('path/to/kinobiIdl.json', 'utf-8');
+const kinobi = createFromJson(json);
+```

+ 2 - 4
packages/node-types/README.md

@@ -7,6 +7,8 @@
 [npm-image]: https://img.shields.io/npm/v/@kinobi-so/node-types.svg?style=flat&label=%40kinobi-so%2Fnode-types
 [npm-url]: https://www.npmjs.com/package/@kinobi-so/node-types
 
+This package is the type-only version of the `@kinobi-so/nodes` package. Check out the [nodes documentation](../nodes) for more information.
+
 ## Installation
 
 ```sh
@@ -20,7 +22,3 @@ pnpm install @kinobi-so/node-types
 > pnpm install @kinobi-so/nodes
 > pnpm install kinobi
 > ```
-
-## Documentation
-
-This package is the type-only version of the `@kinobi-so/nodes` package. Check out the [nodes documentation](../nodes) for more information.

+ 29 - 15
packages/nodes-from-anchor/README.md

@@ -1,26 +1,40 @@
 # Kinobi ➤ Nodes From Anchor
 
-Parse Anchor IDL version `0.0` or `0.1` (from Anchor `0.30`) into Kinobi node definitions.
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
 
-```javascript
-// node ./kinobi.mjs
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/nodes-from-anchor.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/nodes-from-anchor.svg?style=flat&label=%40kinobi-so%2Fnodes-from-anchor
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/nodes-from-anchor
 
-import path from 'path';
-import { renderRustVisitor, renderJavaScriptVisitor } from '@kinobi-so/renderers';
-import { rootNodeFromAnchor } from '@kinobi-so/nodes-from-anchor';
-import { readJson } from '@kinobi-so/renderers-core';
-import { visit } from '@kinobi-so/visitors-core';
+This package converts Anchor IDLs from various versions into Kinobi IDLs.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/nodes-from-anchor
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
 
-const clientDir = path.join(__dirname, 'clients');
+## Functions
 
-const idlPath = path.join(__dirname, 'target', 'idl', 'anchor_program.json');
-const idl = readJson(idlPath);
+### `rootNodeFromAnchor(anchorIdl)`
 
-const node = rootNodeFromAnchor(idl);
+This function takes a valid Anchor IDL and returns a `RootNode`.
 
-const sdkName = idl.metadata.name;
+```js
+// node ./kinobi.mjs
+import { rootNodeFromAnchor } from '@kinobi-so/nodes-from-anchor';
+import { createFromRootNode } from 'kinobi';
+import { readFileSync } from 'node:fs';
+import path from 'path';
 
-await visit(node, renderJavaScriptVisitor(path.join(clientDir, 'js', sdkName, 'src', 'generated')));
+// Read the content of your IDL file.
+const anchorIdlPath = path.join(__dirname, 'target', 'idl', 'anchor_program.json');
+const anchorIdl = JSON.parse(readFileSync(anchorIdlPath, 'utf-8'));
 
-visit(node, renderRustVisitor(path.join(clientDir, 'rust', sdkName, 'src', 'generated'), { format: true }));
+// Parse it into a Kinobi IDL.
+const kinobi = createFromRoot(rootNodeFromAnchor(anchorIdl));
 ```

+ 3 - 3
packages/nodes/README.md

@@ -7,6 +7,8 @@
 [npm-image]: https://img.shields.io/npm/v/@kinobi-so/nodes.svg?style=flat&label=%40kinobi-so%2Fnodes
 [npm-url]: https://www.npmjs.com/package/@kinobi-so/nodes
 
+This package defines the various nodes that make up the Kinobi IDL. It provides types and helper functions to work with these nodes. If you are looking for a type-only version of these nodes, you can find them in the [`@kinobi-so/node-types`](../node-types) package.
+
 ## Installation
 
 ```sh
@@ -20,9 +22,7 @@ pnpm install @kinobi-so/nodes
 > pnpm install kinobi
 > ```
 
-## Documentation
-
-This package defines the various nodes that make up the Kinobi IDL. It provides types and helper functions to work with these nodes. If you are looking for a type-only version of these nodes, you can find them in the [`@kinobi-so/node-types`](../node-types) package.
+## All available nodes
 
 The Kinobi IDL is composed of various nodes that describe different aspects of a Solana program. Some nodes are categorised together as they share a similar purpose. For instance, all the nodes that describe a data structure that can be encoded and decoded into buffers are grouped under the `TypeNode` category.
 

+ 21 - 1
packages/renderers-core/README.md

@@ -1,3 +1,23 @@
 # Kinobi ➤ Renderers ➤ Core
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/renderers-core.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/renderers-core.svg?style=flat&label=%40kinobi-so%2Frenderers-core
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/renderers-core
+
+This package provides the core utility for generating clients from Kinobi IDLs. Its aim is mainly to provide helpers for other renderer packages such as [`@kinobi-so/renderers-js`](../renderers-js) and [`@kinobi-so/renderers-rust`](../renderers-rust).
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/renderers-core
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
+
+## Documentation
+
+_Coming soon..._

+ 31 - 1
packages/renderers-js-umi/README.md

@@ -1,3 +1,33 @@
 # Kinobi ➤ Renderers ➤ JavaScript Umi
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/renderers-js-umi.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/renderers-js-umi.svg?style=flat&label=%40kinobi-so%2Frenderers-js-umi
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/renderers-js-umi
+
+This package generates JavaScript clients from your Kinobi IDLs. The generated clients are compatible with Metaplex's [Umi framework](https://github.com/metaplex-foundation/umi).
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/renderers-js-umi
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
+>
+> However, note that the [`renderers`](../renderers) package re-exports the `renderVisitor` function of this package as `renderJavaScriptUmiVisitor`.
+
+## Documentation
+
+_Coming soon..._
+
+```ts
+// node ./kinobi.mjs
+import { renderVisitor } from '@kinobi-so/renderers-js-umi';
+
+const pathToGeneratedFolder = path.join(__dirname, 'clients', 'js', 'src', 'generated');
+kinobi.accept(renderVisitor(pathToGeneratedFolder));
+```

+ 31 - 1
packages/renderers-js/README.md

@@ -1,3 +1,33 @@
 # Kinobi ➤ Renderers ➤ JavaScript
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/renderers-js.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/renderers-js.svg?style=flat&label=%40kinobi-so%2Frenderers-js
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/renderers-js
+
+This package generates JavaScript clients from your Kinobi IDLs. The generated clients are compatible with the soon-to-be-released 2.0 line of [`@solana/web3.js`](https://github.com/solana-labs/solana-web3.js).
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/renderers-js
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
+>
+> However, note that the [`renderers`](../renderers) package re-exports the `renderVisitor` function of this package as `renderJavaScriptVisitor`.
+
+## Documentation
+
+_Coming soon..._
+
+```ts
+// node ./kinobi.mjs
+import { renderVisitor } from '@kinobi-so/renderers-js';
+
+const pathToGeneratedFolder = path.join(__dirname, 'clients', 'js', 'src', 'generated');
+kinobi.accept(renderVisitor(pathToGeneratedFolder));
+```

+ 31 - 1
packages/renderers-rust/README.md

@@ -1,3 +1,33 @@
 # Kinobi ➤ Renderers ➤ Rust
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/renderers-rust.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/renderers-rust.svg?style=flat&label=%40kinobi-so%2Frenderers-rust
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/renderers-rust
+
+This package generates Rust clients from your Kinobi IDLs.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/renderers-rust
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
+>
+> However, note that the [`renderers`](../renderers) package re-exports the `renderVisitor` function of this package as `renderRustVisitor`.
+
+## Documentation
+
+_Coming soon..._
+
+```ts
+// node ./kinobi.mjs
+import { renderVisitor } from '@kinobi-so/renderers-rust';
+
+const pathToGeneratedFolder = path.join(__dirname, 'clients', 'rust', 'src', 'generated');
+kinobi.accept(renderVisitor(pathToGeneratedFolder));
+```

+ 30 - 1
packages/renderers/README.md

@@ -1,3 +1,32 @@
 # Kinobi ➤ Renderers
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/renderers.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/renderers.svg?style=flat&label=%40kinobi-so%2Frenderers
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/renderers
+
+This package re-exports all available renderers for Kinobi IDLs.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/renderers
+```
+
+> [!NOTE]
+> This package is **not** included in the main [`kinobi`](../library) package.
+
+## Documentation
+
+_Coming soon..._
+
+```ts
+// node ./kinobi.mjs
+import { renderJavaScriptVisitor, renderJavaScriptUmiVisitor, renderRustVisitor } from '@kinobi-so/renderers';
+
+kinobi.accept(renderJavaScriptVisitor('clients/js/src/generated'));
+kinobi.accept(renderJavaScriptUmiVisitor('clients/js-umi/src/generated'));
+kinobi.accept(renderRustVisitor('clients/rust/src/generated'));
+```

+ 31 - 1
packages/validators/README.md

@@ -1,3 +1,33 @@
 # Kinobi ➤ Validators
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/validators.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/validators.svg?style=flat&label=%40kinobi-so%2Fvalidators
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/validators
+
+This package offers a set of validation rules for Kinobi IDLs to ensure that they are correctly formatted.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/validators
+```
+
+> [!NOTE]
+> This package is included in the main [`kinobi`](../library) package. Meaning, you already have access to its content if you are installing Kinobi this way.
+>
+> ```sh
+> pnpm install kinobi
+> ```
+
+## Documentation
+
+_Coming soon..._
+
+```ts
+import { throwValidatorItemsVisitor, getValidationItemsVisitor } from '@kinobi-so/validators';
+
+kinobi.accept(throwValidatorItemsVisitor(getValidationItemsVisitor()));
+```

+ 26 - 1
packages/visitors-core/README.md

@@ -1,3 +1,28 @@
 # Kinobi ➤ Visitors ➤ Core
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/visitors-core.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/visitors-core.svg?style=flat&label=%40kinobi-so%2Fvisitors-core
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/visitors-core
+
+This package provides core interfaces and utilities for creating visitors for Kinobi IDLs.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/visitors-core
+```
+
+> [!NOTE]
+> This package is included in the [`@kinobi-so/visitors`](../visitors) package and in the main [`kinobi`](../library) library. Meaning, you already have access to its content if you are installing Kinobi in one of these ways.
+>
+> ```sh
+> pnpm install @kinobi-so/visitors
+> pnpm install kinobi
+> ```
+
+## Documentation
+
+_Coming soon..._

+ 25 - 1
packages/visitors/README.md

@@ -1,3 +1,27 @@
 # Kinobi ➤ Visitors
 
-TODO
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@kinobi-so/visitors.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@kinobi-so/visitors.svg?style=flat&label=%40kinobi-so%2Fvisitors
+[npm-url]: https://www.npmjs.com/package/@kinobi-so/visitors
+
+This package offers various visitors for Kinobi IDLs to traverse and manipulate their nodes.
+
+## Installation
+
+```sh
+pnpm install @kinobi-so/visitors
+```
+
+> [!NOTE]
+> This package is included in the main [`kinobi`](../library) package. Meaning, you already have access to its content if you are installing Kinobi this way.
+>
+> ```sh
+> pnpm install kinobi
+> ```
+
+## Documentation
+
+_Coming soon..._