Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 7c23ab4

Browse files
feat: remove all TypeScript references when isTypeScript is passed as false to remix.init (#127)
1 parent 1dccf73 commit 7c23ab4

File tree

8 files changed

+158
-55
lines changed

8 files changed

+158
-55
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
- main
66
- dev
77
pull_request: {}
8+
89
permissions:
910
actions: write
1011
contents: read

cypress/support/create-user.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
// and it will log out the cookie value you can use to interact with the server
55
// as that new user.
66

7-
import { parse } from "cookie";
87
import { installGlobals } from "@remix-run/node";
9-
import { createUserSession } from "~/session.server";
8+
import { parse } from "cookie";
9+
1010
import { createUser } from "~/models/user.server";
11+
import { createUserSession } from "~/session.server";
1112

1213
installGlobals();
1314

cypress/support/delete-user.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
77
import { installGlobals } from "@remix-run/node";
8+
89
import { prisma } from "~/db.server";
910

1011
installGlobals();

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@
8383
"node": ">=14"
8484
},
8585
"prisma": {
86-
"seed": "node --require tsconfig-paths/register prisma/seed.js"
86+
"seed": "ts-node --require tsconfig-paths/register prisma/seed.ts"
8787
}
8888
}

prisma/seed.js renamed to prisma/seed.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const { PrismaClient } = require("@prisma/client");
2-
const bcrypt = require("bcryptjs");
1+
import { PrismaClient } from "@prisma/client";
2+
import bcrypt from "bcryptjs";
33

44
const prisma = new PrismaClient();
55

remix.init/index.js

Lines changed: 148 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,111 @@ const fs = require("fs/promises");
44
const path = require("path");
55

66
const toml = require("@iarna/toml");
7+
const PackageJson = require("@npmcli/package-json");
78
const YAML = require("yaml");
8-
const sort = require("sort-package-json");
99

10-
function escapeRegExp(string) {
10+
const cleanupCypressFiles = (filesEntries) =>
11+
filesEntries.flatMap(([filePath, content]) => {
12+
const newContent = content
13+
.replace("npx ts-node", "node")
14+
.replace("create-user.ts", "create-user.js")
15+
.replace("delete-user.ts", "delete-user.js");
16+
17+
return [fs.writeFile(filePath, newContent)];
18+
});
19+
20+
const cleanupDeployWorkflow = (deployWorkflow, deployWorkflowPath) => {
21+
delete deployWorkflow.jobs.typecheck;
22+
deployWorkflow.jobs.deploy.needs = deployWorkflow.jobs.deploy.needs.filter(
23+
(need) => need !== "typecheck"
24+
);
25+
26+
return [fs.writeFile(deployWorkflowPath, YAML.stringify(deployWorkflow))];
27+
};
28+
29+
const cleanupVitestConfig = (vitestConfig, vitestConfigPath) => {
30+
const newVitestConfig = vitestConfig.replace(
31+
"setup-test-env.ts",
32+
"setup-test-env.js"
33+
);
34+
35+
return [fs.writeFile(vitestConfigPath, newVitestConfig)];
36+
};
37+
38+
const escapeRegExp = (string) =>
1139
// $& means the whole matched string
12-
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13-
}
40+
string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1441

15-
function getRandomString(length) {
16-
return crypto.randomBytes(length).toString("hex");
17-
}
42+
const getRandomString = (length) => crypto.randomBytes(length).toString("hex");
1843

