create-newt-app 0.27.0 → 0.29.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 (25) hide show
  1. package/dist/index.d.ts +5 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +286 -109
  4. package/dist/index.js.map +1 -1
  5. package/dist/static/anti-slop/static/LICENSE +21 -0
  6. package/dist/static/anti-slop/static/index.ts +41 -0
  7. package/dist/static/anti-slop/static/rules/no-chained-type-assertions.ts +77 -0
  8. package/dist/static/anti-slop/static/rules/no-conditional-empty-object-spread.ts +49 -0
  9. package/dist/static/anti-slop/static/rules/no-known-value-widening.ts +247 -0
  10. package/dist/static/anti-slop/static/rules/no-module-mocking.ts +91 -0
  11. package/dist/static/anti-slop/static/rules/no-object-parameters.ts +126 -0
  12. package/dist/static/anti-slop/static/rules/no-reflect-apply.ts +28 -0
  13. package/dist/static/anti-slop/static/rules/no-reflect-get.ts +28 -0
  14. package/dist/static/anti-slop/static/rules/no-runtime-typeof.ts +67 -0
  15. package/dist/static/anti-slop/static/rules/no-shape-in-symbol-names.ts +39 -0
  16. package/dist/static/anti-slop/static/rules/no-unknown-parameters.ts +83 -0
  17. package/dist/static/anti-slop/static/rules/no-unknown-returns.ts +115 -0
  18. package/dist/static/anti-slop/static/rules/no-unknown-type-aliases.ts +70 -0
  19. package/dist/static/anti-slop/static/rules/no-unsafe-dictionary-type.ts +134 -0
  20. package/dist/static/anti-slop/static/rules/no-widen-then-assert.ts +366 -0
  21. package/dist/static/anti-slop/static/rules/require-safety-comment-for-type-assertion.ts +62 -0
  22. package/dist/static/anti-slop/static/shared/dictionary-types.ts +502 -0
  23. package/dist/static/anti-slop/static/shared/lexical-type-parameters.ts +61 -0
  24. package/dist/static/anti-slop/static/shared/reflect-method.ts +35 -0
  25. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import ejs from "ejs";
10
10
  import { existsSync, promises } from "fs";
11
11
  import path from "path";
12
12
  //#region package.json
13
- var version = "0.27.0";
13
+ var version = "0.29.0";
14
14
  var engines = { "node": ">=24.0.0" };
15
15
  //#endregion
16
16
  //#region src/templates/root/index.ts
@@ -110,10 +110,12 @@ dist
110
110
  "inputs": ["$TURBO_DEFAULT$", ".env*"],
111
111
  "outputs": [".next/**", "!.next/cache/**"]
112
112
  },
