Skip to content

Commit 957e523

Browse files
committed
chore(sdk): enable stricter type-checked eslint rules
1 parent 0bbf07a commit 957e523

File tree

33 files changed

+282
-288
lines changed

33 files changed

+282
-288
lines changed

packages/aws-durable-execution-sdk-js/eslint.config.js

Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// @ts-check
2+
3+
import filenameConvention from "eslint-plugin-filename-convention";
4+
import eslintConfigPrettier from "eslint-config-prettier/flat";
5+
import tsdoc from "eslint-plugin-tsdoc";
6+
import { defineConfig } from "eslint/config";
7+
import globals from "globals";
8+
import tseslint from "typescript-eslint";
9+
import js from "@eslint/js";
10+
import { fileURLToPath } from "node:url";
11+
import { includeIgnoreFile } from "@eslint/compat";
12+
13+
const gitIgnorePath = fileURLToPath(new URL(".gitignore", import.meta.url));
14+
15+
export default defineConfig([
16+
includeIgnoreFile(gitIgnorePath, "Imported .gitignore patterns"),
17+
{
18+
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
19+
plugins: { js },
20+
extends: ["js/recommended"],
21+
},
22+
{
23+
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
24+
languageOptions: { globals: globals.node },
25+
},
26+
tseslint.configs.strictTypeChecked,
27+
tseslint.configs.stylisticTypeChecked,
28+
{
29+
languageOptions: {
30+
ecmaVersion: "latest",
31+
sourceType: "module",
32+
parserOptions: {
33+
projectService: {
34+
allowDefaultProject: ["*.mjs"],
35+
},
36+
tsconfigRootDir: import.meta.dirname,
37+
},
38+
},
39+
plugins: {
40+
"filename-convention": filenameConvention,
41+
tsdoc: tsdoc,
42+
},
43+
rules: {
44+
// Rules that are temporarily set to warning, but should be switched to errors
45+
"@typescript-eslint/restrict-template-expressions": [
46+
"warn",
47+
{
48+
allowNumber: true,
49+
allowBoolean: true,
50+
},
51+
],
52+
"@typescript-eslint/no-unsafe-assignment": "warn",
53+
"@typescript-eslint/no-unsafe-argument": "warn",
54+
"@typescript-eslint/no-non-null-assertion": "warn",
55+
"@typescript-eslint/no-floating-promises": "warn",
56+
"no-empty": "warn",
57+
"@typescript-eslint/no-unsafe-return": "warn",
58+
"@typescript-eslint/prefer-nullish-coalescing": "warn",
59+
"no-async-promise-executor": "warn",
60+
"@typescript-eslint/no-empty-function": "warn",
61+
"@typescript-eslint/no-misused-promises": "warn",
62+
"@typescript-eslint/only-throw-error": "warn",
63+
"@typescript-eslint/use-unknown-in-catch-callback-variable": "warn",
64+
"@typescript-eslint/no-unsafe-member-access": "warn",
65+
66+
// Modified rules
67+
"@typescript-eslint/no-confusing-void-expression": [
68+
"error",
69+
{
70+
ignoreArrowShorthand: true,
71+
},
72+
],
73+
"@typescript-eslint/no-unused-vars": [
74+
"warn",
75+
{
76+
argsIgnorePattern: "^_",
77+
varsIgnorePattern: "^_",
78+
caughtErrorsIgnorePattern: "^_",
79+
},
80+
],
81+
82+
// Additional custom rules
83+
"no-console": "error",
84+
"no-debugger": "error",
85+
"no-duplicate-imports": "error",
86+
"filename-convention/kebab-case": "error",
87+
"tsdoc/syntax": "warn",
88+
89+
// Disabled rules
90+
91+
// Async functions without await allow throwing async promises still
92+
"@typescript-eslint/require-await": "off",
93+
// Validation of parameters will create "unnecessary" conditions
94+
"@typescript-eslint/no-unnecessary-condition": "off",
95+
},
96+
},
97+
{
98+
files: ["src/**/*.test.ts"],
99+
rules: {
100+
"@typescript-eslint/no-explicit-any": "off",
101+
"@typescript-eslint/no-empty-function": "off",
102+
"@typescript-eslint/no-unsafe-return": "off",
103+
"@typescript-eslint/no-unsafe-member-access": "off",
104+
"@typescript-eslint/unbound-method": "off",
105+
"@typescript-eslint/no-unsafe-call": "off",
106+
"@typescript-eslint/no-unsafe-assignment": "off",
107+
"@typescript-eslint/no-unsafe-argument": "off",
108+
"@typescript-eslint/restrict-plus-operands": "off",
109+
"@typescript-eslint/no-non-null-assertion": "off",
110+
"@typescript-eslint/no-floating-promises": "off",
111+
"@typescript-eslint/only-throw-error": "off",
112+
},
113+
},
114+
eslintConfigPrettier,
115+
]);

