Skip to content

Commit

Permalink
Merge pull request #548 from player-ui/docs/dsl
Browse files Browse the repository at this point in the history
Add Missing DSL Docs
  • Loading branch information
KetanReddy authored Nov 21, 2024
2 parents 74f4048 + f4b5cd7 commit 05f718f
Show file tree
Hide file tree
Showing 6 changed files with 677 additions and 13 deletions.
27 changes: 14 additions & 13 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,7 @@ Indicate the type of change your pull request is:
- [ ] `patch`
- [ ] `minor`
- [ ] `major`

<!--
To include release notes in the automatic changelong, just add a level 1 markdown header below
and include any markdown notes to go into the changelog: https://intuit.github.io/auto/docs/generated/changelog#additional-release-notes
Example:
# Release Notes
Added new plugin, to use it:
```typescript
const plugin = new Plugin(...)
```
-->
- [ ] `N/A`


### Does your PR have any documentation updates?
Expand All @@ -44,4 +32,17 @@ Please refer to our site https://player-ui.github.io/latest/about, and include a
If you are unable to update the current documents, please create an issue for us to get back to it.
-->

<!--
To include release notes in the automatic changelong, just add a level 1 markdown header below
and include any markdown notes to go into the changelog: https://intuit.github.io/auto/docs/generated/changelog#additional-release-notes
Example:
# Release Notes
Added new plugin, to use it:
```typescript
const plugin = new Plugin(...)
```
-->
4 changes: 4 additions & 0 deletions docs/site/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export default defineConfig({
label: "Guides",
autogenerate: { directory: "guides" },
},
{
label: "Authoring",
autogenerate: { directory: "authoring" },
},
{
label: "Content",
autogenerate: { directory: "content" },
Expand Down
172 changes: 172 additions & 0 deletions docs/site/src/content/docs/authoring/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: Overview
---

# TSX/JSX Content Authoring (Player DSL)

While Player content _can_ be written directly in JSON, it's definitely not the preferable authoring format. To take advantage of existing developer tool-chains, Player provides a mechanism for authoring content in (J/T)SX as React components and simple TypeScript objects. The Player CLI can then be used to transpile the React tree into a JSON content.

## DSL Benefits

At a high level, the benefits to writing Player content in the DSL can be summarized by three key factors:

#### Easier maintainability
Simply put, DSL code more concise than its JSON equivalent. That means there is less code for you to have to maintain. Also, as its easier to read than JSON, when you do need to make updates to it, its much more wieldy to work with.

#### Better development experience
Since the DSL leverages a lot of standard TypeScript language features, most editors will offer quality of life features like typechecking, suggestions, and code generation. All of this is in service of shortening the feedback loop of writing content and ensuring it is what you intended for it.

#### Easier to extend
The DSL now offers a easily accessible programatic hook into Player content. This allows custom tooling to be created around your DSL integration much easier that before. Common patterns can be extracted into higher level compoennts, functions can be created to generate code, and code generation can be integrated into almost any process where relevant data is present.

For a further explination on the benefits, see the DSL Benefits section in the [DSL Views](./views.mdx#dsl-benefits-in-views) and the [DSL Schema](./schema.mdx#dsl-benefit-in-schema)

## Writing DSL Content

In order to use the DSL to write content, your plugin library should ship a DSL component package. These will define the primitive _components_ to use to build up the tree. Authorship of these components is covered in the [Writing DSL Components](../assets/dsl) secton. The Player Reference Assets ship their own DSL Components via the `@player-ui/reference-assets-components` pacakge.

In the examples below, we will use the Player Reference Assets Components.

### Basic Setup

To get started, you'll need the following dependencies in your `package.json`:

```json
{
"dependencies": {
"@player-tools/dsl": "0.4.1",
"@player-tools/cli": "0.4.1",
"@player-ui/reference-assets-components": "0.6.0",
"@types/react": "17.0.39",
"react": "17.0.2"
}
}
```

Next, you'll need to configure your environment for DSL Compilation and JSON validation. Below is a basic configuration that can be added in your `package.json`. For a more detailed explination and examples on further customization please refer to the [CLI](../tools/cli) section.

```json
{
"player": {
"dsl": {
"src": "./src/main/tsx",
"outDir": "./out"
},
"json": {
"src": "./out/*.json"
},
}
}
```

### Basic Format and File Layout

By default, all files that contain a Player Flow should be exported as a `.tsx` file and the schema should be in a `.ts` file. For how to change this behavior, please refer to the [DSL Plugins](./plugins) section of the docs. Each of these files should contain a default export of their appropriate object. For example a file that exports a flow should look like the following:

```tsx
export default {
id: 'my-flow',
views: [....],
navigation: {....}
}
```

and a file that exports the schema should look like:

```typescript
const mySchema = {...}

export default mySchema

```

### Navigation

At this time the `navigation` section is a basic JS object. The `@player-ui/types` package provides typescript typings for this.

```tsx
import { Navigation } from '@player-ui/types';

const navigation: Navigation = {
BEGIN: 'Start',
Start: {
startState: 'VIEW_1',
VIEW_1: {
state_type: 'VIEW',
ref: 'view-1',
transitions: {
'*': 'END_Done',
},
},
END_Done: {
state_type: 'END',
outcome: 'done',
},
},
};
```

One convenience feature is the auto injection of the the `ref` property for a `VIEW` type state if the corresponding view is a React tree.

```tsx
import { Navigation } from '@player-ui/types';

const view = (
<Collection id="my-view">
<Text>Some value</Text>
<Input>
<Input.Label>Some label</Input.Label>
</Input>
</Collection>
);

const navigation: Navigation = {
BEGIN: 'Start',
Start: {
startState: 'VIEW_1',
VIEW_1: {
state_type: 'VIEW',
ref: view,
transitions: {
'*': 'END_Done',
},
},
END_Done: {
state_type: 'END',
outcome: 'done',
},
},
};
```

_Note: The `Navigation` type we're importing here from the `@player-ui/types` package is different than the `Navigation` type from the `@player-tools/dsl` package. The former is the core definition for what the Navigation section of Player content is. The latter has specific replacements to take DSL constructs where normal objects would be defined._

### Bindings and Expressions

Both `binding` and `expression` in the JSX authoring leverages a tagged template, typically abbreviated as `b` and `e` respectively. In a similar fashion to using `css` or `graphql` in a JS file, this enables syntax-highlighting and validation of bindings and expressions within a JS file.

```tsx
import { binding as b, expression as e } from '@player-tools/dsl';

const myBinding = b`foo.bar`;
const myExpression = e`foo()`;
```

The binding and expression instances can also automatically dereference themselves when used inside of another string:

```tsx
const stringWithBinding = `Some text: ${myBinding}`; // 'Some text: {{foo.bar}}'
const stringWithExp = `Some expr: ${myExpression}`; // 'Some expr: @[foo()]@'
```

### View

Please refer to the [Views](../dsl/views) section for a detailed overview of how to write DSL Views

### Schema

Please refer to the [Schema](../dsl/schema) section for a detailed overview of how to write DSL Schemas

## Compiling DSL Content

Once your DSL content is authored, you can use the Player CLI to compile and validate your content. For documentation on this functionality, please refer to the [Player CLI](../tools/cli) section
46 changes: 46 additions & 0 deletions docs/site/src/content/docs/authoring/plugins.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: Plugins
---

# DSl Plugins

Much like the rest of Player, DSL compilation supports plugins that can influce how content gets compiled and generated. DSL Plugins are a subset of CLI Plugins that use either the hooks available on the CLI itself or on the DSL compiler instance created by the CLI. This section will cover the hooks that are available for use and why you might want to tap them.

## CLI Hooks

The `createCompilerContext` function available to plugins that extend the `PlayerCLIPlugin` class gives access to the `CompilationContext` instance. This class manages the context around DSL compilation and exposes two related hooks.

### `identifyContentType`

The `identifyContentType` hooks's purpose is to allow plugins to inject custom behavior around detecting what kind of file is being compiled. By default there are three types of content the CLI is aware of (`view`, `flow`, and `schema`). Its methods for detecting which kind of content is contained within a file is very rudimentary (the logic can be found [here](https://github.com/player-ui/tools/blob/main/language/dsl/src/compiler/utils.ts#L5)). In order to allow desired convention or orchestrate the compilation of custom file types, this hook provides a mechanism for allowing that custom logic to be injected. The result of this hook is used in the next hook

### `compileContent`

The `compileContent` hook's purpose is to allow the custom compilation logic for any identified file type. As it is an `AsyncSeriesBailHook` it will take the first result returned from a tap who was able to return a result for the compilation for the given file of the identified type. In the case where no external logic is added, the hook will attempt to compile any of its known content types with the built in compiler instance.

## Compilation Hooks

The CLI will initialize an instance of the `DSLCompiler` and provide a reference to it via the `onCreateDSLCompiler` function available to plugins that extend the `PlayerCLIPlugin` class. On the compiler itself, the following hook are available to modify the behavior of how DSL content is compiled.

### `preProcessFlow`
_Note: Only called for `view` or `flow` content_

This hook allows transformations on the content before it is compiled. This enables the injection of additonal data or resolving any integration specific convention into something that may be understood by the compiler. This hook can also be used to collate information on what is being compiled for use later.

### `postProcessFlow`
_Note: Only called for `view` or `flow` content_

This hook allows transformations on the content after it is compiled. This allows modifications to the compiled content which in some cases may be preferable as manipulating JSON may be easier than a React Tree.

### `schemaGenerator`

This hook gives access to the internal `SchemaGenerator` object which is responsible for compiling the schema. On this generator there are the following hooks.

#### `createSchemaNode`

This hook allows custom logic for processing schema nodes as they are generated. This enables arbitrary properties to be statically or dynamically added based on the authored schema node. One potential usecase of this is to allow integration specific semantic conventions to be defined and injected into the final schema. For example, the presence of a specific `Symbol` might mean that a property needs to be injected or even that the schema tree from this point on needs to be modified.


### `onEnd`

This hook is called to signal that the compilation of all files has been completed. This allows any post processing on the output as a whole to take place as a part of the build process. This may include actions like moving or bundling the compilation results or writing new files based on information collected via other hooks on the files that were processed.
Loading

0 comments on commit 05f718f

Please sign in to comment.