Skip to content

Commit fcecf32

Browse files
authored
chore: migrate toolchain to TypeScript 5.5, Vite, Vitest, and ESLint v9 (#84)
1 parent c880d33 commit fcecf32

23 files changed

+11291
-15260
lines changed

.claude/skills/verify/skill.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ Run lint, build, and tests to verify the current state of the codebase.
1616
npm run lint
1717
```
1818

19-
**Build + Tests:**
19+
**Build:**
20+
```bash
21+
npm run build
22+
```
23+
24+
**Tests:**
2025
```bash
2126
npm run test
2227
```
2328

24-
> `npm run test` runs `npm run build && npm run build:test && karma start test/karma.config.js` — it builds the source, builds the test bundle, and runs Karma with Mocha/Chai in Chrome and Firefox.
29+
> `npm run test` runs Vitest in headless jsdom mode.
30+
> `npm run build` runs Vite and produces IIFE and CommonJS bundles + TypeScript type declarations.
2531
2632
2. Report results in this format:
2733

@@ -35,7 +41,8 @@ npm run test
3541

3642
## Notes
3743

38-
- This is a plain JavaScript project — kit source is ES5-style; tests/tooling may use ES6. There is no TypeScript compilation step.
39-
- Build uses Rollup and produces IIFE and CommonJS bundles.
40-
- Tests run in real browsers (Chrome, Firefox) via Karma, not in Node/jsdom.
41-
- `npm run test:debug` launches Chrome in non-headless mode for interactive debugging.
44+
- TypeScript project — source is `src/Rokt-Kit.ts`, tests are `test/src/tests.spec.ts`
45+
- Build uses Vite and produces `dist/Rokt-Kit.iife.js`, `dist/Rokt-Kit.common.js`, and `dist/Rokt-Kit.d.ts`
46+
- Tests run in jsdom via Vitest (no browser required)
47+
- `npm run test:watch` runs Vitest in watch mode for development
48+
- `npm run test:coverage` generates a V8 coverage report

.eslintrc

Lines changed: 0 additions & 30 deletions
This file was deleted.

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v20.13.1
1+
24

.prettierrc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"singleQuote": true,
3-
"trailingComma": "es5",
4-
"tabWidth": 4
5-
}
2+
"printWidth": 120,
3+
"singleQuote": true,
4+
"trailingComma": "all"
5+
}

AGENTS.md

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,46 @@ The Rokt web kit (`@mparticle/web-rokt-kit`) is an mParticle integration kit (fo
1010

1111
## Tech Stack
1212

13-
- **Language**: Plain JavaScript project — kit source is ES5-style; tests/tooling may use ES6. There is no TypeScript compilation step.
14-
- **Build Tool**: Rollup (IIFE and CommonJS output)
15-
- **Testing**: Karma + Mocha/Chai (real browser tests in Chrome and Firefox)
13+
- **Language**: TypeScript 5.5 with `strict: true`
14+
- **Build Tool**: Vite (library mode, IIFE + CJS output)
15+
- **Testing**: Vitest with `jsdom` environment
1616
- **Package Manager**: npm
17-
- **Code Quality**: ESLint
17+
- **Code Quality**: ESLint v9 flat config + `@typescript-eslint/recommended`
18+
- **Formatting**: Prettier (120 chars, single quotes, trailing commas)
1819

1920
## Project Structure
2021

2122
```
2223
/
2324
src/
24-
Rokt-Kit.js # Single monolithic source file (~900 lines)
25+
Rokt-Kit.ts # Single monolithic source file
2526
dist/
2627
Rokt-Kit.iife.js # Browser bundle (IIFE)
2728
Rokt-Kit.common.js # npm bundle (CommonJS)
29+
Rokt-Kit.d.ts # Type definitions
2830
test/
2931
src/
30-
tests.js # Mocha/Chai test suite
31-
config.js # Test mParticle configuration
32-
karma.config.js # Karma test runner config
32+
tests.spec.ts # Vitest test suite
33+
vitest.setup.ts # Global test setup / mParticle mock
3334
lib/ # Test utilities
3435
end-to-end-testapp/ # E2E test app
35-
rollup.config.js # Build configuration
36+
vite.config.ts # Build + test configuration
37+
tsconfig.json # TypeScript config (src only)
38+
tsconfig.test.json # TypeScript config (src + test)
39+
eslint.config.mjs # ESLint v9 flat config
3640
package.json
3741
```
3842

3943
## Key Commands
4044

4145
```bash
42-
npm run build # Build IIFE and CommonJS bundles
43-
npm run build:test # Build test bundle
44-
npm run lint # ESLint check (src/ and test/src/)
46+
npm run build # Vite build (IIFE + CJS + type defs)
47+
npm run build:watch # Vite build in watch mode (rebuilds on change)
48+
npm run lint # ESLint check
4549
npm run lint:fix # ESLint autofix
46-
npm run test # Build + build tests + run Karma
47-
npm run test:debug # Non-headless Chrome for debugging
48-
npm run watch # Watch and rebuild on changes
50+
npm run test # Vitest run
51+
npm run test:watch # Vitest watch mode
52+
npm run test:coverage # Vitest with V8 coverage
4953
```
5054

5155
## Build Artifacts — Do Not Commit
@@ -54,10 +58,10 @@ The `dist/` folder, `CHANGELOG.md`, and version bumps in `package.json`/`package
5458

5559
## Code Conventions
5660

57-
- **Single source file**: All kit logic lives in `src/Rokt-Kit.js`
58-
- **Constructor function pattern**: `var constructor = function() { ... }` with `var self = this;`
59-
- **var declarations**: The codebase uses `var` throughout — match this style
60-
- **No TypeScript**: No type annotations, no interfaces, no generics
61+
- **Single source file**: All kit logic lives in `src/Rokt-Kit.ts`
62+
- **TypeScript class pattern**: `class RoktKit { ... }` with typed public/private members
63+
- **const/let**: Use `const` for values that don't change, `let` for reassignable variables
64+
- **Strict TypeScript**: `strict: true` — all values must be typed, no implicit `any`
6165
- **Module registration**: Kit self-registers via `window.mParticle.addForwarder()` at load time
6266

6367
## Architecture
@@ -69,19 +73,19 @@ The `dist/` folder, `CHANGELOG.md`, and version bumps in `package.json`/`package
6973

7074
## Testing Patterns
7175

72-
- Tests use Mocha `describe`/`it` blocks with Chai `expect` assertions
73-
- mParticle SDK is mocked in test config
74-
- Rokt launcher is mocked with spy functions
76+
- Tests use Vitest `describe`/`it` blocks with `expect()` assertions
77+
- `window.mParticle` is mocked in `test/vitest.setup.ts`
78+
- Rokt launcher is mocked with `vi.fn()` spy functions
7579
- `beforeEach` resets kit state between tests
76-
- Tests run in real browsers (Chrome, Firefox) via Karma
80+
- Tests run headlessly in jsdom via Vitest
7781

7882
## Common Gotchas
7983

80-
1. **Single file**: All changes go in `src/Rokt-Kit.js` — there are no imports/modules
84+
1. **Single file**: All changes go in `src/Rokt-Kit.ts` — there are no imports/modules
8185
2. **Browser-only**: Code runs in browser context, `window` is always available
8286
3. **Async launcher**: Rokt launcher loads asynchronously — events must be queued until ready
83-
4. **var scope**: Use `var` not `let`/`const` to match existing style
84-
5. **self reference**: Use `var self = this;` pattern for callback context
87+
4. **Window extensions**: `window.Rokt` and `window.mParticle.Rokt` are typed via `declare global`
88+
5. **Test isolation**: Each test resets `window.mParticle.forwarder` state in `beforeEach`
8589

8690
## Available Skills
8791

eslint.config.mjs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import js from '@eslint/js';
2+
import typescriptEslint from '@typescript-eslint/eslint-plugin';
3+
import tsParser from '@typescript-eslint/parser';
4+
import prettier from 'eslint-plugin-prettier';
5+
import prettierConfig from 'eslint-config-prettier';
6+
import globals from 'globals';
7+
8+
const vitestGlobals = {
9+
describe: 'readonly',
10+
it: 'readonly',
11+
test: 'readonly',
12+
expect: 'readonly',
13+
beforeEach: 'readonly',
14+
afterEach: 'readonly',
15+
beforeAll: 'readonly',
16+
afterAll: 'readonly',
17+
vi: 'readonly',
18+
vitest: 'readonly',
19+
};
20+
21+
const sharedRules = {
22+
...js.configs.recommended.rules,
23+
...typescriptEslint.configs.recommended.rules,
24+
...prettierConfig.rules,
25+
'prettier/prettier': 'error',
26+
'@typescript-eslint/no-explicit-any': 'warn',
27+
'@typescript-eslint/no-unused-vars': [
28+
'error',
29+
{
30+
argsIgnorePattern: '^_',
31+
varsIgnorePattern: '^_',
32+
caughtErrorsIgnorePattern: '^_',
33+
},
34+
],
35+
'no-prototype-builtins': 'off',
36+
};
37+
38+
export default [
39+
{ ignores: ['**/node_modules/**', '**/dist/**'] },
40+
// Source files
41+
{
42+
files: ['src/**/*.ts'],
43+
plugins: {
44+
'@typescript-eslint': typescriptEslint,
45+
prettier,
46+
},
47+
languageOptions: {
48+
parser: tsParser,
49+
globals: { ...globals.browser, process: 'readonly' },
50+
ecmaVersion: 'latest',
51+
sourceType: 'module',
52+
},
53+
rules: sharedRules,
54+
},
55+
// Test files
56+
{
57+
files: ['test/**/*.ts'],
58+
plugins: {
59+
'@typescript-eslint': typescriptEslint,
60+
prettier,
61+
},
62+
languageOptions: {
63+
parser: tsParser,
64+
globals: { ...globals.browser, ...vitestGlobals },
65+
ecmaVersion: 'latest',
66+
sourceType: 'module',
67+
},
68+
rules: {
69+
...sharedRules,
70+
'@typescript-eslint/no-this-alias': 'off',
71+
},
72+
},
73+
];

0 commit comments

Comments
 (0)