|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +## Project map (read this first) |
| 4 | +- This project implements the FHIRPath language in JavaScript and supports DSTU2, STU3, R4, and R5 model contexts. |
| 5 | +- Entry point is `src/fhirpath.js`: public API is `parse`, `compile`, `evaluate`, `resolveInternalTypes`, `types`. |
| 6 | +- `src/fhirpath.js` also exports `version`, `FP_Decimal`, `ucumUtils`, and `util` (used by external callers and custom function implementations). |
| 7 | +- Evaluation flow is `parse()` -> AST -> `_compile()` -> `applyParsedPath()` -> `engine.doEval()`; see `src/fhirpath.js` and `src/parser/index.js`. |
| 8 | +- Core behavior is table-driven: `engine.invocationTable` in `src/fhirpath.js` maps function/operator names to handlers and arity checks. |
| 9 | +- Most function families live in separate modules (e.g. `src/aggregate.js`, `src/filtering.js`, `src/math.js`) and export an `engine` object. |
| 10 | +- FHIR version-specific typing/model metadata is in `fhir-context/{dstu2,stu3,r4,r5}` and is required for choice-type/type resolution. |
| 11 | +- CLI entry is `bin/fhirpath`; behavior is covered by `test/bin_fhirpath.test.js`. |
| 12 | + |
| 13 | +## Architecture patterns that matter |
| 14 | +- Internal values are wrapped as `ResourceNode` / `FP_Type`; final conversion happens in `prepareEvalResult()` (`src/fhirpath.js`). |
| 15 | +- `evaluate()` mutates input resources by attaching hidden `__path__` metadata (documented in `README.md`); do not assume input objects stay pristine. |
| 16 | +- Base-path evaluation for partial resources uses `{base, expression}` and model normalization via `model.pathsDefinedElsewhere`/`model.path2Type` in `_compile()`. |
| 17 | +- Async operations (`resolve`, `memberOf`, `%terminologies.*`) require `options.async`; guards are enforced via `util.checkAllowAsync` (see `src/additional.js`, `src/terminologies.js`). |
| 18 | +- `%factory.*` is implemented as a class with its own invocation table in `src/factory.js` and injected as `%factory` in eval context. |
| 19 | + |
| 20 | +## Testing workflow (project-specific) |
| 21 | +- Spec-style unit tests are YAML-driven: `test/fhirpath.test.js` loads `test/cases/*.yaml` and generates Jest tests dynamically. |
| 22 | +- Additional Jest suites in `test/*.test.js` cover APIs and behaviors outside YAML cases (e.g. `test/async-functions.test.js`, `test/user-invocation-table.test.js`, `test/bin_fhirpath.test.js`). |
| 23 | +- Many tests run in both math modes automatically (`preciseMath` true/false) unless a case sets `preciseMath` explicitly. |
| 24 | +- `npm run test:unit` runs Jest three times across time zones (`default`, `America/New_York`, `Europe/Paris`) to catch datetime regressions. |
| 25 | +- Test helpers in `test/test_utils.js` auto-load models (`r5`, `r4`, `stu3`, `dstu2`) and deep-clone input resources to avoid cross-test pollution. |
| 26 | +- Add new spec-style cases in `test/cases/*.yaml`; use keys like `model`, `inputfile`, `variables`, `context`, `error`, `result`. |
| 27 | +- Type declaration checks use `npm run test:tsd` with tests in `test/typescript/fhirpath.test-d.ts`. |
| 28 | +- End-to-end browser checks run via Cypress under `test/cypress/` (script: `npm run test:e2e`, which builds the demo first). |
| 29 | + |
| 30 | +## Build/dev commands you will actually use |
| 31 | +- Install: `npm install` (if `node` is missing in this environment, run `source bashrc.fhirpath` and retry). |
| 32 | +- Lint: `npm run lint` (targets `src/parser/index.js`, `src/*.js`, `converter/`). |
| 33 | +- Unit tests: `npm run test:unit`; debugger mode: `npm run test:unit:debug`. |
| 34 | +- Type tests: `npm run test:tsd`. |
| 35 | +- E2E tests: `npm run test:e2e` (builds demo + runs Cypress). |
| 36 | +- Full CI-like local run: `npm test` (lint + tsd + unit + e2e). |
| 37 | +- Parser regeneration: `npm run generateParser` (uses `src/parser/FHIRPath.g4`, `antlr-4.9.3-complete.jar`, then `scripts/fix-parser-imports.js`). |
| 38 | +- Browser artifacts: `npm run build` (webpack outputs in `browser-build/`, plus zipped distributable). |
| 39 | +- Performance comparison: `npm run compare-performance` (`test/benchmark.js`). |
| 40 | + |
| 41 | +## Sandbox and escalation |
| 42 | +- If a command that is important to the task fails due to sandbox restrictions (for example EPERM/spawn permission errors), rerun it with escalated permissions and include a brief justification request. |
| 43 | + |
| 44 | +## Conventions to preserve when editing |
| 45 | +- Use CommonJS (`require`/`module.exports`) and 2-space indentation (see `eslint.config.js`). |
| 46 | +- Use modern JavaScript syntax (`const`/`let`, arrow functions, destructuring) where it matches existing files. |
| 47 | +- In AI chat responses, prefer project-relative file references in `path:line` format (e.g. `src/fhirpath.js:19`). |
| 48 | +- Keep two blank lines between declarations and above JSDoc blocks. |
| 49 | +- Treat JSDoc as part of a declaration: keep two blank lines above the JSDoc block, and no blank line between JSDoc and the declaration. |
| 50 | +- Keep project layout conventions: core logic in `src/`, FHIR-version-specific metadata in `fhir-context/`, tests in `test/`, and docs in `docs/` or `README.md`. |
| 51 | +- New FHIRPath functions are typically added as module functions plus registration in `engine.invocationTable` (`src/fhirpath.js`). |
| 52 | +- For feature work, update tests together with implementation (`test/cases/*.yaml` for spec-style behavior, plus `test/*.test.js` when behavior is API-specific). |
| 53 | +- For custom function hooks, follow `userInvocationTable` conventions in `_compile()`; use `internalStructures: true` only if handler needs raw `ResourceNode` access. |
| 54 | +- For async server calls, thread options via `terminologyUrl`, `fhirServerUrl`, `httpHeaders`, and optional `signal` (see `docs/auth.md`, `docs/abort.md`). |
| 55 | +- If public API signatures or exports change, update `src/fhirpath.d.ts` and validate with `npm run test:tsd` (`test/typescript/fhirpath.test-d.ts`). |
| 56 | +- Keep behavior standards-compliant with FHIRPath and aligned with the selected FHIR model version when model-aware behavior is involved. |
0 commit comments