@powerhousedao/academy 2.5.0-dev.20 → 2.5.0-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +6 -2
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +5 -0
- package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +2 -1
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +67 -21
- package/docs/academy/06-ComponentLibrary/02-CreateCustomScalars.md +403 -0
- package/docs/academy/06-ComponentLibrary/02-ScalarComponent.mdx +6 -76
- package/docs/academy/06-ComponentLibrary/03-ComplexComponent.mdx +1 -1
- package/docs/academy/06-ComponentLibrary/03-IntegrateIntoAReactComponent.md +1 -0
- package/docs/academy/06-ComponentLibrary/04-LayoutComponent.mdx +1 -54
- package/docs/academy/06-ComponentLibrary/05-FragmentsComponent.mdx +1 -54
- package/docs/academy/09-AIResources +23 -0
- package/package.json +1 -1
- package/sidebars.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.5.0-dev.21 (2025-06-12)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
1
5
|
## 2.5.0-dev.20 (2025-06-12)
|
|
2
6
|
|
|
3
7
|
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
@@ -116,7 +116,7 @@ Every operation applied to a document is **stored as an event** in an append-onl
|
|
|
116
116
|
|
|
117
117
|
## **2. How Document Models Work Technically**
|
|
118
118
|
|
|
119
|
-
Document models in Powerhouse rely on **event-driven architecture, event sourcing, and CQRS principles**. Here
|
|
119
|
+
Document models in Powerhouse rely on **event-driven architecture, event sourcing, and CQRS principles**. Here's a step-by-step breakdown:
|
|
120
120
|
|
|
121
121
|
### **2.1 Document Creation**
|
|
122
122
|
|
|
@@ -190,4 +190,8 @@ Document Models offer a range of features that can be leveraged to create sophis
|
|
|
190
190
|
|
|
191
191
|
- **Version Control**: Similar to how Git manages changes to source code, Document Models in Connect will support version control, enabling users to track changes, compare different versions, and ensure data integrity over time.
|
|
192
192
|
|
|
193
|
-
Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
|
|
193
|
+
Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
|
|
194
|
+
|
|
195
|
+
### Up Next: How to build a Document Model
|
|
196
|
+
|
|
197
|
+
In the next chapters, we'll teach you how to build a ToDoList document model while explaining all of the theory that is involved.
|
|
@@ -21,6 +21,8 @@ GraphQL has a set of built-in **scalar types**:
|
|
|
21
21
|
* `Boolean`: `true` or `false`.
|
|
22
22
|
* `ID`: A unique identifier, often used as a key for a field. It is serialized in the same way as a String; however, it is not intended to be human-readable.
|
|
23
23
|
|
|
24
|
+
In addition to these standard types, the Powerhouse Document-Engineering system introduces custom scalars that are linked to reusable front-end components. These scalars are tailored for the web3 ecosystem and will be explored in the Component Library section of the documentation.
|
|
25
|
+
|
|
24
26
|
### Lists and Non-Null
|
|
25
27
|
You can modify types using lists and non-null indicators:
|
|
26
28
|
* **Lists**: To indicate that a field will return a list of a certain type, you wrap the type in square brackets, e.g., `[ToDoItem!]!`. This means the field `items` in `ToDoListState` will be a list of `ToDoItem` objects.
|
|
@@ -70,3 +72,6 @@ type ToDoItem {
|
|
|
70
72
|
6. **Root State Type**: It's a common pattern to have a single root type for your document state (e.g., `ToDoListState`). This provides a clear entry point for accessing all document data.
|
|
71
73
|
|
|
72
74
|
By carefully defining your state schema, you lay a solid foundation for your Powerhouse document model, making it robust, maintainable, and easy to work with. The schema dictates not only how data is stored but also how it can be queried and mutated through operations, which will be covered in the next section.
|
|
75
|
+
|
|
76
|
+
At the end of this Document Model Creation Chapter you will find the ToDoList Repository where you can explore the code and implementation of all the items we have discussed.
|
|
77
|
+
You'll be able to run the advanced ToDoList in Connect Studio and explore the reducers and editor code.
|
|
@@ -145,9 +145,10 @@ This command will **build** the project and create a build directory with the ou
|
|
|
145
145
|
|
|
146
146
|
This command will **start a local server** and serve the build output.
|
|
147
147
|
Inspect the build output and verify that the document models are working correctly.
|
|
148
|
+
Instead of `pnpm serve`, we'll be using:
|
|
148
149
|
|
|
149
150
|
```bash
|
|
150
|
-
|
|
151
|
+
ph connect
|
|
151
152
|
```
|
|
152
153
|
|
|
153
154
|
### 1.4 Storing your project in a git repository
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Document-Engineering
|
|
2
2
|
|
|
3
|
-
The reusable components in the Document-Engineering
|
|
3
|
+
The reusable components in the Document-Engineering system are a set of of front-end components based on graphQL scalars.
|
|
4
4
|
Powerhouse also has a set of custom scalars that are not part of the graphQL standard but are specific to the web3 ecosystem.
|
|
5
|
-
These components are offered through the **Powerhouse Document-Engineering
|
|
5
|
+
These components are offered through the **Powerhouse Document-Engineering system** with the help of storybook & the Academy documentation.
|
|
6
6
|
|
|
7
7
|
It provides a collection of pre-built, reusable UI components designed for consistency and efficiency across Powerhouse applications and editors. Think of it as a toolkit of standard UI elements like buttons, inputs, and checkboxes with many of these components based on graphql scalars.
|
|
8
8
|
|
|
@@ -19,29 +19,19 @@ In the next few chapters of our documentation, we will start with the simplest s
|
|
|
19
19
|
|
|
20
20
|
## **3 types of components**
|
|
21
21
|
|
|
22
|
-
1. **
|
|
22
|
+
1. **Scalar Component** has a simple scalar value as input
|
|
23
23
|
- Component, Composition of smaller UI controls (e.g. Scalar component)
|
|
24
|
-
|
|
25
24
|
2. **Complex Component** has an object/array value
|
|
26
25
|
- Group of components (e.g. sidebar tree view)
|
|
27
|
-
|
|
28
26
|
3. **Layout Component** will contain other components
|
|
29
27
|
- Containers for other components, Sections (e.g. list of other components, color layouts, etc.)
|
|
28
|
+
4. **fragments Component**
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
1. **Component Context**
|
|
34
|
-
2. **Scalar Definition**
|
|
35
|
-
3. **Component Storybook Base Example**
|
|
36
|
-
- Component Code
|
|
37
|
-
- Component Default Props
|
|
38
|
-
4. **Component Storybook Usage Examples**
|
|
30
|
+
For each of these components an implementation example will be given in our documentation.
|
|
39
31
|
|
|
40
32
|
## Exploring Components with Storybook
|
|
41
33
|
|
|
42
|
-
We use Storybook as an interactive catalog for our design system components. It allows you to visually explore each component, interact with different states, and understand how to integrate them into your projects.
|
|
43
|
-
|
|
44
|
-
[https://storybook.powerhouse.academy](https://storybook.powerhouse.academy)
|
|
34
|
+
We use Storybook as an interactive catalog for our design system components. It allows you to visually explore each component, interact with different states, and understand how to integrate them into your projects. [https://storybook.powerhouse.academy](https://storybook.powerhouse.academy)
|
|
45
35
|
|
|
46
36
|
**Understanding the Storybook Interface:**
|
|
47
37
|
|
|
@@ -54,8 +44,8 @@ We use Storybook as an interactive catalog for our design system components. It
|
|
|
54
44
|
Let's walk through the typical workflow for using a component from the document-engineering system, using the `Checkbox` from the [To-do List editor](/academy/GetStarted/BuildToDoListEditor).
|
|
55
45
|
|
|
56
46
|
1. **Identify the Need:** While building your feature (e.g., the To-do List editor in `editor.tsx`), you determine the need for a standard UI element, like a checkbox.
|
|
57
|
-
2. **Consult the
|
|
58
|
-
* Open the Powerhouse Storybook instance.
|
|
47
|
+
2. **Consult the Document Engineering Components in Storybook:**
|
|
48
|
+
* Open the Powerhouse Storybook instance. [https://storybook.powerhouse.academy](https://storybook.powerhouse.academy)
|
|
59
49
|
* Navigate or search to find the `Checkbox` component.
|
|
60
50
|
* Review the visual examples and interactive demo.
|
|
61
51
|
* Examine the "Usage" snippet and the **Props table** to understand the basic implementation and available configuration options (`label`, `value`, `onChange`, etc.).
|
|
@@ -85,10 +75,66 @@ Let's walk through the typical workflow for using a component from the document-
|
|
|
85
75
|
You configure the component's appearance and behavior by passing the appropriate values to its props.
|
|
86
76
|
5. **Test and Refine:** Run your application (e.g., using `ph connect`) to see the component in context. Verify its appearance and functionality.
|
|
87
77
|
|
|
88
|
-
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
The Document Engineering package provides several entry points for different use cases in your powerhouse project:
|
|
81
|
+
|
|
82
|
+
### Main Package
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { ... } from '@powerhousedao/document-engineering';
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### UI Components
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { ... } from '@powerhousedao/document-engineering/ui';
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Scalars
|
|
95
|
+
|
|
96
|
+
For data manipulation and transformation utilities:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { ... } from '@powerhousedao/document-engineering/scalars';
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### GraphQL
|
|
103
|
+
|
|
104
|
+
For GraphQL related utilities and schema definitions:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { ... } from '@powerhousedao/document-engineering/graphql';
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Styles
|
|
111
|
+
|
|
112
|
+
To include the package's styles:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import '@powerhousedao/document-engineering/style.css';
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Import Maps
|
|
119
|
+
|
|
120
|
+
Within the project, the following import maps are available:
|
|
121
|
+
|
|
122
|
+
- `#assets` - Assets utilities and components
|
|
123
|
+
- `#scalars` - Scalar transformations and utilities
|
|
124
|
+
- `#ui` - UI components
|
|
125
|
+
- `#graphql` - GraphQL related utilities
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
## **Storybook vs. Source Code:**
|
|
89
129
|
|
|
90
130
|
Storybook serves as essential documentation and a usage guide. Our developers write Storybook "stories" to demonstrate components and document their common props. However, the **ultimate source of truth** for a component's capabilities is its actual source code (e.g., the `.tsx` file within the `@powerhousedao/document-engineering/scalars` package).
|
|
91
131
|
While Storybook aims for accuracy, there might occasionally be discrepancies or undocumented props.
|
|
92
132
|
|
|
93
|
-
Please don't hesitate to reach out in our discord channels with any questions.
|
|
94
|
-
Happy designing!
|
|
133
|
+
Please don't hesitate to reach out in our discord channels with any questions.
|
|
134
|
+
Happy designing!
|
|
135
|
+
|
|
136
|
+
### Up next: Create Custom Scalars
|
|
137
|
+
|
|
138
|
+
You can learn how to do so in our guide on [Creating Custom Scalars](/academy/ComponentLibrary/CreateCustomScalars).
|
|
139
|
+
|
|
140
|
+
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# Step 1: Create Custom Scalars
|
|
2
|
+
|
|
3
|
+
This tutorial provides step-by-step instructions for creating custom scalars & components, and to contributing to the document-engineering project.
|
|
4
|
+
The github repo for the Document-Engineering can be found [here](https://github.com/powerhouse-inc/document-engineering/tree/main)
|
|
5
|
+
|
|
6
|
+
:::info
|
|
7
|
+
When contributing as an open source developer please submit a pull request to the Powerhouse team.
|
|
8
|
+
Although a design or UI for your scalar is not mandatory, it definitely helps reviewers if there's a visual reference.
|
|
9
|
+
That said, not all scalars require a dedicated UI component.
|
|
10
|
+
Some scalars, like scalar Title or scalar Description, might both map to a string and use the same UI, in this case scalars plays more semantic role than a type definition.
|
|
11
|
+
:::
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Creating New GraphQL Scalars](#creating-new-graphql-scalars)
|
|
16
|
+
- [Step 1: Create the Scalar File](#step-1-create-the-scalar-file)
|
|
17
|
+
- [Key Components to Update](#key-components-to-update)
|
|
18
|
+
- [Step 2: Register the Scalar in scalars.ts](#step-2-register-the-scalar-in-scalarts)
|
|
19
|
+
- [2.1 Add Namespace Import](#21-add-namespace-import)
|
|
20
|
+
- [2.2 Add Type Export](#22-add-type-export)
|
|
21
|
+
- [2.3 Add to Export Object](#23-add-to-export-object)
|
|
22
|
+
- [2.4 Add to Custom Scalars](#24-add-to-custom-scalars)
|
|
23
|
+
- [2.5 Add to Resolvers](#25-add-to-resolvers)
|
|
24
|
+
- [2.6 Add to Type Definitions](#26-add-to-type-definitions)
|
|
25
|
+
- [2.7 Add to Generator Type Definitions](#27-add-to-generator-type-definitions)
|
|
26
|
+
- [2.8 Add to Validation Schema](#28-add-to-validation-schema)
|
|
27
|
+
- [Step 3: Create Tests for Your Scalar](#step-3-create-tests-for-your-scalar)
|
|
28
|
+
- [Required Test Cases](#required-test-cases)
|
|
29
|
+
- [Testing Best Practices](#testing-best-practices)
|
|
30
|
+
- [Example Edge Cases for Different Scalar Types](#example-edge-cases-for-different-scalar-types)
|
|
31
|
+
- [Step 4: Validate Your Implementation](#step-4-validate-your-implementation)
|
|
32
|
+
- [Common Scalar Types](#common-scalar-types)
|
|
33
|
+
- [Tips](#tips)
|
|
34
|
+
|
|
35
|
+
## Creating New GraphQL Scalars
|
|
36
|
+
|
|
37
|
+
GraphQL scalars are custom data types that define how data is validated, serialized, and parsed. This guide will walk you through creating a new scalar in the `src/scalars/graphql/` directory.
|
|
38
|
+
|
|
39
|
+
### Step 1: Create the Scalar File
|
|
40
|
+
|
|
41
|
+
Create a new TypeScript file in `src/scalars/graphql/` for your scalar. Use `EmailAddress.ts` as a reference.
|
|
42
|
+
|
|
43
|
+
**Example: Creating a `PhoneNumber.ts` scalar**
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { GraphQLError, GraphQLScalarType, type GraphQLScalarTypeConfig, Kind } from 'graphql'
|
|
47
|
+
import { z } from 'zod'
|
|
48
|
+
|
|
49
|
+
export interface ScalarType {
|
|
50
|
+
input: string
|
|
51
|
+
output: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const type = 'string' // TS type in string form
|
|
55
|
+
|
|
56
|
+
export const typedef = 'scalar PhoneNumber'
|
|
57
|
+
|
|
58
|
+
export const schema = z.string().regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number format')
|
|
59
|
+
|
|
60
|
+
export const stringSchema = 'z.string().regex(/^\\+?[1-9]\\d{1,14}$/, "Invalid phone number format")'
|
|
61
|
+
|
|
62
|
+
const phoneValidation = (value: unknown): string => {
|
|
63
|
+
if (typeof value !== 'string') {
|
|
64
|
+
throw new GraphQLError(`Value is not string: ${JSON.stringify(value)}`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const result = schema.safeParse(value)
|
|
68
|
+
|
|
69
|
+
if (result.success) return result.data
|
|
70
|
+
throw new GraphQLError(result.error.message)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const config: GraphQLScalarTypeConfig<string, string> = {
|
|
74
|
+
name: 'PhoneNumber',
|
|
75
|
+
description: 'A field whose value conforms to international phone number format.',
|
|
76
|
+
serialize: phoneValidation,
|
|
77
|
+
parseValue: phoneValidation,
|
|
78
|
+
parseLiteral: (value) => {
|
|
79
|
+
if (value.kind !== Kind.STRING) {
|
|
80
|
+
throw new GraphQLError(`Can only validate strings as phone numbers but got a: ${value.kind}`, { nodes: value })
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return phoneValidation(value.value)
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const scalar = new GraphQLScalarType(config)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Key Components to Update:
|
|
91
|
+
|
|
92
|
+
1. **`type`**: The TypeScript type (usually `'string'` for text-based scalars)
|
|
93
|
+
2. **`typedef`**: The GraphQL type definition (e.g., `'scalar PhoneNumber'`)
|
|
94
|
+
3. **`schema`**: Zod validation schema for your data type
|
|
95
|
+
4. **`stringSchema`**: String representation of the zod schema (used for code generation)
|
|
96
|
+
5. **Validation function**: Custom validation logic for your scalar
|
|
97
|
+
6. **`config.name`**: The name of your scalar (must match the typedef)
|
|
98
|
+
7. **`config.description`**: Human-readable description of the scalar
|
|
99
|
+
|
|
100
|
+
### Step 2: Register the Scalar in `scalars.ts`
|
|
101
|
+
|
|
102
|
+
After creating your scalar file, you need to register it in `src/scalars/graphql/scalars.ts`. This involves updating multiple sections of the file.
|
|
103
|
+
The github repo for the Document-Engineering can be found [here](https://github.com/powerhouse-inc/document-engineering/tree/main)
|
|
104
|
+
|
|
105
|
+
#### 2.1 Add Namespace Import
|
|
106
|
+
|
|
107
|
+
Add your scalar to the namespace imports section (around line 2):
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// namespace imports -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
111
|
+
import * as Amount from './Amount.js'
|
|
112
|
+
import * as AmountCrypto from './AmountCrypto.js'
|
|
113
|
+
// ... other imports ...
|
|
114
|
+
import * as PhoneNumber from './PhoneNumber.js' // ADD THIS LINE
|
|
115
|
+
import * as URLScalar from './URL.js'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### 2.2 Add Type Export
|
|
119
|
+
|
|
120
|
+
Add the type export (around line 22):
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// export types -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
124
|
+
export type { ScalarType as AmountScalarType } from './Amount.js'
|
|
125
|
+
// ... other type exports ...
|
|
126
|
+
export type { ScalarType as PhoneNumberScalarType } from './PhoneNumber.js' // ADD THIS LINE
|
|
127
|
+
export type { ScalarType as URLScalarType } from './URL.js'
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### 2.3 Add to Export Object
|
|
131
|
+
|
|
132
|
+
Add your scalar to the main export object (around line 40):
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
export {
|
|
136
|
+
Amount,
|
|
137
|
+
AmountCrypto,
|
|
138
|
+
// ... other exports ...
|
|
139
|
+
PhoneNumber, // ADD THIS LINE
|
|
140
|
+
URLScalar,
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### 2.4 Add to Custom Scalars
|
|
145
|
+
|
|
146
|
+
Add your scalar to the `customScalars` object (around line 54):
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
export const customScalars: Record<string, BasePHScalar<any>> = {
|
|
150
|
+
// ... other scalars ...
|
|
151
|
+
PhoneNumber, // ADD THIS LINE
|
|
152
|
+
URLScalar,
|
|
153
|
+
} as const
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### 2.5 Add to Resolvers
|
|
157
|
+
|
|
158
|
+
Add your scalar to the `resolvers` object (around line 74):
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
export const resolvers = {
|
|
162
|
+
// export resolvers -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
163
|
+
AmountTokens: AmountTokens.scalar,
|
|
164
|
+
// ... other resolvers ...
|
|
165
|
+
PhoneNumber: PhoneNumber.scalar, // ADD THIS LINE
|
|
166
|
+
Amount: Amount.scalar,
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### 2.6 Add to Type Definitions
|
|
171
|
+
|
|
172
|
+
Add your typedef to the `typeDefs` array (around line 90):
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
export const typeDefs = [
|
|
176
|
+
// export typedefs -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
177
|
+
AmountTokens.typedef,
|
|
178
|
+
// ... other typedefs ...
|
|
179
|
+
PhoneNumber.typedef, // ADD THIS LINE
|
|
180
|
+
Amount.typedef,
|
|
181
|
+
]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### 2.7 Add to Generator Type Definitions
|
|
185
|
+
|
|
186
|
+
Add your scalar to the `generatorTypeDefs` object (around line 105):
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
export const generatorTypeDefs = {
|
|
190
|
+
// export generator typedefs -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
191
|
+
[AmountTokens.config.name]: AmountTokens.type,
|
|
192
|
+
// ... other entries ...
|
|
193
|
+
[PhoneNumber.config.name]: PhoneNumber.type, // ADD THIS LINE
|
|
194
|
+
[Amount.config.name]: Amount.type,
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### 2.8 Add to Validation Schema
|
|
199
|
+
|
|
200
|
+
Add your scalar to the `validationSchema` object (around line 120):
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
export const validationSchema = {
|
|
204
|
+
// export validation schema -- DO NOT REMOVE OR EDIT THIS COMMENT
|
|
205
|
+
[AmountTokens.config.name]: AmountTokens.stringSchema,
|
|
206
|
+
// ... other entries ...
|
|
207
|
+
[PhoneNumber.config.name]: PhoneNumber.stringSchema, // ADD THIS LINE
|
|
208
|
+
[Amount.config.name]: Amount.stringSchema,
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Step 3: Create Tests for Your Scalar
|
|
213
|
+
|
|
214
|
+
Every scalar must have comprehensive tests to ensure it works correctly. Create a test file in `src/scalars/graphql/test/` following the naming convention `YourScalar.test.ts`.
|
|
215
|
+
|
|
216
|
+
**Example: Creating `PhoneNumber.test.ts`**
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { Kind } from 'graphql'
|
|
220
|
+
import { scalar } from '../PhoneNumber.js'
|
|
221
|
+
|
|
222
|
+
describe('PhoneNumber Scalar', () => {
|
|
223
|
+
it('should serialize a phone number', () => {
|
|
224
|
+
const phoneNumber = '+1234567890'
|
|
225
|
+
|
|
226
|
+
expect(scalar.serialize(phoneNumber)).toBe(phoneNumber)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
it('should throw an error if the value is not a string', () => {
|
|
230
|
+
const phoneNumber = 123
|
|
231
|
+
|
|
232
|
+
expect(() => scalar.serialize(phoneNumber)).toThrow()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('should throw an error if the value is not a valid phone number', () => {
|
|
236
|
+
const phoneNumber = 'invalid-phone'
|
|
237
|
+
|
|
238
|
+
expect(() => scalar.serialize(phoneNumber)).toThrow()
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('should parse a valid phone number', () => {
|
|
242
|
+
const phoneNumber = '+1234567890'
|
|
243
|
+
|
|
244
|
+
expect(scalar.parseValue(phoneNumber)).toBe(phoneNumber)
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('should throw an error if parse a value that is not a valid phone number', () => {
|
|
248
|
+
const phoneNumber = 'invalid-phone'
|
|
249
|
+
|
|
250
|
+
expect(() => scalar.parseValue(phoneNumber)).toThrow()
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('should throw an error if parse a value that is not a string', () => {
|
|
254
|
+
const phoneNumber = 123
|
|
255
|
+
|
|
256
|
+
expect(() => scalar.parseValue(phoneNumber)).toThrow()
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
it('should parse a valid phone number from a literal', () => {
|
|
260
|
+
const phoneNumber = '+1234567890'
|
|
261
|
+
|
|
262
|
+
expect(
|
|
263
|
+
scalar.parseLiteral({
|
|
264
|
+
kind: Kind.STRING,
|
|
265
|
+
value: phoneNumber,
|
|
266
|
+
})
|
|
267
|
+
).toBe(phoneNumber)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should throw an error if parse a literal that is not a valid phone number', () => {
|
|
271
|
+
const phoneNumber = 'invalid-phone'
|
|
272
|
+
|
|
273
|
+
expect(() =>
|
|
274
|
+
scalar.parseLiteral({
|
|
275
|
+
kind: Kind.STRING,
|
|
276
|
+
value: phoneNumber,
|
|
277
|
+
})
|
|
278
|
+
).toThrow()
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
it('should throw an error if parse a literal that is not a string', () => {
|
|
282
|
+
const phoneNumber = '+1234567890'
|
|
283
|
+
|
|
284
|
+
expect(() =>
|
|
285
|
+
scalar.parseLiteral({
|
|
286
|
+
kind: Kind.INT,
|
|
287
|
+
value: phoneNumber,
|
|
288
|
+
})
|
|
289
|
+
).toThrow()
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Required Test Cases
|
|
295
|
+
|
|
296
|
+
Your scalar tests should cover these essential scenarios:
|
|
297
|
+
|
|
298
|
+
##### Serialization Tests
|
|
299
|
+
|
|
300
|
+
- ✅ **Valid values**: Test that valid inputs are serialized correctly
|
|
301
|
+
- ❌ **Invalid types**: Test that non-string inputs throw errors
|
|
302
|
+
- ❌ **Invalid format**: Test that strings not matching your validation throw errors
|
|
303
|
+
|
|
304
|
+
##### Parse Value Tests
|
|
305
|
+
|
|
306
|
+
- ✅ **Valid values**: Test that valid inputs are parsed correctly
|
|
307
|
+
- ❌ **Invalid format**: Test that invalid strings throw errors
|
|
308
|
+
- ❌ **Invalid types**: Test that non-string inputs throw errors
|
|
309
|
+
|
|
310
|
+
##### Parse Literal Tests
|
|
311
|
+
|
|
312
|
+
- ✅ **Valid STRING literals**: Test that valid string literals are parsed correctly
|
|
313
|
+
- ❌ **Invalid STRING literals**: Test that invalid string literals throw errors
|
|
314
|
+
- ❌ **Non-STRING literals**: Test that non-string literal kinds (INT, FLOAT, etc.) throw errors
|
|
315
|
+
|
|
316
|
+
#### Testing Best Practices
|
|
317
|
+
|
|
318
|
+
1. **Test edge cases**: Include boundary values and common invalid inputs
|
|
319
|
+
2. **Test multiple valid formats**: If your scalar accepts different valid formats, test them all
|
|
320
|
+
3. **Use descriptive test names**: Make it clear what each test is validating
|
|
321
|
+
4. **Follow the naming convention**: `YourScalar.test.ts` in the `test/` directory
|
|
322
|
+
|
|
323
|
+
#### Example Edge Cases for Different Scalar Types
|
|
324
|
+
|
|
325
|
+
**String-based scalars (like PhoneNumber):**
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// Test empty string
|
|
329
|
+
expect(() => scalar.parseValue('')).toThrow()
|
|
330
|
+
|
|
331
|
+
// Test too long/short values
|
|
332
|
+
expect(() => scalar.parseValue('123')).toThrow()
|
|
333
|
+
expect(() => scalar.parseValue('+' + '1'.repeat(20))).toThrow()
|
|
334
|
+
|
|
335
|
+
// Test special characters
|
|
336
|
+
expect(() => scalar.parseValue('+1-234-567-890')).not.toThrow()
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Number-based scalars:**
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
// Test zero
|
|
343
|
+
expect(scalar.parseValue(0)).toBe(0)
|
|
344
|
+
|
|
345
|
+
// Test negative numbers
|
|
346
|
+
expect(() => scalar.parseValue(-1)).toThrow()
|
|
347
|
+
|
|
348
|
+
// Test decimal numbers
|
|
349
|
+
expect(scalar.parseValue(123.45)).toBe(123.45)
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Date-based scalars:**
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// Test valid ISO date
|
|
356
|
+
expect(scalar.parseValue('2023-12-25T00:00:00Z')).toBe('2023-12-25T00:00:00Z')
|
|
357
|
+
|
|
358
|
+
// Test invalid date format
|
|
359
|
+
expect(() => scalar.parseValue('25/12/2023')).toThrow()
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Step 4: Validate Your Implementation
|
|
363
|
+
|
|
364
|
+
After implementing your scalar and tests, make sure to:
|
|
365
|
+
|
|
366
|
+
1. **Run the tests** to ensure they all pass
|
|
367
|
+
2. **Build the project** to ensure there are no TypeScript errors
|
|
368
|
+
3. **Test GraphQL queries** that use your new scalar
|
|
369
|
+
4. **Verify code generation** works with your new scalar
|
|
370
|
+
|
|
371
|
+
### Common Scalar Types
|
|
372
|
+
|
|
373
|
+
Here are some common patterns for different types of scalars:
|
|
374
|
+
|
|
375
|
+
#### String-based Scalars
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
export const type = 'string'
|
|
379
|
+
export const schema = z.string().min(1).max(100)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### Number-based Scalars
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
export const type = 'number'
|
|
386
|
+
export const schema = z.number().positive()
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
#### Date-based Scalars
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
export const type = 'string'
|
|
393
|
+
export const schema = z.string().datetime()
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Tips
|
|
397
|
+
|
|
398
|
+
- Always follow the naming convention: use PascalCase for scalar names
|
|
399
|
+
- Include meaningful validation in your Zod schema
|
|
400
|
+
- Write clear, descriptive error messages
|
|
401
|
+
- Keep the `stringSchema` in sync with your `schema` definition
|
|
402
|
+
- Test edge cases in your validation function
|
|
403
|
+
- Update all required sections in `scalars.ts`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Tabs, TabItem } from '@theme/Tabs';
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Scalar Component Example
|
|
4
4
|
|
|
5
5
|
Scalars are here to help you define custom fields in your document model schema and speed up the development process.
|
|
6
6
|
There are two applications of scalar components in the document model workflow:
|
|
@@ -12,20 +12,13 @@ There are two applications of scalar components in the document model workflow:
|
|
|
12
12
|
|
|
13
13
|
As you might know, the document model schema defines the structure of the document and serves as the backbone of the document model. The GraphQL state schema defines how data is captured with the help of types & scalars. When you define a scalar in the document model schema, you are essentially defining a new field that can be used in the document model to capture data.
|
|
14
14
|
|
|
15
|
-
In the Document Model Editor, you can find all the custom scalar types available
|
|
15
|
+
In the Document Model Editor, you can find all the custom scalar types available under the 'Scalars' section.
|
|
16
16
|
|
|
17
|
-
Insert image of the feature.
|
|
18
|
-
|
|
19
|
-
````
|
|
20
|
-
scalar PHID <-- imported from the design system library? not sure
|
|
21
|
-
type MyType {
|
|
22
|
-
myScalar: PHID
|
|
23
|
-
}
|
|
24
|
-
````
|
|
17
|
+
Insert image of the feature. @callme-t
|
|
25
18
|
|
|
26
19
|
## React Component Implementation in the Frontend
|
|
27
20
|
|
|
28
|
-
All of our reusable components are available in the Document-Engineering
|
|
21
|
+
All of our reusable components are available in the Document-Engineering system package.
|
|
29
22
|
This package comes as a dependency in your project when creating a new document model project.
|
|
30
23
|
````
|
|
31
24
|
import PHIDField from 'document-engineering'
|
|
@@ -55,68 +48,5 @@ The reusable components are essentially a set of front-end components based on G
|
|
|
55
48
|
|
|
56
49
|
Read the next chapter to get familiar with our reusable components.
|
|
57
50
|
|
|
58
|
-
# PHID Field Example
|
|
59
|
-
|
|
60
|
-
### **Scalar Definition**
|
|
61
|
-
|
|
62
|
-
- **Name:** `PHID` (Powerhouse ID)
|
|
63
|
-
- **Purpose:** Represents a unique identifier pointing to a document, branch, scope, or data object within the Powerhouse system.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<details>
|
|
67
|
-
<summary>**Formatting of the component:**</summary>
|
|
68
|
-
- **Basic Notation:** `phd:<documentID>`
|
|
69
|
-
- **Branch and Scope:** Optional components appended using colons `:`.
|
|
70
|
-
- **Full Notation:** `phd:<documentID>:<branch>:<scope>`
|
|
71
|
-
- **Branch:** Defaults to `main` if omitted.
|
|
72
|
-
- **Scope:** Defaults to `public` if omitted.
|
|
73
|
-
- **Data Object Reference:** `phd:<documentID>/<dataObjectID>`
|
|
74
|
-
- **URL Format:** `phd://<domain>/<documentID>`
|
|
75
|
-
- Example: `phd://switchboard.powerhouse.xyz/baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
76
|
-
|
|
77
|
-
**Examples of the component formatting:**
|
|
78
|
-
- **Basic PHID:** `phd:baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
79
|
-
- **With Branch:** `phd:baefc2a4...:draft`
|
|
80
|
-
- **With Scope:** `phd:baefc2a4...::local`
|
|
81
|
-
- **With Branch and Scope:** `phd:baefc2a4...:draft:local`
|
|
82
|
-
- **With Data Object ID:** `phd:baefc2a4.../3cf05e40...`
|
|
83
|
-
</details>
|
|
84
|
-
|
|
85
|
-
<details>
|
|
86
|
-
<summary>**Validation of the Component:**</summary>
|
|
87
|
-
- **Validate each format:**
|
|
88
|
-
1. **PHID only:** Ensure the document ID is a valid UUID.
|
|
89
|
-
2. **PHID with data element (OID):** Validate both the document ID and the data object ID.
|
|
90
|
-
3. **PHID with branch:** Validate the document ID and check if the branch is properly formatted.
|
|
91
|
-
4. **PHID with scope:** Validate the document ID and check if the scope is valid.
|
|
92
|
-
5. **PHID with branch and scope:** Validate all three components: document ID, branch, and scope.
|
|
93
|
-
- **Error Message Example:** "Invalid PHID format. Please check the document ID, branch, or scope."
|
|
94
|
-
</details>
|
|
95
|
-
|
|
96
|
-
The following is the UI component for the PHID field and scalar in a storybook.
|
|
97
|
-
We use Storybook as our component development environment.
|
|
98
|
-
It allows us to build and test UI components in isolation, making it easier to develop, test, and document reusable components.
|
|
99
|
-
In our stories you'll find first find a basic UI implementation example of the component, followed by the component's properties, events, and validation options.
|
|
100
|
-
|
|
101
|
-
- A list of the **default properties** and their descriptions, and a list of the available events that can be triggered.
|
|
102
|
-
- A list of the **component's specific properties** and attributes based on the components functionality.
|
|
103
|
-
- A list of **validation options**, or ways to validate the component's desired input values.
|
|
104
|
-
|
|
105
|
-
Additionally, you'll find various **stories of the components in different states**.
|
|
106
|
-
|
|
107
|
-
<div style={{
|
|
108
|
-
border: '1px solid #E5E7EB',
|
|
109
|
-
borderRadius: '8px',
|
|
110
|
-
padding: '16px',
|
|
111
|
-
marginBottom: '20px',
|
|
112
|
-
}}>
|
|
113
|
-
<iframe
|
|
114
|
-
src="https://storybook.powerhouse.academy/iframe.html?id=scalars-phid-field--readme&viewMode=story"
|
|
115
|
-
style={{
|
|
116
|
-
width: '100%',
|
|
117
|
-
height: '4500px',
|
|
118
|
-
border: 'none',
|
|
119
|
-
}}
|
|
120
|
-
title="PhidField Component Demo"
|
|
121
|
-
/>
|
|
122
|
-
</div>
|
|
51
|
+
# PHID Field Implementation Example
|
|
52
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Integrate your Scalar into a React Component
|
|
@@ -1,58 +1,5 @@
|
|
|
1
1
|
import { Tabs, TabItem } from '@theme/Tabs';
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Layout Component Example
|
|
4
4
|
|
|
5
5
|
## PHID Field Example
|
|
6
|
-
|
|
7
|
-
### **Scalar Definition**
|
|
8
|
-
|
|
9
|
-
- **Name:** `PHID` (Powerhouse ID)
|
|
10
|
-
- **Purpose:** Represents a unique identifier pointing to a document, branch, scope, or data object within the Powerhouse system.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<details>
|
|
14
|
-
<summary>**Formatting of the component:**</summary>
|
|
15
|
-
- **Basic Notation:** `phd:<documentID>`
|
|
16
|
-
- **Branch and Scope:** Optional components appended using colons `:`.
|
|
17
|
-
- **Full Notation:** `phd:<documentID>:<branch>:<scope>`
|
|
18
|
-
- **Branch:** Defaults to `main` if omitted.
|
|
19
|
-
- **Scope:** Defaults to `public` if omitted.
|
|
20
|
-
- **Data Object Reference:** `phd:<documentID>/<dataObjectID>`
|
|
21
|
-
- **URL Format:** `phd://<domain>/<documentID>`
|
|
22
|
-
- Example: `phd://switchboard.powerhouse.xyz/baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
23
|
-
|
|
24
|
-
**Examples of the component formatting:**
|
|
25
|
-
- **Basic PHID:** `phd:baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
26
|
-
- **With Branch:** `phd:baefc2a4...:draft`
|
|
27
|
-
- **With Scope:** `phd:baefc2a4...::local`
|
|
28
|
-
- **With Branch and Scope:** `phd:baefc2a4...:draft:local`
|
|
29
|
-
- **With Data Object ID:** `phd:baefc2a4.../3cf05e40...`
|
|
30
|
-
</details>
|
|
31
|
-
|
|
32
|
-
<details>
|
|
33
|
-
<summary>**Validation of the Component:**</summary>
|
|
34
|
-
- **Validate each format:**
|
|
35
|
-
1. **PHID only:** Ensure the document ID is a valid UUID.
|
|
36
|
-
2. **PHID with data element (OID):** Validate both the document ID and the data object ID.
|
|
37
|
-
3. **PHID with branch:** Validate the document ID and check if the branch is properly formatted.
|
|
38
|
-
4. **PHID with scope:** Validate the document ID and check if the scope is valid.
|
|
39
|
-
5. **PHID with branch and scope:** Validate all three components: document ID, branch, and scope.
|
|
40
|
-
- **Error Message Example:** "Invalid PHID format. Please check the document ID, branch, or scope."
|
|
41
|
-
</details>
|
|
42
|
-
|
|
43
|
-
<div style={{
|
|
44
|
-
border: '1px solid #E5E7EB',
|
|
45
|
-
borderRadius: '8px',
|
|
46
|
-
padding: '16px',
|
|
47
|
-
marginBottom: '20px',
|
|
48
|
-
}}>
|
|
49
|
-
<iframe
|
|
50
|
-
src="https://dspot-scalars-storybook.vercel.app/iframe.html?args=name:amount-field;placeholder:test;label:Enter%20Amount%20and%20Select%20Currency;type:Amount;placeholderSelect:CUR;allowedTokens:!null;tokenIcons.Sol:1;value.amount:3454564564;value.currency:BTC&id=document-engineering-simple-components-phid-field--readme&viewMode=story"
|
|
51
|
-
style={{
|
|
52
|
-
width: '100%',
|
|
53
|
-
height: '4500px',
|
|
54
|
-
border: 'none',
|
|
55
|
-
}}
|
|
56
|
-
title="PhidField Component Demo"
|
|
57
|
-
/>
|
|
58
|
-
</div>
|
|
@@ -1,58 +1,5 @@
|
|
|
1
1
|
import { Tabs, TabItem } from '@theme/Tabs';
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Fragment Component Example
|
|
4
4
|
|
|
5
5
|
## PHID Field Example
|
|
6
|
-
|
|
7
|
-
### **Scalar Definition**
|
|
8
|
-
|
|
9
|
-
- **Name:** `PHID` (Powerhouse ID)
|
|
10
|
-
- **Purpose:** Represents a unique identifier pointing to a document, branch, scope, or data object within the Powerhouse system.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<details>
|
|
14
|
-
<summary>**Formatting of the component:**</summary>
|
|
15
|
-
- **Basic Notation:** `phd:<documentID>`
|
|
16
|
-
- **Branch and Scope:** Optional components appended using colons `:`.
|
|
17
|
-
- **Full Notation:** `phd:<documentID>:<branch>:<scope>`
|
|
18
|
-
- **Branch:** Defaults to `main` if omitted.
|
|
19
|
-
- **Scope:** Defaults to `public` if omitted.
|
|
20
|
-
- **Data Object Reference:** `phd:<documentID>/<dataObjectID>`
|
|
21
|
-
- **URL Format:** `phd://<domain>/<documentID>`
|
|
22
|
-
- Example: `phd://switchboard.powerhouse.xyz/baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
23
|
-
|
|
24
|
-
**Examples of the component formatting:**
|
|
25
|
-
- **Basic PHID:** `phd:baefc2a4-f9a0-4950-8161-fd8d8cc7dea9`
|
|
26
|
-
- **With Branch:** `phd:baefc2a4...:draft`
|
|
27
|
-
- **With Scope:** `phd:baefc2a4...::local`
|
|
28
|
-
- **With Branch and Scope:** `phd:baefc2a4...:draft:local`
|
|
29
|
-
- **With Data Object ID:** `phd:baefc2a4.../3cf05e40...`
|
|
30
|
-
</details>
|
|
31
|
-
|
|
32
|
-
<details>
|
|
33
|
-
<summary>**Validation of the Component:**</summary>
|
|
34
|
-
- **Validate each format:**
|
|
35
|
-
1. **PHID only:** Ensure the document ID is a valid UUID.
|
|
36
|
-
2. **PHID with data element (OID):** Validate both the document ID and the data object ID.
|
|
37
|
-
3. **PHID with branch:** Validate the document ID and check if the branch is properly formatted.
|
|
38
|
-
4. **PHID with scope:** Validate the document ID and check if the scope is valid.
|
|
39
|
-
5. **PHID with branch and scope:** Validate all three components: document ID, branch, and scope.
|
|
40
|
-
- **Error Message Example:** "Invalid PHID format. Please check the document ID, branch, or scope."
|
|
41
|
-
</details>
|
|
42
|
-
|
|
43
|
-
<div style={{
|
|
44
|
-
border: '1px solid #E5E7EB',
|
|
45
|
-
borderRadius: '8px',
|
|
46
|
-
padding: '16px',
|
|
47
|
-
marginBottom: '20px',
|
|
48
|
-
}}>
|
|
49
|
-
<iframe
|
|
50
|
-
src="https://dspot-scalars-storybook.vercel.app/iframe.html?args=name:amount-field;placeholder:test;label:Enter%20Amount%20and%20Select%20Currency;type:Amount;placeholderSelect:CUR;allowedTokens:!null;tokenIcons.Sol:1;value.amount:3454564564;value.currency:BTC&id=document-engineering-simple-components-phid-field--readme&viewMode=story"
|
|
51
|
-
style={{
|
|
52
|
-
width: '100%',
|
|
53
|
-
height: '4500px',
|
|
54
|
-
border: 'none',
|
|
55
|
-
}}
|
|
56
|
-
title="PhidField Component Demo"
|
|
57
|
-
/>
|
|
58
|
-
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# AI Resources
|
|
2
|
+
|
|
3
|
+
We have a couple of AI resources to help you with your daily work.
|
|
4
|
+
|
|
5
|
+
## Deepwiki
|
|
6
|
+
A searchable/queriable wiki to understand our growing mono repo better.
|
|
7
|
+
https://deepwiki.com/powerhouse-inc/powerhouse
|
|
8
|
+
|
|
9
|
+
:::info
|
|
10
|
+
What is DeepWiki?
|
|
11
|
+
DeepWiki provides up-to-date documentation you can talk to, for every repo in the world. Think Deep Research for GitHub.
|
|
12
|
+
:::
|
|
13
|
+
|
|
14
|
+
## Context7
|
|
15
|
+
The Powerhouse Academy is also available as context through the context7 MCP Server.
|
|
16
|
+
https://context7.com/powerhouse-inc/powerhouse
|
|
17
|
+
|
|
18
|
+
:::info
|
|
19
|
+
What is Context7?
|
|
20
|
+
LLMs rely on outdated or generic information about the libraries you use.
|
|
21
|
+
|
|
22
|
+
Context7 pulls up-to-date, version-specific documentation and code examples directly from the source. Paste accurate, relevant documentation directly into tools like Cursor, Claude, or any LLM. Get better answers, no hallucinations and an AI that actually understands your stack.
|
|
23
|
+
:::
|
package/package.json
CHANGED
package/sidebars.ts
CHANGED