create-newt-app 0.32.0 → 0.33.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1445 -175
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { existsSync, promises } from "fs";
|
|
|
11
11
|
import path from "path";
|
|
12
12
|
import https from "node:https";
|
|
13
13
|
//#region package.json
|
|
14
|
-
var version = "0.
|
|
14
|
+
var version = "0.33.0";
|
|
15
15
|
var engines = { "node": ">=24.0.0" };
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/templates/root/index.ts
|
|
@@ -231,7 +231,7 @@ This version has breaking changes — APIs, conventions, and file structure may
|
|
|
231
231
|
const web$1 = {
|
|
232
232
|
templates: [
|
|
233
233
|
{
|
|
234
|
-
when: (s) => s.nest !== "di-only",
|
|
234
|
+
when: (s) => s.nest !== "di-only" && !s.stylex,
|
|
235
235
|
filename: "apps/web/package.json",
|
|
236
236
|
template: `{
|
|
237
237
|
"name": "web",
|
|
@@ -369,6 +369,7 @@ const nextConfig = {
|
|
|
369
369
|
export default nextConfig;`
|
|
370
370
|
},
|
|
371
371
|
{
|
|
372
|
+
when: (s) => !s.stylex,
|
|
372
373
|
filename: "apps/web/postcss.config.mjs",
|
|
373
374
|
template: `export { default } from "@<%= projectName %>/ui/postcss.config";`
|
|
374
375
|
},
|
|
@@ -399,7 +400,7 @@ export default nextConfig;`
|
|
|
399
400
|
}`
|
|
400
401
|
},
|
|
401
402
|
{
|
|
402
|
-
when: (s) => !s.shadcn,
|
|
403
|
+
when: (s) => !s.shadcn && !s.stylex,
|
|
403
404
|
filename: "apps/web/app/layout.tsx",
|
|
404
405
|
template: `import type { Metadata } from "next";
|
|
405
406
|
import localFont from "next/font/local";
|
|
@@ -442,7 +443,7 @@ export default function RootLayout({
|
|
|
442
443
|
}`
|
|
443
444
|
},
|
|
444
445
|
{
|
|
445
|
-
when: (s) => !s.todoExample && !s.shadcn,
|
|
446
|
+
when: (s) => !s.todoExample && !s.shadcn && !s.stylex,
|
|
446
447
|
filename: "apps/web/app/page.tsx",
|
|
447
448
|
template: `'use client';
|
|
448
449
|
|
|
@@ -543,7 +544,7 @@ export default function Providers({ children }: { children: React.ReactNode }) {
|
|
|
543
544
|
}`
|
|
544
545
|
},
|
|
545
546
|
{
|
|
546
|
-
when: (s) => !s.shadcn,
|
|
547
|
+
when: (s) => !s.shadcn && !s.stylex,
|
|
547
548
|
filename: "apps/web/app/auth-form.tsx",
|
|
548
549
|
template: `'use client';
|
|
549
550
|
|
|
@@ -941,6 +942,7 @@ export type Auth = typeof auth;`
|
|
|
941
942
|
filename: "packages/auth/tsconfig.json",
|
|
942
943
|
template: `{
|
|
943
944
|
"compilerOptions": {
|
|
945
|
+
"erasableSyntaxOnly": true,
|
|
944
946
|
"esModuleInterop": true,
|
|
945
947
|
"lib": ["es2022"],
|
|
946
948
|
"module": "NodeNext",
|
|
@@ -961,6 +963,7 @@ var tsconfig_default$2 = {
|
|
|
961
963
|
filename: "packages/db/tsconfig.json",
|
|
962
964
|
template: `{
|
|
963
965
|
"compilerOptions": {
|
|
966
|
+
"erasableSyntaxOnly": true,
|
|
964
967
|
"esModuleInterop": true,
|
|
965
968
|
"lib": ["es2022"],
|
|
966
969
|
"module": "NodeNext",
|
|
@@ -1256,11 +1259,10 @@ const dbPostgres = { templates: [
|
|
|
1256
1259
|
src_index_postgres_default
|
|
1257
1260
|
] };
|
|
1258
1261
|
//#endregion
|
|
1259
|
-
//#region src/templates/ui/
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
template: `{
|
|
1262
|
+
//#region src/templates/ui/templates/package-json.ts
|
|
1263
|
+
var package_json_default$4 = {
|
|
1264
|
+
filename: "packages/ui/package.json",
|
|
1265
|
+
template: `{
|
|
1264
1266
|
"name": "@<%= projectName %>/ui",
|
|
1265
1267
|
"version": "0.0.0",
|
|
1266
1268
|
"private": true,
|
|
@@ -1292,10 +1294,12 @@ const ui$1 = { templates: [
|
|
|
1292
1294
|
"tailwind-merge": "<%= versions["tailwind-merge"] %>"
|
|
1293
1295
|
}
|
|
1294
1296
|
}`
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1297
|
+
};
|
|
1298
|
+
//#endregion
|
|
1299
|
+
//#region src/templates/ui/templates/button.ts
|
|
1300
|
+
var button_default$2 = {
|
|
1301
|
+
filename: "packages/ui/src/button.tsx",
|
|
1302
|
+
template: `"use client";
|
|
1299
1303
|
|
|
1300
1304
|
import { ReactNode } from "react";
|
|
1301
1305
|
import { cn } from "./utils";
|
|
@@ -1327,10 +1331,12 @@ export const Button = ({ children, onClick, type = "button", disabled, className
|
|
|
1327
1331
|
</button>
|
|
1328
1332
|
);
|
|
1329
1333
|
};`
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
+
};
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region src/templates/ui/templates/link.ts
|
|
1337
|
+
var link_default$2 = {
|
|
1338
|
+
filename: "packages/ui/src/link.tsx",
|
|
1339
|
+
template: `import NextLink, { type LinkProps } from "next/link";
|
|
1334
1340
|
import { type PropsWithChildren } from "react";
|
|
1335
1341
|
import { cn } from "./utils";
|
|
1336
1342
|
|
|
@@ -1353,10 +1359,12 @@ export function Link({
|
|
|
1353
1359
|
</NextLink>
|
|
1354
1360
|
);
|
|
1355
1361
|
}`
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1362
|
+
};
|
|
1363
|
+
//#endregion
|
|
1364
|
+
//#region src/templates/ui/templates/logo.ts
|
|
1365
|
+
var logo_default$2 = {
|
|
1366
|
+
filename: "packages/ui/src/logo.tsx",
|
|
1367
|
+
template: `import { cn } from "./utils";
|
|
1360
1368
|
|
|
1361
1369
|
interface LogoProps {
|
|
1362
1370
|
className?: string;
|
|
@@ -1379,19 +1387,23 @@ export function Logo({ className }: LogoProps) {
|
|
|
1379
1387
|
</svg>
|
|
1380
1388
|
);
|
|
1381
1389
|
}`
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1390
|
+
};
|
|
1391
|
+
//#endregion
|
|
1392
|
+
//#region src/templates/ui/templates/utils.ts
|
|
1393
|
+
var utils_default$1 = {
|
|
1394
|
+
filename: "packages/ui/src/utils.ts",
|
|
1395
|
+
template: `import { clsx, type ClassValue } from "clsx";
|
|
1386
1396
|
import { twMerge } from "tailwind-merge";
|
|
1387
1397
|
|
|
1388
1398
|
export function cn(...inputs: ClassValue[]) {
|
|
1389
1399
|
return twMerge(clsx(inputs));
|
|
1390
1400
|
}`
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1401
|
+
};
|
|
1402
|
+
//#endregion
|
|
1403
|
+
//#region src/templates/ui/templates/globals-css.ts
|
|
1404
|
+
var globals_css_default$2 = {
|
|
1405
|
+
filename: "packages/ui/src/globals.css",
|
|
1406
|
+
template: `@import 'tailwindcss';
|
|
1395
1407
|
@source "../../../apps/**/*.{ts,tsx}";
|
|
1396
1408
|
@source "../**/*.{ts,tsx}";
|
|
1397
1409
|
|
|
@@ -1428,20 +1440,24 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1428
1440
|
border-color: var(--border);
|
|
1429
1441
|
}
|
|
1430
1442
|
}`
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1443
|
+
};
|
|
1444
|
+
//#endregion
|
|
1445
|
+
//#region src/templates/ui/templates/postcss-config.ts
|
|
1446
|
+
var postcss_config_default$2 = {
|
|
1447
|
+
filename: "packages/ui/postcss.config.mjs",
|
|
1448
|
+
template: `const config = {
|
|
1435
1449
|
plugins: {
|
|
1436
1450
|
"@tailwindcss/postcss": {},
|
|
1437
1451
|
},
|
|
1438
1452
|
};
|
|
1439
1453
|
|
|
1440
1454
|
export default config;`
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1455
|
+
};
|
|
1456
|
+
//#endregion
|
|
1457
|
+
//#region src/templates/ui/templates/tsconfig.ts
|
|
1458
|
+
var tsconfig_default$1 = {
|
|
1459
|
+
filename: "packages/ui/tsconfig.json",
|
|
1460
|
+
template: `{
|
|
1445
1461
|
"extends": "@<%= projectName %>/typescript-config/react-library.json",
|
|
1446
1462
|
"compilerOptions": {
|
|
1447
1463
|
"outDir": "dist",
|
|
@@ -1450,11 +1466,24 @@ export default config;`
|
|
|
1450
1466
|
"include": ["src"],
|
|
1451
1467
|
"exclude": ["node_modules", "dist"]
|
|
1452
1468
|
}`
|
|
1453
|
-
|
|
1469
|
+
};
|
|
1470
|
+
//#endregion
|
|
1471
|
+
//#region src/templates/ui/index.ts
|
|
1472
|
+
const ui$1 = { templates: [
|
|
1473
|
+
package_json_default$4,
|
|
1474
|
+
button_default$2,
|
|
1475
|
+
link_default$2,
|
|
1476
|
+
logo_default$2,
|
|
1477
|
+
utils_default$1,
|
|
1478
|
+
globals_css_default$2,
|
|
1479
|
+
postcss_config_default$2,
|
|
1480
|
+
tsconfig_default$1
|
|
1454
1481
|
] };
|
|
1455
1482
|
//#endregion
|
|
1456
1483
|
//#region src/templates/versions.ts
|
|
1457
1484
|
const versions = {
|
|
1485
|
+
"@babel/plugin-proposal-decorators": "^8.0.2",
|
|
1486
|
+
"@babel/plugin-transform-class-properties": "^8.0.1",
|
|
1458
1487
|
"@base-ui/react": "^1.6.0",
|
|
1459
1488
|
"@eslint/js": "^9.39.1",
|
|
1460
1489
|
"@nestjs/cli": "^11.0.0",
|
|
@@ -1467,6 +1496,9 @@ const versions = {
|
|
|
1467
1496
|
"@next/eslint-plugin-next": "^16.3.4",
|
|
1468
1497
|
"@oxlint/plugins": "^1.74.0",
|
|
1469
1498
|
"@shadcn/react": "^0.2.1",
|
|
1499
|
+
"@stylexjs/babel-plugin": "0.19.0",
|
|
1500
|
+
"@stylexjs/postcss-plugin": "0.19.0",
|
|
1501
|
+
"@stylexjs/stylex": "0.19.0",
|
|
1470
1502
|
"@swc/core": "^1.10.0",
|
|
1471
1503
|
"@tailwindcss/postcss": "^4.2.1",
|
|
1472
1504
|
"@tanstack/react-form": "^1.28.5",
|
|
@@ -1482,6 +1514,7 @@ const versions = {
|
|
|
1482
1514
|
"@types/supertest": "^6.0.2",
|
|
1483
1515
|
"@vitest/coverage-v8": "^4.1.10",
|
|
1484
1516
|
auth: "^1.5.5",
|
|
1517
|
+
"babel-plugin-transform-typescript-metadata": "^0.4.0",
|
|
1485
1518
|
"better-auth": "^1.2.8",
|
|
1486
1519
|
"better-sqlite3": "^12.11.1",
|
|
1487
1520
|
"class-variance-authority": "^0.7.1",
|
|
@@ -9827,154 +9860,953 @@ export {
|
|
|
9827
9860
|
}]
|
|
9828
9861
|
};
|
|
9829
9862
|
//#endregion
|
|
9830
|
-
//#region src/templates/
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9863
|
+
//#region src/templates/stylex-ui/index.ts
|
|
9864
|
+
const stylexUi = { templates: [
|
|
9865
|
+
{
|
|
9866
|
+
filename: "packages/ui/package.json",
|
|
9867
|
+
template: `{
|
|
9868
|
+
"name": "@<%= projectName %>/ui",
|
|
9835
9869
|
"version": "0.0.0",
|
|
9836
|
-
"type": "module",
|
|
9837
9870
|
"private": true,
|
|
9838
9871
|
"exports": {
|
|
9839
|
-
"./
|
|
9840
|
-
"./
|
|
9841
|
-
"
|
|
9872
|
+
"./globals.css": "./src/globals.css",
|
|
9873
|
+
"./tokens.stylex": "./src/tokens.stylex.ts",
|
|
9874
|
+
"./*": "./src/*.tsx"
|
|
9875
|
+
},
|
|
9876
|
+
"scripts": {
|
|
9877
|
+
"typecheck": "tsc --noEmit"
|
|
9842
9878
|
},
|
|
9843
9879
|
"devDependencies": {
|
|
9844
|
-
"
|
|
9845
|
-
"@
|
|
9846
|
-
"
|
|
9847
|
-
"
|
|
9848
|
-
"
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
"
|
|
9852
|
-
"
|
|
9853
|
-
"
|
|
9854
|
-
|
|
9880
|
+
"@<%= projectName %>/typescript-config": "workspace:*",
|
|
9881
|
+
"@types/node": "<%= versions["@types/node"] %>",
|
|
9882
|
+
"@types/react": "<%= versions["@types/react"] %>",
|
|
9883
|
+
"@types/react-dom": "<%= versions["@types/react-dom"] %>",
|
|
9884
|
+
"typescript": "<%= versions.typescript %>"
|
|
9885
|
+
},
|
|
9886
|
+
"peerDependencies": {
|
|
9887
|
+
"next": ">=15.0.0",
|
|
9888
|
+
"react": ">=19.0.0",
|
|
9889
|
+
"react-dom": ">=19.0.0"
|
|
9890
|
+
},
|
|
9891
|
+
"dependencies": {
|
|
9892
|
+
"@stylexjs/stylex": "<%= versions["@stylexjs/stylex"] %>"
|
|
9855
9893
|
}
|
|
9856
9894
|
}`
|
|
9895
|
+
},
|
|
9896
|
+
{
|
|
9897
|
+
filename: "packages/ui/src/tokens.stylex.ts",
|
|
9898
|
+
template: `import * as stylex from "@stylexjs/stylex";
|
|
9899
|
+
|
|
9900
|
+
export const colors = stylex.defineVars({
|
|
9901
|
+
background: "oklch(0.145 0 0)",
|
|
9902
|
+
foreground: "oklch(0.985 0 0)",
|
|
9903
|
+
muted: "oklch(0.269 0 0)",
|
|
9904
|
+
mutedForeground: "oklch(0.708 0 0)",
|
|
9905
|
+
border: "oklch(0.469 0 0)",
|
|
9906
|
+
accent: "oklch(0.985 0 0)",
|
|
9907
|
+
accentForeground: "oklch(0.205 0 0)",
|
|
9908
|
+
danger: "oklch(0.637 0.237 25.331)",
|
|
9909
|
+
});
|
|
9910
|
+
|
|
9911
|
+
export const fonts = stylex.defineVars({
|
|
9912
|
+
sans: "var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif",
|
|
9913
|
+
mono: "var(--font-geist-mono), ui-monospace, monospace",
|
|
9914
|
+
});
|
|
9915
|
+
|
|
9916
|
+
export const radii = stylex.defineVars({
|
|
9917
|
+
sm: "6px",
|
|
9918
|
+
md: "8px",
|
|
9919
|
+
lg: "12px",
|
|
9920
|
+
});
|
|
9921
|
+
`
|
|
9922
|
+
},
|
|
9923
|
+
{
|
|
9924
|
+
filename: "packages/ui/src/button.tsx",
|
|
9925
|
+
template: `"use client";
|
|
9926
|
+
|
|
9927
|
+
import { ReactNode } from "react";
|
|
9928
|
+
import * as stylex from "@stylexjs/stylex";
|
|
9929
|
+
import type { StyleXStyles } from "@stylexjs/stylex";
|
|
9930
|
+
import { colors, fonts, radii } from "./tokens.stylex";
|
|
9931
|
+
|
|
9932
|
+
interface ButtonProps {
|
|
9933
|
+
children: ReactNode;
|
|
9934
|
+
onClick?: () => void;
|
|
9935
|
+
type?: "button" | "submit" | "reset";
|
|
9936
|
+
disabled?: boolean;
|
|
9937
|
+
style?: StyleXStyles;
|
|
9938
|
+
}
|
|
9939
|
+
|
|
9940
|
+
export const Button = ({ children, onClick, type = "button", disabled, style }: ButtonProps) => {
|
|
9941
|
+
return (
|
|
9942
|
+
<button
|
|
9943
|
+
type={type}
|
|
9944
|
+
onClick={onClick}
|
|
9945
|
+
disabled={disabled}
|
|
9946
|
+
{...stylex.props(styles.base, disabled && styles.disabled, style)}
|
|
9947
|
+
>
|
|
9948
|
+
{children}
|
|
9949
|
+
</button>
|
|
9950
|
+
);
|
|
9857
9951
|
};
|
|
9858
|
-
//#endregion
|
|
9859
|
-
//#region src/templates/eslint-config/templates/base.ts
|
|
9860
|
-
var base_default$1 = {
|
|
9861
|
-
filename: "packages/eslint-config/base.js",
|
|
9862
|
-
template: `import js from "@eslint/js";
|
|
9863
|
-
import eslintConfigPrettier from "eslint-config-prettier";
|
|
9864
|
-
import turboPlugin from "eslint-plugin-turbo";
|
|
9865
|
-
import tseslint from "typescript-eslint";
|
|
9866
|
-
import onlyWarn from "eslint-plugin-only-warn";
|
|
9867
9952
|
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9953
|
+
const styles = stylex.create({
|
|
9954
|
+
base: {
|
|
9955
|
+
display: "inline-flex",
|
|
9956
|
+
alignItems: "center",
|
|
9957
|
+
justifyContent: "center",
|
|
9958
|
+
gap: 8,
|
|
9959
|
+
height: 36,
|
|
9960
|
+
paddingBlock: 0,
|
|
9961
|
+
paddingInline: 16,
|
|
9962
|
+
fontFamily: fonts.sans,
|
|
9963
|
+
fontSize: 14,
|
|
9964
|
+
fontWeight: 500,
|
|
9965
|
+
whiteSpace: "nowrap",
|
|
9966
|
+
color: colors.accentForeground,
|
|
9967
|
+
backgroundColor: {
|
|
9968
|
+
default: colors.accent,
|
|
9969
|
+
":hover": "oklch(0.922 0 0)",
|
|
9883
9970
|
},
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9971
|
+
borderStyle: "none",
|
|
9972
|
+
borderRadius: radii.sm,
|
|
9973
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.3)",
|
|
9974
|
+
cursor: "pointer",
|
|
9975
|
+
transitionProperty: "background-color",
|
|
9976
|
+
transitionDuration: "150ms",
|
|
9977
|
+
outlineColor: "rgba(255, 255, 255, 0.5)",
|
|
9978
|
+
outlineOffset: 2,
|
|
9979
|
+
outlineStyle: {
|
|
9980
|
+
default: "none",
|
|
9981
|
+
":focus-visible": "solid",
|
|
9888
9982
|
},
|
|
9983
|
+
outlineWidth: 2,
|
|
9889
9984
|
},
|
|
9890
|
-
{
|
|
9891
|
-
|
|
9985
|
+
disabled: {
|
|
9986
|
+
opacity: 0.5,
|
|
9987
|
+
pointerEvents: "none",
|
|
9892
9988
|
},
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
import
|
|
9901
|
-
import
|
|
9902
|
-
import
|
|
9903
|
-
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
9904
|
-
import pluginReact from "eslint-plugin-react";
|
|
9905
|
-
import globals from "globals";
|
|
9906
|
-
import pluginNext from "@next/eslint-plugin-next";
|
|
9907
|
-
import { config as baseConfig } from "./base.js";
|
|
9989
|
+
});
|
|
9990
|
+
`
|
|
9991
|
+
},
|
|
9992
|
+
{
|
|
9993
|
+
filename: "packages/ui/src/link.tsx",
|
|
9994
|
+
template: `import NextLink, { type LinkProps } from "next/link";
|
|
9995
|
+
import { type PropsWithChildren } from "react";
|
|
9996
|
+
import * as stylex from "@stylexjs/stylex";
|
|
9997
|
+
import type { StyleXStyles } from "@stylexjs/stylex";
|
|
9998
|
+
import { colors } from "./tokens.stylex";
|
|
9908
9999
|
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
"
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
...pluginReact.configs.flat.recommended.languageOptions,
|
|
9930
|
-
globals: {
|
|
9931
|
-
...globals.serviceworker,
|
|
9932
|
-
...globals.node,
|
|
9933
|
-
},
|
|
9934
|
-
},
|
|
9935
|
-
},
|
|
9936
|
-
{
|
|
9937
|
-
plugins: {
|
|
9938
|
-
"@next/next": pluginNext,
|
|
9939
|
-
},
|
|
9940
|
-
rules: {
|
|
9941
|
-
...pluginNext.configs.recommended.rules,
|
|
9942
|
-
...pluginNext.configs["core-web-vitals"].rules,
|
|
9943
|
-
},
|
|
9944
|
-
},
|
|
9945
|
-
{
|
|
9946
|
-
plugins: {
|
|
9947
|
-
"react-hooks": pluginReactHooks,
|
|
9948
|
-
},
|
|
9949
|
-
settings: { react: { version: "detect" } },
|
|
9950
|
-
rules: {
|
|
9951
|
-
...pluginReactHooks.configs.recommended.rules,
|
|
9952
|
-
// React scope no longer necessary with new JSX transform.
|
|
9953
|
-
"react/react-in-jsx-scope": "off",
|
|
10000
|
+
export function Link({
|
|
10001
|
+
href,
|
|
10002
|
+
children,
|
|
10003
|
+
style,
|
|
10004
|
+
...rest
|
|
10005
|
+
}: PropsWithChildren<LinkProps & { style?: StyleXStyles }>) {
|
|
10006
|
+
return (
|
|
10007
|
+
<NextLink href={href} {...rest} {...stylex.props(styles.link, style)}>
|
|
10008
|
+
{children}
|
|
10009
|
+
</NextLink>
|
|
10010
|
+
);
|
|
10011
|
+
}
|
|
10012
|
+
|
|
10013
|
+
const styles = stylex.create({
|
|
10014
|
+
link: {
|
|
10015
|
+
color: "inherit",
|
|
10016
|
+
textDecorationLine: "underline",
|
|
10017
|
+
textDecorationColor: {
|
|
10018
|
+
default: colors.mutedForeground,
|
|
10019
|
+
":hover": colors.foreground,
|
|
9954
10020
|
},
|
|
10021
|
+
transitionProperty: "text-decoration-color",
|
|
10022
|
+
transitionDuration: "150ms",
|
|
9955
10023
|
},
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
import
|
|
9964
|
-
import tseslint from "typescript-eslint";
|
|
9965
|
-
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
9966
|
-
import pluginReact from "eslint-plugin-react";
|
|
9967
|
-
import globals from "globals";
|
|
9968
|
-
import { config as baseConfig } from "./base.js";
|
|
10024
|
+
});
|
|
10025
|
+
`
|
|
10026
|
+
},
|
|
10027
|
+
{
|
|
10028
|
+
filename: "packages/ui/src/logo.tsx",
|
|
10029
|
+
template: `import * as stylex from "@stylexjs/stylex";
|
|
10030
|
+
import type { StyleXStyles } from "@stylexjs/stylex";
|
|
10031
|
+
import { colors } from "./tokens.stylex";
|
|
9969
10032
|
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
export
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
10033
|
+
interface LogoProps {
|
|
10034
|
+
style?: StyleXStyles;
|
|
10035
|
+
}
|
|
10036
|
+
|
|
10037
|
+
export function Logo({ style }: LogoProps) {
|
|
10038
|
+
return (
|
|
10039
|
+
<svg
|
|
10040
|
+
width="196"
|
|
10041
|
+
height="138"
|
|
10042
|
+
viewBox="0 0 196 138"
|
|
10043
|
+
fill="none"
|
|
10044
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10045
|
+
{...stylex.props(styles.logo, style)}
|
|
10046
|
+
>
|
|
10047
|
+
<path
|
|
10048
|
+
d="M98 35C102.665 35 107.243 35.2232 111.707 35.6514C111.243 38.1972 111 40.8202 111 43.5C111 67.5244 130.476 87 154.5 87C165.156 87 174.914 83.1658 182.478 76.8057C183.476 79.9455 184 83.186 184 86.5C184 114.943 145.496 138 98 138C50.5035 138 12 114.943 12 86.5C12 83.1861 12.5228 79.9454 13.5215 76.8057C21.0851 83.1661 30.8441 87 41.5 87C65.5244 87 85 67.5244 85 43.5C85 40.8202 84.7559 38.1973 84.292 35.6514C88.7559 35.2232 93.3345 35 98 35ZM38.5 0C59.763 0 77 17.237 77 38.5C77 59.763 59.763 77 38.5 77C17.237 77 0 59.763 0 38.5C0 17.237 17.237 0 38.5 0ZM157.5 0C178.763 0 196 17.237 196 38.5C196 59.763 178.763 77 157.5 77C136.237 77 119 59.763 119 38.5C119 17.237 136.237 0 157.5 0Z"
|
|
10049
|
+
fill="currentColor"
|
|
10050
|
+
/>
|
|
10051
|
+
</svg>
|
|
10052
|
+
);
|
|
10053
|
+
}
|
|
10054
|
+
|
|
10055
|
+
const styles = stylex.create({
|
|
10056
|
+
logo: {
|
|
10057
|
+
color: colors.foreground,
|
|
10058
|
+
},
|
|
10059
|
+
});
|
|
10060
|
+
`
|
|
10061
|
+
},
|
|
10062
|
+
{
|
|
10063
|
+
filename: "packages/ui/src/globals.css",
|
|
10064
|
+
template: `@layer resets {
|
|
10065
|
+
*,
|
|
10066
|
+
*::before,
|
|
10067
|
+
*::after {
|
|
10068
|
+
box-sizing: border-box;
|
|
10069
|
+
}
|
|
10070
|
+
|
|
10071
|
+
* {
|
|
10072
|
+
margin: 0;
|
|
10073
|
+
padding: 0;
|
|
10074
|
+
}
|
|
10075
|
+
|
|
10076
|
+
html,
|
|
10077
|
+
body {
|
|
10078
|
+
height: 100%;
|
|
10079
|
+
}
|
|
10080
|
+
|
|
10081
|
+
html {
|
|
10082
|
+
-webkit-font-smoothing: antialiased;
|
|
10083
|
+
-moz-osx-font-smoothing: grayscale;
|
|
10084
|
+
}
|
|
10085
|
+
}
|
|
10086
|
+
|
|
10087
|
+
@stylex;
|
|
10088
|
+
`
|
|
10089
|
+
},
|
|
10090
|
+
tsconfig_default$1,
|
|
10091
|
+
{
|
|
10092
|
+
when: (s) => s.nest !== "di-only",
|
|
10093
|
+
filename: "apps/web/package.json",
|
|
10094
|
+
template: `{
|
|
10095
|
+
"name": "web",
|
|
10096
|
+
"version": "0.1.0",
|
|
10097
|
+
"type": "module",
|
|
10098
|
+
"private": true,
|
|
10099
|
+
"scripts": {
|
|
10100
|
+
"dev": "next dev --port 3000",
|
|
10101
|
+
"build": "next build",
|
|
10102
|
+
"start": "next start",
|
|
10103
|
+
"typecheck": "next typegen && tsc --noEmit"
|
|
10104
|
+
},
|
|
10105
|
+
"dependencies": {
|
|
10106
|
+
"@<%= projectName %>/auth": "workspace:*",
|
|
10107
|
+
"@<%= projectName %>/ui": "workspace:*",
|
|
10108
|
+
"@stylexjs/stylex": "<%= versions["@stylexjs/stylex"] %>",
|
|
10109
|
+
"dotenv": "<%= versions.dotenv %>",
|
|
10110
|
+
"@tanstack/react-form": "<%= versions["@tanstack/react-form"] %>",
|
|
10111
|
+
"@tanstack/react-query": "<%= versions["@tanstack/react-query"] %>",
|
|
10112
|
+
"better-auth": "<%= versions["better-auth"] %>",
|
|
10113
|
+
"next": "<%= versions.next %>",
|
|
10114
|
+
"react": "<%= versions.react %>",
|
|
10115
|
+
"react-dom": "<%= versions["react-dom"] %>"
|
|
10116
|
+
},
|
|
10117
|
+
"devDependencies": {
|
|
10118
|
+
"@<%= projectName %>/typescript-config": "workspace:*",
|
|
10119
|
+
"@stylexjs/babel-plugin": "<%= versions["@stylexjs/babel-plugin"] %>",
|
|
10120
|
+
"@stylexjs/postcss-plugin": "<%= versions["@stylexjs/postcss-plugin"] %>",
|
|
10121
|
+
"@types/node": "<%= versions["@types/node"] %>",
|
|
10122
|
+
"@types/react": "<%= versions["@types/react"] %>",
|
|
10123
|
+
"@types/react-dom": "<%= versions["@types/react-dom"] %>",
|
|
10124
|
+
"typescript": "<%= versions.typescript %>"
|
|
10125
|
+
}
|
|
10126
|
+
}`
|
|
10127
|
+
},
|
|
10128
|
+
{
|
|
10129
|
+
when: (s) => s.nest === "di-only",
|
|
10130
|
+
filename: "apps/web/package.json",
|
|
10131
|
+
template: `{
|
|
10132
|
+
"name": "web",
|
|
10133
|
+
"version": "0.1.0",
|
|
10134
|
+
"type": "module",
|
|
10135
|
+
"private": true,
|
|
10136
|
+
"scripts": {
|
|
10137
|
+
"dev": "next dev --port 3000",
|
|
10138
|
+
"build": "next build",
|
|
10139
|
+
"start": "next start"
|
|
10140
|
+
},
|
|
10141
|
+
"dependencies": {
|
|
10142
|
+
"@<%= projectName %>/api": "workspace:*",
|
|
10143
|
+
"@<%= projectName %>/auth": "workspace:*",
|
|
10144
|
+
"@<%= projectName %>/db": "workspace:*",
|
|
10145
|
+
"@<%= projectName %>/ui": "workspace:*",
|
|
10146
|
+
"@nestjs/common": "<%= versions["@nestjs/common"] %>",
|
|
10147
|
+
"@nestjs/core": "<%= versions["@nestjs/core"] %>",
|
|
10148
|
+
"reflect-metadata": "<%= versions["reflect-metadata"] %>",
|
|
10149
|
+
"@stylexjs/stylex": "<%= versions["@stylexjs/stylex"] %>",
|
|
10150
|
+
"dotenv": "<%= versions.dotenv %>",
|
|
10151
|
+
"@tanstack/react-form": "<%= versions["@tanstack/react-form"] %>",
|
|
10152
|
+
"@tanstack/react-query": "<%= versions["@tanstack/react-query"] %>",
|
|
10153
|
+
"better-auth": "<%= versions["better-auth"] %>",
|
|
10154
|
+
"next": "<%= versions.next %>",
|
|
10155
|
+
"react": "<%= versions.react %>",
|
|
10156
|
+
"react-dom": "<%= versions["react-dom"] %>"
|
|
10157
|
+
},
|
|
10158
|
+
"devDependencies": {
|
|
10159
|
+
"@<%= projectName %>/typescript-config": "workspace:*",
|
|
10160
|
+
"@babel/plugin-proposal-decorators": "<%= versions["@babel/plugin-proposal-decorators"] %>",
|
|
10161
|
+
"@babel/plugin-transform-class-properties": "<%= versions["@babel/plugin-transform-class-properties"] %>",
|
|
10162
|
+
"babel-plugin-transform-typescript-metadata": "<%= versions["babel-plugin-transform-typescript-metadata"] %>",
|
|
10163
|
+
"@stylexjs/babel-plugin": "<%= versions["@stylexjs/babel-plugin"] %>",
|
|
10164
|
+
"@stylexjs/postcss-plugin": "<%= versions["@stylexjs/postcss-plugin"] %>",
|
|
10165
|
+
"@types/node": "<%= versions["@types/node"] %>",
|
|
10166
|
+
"@types/react": "<%= versions["@types/react"] %>",
|
|
10167
|
+
"@types/react-dom": "<%= versions["@types/react-dom"] %>",
|
|
10168
|
+
"typescript": "<%= versions.typescript %>"
|
|
10169
|
+
}
|
|
10170
|
+
}`
|
|
10171
|
+
},
|
|
10172
|
+
{
|
|
10173
|
+
filename: "apps/web/babel.config.js",
|
|
10174
|
+
template: `import path from "node:path";
|
|
10175
|
+
import { fileURLToPath } from "node:url";
|
|
10176
|
+
|
|
10177
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10178
|
+
|
|
10179
|
+
const config = {
|
|
10180
|
+
presets: ["next/babel"],
|
|
10181
|
+
plugins: [
|
|
10182
|
+
<% if (nest === 'di-only') { %> "babel-plugin-transform-typescript-metadata",
|
|
10183
|
+
["@babel/plugin-proposal-decorators", { version: "legacy" }],
|
|
10184
|
+
["@babel/plugin-transform-class-properties", { loose: true }],
|
|
10185
|
+
<% } %> [
|
|
10186
|
+
"@stylexjs/babel-plugin",
|
|
10187
|
+
{
|
|
10188
|
+
dev: process.env.NODE_ENV !== "production",
|
|
10189
|
+
runtimeInjection: false,
|
|
10190
|
+
treeshakeCompensation: true,
|
|
10191
|
+
unstable_moduleResolution: {
|
|
10192
|
+
type: "commonJS",
|
|
10193
|
+
rootDir: path.join(dirname, "../.."),
|
|
10194
|
+
},
|
|
10195
|
+
},
|
|
10196
|
+
],
|
|
10197
|
+
],
|
|
10198
|
+
};
|
|
10199
|
+
|
|
10200
|
+
export default config;`
|
|
10201
|
+
},
|
|
10202
|
+
{
|
|
10203
|
+
filename: "apps/web/postcss.config.mjs",
|
|
10204
|
+
template: `import babelConfig from "./babel.config.js";
|
|
10205
|
+
|
|
10206
|
+
const config = {
|
|
10207
|
+
plugins: {
|
|
10208
|
+
"@stylexjs/postcss-plugin": {
|
|
10209
|
+
include: [
|
|
10210
|
+
"app/**/*.{js,jsx,ts,tsx}",
|
|
10211
|
+
"../../packages/ui/src/**/*.{js,jsx,ts,tsx}",
|
|
10212
|
+
],
|
|
10213
|
+
babelConfig: {
|
|
10214
|
+
babelrc: false,
|
|
10215
|
+
parserOpts: { plugins: ["typescript", "jsx"] },
|
|
10216
|
+
plugins: babelConfig.plugins,
|
|
10217
|
+
},
|
|
10218
|
+
useCSSLayers: true,
|
|
10219
|
+
},
|
|
10220
|
+
},
|
|
10221
|
+
};
|
|
10222
|
+
|
|
10223
|
+
export default config;`
|
|
10224
|
+
},
|
|
10225
|
+
{
|
|
10226
|
+
filename: "apps/web/app/layout.tsx",
|
|
10227
|
+
template: `import type { Metadata } from "next";
|
|
10228
|
+
import localFont from "next/font/local";
|
|
10229
|
+
import * as stylex from "@stylexjs/stylex";
|
|
10230
|
+
import Providers from "@/app/providers";
|
|
10231
|
+
import { colors, fonts } from "@<%= projectName %>/ui/tokens.stylex";
|
|
10232
|
+
import "@<%= projectName %>/ui/globals.css";
|
|
10233
|
+
|
|
10234
|
+
const geistSans = localFont({
|
|
10235
|
+
src: "./fonts/GeistVF.woff",
|
|
10236
|
+
variable: "--font-geist-sans",
|
|
10237
|
+
});
|
|
10238
|
+
const geistMono = localFont({
|
|
10239
|
+
src: "./fonts/GeistMonoVF.woff",
|
|
10240
|
+
variable: "--font-geist-mono",
|
|
10241
|
+
});
|
|
10242
|
+
|
|
10243
|
+
export const metadata: Metadata = {
|
|
10244
|
+
title: "<%= projectName %>",
|
|
10245
|
+
description: "Next + Nest = Newt",
|
|
10246
|
+
icons: {
|
|
10247
|
+
icon: [
|
|
10248
|
+
{ url: "/icon0.svg", type: "image/svg+xml" },
|
|
10249
|
+
{ url: "/icon1.png", type: "image/png" },
|
|
10250
|
+
],
|
|
10251
|
+
apple: "/apple-icon.png",
|
|
10252
|
+
},
|
|
10253
|
+
};
|
|
10254
|
+
|
|
10255
|
+
export default function RootLayout({
|
|
10256
|
+
children,
|
|
10257
|
+
}: Readonly<{
|
|
10258
|
+
children: React.ReactNode;
|
|
10259
|
+
}>) {
|
|
10260
|
+
return (
|
|
10261
|
+
<html lang="en" className={\`\${geistSans.variable} \${geistMono.variable}\`}>
|
|
10262
|
+
<body {...stylex.props(styles.body)}>
|
|
10263
|
+
<Providers>{children}</Providers>
|
|
10264
|
+
</body>
|
|
10265
|
+
</html>
|
|
10266
|
+
);
|
|
10267
|
+
}
|
|
10268
|
+
|
|
10269
|
+
const styles = stylex.create({
|
|
10270
|
+
body: {
|
|
10271
|
+
backgroundColor: colors.background,
|
|
10272
|
+
color: colors.foreground,
|
|
10273
|
+
fontFamily: fonts.sans,
|
|
10274
|
+
},
|
|
10275
|
+
});
|
|
10276
|
+
`
|
|
10277
|
+
},
|
|
10278
|
+
{
|
|
10279
|
+
when: (s) => !s.todoExample,
|
|
10280
|
+
filename: "apps/web/app/page.tsx",
|
|
10281
|
+
template: `'use client';
|
|
10282
|
+
|
|
10283
|
+
import { useQuery } from '@tanstack/react-query';
|
|
10284
|
+
import * as stylex from '@stylexjs/stylex';
|
|
10285
|
+
import { authClient } from '@/lib/auth-client';
|
|
10286
|
+
import { AuthForm } from '@/app/auth-form';
|
|
10287
|
+
import { Button } from '@<%= projectName %>/ui/button';
|
|
10288
|
+
import { Link } from '@<%= projectName %>/ui/link';
|
|
10289
|
+
import { Logo } from '@<%= projectName %>/ui/logo';
|
|
10290
|
+
import { colors, fonts, radii } from '@<%= projectName %>/ui/tokens.stylex';
|
|
10291
|
+
|
|
10292
|
+
export default function Home() {
|
|
10293
|
+
const { data: session, isPending } = authClient.useSession();
|
|
10294
|
+
|
|
10295
|
+
const { data: hello } = useQuery({
|
|
10296
|
+
queryKey: ['hello'],
|
|
10297
|
+
queryFn: () => fetch('/api/hello').then((r) => r.json()),
|
|
10298
|
+
});
|
|
10299
|
+
|
|
10300
|
+
return (
|
|
10301
|
+
<main {...stylex.props(styles.main)}>
|
|
10302
|
+
<div {...stylex.props(styles.header)}>
|
|
10303
|
+
<p {...stylex.props(styles.mono, styles.muted)}>apps/web/app/page.tsx</p>
|
|
10304
|
+
<p {...stylex.props(styles.muted)}>Delete me to get started!</p>
|
|
10305
|
+
</div>
|
|
10306
|
+
|
|
10307
|
+
<div {...stylex.props(styles.titleRow)}>
|
|
10308
|
+
<Logo style={styles.logo} />
|
|
10309
|
+
<div>
|
|
10310
|
+
<h1 {...stylex.props(styles.h1)}><%= projectName %></h1>
|
|
10311
|
+
<p {...stylex.props(styles.muted, styles.tagline)}>
|
|
10312
|
+
Next + Nest = Newt 💜
|
|
10313
|
+
</p>
|
|
10314
|
+
</div>
|
|
10315
|
+
</div>
|
|
10316
|
+
|
|
10317
|
+
<div {...stylex.props(styles.card)}>
|
|
10318
|
+
<p {...stylex.props(styles.eyebrow)}>next.js</p>
|
|
10319
|
+
<p {...stylex.props(styles.mono, styles.muted)}>apps/web/app/layout.tsx</p>
|
|
10320
|
+
<p {...stylex.props(styles.muted)}>Next.js rendering</p>
|
|
10321
|
+
</div>
|
|
10322
|
+
|
|
10323
|
+
<div {...stylex.props(styles.card)}>
|
|
10324
|
+
<p {...stylex.props(styles.eyebrow)}>nest.js</p>
|
|
10325
|
+
<p {...stylex.props(styles.mono, styles.muted)}>GET /api/hello</p>
|
|
10326
|
+
<pre {...stylex.props(styles.pre)}>
|
|
10327
|
+
<code>{JSON.stringify(hello, null, 2)}</code>
|
|
10328
|
+
</pre>
|
|
10329
|
+
</div>
|
|
10330
|
+
|
|
10331
|
+
<div {...stylex.props(styles.card)}>
|
|
10332
|
+
<p {...stylex.props(styles.eyebrow, styles.eyebrowSpaced)}>better-auth</p>
|
|
10333
|
+
{isPending ? (
|
|
10334
|
+
<p {...stylex.props(styles.muted)}>Loading…</p>
|
|
10335
|
+
) : session ? (
|
|
10336
|
+
<div {...stylex.props(styles.signedIn)}>
|
|
10337
|
+
<p>Signed in as {session.user.name}</p>
|
|
10338
|
+
<Button onClick={() => void authClient.signOut()}>
|
|
10339
|
+
Sign out
|
|
10340
|
+
</Button>
|
|
10341
|
+
</div>
|
|
10342
|
+
) : (
|
|
10343
|
+
<AuthForm />
|
|
10344
|
+
)}
|
|
10345
|
+
</div>
|
|
10346
|
+
|
|
10347
|
+
<div {...stylex.props(styles.footer)}>
|
|
10348
|
+
<p {...stylex.props(styles.muted)}>Learn more</p>
|
|
10349
|
+
<ul {...stylex.props(styles.list)}>
|
|
10350
|
+
<li>
|
|
10351
|
+
<Link href="https://newt-app.com">Documentation</Link>
|
|
10352
|
+
</li>
|
|
10353
|
+
<li>
|
|
10354
|
+
<Link href="https://github.com/zeevo/newt-app">GitHub</Link>
|
|
10355
|
+
</li>
|
|
10356
|
+
<li>
|
|
10357
|
+
<Link href="https://nextjs.org">Next.js</Link>
|
|
10358
|
+
</li>
|
|
10359
|
+
<li>
|
|
10360
|
+
<Link href="https://nestjs.com">NestJS</Link>
|
|
10361
|
+
</li>
|
|
10362
|
+
</ul>
|
|
10363
|
+
</div>
|
|
10364
|
+
</main>
|
|
10365
|
+
);
|
|
10366
|
+
}
|
|
10367
|
+
|
|
10368
|
+
const styles = stylex.create({
|
|
10369
|
+
main: {
|
|
10370
|
+
display: 'flex',
|
|
10371
|
+
flexDirection: 'column',
|
|
10372
|
+
gap: '1rem',
|
|
10373
|
+
maxWidth: '32rem',
|
|
10374
|
+
minHeight: '100%',
|
|
10375
|
+
marginInline: 'auto',
|
|
10376
|
+
paddingBlock: '2rem',
|
|
10377
|
+
paddingInline: '1rem',
|
|
10378
|
+
fontSize: '0.875rem',
|
|
10379
|
+
},
|
|
10380
|
+
header: {
|
|
10381
|
+
paddingBottom: '1rem',
|
|
10382
|
+
borderBottomColor: colors.border,
|
|
10383
|
+
borderBottomStyle: 'solid',
|
|
10384
|
+
borderBottomWidth: 1,
|
|
10385
|
+
},
|
|
10386
|
+
titleRow: {
|
|
10387
|
+
display: 'flex',
|
|
10388
|
+
alignItems: 'center',
|
|
10389
|
+
gap: '0.75rem',
|
|
10390
|
+
paddingBlock: '0.5rem',
|
|
10391
|
+
},
|
|
10392
|
+
logo: {
|
|
10393
|
+
width: '2.5rem',
|
|
10394
|
+
height: 'auto',
|
|
10395
|
+
},
|
|
10396
|
+
h1: {
|
|
10397
|
+
fontSize: '2.25rem',
|
|
10398
|
+
fontWeight: 900,
|
|
10399
|
+
letterSpacing: '-0.025em',
|
|
10400
|
+
},
|
|
10401
|
+
tagline: {
|
|
10402
|
+
letterSpacing: '0.1em',
|
|
10403
|
+
textTransform: 'uppercase',
|
|
10404
|
+
},
|
|
10405
|
+
card: {
|
|
10406
|
+
display: 'flex',
|
|
10407
|
+
flexDirection: 'column',
|
|
10408
|
+
gap: '0.25rem',
|
|
10409
|
+
padding: '1.5rem',
|
|
10410
|
+
borderColor: colors.border,
|
|
10411
|
+
borderRadius: radii.lg,
|
|
10412
|
+
borderStyle: 'solid',
|
|
10413
|
+
borderWidth: 1,
|
|
10414
|
+
},
|
|
10415
|
+
eyebrow: {
|
|
10416
|
+
fontFamily: fonts.mono,
|
|
10417
|
+
fontSize: '0.75rem',
|
|
10418
|
+
letterSpacing: '0.1em',
|
|
10419
|
+
textTransform: 'uppercase',
|
|
10420
|
+
color: colors.mutedForeground,
|
|
10421
|
+
},
|
|
10422
|
+
eyebrowSpaced: {
|
|
10423
|
+
marginBottom: '0.75rem',
|
|
10424
|
+
},
|
|
10425
|
+
pre: {
|
|
10426
|
+
marginTop: '0.5rem',
|
|
10427
|
+
padding: '0.75rem',
|
|
10428
|
+
fontFamily: fonts.mono,
|
|
10429
|
+
backgroundColor: 'oklch(0.269 0 0 / 0.5)',
|
|
10430
|
+
borderColor: colors.border,
|
|
10431
|
+
borderRadius: radii.sm,
|
|
10432
|
+
borderStyle: 'solid',
|
|
10433
|
+
borderWidth: 1,
|
|
10434
|
+
overflowX: 'auto',
|
|
10435
|
+
},
|
|
10436
|
+
signedIn: {
|
|
10437
|
+
display: 'flex',
|
|
10438
|
+
flexDirection: 'column',
|
|
10439
|
+
alignItems: 'flex-start',
|
|
10440
|
+
gap: '0.75rem',
|
|
10441
|
+
},
|
|
10442
|
+
footer: {
|
|
10443
|
+
display: 'flex',
|
|
10444
|
+
flexDirection: 'column',
|
|
10445
|
+
gap: '0.5rem',
|
|
10446
|
+
paddingBlock: '1rem',
|
|
10447
|
+
paddingInline: '0.5rem',
|
|
10448
|
+
},
|
|
10449
|
+
list: {
|
|
10450
|
+
display: 'flex',
|
|
10451
|
+
flexDirection: 'column',
|
|
10452
|
+
gap: '0.5rem',
|
|
10453
|
+
listStylePosition: 'inside',
|
|
10454
|
+
listStyleType: 'disc',
|
|
10455
|
+
},
|
|
10456
|
+
mono: {
|
|
10457
|
+
fontFamily: fonts.mono,
|
|
10458
|
+
},
|
|
10459
|
+
muted: {
|
|
10460
|
+
color: colors.mutedForeground,
|
|
10461
|
+
},
|
|
10462
|
+
});
|
|
10463
|
+
`
|
|
10464
|
+
},
|
|
10465
|
+
{
|
|
10466
|
+
filename: "apps/web/app/auth-form.tsx",
|
|
10467
|
+
template: `'use client';
|
|
10468
|
+
|
|
10469
|
+
import { useForm } from '@tanstack/react-form';
|
|
10470
|
+
import { useState } from 'react';
|
|
10471
|
+
import * as stylex from '@stylexjs/stylex';
|
|
10472
|
+
import { authClient } from '@/lib/auth-client';
|
|
10473
|
+
import { Button } from '@<%= projectName %>/ui/button';
|
|
10474
|
+
import { colors, radii } from '@<%= projectName %>/ui/tokens.stylex';
|
|
10475
|
+
|
|
10476
|
+
export function AuthForm() {
|
|
10477
|
+
const [tab, setTab] = useState<'signin' | 'signup'>('signup');
|
|
10478
|
+
const [error, setError] = useState('');
|
|
10479
|
+
|
|
10480
|
+
const form = useForm({
|
|
10481
|
+
defaultValues: { name: '', email: '', password: '' },
|
|
10482
|
+
onSubmit: async ({ value }) => {
|
|
10483
|
+
setError('');
|
|
10484
|
+
if (tab === 'signin') {
|
|
10485
|
+
const { error } = await authClient.signIn.email(value);
|
|
10486
|
+
if (error) setError(error.message ?? 'Sign in failed');
|
|
10487
|
+
} else {
|
|
10488
|
+
const { error } = await authClient.signUp.email(value);
|
|
10489
|
+
if (error) setError(error.message ?? 'Sign up failed');
|
|
10490
|
+
}
|
|
10491
|
+
},
|
|
10492
|
+
});
|
|
10493
|
+
|
|
10494
|
+
return (
|
|
10495
|
+
<>
|
|
10496
|
+
<div {...stylex.props(styles.tabs)}>
|
|
10497
|
+
<button
|
|
10498
|
+
onClick={() => setTab('signup')}
|
|
10499
|
+
{...stylex.props(styles.tab, tab === 'signup' && styles.tabActive)}
|
|
10500
|
+
>
|
|
10501
|
+
Sign up
|
|
10502
|
+
</button>
|
|
10503
|
+
<span {...stylex.props(styles.divider)}>|</span>
|
|
10504
|
+
<button
|
|
10505
|
+
onClick={() => setTab('signin')}
|
|
10506
|
+
{...stylex.props(styles.tab, tab === 'signin' && styles.tabActive)}
|
|
10507
|
+
>
|
|
10508
|
+
Sign in
|
|
10509
|
+
</button>
|
|
10510
|
+
</div>
|
|
10511
|
+
|
|
10512
|
+
<form
|
|
10513
|
+
onSubmit={(e) => {
|
|
10514
|
+
e.preventDefault();
|
|
10515
|
+
form.handleSubmit();
|
|
10516
|
+
}}
|
|
10517
|
+
{...stylex.props(styles.form)}
|
|
10518
|
+
>
|
|
10519
|
+
{tab === 'signup' && (
|
|
10520
|
+
<form.Field name="name">
|
|
10521
|
+
{(field) => (
|
|
10522
|
+
<div {...stylex.props(styles.field)}>
|
|
10523
|
+
<label {...stylex.props(styles.label)}>Name</label>
|
|
10524
|
+
<input
|
|
10525
|
+
type="text"
|
|
10526
|
+
autoComplete="name"
|
|
10527
|
+
value={field.state.value}
|
|
10528
|
+
onChange={(e) => field.handleChange(e.target.value)}
|
|
10529
|
+
required
|
|
10530
|
+
{...stylex.props(styles.input)}
|
|
10531
|
+
/>
|
|
10532
|
+
</div>
|
|
10533
|
+
)}
|
|
10534
|
+
</form.Field>
|
|
10535
|
+
)}
|
|
10536
|
+
|
|
10537
|
+
<form.Field name="email">
|
|
10538
|
+
{(field) => (
|
|
10539
|
+
<div {...stylex.props(styles.field)}>
|
|
10540
|
+
<label {...stylex.props(styles.label)}>Email</label>
|
|
10541
|
+
<input
|
|
10542
|
+
type="email"
|
|
10543
|
+
autoComplete="email"
|
|
10544
|
+
value={field.state.value}
|
|
10545
|
+
onChange={(e) => field.handleChange(e.target.value)}
|
|
10546
|
+
required
|
|
10547
|
+
{...stylex.props(styles.input)}
|
|
10548
|
+
/>
|
|
10549
|
+
</div>
|
|
10550
|
+
)}
|
|
10551
|
+
</form.Field>
|
|
10552
|
+
|
|
10553
|
+
<form.Field name="password">
|
|
10554
|
+
{(field) => (
|
|
10555
|
+
<div {...stylex.props(styles.field)}>
|
|
10556
|
+
<label {...stylex.props(styles.label)}>Password</label>
|
|
10557
|
+
<input
|
|
10558
|
+
type="password"
|
|
10559
|
+
autoComplete={
|
|
10560
|
+
tab === 'signin' ? 'current-password' : 'new-password'
|
|
10561
|
+
}
|
|
10562
|
+
value={field.state.value}
|
|
10563
|
+
onChange={(e) => field.handleChange(e.target.value)}
|
|
10564
|
+
required
|
|
10565
|
+
minLength={8}
|
|
10566
|
+
{...stylex.props(styles.input)}
|
|
10567
|
+
/>
|
|
10568
|
+
</div>
|
|
10569
|
+
)}
|
|
10570
|
+
</form.Field>
|
|
10571
|
+
|
|
10572
|
+
{error && <p {...stylex.props(styles.error)}>{error}</p>}
|
|
10573
|
+
|
|
10574
|
+
<form.Subscribe selector={(s) => s.isSubmitting}>
|
|
10575
|
+
{(isSubmitting) => (
|
|
10576
|
+
<Button type="submit" disabled={isSubmitting} style={styles.submit}>
|
|
10577
|
+
{isSubmitting
|
|
10578
|
+
? 'Loading…'
|
|
10579
|
+
: tab === 'signin'
|
|
10580
|
+
? 'Sign in'
|
|
10581
|
+
: 'Create account'}
|
|
10582
|
+
</Button>
|
|
10583
|
+
)}
|
|
10584
|
+
</form.Subscribe>
|
|
10585
|
+
</form>
|
|
10586
|
+
</>
|
|
10587
|
+
);
|
|
10588
|
+
}
|
|
10589
|
+
|
|
10590
|
+
const styles = stylex.create({
|
|
10591
|
+
tabs: {
|
|
10592
|
+
display: 'flex',
|
|
10593
|
+
gap: '0.5rem',
|
|
10594
|
+
marginBottom: '1.5rem',
|
|
10595
|
+
fontSize: '0.875rem',
|
|
10596
|
+
},
|
|
10597
|
+
tab: {
|
|
10598
|
+
color: {
|
|
10599
|
+
default: colors.mutedForeground,
|
|
10600
|
+
':hover': colors.foreground,
|
|
10601
|
+
},
|
|
10602
|
+
backgroundColor: 'transparent',
|
|
10603
|
+
borderStyle: 'none',
|
|
10604
|
+
cursor: 'pointer',
|
|
10605
|
+
padding: 0,
|
|
10606
|
+
fontFamily: 'inherit',
|
|
10607
|
+
fontSize: 'inherit',
|
|
10608
|
+
},
|
|
10609
|
+
tabActive: {
|
|
10610
|
+
color: colors.foreground,
|
|
10611
|
+
fontWeight: 600,
|
|
10612
|
+
},
|
|
10613
|
+
divider: {
|
|
10614
|
+
color: colors.border,
|
|
10615
|
+
},
|
|
10616
|
+
form: {
|
|
10617
|
+
display: 'flex',
|
|
10618
|
+
flexDirection: 'column',
|
|
10619
|
+
gap: '1rem',
|
|
10620
|
+
},
|
|
10621
|
+
field: {
|
|
10622
|
+
display: 'flex',
|
|
10623
|
+
flexDirection: 'column',
|
|
10624
|
+
gap: '0.25rem',
|
|
10625
|
+
},
|
|
10626
|
+
label: {
|
|
10627
|
+
fontSize: '0.875rem',
|
|
10628
|
+
fontWeight: 500,
|
|
10629
|
+
},
|
|
10630
|
+
input: {
|
|
10631
|
+
width: '100%',
|
|
10632
|
+
height: 36,
|
|
10633
|
+
paddingBlock: '0.25rem',
|
|
10634
|
+
paddingInline: '0.75rem',
|
|
10635
|
+
fontFamily: 'inherit',
|
|
10636
|
+
fontSize: '0.875rem',
|
|
10637
|
+
color: colors.foreground,
|
|
10638
|
+
backgroundColor: 'oklch(0.269 0 0 / 0.5)',
|
|
10639
|
+
borderColor: {
|
|
10640
|
+
default: colors.border,
|
|
10641
|
+
':focus-visible': colors.mutedForeground,
|
|
10642
|
+
},
|
|
10643
|
+
borderRadius: radii.sm,
|
|
10644
|
+
borderStyle: 'solid',
|
|
10645
|
+
borderWidth: 1,
|
|
10646
|
+
outlineStyle: 'none',
|
|
10647
|
+
transitionProperty: 'border-color',
|
|
10648
|
+
transitionDuration: '150ms',
|
|
10649
|
+
},
|
|
10650
|
+
error: {
|
|
10651
|
+
fontSize: '0.875rem',
|
|
10652
|
+
color: colors.danger,
|
|
10653
|
+
},
|
|
10654
|
+
submit: {
|
|
10655
|
+
width: '100%',
|
|
10656
|
+
},
|
|
10657
|
+
});
|
|
10658
|
+
`
|
|
10659
|
+
}
|
|
10660
|
+
] };
|
|
10661
|
+
//#endregion
|
|
10662
|
+
//#region src/templates/eslint-config/templates/package-json.ts
|
|
10663
|
+
var package_json_default$1 = {
|
|
10664
|
+
filename: "packages/eslint-config/package.json",
|
|
10665
|
+
template: `{
|
|
10666
|
+
"name": "@<%= projectName %>/eslint-config",
|
|
10667
|
+
"version": "0.0.0",
|
|
10668
|
+
"type": "module",
|
|
10669
|
+
"private": true,
|
|
10670
|
+
"exports": {
|
|
10671
|
+
"./base": "./base.js",
|
|
10672
|
+
"./next-js": "./next.js",
|
|
10673
|
+
"./react-internal": "./react-internal.js"
|
|
10674
|
+
},
|
|
10675
|
+
"devDependencies": {
|
|
10676
|
+
"@eslint/js": "<%= versions["@eslint/js"] %>",
|
|
10677
|
+
"@next/eslint-plugin-next": "<%= versions["@next/eslint-plugin-next"] %>",
|
|
10678
|
+
"eslint": "<%= versions.eslint %>",
|
|
10679
|
+
"eslint-config-prettier": "<%= versions["eslint-config-prettier"] %>",
|
|
10680
|
+
"eslint-plugin-only-warn": "<%= versions["eslint-plugin-only-warn"] %>",
|
|
10681
|
+
"eslint-plugin-react": "<%= versions["eslint-plugin-react"] %>",
|
|
10682
|
+
"eslint-plugin-react-hooks": "<%= versions["eslint-plugin-react-hooks"] %>",
|
|
10683
|
+
"eslint-plugin-turbo": "<%= versions["eslint-plugin-turbo"] %>",
|
|
10684
|
+
"globals": "<%= versions.globals %>",
|
|
10685
|
+
"typescript": "<%= versions.typescript %>",
|
|
10686
|
+
"typescript-eslint": "<%= versions["typescript-eslint"] %>"
|
|
10687
|
+
}
|
|
10688
|
+
}`
|
|
10689
|
+
};
|
|
10690
|
+
//#endregion
|
|
10691
|
+
//#region src/templates/eslint-config/templates/base.ts
|
|
10692
|
+
var base_default$1 = {
|
|
10693
|
+
filename: "packages/eslint-config/base.js",
|
|
10694
|
+
template: `import js from "@eslint/js";
|
|
10695
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
10696
|
+
import turboPlugin from "eslint-plugin-turbo";
|
|
10697
|
+
import tseslint from "typescript-eslint";
|
|
10698
|
+
import onlyWarn from "eslint-plugin-only-warn";
|
|
10699
|
+
|
|
10700
|
+
/**
|
|
10701
|
+
* A shared ESLint configuration for the repository.
|
|
10702
|
+
*
|
|
10703
|
+
* @type {import("eslint").Linter.Config[]}
|
|
10704
|
+
* */
|
|
10705
|
+
export const config = [
|
|
10706
|
+
js.configs.recommended,
|
|
10707
|
+
eslintConfigPrettier,
|
|
10708
|
+
...tseslint.configs.recommended,
|
|
10709
|
+
{
|
|
10710
|
+
plugins: {
|
|
10711
|
+
turbo: turboPlugin,
|
|
10712
|
+
},
|
|
10713
|
+
rules: {
|
|
10714
|
+
"turbo/no-undeclared-env-vars": "warn",
|
|
10715
|
+
},
|
|
10716
|
+
},
|
|
10717
|
+
{
|
|
10718
|
+
plugins: {
|
|
10719
|
+
onlyWarn,
|
|
10720
|
+
},
|
|
10721
|
+
},
|
|
10722
|
+
{
|
|
10723
|
+
ignores: ["dist/**"],
|
|
10724
|
+
},
|
|
10725
|
+
];`
|
|
10726
|
+
};
|
|
10727
|
+
//#endregion
|
|
10728
|
+
//#region src/templates/eslint-config/templates/next.ts
|
|
10729
|
+
var next_default = {
|
|
10730
|
+
filename: "packages/eslint-config/next.js",
|
|
10731
|
+
template: `import js from "@eslint/js";
|
|
10732
|
+
import { globalIgnores } from "eslint/config";
|
|
10733
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
10734
|
+
import tseslint from "typescript-eslint";
|
|
10735
|
+
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
10736
|
+
import pluginReact from "eslint-plugin-react";
|
|
10737
|
+
import globals from "globals";
|
|
10738
|
+
import pluginNext from "@next/eslint-plugin-next";
|
|
10739
|
+
import { config as baseConfig } from "./base.js";
|
|
10740
|
+
|
|
10741
|
+
/**
|
|
10742
|
+
* A custom ESLint configuration for libraries that use Next.js.
|
|
10743
|
+
*
|
|
10744
|
+
* @type {import("eslint").Linter.Config[]}
|
|
10745
|
+
* */
|
|
10746
|
+
export const nextJsConfig = [
|
|
10747
|
+
...baseConfig,
|
|
10748
|
+
js.configs.recommended,
|
|
10749
|
+
eslintConfigPrettier,
|
|
10750
|
+
...tseslint.configs.recommended,
|
|
10751
|
+
globalIgnores([
|
|
10752
|
+
// Default ignores of eslint-config-next:
|
|
10753
|
+
".next/**",
|
|
10754
|
+
"out/**",
|
|
10755
|
+
"build/**",
|
|
10756
|
+
"next-env.d.ts",
|
|
10757
|
+
]),
|
|
10758
|
+
{
|
|
10759
|
+
...pluginReact.configs.flat.recommended,
|
|
10760
|
+
languageOptions: {
|
|
10761
|
+
...pluginReact.configs.flat.recommended.languageOptions,
|
|
10762
|
+
globals: {
|
|
10763
|
+
...globals.serviceworker,
|
|
10764
|
+
...globals.node,
|
|
10765
|
+
},
|
|
10766
|
+
},
|
|
10767
|
+
},
|
|
10768
|
+
{
|
|
10769
|
+
plugins: {
|
|
10770
|
+
"@next/next": pluginNext,
|
|
10771
|
+
},
|
|
10772
|
+
rules: {
|
|
10773
|
+
...pluginNext.configs.recommended.rules,
|
|
10774
|
+
...pluginNext.configs["core-web-vitals"].rules,
|
|
10775
|
+
},
|
|
10776
|
+
},
|
|
10777
|
+
{
|
|
10778
|
+
plugins: {
|
|
10779
|
+
"react-hooks": pluginReactHooks,
|
|
10780
|
+
},
|
|
10781
|
+
settings: { react: { version: "detect" } },
|
|
10782
|
+
rules: {
|
|
10783
|
+
...pluginReactHooks.configs.recommended.rules,
|
|
10784
|
+
// React scope no longer necessary with new JSX transform.
|
|
10785
|
+
"react/react-in-jsx-scope": "off",
|
|
10786
|
+
},
|
|
10787
|
+
},
|
|
10788
|
+
];`
|
|
10789
|
+
};
|
|
10790
|
+
//#endregion
|
|
10791
|
+
//#region src/templates/eslint-config/templates/react-internal.ts
|
|
10792
|
+
var react_internal_default = {
|
|
10793
|
+
filename: "packages/eslint-config/react-internal.js",
|
|
10794
|
+
template: `import js from "@eslint/js";
|
|
10795
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
10796
|
+
import tseslint from "typescript-eslint";
|
|
10797
|
+
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
10798
|
+
import pluginReact from "eslint-plugin-react";
|
|
10799
|
+
import globals from "globals";
|
|
10800
|
+
import { config as baseConfig } from "./base.js";
|
|
10801
|
+
|
|
10802
|
+
/**
|
|
10803
|
+
* A custom ESLint configuration for libraries that use React.
|
|
10804
|
+
*
|
|
10805
|
+
* @type {import("eslint").Linter.Config[]} */
|
|
10806
|
+
export const config = [
|
|
10807
|
+
...baseConfig,
|
|
10808
|
+
js.configs.recommended,
|
|
10809
|
+
eslintConfigPrettier,
|
|
9978
10810
|
...tseslint.configs.recommended,
|
|
9979
10811
|
pluginReact.configs.flat.recommended,
|
|
9980
10812
|
{
|
|
@@ -11093,6 +11925,7 @@ export async function GET() {
|
|
|
11093
11925
|
}`
|
|
11094
11926
|
},
|
|
11095
11927
|
{
|
|
11928
|
+
when: (s) => !s.stylex,
|
|
11096
11929
|
filename: "apps/web/package.json",
|
|
11097
11930
|
template: `{
|
|
11098
11931
|
"name": "web",
|
|
@@ -11966,7 +12799,7 @@ export function TodoList({
|
|
|
11966
12799
|
//#endregion
|
|
11967
12800
|
//#region src/templates/todo-example/templates/web-page.ts
|
|
11968
12801
|
var web_page_default = {
|
|
11969
|
-
when: (s) => s.todoExample && !s.shadcn,
|
|
12802
|
+
when: (s) => s.todoExample && !s.shadcn && !s.stylex,
|
|
11970
12803
|
filename: "apps/web/app/page.tsx",
|
|
11971
12804
|
template: `'use client';
|
|
11972
12805
|
|
|
@@ -12304,6 +13137,424 @@ export default function Home() {
|
|
|
12304
13137
|
}`
|
|
12305
13138
|
};
|
|
12306
13139
|
//#endregion
|
|
13140
|
+
//#region src/templates/todo-example/templates/stylex-todo-list.ts
|
|
13141
|
+
var stylex_todo_list_default = {
|
|
13142
|
+
filename: "apps/web/app/todo-list.tsx",
|
|
13143
|
+
template: `'use client';
|
|
13144
|
+
|
|
13145
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
13146
|
+
import { useForm } from '@tanstack/react-form';
|
|
13147
|
+
import * as stylex from '@stylexjs/stylex';
|
|
13148
|
+
import { authClient } from '@/lib/auth-client';
|
|
13149
|
+
import { Button } from '@<%= projectName %>/ui/button';
|
|
13150
|
+
import { colors, radii } from '@<%= projectName %>/ui/tokens.stylex';
|
|
13151
|
+
|
|
13152
|
+
interface Todo {
|
|
13153
|
+
id: string;
|
|
13154
|
+
title: string;
|
|
13155
|
+
done: boolean;
|
|
13156
|
+
}
|
|
13157
|
+
|
|
13158
|
+
const api = {
|
|
13159
|
+
getTodos: (): Promise<Todo[]> => fetch('/api/todos').then((r) => r.json()),
|
|
13160
|
+
createTodo: (title: string): Promise<Todo> =>
|
|
13161
|
+
fetch('/api/todos', {
|
|
13162
|
+
method: 'POST',
|
|
13163
|
+
headers: { 'Content-Type': 'application/json' },
|
|
13164
|
+
body: JSON.stringify({ title }),
|
|
13165
|
+
}).then((r) => r.json()),
|
|
13166
|
+
toggleTodo: (id: string): Promise<Todo> =>
|
|
13167
|
+
fetch(\`/api/todos/\${id}/toggle\`, { method: 'PATCH' }).then((r) => r.json()),
|
|
13168
|
+
deleteTodo: (id: string): Promise<void> =>
|
|
13169
|
+
fetch(\`/api/todos/\${id}\`, { method: 'DELETE' }).then(() => undefined),
|
|
13170
|
+
};
|
|
13171
|
+
|
|
13172
|
+
export function TodoList({
|
|
13173
|
+
session,
|
|
13174
|
+
}: {
|
|
13175
|
+
session: { user: { email: string } };
|
|
13176
|
+
}) {
|
|
13177
|
+
const queryClient = useQueryClient();
|
|
13178
|
+
|
|
13179
|
+
const { data: todos = [], isPending } = useQuery({
|
|
13180
|
+
queryKey: ['todos'],
|
|
13181
|
+
queryFn: api.getTodos,
|
|
13182
|
+
});
|
|
13183
|
+
|
|
13184
|
+
const createMutation = useMutation({
|
|
13185
|
+
mutationFn: api.createTodo,
|
|
13186
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
13187
|
+
});
|
|
13188
|
+
|
|
13189
|
+
const toggleMutation = useMutation({
|
|
13190
|
+
mutationFn: api.toggleTodo,
|
|
13191
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
13192
|
+
});
|
|
13193
|
+
|
|
13194
|
+
const deleteMutation = useMutation({
|
|
13195
|
+
mutationFn: api.deleteTodo,
|
|
13196
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
13197
|
+
});
|
|
13198
|
+
|
|
13199
|
+
const form = useForm({
|
|
13200
|
+
defaultValues: { title: '' },
|
|
13201
|
+
onSubmit: async ({ value }) => {
|
|
13202
|
+
if (!value.title.trim()) return;
|
|
13203
|
+
createMutation.mutate(value.title.trim());
|
|
13204
|
+
form.reset();
|
|
13205
|
+
},
|
|
13206
|
+
});
|
|
13207
|
+
|
|
13208
|
+
return (
|
|
13209
|
+
<>
|
|
13210
|
+
<div {...stylex.props(styles.header)}>
|
|
13211
|
+
<h1 {...stylex.props(styles.h1)}>Todos</h1>
|
|
13212
|
+
<div {...stylex.props(styles.session)}>
|
|
13213
|
+
<span>{session.user.email}</span>
|
|
13214
|
+
<button
|
|
13215
|
+
{...stylex.props(styles.signOut)}
|
|
13216
|
+
onClick={() => authClient.signOut()}
|
|
13217
|
+
>
|
|
13218
|
+
Sign out
|
|
13219
|
+
</button>
|
|
13220
|
+
</div>
|
|
13221
|
+
</div>
|
|
13222
|
+
|
|
13223
|
+
<form
|
|
13224
|
+
onSubmit={(e) => {
|
|
13225
|
+
e.preventDefault();
|
|
13226
|
+
form.handleSubmit();
|
|
13227
|
+
}}
|
|
13228
|
+
{...stylex.props(styles.form)}
|
|
13229
|
+
>
|
|
13230
|
+
<form.Field name="title">
|
|
13231
|
+
{(field) => (
|
|
13232
|
+
<input
|
|
13233
|
+
value={field.state.value}
|
|
13234
|
+
onChange={(e) => field.handleChange(e.target.value)}
|
|
13235
|
+
placeholder="New todo…"
|
|
13236
|
+
{...stylex.props(styles.input)}
|
|
13237
|
+
/>
|
|
13238
|
+
)}
|
|
13239
|
+
</form.Field>
|
|
13240
|
+
|
|
13241
|
+
<form.Subscribe selector={(s) => s.isSubmitting}>
|
|
13242
|
+
{(isSubmitting) => (
|
|
13243
|
+
<Button type="submit" disabled={isSubmitting || createMutation.isPending}>
|
|
13244
|
+
Add
|
|
13245
|
+
</Button>
|
|
13246
|
+
)}
|
|
13247
|
+
</form.Subscribe>
|
|
13248
|
+
</form>
|
|
13249
|
+
|
|
13250
|
+
{isPending ? (
|
|
13251
|
+
<p {...stylex.props(styles.muted)}>Loading…</p>
|
|
13252
|
+
) : (
|
|
13253
|
+
<ul {...stylex.props(styles.list)}>
|
|
13254
|
+
{todos.map((todo) => (
|
|
13255
|
+
<li key={todo.id} {...stylex.props(styles.item)}>
|
|
13256
|
+
<input
|
|
13257
|
+
type="checkbox"
|
|
13258
|
+
checked={todo.done}
|
|
13259
|
+
onChange={() => toggleMutation.mutate(todo.id)}
|
|
13260
|
+
/>
|
|
13261
|
+
<span {...stylex.props(styles.title, todo.done && styles.titleDone)}>
|
|
13262
|
+
{todo.title}
|
|
13263
|
+
</span>
|
|
13264
|
+
<button
|
|
13265
|
+
onClick={() => deleteMutation.mutate(todo.id)}
|
|
13266
|
+
{...stylex.props(styles.remove)}
|
|
13267
|
+
>
|
|
13268
|
+
×
|
|
13269
|
+
</button>
|
|
13270
|
+
</li>
|
|
13271
|
+
))}
|
|
13272
|
+
</ul>
|
|
13273
|
+
)}
|
|
13274
|
+
|
|
13275
|
+
{!isPending && todos.length === 0 && (
|
|
13276
|
+
<p {...stylex.props(styles.muted)}>No todos yet.</p>
|
|
13277
|
+
)}
|
|
13278
|
+
</>
|
|
13279
|
+
);
|
|
13280
|
+
}
|
|
13281
|
+
|
|
13282
|
+
const styles = stylex.create({
|
|
13283
|
+
header: {
|
|
13284
|
+
display: 'flex',
|
|
13285
|
+
alignItems: 'center',
|
|
13286
|
+
justifyContent: 'space-between',
|
|
13287
|
+
marginBottom: '2rem',
|
|
13288
|
+
},
|
|
13289
|
+
h1: {
|
|
13290
|
+
fontSize: '1.5rem',
|
|
13291
|
+
fontWeight: 600,
|
|
13292
|
+
},
|
|
13293
|
+
session: {
|
|
13294
|
+
display: 'flex',
|
|
13295
|
+
alignItems: 'center',
|
|
13296
|
+
gap: '0.75rem',
|
|
13297
|
+
fontSize: '0.875rem',
|
|
13298
|
+
color: colors.mutedForeground,
|
|
13299
|
+
},
|
|
13300
|
+
signOut: {
|
|
13301
|
+
color: {
|
|
13302
|
+
default: 'inherit',
|
|
13303
|
+
':hover': colors.foreground,
|
|
13304
|
+
},
|
|
13305
|
+
backgroundColor: 'transparent',
|
|
13306
|
+
borderStyle: 'none',
|
|
13307
|
+
cursor: 'pointer',
|
|
13308
|
+
padding: 0,
|
|
13309
|
+
fontFamily: 'inherit',
|
|
13310
|
+
fontSize: 'inherit',
|
|
13311
|
+
},
|
|
13312
|
+
form: {
|
|
13313
|
+
display: 'flex',
|
|
13314
|
+
gap: '0.5rem',
|
|
13315
|
+
marginBottom: '1.5rem',
|
|
13316
|
+
},
|
|
13317
|
+
input: {
|
|
13318
|
+
flexGrow: 1,
|
|
13319
|
+
height: 36,
|
|
13320
|
+
paddingBlock: '0.25rem',
|
|
13321
|
+
paddingInline: '0.75rem',
|
|
13322
|
+
fontFamily: 'inherit',
|
|
13323
|
+
fontSize: '0.875rem',
|
|
13324
|
+
color: colors.foreground,
|
|
13325
|
+
backgroundColor: 'oklch(0.269 0 0 / 0.5)',
|
|
13326
|
+
borderColor: {
|
|
13327
|
+
default: colors.border,
|
|
13328
|
+
':focus-visible': colors.mutedForeground,
|
|
13329
|
+
},
|
|
13330
|
+
borderRadius: radii.sm,
|
|
13331
|
+
borderStyle: 'solid',
|
|
13332
|
+
borderWidth: 1,
|
|
13333
|
+
outlineStyle: 'none',
|
|
13334
|
+
transitionProperty: 'border-color',
|
|
13335
|
+
transitionDuration: '150ms',
|
|
13336
|
+
},
|
|
13337
|
+
list: {
|
|
13338
|
+
listStyleType: 'none',
|
|
13339
|
+
},
|
|
13340
|
+
item: {
|
|
13341
|
+
display: 'flex',
|
|
13342
|
+
alignItems: 'center',
|
|
13343
|
+
gap: '0.75rem',
|
|
13344
|
+
paddingBlock: '0.75rem',
|
|
13345
|
+
borderTopColor: colors.border,
|
|
13346
|
+
borderTopStyle: 'solid',
|
|
13347
|
+
borderTopWidth: {
|
|
13348
|
+
default: 1,
|
|
13349
|
+
':first-child': 0,
|
|
13350
|
+
},
|
|
13351
|
+
},
|
|
13352
|
+
title: {
|
|
13353
|
+
flexGrow: 1,
|
|
13354
|
+
fontSize: '0.875rem',
|
|
13355
|
+
},
|
|
13356
|
+
titleDone: {
|
|
13357
|
+
color: colors.mutedForeground,
|
|
13358
|
+
textDecorationLine: 'line-through',
|
|
13359
|
+
},
|
|
13360
|
+
remove: {
|
|
13361
|
+
color: {
|
|
13362
|
+
default: colors.mutedForeground,
|
|
13363
|
+
':hover': colors.danger,
|
|
13364
|
+
},
|
|
13365
|
+
backgroundColor: 'transparent',
|
|
13366
|
+
borderStyle: 'none',
|
|
13367
|
+
cursor: 'pointer',
|
|
13368
|
+
padding: 0,
|
|
13369
|
+
fontSize: '1.125rem',
|
|
13370
|
+
lineHeight: 1,
|
|
13371
|
+
},
|
|
13372
|
+
muted: {
|
|
13373
|
+
fontSize: '0.875rem',
|
|
13374
|
+
color: colors.mutedForeground,
|
|
13375
|
+
},
|
|
13376
|
+
});
|
|
13377
|
+
`
|
|
13378
|
+
};
|
|
13379
|
+
//#endregion
|
|
13380
|
+
//#region src/templates/todo-example/templates/stylex-page.ts
|
|
13381
|
+
var stylex_page_default = {
|
|
13382
|
+
when: (s) => s.todoExample && s.stylex,
|
|
13383
|
+
filename: "apps/web/app/page.tsx",
|
|
13384
|
+
template: `'use client';
|
|
13385
|
+
|
|
13386
|
+
import { useQuery } from '@tanstack/react-query';
|
|
13387
|
+
import * as stylex from '@stylexjs/stylex';
|
|
13388
|
+
import { authClient } from '@/lib/auth-client';
|
|
13389
|
+
import { AuthForm } from '@/app/auth-form';
|
|
13390
|
+
import { Link } from '@<%= projectName %>/ui/link';
|
|
13391
|
+
import { Logo } from '@<%= projectName %>/ui/logo';
|
|
13392
|
+
import { TodoList } from '@/app/todo-list';
|
|
13393
|
+
import { colors, fonts, radii } from '@<%= projectName %>/ui/tokens.stylex';
|
|
13394
|
+
|
|
13395
|
+
export default function Home() {
|
|
13396
|
+
const { data: session, isPending } = authClient.useSession();
|
|
13397
|
+
|
|
13398
|
+
const { data: hello } = useQuery({
|
|
13399
|
+
queryKey: ['hello'],
|
|
13400
|
+
queryFn: () => fetch('/api/hello').then((r) => r.json()),
|
|
13401
|
+
});
|
|
13402
|
+
|
|
13403
|
+
return (
|
|
13404
|
+
<main {...stylex.props(styles.main)}>
|
|
13405
|
+
<div {...stylex.props(styles.header)}>
|
|
13406
|
+
<p {...stylex.props(styles.mono, styles.muted)}>apps/web/app/page.tsx</p>
|
|
13407
|
+
<p {...stylex.props(styles.muted)}>Delete me to get started!</p>
|
|
13408
|
+
</div>
|
|
13409
|
+
|
|
13410
|
+
<div {...stylex.props(styles.titleRow)}>
|
|
13411
|
+
<Logo style={styles.logo} />
|
|
13412
|
+
<div>
|
|
13413
|
+
<h1 {...stylex.props(styles.h1)}><%= projectName %></h1>
|
|
13414
|
+
<p {...stylex.props(styles.muted, styles.tagline)}>
|
|
13415
|
+
Next + Nest = Newt 💜
|
|
13416
|
+
</p>
|
|
13417
|
+
</div>
|
|
13418
|
+
</div>
|
|
13419
|
+
|
|
13420
|
+
<div {...stylex.props(styles.card)}>
|
|
13421
|
+
<p {...stylex.props(styles.eyebrow)}>next.js</p>
|
|
13422
|
+
<p {...stylex.props(styles.mono, styles.muted)}>apps/web/app/layout.tsx</p>
|
|
13423
|
+
<p {...stylex.props(styles.muted)}>Next.js rendering</p>
|
|
13424
|
+
</div>
|
|
13425
|
+
|
|
13426
|
+
<div {...stylex.props(styles.card)}>
|
|
13427
|
+
<p {...stylex.props(styles.eyebrow)}>nest.js</p>
|
|
13428
|
+
<p {...stylex.props(styles.mono, styles.muted)}>GET /api/hello</p>
|
|
13429
|
+
<pre {...stylex.props(styles.pre)}>
|
|
13430
|
+
<code>{JSON.stringify(hello, null, 2)}</code>
|
|
13431
|
+
</pre>
|
|
13432
|
+
</div>
|
|
13433
|
+
|
|
13434
|
+
<div {...stylex.props(styles.card)}>
|
|
13435
|
+
<p {...stylex.props(styles.eyebrow, styles.eyebrowSpaced)}>better-auth</p>
|
|
13436
|
+
{isPending ? (
|
|
13437
|
+
<p {...stylex.props(styles.muted)}>Loading…</p>
|
|
13438
|
+
) : session ? (
|
|
13439
|
+
<TodoList session={session} />
|
|
13440
|
+
) : (
|
|
13441
|
+
<AuthForm />
|
|
13442
|
+
)}
|
|
13443
|
+
</div>
|
|
13444
|
+
|
|
13445
|
+
<div {...stylex.props(styles.footer)}>
|
|
13446
|
+
<p {...stylex.props(styles.muted)}>Learn more</p>
|
|
13447
|
+
<ul {...stylex.props(styles.list)}>
|
|
13448
|
+
<li>
|
|
13449
|
+
<Link href="https://newt-app.com">Documentation</Link>
|
|
13450
|
+
</li>
|
|
13451
|
+
<li>
|
|
13452
|
+
<Link href="https://github.com/zeevo/newt-app">GitHub</Link>
|
|
13453
|
+
</li>
|
|
13454
|
+
<li>
|
|
13455
|
+
<Link href="https://nextjs.org">Next.js</Link>
|
|
13456
|
+
</li>
|
|
13457
|
+
<li>
|
|
13458
|
+
<Link href="https://nestjs.com">NestJS</Link>
|
|
13459
|
+
</li>
|
|
13460
|
+
</ul>
|
|
13461
|
+
</div>
|
|
13462
|
+
</main>
|
|
13463
|
+
);
|
|
13464
|
+
}
|
|
13465
|
+
|
|
13466
|
+
const styles = stylex.create({
|
|
13467
|
+
main: {
|
|
13468
|
+
display: 'flex',
|
|
13469
|
+
flexDirection: 'column',
|
|
13470
|
+
gap: '1rem',
|
|
13471
|
+
maxWidth: '32rem',
|
|
13472
|
+
minHeight: '100%',
|
|
13473
|
+
marginInline: 'auto',
|
|
13474
|
+
paddingBlock: '2rem',
|
|
13475
|
+
paddingInline: '1rem',
|
|
13476
|
+
fontSize: '0.875rem',
|
|
13477
|
+
},
|
|
13478
|
+
header: {
|
|
13479
|
+
paddingBottom: '1rem',
|
|
13480
|
+
borderBottomColor: colors.border,
|
|
13481
|
+
borderBottomStyle: 'solid',
|
|
13482
|
+
borderBottomWidth: 1,
|
|
13483
|
+
},
|
|
13484
|
+
titleRow: {
|
|
13485
|
+
display: 'flex',
|
|
13486
|
+
alignItems: 'center',
|
|
13487
|
+
gap: '0.75rem',
|
|
13488
|
+
paddingBlock: '0.5rem',
|
|
13489
|
+
},
|
|
13490
|
+
logo: {
|
|
13491
|
+
width: '2.5rem',
|
|
13492
|
+
height: 'auto',
|
|
13493
|
+
},
|
|
13494
|
+
h1: {
|
|
13495
|
+
fontSize: '2.25rem',
|
|
13496
|
+
fontWeight: 900,
|
|
13497
|
+
letterSpacing: '-0.025em',
|
|
13498
|
+
},
|
|
13499
|
+
tagline: {
|
|
13500
|
+
letterSpacing: '0.1em',
|
|
13501
|
+
textTransform: 'uppercase',
|
|
13502
|
+
},
|
|
13503
|
+
card: {
|
|
13504
|
+
display: 'flex',
|
|
13505
|
+
flexDirection: 'column',
|
|
13506
|
+
gap: '0.25rem',
|
|
13507
|
+
padding: '1.5rem',
|
|
13508
|
+
borderColor: colors.border,
|
|
13509
|
+
borderRadius: radii.lg,
|
|
13510
|
+
borderStyle: 'solid',
|
|
13511
|
+
borderWidth: 1,
|
|
13512
|
+
},
|
|
13513
|
+
eyebrow: {
|
|
13514
|
+
fontFamily: fonts.mono,
|
|
13515
|
+
fontSize: '0.75rem',
|
|
13516
|
+
letterSpacing: '0.1em',
|
|
13517
|
+
textTransform: 'uppercase',
|
|
13518
|
+
color: colors.mutedForeground,
|
|
13519
|
+
},
|
|
13520
|
+
eyebrowSpaced: {
|
|
13521
|
+
marginBottom: '0.75rem',
|
|
13522
|
+
},
|
|
13523
|
+
pre: {
|
|
13524
|
+
marginTop: '0.5rem',
|
|
13525
|
+
padding: '0.75rem',
|
|
13526
|
+
fontFamily: fonts.mono,
|
|
13527
|
+
backgroundColor: 'oklch(0.269 0 0 / 0.5)',
|
|
13528
|
+
borderColor: colors.border,
|
|
13529
|
+
borderRadius: radii.sm,
|
|
13530
|
+
borderStyle: 'solid',
|
|
13531
|
+
borderWidth: 1,
|
|
13532
|
+
overflowX: 'auto',
|
|
13533
|
+
},
|
|
13534
|
+
footer: {
|
|
13535
|
+
display: 'flex',
|
|
13536
|
+
flexDirection: 'column',
|
|
13537
|
+
gap: '0.5rem',
|
|
13538
|
+
paddingBlock: '1rem',
|
|
13539
|
+
paddingInline: '0.5rem',
|
|
13540
|
+
},
|
|
13541
|
+
list: {
|
|
13542
|
+
display: 'flex',
|
|
13543
|
+
flexDirection: 'column',
|
|
13544
|
+
gap: '0.5rem',
|
|
13545
|
+
listStylePosition: 'inside',
|
|
13546
|
+
listStyleType: 'disc',
|
|
13547
|
+
},
|
|
13548
|
+
mono: {
|
|
13549
|
+
fontFamily: fonts.mono,
|
|
13550
|
+
},
|
|
13551
|
+
muted: {
|
|
13552
|
+
color: colors.mutedForeground,
|
|
13553
|
+
},
|
|
13554
|
+
});
|
|
13555
|
+
`
|
|
13556
|
+
};
|
|
13557
|
+
//#endregion
|
|
12307
13558
|
//#region src/templates/todo-example/index.ts
|
|
12308
13559
|
const todoExampleApi = { templates: [
|
|
12309
13560
|
todos_module_default,
|
|
@@ -12326,6 +13577,7 @@ const todoExampleDi = { templates: [
|
|
|
12326
13577
|
] };
|
|
12327
13578
|
const todoExampleWeb = { templates: [web_todo_list_default, web_page_default] };
|
|
12328
13579
|
const todoExampleShadcn = { templates: [shadcn_todo_list_default, shadcn_page_default] };
|
|
13580
|
+
const todoExampleStylex = { templates: [stylex_todo_list_default, stylex_page_default] };
|
|
12329
13581
|
//#endregion
|
|
12330
13582
|
//#region src/templates/index.ts
|
|
12331
13583
|
const staticDir = new URL("./static/", import.meta.url);
|
|
@@ -12339,7 +13591,7 @@ const E2E_FILES = [
|
|
|
12339
13591
|
"apps/api/vitest.config.e2e.mts"
|
|
12340
13592
|
];
|
|
12341
13593
|
function selectModules(selection) {
|
|
12342
|
-
const { deployment, nest, todoExample, shadcn, database, linter, testing, extras } = selection;
|
|
13594
|
+
const { deployment, nest, todoExample, shadcn, stylex, database, linter, testing, extras } = selection;
|
|
12343
13595
|
const deploymentModule = deployment === "standalone" ? deploymentStandalone : deployment === "spa" ? singleProcessStaticExport : null;
|
|
12344
13596
|
const webModule = deployment === "spa" ? {
|
|
12345
13597
|
...web$1,
|
|
@@ -12358,7 +13610,7 @@ function selectModules(selection) {
|
|
|
12358
13610
|
...nest === "off" ? [] : [api$1],
|
|
12359
13611
|
database === "postgres" ? dbPostgres : dbSqlite,
|
|
12360
13612
|
auth,
|
|
12361
|
-
shadcn ? shadcnUi : ui$1,
|
|
13613
|
+
shadcn ? shadcnUi : stylex ? stylexUi : ui$1,
|
|
12362
13614
|
linter === "oxc" ? oxc : eslintConfig,
|
|
12363
13615
|
...extras.includes("anti-slop") ? [antiSlop] : [],
|
|
12364
13616
|
typescriptConfig,
|
|
@@ -12369,7 +13621,7 @@ function selectModules(selection) {
|
|
|
12369
13621
|
...todoExample ? [
|
|
12370
13622
|
todoExampleApi,
|
|
12371
13623
|
...nest === "di-only" ? [todoExampleDi] : [todoExampleControllers],
|
|
12372
|
-
shadcn ? todoExampleShadcn : todoExampleWeb
|
|
13624
|
+
shadcn ? todoExampleShadcn : stylex ? todoExampleStylex : todoExampleWeb
|
|
12373
13625
|
] : []
|
|
12374
13626
|
];
|
|
12375
13627
|
}
|
|
@@ -12476,6 +13728,13 @@ function validateExtrasCombo(extras, linter) {
|
|
|
12476
13728
|
};
|
|
12477
13729
|
return { valid: true };
|
|
12478
13730
|
}
|
|
13731
|
+
function validateStylingCombo(shadcn, stylex) {
|
|
13732
|
+
if (shadcn && stylex) return {
|
|
13733
|
+
valid: false,
|
|
13734
|
+
error: "--shadcn cannot be combined with --stylex.\nshadcn/ui components are written in Tailwind utility classes, which StyleX does\nnot compile. Pick one styling system: drop --stylex for shadcn/ui, or drop\n--shadcn for StyleX."
|
|
13735
|
+
};
|
|
13736
|
+
return { valid: true };
|
|
13737
|
+
}
|
|
12479
13738
|
function validateDeploymentCombo(deployment, nest) {
|
|
12480
13739
|
if (deployment === "spa" && nest === "di-only") return {
|
|
12481
13740
|
valid: false,
|
|
@@ -12631,6 +13890,7 @@ function buildPayload(report) {
|
|
|
12631
13890
|
ci: detectCi(),
|
|
12632
13891
|
explicitFlags: [...report.explicitFlags].sort().join(","),
|
|
12633
13892
|
shadcn: selection.shadcn,
|
|
13893
|
+
stylex: selection.stylex,
|
|
12634
13894
|
testing: selection.testing,
|
|
12635
13895
|
database: selection.database,
|
|
12636
13896
|
linter: selection.linter,
|
|
@@ -12704,6 +13964,10 @@ async function doInit(options) {
|
|
|
12704
13964
|
message: "Use shadcn/ui?",
|
|
12705
13965
|
initialValue: true
|
|
12706
13966
|
}),
|
|
13967
|
+
stylex: ({ results }) => results.shadcn ? void 0 : p.confirm({
|
|
13968
|
+
message: "Use StyleX instead of Tailwind?",
|
|
13969
|
+
initialValue: false
|
|
13970
|
+
}),
|
|
12707
13971
|
nest: () => p.select({
|
|
12708
13972
|
message: "NestJS?",
|
|
12709
13973
|
options: [
|
|
@@ -12809,6 +14073,7 @@ async function doInit(options) {
|
|
|
12809
14073
|
process.exit(0);
|
|
12810
14074
|
} });
|
|
12811
14075
|
const useShadcn = options.nonInteractive ? options.shadcn : answers.shadcn ?? true;
|
|
14076
|
+
const useStylex = options.nonInteractive ? options.stylex : answers.stylex ?? false;
|
|
12812
14077
|
const testing = options.nonInteractive ? options.testing : answers.testing ?? "jest";
|
|
12813
14078
|
const database = options.nonInteractive ? options.database : answers.database ?? "sqlite";
|
|
12814
14079
|
const linter = options.nonInteractive ? options.linter : answers.linter ?? "eslint";
|
|
@@ -12816,6 +14081,8 @@ async function doInit(options) {
|
|
|
12816
14081
|
const nest = options.nonInteractive ? options.nest : answers.nest ?? "on";
|
|
12817
14082
|
const todoExample = options.nonInteractive ? options.includeExample : nest !== "off" && (answers.todoExample ?? true);
|
|
12818
14083
|
const extras = options.nonInteractive ? options.extras : answers.extras ?? [];
|
|
14084
|
+
const stylingCombo = validateStylingCombo(useShadcn, useStylex);
|
|
14085
|
+
if (!stylingCombo.valid) throw new Error(stylingCombo.error);
|
|
12819
14086
|
const deploymentCombo = validateDeploymentCombo(deployment, nest);
|
|
12820
14087
|
if (!deploymentCombo.valid) throw new Error(deploymentCombo.error);
|
|
12821
14088
|
const exampleCombo = validateExampleCombo(todoExample, nest);
|
|
@@ -12827,6 +14094,7 @@ async function doInit(options) {
|
|
|
12827
14094
|
nest,
|
|
12828
14095
|
todoExample,
|
|
12829
14096
|
shadcn: useShadcn,
|
|
14097
|
+
stylex: useStylex,
|
|
12830
14098
|
database,
|
|
12831
14099
|
linter,
|
|
12832
14100
|
testing,
|
|
@@ -12895,10 +14163,11 @@ async function doInit(options) {
|
|
|
12895
14163
|
}
|
|
12896
14164
|
}
|
|
12897
14165
|
const program = new Command();
|
|
12898
|
-
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 <mode>", "NestJS: on, off, or di-only", "on").option("--include-example", "Include the todo example", false).option("--extras <list>", "Extras, comma-separated: anti-slop", "").action(async (name, options, command) => {
|
|
14166
|
+
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("--stylex", "Use StyleX instead of Tailwind", 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 <mode>", "NestJS: on, off, or di-only", "on").option("--include-example", "Include the todo example", false).option("--extras <list>", "Extras, comma-separated: anti-slop", "").action(async (name, options, command) => {
|
|
12899
14167
|
intro(`Create a ${chalk.blue("newt")} app.`);
|
|
12900
14168
|
const explicitFlags = Object.entries({
|
|
12901
14169
|
shadcn: "--shadcn",
|
|
14170
|
+
stylex: "--stylex",
|
|
12902
14171
|
testing: "--testing",
|
|
12903
14172
|
database: "--database",
|
|
12904
14173
|
linter: "--linter",
|
|
@@ -12951,6 +14220,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12951
14220
|
git: options.git,
|
|
12952
14221
|
nonInteractive,
|
|
12953
14222
|
shadcn: options.shadcn,
|
|
14223
|
+
stylex: options.stylex,
|
|
12954
14224
|
testing: options.testing,
|
|
12955
14225
|
database: options.database,
|
|
12956
14226
|
linter: options.linter,
|