create-newt-app 0.31.2 → 0.31.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";KAgCY;;;cChBN;cACA;cACA;cACA;KAGD,kBAAkB;KAClB,mBAAmB;KACnB,iBAAiB;KACjB,qBAAqB;KAcrB;EACH;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV,QAAQ;EACR,YAAY;EACZ;EACA;EACA,iBAAiB;;iBAWG,OAAO,SAAS,UAAO"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";KAgCY;;;cCdN;cACA;cACA;cACA;KAGD,kBAAkB;KAClB,mBAAmB;KACnB,iBAAiB;KACjB,qBAAqB;KAcrB;EACH;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV,QAAQ;EACR,YAAY;EACZ;EACA;EACA,iBAAiB;;iBAWG,OAAO,SAAS,UAAO"}
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.31.2";
13
+ var version = "0.31.4";
14
14
  var engines = { "node": ">=24.0.0" };
15
15
  //#endregion
16
16
  //#region src/templates/root/index.ts
@@ -112,7 +112,7 @@ dist
112
112
  "env": ["DATABASE_URL"],
113
113
  "dependsOn": ["^build"],
114
114
  "inputs": ["$TURBO_DEFAULT$", ".env*"],
115
- "outputs": [".next/**", "!.next/cache/**"]
115
+ "outputs": [".next/**", "!.next/cache/**", "dist/**"]
116
116
  },
117
117
  "typecheck": {
118
118
  "dependsOn": ["^build"]
@@ -126,8 +126,7 @@ dist
126
126
  "env": ["NODE_ENV"]
127
127
  },<% } %>
128
128
  "test": {
129
- "dependsOn": ["^build"],
130
- "outputs": ["coverage/**"]
129
+ "dependsOn": ["^build"]
131
130
  },
