startx 0.0.1

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.
Files changed (181) hide show
  1. package/.editorconfig +20 -0
  2. package/.prettierignore +24 -0
  3. package/.prettierrc.js +52 -0
  4. package/.vscode/settings.json +3 -0
  5. package/LICENSE +21 -0
  6. package/apps/core-server/.env.example +24 -0
  7. package/apps/core-server/Dockerfile +61 -0
  8. package/apps/core-server/eslint.config.mjs +47 -0
  9. package/apps/core-server/package.json +73 -0
  10. package/apps/core-server/src/config/custom-type.ts +54 -0
  11. package/apps/core-server/src/events/index.ts +37 -0
  12. package/apps/core-server/src/index.ts +19 -0
  13. package/apps/core-server/src/middlewares/auth-middleware.ts +50 -0
  14. package/apps/core-server/src/middlewares/cors-middleware.ts +6 -0
  15. package/apps/core-server/src/middlewares/error-middleware.ts +23 -0
  16. package/apps/core-server/src/middlewares/logger-middleware.ts +21 -0
  17. package/apps/core-server/src/middlewares/notfound-middleware.ts +14 -0
  18. package/apps/core-server/src/middlewares/serve-static.ts +24 -0
  19. package/apps/core-server/src/routes/files/router.ts +7 -0
  20. package/apps/core-server/src/routes/server.ts +36 -0
  21. package/apps/core-server/tsconfig.json +10 -0
  22. package/apps/core-server/tsdown.config.ts +14 -0
  23. package/biome.json +62 -0
  24. package/configs/eslint-config/package.json +60 -0
  25. package/configs/eslint-config/plugins.d.ts +1 -0
  26. package/configs/eslint-config/src/configs/base.ts +237 -0
  27. package/configs/eslint-config/src/configs/frontend.ts +62 -0
  28. package/configs/eslint-config/src/configs/node.ts +10 -0
  29. package/configs/eslint-config/src/plugin.ts +25 -0
  30. package/configs/eslint-config/src/rules/index.ts +30 -0
  31. package/configs/eslint-config/src/rules/no-argument-spread.test.ts +47 -0
  32. package/configs/eslint-config/src/rules/no-argument-spread.ts +96 -0
  33. package/configs/eslint-config/src/rules/no-dynamic-import-template.ts +32 -0
  34. package/configs/eslint-config/src/rules/no-internal-package-import.ts +40 -0
  35. package/configs/eslint-config/src/rules/no-interpolation-in-regular-string.ts +32 -0
  36. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.test.ts +34 -0
  37. package/configs/eslint-config/src/rules/no-json-parse-json-stringify.ts +49 -0
  38. package/configs/eslint-config/src/rules/no-plain-errors.ts +50 -0
  39. package/configs/eslint-config/src/rules/no-skipped-tests.ts +61 -0
  40. package/configs/eslint-config/src/rules/no-top-level-relative-imports-in-backend-module.ts +27 -0
  41. package/configs/eslint-config/src/rules/no-type-unsafe-event-emitter.ts +33 -0
  42. package/configs/eslint-config/src/rules/no-uncaught-json-parse.test.ts +21 -0
  43. package/configs/eslint-config/src/rules/no-uncaught-json-parse.ts +45 -0
  44. package/configs/eslint-config/src/rules/no-untyped-config-class-field.ts +26 -0
  45. package/configs/eslint-config/src/rules/no-unused-param-catch-clause.ts +33 -0
  46. package/configs/eslint-config/src/rules/no-useless-catch-throw.test.ts +34 -0
  47. package/configs/eslint-config/src/rules/no-useless-catch-throw.ts +47 -0
  48. package/configs/eslint-config/src/utils/json.ts +21 -0
  49. package/configs/eslint-config/tsconfig.json +8 -0
  50. package/configs/eslint-config/tsdown.config.ts +11 -0
  51. package/configs/eslint-config/vitest.config.ts +3 -0
  52. package/configs/tsdown-config/package.json +14 -0
  53. package/configs/tsdown-config/src/config/tsdown.base.ts +13 -0
  54. package/configs/typescript-config/package.json +10 -0
  55. package/configs/typescript-config/tsconfig.common.json +32 -0
  56. package/configs/typescript-config/tsconfig.frontend.json +14 -0
  57. package/configs/typescript-config/tsconfig.node.json +9 -0
  58. package/configs/vitest-config/package.json +25 -0
  59. package/configs/vitest-config/src/base.ts +34 -0
  60. package/configs/vitest-config/src/frontend.ts +15 -0
  61. package/configs/vitest-config/src/node.ts +5 -0
  62. package/configs/vitest-config/tsconfig.json +7 -0
  63. package/package.json +47 -0
  64. package/packages/@repo/constants/eslint.config.mjs +21 -0
  65. package/packages/@repo/constants/package.json +19 -0
  66. package/packages/@repo/constants/src/api.ts +1 -0
  67. package/packages/@repo/constants/src/index.ts +8 -0
  68. package/packages/@repo/constants/src/time.ts +23 -0
  69. package/packages/@repo/constants/tsconfig.json +7 -0
  70. package/packages/@repo/db/eslint.config.mjs +21 -0
  71. package/packages/@repo/db/package.json +30 -0
  72. package/packages/@repo/db/src/functions.ts +122 -0
  73. package/packages/@repo/db/src/index.ts +20 -0
  74. package/packages/@repo/db/src/schema/common.ts +49 -0
  75. package/packages/@repo/db/src/schema/index.ts +1 -0
  76. package/packages/@repo/db/tsconfig.json +13 -0
  77. package/packages/@repo/lib/eslint.config.mjs +49 -0
  78. package/packages/@repo/lib/package.json +57 -0
  79. package/packages/@repo/lib/src/bucket-module/file-storage.ts +49 -0
  80. package/packages/@repo/lib/src/bucket-module/s3-storage.ts +114 -0
  81. package/packages/@repo/lib/src/bucket-module/utils.ts +11 -0
  82. package/packages/@repo/lib/src/command-module.ts +77 -0
  83. package/packages/@repo/lib/src/constants.ts +3 -0
  84. package/packages/@repo/lib/src/cookie-module.ts +42 -0
  85. package/packages/@repo/lib/src/custom-type.ts +54 -0
  86. package/packages/@repo/lib/src/env.ts +13 -0
  87. package/packages/@repo/lib/src/error-handlers-module/index.ts +11 -0
  88. package/packages/@repo/lib/src/file-system/index.ts +90 -0
  89. package/packages/@repo/lib/src/hashing-module.ts +9 -0
  90. package/packages/@repo/lib/src/index.ts +27 -0
  91. package/packages/@repo/lib/src/logger-module/log-config.ts +16 -0
  92. package/packages/@repo/lib/src/logger-module/logger.ts +78 -0
  93. package/packages/@repo/lib/src/logger-module/memory-profiler.ts +65 -0
  94. package/packages/@repo/lib/src/mail-module/api.ts +0 -0
  95. package/packages/@repo/lib/src/mail-module/mock.ts +8 -0
  96. package/packages/@repo/lib/src/mail-module/nodemailer.ts +45 -0
  97. package/packages/@repo/lib/src/notification-module/index.ts +172 -0
  98. package/packages/@repo/lib/src/notification-module/push-notification.ts +90 -0
  99. package/packages/@repo/lib/src/oauth2-client.ts +109 -0
  100. package/packages/@repo/lib/src/otp-module.ts +98 -0
  101. package/packages/@repo/lib/src/pagination-module.ts +49 -0
  102. package/packages/@repo/lib/src/token-module.ts +35 -0
  103. package/packages/@repo/lib/src/user-session.ts +117 -0
  104. package/packages/@repo/lib/src/utils.ts +42 -0
  105. package/packages/@repo/lib/src/validation-module.ts +187 -0
  106. package/packages/@repo/lib/tsconfig.json +7 -0
  107. package/packages/@repo/mail/package.json +29 -0
  108. package/packages/@repo/mail/src/emails/admin/OtpEmail.tsx +168 -0
  109. package/packages/@repo/mail/src/index.ts +13 -0
  110. package/packages/@repo/mail/tsconfig.build.json +14 -0
  111. package/packages/@repo/mail/tsconfig.json +13 -0
  112. package/packages/@repo/mail/tsdown.config.ts +9 -0
  113. package/packages/@repo/redis/eslint.config.mjs +8 -0
  114. package/packages/@repo/redis/package.json +31 -0
  115. package/packages/@repo/redis/src/index.ts +2 -0
  116. package/packages/@repo/redis/src/lib/redis-client.ts +23 -0
  117. package/packages/@repo/redis/src/lib/redis-module.ts +3 -0
  118. package/packages/@repo/redis/tsconfig.json +12 -0
  119. package/packages/ui/components.json +17 -0
  120. package/packages/ui/eslint.config.mjs +18 -0
  121. package/packages/ui/package.json +67 -0
  122. package/packages/ui/postcss.config.mjs +9 -0
  123. package/packages/ui/src/components/custom/form-wrapper.tsx +551 -0
  124. package/packages/ui/src/components/custom/grid-component.tsx +23 -0
  125. package/packages/ui/src/components/custom/hover-tool.tsx +38 -0
  126. package/packages/ui/src/components/custom/image-picker.tsx +109 -0
  127. package/packages/ui/src/components/custom/no-content.tsx +37 -0
  128. package/packages/ui/src/components/custom/page-container.tsx +24 -0
  129. package/packages/ui/src/components/custom/page-section.tsx +59 -0
  130. package/packages/ui/src/components/custom/simple-popover.tsx +29 -0
  131. package/packages/ui/src/components/custom/switch-component.tsx +20 -0
  132. package/packages/ui/src/components/custom/theme-provider.tsx +74 -0
  133. package/packages/ui/src/components/custom/typography.tsx +111 -0
  134. package/packages/ui/src/components/extensions/carousel.tsx +392 -0
  135. package/packages/ui/src/components/hooks/event/use-click.tsx +39 -0
  136. package/packages/ui/src/components/hooks/time/useDebounce.tsx +21 -0
  137. package/packages/ui/src/components/hooks/time/useInterval.tsx +35 -0
  138. package/packages/ui/src/components/hooks/time/useTimeout.tsx +19 -0
  139. package/packages/ui/src/components/hooks/time/useTimer.tsx +51 -0
  140. package/packages/ui/src/components/hooks/use-media-query.tsx +19 -0
  141. package/packages/ui/src/components/hooks/use-persistent-storage.tsx +52 -0
  142. package/packages/ui/src/components/hooks/use-update-effect.tsx +13 -0
  143. package/packages/ui/src/components/hooks/use-window-dimension.tsx +30 -0
  144. package/packages/ui/src/components/lib/utils.ts +242 -0
  145. package/packages/ui/src/components/lucide.tsx +3 -0
  146. package/packages/ui/src/components/sonner.tsx +1 -0
  147. package/packages/ui/src/components/ui/alert-dialog.tsx +116 -0
  148. package/packages/ui/src/components/ui/avatar.tsx +53 -0
  149. package/packages/ui/src/components/ui/badge.tsx +46 -0
  150. package/packages/ui/src/components/ui/breadcrumb.tsx +109 -0
  151. package/packages/ui/src/components/ui/button.tsx +96 -0
  152. package/packages/ui/src/components/ui/card.tsx +92 -0
  153. package/packages/ui/src/components/ui/carousel.tsx +243 -0
  154. package/packages/ui/src/components/ui/checkbox.tsx +32 -0
  155. package/packages/ui/src/components/ui/command.tsx +155 -0
  156. package/packages/ui/src/components/ui/dialog.tsx +127 -0
  157. package/packages/ui/src/components/ui/dropdown-menu.tsx +226 -0
  158. package/packages/ui/src/components/ui/form.tsx +165 -0
  159. package/packages/ui/src/components/ui/input-otp.tsx +76 -0
  160. package/packages/ui/src/components/ui/input.tsx +21 -0
  161. package/packages/ui/src/components/ui/label.tsx +24 -0
  162. package/packages/ui/src/components/ui/multiple-select.tsx +510 -0
  163. package/packages/ui/src/components/ui/popover.tsx +42 -0
  164. package/packages/ui/src/components/ui/select.tsx +170 -0
  165. package/packages/ui/src/components/ui/separator.tsx +28 -0
  166. package/packages/ui/src/components/ui/sheet.tsx +130 -0
  167. package/packages/ui/src/components/ui/skeleton.tsx +13 -0
  168. package/packages/ui/src/components/ui/spinner.tsx +16 -0
  169. package/packages/ui/src/components/ui/switch.tsx +28 -0
  170. package/packages/ui/src/components/ui/table.tsx +116 -0
  171. package/packages/ui/src/components/ui/tabs.tsx +54 -0
  172. package/packages/ui/src/components/ui/textarea.tsx +18 -0
  173. package/packages/ui/src/components/ui/timeline.tsx +118 -0
  174. package/packages/ui/src/components/ui/tooltip.tsx +30 -0
  175. package/packages/ui/src/components/util/n-formattor.ts +22 -0
  176. package/packages/ui/src/components/util/storage.ts +37 -0
  177. package/packages/ui/src/globals.css +87 -0
  178. package/packages/ui/tailwind.config.ts +94 -0
  179. package/packages/ui/tsconfig.json +12 -0
  180. package/pnpm-workspace.yaml +43 -0
  181. package/turbo.json +77 -0
