# Interview Brief: SDK Size Reduction

**Feature Name:** sdk-size-reduction
**Date:** 2026-03-16

## Problem & Goals

### Problem
The avo-inspector npm package ships 129 files / 522 KB unpacked / 72 kB tarball. About half is unnecessary: a duplicate `dist-native/` directory (for React Native, not this SDK), test/mock files leaking through `.npmignore` gaps, and dev config files. Additionally, encryption and event spec validation code only runs in dev/staging but is always loaded at startup.

### Success Criteria
- Remove obvious waste from the npm package (dist-native, test files, config files)
- Implement dynamic imports for dev/staging-only modules
- Production bundle target: 25-30 kB
- Full prepublishOnly verification must pass

### Consumers
1. Standard npm/bundler users (webpack, rollup, etc.)
2. Monorepo ReScript project (uses `avo-inspector` as `bs-dependency` - needs `bsconfig.json` + `rescript/` in package)
3. CDN/script-tag users (dist/browser.js distributed separately, NOT in npm package)

## Scope

### In Scope
1. **Package cleanup**: Switch from `.npmignore` to `"files"` whitelist in package.json
2. **Build fix**: Make builds reproducible from clean state (current build uses `tsc --emitDeclarationOnly` + webpack, but dist/ has stale JS files from prior full tsc compile)
3. **Dynamic imports**: Lazy-load dev/staging-only modules (AvoEncryption + @noble/curves, eventSpec/* + safe-regex2)
4. **Verification**: Full prepublishOnly flow (build + test:browser + example project tests)

### Out of Scope
- ESM dual build (deferred to future)
- Moving dependencies to peerDependencies
- CDN bundle optimization (browser.js is distributed separately)

## Changes Already Made (In Progress)

The following files have already been modified but need verification:

### package.json
- Added `"sideEffects": false`
- Added `"files"` whitelist: `dist/**/*.js`, `dist/**/*.d.ts`, exclusions for tests/mocks/browser.js, plus `bin/`, `bsconfig.json`, `rescript/`
- Changed build script to `"rm -rf dist && tsc"`
- Kept `build-for-script-tag` for CDN bundle

### tsconfig.json
- Changed `target` from `"ES5"` to `"ES2020"` (NOTE: user unsure if all consumers support ES2020 - needs verification. Package requires Node 18+ per engines field)
- Removed `emitDeclarationOnly` (was causing broken builds from clean state)
- Added `"src/__tests__"` and `"src/__mocks__"` to exclude

### src/AvoSchemaParser.ts
- Removed static `import { encryptValue } from "./AvoEncryption"`
- Added module-level cache: `let _encryptValueFn`
- Changed `getEncryptedPropertyValueIfEnabled` to use `await import("./AvoEncryption")` with caching

### src/AvoInspector.ts
- Removed static imports of `EventSpecCache`, `AvoEventSpecFetcher`, `validateEvent`
- Kept type-only imports (erased at compile time)
- Added `_validateEvent`, `_eventSpecReady` instance fields
- Added `initEventSpecModules()` async method that dynamically imports all three eventSpec modules
- Added `ensureEventSpecReady()` helper that awaits initialization and returns null if not ready
- Updated `fetchEventSpecIfNeeded()` and `fetchAndValidateEvent()` to use `ensureEventSpecReady()`
- Constructor fires `initEventSpecModules()` for non-prod environments with streamId

### src/index.ts
- Added `AvoStreamId` export (was exported in stale dist/index.js but not in source)

## Remaining Work
1. Delete `.npmignore` (superseded by `"files"` field)
2. Build from clean state: `rm -rf dist && tsc`
3. Run full test suite: `yarn test` and `yarn test:browser`
4. Verify package contents: `npm pack --dry-run`
5. Run full prepublishOnly flow if possible
6. Verify tarball size meets target

## Affected Areas

| Area | Files/Modules | Impact |
|------|--------------|--------|
| Package config | package.json, .npmignore, tsconfig.json | Distribution contents, build system |
| Schema parsing | src/AvoSchemaParser.ts | Dynamic import for encryption |
| Inspector core | src/AvoInspector.ts | Dynamic imports for eventSpec modules |
| Exports | src/index.ts | Added AvoStreamId export |
| Event spec | src/eventSpec/* | Now lazy-loaded, not imported at startup |
| Encryption | src/AvoEncryption.ts | Now lazy-loaded, not imported at startup |

## Edge Cases
- ReScript consumers need `bsconfig.json` + `rescript/` in the package
- CDN bundle (browser.js) distributed separately, excluded from npm package
- `InstanceType<typeof EventSpecCache>` used for type-safe lazy-loaded instances
- `_eventSpecReady` promise pattern: if modules haven't loaded yet when a validation call comes in, gracefully returns null
- ES2020 target compatibility with consumer bundlers (user unsure - needs checking)

## Acceptance Criteria
- [ ] `rm -rf dist && yarn build` produces correct output (JS + .d.ts files, no test files)
- [ ] `npm pack --dry-run` shows only dist JS/TS declarations, bin/, bsconfig.json, rescript/
- [ ] No dist-native/, dist-browser/, .claude/, config files in package
- [ ] All tests pass: `yarn test` and `yarn test:browser`
- [ ] Package tarball <= 30 kB
- [ ] Production users (env=prod) never load AvoEncryption or eventSpec modules
- [ ] Dev/staging users with streamId still get event spec validation working
- [ ] ReScript integration works (bsconfig.json and rescript/ present in package)
- [ ] `.npmignore` file is deleted

## Open Questions
- Is ES2020 target safe for all consumers? Package requires Node 18+ but some browser consumers might need lower target. However, browser consumers use the CDN bundle (separate distribution), so ES2020 for the npm CJS output should be fine.
- Should we keep the `bin/avo-inspector.js` in the package? It's included in the files whitelist.
