Skip to content

Commit 4b546bf

Browse files
authored
fix(cli): remix detection (#4972)
# What Some remix templates doesn't package a `vite.config.*` file at their root. It's the case for the recommended starter "stack" templates: blues-stack, indie-stack and grunge-stack. As recommended in a TODO comment, it's more suitable to check for a `@remix-run/*` dependency in the package dependencies. # How - decouple vite and remix checks - retrieve the `package.json` - allow passing a `cwd` to the retrieval method - remove the "empty config file list" that can be empty for a remix stack - check that the `package.json` contains a `@remix-run/*` dependency # Test Added a fixture by running `npx create-remix@latest --template remix-run/indie-stack` in the [frameworks](/Fluf22/shadcn-ui/tree/fix/cli-remix-detection/packages/cli/test/fixtures/frameworks) folder and named it `remix-indie-stack`, if ever we want another stack as a fixture later --- Fixes #4967
1 parent 5fc9ade commit 4b546bf

74 files changed

Lines changed: 3113 additions & 14 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/good-toes-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"shadcn": patch
3+
---
4+
5+
update remix detection

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ yarn-error.log*
3333
.turbo
3434

3535
.contentlayer
36-
tsconfig.tsbuildinfo
36+
tsconfig.tsbuildinfo
37+
38+
# ide
39+
.idea
40+
.fleet
41+
.vscode

packages/shadcn/src/utils/get-package-info.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import path from "path"
22
import fs from "fs-extra"
33
import { type PackageJson } from "type-fest"
44

5-
export function getPackageInfo() {
6-
const packageJsonPath = path.join("package.json")
5+
export function getPackageInfo(
6+
cwd: string = "",
7+
shouldThrow: boolean = true
8+
): PackageJson | null {
9+
const packageJsonPath = path.join(cwd, "package.json")
710

8-
return fs.readJSONSync(packageJsonPath) as PackageJson
11+
return fs.readJSONSync(packageJsonPath, {
12+
throws: shouldThrow,
13+
}) as PackageJson
914
}

packages/shadcn/src/utils/get-project-info.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
getConfig,
77
resolveConfigPaths,
88
} from "@/src/utils/get-config"
9+
import { getPackageInfo } from "@/src/utils/get-package-info"
910
import fg from "fast-glob"
1011
import fs from "fs-extra"
1112
import { loadConfig } from "tsconfig-paths"
@@ -36,6 +37,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
3637
tailwindConfigFile,
3738
tailwindCssFile,
3839
aliasPrefix,
40+
packageJson,
3941
] = await Promise.all([
4042
fg.glob("**/{next,vite,astro}.config.*|gatsby-config.*|composer.json", {
4143
cwd,
@@ -47,6 +49,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
4749
getTailwindConfigFile(cwd),
4850
getTailwindCssFile(cwd),
4951
getTsConfigAliasPrefix(cwd),
52+
getPackageInfo(cwd, false),
5053
])
5154

5255
const isUsingAppDir = await fs.pathExists(
@@ -63,10 +66,6 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
6366
aliasPrefix,
6467
}
6568

66-
if (!configFiles.length) {
67-
return type
68-
}
69-
7069
// Next.js.
7170
if (configFiles.find((file) => file.startsWith("next.config."))?.length) {
7271
type.framework = isUsingAppDir
@@ -94,13 +93,21 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
9493
return type
9594
}
9695

97-
// Vite and Remix.
98-
// They both have a vite.config.* file.
96+
// Remix.
97+
if (
98+
Object.keys(packageJson?.dependencies ?? {}).find((dep) =>
99+
dep.startsWith("@remix-run/")
100+
)
101+
) {
102+
type.framework = FRAMEWORKS["remix"]
103+
return type
104+
}
105+
106+
// Vite.
107+
// Some Remix templates also have a vite.config.* file.
108+
// We'll assume that it got caught by the Remix check above.
99109
if (configFiles.find((file) => file.startsWith("vite.config."))?.length) {
100-
// We'll assume that if the project has an app dir, it's a Remix project.
101-
// Otherwise, it's a Vite project.
102-
// TODO: Maybe check for `@remix-run/react` in package.json?
103-
type.framework = isUsingAppDir ? FRAMEWORKS["remix"] : FRAMEWORKS["vite"]
110+
type.framework = FRAMEWORKS["vite"]
104111
return type
105112
}
106113

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/node_modules
2+
*.log
3+
.DS_Store
4+
.env
5+
/.cache
6+
/public/build
7+
/build
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DATABASE_URL="file:./data.db?connection_limit=1"
2+
SESSION_SECRET="super-duper-s3cret"
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/**
2+
* This is intended to be a basic starting point for linting in the Indie Stack.
3+
* It relies on recommended configs out of the box for simplicity, but you can
4+
* and should modify this configuration to best suit your team's needs.
5+
*/
6+
7+
/** @type {import('eslint').Linter.Config} */
8+
module.exports = {
9+
root: true,
10+
parserOptions: {
11+
ecmaVersion: "latest",
12+
sourceType: "module",
13+
ecmaFeatures: {
14+
jsx: true,
15+
},
16+
},
17+
env: {
18+
browser: true,
19+
commonjs: true,
20+
es6: true,
21+
},
22+
23+
// Base config
24+
extends: ["eslint:recommended"],
25+
26+
overrides: [
27+
// React
28+
{
29+
files: ["**/*.{js,jsx,ts,tsx}"],
30+
plugins: ["react", "jsx-a11y"],
31+
extends: [
32+
"plugin:react/recommended",
33+
"plugin:react/jsx-runtime",
34+
"plugin:react-hooks/recommended",
35+
"plugin:jsx-a11y/recommended",
36+
"prettier",
37+
],
38+
settings: {
39+
react: {
40+
version: "detect",
41+
},
42+
formComponents: ["Form"],
43+
linkComponents: [
44+
{ name: "Link", linkAttribute: "to" },
45+
{ name: "NavLink", linkAttribute: "to" },
46+
],
47+
},
48+
rules: {
49+
"react/jsx-no-leaked-render": [
50+
"warn",
51+
{ validStrategies: ["ternary"] },
52+
],
53+
},
54+
},
55+
56+
// Typescript
57+
{
58+
files: ["**/*.{ts,tsx}"],
59+
plugins: ["@typescript-eslint", "import"],
60+
parser: "@typescript-eslint/parser",
61+
settings: {
62+
"import/internal-regex": "^~/",
63+
"import/resolver": {
64+
node: {
65+
extensions: [".ts", ".tsx"],
66+
},
67+
typescript: {
68+
alwaysTryTypes: true,
69+
},
70+
},
71+
},
72+
extends: [
73+
"plugin:@typescript-eslint/recommended",
74+
"plugin:@typescript-eslint/stylistic",
75+
"plugin:import/recommended",
76+
"plugin:import/typescript",
77+
"prettier",
78+
],
79+
rules: {
80+
"import/order": [
81+
"error",
82+
{
83+
alphabetize: { caseInsensitive: true, order: "asc" },
84+
groups: ["builtin", "external", "internal", "parent", "sibling"],
85+
"newlines-between": "always",
86+
},
87+
],
88+
},
89+
},
90+
91+
// Markdown
92+
{
93+
files: ["**/*.md"],
94+
plugins: ["markdown"],
95+
extends: ["plugin:markdown/recommended-legacy", "prettier"],
96+
},
97+
98+
// Jest/Vitest
99+
{
100+
files: ["**/*.test.{js,jsx,ts,tsx}"],
101+
plugins: ["jest", "jest-dom", "testing-library"],
102+
extends: [
103+
"plugin:jest/recommended",
104+
"plugin:jest-dom/recommended",
105+
"plugin:testing-library/react",
106+
"prettier",
107+
],
108+
env: {
109+
"jest/globals": true,
110+
},
111+
settings: {
112+
jest: {
113+
// we're using vitest which has a very similar API to jest
114+
// (so the linting plugins work nicely), but it means we have to explicitly
115+
// set the jest version.
116+
version: 28,
117+
},
118+
},
119+
},
120+
121+
// Cypress
122+
{
123+
files: ["cypress/**/*.ts"],
124+
plugins: ["cypress"],
125+
extends: ["plugin:cypress/recommended", "prettier"],
126+
},
127+
128+
// Node
129+
{
130+
files: [".eslintrc.js", "mocks/**/*.js"],
131+
env: {
132+
node: true,
133+
},
134+
},
135+
],
136+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: 🐛 Bug Report
2+
description: Something is wrong with the Stack.
3+
body:
4+
- type: markdown
5+
attributes:
6+
value: >-
7+
Thank you for helping to improve Remix!
8+
9+
Our bandwidth on maintaining these stacks is limited. As a team, we're
10+
currently focusing our efforts on Remix itself. The good news is you can
11+
fork and adjust this stack however you'd like and start using it today
12+
as a custom stack. Learn more from
13+
[the Remix Stacks docs](https://remix.run/stacks).
14+
15+
If you'd still like to report a bug, please fill out this form. We can't
16+
promise a timely response, but hopefully when we have the bandwidth to
17+
work on these stacks again we can take a look. Thanks!
18+
19+
- type: input
20+
attributes:
21+
label: Have you experienced this bug with the latest version of the template?
22+
validations:
23+
required: true
24+
- type: textarea
25+
attributes:
26+
label: Steps to Reproduce
27+
description: Steps to reproduce the behavior.
28+
validations:
29+
required: true
30+
- type: textarea
31+
attributes:
32+
label: Expected Behavior
33+
description: A concise description of what you expected to happen.
34+
validations:
35+
required: true
36+
- type: textarea
37+
attributes:
38+
label: Actual Behavior
39+
description: A concise description of what you're experiencing.
40+
validations:
41+
required: true
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Get Help
4+
url: https://github.com/remix-run/remix/discussions/new?category=q-a
5+
about:
6+
If you can't get something to work the way you expect, open a question in
7+
the Remix discussions.
8+
- name: Feature Request
9+
url: https://github.com/remix-run/remix/discussions/new?category=ideas
10+
about:
11+
We appreciate you taking the time to improve Remix with your ideas, but we
12+
use the Remix Discussions for this instead of the issues tab 🙂.
13+
- name: 💬 Remix Discord Channel
14+
url: https://rmx.as/discord
15+
about: Interact with other people using Remix 💿
16+
- name: 💬 New Updates (Twitter)
17+
url: https://twitter.com/remix_run
18+
about: Stay up to date with Remix news on twitter
19+
- name: 🍿 Remix YouTube Channel
20+
url: https://rmx.as/youtube
21+
about: Are you a tech lead or wanting to learn more about Remix in depth? Checkout the Remix YouTube Channel
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!--
2+
3+
👋 Hey, thanks for your interest in contributing to Remix!
4+
5+
Our bandwidth on maintaining these stacks is limited. As a team, we're currently
6+
focusing our efforts on Remix itself. The good news is you can fork and adjust
7+
this stack however you'd like and start using it today as a custom stack. Learn
8+
more from [the Remix Stacks docs](https://remix.run/stacks).
9+
10+
You're still welcome to make a PR. We can't promise a timely response, but
11+
hopefully when we have the bandwidth to work on these stacks again we can take
12+
a look. Thanks!
13+
14+
-->

0 commit comments

Comments
 (0)