package/biome.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
+ "vcs": {
4
+ "clientKind": "git",
5
+ "enabled": true,
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false,
10
+ "ignore": [
11
+ "**/.turbo",
12
+ "**/components.d.ts",
13
+ "**/coverage",
14
+ "**/dist",
15
+ "**/build",
16
+ "**/node_modules",
17
+ "**/pnpm-lock.yaml",
18
+ "**/package-lock.json",
19
+ "**/yarn.lock",
20
+ "**/CHANGELOG.md",
21
+ "**/cl100k_base.json",
22
+ "**/o200k_base.json"
23
+ ]
24
+ },
25
+ "formatter": {
26
+ "enabled": true,
27
+ "formatWithErrors": false,
28
+ "indentStyle": "tab",
29
+ "indentWidth": 2,
30
+ "lineEnding": "lf",
31
+ "lineWidth": 100,
32
+ "attributePosition": "auto"
33
+ },
34
+ "organizeImports": {
35
+ "enabled": true
36
+ },
37
+ "linter": {
38
+ "enabled": false
39
+ },
40
+ "javascript": {
41
+ "parser": {
42
+ "unsafeParameterDecoratorsEnabled": true
43
+ },
44
+ "formatter": {
45
+ "jsxQuoteStyle": "double",
46
+ "quoteProperties": "preserve",
47
+ "trailingCommas": "es5",
48
+ "semicolons": "always",
49
+ "arrowParentheses": "asNeeded",
50
+ "bracketSpacing": true,
51
+ "bracketSameLine": false,
52
+ "quoteStyle": "double",
53
+ "attributePosition": "auto"
54
+ }
55
+ },
56
+ "json": {
57
+ "parser": {
58
+ "allowComments": true,
59
+ "allowTrailingCommas": false
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "eslint-config",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "exports": {
7
+ "./base": {
8
+ "types": "./src/configs/base.ts",
9
+ "import": "./dist/configs/base.mjs",
10
+ "require": "./dist/configs/base.mjs"
11
+ },
12
+ "./frontend": {
13
+ "types": "./src/configs/frontend.ts",
14
+ "import": "./dist/configs/frontend.mjs",
15
+ "require": "./dist/configs/frontend.mjs"
16
+ },
17
+ "./node": {
18
+ "types": "./src/configs/node.ts",
19
+ "import": "./dist/configs/node.mjs",
20
+ "require": "./dist/configs/node.mjs"
21
+ }
22
+ },
23
+ "scripts": {
24
+ "config:build": "tsdown",
25
+ "clean": "rimraf dist .turbo",
26
+ "deep:clean": "rimraf node_modules dist .turbo",
27
+ "typecheck": "tsc --noEmit",
28
+ "format": "biome format --write .",
29
+ "format:check": "biome ci .",
30
+ "test": "vitest run",
31
+ "test:dev": "vitest"
32
+ },
33
+ "dependencies": {
34
+ "@eslint/compat": "^2.0.2",
35
+ "@eslint/js": "^9.0.0",
36
+ "@stylistic/eslint-plugin": "^2.0.0",
37
+ "eslint-config-prettier": "^9.1.0",
38
+ "eslint-import-resolver-typescript": "^3.6.1",
39
+ "eslint-plugin-import-x": "^4.0.0",
40
+ "eslint-plugin-jsx-a11y": "^6.9.0",
41
+ "eslint-plugin-lodash": "^8.0.0",
42
+ "eslint-plugin-react": "^7.35.0",
43
+ "eslint-plugin-react-hooks": "^5.0.0",
44
+ "eslint-plugin-unicorn": "^55.0.0",
45
+ "eslint-plugin-unused-imports": "^4.0.0",
46
+ "globals": "^15.9.0",
47
+ "typescript-eslint": "^8.54.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/eslint-config-prettier": "^6.11.3",
51
+ "@types/eslint-plugin-jsx-a11y": "^6.10.1",
52
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
53
+ "@typescript-eslint/rule-tester": "^8.54.0",
54
+ "@typescript-eslint/utils": "^8.0.0",
55
+ "eslint": "catalog:",
56
+ "tsdown-config": "workspace:*",
57
+ "typescript-config": "workspace:*",
58
+ "vitest-config": "workspace:*"
59
+ }
60
+ }
@@ -0,0 +1 @@
1
+ declare module "eslint-plugin-lodash";
@@ -0,0 +1,237 @@
1
+ import js from "@eslint/js";
2
+ import { fixupPluginRules } from "@eslint/compat";
3
+ import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
4
+ import importPlugin from "eslint-plugin-import-x";
5
+ import lodashPlugin from "eslint-plugin-lodash";
6
+ import reactPlugin from "eslint-plugin-react";
7
+ import reactHooksPlugin from "eslint-plugin-react-hooks";
8
+ import unicornPlugin from "eslint-plugin-unicorn";
9
+ import unusedImportsPlugin from "eslint-plugin-unused-imports";
10
+ import globals from "globals";
11
+ import tseslint from "typescript-eslint";
12
+ import stylisticPlugin from "@stylistic/eslint-plugin";
13
+ import eslintConfigPrettier from "eslint-config-prettier";
14
+ import { localRulesPlugin } from "../plugin.js"; // Assuming this exists
15
+
16
+ export const baseConfig = tseslint.config(
17
+ {
18
+ ignores: [
19
+ "**/node_modules/**",
20
+ "**/dist/**",
21
+ "**/build/**",
22
+ "**/.next/**",
23
+ "eslint.config.mjs",
24
+ "tsup.config.ts",
25
+ "jest.config.js",
26
+ "cypress.config.js",
27
+ "vite.config.ts",
28
+ "vitest.config.ts",
29
+ "tsdown.config.ts",
30
+ ],
31
+ },
32
+
33
+ // 2. Base Configurations (Order matters)
34
+ js.configs.recommended,
35
+ ...tseslint.configs.recommended,
36
+ ...tseslint.configs.recommendedTypeChecked,
37
+ importPlugin.flatConfigs.recommended,
38
+ importPlugin.flatConfigs.typescript,
39
+
40
+ // 3. Main Configuration (Node, Express, Shared Logic)
41
+ {
42
+ plugins: {
43
+ // Compatibility fixups for plugins not yet strictly flat-config ready
44
+ "unused-imports": fixupPluginRules(unusedImportsPlugin),
45
+ "react-hooks": fixupPluginRules(reactHooksPlugin as any),
46
+ lodash: fixupPluginRules(lodashPlugin),
47
+
48
+ "@stylistic": stylisticPlugin as any,
49
+ unicorn: unicornPlugin,
50
+ react: reactPlugin,
51
+ },
52
+ languageOptions: {
53
+ ecmaVersion: 2022,
54
+ sourceType: "module",
55
+ // Combine globals for Monorepo (Node + Browser)
56
+ globals: {
57
+ ...globals.browser,
58
+ ...globals.node,
59
+ ...globals.es2021,
60
+ },
61
+ parserOptions: {
62
+ projectService: true, // Faster than 'project: true' for monorepos
63
+ tsconfigRootDir: import.meta.dirname,
64
+ },
65
+ },
66
+ settings: {
67
+ "import-x/resolver-next": [createTypeScriptImportResolver()],
68
+ react: {
69
+ version: "detect",
70
+ },
71
+ },
72
+ rules: {
73
+ // ******************************************************************
74
+ // Core Rules
75
+ // ******************************************************************
76
+ "no-void": ["error", { allowAsStatement: true }],
77
+ "no-constant-binary-expression": "error",
78
+ "no-console": ["warn", { allow: ["warn", "error"] }],
79
+ eqeqeq: "error",
80
+ "object-shorthand": "error",
81
+ "prefer-const": "error",
82
+
83
+ // ID Denylist
84
+ "id-denylist": [
85
+ "error",
86
+ "err",
87
+ "cb",
88
+ "callback",
89
+ "any",
90
+ "Number",
91
+ "number",
92
+ "String",
93
+ "string",
94
+ "Boolean",
95
+ "boolean",
96
+ "Undefined",
97
+ "undefined",
98
+ ],
99
+
100
+ // ******************************************************************
101
+ // TypeScript
102
+ // ******************************************************************
103
+ "@typescript-eslint/array-type": ["error", { default: "array-simple" }],
104
+ "@typescript-eslint/await-thenable": "error",
105
+ "@typescript-eslint/consistent-type-assertions": "error",
106
+ "@typescript-eslint/consistent-type-imports": "error",
107
+ "@typescript-eslint/consistent-type-exports": "error",
108
+ "@typescript-eslint/no-floating-promises": [
109
+ "error",
110
+ { ignoreVoid: true },
111
+ ],
112
+ "@typescript-eslint/no-misused-promises": [
113
+ "error",
114
+ { checksVoidReturn: false },
115
+ ],
116
+ "@typescript-eslint/only-throw-error": "error",
117
+ "@typescript-eslint/return-await": ["error", "always"],
118
+ "@typescript-eslint/explicit-member-accessibility": [
119
+ "error",
120
+ { accessibility: "no-public" },
121
+ ],
122
+ "@typescript-eslint/naming-convention": [
123
+ "error",
124
+ {
125
+ selector: "default",
126
+ format: ["camelCase"],
127
+ },
128
+ {
129
+ selector: "import",
130
+ format: ["camelCase", "PascalCase"],
131
+ },
132
+ {
133
+ selector: "variable",
134
+ format: ["camelCase", "snake_case", "UPPER_CASE", "PascalCase"],
135
+ leadingUnderscore: "allowSingleOrDouble",
136
+ trailingUnderscore: "allowSingleOrDouble",
137
+ },
138
+ {
139
+ selector: "typeLike",
140
+ format: ["PascalCase"],
141
+ },
142
+ {
143
+ selector: "enumMember",
144
+ format: ["UPPER_CASE", "PascalCase"],
145
+ },
146
+ ],
147
+ "@typescript-eslint/no-restricted-types": [
148
+ "error",
149
+ {
150
+ types: {
151
+ Object: { message: "Use object instead", fixWith: "object" },
152
+ String: { message: "Use string instead", fixWith: "string" },
153
+ Boolean: { message: "Use boolean instead", fixWith: "boolean" },
154
+ Number: { message: "Use number instead", fixWith: "number" },
155
+ Symbol: { message: "Use symbol instead", fixWith: "symbol" },
156
+ Function: {
157
+ message:
158
+ "The `Function` type accepts any function-like value. Define the explicit function shape.",
159
+ },
160
+ },
161
+ },
162
+ ],
163
+
164
+ // ******************************************************************
165
+ // Stylistic
166
+ // ******************************************************************
167
+ "@stylistic/member-delimiter-style": [
168
+ "error",
169
+ {
170
+ multiline: { delimiter: "semi", requireLast: true },
171
+ singleline: { delimiter: "semi", requireLast: false },
172
+ },
173
+ ],
174
+
175
+ // ******************************************************************
176
+ // Import X
177
+ // ******************************************************************
178
+ "import-x/no-cycle": ["error", { ignoreExternal: false, maxDepth: 3 }],
179
+ "import-x/no-default-export": "warn",
180
+ "import-x/no-duplicates": "error",
181
+ "import-x/order": [
182
+ "error",
183
+ {
184
+ alphabetize: { order: "asc", caseInsensitive: true },
185
+ groups: [
186
+ ["builtin", "external"],
187
+ "internal",
188
+ ["parent", "index", "sibling"],
189
+ "object",
190
+ ],
191
+ "newlines-between": "always",
192
+ },
193
+ ],
194
+
195
+ // ******************************************************************
196
+ // Plugins
197
+ // ******************************************************************
198
+ "unused-imports/no-unused-imports":
199
+ process.env.NODE_ENV === "development" ? "warn" : "error",
200
+
201
+ "unicorn/no-unnecessary-await": "error",
202
+ "unicorn/no-useless-promise-resolve-reject": "error",
203
+
204
+ "lodash/path-style": ["error", "as-needed"],
205
+ "lodash/import-scope": ["error", "method"],
206
+ },
207
+ },
208
+
209
+ // 4. React Specific Overrides (Only for .tsx / .jsx files)
210
+ {
211
+ files: ["**/*.tsx", "**/*.jsx"],
212
+ ...reactPlugin.configs.flat.recommended,
213
+ ...reactPlugin.configs.flat["jsx-runtime"],
214
+ rules: {
215
+ ...reactHooksPlugin.configs.recommended.rules,
216
+ "react/prop-types": "off", // Not needed with TypeScript
217
+ "react/react-in-jsx-scope": "off", // Not needed in modern React
218
+ "react/jsx-no-leaked-render": "error", // Security/Perf rule
219
+ },
220
+ },
221
+
222
+ // 5. Test Overrides
223
+ {
224
+ files: ["test/**/*.ts", "**/__tests__/*.ts", "**/*.test.ts", "**/*.cy.ts"],
225
+ rules: {
226
+ "local-rules/no-plain-errors": "off",
227
+ "@typescript-eslint/unbound-method": "off",
228
+ "import-x/no-default-export": "off", // Tests often need default export for config or simply don't care
229
+ },
230
+ },
231
+
232
+ // 6. Local Rules
233
+ localRulesPlugin.configs.recommended,
234
+
235
+ // 7. Prettier (Must be last to override stylistic rules)
236
+ eslintConfigPrettier
237
+ );
@@ -0,0 +1,62 @@
1
+ import { fixupPluginRules } from "@eslint/compat";
2
+ import { baseConfig } from "./base.js";
3
+ import jsxA11yPlugin from "eslint-plugin-jsx-a11y";
4
+ import reactPlugin from "eslint-plugin-react";
5
+ import reactHooksPlugin from "eslint-plugin-react-hooks";
6
+ import globals from "globals";
7
+ import tseslint from "typescript-eslint";
8
+
9
+ export const frontendConfig = tseslint.config(
10
+ ...baseConfig,
11
+
12
+ {
13
+ ignores: [
14
+ "**/dist/**",
15
+ "**/coverage/**",
16
+ "**/storybook-static/**",
17
+ "**/*.snap",
18
+ "**/*.d.ts",
19
+ "vite.config.ts",
20
+ ],
21
+ },
22
+
23
+ {
24
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
25
+ languageOptions: {
26
+ globals: {
27
+ ...globals.browser,
28
+ ...globals.serviceworker,
29
+ },
30
+ },
31
+ settings: {
32
+ react: {
33
+ version: "detect",
34
+ },
35
+ },
36
+ },
37
+ reactPlugin.configs.flat.recommended,
38
+ reactPlugin.configs.flat["jsx-runtime"],
39
+
40
+ {
41
+ files: ["**/*.tsx", "**/*.jsx"],
42
+ plugins: {
43
+ "react-hooks": fixupPluginRules(reactHooksPlugin as any),
44
+ "jsx-a11y": fixupPluginRules(jsxA11yPlugin),
45
+ },
46
+ rules: {
47
+ ...reactHooksPlugin.configs.recommended.rules,
48
+ ...jsxA11yPlugin.configs.recommended.rules,
49
+
50
+ // --- React Hooks Specifics ---
51
+ "react-hooks/rules-of-hooks": "error",
52
+ "react-hooks/exhaustive-deps": "warn",
53
+
54
+ // --- Accessibility Specifics ---
55
+ "jsx-a11y/no-autofocus": "warn",
56
+ "jsx-a11y/click-events-have-key-events": "warn",
57
+ "jsx-a11y/no-static-element-interactions": "warn",
58
+ // Disable legacy rule that conflicts with modern HTML5
59
+ "jsx-a11y/no-onchange": "off",
60
+ },
61
+ }
62
+ );
@@ -0,0 +1,10 @@
1
+ import globals from "globals";
2
+ import tseslint from "typescript-eslint";
3
+ import { baseConfig } from "./base.js";
4
+
5
+ export const nodeConfig = tseslint.config(baseConfig, {
6
+ languageOptions: {
7
+ ecmaVersion: 2024,
8
+ globals: globals.node,
9
+ },
10
+ });
@@ -0,0 +1,25 @@
1
+ import type { ESLint } from "eslint";
2
+ import { rules } from "./rules/index.js";
3
+ const plugin = {
4
+ configs: {},
5
+ // @ts-expect-error Rules type does not match for typescript-eslint and eslint
6
+ rules: rules as ESLint.Plugin["rules"],
7
+ } satisfies ESLint.Plugin;
8
+ export const localRulesPlugin = {
9
+ ...plugin,
10
+ configs: {
11
+ recommended: {
12
+ plugins: {
13
+ "local-rules": plugin,
14
+ },
15
+ rules: {
16
+ "local-rules/no-uncaught-json-parse": "error",
17
+ "local-rules/no-json-parse-json-stringify": "error",
18
+ "local-rules/no-interpolation-in-regular-string": "error",
19
+ "local-rules/no-unused-param-in-catch-clause": "error",
20
+ "local-rules/no-useless-catch-throw": "error",
21
+ "local-rules/no-internal-package-import": "error",
22
+ },
23
+ },
24
+ },
25
+ } satisfies ESLint.Plugin;
@@ -0,0 +1,30 @@
1
+ import { NoJsonParseJsonStringifyRule } from "./no-json-parse-json-stringify.js";
2
+ import { NoUncaughtJsonParseRule } from "./no-uncaught-json-parse.js";
3
+ import { NoUnusedParamInCatchClauseRule } from "./no-unused-param-catch-clause.js";
4
+ import { NoUselessCatchThrowRule } from "./no-useless-catch-throw.js";
5
+ import { NoSkippedTestsRule } from "./no-skipped-tests.js";
6
+ import { NoInterpolationInRegularStringRule } from "./no-interpolation-in-regular-string.js";
7
+ import { NoPlainErrorsRule } from "./no-plain-errors.js";
8
+ import { NoDynamicImportTemplateRule } from "./no-dynamic-import-template.js";
9
+ import { NoTypeUnsafeEventEmitterRule } from "./no-type-unsafe-event-emitter.js";
10
+ import { NoUntypedConfigClassFieldRule } from "./no-untyped-config-class-field.js";
11
+ import { NoTopLevelRelativeImportsInBackendModuleRule } from "./no-top-level-relative-imports-in-backend-module.js";
12
+ import type { AnyRuleModule } from "@typescript-eslint/utils/ts-eslint";
13
+ import { NoArgumentSpreadRule } from "./no-argument-spread.js";
14
+ import { NoInternalPackageImportRule } from "./no-internal-package-import.js";
15
+
16
+ export const rules = {
17
+ "no-uncaught-json-parse": NoUncaughtJsonParseRule,
18
+ "no-json-parse-json-stringify": NoJsonParseJsonStringifyRule,
19
+ "no-unused-param-in-catch-clause": NoUnusedParamInCatchClauseRule,
20
+ "no-useless-catch-throw": NoUselessCatchThrowRule,
21
+ "no-skipped-tests": NoSkippedTestsRule,
22
+ "no-interpolation-in-regular-string": NoInterpolationInRegularStringRule,
23
+ "no-plain-errors": NoPlainErrorsRule,
24
+ "no-dynamic-import-template": NoDynamicImportTemplateRule,
25
+ "no-type-unsafe-event-emitter": NoTypeUnsafeEventEmitterRule,
26
+ "no-untyped-config-class-field": NoUntypedConfigClassFieldRule,
27
+ "no-top-level-relative-imports-in-backend-module": NoTopLevelRelativeImportsInBackendModuleRule,
28
+ "no-argument-spread": NoArgumentSpreadRule,
29
+ "no-internal-package-import": NoInternalPackageImportRule,
30
+ } satisfies Record<string, AnyRuleModule>;
@@ -0,0 +1,47 @@
1
+ import { RuleTester } from "@typescript-eslint/rule-tester";
2
+ import { NoArgumentSpreadRule } from "./no-argument-spread.js";
3
+
4
+ const ruleTester = new RuleTester();
5
+
6
+ ruleTester.run("no-unbounded-argument-spread", NoArgumentSpreadRule, {
7
+ valid: [
8
+ { code: "fn(1, 2, 3)" },
9
+ { code: "fn(...[1, 2, 3])" },
10
+ { code: "new Foo(...[1, 2])" },
11
+ { code: "fn.apply(null, deps)" },
12
+ { code: "Reflect.construct(Foo, deps)" },
13
+ ],
14
+
15
+ invalid: [
16
+ {
17
+ code: "fn(...deps)",
18
+ output: "fn.apply(undefined, deps)",
19
+ errors: [{ messageId: "replaceWithApply" }],
20
+ },
21
+ {
22
+ code: "obj.fn(...deps)",
23
+ output: "obj.fn.apply(obj, deps)",
24
+ errors: [{ messageId: "replaceWithApply" }],
25
+ },
26
+ {
27
+ code: "instance = metadata.factory(...dependencies);",
28
+ output: "instance = metadata.factory.apply(metadata, dependencies);",
29
+ errors: [{ messageId: "replaceWithApply" }],
30
+ },
31
+ {
32
+ code: "new Foo(...deps)",
33
+ output: "Reflect.construct(Foo, deps)",
34
+ errors: [{ messageId: "replaceWithReflect" }],
35
+ },
36
+ {
37
+ code: "someFunction(a, ...deps)",
38
+ output: null, // multiple args — no fix
39
+ errors: [{ messageId: "replaceWithApply" }],
40
+ },
41
+ {
42
+ code: "new Bar(a, ...deps)",
43
+ output: null,
44
+ errors: [{ messageId: "replaceWithReflect" }],
45
+ },
46
+ ],
47
+ });
@@ -0,0 +1,96 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+
3
+ export const NoArgumentSpreadRule = ESLintUtils.RuleCreator.withoutDocs({
4
+ name: "no-argument-spread",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description:
9
+ "Avoid spreading potentially large arrays in function or constructor calls — can cause stack overflows. Use `.apply` or `Reflect.construct` instead.",
10
+ },
11
+ fixable: "code",
12
+ messages: {
13
+ noUnboundedSpread:
14
+ "Avoid spreading an array in function or constructor calls unless known to be small.",
15
+ replaceWithApply:
16
+ "Replace `array.push(...largeArray)` with `array.push.apply(array, largeArray)` to avoid potential stack overflows.",
17
+ replaceWithReflect:
18
+ "Replace `new Constructor(...args)` with `Reflect.construct(Constructor, args)` to avoid potential stack overflows.",
19
+ },
20
+ schema: [],
21
+ },
22
+ defaultOptions: [],
23
+ create(context) {
24
+ return {
25
+ CallExpression(node) {
26
+ for (const arg of node.arguments) {
27
+ if (arg.type !== "SpreadElement") continue;
28
+
29
+ const spreadArg = arg.argument;
30
+
31
+ // Allow spread of inline arrays
32
+ if (spreadArg.type === "ArrayExpression") return;
33
+
34
+ // Only autofix if it's the sole argument
35
+ const canFix = node.arguments.length === 1;
36
+
37
+ context.report({
38
+ node,
39
+ messageId: "replaceWithApply",
40
+ fix: canFix
41
+ ? (fixer) => {
42
+ const source = context.sourceCode;
43
+
44
+ if (node.callee.type === "MemberExpression") {
45
+ // Preserve `this`
46
+ const thisText = source.getText(node.callee.object);
47
+ const calleeText = source.getText(node.callee);
48
+ const argText = source.getText(spreadArg);
49
+ return fixer.replaceText(
50
+ node,
51
+ `${calleeText}.apply(${thisText}, ${argText})`
52
+ );
53
+ }
54
+ // Not a memberexpression, use undefined as thisArg
55
+ const calleeText = source.getText(node.callee);
56
+ const argText = source.getText(spreadArg);
57
+ return fixer.replaceText(
58
+ node,
59
+ `${calleeText}.apply(undefined, ${argText})`
60
+ );
61
+ }
62
+ : null,
63
+ });
64
+ }
65
+ },
66
+
67
+ NewExpression(node) {
68
+ for (const arg of node.arguments || []) {
69
+ if (arg.type !== "SpreadElement") continue;
70
+
71
+ const spreadArg = arg.argument;
72
+
73
+ if (spreadArg.type === "ArrayExpression") return;
74
+
75
+ const canFix = node.arguments.length === 1;
76
+
77
+ context.report({
78
+ node,
79
+ messageId: "replaceWithReflect",
80
+ fix: canFix
81
+ ? (fixer) => {
82
+ const source = context.sourceCode;
83
+ const ctorText = source.getText(node.callee);
84
+ const argText = source.getText(spreadArg);
85
+ return fixer.replaceText(
86
+ node,
87
+ `Reflect.construct(${ctorText}, ${argText})`
88
+ );
89
+ }
90
+ : null,
91
+ });
92
+ }
93
+ },
94
+ };
95
+ },
96
+ });
@@ -0,0 +1,32 @@
1
+ import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
2
+
3
+ export const NoDynamicImportTemplateRule = ESLintUtils.RuleCreator.withoutDocs({
4
+ name: 'no-dynamic-import-template',
5
+ meta: {
6
+ type: 'problem',
7
+ docs: {
8
+ description:
9
+ 'Disallow non-relative imports in template string argument to `await import()`, because `tsc-alias` as of 1.8.7 is unable to resolve aliased paths in this scenario.',
10
+ },
11
+ schema: [],
12
+ messages: {
13
+ noDynamicImportTemplate:
14
+ 'Use relative imports in template string argument to `await import()`, because `tsc-alias` as of 1.8.7 is unable to resolve aliased paths in this scenario.',
15
+ },
16
+ },
17
+ defaultOptions: [],
18
+ create(context) {
19
+ return {
20
+ 'AwaitExpression > ImportExpression TemplateLiteral'(node: TSESTree.TemplateLiteral) {
21
+ const templateValue = node.quasis[0].value.cooked;
22
+
23
+ if (!templateValue?.startsWith('@/')) return;
24
+
25
+ context.report({
26
+ node,
27
+ messageId: 'noDynamicImportTemplate',
28
+ });
29
+ },
30
+ };
31
+ },
32
+ });