@rtorcato/repo-tooling 2.59.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.
Files changed (136) hide show
  1. package/AGENTS.md +113 -0
  2. package/LICENSE +21 -0
  3. package/README.md +201 -0
  4. package/dist/cli/commands/doctor.js +336 -0
  5. package/dist/cli/commands/fix-targets.js +192 -0
  6. package/dist/cli/commands/fix.js +440 -0
  7. package/dist/cli/commands/setup-presets.js +281 -0
  8. package/dist/cli/commands/setup.js +501 -0
  9. package/dist/cli/generators/agent-rules.js +103 -0
  10. package/dist/cli/generators/badges.js +88 -0
  11. package/dist/cli/generators/build.js +216 -0
  12. package/dist/cli/generators/bun.js +25 -0
  13. package/dist/cli/generators/community-health.js +145 -0
  14. package/dist/cli/generators/docs-site.js +436 -0
  15. package/dist/cli/generators/git.js +164 -0
  16. package/dist/cli/generators/github-actions.js +35 -0
  17. package/dist/cli/generators/github-workflows.js +24 -0
  18. package/dist/cli/generators/gitlab-ci.js +10 -0
  19. package/dist/cli/generators/index.js +123 -0
  20. package/dist/cli/generators/linting.js +54 -0
  21. package/dist/cli/generators/misc.js +298 -0
  22. package/dist/cli/generators/nx.js +16 -0
  23. package/dist/cli/generators/package-json.js +317 -0
  24. package/dist/cli/generators/pnpm-workspace.js +126 -0
  25. package/dist/cli/generators/postcss.js +24 -0
  26. package/dist/cli/generators/readme.js +268 -0
  27. package/dist/cli/generators/security.js +156 -0
  28. package/dist/cli/generators/skills-install.js +70 -0
  29. package/dist/cli/generators/tailwind.js +34 -0
  30. package/dist/cli/generators/testing.js +88 -0
  31. package/dist/cli/generators/treeshake.js +148 -0
  32. package/dist/cli/generators/tsconfig.js +27 -0
  33. package/dist/cli/generators/turborepo.js +35 -0
  34. package/dist/cli/generators/typedoc.js +40 -0
  35. package/dist/cli/index.js +332 -0
  36. package/dist/cli/utils/copy-preset.js +98 -0
  37. package/dist/cli/utils/detect-language.js +22 -0
  38. package/dist/cli/utils/format.js +32 -0
  39. package/dist/cli/utils/install.js +28 -0
  40. package/dist/cli/utils/lockfile.js +84 -0
  41. package/dist/languages/js/checks.js +949 -0
  42. package/dist/languages/js/ci.js +251 -0
  43. package/dist/languages/js/fixers.js +735 -0
  44. package/dist/languages/registry.js +37 -0
  45. package/dist/languages/swift/checks.js +127 -0
  46. package/dist/languages/swift/ci.js +165 -0
  47. package/dist/languages/swift/fixers.js +102 -0
  48. package/dist/languages/swift/git-hooks.js +63 -0
  49. package/dist/languages/swift/gitignore.js +43 -0
  50. package/dist/languages/swift/scaffold.js +244 -0
  51. package/package.json +461 -0
  52. package/tooling/biome/README.md +90 -0
  53. package/tooling/biome/biome.json +63 -0
  54. package/tooling/bun/bunfig.toml +14 -0
  55. package/tooling/changesets/README.md +35 -0
  56. package/tooling/changesets/config.json +11 -0
  57. package/tooling/claude/repo-tooling.md +87 -0
  58. package/tooling/commitlint/commitlint.d.mts +4 -0
  59. package/tooling/commitlint/commitlint.mjs +40 -0
  60. package/tooling/cypress/cypress.config.d.mts +4 -0
  61. package/tooling/cypress/cypress.config.mjs +11 -0
  62. package/tooling/docusaurus/index.d.mts +17 -0
  63. package/tooling/docusaurus/index.mjs +38 -0
  64. package/tooling/docusaurus/sync-changelog.mjs +42 -0
  65. package/tooling/docusaurus/theme-tokens.css +79 -0
  66. package/tooling/docusaurus/theme.css +378 -0
  67. package/tooling/esbuild/index.d.mts +6 -0
  68. package/tooling/esbuild/index.mjs +102 -0
  69. package/tooling/eslint/base.d.mts +6 -0
  70. package/tooling/eslint/base.mjs +122 -0
  71. package/tooling/eslint/nextjs.d.mts +4 -0
  72. package/tooling/eslint/nextjs.mjs +22 -0
  73. package/tooling/eslint/types.d.ts +58 -0
  74. package/tooling/github-actions/workflows/cloudflare-pages.yml +42 -0
  75. package/tooling/github-actions/workflows/docker-publish.yml +44 -0
  76. package/tooling/github-actions/workflows/preview-deployments.yml +54 -0
  77. package/tooling/github-actions/workflows/vercel-deploy.yml +40 -0
  78. package/tooling/jest-presets/browser/jest-preset.d.mts +4 -0
  79. package/tooling/jest-presets/browser/jest-preset.mjs +14 -0
  80. package/tooling/jest-presets/node/jest-preset.d.mts +4 -0
  81. package/tooling/jest-presets/node/jest-preset.mjs +13 -0
  82. package/tooling/mcp/mcp.json.example +27 -0
  83. package/tooling/nx/nx.json +24 -0
  84. package/tooling/oxlint/README.md +25 -0
  85. package/tooling/oxlint/oxlintrc.json +28 -0
  86. package/tooling/playwright/playwright.config.d.mts +4 -0
  87. package/tooling/playwright/playwright.config.mjs +19 -0
  88. package/tooling/prettier/index.d.mts +4 -0
  89. package/tooling/prettier/index.mjs +36 -0
  90. package/tooling/release-please/.release-please-manifest.json +3 -0
  91. package/tooling/release-please/release-please-config.json +9 -0
  92. package/tooling/rolldown/rolldown.config.d.mts +18 -0
  93. package/tooling/rolldown/rolldown.config.mjs +59 -0
  94. package/tooling/rollup/rollup.config.d.mts +20 -0
  95. package/tooling/rollup/rollup.config.mjs +70 -0
  96. package/tooling/semantic-release/docker.d.mts +4 -0
  97. package/tooling/semantic-release/docker.mjs +59 -0
  98. package/tooling/semantic-release/github.d.mts +4 -0
  99. package/tooling/semantic-release/github.mjs +79 -0
  100. package/tooling/semantic-release/index.d.mts +4 -0
  101. package/tooling/semantic-release/index.mjs +80 -0
  102. package/tooling/swift/periphery.yml +4 -0
  103. package/tooling/swift/swiftlint.yml +23 -0
  104. package/tooling/tests/exports-resolution.d.mts +14 -0
  105. package/tooling/tests/exports-resolution.mjs +68 -0
  106. package/tooling/tests/ssr-safety.d.mts +14 -0
  107. package/tooling/tests/ssr-safety.mjs +53 -0
  108. package/tooling/tsup/index.d.mts +8 -0
  109. package/tooling/tsup/index.mjs +33 -0
  110. package/tooling/typedoc/typedoc.json +7 -0
  111. package/tooling/typescript/README.md +49 -0
  112. package/tooling/typescript/reset.d.ts +9 -0
  113. package/tooling/typescript/tsconfig.base.json +84 -0
  114. package/tooling/typescript/tsconfig.build.json +11 -0
  115. package/tooling/typescript/tsconfig.bun.json +9 -0
  116. package/tooling/typescript/tsconfig.express.json +9 -0
  117. package/tooling/typescript/tsconfig.next.json +20 -0
  118. package/tooling/typescript/tsconfig.node.json +9 -0
  119. package/tooling/typescript/tsconfig.react.json +15 -0
  120. package/tooling/typescript/tsconfig.test.json +8 -0
  121. package/tooling/typescript/v1/tsconfig.base.json +81 -0
  122. package/tooling/typescript/v1/tsconfig.express.json +9 -0
  123. package/tooling/typescript/v1/tsconfig.next.json +19 -0
  124. package/tooling/typescript/v1/tsconfig.node.json +9 -0
  125. package/tooling/typescript/v1/tsconfig.react.json +14 -0
  126. package/tooling/typescript/v1/tsconfig.test.json +8 -0
  127. package/tooling/vite/vite.config.d.mts +4 -0
  128. package/tooling/vite/vite.config.mjs +18 -0
  129. package/tooling/vitest/jsdom-shims.d.mts +1 -0
  130. package/tooling/vitest/jsdom-shims.mjs +58 -0
  131. package/tooling/vitest/vitest.config.d.mts +4 -0
  132. package/tooling/vitest/vitest.config.mjs +25 -0
  133. package/tooling/vitest/vitest.config.react.d.mts +4 -0
  134. package/tooling/vitest/vitest.config.react.mjs +27 -0
  135. package/tooling/vitest/vitest.setup.d.mts +1 -0
  136. package/tooling/vitest/vitest.setup.mjs +3 -0
