create-newt-app 0.32.1 → 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 +1443 -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
|
|
|
@@ -1258,11 +1259,10 @@ const dbPostgres = { templates: [
|
|
|
1258
1259
|
src_index_postgres_default
|
|
1259
1260
|
] };
|
|
1260
1261
|
//#endregion
|
|
1261
|
-
//#region src/templates/ui/
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
template: `{
|
|
1262
|
+
//#region src/templates/ui/templates/package-json.ts
|
|
1263
|
+
var package_json_default$4 = {
|
|
1264
|
+
filename: "packages/ui/package.json",
|
|
1265
|
+
template: `{
|
|
1266
1266
|
"name": "@<%= projectName %>/ui",
|
|
1267
1267
|
"version": "0.0.0",
|
|
1268
1268
|
"private": true,
|
|
@@ -1294,10 +1294,12 @@ const ui$1 = { templates: [
|
|
|
1294
1294
|
"tailwind-merge": "<%= versions["tailwind-merge"] %>"
|
|
1295
1295
|
}
|
|
1296
1296
|
}`
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
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";
|
|
1301
1303
|
|
|
1302
1304
|
import { ReactNode } from "react";
|
|
1303
1305
|
import { cn } from "./utils";
|
|
@@ -1329,10 +1331,12 @@ export const Button = ({ children, onClick, type = "button", disabled, className
|
|
|
1329
1331
|
</button>
|
|
1330
1332
|
);
|
|
1331
1333
|
};`
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
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";
|
|
1336
1340
|
import { type PropsWithChildren } from "react";
|
|
1337
1341
|
import { cn } from "./utils";
|
|
1338
1342
|
|
|
@@ -1355,10 +1359,12 @@ export function Link({
|
|
|
1355
1359
|
</NextLink>
|
|
1356
1360
|
);
|
|
1357
1361
|
}`
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
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";
|
|
1362
1368
|
|
|
1363
1369
|
interface LogoProps {
|
|
1364
1370
|
className?: string;
|
|
@@ -1381,19 +1387,23 @@ export function Logo({ className }: LogoProps) {
|
|
|
1381
1387
|
</svg>
|
|
1382
1388
|
);
|
|
1383
1389
|
}`
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
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";
|
|
1388
1396
|
import { twMerge } from "tailwind-merge";
|
|
1389
1397
|
|
|
1390
1398
|
export function cn(...inputs: ClassValue[]) {
|
|
1391
1399
|
return twMerge(clsx(inputs));
|
|
1392
1400
|
}`
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
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';
|
|
1397
1407
|
@source "../../../apps/**/*.{ts,tsx}";
|
|
1398
1408
|
@source "../**/*.{ts,tsx}";
|
|
1399
1409
|
|
|
@@ -1430,20 +1440,24 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1430
1440
|
border-color: var(--border);
|
|
1431
1441
|
}
|
|
1432
1442
|
}`
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
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 = {
|
|
1437
1449
|
plugins: {
|
|
1438
1450
|
"@tailwindcss/postcss": {},
|
|
1439
1451
|
},
|
|
1440
1452
|
};
|
|
1441
1453
|
|
|
1442
1454
|
export default config;`
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1455
|
+
};
|
|
1456
|
+
//#endregion
|
|
1457
|
+
//#region src/templates/ui/templates/tsconfig.ts
|
|
1458
|
+
var tsconfig_default$1 = {
|
|
1459
|
+
filename: "packages/ui/tsconfig.json",
|
|
1460
|
+
template: `{
|
|
1447
1461
|
"extends": "@<%= projectName %>/typescript-config/react-library.json",
|
|
1448
1462
|
"compilerOptions": {
|
|
1449
1463
|
"outDir": "dist",
|
|
@@ -1452,11 +1466,24 @@ export default config;`
|
|
|
1452
1466
|
"include": ["src"],
|
|
1453
1467
|
"exclude": ["node_modules", "dist"]
|
|
1454
1468
|
}`
|
|
1455
|
-
|
|
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
|
|
1456
1481
|
] };
|
|
1457
1482
|
//#endregion
|
|
1458
1483
|
//#region src/templates/versions.ts
|
|
1459
1484
|
const versions = {
|
|
1485
|
+
"@babel/plugin-proposal-decorators": "^8.0.2",
|
|
1486
|
+
"@babel/plugin-transform-class-properties": "^8.0.1",
|
|
1460
1487
|
"@base-ui/react": "^1.6.0",
|
|
1461
1488
|
"@eslint/js": "^9.39.1",
|
|
1462
1489
|
"@nestjs/cli": "^11.0.0",
|
|
@@ -1469,6 +1496,9 @@ const versions = {
|
|
|
1469
1496
|
"@next/eslint-plugin-next": "^16.3.4",
|
|
1470
1497
|
"@oxlint/plugins": "^1.74.0",
|
|
1471
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",
|
|
1472
1502
|
"@swc/core": "^1.10.0",
|
|
1473
1503
|
"@tailwindcss/postcss": "^4.2.1",
|
|
1474
1504
|
"@tanstack/react-form": "^1.28.5",
|
|
@@ -1484,6 +1514,7 @@ const versions = {
|
|
|
1484
1514
|
"@types/supertest": "^6.0.2",
|
|
1485
1515
|
"@vitest/coverage-v8": "^4.1.10",
|
|
1486
1516
|
auth: "^1.5.5",
|
|
1517
|
+
"babel-plugin-transform-typescript-metadata": "^0.4.0",
|
|
1487
1518
|
"better-auth": "^1.2.8",
|
|
1488
1519
|
"better-sqlite3": "^12.11.1",
|
|
1489
1520
|
"class-variance-authority": "^0.7.1",
|
|
@@ -9829,154 +9860,953 @@ export {
|
|
|
9829
9860
|
}]
|
|
9830
9861
|
};
|
|
9831
9862
|
//#endregion
|
|
9832
|
-
//#region src/templates/
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
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",
|
|
9837
9869
|
"version": "0.0.0",
|
|
9838
|
-
"type": "module",
|
|
9839
9870
|
"private": true,
|
|
9840
9871
|
"exports": {
|
|
9841
|
-
"./
|
|
9842
|
-
"./
|
|
9843
|
-
"
|
|
9872
|
+
"./globals.css": "./src/globals.css",
|
|
9873
|
+
"./tokens.stylex": "./src/tokens.stylex.ts",
|
|
9874
|
+
"./*": "./src/*.tsx"
|
|
9875
|
+
},
|
|
9876
|
+
"scripts": {
|
|
9877
|
+
"typecheck": "tsc --noEmit"
|
|
9844
9878
|
},
|
|
9845
9879
|
"devDependencies": {
|
|
9846
|
-
"
|
|
9847
|
-
"@
|
|
9848
|
-
"
|
|
9849
|
-
"
|
|
9850
|
-
"
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
"
|
|
9854
|
-
"
|
|
9855
|
-
"
|
|
9856
|
-
|
|
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"] %>"
|
|
9857
9893
|
}
|
|
9858
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
|
+
);
|
|
9859
9951
|
};
|
|
9860
|
-
//#endregion
|
|
9861
|
-
//#region src/templates/eslint-config/templates/base.ts
|
|
9862
|
-
var base_default$1 = {
|
|
9863
|
-
filename: "packages/eslint-config/base.js",
|
|
9864
|
-
template: `import js from "@eslint/js";
|
|
9865
|
-
import eslintConfigPrettier from "eslint-config-prettier";
|
|
9866
|
-
import turboPlugin from "eslint-plugin-turbo";
|
|
9867
|
-
import tseslint from "typescript-eslint";
|
|
9868
|
-
import onlyWarn from "eslint-plugin-only-warn";
|
|
9869
9952
|
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
9884
|
-
|
|
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)",
|
|
9885
9970
|
},
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
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",
|
|
9890
9982
|
},
|
|
9983
|
+
outlineWidth: 2,
|
|
9891
9984
|
},
|
|
9892
|
-
{
|
|
9893
|
-
|
|
9985
|
+
disabled: {
|
|
9986
|
+
opacity: 0.5,
|
|
9987
|
+
pointerEvents: "none",
|
|
9894
9988
|
},
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
import
|
|
9903
|
-
import
|
|
9904
|
-
import
|
|
9905
|
-
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
9906
|
-
import pluginReact from "eslint-plugin-react";
|
|
9907
|
-
import globals from "globals";
|
|
9908
|
-
import pluginNext from "@next/eslint-plugin-next";
|
|
9909
|
-
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";
|
|
9910
9999
|
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
"
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
...pluginReact.configs.flat.recommended.languageOptions,
|
|
9932
|
-
globals: {
|
|
9933
|
-
...globals.serviceworker,
|
|
9934
|
-
...globals.node,
|
|
9935
|
-
},
|
|
9936
|
-
},
|
|
9937
|
-
},
|
|
9938
|
-
{
|
|
9939
|
-
plugins: {
|
|
9940
|
-
"@next/next": pluginNext,
|
|
9941
|
-
},
|
|
9942
|
-
rules: {
|
|
9943
|
-
...pluginNext.configs.recommended.rules,
|
|
9944
|
-
...pluginNext.configs["core-web-vitals"].rules,
|
|
9945
|
-
},
|
|
9946
|
-
},
|
|
9947
|
-
{
|
|
9948
|
-
plugins: {
|
|
9949
|
-
"react-hooks": pluginReactHooks,
|
|
9950
|
-
},
|
|
9951
|
-
settings: { react: { version: "detect" } },
|
|
9952
|
-
rules: {
|
|
9953
|
-
...pluginReactHooks.configs.recommended.rules,
|
|
9954
|
-
// React scope no longer necessary with new JSX transform.
|
|
9955
|
-
"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,
|
|
9956
10020
|
},
|
|
10021
|
+
transitionProperty: "text-decoration-color",
|
|
10022
|
+
transitionDuration: "150ms",
|
|
9957
10023
|
},
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
import
|
|
9966
|
-
import tseslint from "typescript-eslint";
|
|
9967
|
-
import pluginReactHooks from "eslint-plugin-react-hooks";
|
|
9968
|
-
import pluginReact from "eslint-plugin-react";
|
|
9969
|
-
import globals from "globals";
|
|
9970
|
-
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";
|
|
9971
10032
|
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
export
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
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,
|
|
9980
10810
|
...tseslint.configs.recommended,
|
|
9981
10811
|
pluginReact.configs.flat.recommended,
|
|
9982
10812
|
{
|
|
@@ -11095,6 +11925,7 @@ export async function GET() {
|
|
|
11095
11925
|
}`
|
|
11096
11926
|
},
|
|
11097
11927
|
{
|
|
11928
|
+
when: (s) => !s.stylex,
|
|
11098
11929
|
filename: "apps/web/package.json",
|
|
11099
11930
|
template: `{
|
|
11100
11931
|
"name": "web",
|
|
@@ -11968,7 +12799,7 @@ export function TodoList({
|
|
|
11968
12799
|
//#endregion
|
|
11969
12800
|
//#region src/templates/todo-example/templates/web-page.ts
|
|
11970
12801
|
var web_page_default = {
|
|
11971
|
-
when: (s) => s.todoExample && !s.shadcn,
|
|
12802
|
+
when: (s) => s.todoExample && !s.shadcn && !s.stylex,
|
|
11972
12803
|
filename: "apps/web/app/page.tsx",
|
|
11973
12804
|
template: `'use client';
|
|
11974
12805
|
|
|
@@ -12306,6 +13137,424 @@ export default function Home() {
|
|
|
12306
13137
|
}`
|
|
12307
13138
|
};
|
|
12308
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
|
|
12309
13558
|
//#region src/templates/todo-example/index.ts
|
|
12310
13559
|
const todoExampleApi = { templates: [
|
|
12311
13560
|
todos_module_default,
|
|
@@ -12328,6 +13577,7 @@ const todoExampleDi = { templates: [
|
|
|
12328
13577
|
] };
|
|
12329
13578
|
const todoExampleWeb = { templates: [web_todo_list_default, web_page_default] };
|
|
12330
13579
|
const todoExampleShadcn = { templates: [shadcn_todo_list_default, shadcn_page_default] };
|
|
13580
|
+
const todoExampleStylex = { templates: [stylex_todo_list_default, stylex_page_default] };
|
|
12331
13581
|
//#endregion
|
|
12332
13582
|
//#region src/templates/index.ts
|
|
12333
13583
|
const staticDir = new URL("./static/", import.meta.url);
|
|
@@ -12341,7 +13591,7 @@ const E2E_FILES = [
|
|
|
12341
13591
|
"apps/api/vitest.config.e2e.mts"
|
|
12342
13592
|
];
|
|
12343
13593
|
function selectModules(selection) {
|
|
12344
|
-
const { deployment, nest, todoExample, shadcn, database, linter, testing, extras } = selection;
|
|
13594
|
+
const { deployment, nest, todoExample, shadcn, stylex, database, linter, testing, extras } = selection;
|
|
12345
13595
|
const deploymentModule = deployment === "standalone" ? deploymentStandalone : deployment === "spa" ? singleProcessStaticExport : null;
|
|
12346
13596
|
const webModule = deployment === "spa" ? {
|
|
12347
13597
|
...web$1,
|
|
@@ -12360,7 +13610,7 @@ function selectModules(selection) {
|
|
|
12360
13610
|
...nest === "off" ? [] : [api$1],
|
|
12361
13611
|
database === "postgres" ? dbPostgres : dbSqlite,
|
|
12362
13612
|
auth,
|
|
12363
|
-
shadcn ? shadcnUi : ui$1,
|
|
13613
|
+
shadcn ? shadcnUi : stylex ? stylexUi : ui$1,
|
|
12364
13614
|
linter === "oxc" ? oxc : eslintConfig,
|
|
12365
13615
|
...extras.includes("anti-slop") ? [antiSlop] : [],
|
|
12366
13616
|
typescriptConfig,
|
|
@@ -12371,7 +13621,7 @@ function selectModules(selection) {
|
|
|
12371
13621
|
...todoExample ? [
|
|
12372
13622
|
todoExampleApi,
|
|
12373
13623
|
...nest === "di-only" ? [todoExampleDi] : [todoExampleControllers],
|
|
12374
|
-
shadcn ? todoExampleShadcn : todoExampleWeb
|
|
13624
|
+
shadcn ? todoExampleShadcn : stylex ? todoExampleStylex : todoExampleWeb
|
|
12375
13625
|
] : []
|
|
12376
13626
|
];
|
|
12377
13627
|
}
|
|
@@ -12478,6 +13728,13 @@ function validateExtrasCombo(extras, linter) {
|
|
|
12478
13728
|
};
|
|
12479
13729
|
return { valid: true };
|
|
12480
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
|
+
}
|
|
12481
13738
|
function validateDeploymentCombo(deployment, nest) {
|
|
12482
13739
|
if (deployment === "spa" && nest === "di-only") return {
|
|
12483
13740
|
valid: false,
|
|
@@ -12633,6 +13890,7 @@ function buildPayload(report) {
|
|
|
12633
13890
|
ci: detectCi(),
|
|
12634
13891
|
explicitFlags: [...report.explicitFlags].sort().join(","),
|
|
12635
13892
|
shadcn: selection.shadcn,
|
|
13893
|
+
stylex: selection.stylex,
|
|
12636
13894
|
testing: selection.testing,
|
|
12637
13895
|
database: selection.database,
|
|
12638
13896
|
linter: selection.linter,
|
|
@@ -12706,6 +13964,10 @@ async function doInit(options) {
|
|
|
12706
13964
|
message: "Use shadcn/ui?",
|
|
12707
13965
|
initialValue: true
|
|
12708
13966
|
}),
|
|
13967
|
+
stylex: ({ results }) => results.shadcn ? void 0 : p.confirm({
|
|
13968
|
+
message: "Use StyleX instead of Tailwind?",
|
|
13969
|
+
initialValue: false
|
|
13970
|
+
}),
|
|
12709
13971
|
nest: () => p.select({
|
|
12710
13972
|
message: "NestJS?",
|
|
12711
13973
|
options: [
|
|
@@ -12811,6 +14073,7 @@ async function doInit(options) {
|
|
|
12811
14073
|
process.exit(0);
|
|
12812
14074
|
} });
|
|
12813
14075
|
const useShadcn = options.nonInteractive ? options.shadcn : answers.shadcn ?? true;
|
|
14076
|
+
const useStylex = options.nonInteractive ? options.stylex : answers.stylex ?? false;
|
|
12814
14077
|
const testing = options.nonInteractive ? options.testing : answers.testing ?? "jest";
|
|
12815
14078
|
const database = options.nonInteractive ? options.database : answers.database ?? "sqlite";
|
|
12816
14079
|
const linter = options.nonInteractive ? options.linter : answers.linter ?? "eslint";
|
|
@@ -12818,6 +14081,8 @@ async function doInit(options) {
|
|
|
12818
14081
|
const nest = options.nonInteractive ? options.nest : answers.nest ?? "on";
|
|
12819
14082
|
const todoExample = options.nonInteractive ? options.includeExample : nest !== "off" && (answers.todoExample ?? true);
|
|
12820
14083
|
const extras = options.nonInteractive ? options.extras : answers.extras ?? [];
|
|
14084
|
+
const stylingCombo = validateStylingCombo(useShadcn, useStylex);
|
|
14085
|
+
if (!stylingCombo.valid) throw new Error(stylingCombo.error);
|
|
12821
14086
|
const deploymentCombo = validateDeploymentCombo(deployment, nest);
|
|
12822
14087
|
if (!deploymentCombo.valid) throw new Error(deploymentCombo.error);
|
|
12823
14088
|
const exampleCombo = validateExampleCombo(todoExample, nest);
|
|
@@ -12829,6 +14094,7 @@ async function doInit(options) {
|
|
|
12829
14094
|
nest,
|
|
12830
14095
|
todoExample,
|
|
12831
14096
|
shadcn: useShadcn,
|
|
14097
|
+
stylex: useStylex,
|
|
12832
14098
|
database,
|
|
12833
14099
|
linter,
|
|
12834
14100
|
testing,
|
|
@@ -12897,10 +14163,11 @@ async function doInit(options) {
|
|
|
12897
14163
|
}
|
|
12898
14164
|
}
|
|
12899
14165
|
const program = new Command();
|
|
12900
|
-
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) => {
|
|
12901
14167
|
intro(`Create a ${chalk.blue("newt")} app.`);
|
|
12902
14168
|
const explicitFlags = Object.entries({
|
|
12903
14169
|
shadcn: "--shadcn",
|
|
14170
|
+
stylex: "--stylex",
|
|
12904
14171
|
testing: "--testing",
|
|
12905
14172
|
database: "--database",
|
|
12906
14173
|
linter: "--linter",
|
|
@@ -12953,6 +14220,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12953
14220
|
git: options.git,
|
|
12954
14221
|
nonInteractive,
|
|
12955
14222
|
shadcn: options.shadcn,
|
|
14223
|
+
stylex: options.stylex,
|
|
12956
14224
|
testing: options.testing,
|
|
12957
14225
|
database: options.database,
|
|
12958
14226
|
linter: options.linter,
|