untodo 0.0.1-alpha.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/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/cli.cjs +81 -0
- package/dist/cli.d.cts +2 -0
- package/dist/cli.d.mts +2 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.mjs +79 -0
- package/dist/eslint.cjs +124 -0
- package/dist/eslint.d.cts +101 -0
- package/dist/eslint.d.mts +101 -0
- package/dist/eslint.d.ts +101 -0
- package/dist/eslint.mjs +122 -0
- package/dist/index.cjs +77 -0
- package/dist/index.d.cts +176 -0
- package/dist/index.d.mts +176 -0
- package/dist/index.d.ts +176 -0
- package/dist/index.mjs +66 -0
- package/package.json +76 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base meta passed to {@link TODO}.
|
|
3
|
+
*
|
|
4
|
+
* Users can extend it via Declaration Merging — additional fields are additive,
|
|
5
|
+
* so `reason` is always required:
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* declare module 'untodo' {
|
|
9
|
+
* interface TodoMeta {
|
|
10
|
+
* issue?: number | string;
|
|
11
|
+
* assignee?: string;
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
interface TodoMeta {
|
|
17
|
+
/** Human-readable reason this code is unimplemented. Required. */
|
|
18
|
+
reason: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Base meta passed to {@link FIXME}.
|
|
22
|
+
*
|
|
23
|
+
* Extendable via Declaration Merging in the same way as {@link TodoMeta}.
|
|
24
|
+
*/
|
|
25
|
+
interface FixmeMeta {
|
|
26
|
+
/** Human-readable description of what is broken. Required. */
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Base meta passed to {@link HACK}.
|
|
31
|
+
*
|
|
32
|
+
* Extendable via Declaration Merging in the same way as {@link TodoMeta}.
|
|
33
|
+
*/
|
|
34
|
+
interface HackMeta {
|
|
35
|
+
/** Human-readable description of the workaround. Required. */
|
|
36
|
+
reason: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Union of all meta shapes accepted by the untodo function family.
|
|
40
|
+
*/
|
|
41
|
+
type AnyUntodoMeta = TodoMeta | FixmeMeta | HackMeta;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Base class for all errors thrown by user-supplied untodo callbacks.
|
|
45
|
+
*
|
|
46
|
+
* The library itself never throws; this hierarchy exists so that consumers
|
|
47
|
+
* who *want* to throw inside `onTodo` / `onFixme` / `onHack` can use a
|
|
48
|
+
* consistent type for catch blocks.
|
|
49
|
+
*/
|
|
50
|
+
declare class UntodoError extends Error {
|
|
51
|
+
/**
|
|
52
|
+
* @param message Human-readable error message.
|
|
53
|
+
*/
|
|
54
|
+
constructor(message: string);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Error intended to be thrown from a {@link TODO} callback when the missing
|
|
58
|
+
* implementation must surface as a runtime failure.
|
|
59
|
+
*/
|
|
60
|
+
declare class NotImplementedError extends UntodoError {
|
|
61
|
+
/**
|
|
62
|
+
* @param message Human-readable error message.
|
|
63
|
+
*/
|
|
64
|
+
constructor(message: string);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Error intended to be thrown from a {@link FIXME} callback.
|
|
68
|
+
*/
|
|
69
|
+
declare class FixmeError extends UntodoError {
|
|
70
|
+
/**
|
|
71
|
+
* @param message Human-readable error message.
|
|
72
|
+
*/
|
|
73
|
+
constructor(message: string);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Error intended to be thrown from a {@link HACK} callback.
|
|
77
|
+
*/
|
|
78
|
+
declare class HackError extends UntodoError {
|
|
79
|
+
/**
|
|
80
|
+
* @param message Human-readable error message.
|
|
81
|
+
*/
|
|
82
|
+
constructor(message: string);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Project-wide configuration consumed by {@link TODO}, {@link FIXME}
|
|
87
|
+
* and {@link HACK} when no per-call callback is supplied.
|
|
88
|
+
*
|
|
89
|
+
* Set this once from a setup file (e.g. `untodo.config.ts`) using
|
|
90
|
+
* {@link defineConfig}.
|
|
91
|
+
*/
|
|
92
|
+
interface UntodoConfig {
|
|
93
|
+
/**
|
|
94
|
+
* Repository in `org/repo` form. Used by tooling to expand the `issue`
|
|
95
|
+
* meta field into a full URL (e.g. `https://github.com/org/repo/issues/123`).
|
|
96
|
+
*/
|
|
97
|
+
repo?: string;
|
|
98
|
+
/** Default handler invoked for {@link TODO} calls without a callback. */
|
|
99
|
+
onTodo?: (meta: TodoMeta) => void;
|
|
100
|
+
/** Default handler invoked for {@link FIXME} calls without a callback. */
|
|
101
|
+
onFixme?: (meta: FixmeMeta) => void;
|
|
102
|
+
/** Default handler invoked for {@link HACK} calls without a callback. */
|
|
103
|
+
onHack?: (meta: HackMeta) => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Register the project-wide untodo configuration and return it unchanged.
|
|
107
|
+
*
|
|
108
|
+
* Mirrors the `defineConfig` ergonomics used by Vite / Vitest. Per-call
|
|
109
|
+
* callbacks passed to {@link TODO}, {@link FIXME} or {@link HACK} take
|
|
110
|
+
* precedence over the handlers registered here.
|
|
111
|
+
*
|
|
112
|
+
* @param config The configuration object to register.
|
|
113
|
+
* @returns The same `config` object, for chaining or assignment.
|
|
114
|
+
*/
|
|
115
|
+
declare function defineConfig(config: UntodoConfig): UntodoConfig;
|
|
116
|
+
/**
|
|
117
|
+
* Read the currently-registered {@link UntodoConfig}.
|
|
118
|
+
*
|
|
119
|
+
* Returns an empty object if {@link defineConfig} has not been called
|
|
120
|
+
* (or after {@link resetConfig}).
|
|
121
|
+
*/
|
|
122
|
+
declare function getConfig(): UntodoConfig;
|
|
123
|
+
/**
|
|
124
|
+
* Clear the registered configuration. Primarily intended for tests.
|
|
125
|
+
*/
|
|
126
|
+
declare function resetConfig(): void;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Marks a code path as not yet implemented.
|
|
130
|
+
*
|
|
131
|
+
* Returns `never`, so callers continue to type-check as if the value flowed
|
|
132
|
+
* through. Does **not** throw — runtime behaviour is delegated to the
|
|
133
|
+
* supplied callback (or the global `onTodo` from {@link defineConfig}).
|
|
134
|
+
*
|
|
135
|
+
* Lint enforcement is the responsibility of the `untodo/no-todo` ESLint /
|
|
136
|
+
* oxlint rule shipped from `untodo/eslint`.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* function fetchUser(): User {
|
|
141
|
+
* return TODO({ reason: 'wire up the user repository' });
|
|
142
|
+
* }
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @param meta Structured description of the unimplemented work.
|
|
146
|
+
* @param cb Optional per-call handler; overrides the global `onTodo`.
|
|
147
|
+
* @returns Never — the function returns `undefined` typed as `never`.
|
|
148
|
+
*/
|
|
149
|
+
declare function TODO(meta: TodoMeta, cb?: (meta: TodoMeta) => void): never;
|
|
150
|
+
/**
|
|
151
|
+
* Marks code that is known to be broken and must be repaired.
|
|
152
|
+
*
|
|
153
|
+
* Same semantics as {@link TODO}: returns `never`, never throws, and
|
|
154
|
+
* runtime behaviour is delegated to the supplied callback (or the global
|
|
155
|
+
* `onFixme` from {@link defineConfig}).
|
|
156
|
+
*
|
|
157
|
+
* @param meta Structured description of the defect.
|
|
158
|
+
* @param cb Optional per-call handler; overrides the global `onFixme`.
|
|
159
|
+
* @returns Never — the function returns `undefined` typed as `never`.
|
|
160
|
+
*/
|
|
161
|
+
declare function FIXME(meta: FixmeMeta, cb?: (meta: FixmeMeta) => void): never;
|
|
162
|
+
/**
|
|
163
|
+
* Marks a deliberate workaround that should be revisited.
|
|
164
|
+
*
|
|
165
|
+
* Same semantics as {@link TODO}: returns `never`, never throws, and
|
|
166
|
+
* runtime behaviour is delegated to the supplied callback (or the global
|
|
167
|
+
* `onHack` from {@link defineConfig}).
|
|
168
|
+
*
|
|
169
|
+
* @param meta Structured description of the workaround.
|
|
170
|
+
* @param cb Optional per-call handler; overrides the global `onHack`.
|
|
171
|
+
* @returns Never — the function returns `undefined` typed as `never`.
|
|
172
|
+
*/
|
|
173
|
+
declare function HACK(meta: HackMeta, cb?: (meta: HackMeta) => void): never;
|
|
174
|
+
|
|
175
|
+
export { FIXME, FixmeError, HACK, HackError, NotImplementedError, TODO, UntodoError, defineConfig, getConfig, resetConfig };
|
|
176
|
+
export type { AnyUntodoMeta, FixmeMeta, HackMeta, TodoMeta, UntodoConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
class UntodoError extends Error {
|
|
2
|
+
/**
|
|
3
|
+
* @param message Human-readable error message.
|
|
4
|
+
*/
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "UntodoError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
class NotImplementedError extends UntodoError {
|
|
11
|
+
/**
|
|
12
|
+
* @param message Human-readable error message.
|
|
13
|
+
*/
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "NotImplementedError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
class FixmeError extends UntodoError {
|
|
20
|
+
/**
|
|
21
|
+
* @param message Human-readable error message.
|
|
22
|
+
*/
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "FixmeError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class HackError extends UntodoError {
|
|
29
|
+
/**
|
|
30
|
+
* @param message Human-readable error message.
|
|
31
|
+
*/
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "HackError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let currentConfig = {};
|
|
39
|
+
function defineConfig(config) {
|
|
40
|
+
currentConfig = config;
|
|
41
|
+
return config;
|
|
42
|
+
}
|
|
43
|
+
function getConfig() {
|
|
44
|
+
return currentConfig;
|
|
45
|
+
}
|
|
46
|
+
function resetConfig() {
|
|
47
|
+
currentConfig = {};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function TODO(meta, cb) {
|
|
51
|
+
const handler = cb ?? getConfig().onTodo;
|
|
52
|
+
handler?.(meta);
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
function FIXME(meta, cb) {
|
|
56
|
+
const handler = cb ?? getConfig().onFixme;
|
|
57
|
+
handler?.(meta);
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
function HACK(meta, cb) {
|
|
61
|
+
const handler = cb ?? getConfig().onHack;
|
|
62
|
+
handler?.(meta);
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { FIXME, FixmeError, HACK, HackError, NotImplementedError, TODO, UntodoError, defineConfig, getConfig, resetConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "untodo",
|
|
3
|
+
"version": "0.0.1-alpha.0",
|
|
4
|
+
"description": "Type-safe replacement for TODO/FIXME/HACK comments — trackable in IDE, enforceable by lint and the type system.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./eslint": {
|
|
16
|
+
"types": "./dist/eslint.d.ts",
|
|
17
|
+
"import": "./dist/eslint.mjs",
|
|
18
|
+
"require": "./dist/eslint.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"untodo": "./dist/cli.mjs"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "unbuild",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:coverage": "vitest run --coverage",
|
|
33
|
+
"lint": "eslint .",
|
|
34
|
+
"lint:fix": "eslint . --fix"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"todo",
|
|
38
|
+
"fixme",
|
|
39
|
+
"hack",
|
|
40
|
+
"type-safe",
|
|
41
|
+
"eslint",
|
|
42
|
+
"eslint-plugin",
|
|
43
|
+
"oxlint",
|
|
44
|
+
"oxlint-plugin",
|
|
45
|
+
"unjs"
|
|
46
|
+
],
|
|
47
|
+
"author": "Kanon",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/ysknsid25/untodo.git"
|
|
51
|
+
},
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^9.39.2",
|
|
55
|
+
"@stylistic/eslint-plugin": "^5.6.1",
|
|
56
|
+
"@types/node": "^22.10.1",
|
|
57
|
+
"@typescript-eslint/rule-tester": "^8.17.0",
|
|
58
|
+
"@typescript-eslint/utils": "^8.17.0",
|
|
59
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
60
|
+
"eslint": "^9.16.0",
|
|
61
|
+
"eslint-define-config": "^2.1.0",
|
|
62
|
+
"globals": "^16.5.0",
|
|
63
|
+
"typescript": "^5.7.2",
|
|
64
|
+
"typescript-eslint": "^8.49.0",
|
|
65
|
+
"unbuild": "^2.0.0",
|
|
66
|
+
"vitest": "^2.1.8"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"eslint": "^8.0.0 || ^9.0.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"eslint": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|