Skip to content

Commit b6c7948

Browse files
PascalThuetclaude
andcommitted
docs: rewrite AGENTS.md — gotchas-only, DRY, verifiable
Rewrites AGENTS.md from 170 lines to ~50. Removes duplicated content (ESLint rules, FactoryMaker examples, project tree, naming conventions) that had already drifted out of sync. Fixes inaccuracies (npm run build pipeline, entry point exports, webpack bundle counts). Keeps only non-derivable gotchas and a "where to look" index. Closes Dash-Industry-Forum#4995 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 98d2e9f commit b6c7948

1 file changed

Lines changed: 47 additions & 167 deletions

File tree

AGENTS.md

Lines changed: 47 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -1,169 +1,49 @@
11
# AGENTS.md
22

3-
## Project Overview
4-
5-
dash.js is the DASH Industry Forum reference client for MPEG-DASH playback in browsers.
6-
Pure JavaScript (ES2020), ESM modules (`"type": "module"`), no TypeScript in source code
7-
(TypeScript is only used to validate `index.d.ts`). Node >= 20 required.
8-
9-
## Build Commands
10-
11-
```bash
12-
npm run build # Full build: clean, typecheck, test, lint, then webpack (modern + legacy)
13-
npm run build-modern # Clean + typecheck + test + lint + webpack modern only
14-
npm run build-legacy # Clean + typecheck + test + lint + webpack
15-
npm run dev # Typecheck + webpack modern dev (watch mode)
16-
npm start # webpack-dev-server on port 3000 (opens samples/index.html)
17-
npm run lint # ESLint on src/**/*.js and test/unit/{mocks,test}/**/*.js
18-
npm run doc # Generate JSDoc documentation
19-
```
20-
21-
## Testing
22-
23-
**Frameworks:** Karma (runner) + Mocha (describe/it) + Chai (expect/assert) + Sinon (spy/stub/mock)
24-
25-
```bash
26-
# Run all unit tests (ChromeHeadless + FirefoxHeadless)
27-
npm test
28-
29-
# Run a single test or subset by grep pattern (matches describe/it names)
30-
npx karma start test/unit/config/karma.unit.conf.cjs --grep="EventBus"
31-
npx karma start test/unit/config/karma.unit.conf.cjs --grep="getOptimalRepresentationForBitrate"
32-
33-
# Run functional tests
34-
npm run test-functional
35-
```
36-
37-
There is no per-file test runner. All unit tests are bundled by Karma/webpack and run
38-
together in a headless browser. Use `--grep` to filter by test name.
39-
40-
Unit test files live in `test/unit/test/` and mirror the `src/` directory structure.
41-
Test file naming convention uses dot-separated module paths:
42-
- `core.EventBus.js` tests `src/core/EventBus.js`
43-
- `streaming.controllers.AbrController.js` tests `src/streaming/controllers/AbrController.js`
44-
- `dash.models.DashManifestModel.js` tests `src/dash/models/DashManifestModel.js`
45-
46-
## Code Style
47-
48-
### Formatting (enforced by ESLint flat config in `eslint.config.mjs`)
49-
50-
- **Indentation:** 4 spaces (including switch case bodies)
51-
- **Quotes:** Single quotes, template literals allowed
52-
- **Semicolons:** Required
53-
- **Curly braces:** Always required, even for single-line blocks (`curly: 'all'`)
54-
- **Line endings:** LF (see `.editorconfig`)
55-
- **Trailing whitespace:** Trimmed in `.js` files
56-
- **Final newline:** Required in `.js` and `.md` files
57-
- **Keyword spacing:** Space before and after keywords (`if`, `else`, `for`, etc.)
58-
- **Infix operators:** Spaces around operators (`a + b`, not `a+b`)
59-
- **No multi-spaces:** Only single spaces between tokens
60-
- **No Prettier:** Formatting is handled by ESLint rules only
61-
62-
### Imports
63-
64-
- ES module `import`/`export` syntax exclusively
65-
- Always include `.js` extension in import paths: `import Foo from './Foo.js'`
66-
- Relative paths for internal imports
67-
- Group order: external dependencies first, then internal modules
68-
- Default exports are the norm; named exports are rare
69-
70-
### Architecture Pattern — FactoryMaker
71-
72-
Most modules use the **factory function pattern**, not ES classes:
73-
74-
```js
75-
function MyController() {
76-
const context = this.context;
77-
let instance, logger, someState;
78-
79-
function setup() { /* init logic, called at bottom of factory */ }
80-
function _privateMethod() { /* underscore prefix */ }
81-
function publicMethod() { /* no prefix */ }
82-
function reset() { /* cleanup on teardown */ }
83-
84-
instance = { publicMethod, reset };
85-
setup();
86-
return instance;
87-
}
88-
MyController.__dashjs_factory_name = 'MyController';
89-
export default FactoryMaker.getSingletonFactory(MyController);
90-
```
91-
92-
Key conventions:
93-
- **Singletons** (`getSingletonFactory`): one instance per context (controllers, models)
94-
- **Class factories** (`getClassFactory`): new instance each call (value objects, processors)
95-
- **`__dashjs_factory_name`**: required static property for registration, matches the function name
96-
- **`setup()`**: called at the bottom of the factory function for initialization
97-
- **`reset()`**: cleanup method, should restore initial state
98-
- **`setConfig(config)`**: dependency injection method, receives an object with dependencies
99-
- **`instance` object**: the public API; only methods listed here are public
100-
101-
### Value Objects
102-
103-
Simple data classes in `src/*/vo/` use ES class syntax with constructor assignments
104-
and `export default ClassName`. See `src/streaming/vo/DashJSError.js` for an example.
105-
106-
### Naming Conventions
107-
108-
- **Files:** PascalCase for classes/factories (`AbrController.js`, `MediaPlayer.js`)
109-
- **Private methods:** `_underscore` prefix (`_onQualityChangeRendered`, `_commonOn`)
110-
- **Public methods:** camelCase, no prefix
111-
- **Constants:** UPPER_SNAKE_CASE for module-level constants; constant objects use PascalCase keys
112-
- **Events:** Class-based hierarchy extending `EventsBase`, string constant properties
113-
- **Loggers:** `logger = debug.getLogger(instance)` — use `logger.debug()`, `logger.info()`, `logger.warn()`, `logger.error()`
114-
115-
### Error Handling
116-
117-
- Errors are dispatched via `EventBus` as error events, not thrown
118-
- Use `DashJSError` value objects (code + message + data)
119-
- Error codes are defined as constants in `src/core/errors/Errors.js` and `src/streaming/vo/metrics/PlayList.js`
120-
- Critical errors trigger `Events.ERROR`; check `error.code` to distinguish types
121-
122-
### License Header
123-
124-
Every source file must include the BSD-3-Clause license header (approximately 30 lines)
125-
at the top of the file. See any existing source file for the exact text.
126-
127-
## Test Conventions
128-
129-
Tests follow this general pattern: import module + mocks, create `const context = {}`,
130-
instantiate singletons with `Module(context).getInstance()`, inject mocks via `setConfig()`,
131-
call `initialize()` in `beforeEach`, and call `reset()` in `afterEach`. Tests use nested
132-
`describe` blocks (one per method) and `it('Should ...', function () { ... })` blocks.
133-
134-
- **Mocks:** Hand-written in `test/unit/mocks/`, each mirrors the real class API
135-
- **Helpers:** `test/unit/helpers/``ObjectsHelper`, `VOHelper`, `SpecHelper` create dummy objects
136-
- **Assertions:** Chai `expect` style preferred; `assert` also used
137-
- **Spying/stubbing:** Sinon (`sinon.spy()`, `sinon.stub()`)
138-
- **Context:** Each test suite creates `const context = {}` and instantiates singletons against it
139-
- **Cleanup:** Always call `reset()` on instances, settings, and eventBus in `afterEach`
140-
- **Test data:** Fixtures in `test/unit/data/` (XML manifests, subtitle files, etc.)
141-
142-
## Project Structure
143-
144-
```
145-
src/
146-
├── core/ # EventBus, FactoryMaker, Settings, Debug, Utils, errors
147-
├── dash/ # DASH-specific: parser, adapter, manifest model, segment handling
148-
├── mss/ # Microsoft Smooth Streaming support
149-
├── offline/ # Offline playback / download support
150-
└── streaming/ # Core player: controllers, models, rules, protection (DRM), text, net
151-
test/
152-
├── unit/ # Unit tests (Karma + Mocha + Chai)
153-
│ ├── config/ # karma.unit.conf.cjs
154-
│ ├── data/ # Test fixtures (MPDs, subtitles)
155-
│ ├── helpers/ # ObjectsHelper, VOHelper, etc.
156-
│ ├── mocks/ # Hand-written mock classes
157-
│ └── test/ # Test files (mirrors src/ structure)
158-
└── functional/ # Functional/integration tests (real playback)
159-
build/webpack/ # Webpack configs (modern/legacy, dev/prod, UMD/ESM)
160-
```
161-
162-
## CI and Contributing
163-
164-
- PRs target the `development` branch (not `main`/`master`)
165-
- CI runs `npm run build` which executes: clean -> typecheck -> unit tests -> lint -> webpack
166-
- A pre-commit git hook runs `npm run lint` automatically
167-
- Functional tests run on LambdaTest/BrowserStack in CI for cross-browser validation
168-
- Always run `npm run build` before committing to catch test failures and lint errors
169-
- Include BSD-3-Clause header in new files; add/update unit tests for changes
3+
dash.js — DASH Industry Forum reference client. Pure JS (ES2020), ESM, Node >= 20.
4+
5+
## Gotchas
6+
7+
### Build & Test
8+
- **`npm run build` skips tests/lint.** Use `npm run build-modern` for the full pipeline (clean + tsc + test + lint + webpack).
9+
- **No per-file test runner.** All unit tests are bundled by Karma/webpack. Filter with `--grep`:
10+
```bash
11+
npx karma start test/unit/config/karma.unit.conf.cjs --grep="EventBus"
12+
```
13+
- **Functional tests load from `dist/`**, not source. Build first.
14+
- **Two entry points:** `index.js` (full) and `index_mediaplayerOnly.js` (lightweight). Public API changes may need both updated.
15+
- **Dev builds fewer webpack bundles than prod.** See `build/webpack/common/webpack.common.base.cjs`.
16+
17+
### Architecture
18+
- **Context = DI container.** Each `MediaPlayer` creates its own `context` object. All singletons are scoped to it: `EventBus(context).getInstance()`. This enables multiple independent players on one page.
19+
- **Errors are events, never thrown.** Use `DashJSError` + `EventBus` (`Events.ERROR`). Codes in `src/core/errors/Errors.js`.
20+
- **Protection/DRM is opt-in.** Call `player.setProtectionData()` explicitly.
21+
- **`player.extend()` must be called BEFORE `initialize()`.**
22+
23+
### Code changes
24+
- **PRs target `development`**, not `main`/`master`.
25+
- **BSD-3-Clause header required** in every new source file.
26+
- **v5 API — don't use deprecated v4 methods:**
27+
- `getBitrateInfoListFor()``getRepresentationsByType(type)`
28+
- `setQualityFor()``setRepresentationForTypeByIndex(type, index, forceReplace)`
29+
- `getQualityFor()``getCurrentRepresentationForType(type)`
30+
- **New settings** need both `Settings.js` (value + JSDoc) and `index.d.ts`.
31+
- **New samples** must update `samples/samples.json`.
32+
33+
## Where to look
34+
35+
| What | Where |
36+
|---|---|
37+
| Build scripts | `package.json``scripts` |
38+
| Lint rules | `eslint.config.mjs` + `.editorconfig` |
39+
| Architecture pattern | Any `src/` file — look for `FactoryMaker` |
40+
| Test patterns | Any file in `test/unit/test/` |
41+
| Test naming | `test/unit/test/` mirrors `src/` with dot-separated paths: `core.EventBus.js``src/core/EventBus.js` |
42+
| Mocks | `test/unit/mocks/` |
43+
| Test fixtures | `test/unit/data/` |
44+
| API surface | `src/streaming/MediaPlayer.js` |
45+
| Public exports | `index.js` + `index_mediaplayerOnly.js` |
46+
| TypeScript defs | `index.d.ts` |
47+
| Webpack entries | `build/webpack/common/webpack.common.base.cjs` |
48+
| Sample registry | `samples/samples.json` |
49+
| CI pipelines | `.github/workflows/` |

0 commit comments

Comments
 (0)