@@ -0,0 +1,378 @@
1
+ /**
2
+ * Shared @rtorcato Docusaurus component theme (shipped by @rtorcato/repo-tooling —
3
+ * copy via `repo-tooling copy docusaurus-theme`).
4
+ *
5
+ * The accent-agnostic component-override sheet every sibling docs site shares:
6
+ * navbar, doc cards, sidebar, TOC, pagination, footer, code blocks, markdown
7
+ * tables, buttons, and the hardened navy dark surfaces. Every rule references
8
+ * the `--jt-*` / `--ifm-*` tokens from `_jt-tokens.css` (see
9
+ * `copy docusaurus-theme-tokens`) — it defines NO accent colours.
10
+ *
11
+ * Usage in your `src/css/custom.css`:
12
+ *
13
+ * @import "./_jt-tokens.css"; // shared design tokens
14
+ * @import "./theme.css"; // this file — shared component styling
15
+ * :root { --ifm-color-primary: #YOURHEX; --jt-accent: #YOURHEX; ... }
16
+ * [data-theme=dark]{ --ifm-color-primary: #YOURHEX; --jt-accent: #YOURHEX; ... }
17
+ * ::selection { background: rgba(R, G, B, 0.24); } // accent — keep local
18
+ *
19
+ * The single-flat mobile drawer (the `.navbar-sidebar__items` transform lock +
20
+ * the repo-namespaced `.xx-mobile-menu` rules) is NOT here — it ships with the
21
+ * Navbar/MobileSidebar swizzle files, since its class prefix is per-repo.
22
+ */
23
+
24
+ /* ---------- Navbar ---------- */
25
+ .navbar {
26
+ border-bottom: 1px solid var(--jt-border);
27
+ box-shadow: none;
28
+ }
29
+ .navbar__link--active {
30
+ color: var(--jt-heading);
31
+ }
32
+
33
+ /* Configuration Reference / index cards (generated-index). Match the clean
34
+ "install box" look — near-page-bg fill + thin border instead of infima's dull
35
+ surface fill — with an accent-border hover. Full description (no one-line
36
+ `text--truncate` clamp) and equal card heights per row. */
37
+ .theme-doc-card-container {
38
+ height: 100%;
39
+ background: var(--jt-code-bg);
40
+ border: 1px solid var(--jt-border);
41
+ border-radius: 14px;
42
+ box-shadow: none;
43
+ transition:
44
+ border-color 0.15s ease,
45
+ background 0.15s ease,
46
+ transform 0.15s ease;
47
+ }
48
+ .theme-doc-card-container:hover {
49
+ background: var(--jt-surface2);
50
+ border-color: var(--jt-accent-border);
51
+ transform: translateY(-2px);
52
+ }
53
+ .theme-doc-card-description.text--truncate {
54
+ white-space: normal;
55
+ overflow: visible;
56
+ text-overflow: unset;
57
+ }
58
+
59
+ /* ---------- Backgrounds ---------- */
60
+ html,
61
+ body,
62
+ #__docusaurus,
63
+ .main-wrapper {
64
+ background: var(--ifm-background-color);
65
+ }
66
+ /* Sidebar container: match page background, clean 1px right border, and
67
+ ensure a long sidebar list scrolls without clipping the page footer. The
68
+ sticky positioning + bounded height come from Infima defaults; the explicit
69
+ overflow rule here defends against any inner container with overflow: hidden. */
70
+ .theme-doc-sidebar-container {
71
+ background: var(--ifm-background-color) !important;
72
+ border-right: 1px solid var(--jt-border) !important;
73
+ }
74
+ .theme-doc-sidebar-container > div,
75
+ .theme-doc-sidebar-container nav,
76
+ .theme-doc-sidebar-menu,
77
+ .menu,
78
+ .menu__list {
79
+ background: var(--ifm-background-color);
80
+ }
81
+ /* The sticky inner wrapper that holds the scrollable menu list. */
82
+ .theme-doc-sidebar-container > div:first-child {
83
+ height: 100%;
84
+ overflow-y: auto;
85
+ overscroll-behavior: contain;
86
+ }
87
+
88
+ /* ---------- Sidebar ---------- */
89
+ .menu {
90
+ font-size: 14px;
91
+ background: transparent;
92
+ padding: 16px 12px;
93
+ }
94
+ .menu__list .menu__list {
95
+ padding-left: 8px;
96
+ }
97
+ .menu__link {
98
+ border-radius: 8px;
99
+ color: var(--jt-muted);
100
+ line-height: 1.4;
101
+ }
102
+ .menu__link:hover {
103
+ background: var(--jt-surface2);
104
+ color: var(--jt-heading);
105
+ }
106
+ .menu__link--active:not(.menu__link--sublist) {
107
+ color: var(--jt-accent);
108
+ background: var(--jt-accent-soft);
109
+ font-weight: 600;
110
+ }
111
+ .menu__list-item-collapsible .menu__link {
112
+ font-weight: 600;
113
+ color: var(--jt-heading);
114
+ background: transparent;
115
+ }
116
+ .menu__list-item-collapsible .menu__link--active {
117
+ color: var(--jt-accent);
118
+ background: transparent;
119
+ }
120
+ .menu__list-item-collapsible:hover {
121
+ background: var(--jt-surface2);
122
+ border-radius: 8px;
123
+ }
124
+ .menu__caret:hover {
125
+ background: transparent;
126
+ }
127
+
128
+ /* ---------- Table of contents ---------- */
129
+ .table-of-contents__link--active {
130
+ color: var(--jt-accent);
131
+ font-weight: 600;
132
+ }
133
+ .table-of-contents .table-of-contents__link:hover {
134
+ color: var(--jt-heading);
135
+ }
136
+
137
+ /* ---------- Pagination ---------- */
138
+ .pagination-nav__link {
139
+ border: 1px solid var(--jt-border);
140
+ border-radius: 8px;
141
+ background: var(--jt-surface);
142
+ }
143
+ .pagination-nav__link:hover {
144
+ border-color: var(--jt-accent-border);
145
+ background: var(--jt-surface2);
146
+ }
147
+
148
+ /* ---------- Footer ---------- */
149
+ .footer,
150
+ .footer--dark {
151
+ --ifm-footer-background-color: var(--jt-bg2);
152
+ --ifm-footer-color: var(--jt-text);
153
+ --ifm-footer-link-color: var(--jt-text);
154
+ --ifm-footer-title-color: var(--jt-faint);
155
+ border-top: 1px solid var(--jt-border);
156
+ }
157
+ .footer__title {
158
+ font-size: 12px;
159
+ font-weight: 700;
160
+ letter-spacing: 0.08em;
161
+ text-transform: uppercase;
162
+ color: var(--jt-faint);
163
+ }
164
+ .footer__link-item {
165
+ color: var(--jt-text);
166
+ }
167
+ .footer__link-item:hover {
168
+ color: var(--jt-accent);
169
+ text-decoration: none;
170
+ }
171
+ .footer__copyright {
172
+ color: var(--jt-faint);
173
+ font-size: 13px;
174
+ text-align: left;
175
+ }
176
+ .footer__col {
177
+ font-size: 14px;
178
+ }
179
+ /* Hide the external-link "↗" SVG Docusaurus auto-appends to footer href links —
180
+ the design uses clean text labels only. The class is CSS-module hashed
181
+ (iconExternalLink_<hash>), so we target by attribute prefix. */
182
+ .footer__link-item svg,
183
+ .footer__link-item [class*="iconExternalLink"] {
184
+ display: none;
185
+ }
186
+
187
+ /* ---------- Code ----------
188
+ Prism is vsDark in both light & dark mode (to match the navy aesthetic),
189
+ so fenced code blocks must stay dark in BOTH themes — otherwise the pale
190
+ vsDark tokens wash out on a light background. Inline code (the `code` pills)
191
+ keeps the themed --ifm-code-background and stays readable. */
192
+ code {
193
+ background: var(--jt-code-bg);
194
+ border: 1px solid var(--jt-border);
195
+ border-radius: 4px;
196
+ padding: 1px 6px;
197
+ font-size: var(--ifm-code-font-size);
198
+ font-family: var(--ifm-font-family-monospace);
199
+ }
200
+ .theme-code-block,
201
+ div[class*="codeBlockContainer"],
202
+ pre[class*="language-"] {
203
+ border: 1px solid var(--jt-border);
204
+ border-radius: 12px;
205
+ background: #0c111b !important;
206
+ }
207
+ .theme-code-block code,
208
+ pre[class*="language-"] code {
209
+ background: transparent !important;
210
+ border: none !important;
211
+ color: #dfe5ee;
212
+ }
213
+ div[class*="codeBlockTitle"] {
214
+ background: #0a0e16 !important;
215
+ color: #94a1b4 !important;
216
+ border-bottom: 1px solid var(--jt-border);
217
+ }
218
+ [data-theme="light"] .theme-code-block,
219
+ [data-theme="light"] div[class*="codeBlockContainer"],
220
+ [data-theme="light"] pre[class*="language-"] {
221
+ border-color: rgba(12, 18, 28, 0.16);
222
+ box-shadow: 0 8px 24px -18px rgba(12, 18, 28, 0.5);
223
+ }
224
+
225
+ /* ---------- Markdown tables ----------
226
+ Rounded container, horizontal row dividers only (no heavy cell gridlines). */
227
+ .markdown table,
228
+ .theme-doc-markdown table,
229
+ article table {
230
+ display: table;
231
+ width: 100%;
232
+ border-collapse: separate;
233
+ border-spacing: 0;
234
+ margin: 22px 0;
235
+ border: 1px solid var(--jt-border);
236
+ border-radius: 12px;
237
+ overflow: hidden;
238
+ font-size: 14px;
239
+ }
240
+ .markdown table thead,
241
+ article table thead {
242
+ background: var(--jt-bg2);
243
+ }
244
+ .markdown table thead tr,
245
+ article table thead tr {
246
+ border: none;
247
+ background: transparent;
248
+ }
249
+ .markdown table th,
250
+ article table th {
251
+ text-align: left;
252
+ font-weight: 700;
253
+ font-size: 12px;
254
+ letter-spacing: 0.06em;
255
+ text-transform: uppercase;
256
+ color: var(--jt-faint);
257
+ border: none;
258
+ border-bottom: 1px solid var(--jt-border);
259
+ padding: 14px 18px;
260
+ }
261
+ .markdown table tbody tr,
262
+ article table tbody tr {
263
+ background: transparent !important;
264
+ border: none;
265
+ }
266
+ .markdown table td,
267
+ article table td {
268
+ border: none;
269
+ border-bottom: 1px solid var(--jt-border);
270
+ padding: 13px 18px;
271
+ vertical-align: middle;
272
+ color: var(--jt-text);
273
+ }
274
+ .markdown table tbody tr:last-child td,
275
+ article table tbody tr:last-child td {
276
+ border-bottom: none;
277
+ }
278
+ .markdown table td:first-child,
279
+ article table td:first-child {
280
+ font-weight: 600;
281
+ color: var(--jt-heading);
282
+ white-space: nowrap;
283
+ }
284
+ .markdown table td code,
285
+ .markdown table th code,
286
+ article table td code {
287
+ background: transparent !important;
288
+ border: none !important;
289
+ padding: 0 !important;
290
+ font-size: 13px;
291
+ }
292
+ .markdown table td:nth-child(2) code,
293
+ article table td:nth-child(2) code {
294
+ color: var(--jt-accent);
295
+ }
296
+ .markdown table td:nth-child(3),
297
+ article table td:nth-child(3) {
298
+ color: var(--jt-muted);
299
+ line-height: 1.9;
300
+ }
301
+ .markdown table td:nth-child(3) code,
302
+ article table td:nth-child(3) code {
303
+ color: var(--jt-muted);
304
+ }
305
+
306
+ /* ---------- Buttons ---------- */
307
+ .button--primary {
308
+ background: var(--jt-accent-fill);
309
+ border-color: var(--jt-accent-fill);
310
+ color: var(--jt-on-accent);
311
+ font-weight: 700;
312
+ }
313
+ .button--primary:hover {
314
+ background: var(--ifm-color-primary-light);
315
+ border-color: var(--ifm-color-primary-light);
316
+ color: var(--jt-on-accent);
317
+ }
318
+ .button--secondary {
319
+ background: transparent;
320
+ border-color: var(--jt-border2);
321
+ color: var(--jt-heading);
322
+ }
323
+
324
+ /* ============================================================
325
+ HARDENED DARK SURFACES
326
+ Infima's dark defaults are grey (#1b1b1d) and the footer is
327
+ slate. These explicit overrides force the navy palette even
328
+ if a default loads after this file.
329
+ ============================================================ */
330
+ [data-theme="dark"] {
331
+ --ifm-background-color: #0a0e16;
332
+ --ifm-background-surface-color: #111824;
333
+ --ifm-navbar-background-color: #0a0e16;
334
+ --ifm-footer-background-color: #0b101a;
335
+ }
336
+ [data-theme="dark"],
337
+ [data-theme="dark"] body,
338
+ [data-theme="dark"] #__docusaurus,
339
+ [data-theme="dark"] .main-wrapper,
340
+ [data-theme="dark"] .navbar,
341
+ [data-theme="dark"] main {
342
+ background-color: #0a0e16;
343
+ }
344
+ /* Footer follows the theme: soft grey panel in light mode, page-matching navy
345
+ in dark mode. Selectors are theme-scoped so the config's `style: 'dark'`
346
+ (which adds .footer--dark in BOTH modes) can't drag the light-mode footer
347
+ into a dark slate. */
348
+ html[data-theme="light"] .footer,
349
+ html[data-theme="light"] .footer--dark {
350
+ background-color: var(--jt-bg2) !important;
351
+ border-top: 1px solid var(--jt-border);
352
+ }
353
+ html[data-theme="light"] .footer__link-item {
354
+ color: var(--jt-text) !important;
355
+ }
356
+ html[data-theme="light"] .footer__title {
357
+ color: var(--jt-faint) !important;
358
+ }
359
+ html[data-theme="light"] .footer__copyright {
360
+ color: var(--jt-faint) !important;
361
+ }
362
+ html[data-theme="dark"] .footer,
363
+ html[data-theme="dark"] .footer--dark {
364
+ background-color: #0a0e16 !important;
365
+ border-top: 1px solid var(--jt-border);
366
+ }
367
+ html[data-theme="dark"] .footer__link-item {
368
+ color: var(--jt-text) !important;
369
+ }
370
+ html[data-theme="dark"] .footer__title {
371
+ color: var(--jt-faint) !important;
372
+ }
373
+ html[data-theme="dark"] .footer__copyright {
374
+ color: var(--jt-faint) !important;
375
+ }
376
+ .footer__link-item:hover {
377
+ color: var(--jt-accent) !important;
378
+ }
@@ -0,0 +1,6 @@
1
+ import type { BuildOptions, BuildResult } from 'esbuild'
2
+
3
+ export declare function buildCode(
4
+ entryPoints?: string[],
5
+ options?: Partial<BuildOptions>
6
+ ): Promise<BuildResult | undefined>
@@ -0,0 +1,102 @@
1
+ import * as fs from 'node:fs/promises'
2
+ import * as path from 'node:path'
3
+ import * as esbuild from 'esbuild'
4
+ import { nodeExternalsPlugin } from 'esbuild-node-externals'
5
+
6
+ // EXAMPLE ENTRY POINTS
7
+ // const folders = await getEntrypointFolders('src')
8
+ // const libEntryPointsArrays = await Promise.all(folders.map((folder) => getEntryPoints(folder)))
9
+ // const libEntryPoints = libEntryPointsArrays.flat()
10
+ // const allEntryPoints = [
11
+ // 'src/index.ts', // Main entry point
12
+ // ...libEntryPoints,
13
+ // // ...exampleEntryPoints,
14
+ // ]
15
+
16
+ export async function buildCode(entryPoints = []) {
17
+ const isProduction = process.env['NODE_ENV'] === 'production'
18
+ console.log(`Building...${isProduction ? '(production)' : '(development)'}`)
19
+ console.log('All entry points:', entryPoints)
20
+ if (entryPoints && entryPoints.length > 0) {
21
+ const buildPrefs = {
22
+ entryPoints: entryPoints, // Array of entry points to build
23
+ outdir: 'dist', // Output directory
24
+ platform: 'node', // Use 'browser' for browser builds
25
+ // outbase: 'src', // Base directory for output files
26
+ sourcemap: !isProduction, // Generate sourcemaps in development mode
27
+ minify: isProduction, // Minify in production mode
28
+ logLevel: 'info', // Set log level to 'info'
29
+ splitting: true, // Enable code splitting
30
+ format: 'esm', // Use 'cjs' as 'cjs' for CommonJS format
31
+ target: ['esnext'], // Specify ECMAScript target version
32
+ bundle: true, // Bundle all dependencies into the output
33
+ chunkNames: 'chunks/[name]-[hash]', // Define chunk naming pattern
34
+ // external: ['react', 'react-dom'], // Add other external dependencies here
35
+ // plugins: [
36
+ // {
37
+ // name: 'make-all-packages-external',
38
+ // setup(build) {
39
+ // let filter = /^[^.\/]|^\.[^.\/]|^\.\.[^\/]/; // Must not start with "/" or "./" or "../"
40
+ // build.onResolve({ filter }, args => ({ path: args.path, external: true }));
41
+ // },
42
+ // },
43
+ // ],
44
+ plugins: [nodeExternalsPlugin()],
45
+ }
46
+ await esbuild.build(buildPrefs)
47
+ } else {
48
+ console.log('No entry points provided. Skipping build.')
49
+ }
50
+ }
51
+ /**
52
+ * Returns a list of entry point files in a directory.
53
+ *
54
+ * Scans the given directory and returns all files that:
55
+ * - End with the specified file extension (default: ".ts")
56
+ * - Are not test files (by default, excludes files containing ".test.")
57
+ *
58
+ * @param {string} dir - The directory to search (e.g., 'src')
59
+ * @param {string} [fileExtension='.ts'] - The file extension to match (e.g., '.ts', '.tsx')
60
+ * @param {boolean} [excludeTestFiles=true] - Whether to exclude test files (files containing '.test.')
61
+ * @returns {Promise<string[]>} - Array of entry point file paths (e.g., ['src/arrays/index.ts', ...])
62
+ */
63
+ export async function getEntryPoints(dir, fileExtension = '.ts', excludeTestFiles = true) {
64
+ try {
65
+ const entries = await fs.readdir(dir, { withFileTypes: true })
66
+ return entries
67
+ .filter(
68
+ (entry) =>
69
+ entry.isFile() &&
70
+ entry.name.endsWith(fileExtension) &&
71
+ (!excludeTestFiles || !entry.name.includes('.test.'))
72
+ )
73
+ .map((entry) => path.join(dir, entry.name))
74
+ } catch (error) {
75
+ // @ts-expect-error
76
+ if (error.code === 'ENOENT') {
77
+ console.warn(`Directory ${dir} does not exist.`)
78
+ return []
79
+ }
80
+ throw error
81
+ }
82
+ }
83
+ /**
84
+ * Returns a list of all subdirectories in the given directory that contain an index.ts file.
85
+ * @param {string} dir - The directory to search (e.g., 'src')
86
+ * @returns {Promise<string[]>} - Array of entrypoint folder paths (e.g., ['src/arrays', 'src/strings'])
87
+ */
88
+ export async function getEntrypointFolders(dir) {
89
+ const entries = await fs.readdir(dir, { withFileTypes: true })
90
+ const folders = entries.filter((e) => e.isDirectory())
91
+ const entryFolders = []
92
+ for (const folder of folders) {
93
+ const indexPath = path.join(dir, folder.name, 'index.ts')
94
+ try {
95
+ await fs.access(indexPath)
96
+ entryFolders.push(path.join(dir, folder.name))
97
+ } catch {
98
+ // index.ts does not exist, skip
99
+ }
100
+ }
101
+ return entryFolders
102
+ }
@@ -0,0 +1,6 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ declare const config: Linter.Config[]
4
+ export default config
5
+
6
+ export declare const restrictEnvAccess: Linter.Config[]
@@ -0,0 +1,122 @@
1
+ /// <reference types="./types.d.ts" />
2
+
3
+ import eslint from '@eslint/js'
4
+ import tsPlugin from '@typescript-eslint/eslint-plugin'
5
+ import importPlugin from 'eslint-plugin-import'
6
+ import jestPlugin from 'eslint-plugin-jest'
7
+ import tseslint from 'typescript-eslint'
8
+
9
+ // import path from 'path';
10
+ // import url from 'url';
11
+
12
+ // const __filename = url.fileURLToPath(import.meta.url);
13
+ // const __dirname = path.dirname(__filename);
14
+
15
+ /**
16
+ * All packages that leverage t3-env should use this rule
17
+ */
18
+ export const restrictEnvAccess = tseslint.config({
19
+ files: ['**/*.js', '**/*.ts', '**/*.tsx'],
20
+ rules: {
21
+ 'no-restricted-properties': [
22
+ 'error',
23
+ {
24
+ object: 'process',
25
+ property: 'env',
26
+ message: "Use `import { env } from '~/env'` instead to ensure validated types.",
27
+ },
28
+ ],
29
+ 'no-restricted-imports': [
30
+ 'error',
31
+ {
32
+ name: 'process',
33
+ importNames: ['env'],
34
+ message: "Use `import { env } from '~/env'` instead to ensure validated types.",
35
+ },
36
+ ],
37
+ },
38
+ })
39
+
40
+ export default tseslint.config(
41
+ {
42
+ // Globally ignored files
43
+ ignores: [
44
+ //
45
+ '**/*.config.js',
46
+ '.turbo',
47
+ 'dist',
48
+ 'build',
49
+ '.react-email',
50
+ 'not-used',
51
+ 'out', //for next js static builds
52
+ '.next',
53
+ 'pnpm-lock.yaml',
54
+ 'node_modules',
55
+ '.react-email',
56
+ ],
57
+ },
58
+ {
59
+ files: ['**/*.js', '**/*.ts', '**/*.tsx'],
60
+ plugins: {
61
+ import: importPlugin,
62
+ '@typescript-eslint': tsPlugin,
63
+ jest: jestPlugin,
64
+ },
65
+ extends: [
66
+ //
67
+ eslint.configs.recommended,
68
+ ...tseslint.configs.recommended,
69
+ ...tseslint.configs.recommendedTypeChecked,
70
+ ...tseslint.configs.stylisticTypeChecked,
71
+ // ...jestPlugin.configs['flat/recommended'],
72
+ // turbo,
73
+ // vitest,
74
+ // airbnb,
75
+ // "eslint:recommended",
76
+ // 'airbnb-typescript',
77
+ // 'plugin:jest/recommended',
78
+ //"plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
79
+ // eslintConfigPrettier,
80
+ ],
81
+ rules: {
82
+ 'no-console': 'warn',
83
+ '@typescript-eslint/no-unsafe-assignment': 'error',
84
+ '@typescript-eslint/no-explicit-any': 'off',
85
+ '@typescript-eslint/consistent-type-definitions': 'off',
86
+ 'tailwindcss/no-custom-classname': 'off',
87
+ '@typescript-eslint/no-unsafe-return': 'off',
88
+ '@typescript-eslint/no-unsafe-call': 'off',
89
+ '@typescript-eslint/no-unsafe-member-access': 'off',
90
+ // "jest/no-disabled-tests": "warn",
91
+ // "jest/no-focused-tests": "error",
92
+ // "jest/no-identical-title": "error",
93
+ // "jest/prefer-to-have-length": "warn",
94
+ // "jest/valid-expect": "error"
95
+ //
96
+ '@typescript-eslint/no-unused-vars': [
97
+ 'error',
98
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
99
+ ],
100
+ '@typescript-eslint/consistent-type-imports': [
101
+ 'warn',
102
+ { prefer: 'type-imports', fixStyle: 'separate-type-imports' },
103
+ ],
104
+ '@typescript-eslint/no-misused-promises': [2, { checksVoidReturn: { attributes: false } }],
105
+ '@typescript-eslint/no-unnecessary-condition': [
106
+ 'error',
107
+ {
108
+ allowConstantLoopConditions: true,
109
+ },
110
+ ],
111
+ '@typescript-eslint/no-non-null-assertion': 'error',
112
+ 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
113
+ },
114
+ },
115
+ {
116
+ linterOptions: { reportUnusedDisableDirectives: true },
117
+ // languageOptions: { parserOptions: { project: ['./tsconfig.json', './**/*/tsconfig.json'] } },
118
+ languageOptions: {
119
+ parserOptions: { project: true }, //, tsconfigRootDir: __dirname
120
+ },
121
+ }
122
+ )
@@ -0,0 +1,4 @@
1
+ import type { Linter } from 'eslint'
2
+
3
+ declare const config: Linter.Config[]
4
+ export default config
@@ -0,0 +1,22 @@
1
+ import nextPlugin from '@next/eslint-plugin-next'
2
+
3
+ /** @type {Awaited<import('typescript-eslint').Config>} */
4
+ export default [
5
+ {
6
+ files: ['**/*.ts', '**/*.tsx'],
7
+ plugins: {
8
+ '@next/next': nextPlugin,
9
+ },
10
+ rules: {
11
+ ...nextPlugin.configs.recommended.rules,
12
+ ...nextPlugin.configs['core-web-vitals'].rules,
13
+ // TypeError: context.getAncestors is not a function
14
+ '@next/next/no-duplicate-head': 'off',
15
+ '@next/next/no-page-custom-font': 'off',
16
+ //
17
+ '@next/next/no-img-element': 'off',
18
+ '@next/next/no-html-link-for-pages': 'off',
19
+ 'react/jsx-key': 'off',
20
+ },
21
+ },
22
+ ]
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Since the ecosystem hasn't fully migrated to ESLint's new FlatConfig system yet,
3
+ * we "need" to type some of the plugins manually :(
4
+ */
5
+
6
+ declare module '@eslint/js' {
7
+ // Why the hell doesn't eslint themselves export their types?
8
+ import type { Linter } from 'eslint'
9
+
10
+ export const configs: {
11
+ readonly recommended: { readonly rules: Readonly<Linter.RulesRecord> }
12
+ readonly all: { readonly rules: Readonly<Linter.RulesRecord> }
13
+ }
14
+ }
15
+
16
+ declare module 'eslint-plugin-import' {
17
+ import type { Linter, Rule } from 'eslint'
18
+
19
+ export const configs: {
20
+ recommended: { rules: Linter.RulesRecord }
21
+ }
22
+ export const rules: Record<string, Rule.RuleModule>
23
+ }
24
+
25
+ declare module 'eslint-plugin-react' {
26
+ import type { Linter, Rule } from 'eslint'
27
+
28
+ export const configs: {
29
+ recommended: { rules: Linter.RulesRecord }
30
+ all: { rules: Linter.RulesRecord }
31
+ 'jsx-runtime': { rules: Linter.RulesRecord }
32
+ }
33
+ export const rules: Record<string, Rule.RuleModule>
34
+ }
35
+
36
+ declare module 'eslint-plugin-react-hooks' {
37
+ import type { Linter, Rule } from 'eslint'
38
+
39
+ export const configs: {
40
+ recommended: {
41
+ rules: {
42
+ 'rules-of-hooks': Linter.RuleEntry
43
+ 'exhaustive-deps': Linter.RuleEntry
44
+ }
45
+ }
46
+ }
47
+ export const rules: Record<string, Rule.RuleModule>
48
+ }
49
+
50
+ declare module '@next/eslint-plugin-next' {
51
+ import type { Linter, Rule } from 'eslint'
52
+
53
+ export const configs: {
54
+ recommended: { rules: Linter.RulesRecord }
55
+ 'core-web-vitals': { rules: Linter.RulesRecord }
56
+ }
57
+ export const rules: Record<string, Rule.RuleModule>
58
+ }