@sha1n/about-time 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/superpowers/plans/2026-04-02-about-time-modernization.md +174 -0
- package/docs/superpowers/specs/2026-04-02-about-time-modernization-design.md +33 -0
- package/eslint.config.mjs +85 -0
- package/lib/retry.ts +5 -1
- package/lib/timeout.ts +6 -3
- package/package.json +23 -23
- package/tsconfig.eslint.json +11 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# about-time Modernization Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Upgrade dependencies for `about-time` to latest versions, resolve 24 vulnerabilities, and modernize tooling.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Block-by-block migration strategy: Infrastructure -> Jest -> ESLint Flat Config.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** TypeScript 5, Jest 29, ESLint 10 (Flat Config), pnpm.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### Task 1: TypeScript & Infrastructure Upgrade
|
|
14
|
+
|
|
15
|
+
**Files:**
|
|
16
|
+
- Modify: `../about-time/package.json`
|
|
17
|
+
- Modify: `../about-time/tsconfig.json`
|
|
18
|
+
|
|
19
|
+
- [ ] **Step 1: Update package.json core dev deps**
|
|
20
|
+
|
|
21
|
+
Update `package.json` with latest versions for core tools.
|
|
22
|
+
```json
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/chance": "^1.1.6",
|
|
25
|
+
"@types/is-ci": "^3.0.4",
|
|
26
|
+
"@types/node": "^22.13.5",
|
|
27
|
+
"chance": "^1.1.12",
|
|
28
|
+
"is-ci": "^4.1.0",
|
|
29
|
+
"prettier": "^3.5.2",
|
|
30
|
+
"ts-node": "^10.9.2",
|
|
31
|
+
"typescript": "^5.7.3"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- [ ] **Step 2: Fix tsconfig.json deprecations**
|
|
36
|
+
|
|
37
|
+
Update `tsconfig.json` with `moduleResolution: "node10"` and `ignoreDeprecations: "5.0"`.
|
|
38
|
+
|
|
39
|
+
- [ ] **Step 3: Run pnpm install and build**
|
|
40
|
+
|
|
41
|
+
Run: `cd ../about-time && pnpm install && pnpm build`
|
|
42
|
+
Expected: SUCCESS
|
|
43
|
+
|
|
44
|
+
- [ ] **Step 4: Commit changes**
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git add package.json tsconfig.json pnpm-lock.yaml
|
|
48
|
+
git commit -m "chore: upgrade typescript and core infra"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### Task 2: Jest Modernization (v29)
|
|
54
|
+
|
|
55
|
+
**Files:**
|
|
56
|
+
- Modify: `../about-time/package.json`
|
|
57
|
+
- Modify: `../about-time/jest.config.ts`
|
|
58
|
+
|
|
59
|
+
- [ ] **Step 1: Update package.json with Jest 29 deps**
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/jest": "^29.5.14",
|
|
64
|
+
"jest": "^29.7.0",
|
|
65
|
+
"jest-environment-node": "^29.7.0",
|
|
66
|
+
"jest-extended": "^6.0.0",
|
|
67
|
+
"jest-html-reporters": "^3.1.7",
|
|
68
|
+
"jest-mock-extended": "^4.0.0",
|
|
69
|
+
"jest-summary-reporter": "^0.0.2",
|
|
70
|
+
"ts-jest": "^29.2.6"
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- [ ] **Step 2: Modernize jest.config.ts**
|
|
75
|
+
|
|
76
|
+
Update `jest.config.ts` using `dagraph` patterns.
|
|
77
|
+
```typescript
|
|
78
|
+
import isCI from 'is-ci';
|
|
79
|
+
|
|
80
|
+
const reporters = ['default', ['jest-summary-reporter', { failuresOnly: true }]];
|
|
81
|
+
|
|
82
|
+
if (!isCI) {
|
|
83
|
+
reporters.push(['jest-html-reporters', { failuresOnly: false }]);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default {
|
|
87
|
+
testMatch: ['**/test/**/*.spec.ts'],
|
|
88
|
+
coveragePathIgnorePatterns: ['test/*', 'dist/*'],
|
|
89
|
+
reporters,
|
|
90
|
+
verbose: true,
|
|
91
|
+
maxWorkers: isCI ? '2' : '100%',
|
|
92
|
+
transform: {
|
|
93
|
+
'^.+\\.(ts|tsx)$': ['ts-jest', { tsconfig: 'tsconfig.json' }]
|
|
94
|
+
},
|
|
95
|
+
testEnvironment: 'node',
|
|
96
|
+
preset: 'ts-jest',
|
|
97
|
+
slowTestThreshold: 1.5 * 1000,
|
|
98
|
+
testTimeout: 10 * 1000,
|
|
99
|
+
setupFilesAfterEnv: ['jest-extended/all']
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- [ ] **Step 3: Verify tests**
|
|
104
|
+
|
|
105
|
+
Run: `cd ../about-time && pnpm jest`
|
|
106
|
+
Expected: PASS
|
|
107
|
+
|
|
108
|
+
- [ ] **Step 4: Commit changes**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
git add package.json jest.config.ts pnpm-lock.yaml
|
|
112
|
+
git commit -m "chore: upgrade jest to v29"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### Task 3: ESLint v10 Migration (Flat Config)
|
|
118
|
+
|
|
119
|
+
**Files:**
|
|
120
|
+
- Modify: `../about-time/package.json`
|
|
121
|
+
- Create: `../about-time/eslint.config.mjs`
|
|
122
|
+
- Delete: `../about-time/.eslintrc.js`
|
|
123
|
+
|
|
124
|
+
- [ ] **Step 1: Update package.json with ESLint 10 deps**
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
"devDependencies": {
|
|
128
|
+
"@eslint/js": "^9.21.0",
|
|
129
|
+
"eslint": "^9.21.0",
|
|
130
|
+
"eslint-config-prettier": "^10.0.2",
|
|
131
|
+
"eslint-plugin-import": "^2.31.0",
|
|
132
|
+
"eslint-plugin-jest": "^28.11.0",
|
|
133
|
+
"eslint-plugin-no-floating-promise": "^2.0.0",
|
|
134
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
135
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
136
|
+
"globals": "^16.0.0",
|
|
137
|
+
"typescript-eslint": "^8.24.1"
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- [ ] **Step 2: Create eslint.config.mjs**
|
|
142
|
+
|
|
143
|
+
Use `dagraph`'s `eslint.config.mjs` as template, tailored for `about-time`.
|
|
144
|
+
|
|
145
|
+
- [ ] **Step 3: Cleanup and verify lint**
|
|
146
|
+
|
|
147
|
+
Run: `cd ../about-time && rm .eslintrc.js && pnpm lint`
|
|
148
|
+
Expected: SUCCESS
|
|
149
|
+
|
|
150
|
+
- [ ] **Step 4: Commit changes**
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git add package.json eslint.config.mjs pnpm-lock.yaml
|
|
154
|
+
git rm .eslintrc.js
|
|
155
|
+
git commit -m "chore: migrate to eslint v10 flat config"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Task 4: Release and Final Audit
|
|
161
|
+
|
|
162
|
+
- [ ] **Step 1: Final Audit**
|
|
163
|
+
|
|
164
|
+
Run: `cd ../about-time && pnpm audit`
|
|
165
|
+
Expected: 0 vulnerabilities found.
|
|
166
|
+
|
|
167
|
+
- [ ] **Step 2: Prepare for release**
|
|
168
|
+
|
|
169
|
+
Update version in `package.json` to `1.0.0` or similar (ask user for version if unsure, but for plan let's say bump minor).
|
|
170
|
+
|
|
171
|
+
- [ ] **Step 3: Build and Commit**
|
|
172
|
+
|
|
173
|
+
Run: `pnpm build`
|
|
174
|
+
Commit final changes.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Design Doc: Dependency Modernization for about-time
|
|
2
|
+
|
|
3
|
+
This document outlines the plan to upgrade all dependencies in the `about-time` repository to their latest major versions, resolving 24 security vulnerabilities (mostly transitives from older `eslint` and `ts-jest` dependencies) and fixing TypeScript deprecations.
|
|
4
|
+
|
|
5
|
+
## Goals
|
|
6
|
+
|
|
7
|
+
1. **Resolve Security Vulnerabilities:** Fix all vulnerabilities reported by `pnpm audit`.
|
|
8
|
+
2. **Fix TypeScript Deprecations:** Resolve the `moduleResolution: node` deprecation error in TypeScript 5+.
|
|
9
|
+
3. **Modernize Tooling:** Upgrade ESLint (v8 -> v9/v10) to the flat config standard, update Jest configurations, and bump core dependencies like `typescript`, `prettier`, etc.
|
|
10
|
+
|
|
11
|
+
## Approach
|
|
12
|
+
|
|
13
|
+
We will use an incremental block upgrade strategy, identical to the one used for the `pipelines` repository.
|
|
14
|
+
|
|
15
|
+
### Block 1: TypeScript & Infrastructure Upgrade
|
|
16
|
+
- **Action:** Bump `typescript`, `ts-node`, `prettier`, and types.
|
|
17
|
+
- **Config:** Update `tsconfig.json` to use `"moduleResolution": "node10"` and `"ignoreDeprecations": "5.0"`.
|
|
18
|
+
- **Verification:** Run `pnpm install && pnpm run build`.
|
|
19
|
+
|
|
20
|
+
### Block 2: Jest Configuration Modernization
|
|
21
|
+
- **Action:** Bump Jest dependencies (`jest`, `ts-jest`, `@types/jest`, reporters, etc.) to their latest stable versions.
|
|
22
|
+
- **Config:** Update `jest.config.ts` to use the modern array-based transform config for `ts-jest`, moving away from the deprecated string preset.
|
|
23
|
+
- **Verification:** Run `pnpm jest`.
|
|
24
|
+
|
|
25
|
+
### Block 3: ESLint v10 Migration (Flat Config)
|
|
26
|
+
- **Action:** Upgrade ESLint and all plugins to v9+.
|
|
27
|
+
- **Migration:** Convert `.eslintrc.js` to the new Flat Config system (`eslint.config.mjs`).
|
|
28
|
+
- **Verification:** Run `pnpm lint`.
|
|
29
|
+
|
|
30
|
+
### Final Steps
|
|
31
|
+
- **Audit:** Run `pnpm audit` to ensure all vulnerabilities are cleared.
|
|
32
|
+
- **Test:** Run the full `pnpm test` suite.
|
|
33
|
+
- **Commit:** Prepare for release.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import eslint from '@eslint/js';
|
|
2
|
+
import tseslint from 'typescript-eslint';
|
|
3
|
+
import jestPlugin from 'eslint-plugin-jest';
|
|
4
|
+
import prettierPlugin from 'eslint-plugin-prettier';
|
|
5
|
+
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
6
|
+
import importPlugin from 'eslint-plugin-import';
|
|
7
|
+
import unusedImportsPlugin from 'eslint-plugin-unused-imports';
|
|
8
|
+
import noFloatingPromisePlugin from 'eslint-plugin-no-floating-promise';
|
|
9
|
+
import globals from 'globals';
|
|
10
|
+
|
|
11
|
+
export default tseslint.config(
|
|
12
|
+
{
|
|
13
|
+
ignores: ['dist', 'node_modules', '**/generated', 'jest-html-reporters-attach', 'coverage']
|
|
14
|
+
},
|
|
15
|
+
eslint.configs.recommended,
|
|
16
|
+
...tseslint.configs.recommended,
|
|
17
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
18
|
+
{
|
|
19
|
+
languageOptions: {
|
|
20
|
+
parserOptions: {
|
|
21
|
+
project: './tsconfig.eslint.json',
|
|
22
|
+
tsconfigRootDir: import.meta.dirname
|
|
23
|
+
},
|
|
24
|
+
globals: {
|
|
25
|
+
...globals.node,
|
|
26
|
+
...globals.jest
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
plugins: {
|
|
30
|
+
prettier: prettierPlugin,
|
|
31
|
+
jest: jestPlugin,
|
|
32
|
+
import: importPlugin,
|
|
33
|
+
'unused-imports': unusedImportsPlugin,
|
|
34
|
+
'no-floating-promise': noFloatingPromisePlugin
|
|
35
|
+
},
|
|
36
|
+
rules: {
|
|
37
|
+
'@typescript-eslint/no-var-requires': 'off',
|
|
38
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
39
|
+
'no-return-await': 'error',
|
|
40
|
+
'no-floating-promise/no-floating-promise': 'error',
|
|
41
|
+
'unused-imports/no-unused-imports': 'error',
|
|
42
|
+
|
|
43
|
+
// Temporarily disabling strict rules from recommendedTypeChecked that were not present before
|
|
44
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
45
|
+
'@typescript-eslint/prefer-promise-reject-errors': 'off',
|
|
46
|
+
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
47
|
+
'@typescript-eslint/no-unsafe-return': 'off',
|
|
48
|
+
'@typescript-eslint/no-unsafe-argument': 'off',
|
|
49
|
+
'@typescript-eslint/no-misused-promises': 'off',
|
|
50
|
+
'@typescript-eslint/require-await': 'off',
|
|
51
|
+
|
|
52
|
+
'prettier/prettier': [
|
|
53
|
+
'warn',
|
|
54
|
+
{
|
|
55
|
+
printWidth: 120,
|
|
56
|
+
tabWidth: 2,
|
|
57
|
+
tabs: false,
|
|
58
|
+
semi: true,
|
|
59
|
+
singleQuote: true,
|
|
60
|
+
quoteProps: 'as-needed',
|
|
61
|
+
trailingComma: 'none',
|
|
62
|
+
bracketSpacing: true,
|
|
63
|
+
arrowParens: 'avoid'
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
files: ['test/**/*.spec.ts', 'test/**/*.ts'],
|
|
70
|
+
...jestPlugin.configs['flat/recommended'],
|
|
71
|
+
rules: {
|
|
72
|
+
...jestPlugin.configs['flat/recommended'].rules,
|
|
73
|
+
'jest/no-disabled-tests': 'warn',
|
|
74
|
+
'jest/no-focused-tests': 'error',
|
|
75
|
+
'jest/no-identical-title': 'error',
|
|
76
|
+
'jest/prefer-to-have-length': 'warn',
|
|
77
|
+
'jest/valid-expect': 'error'
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
files: ['**/*.js', '**/*.mjs'],
|
|
82
|
+
...tseslint.configs.disableTypeChecked
|
|
83
|
+
},
|
|
84
|
+
eslintConfigPrettier
|
|
85
|
+
);
|
package/lib/retry.ts
CHANGED
|
@@ -9,7 +9,11 @@ interface RetryPolicy {
|
|
|
9
9
|
class SimpleRetryPolicy implements RetryPolicy {
|
|
10
10
|
private readonly interval: number;
|
|
11
11
|
|
|
12
|
-
constructor(
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly count: number,
|
|
14
|
+
interval: number,
|
|
15
|
+
units?: TimeUnit
|
|
16
|
+
) {
|
|
13
17
|
this.interval = toMilliseconds(interval, units);
|
|
14
18
|
}
|
|
15
19
|
|
package/lib/timeout.ts
CHANGED
|
@@ -18,9 +18,12 @@ async function timeoutAround<T>(action: () => T | Promise<T>, options: TimerOpti
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const race = new Promise<T>((resolve, reject) => {
|
|
21
|
-
const timer = setTimeout(
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const timer = setTimeout(
|
|
22
|
+
() => {
|
|
23
|
+
reject(new TimeoutError());
|
|
24
|
+
},
|
|
25
|
+
toMilliseconds(options.time, options.units)
|
|
26
|
+
);
|
|
24
27
|
|
|
25
28
|
if (options.unref) {
|
|
26
29
|
timer.unref();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sha1n/about-time",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "A set of essential time related utilities",
|
|
6
6
|
"repository": "https://github.com/sha1n/about-time",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"scripts": {
|
|
28
28
|
"clean": "rm -rf ./dist",
|
|
29
29
|
"build": "tsc",
|
|
30
|
-
"lint": "eslint --fix
|
|
30
|
+
"lint": "eslint --fix .",
|
|
31
31
|
"jest": "DEBUG='error:*' jest --coverage",
|
|
32
32
|
"test": "pnpm jest && pnpm lint",
|
|
33
33
|
"prepare": "pnpm run build"
|
|
@@ -37,36 +37,36 @@
|
|
|
37
37
|
"registry": "https://registry.npmjs.org/"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@types/
|
|
40
|
+
"@eslint/js": "^9.39.4",
|
|
41
|
+
"@types/chance": "^1.1.7",
|
|
42
|
+
"@types/is-ci": "^3.0.4",
|
|
42
43
|
"@types/jest": "^29.5.14",
|
|
43
|
-
"@types/node": "^22.
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"eslint": "^
|
|
48
|
-
"eslint-
|
|
49
|
-
"eslint-plugin-
|
|
50
|
-
"eslint-plugin-
|
|
51
|
-
"eslint-plugin-
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"eslint-plugin-unused-imports": "^4.3.0",
|
|
55
|
-
"is-ci": "^3.0.1",
|
|
44
|
+
"@types/node": "^22.19.15",
|
|
45
|
+
"chance": "^1.1.13",
|
|
46
|
+
"eslint": "^9.39.4",
|
|
47
|
+
"eslint-config-prettier": "^10.1.8",
|
|
48
|
+
"eslint-plugin-import": "^2.32.0",
|
|
49
|
+
"eslint-plugin-jest": "^28.14.0",
|
|
50
|
+
"eslint-plugin-no-floating-promise": "^2.0.0",
|
|
51
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
52
|
+
"eslint-plugin-unused-imports": "^4.4.1",
|
|
53
|
+
"globals": "^16.5.0",
|
|
54
|
+
"is-ci": "^4.1.0",
|
|
56
55
|
"jest": "^29.7.0",
|
|
57
56
|
"jest-environment-node": "^29.7.0",
|
|
58
|
-
"jest-extended": "^
|
|
59
|
-
"jest-html-reporters": "^3.
|
|
57
|
+
"jest-extended": "^6.0.0",
|
|
58
|
+
"jest-html-reporters": "^3.1.7",
|
|
60
59
|
"jest-mock-extended": "^4.0.0",
|
|
61
60
|
"jest-summary-reporter": "^0.0.2",
|
|
62
|
-
"prettier": "^
|
|
63
|
-
"ts-jest": "^29.4.
|
|
61
|
+
"prettier": "^3.8.1",
|
|
62
|
+
"ts-jest": "^29.4.9",
|
|
64
63
|
"ts-node": "^10.9.2",
|
|
65
|
-
"typescript": "^5.
|
|
64
|
+
"typescript": "^5.9.3",
|
|
65
|
+
"typescript-eslint": "^8.58.0"
|
|
66
66
|
},
|
|
67
67
|
"packageManager": "pnpm@9.15.4",
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
69
|
+
"@typescript-eslint/typescript-estree": "^8.58.0"
|
|
70
70
|
},
|
|
71
71
|
"engines": {
|
|
72
72
|
"node": ">=24"
|