Skip to content

Commit 8a6fde7

Browse files
committed
Add AGENTS.md
1 parent f9d0970 commit 8a6fde7

File tree

5 files changed

+145
-0
lines changed

5 files changed

+145
-0
lines changed

AGENTS.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# AGENTS.md for Bot Framework Web Chat
2+
3+
## Coding
4+
5+
### Package management
6+
7+
- When adding dependencies, use `npm install`
8+
- Do not add it to workspace root
9+
- If it is an existing package, must use consistent version: either use existing version for the package or consider bumping every dependents to latest
10+
- Production code must avoid packages from Node.js packages or polyfills
11+
- Use `ReadableStream`, `WritableStream`, `TransformStream`, instead of Node.js `buffer`
12+
- Use Web Cryptography instead of Node.js `crypto`
13+
- Do not use `fs`-like or `net`-like packages
14+
- Do not use any Browserify-like packages
15+
- When adding pacakges to the following packages, verify:
16+
- `/packages/api/` and `/packages/core/`: Newly added packages and transient packages must be platform-neutral
17+
- `/packages/test/`: Open to any packages
18+
- `/packages/*/`: Newly added packages and transient packages must be either platform-neutral or targetting browser
19+
- Do not add external/publishing packages unless explicitly requested
20+
- Always prefix internal/non-publishing packages with `@msinternal/` to prevent package squatting
21+
22+
### General
23+
24+
- Unless stated otherwise, assume browser and React is available, avoid Node.js
25+
- Apply our latest coding style to every file changed
26+
- Avoid spaghetti code: on new feature with a similar existing feature, refactor existing one before writing new feature
27+
- This does not applies to test code
28+
- Avoid global pollution, do not modify `window` object
29+
- Markdown are always space-indented with 3 spaces
30+
- Use `/prettierrc.yml` to format
31+
- Sort names in property bags
32+
- Avoid one-use variable, inline them instead
33+
- More new lines to separate code with different responsibilities
34+
- Multiple lines of code that can run in random order, put them into a group, no need new line between them
35+
- Otherwise, lines of code that depends on each other in a specific order, separate them with new line
36+
- Prefer `&&` over if-statement if it is a oneliner
37+
- Importing relative file should always include file extension
38+
- Prefer truthy/false check like `!array.length` over `array.length === 0`
39+
- Prefer `numValue` over `valueCount` for "how many values are there"
40+
- Prefer uppercase for acronyms instead of Pascal case, e.g. `getURL()` over `getUrl()`
41+
- The only exception is `id`, e.g. `getId()` over `getID()`
42+
- Use fewer shorthands, only allow `min`, `max`, `num`
43+
44+
### Design
45+
46+
- Use immutability as much as possible, add `object.freeze()`
47+
- Follow W3C convention for API design
48+
- Extends `EventTarget` when eventing is needed, do not use Node.js `on`/`off`
49+
- Consider `IntersectionObserver`-like pattern for allow userland to subscribe to live changes
50+
- Allow ESNext code that is polyfilled by `core-js-pure` or `iter-fest` package
51+
52+
### Typing
53+
54+
- TypeScript is best-effort checking, use valibot for strict type checking
55+
- Use `valibot` for runtime type checker, never use `zod`
56+
- Assume all externally exported functions will receive unsafe/invalid input, always check with `valibot`
57+
- Avoid `any`
58+
- Avoid `as`, use `valibot` instead
59+
- If absolutely needed, use `satisifes X as Y` to make sure it is `X` before force casting to `Y`
60+
- Use as few `unknown` as possible
61+
- All optional properties must be `undefined`-able, i.e. use `value?: number | undefined` over `value?: number`
62+
- For functions exported outside of current file, make sure all arguments and return value are typed
63+
- If need to look inside the object to check for types, use `valibot`
64+
- E.g. `if (obj && typeof obj === 'object' && 'value' in obj && typeof obj.value === 'string')` should be replaced with `safeParse(object({ value: string }), obj).success`
65+
- Use `{ readonly value: string }` instead of `Readonly<{ value: string }>`
66+
- Use as much `readonly` as possible
67+
68+
### React template
69+
70+
```tsx
71+
import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
72+
import React from 'react';
73+
import { number, object, pipe, readonly } from 'valibot';
74+
75+
// Use valibot to validate props.
76+
const MyComponentPropsSchema = pipe(
77+
object({
78+
children: optional(reactNode())
79+
}),
80+
readonly()
81+
);
82+
83+
type MyComponentProps = InferInput<typeof MyComponentPropsSchema>;
84+
85+
// Use big function instead of arrow function.
86+
function MyComponent(props: MyComponentProps) {
87+
// Call `validateProps` to get a validated props.
88+
const { children } = validateProps(MyComponentPropsSchema, props);
89+
90+
// Use `<>` instead of `<Fragment>`.
91+
// Never export `children` by itself, always wrap with `<>`.
92+
return <>{children}</>;
93+
}
94+
95+
// Set `displayName`.
96+
MyComponent.displayName = 'MyComponent';
97+
98+
// Export as memoized/exotic component, export as default.
99+
export default memo(MyComponent);
100+
101+
// Export both schema and typing.
102+
export { MyComponentPropsSchema, type MyComponentProps };
103+
```
104+
105+
## Testing instructions
106+
107+
- Practice test-driven development
108+
- Build and run Docker to host WebDriver-controlled browser instances
109+
- Build container by `docker compose -f docker-compose-wsl2.yml build --build-arg REGISTRY=mcr.microsoft.com`
110+
- Start container by `docker compose -f docker-compose-wsl2.yml up --detach --scale chrome=2`
111+
- Run `curl http://localhost:4444/wd/hub/status` and wait until `.value.ready` become `true`
112+
- Run `npm test`, or `npm test -- --testPathPattern test-html-file.html` to focus on one
113+
- Test files are HTML files under `/__tests__/html2/`, they are not JS
114+
- Follow other HTML files under the same folder on how to write tests
115+
- Page conditions, page elements, and page objects can be found at `/packages/test/page-object/src/globals`
116+
- Use `expect` instead of `assert`
117+
- Use `@testduet/given-when-then` package instead of xUnit style `describe`/`before`/`test`/`after`
118+
- Prefer integration/end-to-end testing than unit testing
119+
- Use as realistic setup as possible, such as using `msw` than mocking calls
120+
121+
## PR instructions
122+
123+
- Run new test and all of them must be green
124+
- Run `npm run precommit` to make sure it pass all linting process
125+
- Add changelog entry to `CHANGELOG.md`, follow our existing format

packages/api/AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# AGENTS.md for `botframework-webchat-api`
2+
3+
## Coding
4+
5+
- Allow browser technologies, but no Node.js nor React

packages/base/AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# AGENTS.md for `botframework-webchat-base`
2+
3+
## Coding
4+
5+
- Stay platform neutral, no browser technologies, no Node.js, no React

packages/core/AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# AGENTS.md for `botframework-webchat-core`
2+
3+
## Coding
4+
5+
- Stay platform neutral, no browser technologies, no Node.js, no React

packages/test/AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# AGENTS.md for test framework
2+
3+
## Coding
4+
5+
- All technologies are allowed, including Node.js

0 commit comments

Comments
 (0)