react-native-avo-inspector
Version:
[](https://badge.fury.io/js/react-native-avo-inspector)
298 lines (297 loc) • 17.5 kB
JSON
{
"featureName": "lite-entry-point",
"branchName": "feat/lite-entry-point",
"baseBranch": "main",
"createdAt": "2026-03-18",
"status": "Draft — Rev 2 (Thing Rev 1 fixes)",
"maxIterations": 14,
"stories": [
{
"id": "story-1",
"title": "Lite source files: AvoSchemaParserLite + AvoNetworkCallsHandlerLite",
"approach": "general-purpose",
"dependencies": [],
"files": {
"create": [
"src/lite/AvoSchemaParserLite.ts",
"src/lite/AvoNetworkCallsHandlerLite.ts"
],
"modify": []
},
"implementationNotes": [
"Create src/lite/ directory first: mkdir -p src/lite (directory does not exist in the repo)",
"AvoSchemaParserLite: remove encryptValue import; change types import to from './AvoNetworkCallsHandlerLite'; delete canSendEncryptedValues, getEncryptedPropertyValueIfEnabled methods; in extractSchema remove canSendEncryptedValues variable and encryptedValue block; keep method signature accepting publicEncryptionKey and env params (accepted but unused)",
"AvoNetworkCallsHandlerLite: change AvoInspector import to AvoInspectorLite as AvoInspector; change AvoGuid import to '../AvoGuid'; change AvoStreamId import to AvoStreamIdLite as AvoStreamId from './AvoStreamIdLite'; change EventSpecMetadata import to '../eventSpec/AvoEventSpecFetchTypes'",
"Both files: add LITE COPY header comment: '// LITE COPY of src/<OriginalFile>.ts\\n// Sync obligation: any change to src/<OriginalFile>.ts must be reviewed for applicability here.\\n// Diff against original: git diff HEAD src/<OriginalFile>.ts src/lite/<LiteCopyFile>.ts'",
"Build will not pass until Story 3 completes (AvoInspectorLite not yet created); ts-jest will fail to compile AvoNetworkCallsHandlerLite.ts due to forward import of AvoInspectorLite — tests and browser tests are non-required for this reason"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": false,
"note": "Expected to fail until Story 3 — AvoInspectorLite not yet created"
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": false,
"note": "Non-required — ts-jest will fail to compile AvoNetworkCallsHandlerLite.ts due to forward import of AvoInspectorLite which does not exist until Story 3"
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": false,
"note": "Non-required — same ts-jest forward-import constraint applies"
}
}
},
{
"id": "story-2",
"title": "Lite source files: AvoStreamIdLite + AvoDeduplicatorLite + AvoBatcherLite",
"approach": "general-purpose",
"dependencies": ["story-1"],
"files": {
"create": [
"src/lite/AvoStreamIdLite.ts",
"src/lite/AvoDeduplicatorLite.ts",
"src/lite/AvoBatcherLite.ts"
],
"modify": []
},
"implementationNotes": [
"AvoStreamIdLite: change AvoInspector import to AvoInspectorLite as AvoInspector from './AvoInspectorLite'; change AvoGuid import to '../AvoGuid'; alias as AvoInspector means zero body changes",
"AvoDeduplicatorLite: change AvoSchemaParser import to AvoSchemaParserLite as AvoSchemaParser from './AvoSchemaParserLite'; change deepEquals import to '../utils'; alias as AvoSchemaParser means zero body changes",
"AvoBatcherLite: change AvoInspector import to AvoInspectorLite as AvoInspector from './AvoInspectorLite'; change AvoNetworkCallsHandler import to from './AvoNetworkCallsHandlerLite'; change EventSpecMetadata import to '../eventSpec/AvoEventSpecFetchTypes'; keep eventSpecMetadata? in AvoBatcherType interface",
"All three files: add LITE COPY header comment",
"Build still not expected to pass cleanly until Story 3"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": false,
"note": "Expected to fail until Story 3 — AvoInspectorLite not yet created"
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": false,
"note": "Non-required — ts-jest will fail to compile lite files that forward-import AvoInspectorLite, which does not exist until Story 3"
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": false,
"note": "Non-required — same ts-jest forward-import constraint applies"
}
}
},
{
"id": "story-3",
"title": "AvoInspectorLite + index + tsconfig.lite.json + package.json",
"approach": "general-purpose",
"dependencies": ["story-1", "story-2"],
"files": {
"create": [
"src/lite/AvoInspectorLite.ts",
"src/lite/index.ts",
"tsconfig.lite.json"
],
"modify": [
"package.json"
]
},
"implementationNotes": [
"AvoInspectorLite imports: AvoInspectorEnv from '../AvoInspectorEnv'; AvoSchemaParserLite from './AvoSchemaParserLite'; AvoBatcherLite as AvoBatcher from './AvoBatcherLite'; AvoNetworkCallsHandlerLite as AvoNetworkCallsHandler + EventProperty type from './AvoNetworkCallsHandlerLite'; AvoStorage from '../AvoStorage'; AvoDeduplicatorLite as AvoDeduplicator from './AvoDeduplicatorLite'; AvoStreamIdLite as AvoStreamId from './AvoStreamIdLite'; isValueEmpty from '../utils'; libVersion = require('../../package.json').version",
"Constructor options: { apiKey, env, version, appName?, suffix? } — no publicEncryptionKey",
"Constructor body: no this.publicEncryptionKey assignment; no this.streamId field or assignment; no if(this.streamId) eventSpec init block; pass undefined as 6th arg to new AvoNetworkCallsHandlerLite(..., undefined)",
"Static fields: avoStorage, _batchSize (get+set), _batchFlushSeconds (get only — no static setter), _shouldLog (get+set), _networkTimeout (get+set) — exactly mirroring the full class",
"trackSchemaFromEvent: no fetchAndValidateEvent, no validationResult branch; always calls trackSchemaInternal directly",
"_avoFunctionTrackSchemaFromEvent: mirrors trackSchemaFromEvent but shouldRegisterEvent(name, params, true) and forwards eventId/eventHash",
"trackSchema: identical to full but without await this.fetchEventSpecIfNeeded(eventName)",
"extractSchema: calls AvoSchemaParserLite.extractSchema(eventProperties) — no key, no env",
"src/lite/index.ts: export { AvoInspectorLite as AvoInspector } from './AvoInspectorLite'; export { AvoInspectorEnv, type AvoInspectorEnvType, type AvoInspectorEnvValueType } from '../AvoInspectorEnv'",
"tsconfig.lite.json: extends tsconfig.json; outDir ./dist; include: src/lite/**/* + src/AvoInspectorEnv.ts + src/AvoStorage.ts + src/AvoGuid.ts + src/utils.ts + src/eventSpec/AvoEventSpecFetchTypes.ts",
"package.json: add files:[dist,bin]; add exports map with . and ./lite each having types and default conditions; update build script to add && tsc --project tsconfig.lite.json --noEmit before webpack; add check:lite-size and verify:lite-sync scripts; update prepublishOnly to append && yarn check:lite-size && yarn verify:lite-sync so the size gate and drift check are publish-blocking",
"Post-story verification: grep -r 'AvoEncryption' dist/lite/ must return no matches; same for AvoEventSpecFetcher, noble, EventSpecCache"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": true
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": true
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": true
}
}
},
{
"id": "story-4",
"title": "Tests for lite build",
"approach": "general-purpose",
"dependencies": ["story-3"],
"files": {
"create": [
"src/__tests__/AvoInspectorLite_test.ts",
"src/__tests__/AvoSchemaParserLite_test.ts"
],
"modify": []
},
"implementationNotes": [
"AvoInspectorLite_test.ts test cases: (1) constructor accepts apiKey/env/version/appName/suffix; (2) publicEncryptionKey causes TS error via @ts-expect-error; (3) trackSchemaFromEvent returns schema with no encryptedPropertyValue; (4) trackSchemaFromEvent returns [] for deduplicated events; (5) trackSchema completes without throwing; (6) extractSchema returns correct schema; (7) static getters batchSize/batchFlushSeconds/shouldLog/networkTimeout readable; (8) setters for batchSize/shouldLog/networkTimeout work; batchFlushSeconds set only via setBatchFlushSeconds(n); (9) import from src/lite/index.ts exports AvoInspector and AvoInspectorEnv; (10) static isolation: AvoInspector.batchSize = 99 does NOT change AvoInspectorLite.batchSize",
"AvoSchemaParserLite_test.ts: (1) correct property types; (2) never sets encryptedPropertyValue even if publicEncryptionKey passed; (3) nested objects extracted; (4) arrays/lists extracted",
"Mock XMLHttpRequest following pattern in AvoInspectorEventSpec_test.ts",
"Use defaultOptions from src/__tests__/constants.ts as base",
"Static isolation test pattern: AvoInspector.batchSize = 99; expect(AvoInspectorLite.batchSize).not.toBe(99); AvoInspector.batchSize = 30"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": true
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": true
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": true
}
}
},
{
"id": "story-5",
"title": "Drift detection and size verification scripts",
"approach": "general-purpose",
"dependencies": ["story-3"],
"files": {
"create": [
"scripts/verify-lite-sync.sh",
"scripts/check-lite-size.js",
"scripts/webpack.lite-size.config.js"
],
"modify": []
},
"implementationNotes": [
"Create scripts/ directory with mkdir -p scripts before writing files",
"verify-lite-sync.sh: PAIRS array with 4 pairs (AvoNetworkCallsHandler/Lite, AvoBatcher/Lite, AvoStreamId/Lite, AvoDeduplicator/Lite); add comment above PAIRS: '# AvoSchemaParser is excluded: AvoSchemaParserLite removes entire methods (encryption), not just one import line. Drift there requires manual review.'; fail if any pair has >10 changed lines; make script executable",
"check-lite-size.js: before running webpack call fs.mkdirSync(path.resolve(__dirname, '../test-bundle-size/output'), { recursive: true }) to guard against missing output directory on fresh clones (mirrors defensive mkdir -p in existing analyze.sh); then execSync webpack with scripts/webpack.lite-size.config.js; then run terser on test-bundle-size/output/bundle-lite.js writing to bundle-lite-terser.js; gzip and fail if > 7168 bytes (7 KB)",
"webpack.lite-size.config.js: entry ./dist/lite/index.js; output bundle-lite.js in test-bundle-size/output/; mode production; no ts-loader (pre-compiled JS); libraryTarget umd; splitChunks false",
"verify-lite-sync.sh must have shebang #!/usr/bin/env bash and be chmod +x",
"package.json scripts were already added in Story 3 (check:lite-size and verify:lite-sync); confirm they point to the correct paths"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": true
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": true
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": true
},
"additionalChecks": [
"yarn verify:lite-sync — must pass with no drift",
"yarn check:lite-size — must pass under 7168 bytes gzipped"
]
}
},
{
"id": "story-6",
"title": "Example apps: examples/lite-size-demos/",
"approach": "general-purpose",
"dependencies": ["story-3"],
"files": {
"create": [
"examples/lite-size-demos/terser-only/entry.js",
"examples/lite-size-demos/terser-only/build.sh",
"examples/lite-size-demos/terser-only/README.md",
"examples/lite-size-demos/webpack/entry.js",
"examples/lite-size-demos/webpack/webpack.config.js",
"examples/lite-size-demos/webpack/package.json",
"examples/lite-size-demos/webpack/README.md",
"examples/lite-size-demos/rollup/entry.js",
"examples/lite-size-demos/rollup/rollup.config.js",
"examples/lite-size-demos/rollup/package.json",
"examples/lite-size-demos/rollup/README.md"
],
"modify": [
"package.json"
]
},
"implementationNotes": [
"terser-only/entry.js: const { AvoInspector, AvoInspectorEnv } = require('avo-inspector/lite'); construct and call trackSchemaFromEvent",
"terser-only/build.sh: esbuild entry.js --bundle --platform=browser --target=es5 --outfile=build/bundle.js && npx terser build/bundle.js --compress passes=2,unsafe=true,unsafe_comps=true --mangle --output build/bundle.min.js",
"webpack/entry.js: import { AvoInspector, AvoInspectorEnv } from 'avo-inspector/lite'; construct and call trackSchemaFromEvent",
"webpack/webpack.config.js: production mode; resolve avo-inspector to the parent package; UMD output",
"rollup/entry.js: import { AvoInspector, AvoInspectorEnv } from 'avo-inspector/lite'; construct and call trackSchemaFromEvent",
"rollup/rollup.config.js: uses @rollup/plugin-node-resolve and @rollup/plugin-commonjs",
"rollup/package.json: declare rollup, @rollup/plugin-node-resolve, and @rollup/plugin-commonjs in devDependencies so the example is self-contained; user must run npm install inside the directory",
"webpack/package.json: declare webpack and webpack-cli in devDependencies so the example is self-contained; user must run npm install inside the directory",
"Each README.md: exact import, exact build command, expected sizes (~X KB placeholder until built), grep command showing no encryption code",
"Add 'examples/lite-size-demos/' to package.json files array (alongside dist and bin)",
"MERGE-CONFLICT WARNING: Story 6 and Story 3 both modify package.json. Although Story 6 depends on Story 3 (logically sequenced), if worked in parallel by different agents they will produce a merge conflict. Story 6's package.json edit must be applied only after Story 3's changes are fully committed."
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": true
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": true
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": true
}
}
},
{
"id": "story-7",
"title": "Final verification pass",
"approach": "general-purpose",
"dependencies": ["story-1", "story-2", "story-3", "story-4", "story-5", "story-6"],
"files": {
"create": [],
"modify": []
},
"implementationNotes": [
"Run all 24 spec acceptance criteria checks end-to-end",
"yarn build — must succeed, produce dist/index.js and dist/lite/index.js",
"grep -r 'AvoEncryption' dist/lite/ — no matches",
"grep -r 'AvoEventSpecFetcher' dist/lite/ — no matches",
"grep -r 'EventSpecCache' dist/lite/ — no matches",
"grep -r 'noble' dist/lite/ — no matches",
"grep -r 'safe-regex' dist/lite/ — no matches",
"yarn test --roots='<rootDir>/src' — all tests pass",
"BROWSER=1 yarn test --roots='<rootDir>/src' — all tests pass",
"npm pack --dry-run | grep 'dist/lite' — includes dist/lite/index.js and dist/lite/index.d.ts",
"yarn verify:lite-sync — no drift detected",
"yarn check:lite-size — under 7168 bytes gzipped",
"Verify static isolation test passes (batchSize isolation between full and lite)",
"AC 21 — cd examples/lite-size-demos/terser-only && bash build.sh; verify build/bundle.min.js gzipped is under 7 KB",
"AC 22 — cd examples/lite-size-demos/webpack && npm install && npx webpack; verify output gzipped is under 7 KB",
"AC 23 — cd examples/lite-size-demos/rollup && npm install && npx rollup -c; verify output gzipped is under 7 KB",
"Fix any issues found — no new files should be needed; corrections go in existing files from earlier stories"
],
"qualityChecks": {
"build": {
"command": "yarn build",
"required": true
},
"tests": {
"command": "yarn test --roots='<rootDir>/src'",
"required": true
},
"browserTests": {
"command": "BROWSER=1 yarn test --roots='<rootDir>/src'",
"required": true
}
}
}
]
}