132
131
  "dev": {
133
132
  "dependsOn": ["^migrate"],
@@ -187,7 +186,16 @@ Open [http://localhost:3000](http://localhost:3000).
187
186
  template: `<% if (database === 'postgres') { %>DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
188
187
  <% } else { %># Local SQLite database, written to dev.db at the repo root
189
188
  <% } %>BETTER_AUTH_URL=http://localhost:3000
190
- BETTER_AUTH_SECRET=<%= authSecret %>`
189
+ BETTER_AUTH_SECRET=<%= authSecret %>
190
+ `
191
+ },
192
+ {
193
+ filename: ".env.example",
194
+ template: `<% if (database === 'postgres') { %>DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
195
+ <% } else { %># Local SQLite database, written to dev.db at the repo root
196
+ <% } %>BETTER_AUTH_URL=http://localhost:3000
197
+ BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
198
+ `
191
199
  },
192
200
  {
193
201
  filename: "AGENTS.md",
@@ -587,6 +595,7 @@ export function AuthForm() {
587
595
  <label className="text-sm font-medium">Name</label>
588
596
  <input
589
597
  type="text"
598
+ autoComplete="name"
590
599
  value={field.state.value}
591
600
  onChange={(e) => field.handleChange(e.target.value)}
592
601
  required
@@ -603,6 +612,7 @@ export function AuthForm() {
603
612
  <label className="text-sm font-medium">Email</label>
604
613
  <input
605
614
  type="email"
615
+ autoComplete="email"
606
616
  value={field.state.value}
607
617
  onChange={(e) => field.handleChange(e.target.value)}
608
618
  required
@@ -618,6 +628,9 @@ export function AuthForm() {
618
628
  <label className="text-sm font-medium">Password</label>
619
629
  <input
620
630
  type="password"
631
+ autoComplete={
632
+ tab === 'signin' ? 'current-password' : 'new-password'
633
+ }
621
634
  value={field.state.value}
622
635
  onChange={(e) => field.handleChange(e.target.value)}
623
636
  required
@@ -756,16 +769,12 @@ const api$1 = { templates: [
756
769
  template: `{
757
770
  "name": "api",
758
771
  "version": "0.0.1",
759
- "description": "",
760
- "author": "",
761
772
  "private": true,
762
- "license": "UNLICENSED",
763
773
  "scripts": {
764
774
  "build": "nest build",
765
775
  "typecheck": "tsc -p tsconfig.build.json --noEmit",
766
776
  "start": "nest start",
767
777
  "dev": "nest start --watch",
768
- "start:dev": "nest start --watch",
769
778
  "start:debug": "nest start --debug --watch",
770
779
  "start:prod": "node dist/main"
771
780
  },
@@ -788,8 +797,6 @@ const api$1 = { templates: [
788
797
  "@types/node": "<%= versions["@types/node"] %>",
789
798
  "@types/supertest": "<%= versions["@types/supertest"] %>",
790
799
  "supertest": "<%= versions.supertest %>",
791
- "ts-node": "<%= versions["ts-node"] %>",
792
- "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
793
800
  "typescript": "<%= versions.typescript %>"
794
801
  }
795
802
  }`
@@ -1505,7 +1512,6 @@ export default config;`
1505
1512
  //#region src/templates/versions.ts
1506
1513
  const versions = {
1507
1514
  "@base-ui/react": "^1.6.0",
1508
- "@eslint/eslintrc": "^3.2.0",
1509
1515
  "@eslint/js": "^9.39.1",
1510
1516
  "@nestjs/cli": "^11.0.0",
1511
1517
  "@nestjs/common": "^11.0.1",
@@ -1514,7 +1520,7 @@ const versions = {
1514
1520
  "@nestjs/schematics": "^11.0.0",
1515
1521
  "@nestjs/serve-static": "^5.0.0",
1516
1522
  "@nestjs/testing": "^11.0.1",
1517
- "@next/eslint-plugin-next": "^16.3.2",
1523
+ "@next/eslint-plugin-next": "^16.3.3",
1518
1524
  "@oxlint/plugins": "^1.74.0",
1519
1525
  "@shadcn/react": "^0.2.1",
1520
1526
  "@swc/core": "^1.10.0",
@@ -1552,7 +1558,7 @@ const versions = {
1552
1558
  jest: "^30.0.0",
1553
1559
  kysely: "^0.28.2",
1554
1560
  "lucide-react": "^1.16.0",
1555
- next: "16.3.2",
1561
+ next: "16.3.3",
1556
1562
  "next-themes": "^0.4.6",
1557
1563
  oxfmt: "^0.59.0",
1558
1564
  oxlint: "^1.74.0",
@@ -1567,14 +1573,10 @@ const versions = {
1567
1573
  rxjs: "^7.8.1",
1568
1574
  shadcn: "^4.7.0",
1569
1575
  sonner: "^2.0.7",
1570
- "source-map-support": "^0.5.21",
1571
1576
  supertest: "^7.0.0",
1572
1577
  "tailwind-merge": "^3.6.0",
1573
1578
  tailwindcss: "^4.2.1",
1574
1579
  "ts-jest": "^29.2.5",
1575
- "ts-loader": "^9.5.2",
1576
- "ts-node": "^10.9.2",
1577
- "tsconfig-paths": "^4.2.0",
1578
1580
  tsx: "^4.19.4",
1579
1581
  turbo: "^2.8.16",
1580
1582
  "tw-animate-css": "^1.4.0",
@@ -2138,6 +2140,7 @@ export function AuthForm() {
2138
2140
  <Input
2139
2141
  id="name"
2140
2142
  type="text"
2143
+ autoComplete="name"
2141
2144
  value={field.state.value}
2142
2145
  onChange={(e) => field.handleChange(e.target.value)}
2143
2146
  required
@@ -2154,6 +2157,7 @@ export function AuthForm() {
2154
2157
  <Input
2155
2158
  id="email"
2156
2159
  type="email"
2160
+ autoComplete="email"
2157
2161
  value={field.state.value}
2158
2162
  onChange={(e) => field.handleChange(e.target.value)}
2159
2163
  required
@@ -2169,6 +2173,9 @@ export function AuthForm() {
2169
2173
  <Input
2170
2174
  id="password"
2171
2175
  type="password"
2176
+ autoComplete={
2177
+ tab === 'signin' ? 'current-password' : 'new-password'
2178
+ }
2172
2179
  value={field.state.value}
2173
2180
  onChange={(e) => field.handleChange(e.target.value)}
2174
2181
  required
@@ -10079,7 +10086,7 @@ export default tseslint.config(
10079
10086
  languageOptions: {
10080
10087
  globals: {
10081
10088
  ...globals.node,
10082
- ...globals.jest,
10089
+ ...globals.<%= testing %>,
10083
10090
  },
10084
10091
  sourceType: 'commonjs',
10085
10092
  parserOptions: {
@@ -10142,12 +10149,6 @@ const eslintConfig = {
10142
10149
  version: "workspace:*",
10143
10150
  dev: true
10144
10151
  },
10145
- {
10146
- package: "@eslint/eslintrc",
10147
- module: api,
10148
- version: versions["@eslint/eslintrc"],
10149
- dev: true
10150
- },
10151
10152
  {
10152
10153
  package: "@eslint/js",
10153
10154
  module: api,
@@ -10637,18 +10638,6 @@ module.exports = {
10637
10638
  module: "apps/api",
10638
10639
  version: versions["@types/jest"],
10639
10640
  dev: true
10640
- },
10641
- {
10642
- package: "ts-loader",
10643
- module: "apps/api",
10644
- version: versions["ts-loader"],
10645
- dev: true
10646
- },
10647
- {
10648
- package: "source-map-support",
10649
- module: "apps/api",
10650
- version: versions["source-map-support"],
10651
- dev: true
10652
10641
  }
10653
10642
  ],
10654
10643
  scripts: [
@@ -10670,7 +10659,7 @@ module.exports = {
10670
10659
  {
10671
10660
  module: "apps/api",
10672
10661
  name: "test:debug",
10673
- script: "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"
10662
+ script: "node --inspect-brk node_modules/.bin/jest --runInBand"
10674
10663
  },
10675
10664
  {
10676
10665
  module: "apps/api",
@@ -10804,7 +10793,7 @@ const deploymentStandalone = { templates: [
10804
10793
  {
10805
10794
  when: (s) => !s.nestDiOnly,
10806
10795
  filename: "Dockerfile",
10807
- template: `FROM node:22-alpine AS base
10796
+ template: `FROM node:24-alpine AS base
10808
10797
  ENV PNPM_HOME="/pnpm"
10809
10798
  ENV PATH="$PNPM_HOME:$PATH"
10810
10799
  RUN corepack enable
@@ -10816,7 +10805,6 @@ RUN pnpm install --frozen-lockfile
10816
10805
  ARG API_HOST=localhost
10817
10806
  ENV API_HOST=$API_HOST
10818
10807
  RUN pnpm build --filter=web --filter=api --filter=@<%= projectName %>/auth
10819
- RUN pnpm deploy --filter=api --prod /deploy/api
10820
10808
 
10821
10809
  # --- web ---
10822
10810
  FROM base AS web
@@ -10829,10 +10817,9 @@ EXPOSE 3000
10829
10817
  CMD ["node", "apps/web/server.js"]
10830
10818
 
10831
10819
  # --- api ---
10832
- FROM base AS api
10820
+ FROM build AS api
10821
+ WORKDIR /app/apps/api
10833
10822
  ENV NODE_ENV=production
10834
- COPY --from=build /deploy/api /app
10835
- WORKDIR /app
10836
10823
  EXPOSE 3001
10837
10824
  CMD ["node", "dist/main"]
10838
10825
 
@@ -10942,7 +10929,7 @@ export default nextConfig;`
10942
10929
  "dependsOn": ["^build"],
10943
10930
  "inputs": ["$TURBO_DEFAULT$", ".env*"],
10944
10931
  "env": ["API_HOST", "DATABASE_URL"],
10945
- "outputs": [".next/**", "!.next/cache/**"]
10932
+ "outputs": [".next/**", "!.next/cache/**", "dist/**"]
10946
10933
  },
10947
10934
  "typecheck": {
10948
10935
  "dependsOn": ["^build"]
@@ -10956,8 +10943,7 @@ export default nextConfig;`
10956
10943
  "env": ["NODE_ENV"]
10957
10944
  },<% } %>
10958
10945
  "test": {
10959
- "dependsOn": ["^build"],
10960
- "outputs": ["coverage/**"]
10946
+ "dependsOn": ["^build"]
10961
10947
  },
10962
10948
  "dev": {
10963
10949
  "env": ["DATABASE_URL"],
@@ -10984,15 +10970,11 @@ const singleProcessStaticExport = { templates: [{
10984
10970
  template: `{
10985
10971
  "name": "api",
10986
10972
  "version": "0.0.1",
10987
- "description": "",
10988
- "author": "",
10989
10973
  "private": true,
10990
- "license": "UNLICENSED",
10991
10974
  "scripts": {
10992
10975
  "build": "nest build",
10993
10976
  "start": "nest start",
10994
10977
  "dev": "nest start --watch",
10995
- "start:dev": "nest start --watch",
10996
10978
  "start:debug": "nest start --debug --watch",
10997
10979
  "start:prod": "node dist/main"
10998
10980
  },
@@ -11016,8 +10998,6 @@ const singleProcessStaticExport = { templates: [{
11016
10998
  "@types/node": "<%= versions["@types/node"] %>",
11017
10999
  "@types/supertest": "<%= versions["@types/supertest"] %>",
11018
11000
  "supertest": "<%= versions.supertest %>",
11019
- "ts-node": "<%= versions["ts-node"] %>",
11020
- "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
11021
11001
  "typescript": "<%= versions.typescript %>"
11022
11002
  }
11023
11003
  }`
@@ -11059,10 +11039,7 @@ const nestDiOnly = { templates: [
11059
11039
  template: `{
11060
11040
  "name": "@<%= projectName %>/api",
11061
11041
  "version": "0.0.1",
11062
- "description": "",
11063
- "author": "",
11064
11042
  "private": true,
11065
- "license": "UNLICENSED",
11066
11043
  "exports": {
11067
11044
  ".": "./src/index.ts"
11068
11045
  },
@@ -11084,8 +11061,6 @@ const nestDiOnly = { templates: [
11084
11061
  "@nestjs/schematics": "<%= versions["@nestjs/schematics"] %>",
11085
11062
  "@nestjs/testing": "<%= versions["@nestjs/testing"] %>",
11086
11063
  "@types/node": "<%= versions["@types/node"] %>",
11087
- "ts-node": "<%= versions["ts-node"] %>",
11088
- "tsconfig-paths": "<%= versions["tsconfig-paths"] %>",
11089
11064
  "typescript": "<%= versions.typescript %>"
11090
11065
  }
11091
11066
  }`
@@ -11259,7 +11234,7 @@ export default nextConfig;`
11259
11234
  const deploymentStandaloneDi = { templates: [
11260
11235
  {
11261
11236
  filename: "Dockerfile",
11262
- template: `FROM node:22-alpine AS base
11237
+ template: `FROM node:24-alpine AS base
11263
11238
  ENV PNPM_HOME="/pnpm"
11264
11239
  ENV PATH="$PNPM_HOME:$PATH"
11265
11240
  RUN corepack enable
@@ -12536,27 +12511,23 @@ function validateNodeVersion(current, requirement) {
12536
12511
  error: `Node ${requirement} is required, but this is ${current}.\nUpgrade Node, or switch versions with a manager such as nvm or fnm.`
12537
12512
  };
12538
12513
  }
12514
+ function normalizeProjectName(projectName) {
12515
+ return projectName.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9\-._~]/g, "-").replace(/-+/g, "-").replace(/^[-._]+/, "").replace(/-+$/, "").slice(0, 214);
12516
+ }
12539
12517
  function validateProjectName(projectName) {
12540
12518
  if (!projectName) return {
12541
12519
  valid: false,
12542
12520
  error: "Project name is required"
12543
12521
  };
12544
- if (projectName.length < 1) return {
12545
- valid: false,
12546
- error: "Project name must be at least 1 character long"
12547
- };
12548
- if (projectName.length > 214) return {
12522
+ const normalized = normalizeProjectName(projectName);
12523
+ if (!normalized) return {
12549
12524
  valid: false,
12550
- error: "Project name must be less than 214 characters"
12525
+ error: `"${projectName}" has nothing left after normalizing. Include a letter or a digit.`
12551
12526
  };
12552
- if (/[<>:"/\\|?*]/.test(projectName)) return {
12553
- valid: false,
12554
- error: "Project name contains invalid characters"
12555
- };
12556
- const targetPath = path.resolve(process.cwd(), projectName);
12527
+ const targetPath = path.resolve(process.cwd(), normalized);
12557
12528
  if (existsSync(targetPath)) return {
12558
12529
  valid: false,
12559
- error: `Directory "${projectName}" already exists`
12530
+ error: `Directory "${normalized}" already exists`
12560
12531
  };
12561
12532
  return { valid: true };
12562
12533
  }
@@ -12632,11 +12603,7 @@ async function doInit(options) {
12632
12603
  ...!options.name && { name: () => p.text({
12633
12604
  message: "What is your project name?",
12634
12605
  placeholder: "my-newt-app",
12635
- validate: (value) => {
12636
- if (!value) return "Project name is required";
12637
- if (value.length > 214) return "Project name is too long";
12638
- if (/[<>:"/\\|?*]/.test(value)) return "Project name contains invalid characters";
12639
- }
12606
+ validate: (value) => validateProjectName(value).error
12640
12607
  }) },
12641
12608
  ...!options.nonInteractive && {
12642
12609
  shadcn: () => p.confirm({
@@ -12749,7 +12716,10 @@ async function doInit(options) {
12749
12716
  extras
12750
12717
  };
12751
12718
  const allModules = selectModules(selection);
12752
- const name = answers.name ?? options.name ?? "";
12719
+ const rawName = answers.name ?? options.name ?? "";
12720
+ const nameCheck = validateProjectName(rawName);
12721
+ if (!nameCheck.valid) throw new Error(nameCheck.error);
12722
+ const name = normalizeProjectName(rawName);
12753
12723
  const taskBuilder = new TaskBuilder();
12754
12724
  taskBuilder.add({
12755
12725
  title: "Scaffolding project",
@@ -12802,7 +12772,7 @@ async function doInit(options) {
12802
12772
  }
12803
12773
  }
12804
12774
  const program = new Command();
12805
- 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, 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) => {
12775
+ 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: none, standalone, or 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) => {
12806
12776
  intro(`Create a ${chalk.blue("newt")} app.`);
12807
12777
  const nonInteractive = [
12808
12778
  "shadcn",