113
- "lint": {
113
+ <% if (linter === "oxc") { %> "typecheck": {
114
+ "dependsOn": ["^build"]
115
+ },<% } else { %> "lint": {
114
116
  "dependsOn": ["^lint"],
115
117
  "env": ["NODE_ENV"]
116
- },
118
+ },<% } %>
117
119
  "test": {
118
120
  "dependsOn": ["^build"],
119
121
  "outputs": ["coverage/**"]
@@ -737,7 +739,7 @@ export const authClient: ReturnType<typeof createAuthClient> = createAuthClient(
737
739
  };
738
740
  //#endregion
739
741
  //#region src/templates/api/index.ts
740
- const api$2 = { templates: [
742
+ const api$1 = { templates: [
741
743
  {
742
744
  when: (s) => !s.nestDiOnly && s.deployment !== "spa" && s.deployment !== "custom-server",
743
745
  filename: "apps/api/package.json",
@@ -1246,7 +1248,7 @@ const dbPostgres = { templates: [
1246
1248
  ] };
1247
1249
  //#endregion
1248
1250
  //#region src/templates/ui/index.ts
1249
- const ui$2 = { templates: [
1251
+ const ui$1 = { templates: [
1250
1252
  {
1251
1253
  filename: "packages/ui/package.json",
1252
1254
  template: `{
@@ -1499,6 +1501,7 @@ const versions = {
1499
1501
  "@nestjs/serve-static": "^5.0.0",
1500
1502
  "@nestjs/testing": "^11.0.1",
1501
1503
  "@next/eslint-plugin-next": "^16.3.0",
1504
+ "@oxlint/plugins": "^1.74.0",
1502
1505
  "@shadcn/react": "^0.2.1",
1503
1506
  "@swc/core": "^1.10.0",
1504
1507
  "@tailwindcss/postcss": "^4.2.1",
@@ -1514,57 +1517,57 @@ const versions = {
1514
1517
  "@types/react-dom": "19.2.3",
1515
1518
  "@types/supertest": "^6.0.2",
1516
1519
  "@vitest/coverage-v8": "^4.1.10",
1517
- "auth": "^1.5.5",
1520
+ auth: "^1.5.5",
1518
1521
  "better-auth": "^1.2.8",
1519
1522
  "better-sqlite3": "^12.11.1",
1520
1523
  "class-variance-authority": "^0.7.1",
1521
- "clsx": "^2.1.1",
1522
- "cmdk": "^1.1.1",
1524
+ clsx: "^2.1.1",
1525
+ cmdk: "^1.1.1",
1523
1526
  "date-fns": "^4.2.1",
1524
- "dotenv": "^17.3.1",
1527
+ dotenv: "^17.3.1",
1525
1528
  "dotenv-cli": "^11.0.0",
1526
1529
  "embla-carousel-react": "^8.6.0",
1527
- "eslint": "^9.39.1",
1530
+ eslint: "^9.39.1",
1528
1531
  "eslint-config-prettier": "^10.1.1",
1529
1532
  "eslint-plugin-only-warn": "^1.1.0",
1530
1533
  "eslint-plugin-react": "^7.37.5",
1531
1534
  "eslint-plugin-react-hooks": "^5.2.0",
1532
1535
  "eslint-plugin-turbo": "^2.7.1",
1533
- "globals": "^16.5.0",
1536
+ globals: "^16.5.0",
1534
1537
  "input-otp": "^1.4.2",
1535
- "jest": "^30.0.0",
1536
- "kysely": "^0.28.2",
1538
+ jest: "^30.0.0",
1539
+ kysely: "^0.28.2",
1537
1540
  "lucide-react": "^1.16.0",
1538
- "next": "16.3.0",
1541
+ next: "16.3.0",
1539
1542
  "next-themes": "^0.4.6",
1540
- "oxfmt": "^0.59.0",
1541
- "oxlint": "^1.74.0",
1542
- "pg": "^8.14.1",
1543
- "prettier": "^3.7.4",
1544
- "react": "^19.2.4",
1543
+ oxfmt: "^0.59.0",
1544
+ oxlint: "^1.74.0",
1545
+ pg: "^8.14.1",
1546
+ prettier: "^3.7.4",
1547
+ react: "^19.2.4",
1545
1548
  "react-day-picker": "^10.0.1",
1546
1549
  "react-dom": "^19.2.4",
1547
1550
  "react-resizable-panels": "^4.11.1",
1548
- "recharts": "^3.8.0",
1551
+ recharts: "^3.8.0",
1549
1552
  "reflect-metadata": "^0.2.2",
1550
- "rxjs": "^7.8.1",
1551
- "shadcn": "^4.7.0",
1552
- "sonner": "^2.0.7",
1553
+ rxjs: "^7.8.1",
1554
+ shadcn: "^4.7.0",
1555
+ sonner: "^2.0.7",
1553
1556
  "source-map-support": "^0.5.21",
1554
- "supertest": "^7.0.0",
1557
+ supertest: "^7.0.0",
1555
1558
  "tailwind-merge": "^3.6.0",
1556
- "tailwindcss": "^4.2.1",
1559
+ tailwindcss: "^4.2.1",
1557
1560
  "ts-jest": "^29.2.5",
1558
1561
  "ts-loader": "^9.5.2",
1559
1562
  "ts-node": "^10.9.2",
1560
1563
  "tsconfig-paths": "^4.2.0",
1561
- "tsx": "^4.19.4",
1562
- "turbo": "^2.8.16",
1564
+ tsx: "^4.19.4",
1565
+ turbo: "^2.8.16",
1563
1566
  "tw-animate-css": "^1.4.0",
1564
- "typescript": "6.0.2",
1567
+ typescript: "6.0.2",
1565
1568
  "typescript-eslint": "^8.50.0",
1566
1569
  "unplugin-swc": "^1.5.9",
1567
- "vitest": "^4.1.10"
1570
+ vitest: "^4.1.10"
1568
1571
  };
1569
1572
  //#endregion
1570
1573
  //#region src/templates/shadcn-ui/index.ts
@@ -3048,7 +3051,6 @@ function Calendar({
3048
3051
  ...classNames,
3049
3052
  }}
3050
3053
  components={{
3051
- // eslint-disable-next-line react/prop-types
3052
3054
  Root: ({ className, rootRef, ...props }) => {
3053
3055
  return (
3054
3056
  <div
@@ -3059,7 +3061,6 @@ function Calendar({
3059
3061
  />
3060
3062
  )
3061
3063
  },
3062
- // eslint-disable-next-line react/prop-types
3063
3064
  Chevron: ({ className, orientation, ...props }) => {
3064
3065
  if (orientation === "left") {
3065
3066
  return (
@@ -3881,7 +3882,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
3881
3882
  <CheckboxPrimitive.Root
3882
3883
  data-slot="checkbox"
3883
3884
  className={cn(
3884
- "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
3885
+ "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary",
3885
3886
  className
3886
3887
  )}
3887
3888
  {...props}
@@ -5597,7 +5598,7 @@ function FieldLabel({
5597
5598
  <Label
5598
5599
  data-slot="field-label"
5599
5600
  className={cn(
5600
- "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
5601
+ "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-muted/50 has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10",
5601
5602
  "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
5602
5603
  className
5603
5604
  )}
@@ -7285,7 +7286,7 @@ function RadioGroupItem({ className, ...props }: RadioPrimitive.Root.Props) {
7285
7286
  <RadioPrimitive.Root
7286
7287
  data-slot="radio-group-item"
7287
7288
  className={cn(
7288
- "group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary",
7289
+ "group/radio-group-item peer relative flex aspect-square size-4 shrink-0 rounded-full border border-input outline-none group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary",
7289
7290
  className
7290
7291
  )}
7291
7292
  {...props}
@@ -8665,7 +8666,7 @@ function Switch({
8665
8666
  data-slot="switch"
8666
8667
  data-size={size}
8667
8668
  className={cn(
8668
- "peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
8669
+ "peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none group-has-[:focus-visible]/field-label:border-transparent group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
8669
8670
  className
8670
8671
  )}
8671
8672
  {...props}
@@ -10027,6 +10028,7 @@ export const config = [
10027
10028
  ...pluginReactHooks.configs.recommended.rules,
10028
10029
  // React scope no longer necessary with new JSX transform.
10029
10030
  "react/react-in-jsx-scope": "off",
10031
+ "react/prop-types": "off",
10030
10032
  },
10031
10033
  },
10032
10034
  ];`
@@ -10092,16 +10094,13 @@ export default config;`
10092
10094
  //#region src/templates/root/templates/prettierrc.ts
10093
10095
  var prettierrc_default = {
10094
10096
  filename: ".prettierrc",
10095
- template: `{
10096
- "singleQuote": true,
10097
- "trailingComma": "all"
10098
- }`
10097
+ template: `{}`
10099
10098
  };
10100
10099
  //#endregion
10101
10100
  //#region src/templates/eslint-config/index.ts
10102
10101
  const web$1 = "apps/web";
10103
- const api$1 = "apps/api";
10104
- const ui$1 = "packages/ui";
10102
+ const api = "apps/api";
10103
+ const ui = "packages/ui";
10105
10104
  const root$1 = "";
10106
10105
  const eslintConfig = {
10107
10106
  templates: [
@@ -10129,49 +10128,49 @@ const eslintConfig = {
10129
10128
  },
10130
10129
  {
10131
10130
  package: "@eslint/eslintrc",
10132
- module: api$1,
10131
+ module: api,
10133
10132
  version: versions["@eslint/eslintrc"],
10134
10133
  dev: true
10135
10134
  },
10136
10135
  {
10137
10136
  package: "@eslint/js",
10138
- module: api$1,
10137
+ module: api,
10139
10138
  version: versions["@eslint/js"],
10140
10139
  dev: true
10141
10140
  },
10142
10141
  {
10143
10142
  package: "eslint",
10144
- module: api$1,
10143
+ module: api,
10145
10144
  version: versions.eslint,
10146
10145
  dev: true
10147
10146
  },
10148
10147
  {
10149
10148
  package: "eslint-config-prettier",
10150
- module: api$1,
10149
+ module: api,
10151
10150
  version: versions["eslint-config-prettier"],
10152
10151
  dev: true
10153
10152
  },
10154
10153
  {
10155
10154
  package: "globals",
10156
- module: api$1,
10155
+ module: api,
10157
10156
  version: versions.globals,
10158
10157
  dev: true
10159
10158
  },
10160
10159
  {
10161
10160
  package: "typescript-eslint",
10162
- module: api$1,
10161
+ module: api,
10163
10162
  version: versions["typescript-eslint"],
10164
10163
  dev: true
10165
10164
  },
10166
10165
  {
10167
10166
  package: "eslint",
10168
- module: ui$1,
10167
+ module: ui,
10169
10168
  version: versions.eslint,
10170
10169
  dev: true
10171
10170
  },
10172
10171
  {
10173
10172
  package: "@<%= projectName %>/eslint-config",
10174
- module: ui$1,
10173
+ module: ui,
10175
10174
  version: "workspace:*",
10176
10175
  dev: true
10177
10176
  },
@@ -10194,22 +10193,22 @@ const eslintConfig = {
10194
10193
  script: "eslint --max-warnings 0 && next typegen && tsc --noEmit"
10195
10194
  },
10196
10195
  {
10197
- module: api$1,
10196
+ module: api,
10198
10197
  name: "lint",
10199
10198
  script: `eslint "src/**/*.ts" --fix`
10200
10199
  },
10201
10200
  {
10202
- module: api$1,
10201
+ module: api,
10203
10202
  name: "lint:check",
10204
10203
  script: `eslint "src/**/*.ts"`
10205
10204
  },
10206
10205
  {
10207
- module: ui$1,
10206
+ module: ui,
10208
10207
  name: "lint",
10209
10208
  script: "eslint . --fix"
10210
10209
  },
10211
10210
  {
10212
- module: ui$1,
10211
+ module: ui,
10213
10212
  name: "lint:check",
10214
10213
  script: "eslint . --max-warnings 0"
10215
10214
  },
@@ -10233,7 +10232,48 @@ var oxlintrc_default = {
10233
10232
  "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
10234
10233
  "categories": {
10235
10234
  "correctness": "error"
10236
- }
10235
+ }<% if (antiSlop) { %>,
10236
+ "ignorePatterns": ["tools/oxlint/anti-slop/**"],
10237
+ "jsPlugins": [{ "name": "anti-slop", "specifier": "./tools/oxlint/anti-slop/index.ts" }],
10238
+ "rules": {
10239
+ "anti-slop/no-chained-type-assertions": "error",
10240
+ "anti-slop/no-conditional-empty-object-spread": "error",
10241
+ "anti-slop/no-known-value-widening": "error",
10242
+ "anti-slop/no-module-mocking": "error",
10243
+ "anti-slop/no-object-parameters": "error",
10244
+ "anti-slop/no-reflect-apply": "error",
10245
+ "anti-slop/no-reflect-get": "error",
10246
+ "anti-slop/no-runtime-typeof": "error",
10247
+ "anti-slop/no-shape-in-symbol-names": "error",
10248
+ "anti-slop/no-unknown-parameters": "error",
10249
+ "anti-slop/no-unknown-returns": "error",
10250
+ "anti-slop/no-unknown-type-aliases": "error",
10251
+ "anti-slop/no-unsafe-dictionary-type": "error",
10252
+ "anti-slop/no-widen-then-assert": "error",
10253
+ "anti-slop/require-safety-comment-for-type-assertion": "error"
10254
+ }<% if (shadcn) { %>,
10255
+ "overrides": [
10256
+ {
10257
+ "files": ["packages/ui/src/components/**"],
10258
+ "rules": {
10259
+ "anti-slop/no-chained-type-assertions": "off",
10260
+ "anti-slop/no-conditional-empty-object-spread": "off",
10261
+ "anti-slop/no-known-value-widening": "off",
10262
+ "anti-slop/no-module-mocking": "off",
10263
+ "anti-slop/no-object-parameters": "off",
10264
+ "anti-slop/no-reflect-apply": "off",
10265
+ "anti-slop/no-reflect-get": "off",
10266
+ "anti-slop/no-runtime-typeof": "off",
10267
+ "anti-slop/no-shape-in-symbol-names": "off",
10268
+ "anti-slop/no-unknown-parameters": "off",
10269
+ "anti-slop/no-unknown-returns": "off",
10270
+ "anti-slop/no-unknown-type-aliases": "off",
10271
+ "anti-slop/no-unsafe-dictionary-type": "off",
10272
+ "anti-slop/no-widen-then-assert": "off",
10273
+ "anti-slop/require-safety-comment-for-type-assertion": "off"
10274
+ }
10275
+ }
10276
+ ]<% } %><% } %>
10237
10277
  }`
10238
10278
  };
10239
10279
  //#endregion
@@ -10242,85 +10282,187 @@ var oxfmtrc_default = {
10242
10282
  filename: ".oxfmtrc.json",
10243
10283
  template: `{
10244
10284
  "$schema": "./node_modules/oxfmt/configuration_schema.json",
10245
- "ignorePatterns": []
10285
+ "ignorePatterns": [<% if (antiSlop) { %>"tools/oxlint/anti-slop/"<% } %>]
10246
10286
  }`
10247
10287
  };
10248
10288
  //#endregion
10249
10289
  //#region src/templates/oxc/index.ts
10250
10290
  const web = "apps/web";
10251
- const api = "apps/api";
10252
- const ui = "packages/ui";
10253
10291
  const root = "";
10254
10292
  const oxc = {
10255
10293
  templates: [oxlintrc_default, oxfmtrc_default],
10256
- packages: [
10294
+ packages: [{
10295
+ package: "oxlint",
10296
+ module: root,
10297
+ version: versions.oxlint,
10298
+ dev: true
10299
+ }, {
10300
+ package: "oxfmt",
10301
+ module: root,
10302
+ version: versions.oxfmt,
10303
+ dev: true
10304
+ }],
10305
+ scripts: [
10257
10306
  {
10258
- package: "oxlint",
10259
10307
  module: web,
10260
- version: versions.oxlint,
10261
- dev: true
10308
+ name: "typecheck",
10309
+ script: "next typegen && tsc --noEmit"
10262
10310
  },
10263
10311
  {
10264
- package: "oxlint",
10265
- module: api,
10266
- version: versions.oxlint,
10267
- dev: true
10312
+ module: root,
10313
+ name: "lint",
10314
+ script: "oxlint --fix"
10268
10315
  },
10269
10316
  {
10270
- package: "oxlint",
10271
- module: ui,
10272
- version: versions.oxlint,
10273
- dev: true
10317
+ module: root,
10318
+ name: "typecheck",
10319
+ script: "turbo run typecheck"
10274
10320
  },
10275
10321
  {
10276
- package: "oxfmt",
10277
10322
  module: root,
10278
- version: versions.oxfmt,
10279
- dev: true
10323
+ name: "lint:check",
10324
+ script: "oxlint"
10325
+ },
10326
+ {
10327
+ module: root,
10328
+ name: "format",
10329
+ script: "oxfmt"
10330
+ },
10331
+ {
10332
+ module: root,
10333
+ name: "format:check",
10334
+ script: "oxfmt --check"
10280
10335
  }
10281
- ],
10282
- scripts: [
10336
+ ]
10337
+ };
10338
+ //#endregion
10339
+ //#region src/templates/anti-slop/templates/plugin-package-json.ts
10340
+ var plugin_package_json_default = {
10341
+ filename: "tools/oxlint/anti-slop/package.json",
10342
+ template: `{
10343
+ "type": "module"
10344
+ }`
10345
+ };
10346
+ //#endregion
10347
+ //#region src/templates/anti-slop/templates/plugin-readme.ts
10348
+ var plugin_readme_default = {
10349
+ filename: "tools/oxlint/anti-slop/README.md",
10350
+ template: `# anti-slop
10351
+
10352
+ Oxlint rules that reject low-evidence TypeScript patterns, vendored from
10353
+ [dmmulroy/anti-slop](https://github.com/dmmulroy/anti-slop) at \`6d538555cb15\` (MIT, see LICENSE).
10354
+
10355
+ Upstream ships these to be vendored rather than depended on, so these files are
10356
+ yours: read them, change the messages, delete the rules you disagree with.
10357
+
10358
+ \`.oxlintrc.json\` registers the plugin and turns every rule on as an error.
10359
+ Turn one off there:
10360
+
10361
+ \`\`\`json
10362
+ {
10363
+ "rules": {
10364
+ "anti-slop/no-runtime-typeof": "off"
10365
+ }
10366
+ }
10367
+ \`\`\`
10368
+
10369
+ Vendored shadcn components under \`packages/ui/src/components\` are exempt, since
10370
+ they are upstream code you re-pull rather than write.
10371
+ `
10372
+ };
10373
+ //#endregion
10374
+ //#region src/templates/anti-slop/index.ts
10375
+ const plugin = "tools/oxlint/anti-slop";
10376
+ const antiSlop = {
10377
+ templates: [plugin_package_json_default, plugin_readme_default],
10378
+ staticFiles: [
10283
10379
  {
10284
- module: web,
10285
- name: "lint",
10286
- script: "oxlint --fix && next typegen && tsc --noEmit"
10380
+ src: "anti-slop/static/LICENSE",
10381
+ filename: `${plugin}/LICENSE`
10287
10382
  },
10288
10383
  {
10289
- module: web,
10290
- name: "lint:check",
10291
- script: "oxlint && next typegen && tsc --noEmit"
10384
+ src: "anti-slop/static/index.ts",
10385
+ filename: `${plugin}/index.ts`
10292
10386
  },
10293
10387
  {
10294
- module: api,
10295
- name: "lint",
10296
- script: "oxlint src --fix"
10388
+ src: "anti-slop/static/rules/no-chained-type-assertions.ts",
10389
+ filename: `${plugin}/rules/no-chained-type-assertions.ts`
10297
10390
  },
10298
10391
  {
10299
- module: api,
10300
- name: "lint:check",
10301
- script: "oxlint src"
10392
+ src: "anti-slop/static/rules/no-conditional-empty-object-spread.ts",
10393
+ filename: `${plugin}/rules/no-conditional-empty-object-spread.ts`
10302
10394
  },
10303
10395
  {
10304
- module: ui,
10305
- name: "lint",
10306
- script: "oxlint --fix"
10396
+ src: "anti-slop/static/rules/no-known-value-widening.ts",
10397
+ filename: `${plugin}/rules/no-known-value-widening.ts`
10307
10398
  },
10308
10399
  {
10309
- module: ui,
10310
- name: "lint:check",
10311
- script: "oxlint"
10400
+ src: "anti-slop/static/rules/no-module-mocking.ts",
10401
+ filename: `${plugin}/rules/no-module-mocking.ts`
10312
10402
  },
10313
10403
  {
10314
- module: root,
10315
- name: "format",
10316
- script: "oxfmt"
10404
+ src: "anti-slop/static/rules/no-object-parameters.ts",
10405
+ filename: `${plugin}/rules/no-object-parameters.ts`
10317
10406
  },
10318
10407
  {
10319
- module: root,
10320
- name: "format:check",
10321
- script: "oxfmt --check"
10408
+ src: "anti-slop/static/rules/no-reflect-apply.ts",
10409
+ filename: `${plugin}/rules/no-reflect-apply.ts`
10410
+ },
10411
+ {
10412
+ src: "anti-slop/static/rules/no-reflect-get.ts",
10413
+ filename: `${plugin}/rules/no-reflect-get.ts`
10414
+ },
10415
+ {
10416
+ src: "anti-slop/static/rules/no-runtime-typeof.ts",
10417
+ filename: `${plugin}/rules/no-runtime-typeof.ts`
10418
+ },
10419
+ {
10420
+ src: "anti-slop/static/rules/no-shape-in-symbol-names.ts",
10421
+ filename: `${plugin}/rules/no-shape-in-symbol-names.ts`
10422
+ },
10423
+ {
10424
+ src: "anti-slop/static/rules/no-unknown-parameters.ts",
10425
+ filename: `${plugin}/rules/no-unknown-parameters.ts`
10426
+ },
10427
+ {
10428
+ src: "anti-slop/static/rules/no-unknown-returns.ts",
10429
+ filename: `${plugin}/rules/no-unknown-returns.ts`
10430
+ },
10431
+ {
10432
+ src: "anti-slop/static/rules/no-unknown-type-aliases.ts",
10433
+ filename: `${plugin}/rules/no-unknown-type-aliases.ts`
10434
+ },
10435
+ {
10436
+ src: "anti-slop/static/rules/no-unsafe-dictionary-type.ts",
10437
+ filename: `${plugin}/rules/no-unsafe-dictionary-type.ts`
10438
+ },
10439
+ {
10440
+ src: "anti-slop/static/rules/no-widen-then-assert.ts",
10441
+ filename: `${plugin}/rules/no-widen-then-assert.ts`
10442
+ },
10443
+ {
10444
+ src: "anti-slop/static/rules/require-safety-comment-for-type-assertion.ts",
10445
+ filename: `${plugin}/rules/require-safety-comment-for-type-assertion.ts`
10446
+ },
10447
+ {
10448
+ src: "anti-slop/static/shared/dictionary-types.ts",
10449
+ filename: `${plugin}/shared/dictionary-types.ts`
10450
+ },
10451
+ {
10452
+ src: "anti-slop/static/shared/lexical-type-parameters.ts",
10453
+ filename: `${plugin}/shared/lexical-type-parameters.ts`
10454
+ },
10455
+ {
10456
+ src: "anti-slop/static/shared/reflect-method.ts",
10457
+ filename: `${plugin}/shared/reflect-method.ts`
10322
10458
  }
10323
- ]
10459
+ ],
10460
+ packages: [{
10461
+ package: "@oxlint/plugins",
10462
+ module: "",
10463
+ version: versions["@oxlint/plugins"],
10464
+ dev: true
10465
+ }]
10324
10466
  };
10325
10467
  //#endregion
10326
10468
  //#region src/templates/typescript-config/index.ts
@@ -12445,7 +12587,7 @@ function getStaticFilePath(name) {
12445
12587
  return fileURLToPath(new URL(`./static/${name}`, import.meta.url));
12446
12588
  }
12447
12589
  function selectModules(selection) {
12448
- const { deployment, nestDiOnly: nestDiOnly$1, todoExample, shadcn, database, linter, testing } = selection;
12590
+ const { deployment, nestDiOnly: nestDiOnly$1, todoExample, shadcn, database, linter, testing, extras } = selection;
12449
12591
  const deploymentModule = deployment === "standalone" ? deploymentStandalone : deployment === "custom-server" ? singleProcessCustomServer : deployment === "spa" ? singleProcessStaticExport : null;
12450
12592
  const webModule = deployment === "spa" ? {
12451
12593
  ...web$2,
@@ -12454,11 +12596,12 @@ function selectModules(selection) {
12454
12596
  return [
12455
12597
  root$2,
12456
12598
  webModule,
12457
- api$2,
12599
+ api$1,
12458
12600
  database === "postgres" ? dbPostgres : dbSqlite,
12459
12601
  auth,
12460
- shadcn ? shadcnUi : ui$2,
12602
+ shadcn ? shadcnUi : ui$1,
12461
12603
  linter === "oxc" ? oxc : eslintConfig,
12604
+ ...extras.includes("anti-slop") ? [antiSlop] : [],
12462
12605
  typescriptConfig,
12463
12606
  testing === "vitest" ? testingVitest : testingJest,
12464
12607
  ...deploymentModule ? [deploymentModule] : [],
@@ -12564,6 +12707,13 @@ function validateFlagValue(flag, value, allowed) {
12564
12707
  error: `Invalid value "${value}" for ${flag}. Valid choices: ${allowed.join(", ")}.`
12565
12708
  };
12566
12709
  }
12710
+ function validateExtrasCombo(extras, linter) {
12711
+ if (extras.includes("anti-slop") && linter !== "oxc") return {
12712
+ valid: false,
12713
+ error: "--extras anti-slop needs --linter oxc.\nanti-slop is a set of oxlint rules, and the eslint option installs neither oxlint\nnor a config to register them in. Add --linter oxc, or drop the extra."
12714
+ };
12715
+ return { valid: true };
12716
+ }
12567
12717
  function validateDeploymentCombo(deployment, nestDiOnly) {
12568
12718
  if (deployment === "spa" && nestDiOnly) return {
12569
12719
  valid: false,
@@ -12635,6 +12785,9 @@ async function scaffold(modules, options) {
12635
12785
  testing: options.testing,
12636
12786
  database: options.database,
12637
12787
  deployment: options.deployment,
12788
+ linter: options.linter,
12789
+ antiSlop: options.antiSlop,
12790
+ shadcn: options.selection.shadcn,
12638
12791
  authSecret: randomBytes(32).toString("base64url"),
12639
12792
  versions
12640
12793
  };
@@ -12679,6 +12832,7 @@ const DEPLOYMENT_CHOICES = [
12679
12832
  "custom-server",
12680
12833
  "spa"
12681
12834
  ];
12835
+ const EXTRAS_CHOICES = ["anti-slop"];
12682
12836
  var TaskBuilder = class {
12683
12837
  tasks = [];
12684
12838
  add(task) {
@@ -12734,6 +12888,15 @@ async function doInit(options) {
12734
12888
  }],
12735
12889
  initialValue: "eslint"
12736
12890
  }),
12891
+ extras: ({ results }) => results.linter === "oxc" ? p.multiselect({
12892
+ message: "Extras?",
12893
+ options: [{
12894
+ value: "anti-slop",
12895
+ label: "anti-slop",
12896
+ hint: "oxlint rules that reject low-evidence TypeScript"
12897
+ }],
12898
+ required: false
12899
+ }) : void 0,
12737
12900
  nestDiOnly: () => p.confirm({
12738
12901
  message: "Use NestJS for dependency injection only?",
12739
12902
  initialValue: false
@@ -12743,7 +12906,7 @@ async function doInit(options) {
12743
12906
  initialValue: true
12744
12907
  }),
12745
12908
  deployment: ({ results }) => p.select({
12746
- message: "Deployment extras?",
12909
+ message: "Deployment?",
12747
12910
  options: [
12748
12911
  {
12749
12912
  value: "none",
@@ -12785,9 +12948,12 @@ async function doInit(options) {
12785
12948
  const linter = options.nonInteractive ? options.linter : group.linter ?? "eslint";
12786
12949
  const deployment = options.nonInteractive ? options.deployment : group.deployment ?? "none";
12787
12950
  const nestDiOnly = options.nonInteractive ? options.nestDiOnly : group.nestDiOnly ?? false;
12788
- const todoExample = options.nonInteractive ? !options.bare : group.todoExample ?? true;
12951
+ const todoExample = options.nonInteractive ? options.includeExample : group.todoExample ?? true;
12952
+ const extras = options.nonInteractive ? options.extras : group.extras ?? [];
12789
12953
  const deploymentCombo = validateDeploymentCombo(deployment, nestDiOnly);
12790
12954
  if (!deploymentCombo.valid) throw new Error(deploymentCombo.error);
12955
+ const extrasCombo = validateExtrasCombo(extras, linter);
12956
+ if (!extrasCombo.valid) throw new Error(extrasCombo.error);
12791
12957
  const selection = {
12792
12958
  deployment,
12793
12959
  nestDiOnly,
@@ -12795,7 +12961,8 @@ async function doInit(options) {
12795
12961
  shadcn: useShadcn,
12796
12962
  database,
12797
12963
  linter,
12798
- testing
12964
+ testing,
12965
+ extras
12799
12966
  };
12800
12967
  const allModules = selectModules(selection);
12801
12968
  const name = group.name ?? options.name ?? "";
@@ -12808,6 +12975,8 @@ async function doInit(options) {
12808
12975
  testing,
12809
12976
  database,
12810
12977
  deployment,
12978
+ linter,
12979
+ antiSlop: extras.includes("anti-slop"),
12811
12980
  selection
12812
12981
  });
12813
12982
  return "Scaffolded.";
@@ -12849,7 +13018,7 @@ async function doInit(options) {
12849
13018
  }
12850
13019
  }
12851
13020
  const program = new Command();
12852
- program.name("create-newt-app").version(version).description("Create a new newt-app monorepo").argument("[name]").option("-ni, --no-install", "Skip pnpm install", true).option("-ng, --no-git", "Skip git initialization", true).option("--shadcn", "Include shadcn/ui", false).option("--testing <framework>", "Testing framework: vitest or jest", "jest").option("--database <database>", "Database: sqlite or postgres", "sqlite").option("--linter <linter>", "Linter: eslint or oxc", "eslint").option("--deployment <strategy>", "Deployment extras: standalone, custom-server, spa", "none").option("--nest-di-only", "Use NestJS for dependency injection only", false).option("--bare", "Skip the todo example", false).action(async (name, options, command) => {
13021
+ program.name("create-newt-app").version(version).description("Create a new newt-app monorepo").argument("[name]").option("-ni, --no-install", "Skip pnpm install", true).option("-ng, --no-git", "Skip git initialization", true).option("--shadcn", "Include shadcn/ui", false).option("--testing <framework>", "Testing framework: vitest or jest", "jest").option("--database <database>", "Database: sqlite or postgres", "sqlite").option("--linter <linter>", "Linter: eslint or oxc", "eslint").option("--deployment <strategy>", "Deployment: standalone, custom-server, spa", "none").option("--nest-di-only", "Use NestJS for dependency injection only", false).option("--include-example", "Include the todo example", false).option("--extras <list>", "Extras, comma-separated: anti-slop", "").action(async (name, options, command) => {
12853
13022
  intro(`Create a ${chalk.blue("newt")} app.`);
12854
13023
  const nonInteractive = [
12855
13024
  "shadcn",
@@ -12858,8 +13027,10 @@ program.name("create-newt-app").version(version).description("Create a new newt-
12858
13027
  "linter",
12859
13028
  "deployment",
12860
13029
  "nestDiOnly",
12861
- "bare"
13030
+ "includeExample",
13031
+ "extras"
12862
13032
  ].some((flag) => command.getOptionValueSource(flag) === "cli");
13033
+ const extras = options.extras.split(",").map((extra) => extra.trim()).filter(Boolean);
12863
13034
  const invalid = [
12864
13035
  {
12865
13036
  flag: "--testing",
@@ -12880,7 +13051,12 @@ program.name("create-newt-app").version(version).description("Create a new newt-
12880
13051
  flag: "--deployment",
12881
13052
  value: options.deployment,
12882
13053
  allowed: DEPLOYMENT_CHOICES
12883
- }
13054
+ },
13055
+ ...extras.map((extra) => ({
13056
+ flag: "--extras",
13057
+ value: extra,
13058
+ allowed: EXTRAS_CHOICES
13059
+ }))
12884
13060
  ].map(({ flag, value, allowed }) => validateFlagValue(flag, value, allowed)).find((result) => !result.valid);
12885
13061
  if (invalid) {
12886
13062
  console.error(`Error: ${invalid.error}`);
@@ -12897,7 +13073,8 @@ program.name("create-newt-app").version(version).description("Create a new newt-
12897
13073
  linter: options.linter,
12898
13074
  deployment: options.deployment,
12899
13075
  nestDiOnly: options.nestDiOnly,
12900
- bare: options.bare
13076
+ includeExample: options.includeExample,
13077
+ extras
12901
13078
  });
12902
13079
  });
12903
13080
  program.parse();