19-
async function main({ rootDirectory, packageManager, isTypeScript }) {
44+
const readFileIfNotTypeScript = (
45+
isTypeScript,
46+
filePath,
47+
parseFunction = (result) => result
48+
) =>
49+
(isTypeScript ? Promise.resolve() : fs.readFile(filePath, "utf-8")).then(
50+
parseFunction
51+
);
52+
53+
const removeUnusedDependencies = (dependencies, unusedDependencies) =>
54+
Object.fromEntries(
55+
Object.entries(dependencies).filter(
56+
([key]) => !unusedDependencies.includes(key)
57+
)
58+
);
59+
60+
const updatePackageJson = ({ APP_NAME, isTypeScript, packageJson }) => {
61+
const {
62+
devDependencies,
63+
prisma: { seed: prismaSeed, ...prisma },
64+
scripts: { typecheck, validate, ...scripts },
65+
} = packageJson.content;
66+
67+
packageJson.update({
68+
name: APP_NAME,
69+
devDependencies: isTypeScript
70+
? devDependencies
71+
: removeUnusedDependencies(devDependencies, [
72+
"ts-node",
73+
"vite-tsconfig-paths",
74+
]),
75+
prisma: isTypeScript
76+
? prisma
77+
: {
78+
...prisma,
79+
seed: prismaSeed
80+
.replace("ts-node", "node")
81+
.replace("seed.ts", "seed.js"),
82+
},
83+
scripts: isTypeScript
84+
? { ...scripts, typecheck, validate }
85+
: { ...scripts, validate: validate.replace(" typecheck", "") },
86+
});
87+
};
88+
89+
const main = async ({ isTypeScript, packageManager, rootDirectory }) => {
2090
const README_PATH = path.join(rootDirectory, "README.md");
2191
const FLY_TOML_PATH = path.join(rootDirectory, "fly.toml");
2292
const EXAMPLE_ENV_PATH = path.join(rootDirectory, ".env.example");
2393
const ENV_PATH = path.join(rootDirectory, ".env");
24-
const PACKAGE_JSON_PATH = path.join(rootDirectory, "package.json");
25-
const DEPLOY_YAML_PATH = path.join(
94+
const DEPLOY_WORKFLOW_PATH = path.join(
2695
rootDirectory,
27-
".github/workflows/deploy.yml"
96+
".github",
97+
"workflows",
98+
"deploy.yml"
2899
);
29100
const DOCKERFILE_PATH = path.join(rootDirectory, "Dockerfile");
101+
const CYPRESS_SUPPORT_PATH = path.join(rootDirectory, "cypress", "support");
102+
const CYPRESS_COMMANDS_PATH = path.join(CYPRESS_SUPPORT_PATH, "commands.js"); // We renamed this during `create-remix`
103+
const CREATE_USER_COMMAND_PATH = path.join(
104+
CYPRESS_SUPPORT_PATH,
105+
"create-user.js"
106+
); // We renamed this during `create-remix`
107+
const DELETE_USER_COMMAND_PATH = path.join(
108+
CYPRESS_SUPPORT_PATH,
109+
"delete-user.js"
110+
); // We renamed this during `create-remix`
111+
const VITEST_CONFIG_PATH = path.join(rootDirectory, "vitest.config.js"); // We renamed this during `create-remix`
30112

31113
const REPLACER = "indie-stack-template";
32114

@@ -37,15 +119,31 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
37119
// get rid of anything that's not allowed in an app name
38120
.replace(/[^a-zA-Z0-9-_]/g, "-");
39121

40-
const [prodContent, readme, env, packageJson, deployConfig, dockerfile] =
41-
await Promise.all([
42-
fs.readFile(FLY_TOML_PATH, "utf-8"),
43-
fs.readFile(README_PATH, "utf-8"),
44-
fs.readFile(EXAMPLE_ENV_PATH, "utf-8"),
45-
fs.readFile(PACKAGE_JSON_PATH, "utf-8").then((s) => JSON.parse(s)),
46-
fs.readFile(DEPLOY_YAML_PATH, "utf-8").then((s) => YAML.parse(s)),
47-
fs.readFile(DOCKERFILE_PATH, "utf-8"),
48-
]);
122+
const [
123+
prodContent,
124+
readme,
125+
env,
126+
dockerfile,
127+
cypressCommands,
128+
createUserCommand,
129+
deleteUserCommand,
130+
deployWorkflow,
131+
vitestConfig,
132+
packageJson,
133+
] = await Promise.all([
134+
fs.readFile(FLY_TOML_PATH, "utf-8"),
135+
fs.readFile(README_PATH, "utf-8"),
136+
fs.readFile(EXAMPLE_ENV_PATH, "utf-8"),
137+
fs.readFile(DOCKERFILE_PATH, "utf-8"),
138+
readFileIfNotTypeScript(isTypeScript, CYPRESS_COMMANDS_PATH),
139+
readFileIfNotTypeScript(isTypeScript, CREATE_USER_COMMAND_PATH),
140+
readFileIfNotTypeScript(isTypeScript, DELETE_USER_COMMAND_PATH),
141+
readFileIfNotTypeScript(isTypeScript, DEPLOY_WORKFLOW_PATH, (s) =>
142+
YAML.parse(s)
143+
),
144+
readFileIfNotTypeScript(isTypeScript, VITEST_CONFIG_PATH),
145+
PackageJson.load(rootDirectory),
146+
]);
49147

50148
const newEnv = env.replace(
51149
/^SESSION_SECRET=.*$/m,
@@ -60,25 +158,6 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
60158
APP_NAME
61159
);
62160

63-
let saveDeploy = null;
64-
if (!isTypeScript) {
65-
delete packageJson.scripts.typecheck;
66-
packageJson.scripts.validate = packageJson.scripts.validate.replace(
67-
" typecheck",
68-
""
69-
);
70-
71-
delete deployConfig.jobs.typecheck;
72-
deployConfig.jobs.deploy.needs = deployConfig.jobs.deploy.needs.filter(
73-
(n) => n !== "typecheck"
74-
);
75-
// only write the deploy config if it's changed
76-
saveDeploy = fs.writeFile(DEPLOY_YAML_PATH, YAML.stringify(deployConfig));
77-
}
78-
79-
const newPackageJson =
80-
JSON.stringify(sort({ ...packageJson, name: APP_NAME }), null, 2) + "\n";
81-
82161
const lockfile = {
83162
npm: "package-lock.json",
84163
yarn: "yarn.lock",
@@ -92,28 +171,49 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
92171
)
93172
: dockerfile;
94173

95-
await Promise.all([
174+
updatePackageJson({ APP_NAME, isTypeScript, packageJson });
175+
176+
const fileOperationPromises = [
96177
fs.writeFile(FLY_TOML_PATH, toml.stringify(prodToml)),
97178
fs.writeFile(README_PATH, newReadme),
98179
fs.writeFile(ENV_PATH, newEnv),
99-
fs.writeFile(PACKAGE_JSON_PATH, newPackageJson),
100180
fs.writeFile(DOCKERFILE_PATH, newDockerfile),
101-
saveDeploy,
181+
packageJson.save(),
102182
fs.copyFile(
103183
path.join(rootDirectory, "remix.init", "gitignore"),
104184
path.join(rootDirectory, ".gitignore")
105185
),
106-
fs.rm(path.join(rootDirectory, ".github/ISSUE_TEMPLATE"), {
186+
fs.rm(path.join(rootDirectory, ".github", "ISSUE_TEMPLATE"), {
107187
recursive: true,
108188
}),
109-
fs.rm(path.join(rootDirectory, ".github/PULL_REQUEST_TEMPLATE.md")),
110-
]);
189+
fs.rm(path.join(rootDirectory, ".github", "PULL_REQUEST_TEMPLATE.md")),
190+
];
191+
192+
if (!isTypeScript) {
193+
fileOperationPromises.push(
194+
...cleanupCypressFiles([
195+
[CYPRESS_COMMANDS_PATH, cypressCommands],
196+
[CREATE_USER_COMMAND_PATH, createUserCommand],
197+
[DELETE_USER_COMMAND_PATH, deleteUserCommand],
198+
])
199+
);
200+
201+
fileOperationPromises.push(
202+
...cleanupDeployWorkflow(deployWorkflow, DEPLOY_WORKFLOW_PATH)
203+
);
111204

112-
execSync(`npm run setup`, { stdio: "inherit", cwd: rootDirectory });
205+
fileOperationPromises.push(
206+
...cleanupVitestConfig(vitestConfig, VITEST_CONFIG_PATH)
207+
);
208+
}
209+
210+
await Promise.all(fileOperationPromises);
211+
212+
execSync("npm run setup", { cwd: rootDirectory, stdio: "inherit" });
113213

114214
execSync("npm run format -- --loglevel warn", {
115-
stdio: "inherit",
116215
cwd: rootDirectory,
216+
stdio: "inherit",
117217
});
118218

119219
console.log(
@@ -122,6 +222,6 @@ async function main({ rootDirectory, packageManager, isTypeScript }) {
122222
Start development with \`npm run dev\`
123223
`.trim()
124224
);
125-
}
225+
};
126226

127227
module.exports = main;

remix.init/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"license": "MIT",
66
"dependencies": {
77
"@iarna/toml": "^2.2.5",
8-
"sort-package-json": "^1.57.0",
8+
"@npmcli/package-json": "^2.0.0",
99
"yaml": "^2.1.1"
1010
}
1111
}

vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/// <reference types="vitest" />
22
/// <reference types="vite/client" />
33

4-
import { defineConfig } from "vite";
54
import react from "@vitejs/plugin-react";
5+
import { defineConfig } from "vite";
66
import tsconfigPaths from "vite-tsconfig-paths";
77

88
export default defineConfig({

0 commit comments

Comments
 (0)