packages/aws-durable-execution-sdk-js/scripts/eslint-plugin-filename-convention/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// @ts-check
2+
13
/**
24
* @fileoverview ESLint plugin to enforce kebab-case for file names
35
*/
@@ -77,7 +79,8 @@ function findProjectRoot(startDir) {
7779
return null;
7880
}
7981

80-
module.exports = {
82+
/** @type {import('eslint').ESLint.Plugin} */
83+
const plugin = {
8184
rules: {
8285
"kebab-case": {
8386
meta: {
@@ -87,15 +90,15 @@ module.exports = {
8790
category: "Stylistic Issues",
8891
recommended: true,
8992
},
90-
fixable: null,
93+
fixable: undefined,
9194
schema: [],
9295
},
9396
create: function (context) {
9497
// Use default ignore patterns (ESLint v9+ doesn't support CLIEngine)
9598
let ignorePatterns = defaultIgnorePatterns;
9699

97100
// Function to check if a path should be ignored
98-
const shouldIgnorePath = (filePath) => {
101+
const shouldIgnorePath = (/** @type {string} */ filePath) => {
99102
// Convert to posix path for consistent pattern matching
100103
const posixPath = filePath.split(path.sep).join("/");
101104

@@ -178,3 +181,5 @@ module.exports = {
178181
},
179182
},
180183
};
184+
185+
module.exports = plugin;

packages/aws-durable-execution-sdk-js/src/context/durable-context/durable-context.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ import { validateContextUsage } from "../../utils/context-tracker/context-tracke
5151

5252
export class DurableContextImpl implements DurableContext {
5353
private _stepPrefix?: string;
54-
private _stepCounter: number = 0;
54+
private _stepCounter = 0;
5555
private contextLogger: Logger | null;
56-
private modeAwareLoggingEnabled: boolean = true;
56+
private modeAwareLoggingEnabled = true;
5757
private runningOperations = new Set<string>();
5858
private operationsEmitter = new EventEmitter();
5959
private checkpoint: ReturnType<typeof createCheckpoint>;
@@ -361,7 +361,7 @@ export class DurableContextImpl implements DurableContext {
361361
}
362362

363363
waitForCallback<T>(
364-
nameOrSubmitter?: string | undefined | WaitForCallbackSubmitterFunc,
364+
nameOrSubmitter?: string | WaitForCallbackSubmitterFunc,
365365
submitterOrConfig?: WaitForCallbackSubmitterFunc | WaitForCallbackConfig<T>,
366366
maybeConfig?: WaitForCallbackConfig<T>,
367367
): DurablePromise<T> {
@@ -376,7 +376,7 @@ export class DurableContextImpl implements DurableContext {
376376
this.runInChildContext.bind(this),
377377
);
378378
return waitForCallbackHandler(
379-
nameOrSubmitter!,
379+
nameOrSubmitter,
380380
submitterOrConfig,
381381
maybeConfig,
382382
);
@@ -413,7 +413,7 @@ export class DurableContextImpl implements DurableContext {
413413
? waitForConditionHandler(
414414
nameOrCheckFunc,
415415
checkFuncOrConfig as WaitForConditionCheckFunc<T>,
416-
maybeConfig!,
416+
maybeConfig,
417417
)
418418
: waitForConditionHandler(
419419
nameOrCheckFunc,

packages/aws-durable-execution-sdk-js/src/context/execution-context/execution-context.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,15 @@ export const initializeExecutionContext = async (
5656

5757
log("📝", "Operations:", operationsArray);
5858

59-
const stepData: Record<string, Operation> = operationsArray.reduce(
60-
(acc, operation: Operation) => {
61-
if (operation.Id) {
62-
// The stepData received from backend has Id and ParentId as hash, so no need to hash it again
63-
acc[operation.Id] = operation;
64-
}
65-
return acc;
66-
},
67-
{} as Record<string, Operation>,
68-
);
59+
const stepData: Record<string, Operation> = operationsArray.reduce<
60+
Record<string, Operation>
61+
>((acc, operation: Operation) => {
62+
if (operation.Id) {
63+
// The stepData received from backend has Id and ParentId as hash, so no need to hash it again
64+
acc[operation.Id] = operation;
65+
}
66+
return acc;
67+
}, {});
6968

7069
log("📝", "Loaded step data:", stepData);
7170

packages/aws-durable-execution-sdk-js/src/errors/unrecoverable-error/unrecoverable-error.test.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,14 @@ import { TerminationReason } from "../../termination-manager/types";
1111
// Create concrete implementations for testing
1212
class TestUnrecoverableError extends UnrecoverableError {
1313
readonly terminationReason = TerminationReason.CUSTOM;
14-
15-
constructor(message: string, originalError?: Error) {
16-
super(message, originalError);
17-
}
1814
}
1915

2016
class TestExecutionError extends UnrecoverableExecutionError {
2117
readonly terminationReason = TerminationReason.CUSTOM;
22-
23-
constructor(message: string, originalError?: Error) {
24-
super(message, originalError);
25-
}
2618
}
2719

2820
class TestInvocationError extends UnrecoverableInvocationError {
2921
readonly terminationReason = TerminationReason.CUSTOM;
30-
31-
constructor(message: string, originalError?: Error) {
32-
super(message, originalError);
33-
}
3422
}
3523

3624
describe("UnrecoverableError", () => {

packages/aws-durable-execution-sdk-js/src/handlers/callback-handler/callback.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const createCallback = (
3131
parentId?: string,
3232
) => {
3333
return <T>(
34-
nameOrConfig?: string | undefined | CreateCallbackConfig<T>,
34+
nameOrConfig?: string | CreateCallbackConfig<T>,
3535
maybeConfig?: CreateCallbackConfig<T>,
3636
): DurablePromise<CreateCallbackResult<T>> => {
3737
let name: string | undefined;

packages/aws-durable-execution-sdk-js/src/handlers/concurrent-execution-handler/batch-result.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,28 @@ import { Serdes, SerdesContext } from "../../utils/serdes/serdes";
88

99
export class BatchResultImpl<R> implements BatchResult<R> {
1010
constructor(
11-
public readonly all: Array<BatchItem<R>>,
11+
public readonly all: BatchItem<R>[],
1212
public readonly completionReason:
1313
| "ALL_COMPLETED"
1414
| "MIN_SUCCESSFUL_REACHED"
1515
| "FAILURE_TOLERANCE_EXCEEDED",
1616
) {}
1717

18-
succeeded(): Array<BatchItem<R> & { result: R }> {
18+
succeeded(): (BatchItem<R> & { result: R })[] {
1919
return this.all.filter(
2020
(item): item is BatchItem<R> & { result: R } =>
2121
item.status === BatchItemStatus.SUCCEEDED && item.result !== undefined,
2222
);
2323
}
2424

25-
failed(): Array<BatchItem<R> & { error: ChildContextError }> {
25+
failed(): (BatchItem<R> & { error: ChildContextError })[] {
2626
return this.all.filter(
2727
(item): item is BatchItem<R> & { error: ChildContextError } =>
2828
item.status === BatchItemStatus.FAILED && item.error !== undefined,
2929
);
3030
}
3131

32-
started(): Array<BatchItem<R> & { status: BatchItemStatus.STARTED }> {
32+
started(): (BatchItem<R> & { status: BatchItemStatus.STARTED })[] {
3333
return this.all.filter(
3434
(item): item is BatchItem<R> & { status: BatchItemStatus.STARTED } =>
3535
item.status === BatchItemStatus.STARTED,
@@ -53,11 +53,11 @@ export class BatchResultImpl<R> implements BatchResult<R> {
5353
}
5454
}
5555

56-
getResults(): Array<R> {
56+
getResults(): R[] {
5757
return this.succeeded().map((item) => item.result);
5858
}
5959

60-
getErrors(): Array<ChildContextError> {
60+
getErrors(): ChildContextError[] {
6161
return this.failed().map((item) => item.error);
6262
}
6363

packages/aws-durable-execution-sdk-js/src/handlers/concurrent-execution-handler/concurrent-execution-handler.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ describe("ConcurrencyController", () => {
742742
const executor = jest.fn();
743743

744744
// Resolve in reverse order
745-
let resolvers: Array<(value: any) => void> = [];
745+
const resolvers: ((value: any) => void)[] = [];
746746
mockParentContext.runInChildContext.mockImplementation(() => {
747747
return new Promise((resolve) => {
748748
resolvers.push(resolve);

0 commit comments

Comments
 (0)