@cedarjs/codemods 2.8.1-next.116 → 2.8.1-rc.3
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/codemods.js +2 -8
- package/package.json +9 -8
- package/dist/codemods/v3.x/prismaV7/prismaV7.js +0 -77
- package/dist/codemods/v3.x/prismaV7/prismaV7.yargs.js +0 -158
- package/dist/codemods/v3.x/prismaV7/rewriteRemainingImports.js +0 -61
- package/dist/codemods/v3.x/prismaV7/updateApiPackageJson.js +0 -71
- package/dist/codemods/v3.x/prismaV7/updateDbFile.js +0 -248
- package/dist/codemods/v3.x/prismaV7/updateEnvDefaults.js +0 -39
- package/dist/codemods/v3.x/prismaV7/updateGitignore.js +0 -32
- package/dist/codemods/v3.x/prismaV7/updatePrismaConfig.js +0 -48
- package/dist/codemods/v3.x/prismaV7/updateSchemaFile.js +0 -98
- package/dist/codemods/v3.x/prismaV7/updateTsConfigs.js +0 -73
package/dist/codemods.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { hideBin } from "yargs/helpers";
|
|
3
3
|
import yargs from "yargs/yargs";
|
|
4
|
-
import { loadEnvFiles } from "@cedarjs/cli-helpers";
|
|
5
4
|
import * as v2TsconfigForRouteHooks from "./codemods/redwood/v2.3.x/tsconfigForRouteHooks/tsconfigForRouteHooks.yargs.js";
|
|
6
5
|
import * as v2ConfigureFastify from "./codemods/redwood/v2.x.x/configureFastify/configureFastify.yargs.js";
|
|
7
6
|
import * as v2UpdateResolverTypes from "./codemods/redwood/v2.x.x/updateResolverTypes/updateResolverTypes.yargs.js";
|
|
@@ -23,14 +22,9 @@ import * as v6ThemeConfig from "./codemods/redwood/v6.x.x/updateThemeConfig/upda
|
|
|
23
22
|
import * as v7Gql from "./codemods/redwood/v7.x.x/updateGraphQLConfig/updateGraphqlConfig.yargs.js";
|
|
24
23
|
import * as v2MoveGeneratorTemplates from "./codemods/v2.3.x/moveGeneratorTemplates/moveGeneratorTemplates.yargs.js";
|
|
25
24
|
import * as v2PrismaV7Prep from "./codemods/v2.7.x/prismaV7Prep/prismaV7Prep.yargs.js";
|
|
26
|
-
|
|
27
|
-
loadEnvFiles();
|
|
28
|
-
yargs(hideBin(process.argv)).scriptName("").command(v2MoveGeneratorTemplates).command(v2PrismaV7Prep).command(v3PrismaV7).command("redwood", "List or run Redwood codemods", (yargs2) => {
|
|
25
|
+
yargs(hideBin(process.argv)).scriptName("").command(v2MoveGeneratorTemplates).command(v2PrismaV7Prep).command("redwood", "List or run Redwood codemods", (yargs2) => {
|
|
29
26
|
return yargs2.command(v2TsconfigForRouteHooks).command(v2ConfigureFastify).command(v2UpdateResolverTypes).command(v4UpdateClerkGetCurrentUser).command(v4UseArmor).command(v5CellQueryResult).command(v5DetectEmptyCells).command(v5RenameValidateWith).command(v5UpdateAuth0ToV2).command(v5UpdateNodeEngineTo18).command(v5UpgradeToReact18).command(v6GlobalThis).command(v6Jsx).command(v6EntryClient).command(v6EnvDot).command(v6Svgs).command(v6DevFatalErrorPage).command(v6ThemeConfig).command(v7Gql).demandCommand().strict();
|
|
30
|
-
}).demandCommand().
|
|
31
|
-
describe: "Load additional .env files. Values defined in files specified later override earlier ones.",
|
|
32
|
-
array: true
|
|
33
|
-
}).epilog(
|
|
27
|
+
}).demandCommand().epilog(
|
|
34
28
|
[
|
|
35
29
|
"Examples:",
|
|
36
30
|
" npx @cedarjs/codemods@latest <codemod> Run a Cedar codemod",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/codemods",
|
|
3
|
-
"version": "2.8.1-
|
|
3
|
+
"version": "2.8.1-rc.3",
|
|
4
4
|
"description": "Codemods to ease upgrading a CedarJS Project",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,16 +26,17 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@babel/cli": "7.28.6",
|
|
28
28
|
"@babel/core": "^7.26.10",
|
|
29
|
-
"@babel/parser": "7.29.
|
|
29
|
+
"@babel/parser": "7.29.0",
|
|
30
30
|
"@babel/plugin-transform-typescript": "^7.26.8",
|
|
31
|
+
"@babel/runtime-corejs3": "7.29.0",
|
|
31
32
|
"@babel/traverse": "7.29.0",
|
|
32
|
-
"@cedarjs/
|
|
33
|
-
"@cedarjs/project-config": "2.8.1-next.116+784d2c048",
|
|
33
|
+
"@cedarjs/project-config": "2.8.1-rc.3",
|
|
34
34
|
"@svgr/core": "8.1.0",
|
|
35
35
|
"@svgr/plugin-jsx": "8.1.0",
|
|
36
|
-
"@vscode/ripgrep": "1.17.
|
|
36
|
+
"@vscode/ripgrep": "1.17.0",
|
|
37
37
|
"@whatwg-node/fetch": "0.10.13",
|
|
38
38
|
"cheerio": "1.2.0",
|
|
39
|
+
"core-js": "3.48.0",
|
|
39
40
|
"deepmerge": "4.3.1",
|
|
40
41
|
"execa": "5.1.1",
|
|
41
42
|
"fast-glob": "3.3.3",
|
|
@@ -48,11 +49,11 @@
|
|
|
48
49
|
"yargs": "17.7.2"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
|
-
"@cedarjs/framework-tools": "2.8.1-
|
|
52
|
+
"@cedarjs/framework-tools": "2.8.1-rc.3",
|
|
52
53
|
"@types/babel__core": "7.20.5",
|
|
53
54
|
"@types/jscodeshift": "17.3.0",
|
|
54
55
|
"@types/yargs": "17.0.35",
|
|
55
|
-
"memfs": "4.56.
|
|
56
|
+
"memfs": "4.56.10",
|
|
56
57
|
"publint": "0.3.18",
|
|
57
58
|
"ts-dedent": "2.2.0",
|
|
58
59
|
"tsx": "4.21.0",
|
|
@@ -61,5 +62,5 @@
|
|
|
61
62
|
"publishConfig": {
|
|
62
63
|
"access": "public"
|
|
63
64
|
},
|
|
64
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "f778a5b70b97c0b129246e918083f42c63a6dc0a"
|
|
65
66
|
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { getSchemaPath, getPaths } from "@cedarjs/project-config";
|
|
4
|
-
import runTransform from "../../../lib/runTransform.js";
|
|
5
|
-
import rewriteRemainingImports from "./rewriteRemainingImports.js";
|
|
6
|
-
import { updateApiPackageJson } from "./updateApiPackageJson.js";
|
|
7
|
-
import { checkDotEnv, updateEnvDefaults } from "./updateEnvDefaults.js";
|
|
8
|
-
import { updateGitignore } from "./updateGitignore.js";
|
|
9
|
-
import { updatePrismaConfig } from "./updatePrismaConfig.js";
|
|
10
|
-
import runUpdateSchemaFile from "./updateSchemaFile.js";
|
|
11
|
-
import { updateTsConfigs } from "./updateTsConfigs.js";
|
|
12
|
-
function detectProvider(schemaPath) {
|
|
13
|
-
if (!fs.existsSync(schemaPath)) {
|
|
14
|
-
return "sqlite";
|
|
15
|
-
}
|
|
16
|
-
const source = fs.readFileSync(schemaPath, "utf-8");
|
|
17
|
-
const match = source.match(
|
|
18
|
-
/datasource\s+\w+\s*\{[^}]*provider\s*=\s*["']([^"']+)["']/
|
|
19
|
-
);
|
|
20
|
-
return match ? match[1].toLowerCase() : "sqlite";
|
|
21
|
-
}
|
|
22
|
-
async function getPrismaV7Context() {
|
|
23
|
-
const paths = getPaths();
|
|
24
|
-
const schemaPath = await getSchemaPath(paths.api.prismaConfig);
|
|
25
|
-
const provider = detectProvider(schemaPath);
|
|
26
|
-
const isSqlite = provider === "sqlite";
|
|
27
|
-
const isPostgres = provider === "postgresql" || provider === "postgres";
|
|
28
|
-
const dbPathTs = path.join(paths.api.lib, "db.ts");
|
|
29
|
-
const dbPathJs = path.join(paths.api.lib, "db.js");
|
|
30
|
-
let dbFilePath = null;
|
|
31
|
-
if (fs.existsSync(dbPathTs)) {
|
|
32
|
-
dbFilePath = dbPathTs;
|
|
33
|
-
} else if (fs.existsSync(dbPathJs)) {
|
|
34
|
-
dbFilePath = dbPathJs;
|
|
35
|
-
}
|
|
36
|
-
return { provider, isSqlite, isPostgres, dbFilePath };
|
|
37
|
-
}
|
|
38
|
-
async function prismaV7() {
|
|
39
|
-
const paths = getPaths();
|
|
40
|
-
const context = await getPrismaV7Context();
|
|
41
|
-
await runUpdateSchemaFile();
|
|
42
|
-
await updatePrismaConfig(paths.api.prismaConfig);
|
|
43
|
-
if (context.dbFilePath) {
|
|
44
|
-
await runTransform({
|
|
45
|
-
transformPath: path.join(import.meta.dirname, "updateDbFile.js"),
|
|
46
|
-
targetPaths: [context.dbFilePath],
|
|
47
|
-
parser: "ts",
|
|
48
|
-
options: {
|
|
49
|
-
isSqlite: context.isSqlite,
|
|
50
|
-
isPostgres: context.isPostgres,
|
|
51
|
-
silent: true
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
await rewriteRemainingImports();
|
|
56
|
-
if (context.isSqlite || context.isPostgres) {
|
|
57
|
-
await updateApiPackageJson(path.join(paths.api.base, "package.json"), {
|
|
58
|
-
provider: context.provider
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
await updateTsConfigs({
|
|
62
|
-
apiTsConfig: path.join(paths.api.base, "tsconfig.json"),
|
|
63
|
-
scriptsTsConfig: path.join(paths.base, "scripts", "tsconfig.json"),
|
|
64
|
-
webTsConfig: path.join(paths.web.base, "tsconfig.json")
|
|
65
|
-
});
|
|
66
|
-
await updateGitignore(path.join(paths.base, ".gitignore"));
|
|
67
|
-
await updateEnvDefaults(path.join(paths.base, ".env.defaults"));
|
|
68
|
-
const dotEnvWarning = checkDotEnv(path.join(paths.base, ".env"));
|
|
69
|
-
if (dotEnvWarning) {
|
|
70
|
-
console.warn(`
|
|
71
|
-
Warning: ${dotEnvWarning}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
export {
|
|
75
|
-
prismaV7 as default,
|
|
76
|
-
getPrismaV7Context
|
|
77
|
-
};
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { styleText } from "node:util";
|
|
3
|
-
import { getPaths } from "@cedarjs/project-config";
|
|
4
|
-
import runTransform from "../../../lib/runTransform.js";
|
|
5
|
-
import { getPrismaV7Context } from "./prismaV7.js";
|
|
6
|
-
import rewriteRemainingImports from "./rewriteRemainingImports.js";
|
|
7
|
-
import { updateApiPackageJson } from "./updateApiPackageJson.js";
|
|
8
|
-
import { checkDotEnv, updateEnvDefaults } from "./updateEnvDefaults.js";
|
|
9
|
-
import { updateGitignore } from "./updateGitignore.js";
|
|
10
|
-
import { updatePrismaConfig } from "./updatePrismaConfig.js";
|
|
11
|
-
import runUpdateSchemaFile from "./updateSchemaFile.js";
|
|
12
|
-
import { updateTsConfigs } from "./updateTsConfigs.js";
|
|
13
|
-
const command = "prisma-v7";
|
|
14
|
-
const description = "(v3.x) Upgrades your Cedar app to use Prisma v7 \u2013 updates schema.prisma, db.ts, prisma.config.cjs, and related config files";
|
|
15
|
-
function step(label, output) {
|
|
16
|
-
console.log(` ${styleText("green", "\u2714")} ${styleText("bold", label)}`);
|
|
17
|
-
console.log(` \u2192 ${output}`);
|
|
18
|
-
}
|
|
19
|
-
const handler = async () => {
|
|
20
|
-
const paths = getPaths();
|
|
21
|
-
const context = await getPrismaV7Context();
|
|
22
|
-
const { isSqlite, isPostgres, provider, dbFilePath } = context;
|
|
23
|
-
console.log(styleText("bold", "\u276F Prisma v7 Migration"));
|
|
24
|
-
const { results: schemaResults } = await runUpdateSchemaFile();
|
|
25
|
-
if (schemaResults.length === 0) {
|
|
26
|
-
step("Update schema.prisma", "Skipped. No schema.prisma found");
|
|
27
|
-
} else {
|
|
28
|
-
for (const result of schemaResults) {
|
|
29
|
-
if (result.status === "skipped") {
|
|
30
|
-
step("Update schema.prisma", `Skipped. ${result.path} not found`);
|
|
31
|
-
} else if (result.status === "unmodified") {
|
|
32
|
-
step("Update schema.prisma", "No changes needed (already migrated)");
|
|
33
|
-
} else {
|
|
34
|
-
step("Update schema.prisma", `Updated ${result.path}`);
|
|
35
|
-
}
|
|
36
|
-
for (const warning of result.warnings) {
|
|
37
|
-
console.warn(`
|
|
38
|
-
\u26A0\uFE0F ${warning}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const prismaConfigResult = await updatePrismaConfig(paths.api.prismaConfig);
|
|
43
|
-
if (prismaConfigResult === "skipped") {
|
|
44
|
-
step("Update prisma.config.cjs", "Skipped. prisma.config.cjs not found");
|
|
45
|
-
} else if (prismaConfigResult === "unmodified") {
|
|
46
|
-
step(
|
|
47
|
-
"Update prisma.config.cjs",
|
|
48
|
-
"No changes needed (already has datasource block)"
|
|
49
|
-
);
|
|
50
|
-
} else {
|
|
51
|
-
step("Update prisma.config.cjs", `Updated ${paths.api.prismaConfig}`);
|
|
52
|
-
}
|
|
53
|
-
if (!dbFilePath) {
|
|
54
|
-
step(
|
|
55
|
-
"Update api/src/lib/db.{ts,js}",
|
|
56
|
-
"Skipped. No api/src/lib/db.ts or api/src/lib/db.js found"
|
|
57
|
-
);
|
|
58
|
-
} else {
|
|
59
|
-
await runTransform({
|
|
60
|
-
transformPath: path.join(import.meta.dirname, "updateDbFile.js"),
|
|
61
|
-
targetPaths: [dbFilePath],
|
|
62
|
-
parser: "ts",
|
|
63
|
-
options: {
|
|
64
|
-
isSqlite,
|
|
65
|
-
isPostgres,
|
|
66
|
-
silent: true
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
step("Update api/src/lib/db.{ts,js}", `Updated ${dbFilePath}`);
|
|
70
|
-
if (!isSqlite && !isPostgres) {
|
|
71
|
-
const installationUrl = "https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/introduction#installation";
|
|
72
|
-
console.log(
|
|
73
|
-
` \u2139\uFE0F Non-SQLite database detected. The import paths in db.ts have been updated,
|
|
74
|
-
but no driver adapter was added. You'll need to add one manually.
|
|
75
|
-
See: ${installationUrl}`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
await rewriteRemainingImports();
|
|
80
|
-
step("Rewrite remaining @prisma/client imports", "Done");
|
|
81
|
-
if (!isSqlite && !isPostgres) {
|
|
82
|
-
step(
|
|
83
|
-
"Update api/package.json",
|
|
84
|
-
"Skipped. Unsupported provider. Add your own driver adapter package."
|
|
85
|
-
);
|
|
86
|
-
} else {
|
|
87
|
-
const pkgPath = path.join(paths.api.base, "package.json");
|
|
88
|
-
const pkgResult = await updateApiPackageJson(pkgPath, { provider });
|
|
89
|
-
if (pkgResult === "skipped") {
|
|
90
|
-
step("Update api/package.json", "Skipped. api/package.json not found");
|
|
91
|
-
} else if (pkgResult === "unmodified") {
|
|
92
|
-
step(
|
|
93
|
-
"Update api/package.json",
|
|
94
|
-
"No changes needed (adapter already installed)"
|
|
95
|
-
);
|
|
96
|
-
} else {
|
|
97
|
-
step("Update api/package.json", `Updated ${pkgPath}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const tsConfigResults = await updateTsConfigs({
|
|
101
|
-
apiTsConfig: path.join(paths.api.base, "tsconfig.json"),
|
|
102
|
-
scriptsTsConfig: path.join(paths.base, "scripts", "tsconfig.json"),
|
|
103
|
-
webTsConfig: path.join(paths.web.base, "tsconfig.json")
|
|
104
|
-
});
|
|
105
|
-
const updatedTsConfigs = Object.entries(tsConfigResults).filter(([, status]) => status === "updated").map(([name]) => name);
|
|
106
|
-
if (updatedTsConfigs.length === 0) {
|
|
107
|
-
step("Update tsconfig.json files", "No changes needed");
|
|
108
|
-
} else {
|
|
109
|
-
step(
|
|
110
|
-
"Update tsconfig.json files",
|
|
111
|
-
`Updated: ${updatedTsConfigs.join(", ")}`
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
const gitignorePath = path.join(paths.base, ".gitignore");
|
|
115
|
-
const gitignoreResult = await updateGitignore(gitignorePath);
|
|
116
|
-
if (gitignoreResult === "skipped") {
|
|
117
|
-
step("Update .gitignore", "Skipped. .gitignore not found");
|
|
118
|
-
} else if (gitignoreResult === "unmodified") {
|
|
119
|
-
step("Update .gitignore", "No changes needed");
|
|
120
|
-
} else {
|
|
121
|
-
step("Update .gitignore", `Updated ${gitignorePath}`);
|
|
122
|
-
}
|
|
123
|
-
const envDefaultsPath = path.join(paths.base, ".env.defaults");
|
|
124
|
-
const envDefaultsResult = await updateEnvDefaults(envDefaultsPath);
|
|
125
|
-
if (envDefaultsResult === "skipped") {
|
|
126
|
-
step("Update .env.defaults", "Skipped. .env.defaults not found");
|
|
127
|
-
} else if (envDefaultsResult === "unmodified") {
|
|
128
|
-
step("Update .env.defaults", "No changes needed");
|
|
129
|
-
} else {
|
|
130
|
-
step("Update .env.defaults", `Updated ${envDefaultsPath}`);
|
|
131
|
-
}
|
|
132
|
-
const dotEnvWarning = checkDotEnv(path.join(paths.base, ".env"));
|
|
133
|
-
if (dotEnvWarning) {
|
|
134
|
-
console.warn(`
|
|
135
|
-
\u26A0\uFE0F ${dotEnvWarning}`);
|
|
136
|
-
}
|
|
137
|
-
const nextSteps = [];
|
|
138
|
-
if (!isSqlite && !isPostgres) {
|
|
139
|
-
nextSteps.push(
|
|
140
|
-
" 1. Add a Prisma driver adapter for your database to api/src/lib/db.ts",
|
|
141
|
-
" See: https://www.prisma.io/docs/orm/core-concepts/supported-databases/database-drivers"
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
const offset = !isSqlite && !isPostgres ? 1 : 0;
|
|
145
|
-
nextSteps.push(
|
|
146
|
-
` ${offset + 1}. Run \`yarn install\` to install new dependencies`,
|
|
147
|
-
` ${offset + 2}. Run \`yarn cedar prisma generate\` to generate the new Prisma client`,
|
|
148
|
-
` ${offset + 3}. Run \`yarn cedar prisma migrate dev\` to verify migrations work`,
|
|
149
|
-
` ${offset + 4}. Run \`yarn cedar lint --fix\` to fix code formatting issues`
|
|
150
|
-
);
|
|
151
|
-
console.log(styleText("bold", "\n Next steps:"));
|
|
152
|
-
console.log(nextSteps.join("\n"));
|
|
153
|
-
};
|
|
154
|
-
export {
|
|
155
|
-
command,
|
|
156
|
-
description,
|
|
157
|
-
handler
|
|
158
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
ensurePosixPath,
|
|
5
|
-
getDataMigrationsPath,
|
|
6
|
-
getPaths
|
|
7
|
-
} from "@cedarjs/project-config";
|
|
8
|
-
const CODE_FILE_GLOB = "**/*.{ts,tsx,cts,mts,js,jsx,cjs,mjs}";
|
|
9
|
-
async function collectCodeFiles(dir) {
|
|
10
|
-
try {
|
|
11
|
-
return await Array.fromAsync(fs.promises.glob(CODE_FILE_GLOB, { cwd: dir }));
|
|
12
|
-
} catch (error) {
|
|
13
|
-
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
throw error;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
async function rewritePrismaImportsInDirectory(dir, dbFilePath) {
|
|
20
|
-
const scriptsDir = ensurePosixPath(getPaths().scripts);
|
|
21
|
-
const normalizedDbFilePath = dbFilePath ? ensurePosixPath(dbFilePath) : null;
|
|
22
|
-
const fileMatches = await collectCodeFiles(dir);
|
|
23
|
-
const files = fileMatches.map((relativePath) => path.join(dir, relativePath)).filter((filePath) => ensurePosixPath(filePath) !== normalizedDbFilePath);
|
|
24
|
-
if (files.length === 0) {
|
|
25
|
-
return "skipped";
|
|
26
|
-
}
|
|
27
|
-
let anyUpdated = false;
|
|
28
|
-
for (const filePath of files) {
|
|
29
|
-
const source = await fs.promises.readFile(filePath, "utf-8");
|
|
30
|
-
const isScriptFile = ensurePosixPath(filePath).startsWith(scriptsDir);
|
|
31
|
-
const importPath = isScriptFile ? "api/src/lib/db" : "src/lib/db";
|
|
32
|
-
const importPattern = /(['"])@prisma\/client\1/g;
|
|
33
|
-
const transformed = source.replace(importPattern, `$1${importPath}$1`);
|
|
34
|
-
if (transformed !== source) {
|
|
35
|
-
await fs.promises.writeFile(filePath, transformed);
|
|
36
|
-
anyUpdated = true;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return anyUpdated ? "updated" : "skipped";
|
|
40
|
-
}
|
|
41
|
-
async function rewriteRemainingImports() {
|
|
42
|
-
const paths = getPaths();
|
|
43
|
-
const prismaConfigPath = paths.api.prismaConfig;
|
|
44
|
-
const dataMigrationsPath = await getDataMigrationsPath(prismaConfigPath);
|
|
45
|
-
const dbPathTs = path.join(paths.api.lib, "db.ts");
|
|
46
|
-
const dbPathJs = path.join(paths.api.lib, "db.js");
|
|
47
|
-
let dbFilePath = null;
|
|
48
|
-
if (fs.existsSync(dbPathTs)) {
|
|
49
|
-
dbFilePath = dbPathTs;
|
|
50
|
-
} else if (fs.existsSync(dbPathJs)) {
|
|
51
|
-
dbFilePath = dbPathJs;
|
|
52
|
-
}
|
|
53
|
-
const dirsToTransform = [paths.api.src, dataMigrationsPath, paths.scripts];
|
|
54
|
-
for (const dir of dirsToTransform) {
|
|
55
|
-
await rewritePrismaImportsInDirectory(dir, dbFilePath);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
export {
|
|
59
|
-
rewriteRemainingImports as default,
|
|
60
|
-
rewritePrismaImportsInDirectory
|
|
61
|
-
};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
const ADAPTER_PACKAGE = "@prisma/adapter-better-sqlite3";
|
|
3
|
-
const SQLITE_PACKAGE = "better-sqlite3";
|
|
4
|
-
const ADAPTER_VERSION = "^7.0.0";
|
|
5
|
-
const SQLITE_VERSION = "^12.0.0";
|
|
6
|
-
const PG_ADAPTER_PACKAGE = "@prisma/adapter-pg";
|
|
7
|
-
const PG_PACKAGE = "pg";
|
|
8
|
-
const PG_ADAPTER_VERSION = "^7.0.0";
|
|
9
|
-
const PG_VERSION = "^8.0.0";
|
|
10
|
-
function transformApiPackageJson(source, {
|
|
11
|
-
provider = "sqlite",
|
|
12
|
-
adapterVersion = ADAPTER_VERSION,
|
|
13
|
-
sqliteVersion = SQLITE_VERSION,
|
|
14
|
-
pgAdapterVersion = PG_ADAPTER_VERSION,
|
|
15
|
-
pgVersion = PG_VERSION
|
|
16
|
-
} = {}) {
|
|
17
|
-
const pkg = JSON.parse(source);
|
|
18
|
-
const isPostgres = provider === "postgresql" || provider === "postgres";
|
|
19
|
-
if (isPostgres) {
|
|
20
|
-
if (pkg.dependencies?.[PG_ADAPTER_PACKAGE]) {
|
|
21
|
-
return source;
|
|
22
|
-
}
|
|
23
|
-
pkg.dependencies = {
|
|
24
|
-
...pkg.dependencies ?? {},
|
|
25
|
-
[PG_ADAPTER_PACKAGE]: pgAdapterVersion,
|
|
26
|
-
[PG_PACKAGE]: pgVersion
|
|
27
|
-
};
|
|
28
|
-
} else {
|
|
29
|
-
if (pkg.dependencies?.[ADAPTER_PACKAGE]) {
|
|
30
|
-
return source;
|
|
31
|
-
}
|
|
32
|
-
pkg.dependencies = {
|
|
33
|
-
...pkg.dependencies ?? {},
|
|
34
|
-
[ADAPTER_PACKAGE]: adapterVersion,
|
|
35
|
-
[SQLITE_PACKAGE]: sqliteVersion
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
const indentMatch = source.match(/^(\s+)"/m);
|
|
39
|
-
const indent = indentMatch ? indentMatch[1] : " ";
|
|
40
|
-
return JSON.stringify(pkg, null, indent.length) + "\n";
|
|
41
|
-
}
|
|
42
|
-
async function updateApiPackageJson(packageJsonPath, options = {}) {
|
|
43
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
44
|
-
return "skipped";
|
|
45
|
-
}
|
|
46
|
-
const source = fs.readFileSync(packageJsonPath, "utf-8");
|
|
47
|
-
const pkg = JSON.parse(source);
|
|
48
|
-
const isPostgres = options.provider === "postgresql" || options.provider === "postgres";
|
|
49
|
-
const sentinelPackage = isPostgres ? PG_ADAPTER_PACKAGE : ADAPTER_PACKAGE;
|
|
50
|
-
if (pkg.dependencies?.[sentinelPackage]) {
|
|
51
|
-
return "unmodified";
|
|
52
|
-
}
|
|
53
|
-
const transformed = transformApiPackageJson(source, options);
|
|
54
|
-
if (transformed === source) {
|
|
55
|
-
return "unmodified";
|
|
56
|
-
}
|
|
57
|
-
fs.writeFileSync(packageJsonPath, transformed, "utf-8");
|
|
58
|
-
return "updated";
|
|
59
|
-
}
|
|
60
|
-
export {
|
|
61
|
-
ADAPTER_PACKAGE,
|
|
62
|
-
ADAPTER_VERSION,
|
|
63
|
-
PG_ADAPTER_PACKAGE,
|
|
64
|
-
PG_ADAPTER_VERSION,
|
|
65
|
-
PG_PACKAGE,
|
|
66
|
-
PG_VERSION,
|
|
67
|
-
SQLITE_PACKAGE,
|
|
68
|
-
SQLITE_VERSION,
|
|
69
|
-
transformApiPackageJson,
|
|
70
|
-
updateApiPackageJson
|
|
71
|
-
};
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
const NEW_CLIENT_PATH = "api/db/generated/prisma/client.mts";
|
|
2
|
-
const OLD_PRISMA_CLIENT = "@prisma/client";
|
|
3
|
-
function transform(file, api, options = {}) {
|
|
4
|
-
const j = api.jscodeshift;
|
|
5
|
-
const root = j(file.source);
|
|
6
|
-
const isSqlite = options["isSqlite"] !== false;
|
|
7
|
-
const isPostgres = options["isPostgres"] === true;
|
|
8
|
-
const hasNewClientPath = root.find(j.ImportDeclaration, { source: { value: NEW_CLIENT_PATH } }).length > 0;
|
|
9
|
-
const hasPgAdapter = root.find(j.ImportDeclaration, { source: { value: "@prisma/adapter-pg" } }).length > 0;
|
|
10
|
-
const alreadyMigrated = hasNewClientPath && (!isPostgres || hasPgAdapter);
|
|
11
|
-
if (alreadyMigrated) {
|
|
12
|
-
return file.source;
|
|
13
|
-
}
|
|
14
|
-
function stealLeadingComments(fromNode, toNode) {
|
|
15
|
-
const fromComments = fromNode.comments;
|
|
16
|
-
if (!fromComments || fromComments.length === 0) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const leading = fromComments.filter((c) => c.leading);
|
|
20
|
-
if (leading.length === 0) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
toNode.comments = [...leading, ...toNode.comments ?? []];
|
|
24
|
-
fromNode.comments = fromComments.filter((c) => !c.leading);
|
|
25
|
-
}
|
|
26
|
-
function insertAdapterImport(importDecl, { takeLeadingComments = false } = {}) {
|
|
27
|
-
const clientImport = root.find(j.ImportDeclaration, {
|
|
28
|
-
source: { value: NEW_CLIENT_PATH }
|
|
29
|
-
});
|
|
30
|
-
if (clientImport.length > 0) {
|
|
31
|
-
if (takeLeadingComments) {
|
|
32
|
-
stealLeadingComments(clientImport.get().node, importDecl);
|
|
33
|
-
}
|
|
34
|
-
clientImport.insertBefore(importDecl);
|
|
35
|
-
} else {
|
|
36
|
-
root.find(j.ImportDeclaration).at(0).insertBefore(importDecl);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function addAdapterToPrismaClient() {
|
|
40
|
-
root.find(j.NewExpression, {
|
|
41
|
-
callee: { type: "Identifier", name: "PrismaClient" }
|
|
42
|
-
}).forEach((nodePath) => {
|
|
43
|
-
const args = nodePath.node.arguments;
|
|
44
|
-
if (args.length === 0) {
|
|
45
|
-
nodePath.node.arguments = [
|
|
46
|
-
j.objectExpression([
|
|
47
|
-
Object.assign(
|
|
48
|
-
j.objectProperty(
|
|
49
|
-
j.identifier("adapter"),
|
|
50
|
-
j.identifier("adapter")
|
|
51
|
-
),
|
|
52
|
-
{ shorthand: true }
|
|
53
|
-
)
|
|
54
|
-
])
|
|
55
|
-
];
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const firstArg = args[0];
|
|
59
|
-
if (firstArg.type !== "ObjectExpression") {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const hasAdapterProp = firstArg.properties.some(
|
|
63
|
-
(prop) => prop.type === "ObjectProperty" && prop.key.type === "Identifier" && "name" in prop.key && prop.key.name === "adapter"
|
|
64
|
-
);
|
|
65
|
-
if (!hasAdapterProp) {
|
|
66
|
-
firstArg.properties.push(
|
|
67
|
-
Object.assign(
|
|
68
|
-
j.objectProperty(
|
|
69
|
-
j.identifier("adapter"),
|
|
70
|
-
j.identifier("adapter")
|
|
71
|
-
),
|
|
72
|
-
{ shorthand: true }
|
|
73
|
-
)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
let didTransform = false;
|
|
79
|
-
root.find(j.ImportDeclaration, { source: { value: OLD_PRISMA_CLIENT } }).forEach((nodePath) => {
|
|
80
|
-
nodePath.node.source = j.stringLiteral(NEW_CLIENT_PATH);
|
|
81
|
-
didTransform = true;
|
|
82
|
-
});
|
|
83
|
-
root.find(j.ExportAllDeclaration).filter((nodePath) => {
|
|
84
|
-
const src = nodePath.node.source?.value;
|
|
85
|
-
return src === OLD_PRISMA_CLIENT || src === "src/lib/db" || src === "api/src/lib/db";
|
|
86
|
-
}).forEach((nodePath) => {
|
|
87
|
-
nodePath.node.source = j.stringLiteral(NEW_CLIENT_PATH);
|
|
88
|
-
didTransform = true;
|
|
89
|
-
});
|
|
90
|
-
if (!didTransform && !isPostgres) {
|
|
91
|
-
return file.source;
|
|
92
|
-
}
|
|
93
|
-
if (isPostgres) {
|
|
94
|
-
const hasAdapterImport2 = root.find(j.ImportDeclaration, {
|
|
95
|
-
source: { value: "@prisma/adapter-pg" }
|
|
96
|
-
}).length > 0;
|
|
97
|
-
if (!hasAdapterImport2) {
|
|
98
|
-
insertAdapterImport(
|
|
99
|
-
j.importDeclaration(
|
|
100
|
-
[
|
|
101
|
-
j.importSpecifier(
|
|
102
|
-
j.identifier("PrismaPg"),
|
|
103
|
-
j.identifier("PrismaPg")
|
|
104
|
-
)
|
|
105
|
-
],
|
|
106
|
-
j.stringLiteral("@prisma/adapter-pg")
|
|
107
|
-
),
|
|
108
|
-
{ takeLeadingComments: true }
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
const hasAdapter2 = root.find(j.VariableDeclarator, {
|
|
112
|
-
id: { type: "Identifier", name: "adapter" }
|
|
113
|
-
}).length > 0;
|
|
114
|
-
if (!hasAdapter2) {
|
|
115
|
-
const prismaClientDeclaration = root.find(j.NewExpression, {
|
|
116
|
-
callee: { type: "Identifier", name: "PrismaClient" }
|
|
117
|
-
}).closest(j.VariableDeclaration);
|
|
118
|
-
const adapterDecl = j.variableDeclaration("const", [
|
|
119
|
-
j.variableDeclarator(
|
|
120
|
-
j.identifier("adapter"),
|
|
121
|
-
j.newExpression(j.identifier("PrismaPg"), [
|
|
122
|
-
j.objectExpression([
|
|
123
|
-
j.objectProperty(
|
|
124
|
-
j.identifier("connectionString"),
|
|
125
|
-
j.memberExpression(
|
|
126
|
-
j.memberExpression(
|
|
127
|
-
j.identifier("process"),
|
|
128
|
-
j.identifier("env")
|
|
129
|
-
),
|
|
130
|
-
j.identifier("DATABASE_URL")
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
])
|
|
134
|
-
])
|
|
135
|
-
)
|
|
136
|
-
]);
|
|
137
|
-
prismaClientDeclaration.insertBefore(adapterDecl);
|
|
138
|
-
}
|
|
139
|
-
addAdapterToPrismaClient();
|
|
140
|
-
return root.toSource({ quote: "single" });
|
|
141
|
-
}
|
|
142
|
-
if (!isSqlite) {
|
|
143
|
-
return root.toSource({ quote: "single" });
|
|
144
|
-
}
|
|
145
|
-
const hasPathImport = root.find(j.ImportDeclaration, { source: { value: "node:path" } }).length > 0;
|
|
146
|
-
const hasAdapterImport = root.find(j.ImportDeclaration, {
|
|
147
|
-
source: { value: "@prisma/adapter-better-sqlite3" }
|
|
148
|
-
}).length > 0;
|
|
149
|
-
const hasGetPathsImport = root.find(j.ImportDeclaration, {
|
|
150
|
-
source: { value: "@cedarjs/project-config" }
|
|
151
|
-
}).length > 0;
|
|
152
|
-
if (!hasPathImport) {
|
|
153
|
-
insertAdapterImport(
|
|
154
|
-
j.importDeclaration(
|
|
155
|
-
[j.importDefaultSpecifier(j.identifier("path"))],
|
|
156
|
-
j.stringLiteral("node:path")
|
|
157
|
-
),
|
|
158
|
-
{ takeLeadingComments: true }
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
if (!hasAdapterImport) {
|
|
162
|
-
insertAdapterImport(
|
|
163
|
-
j.importDeclaration(
|
|
164
|
-
[
|
|
165
|
-
j.importSpecifier(
|
|
166
|
-
j.identifier("PrismaBetterSqlite3"),
|
|
167
|
-
j.identifier("PrismaBetterSqlite3")
|
|
168
|
-
)
|
|
169
|
-
],
|
|
170
|
-
j.stringLiteral("@prisma/adapter-better-sqlite3")
|
|
171
|
-
)
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
if (!hasGetPathsImport) {
|
|
175
|
-
const cedarjsImports = root.find(
|
|
176
|
-
j.ImportDeclaration,
|
|
177
|
-
(node) => String(node.source.value).startsWith("@cedarjs/")
|
|
178
|
-
);
|
|
179
|
-
const getPathsImport = j.importDeclaration(
|
|
180
|
-
[j.importSpecifier(j.identifier("getPaths"), j.identifier("getPaths"))],
|
|
181
|
-
j.stringLiteral("@cedarjs/project-config")
|
|
182
|
-
);
|
|
183
|
-
const clientImport = root.find(j.ImportDeclaration, {
|
|
184
|
-
source: { value: NEW_CLIENT_PATH }
|
|
185
|
-
});
|
|
186
|
-
if (cedarjsImports.length > 0) {
|
|
187
|
-
cedarjsImports.at(-1).insertAfter(getPathsImport);
|
|
188
|
-
} else {
|
|
189
|
-
clientImport.insertAfter(getPathsImport);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
const hasResolveSqliteUrl = root.find(j.VariableDeclarator, {
|
|
193
|
-
id: { type: "Identifier", name: "resolveSqliteUrl" }
|
|
194
|
-
}).length > 0;
|
|
195
|
-
const hasAdapter = root.find(j.VariableDeclarator, {
|
|
196
|
-
id: { type: "Identifier", name: "adapter" }
|
|
197
|
-
}).length > 0;
|
|
198
|
-
const prismaClientNewExpr = root.find(j.NewExpression, {
|
|
199
|
-
callee: { type: "Identifier", name: "PrismaClient" }
|
|
200
|
-
});
|
|
201
|
-
if (prismaClientNewExpr.length > 0 && (!hasResolveSqliteUrl || !hasAdapter)) {
|
|
202
|
-
const prismaClientDeclaration = prismaClientNewExpr.closest(
|
|
203
|
-
j.VariableDeclaration
|
|
204
|
-
);
|
|
205
|
-
if (!hasResolveSqliteUrl) {
|
|
206
|
-
const resolveSqliteUrlSource = `
|
|
207
|
-
const resolveSqliteUrl = (url = 'file:./db/dev.db') => {
|
|
208
|
-
if (!url.startsWith('file:.')) {
|
|
209
|
-
return url
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return \`file:\${path.resolve(getPaths().api.base, url.slice('file:'.length))}\`
|
|
213
|
-
}
|
|
214
|
-
`;
|
|
215
|
-
const resolveSqliteUrlDecl = j(resolveSqliteUrlSource).find(j.VariableDeclaration).get().node;
|
|
216
|
-
prismaClientDeclaration.insertBefore(resolveSqliteUrlDecl);
|
|
217
|
-
}
|
|
218
|
-
if (!hasAdapter) {
|
|
219
|
-
const adapterDecl = j.variableDeclaration("const", [
|
|
220
|
-
j.variableDeclarator(
|
|
221
|
-
j.identifier("adapter"),
|
|
222
|
-
j.newExpression(j.identifier("PrismaBetterSqlite3"), [
|
|
223
|
-
j.objectExpression([
|
|
224
|
-
j.objectProperty(
|
|
225
|
-
j.identifier("url"),
|
|
226
|
-
j.callExpression(j.identifier("resolveSqliteUrl"), [
|
|
227
|
-
j.memberExpression(
|
|
228
|
-
j.memberExpression(
|
|
229
|
-
j.identifier("process"),
|
|
230
|
-
j.identifier("env")
|
|
231
|
-
),
|
|
232
|
-
j.identifier("DATABASE_URL")
|
|
233
|
-
)
|
|
234
|
-
])
|
|
235
|
-
)
|
|
236
|
-
])
|
|
237
|
-
])
|
|
238
|
-
)
|
|
239
|
-
]);
|
|
240
|
-
prismaClientDeclaration.insertBefore(adapterDecl);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
addAdapterToPrismaClient();
|
|
244
|
-
return root.toSource({ quote: "single" });
|
|
245
|
-
}
|
|
246
|
-
export {
|
|
247
|
-
transform as default
|
|
248
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
const OLD_SQLITE_URL = "file:./dev.db";
|
|
3
|
-
const NEW_SQLITE_URL = "file:./db/dev.db";
|
|
4
|
-
function transformEnvDefaults(source) {
|
|
5
|
-
return source.replace(
|
|
6
|
-
/^(DATABASE_URL=)file:\.\/dev\.db([ \t]*)$/m,
|
|
7
|
-
`$1${NEW_SQLITE_URL}$2`
|
|
8
|
-
);
|
|
9
|
-
}
|
|
10
|
-
async function updateEnvDefaults(envDefaultsPath) {
|
|
11
|
-
if (!fs.existsSync(envDefaultsPath)) {
|
|
12
|
-
return "skipped";
|
|
13
|
-
}
|
|
14
|
-
const source = fs.readFileSync(envDefaultsPath, "utf-8");
|
|
15
|
-
if (!source.includes(`DATABASE_URL=${OLD_SQLITE_URL}`)) {
|
|
16
|
-
return "unmodified";
|
|
17
|
-
}
|
|
18
|
-
const transformed = transformEnvDefaults(source);
|
|
19
|
-
if (transformed === source) {
|
|
20
|
-
return "unmodified";
|
|
21
|
-
}
|
|
22
|
-
fs.writeFileSync(envDefaultsPath, transformed, "utf-8");
|
|
23
|
-
return "updated";
|
|
24
|
-
}
|
|
25
|
-
function checkDotEnv(envPath) {
|
|
26
|
-
if (!fs.existsSync(envPath)) {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
const source = fs.readFileSync(envPath, "utf-8");
|
|
30
|
-
if (source.includes(`DATABASE_URL=${OLD_SQLITE_URL}`)) {
|
|
31
|
-
return `Your .env file still contains DATABASE_URL=${OLD_SQLITE_URL}. You should manually update it to DATABASE_URL=${NEW_SQLITE_URL}.`;
|
|
32
|
-
}
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
export {
|
|
36
|
-
checkDotEnv,
|
|
37
|
-
transformEnvDefaults,
|
|
38
|
-
updateEnvDefaults
|
|
39
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
const GENERATED_PRISMA_ENTRY = "api/db/generated/prisma";
|
|
3
|
-
function transformGitignore(source) {
|
|
4
|
-
if (source.includes(GENERATED_PRISMA_ENTRY)) {
|
|
5
|
-
return source;
|
|
6
|
-
}
|
|
7
|
-
if (/^dev\.db\*/m.test(source)) {
|
|
8
|
-
return source.replace(/^(dev\.db\*)$/m, `$1
|
|
9
|
-
${GENERATED_PRISMA_ENTRY}`);
|
|
10
|
-
}
|
|
11
|
-
const withTrailingNewline = source.endsWith("\n") ? source : source + "\n";
|
|
12
|
-
return withTrailingNewline + GENERATED_PRISMA_ENTRY + "\n";
|
|
13
|
-
}
|
|
14
|
-
async function updateGitignore(gitignorePath) {
|
|
15
|
-
if (!fs.existsSync(gitignorePath)) {
|
|
16
|
-
return "skipped";
|
|
17
|
-
}
|
|
18
|
-
const source = fs.readFileSync(gitignorePath, "utf-8");
|
|
19
|
-
if (source.includes(GENERATED_PRISMA_ENTRY)) {
|
|
20
|
-
return "unmodified";
|
|
21
|
-
}
|
|
22
|
-
const transformed = transformGitignore(source);
|
|
23
|
-
if (transformed === source) {
|
|
24
|
-
return "unmodified";
|
|
25
|
-
}
|
|
26
|
-
fs.writeFileSync(gitignorePath, transformed, "utf-8");
|
|
27
|
-
return "updated";
|
|
28
|
-
}
|
|
29
|
-
export {
|
|
30
|
-
transformGitignore,
|
|
31
|
-
updateGitignore
|
|
32
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
function transformPrismaConfig(source) {
|
|
3
|
-
if (/datasource\s*:/.test(source)) {
|
|
4
|
-
return source;
|
|
5
|
-
}
|
|
6
|
-
let result = source;
|
|
7
|
-
if (!/\benv\b/.test(result)) {
|
|
8
|
-
result = result.replace(
|
|
9
|
-
/const\s*\{([^}]*)\}\s*=\s*require\(['"]prisma\/config['"]\)/,
|
|
10
|
-
(match, destructured) => {
|
|
11
|
-
const trimmed = destructured.trim();
|
|
12
|
-
return `const { ${trimmed}, env } = require('prisma/config')`;
|
|
13
|
-
}
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
result = result.replace(
|
|
17
|
-
/(\n[ \t]*\}[ \t]*,?\s*\n)([ \t]*\}\))/,
|
|
18
|
-
(match, lastPropClose, closingParen) => {
|
|
19
|
-
const indent = lastPropClose.match(/^(\n([ \t]*))/)?.[2] ?? " ";
|
|
20
|
-
const propIndent = indent;
|
|
21
|
-
const innerIndent = indent + " ";
|
|
22
|
-
return lastPropClose + `${propIndent}datasource: {
|
|
23
|
-
${innerIndent}url: env('DATABASE_URL'),
|
|
24
|
-
${propIndent}},
|
|
25
|
-
` + closingParen;
|
|
26
|
-
}
|
|
27
|
-
);
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
async function updatePrismaConfig(configPath) {
|
|
31
|
-
if (!fs.existsSync(configPath)) {
|
|
32
|
-
return "skipped";
|
|
33
|
-
}
|
|
34
|
-
const source = fs.readFileSync(configPath, "utf-8");
|
|
35
|
-
if (/datasource\s*:/.test(source)) {
|
|
36
|
-
return "unmodified";
|
|
37
|
-
}
|
|
38
|
-
const transformed = transformPrismaConfig(source);
|
|
39
|
-
if (transformed === source) {
|
|
40
|
-
return "unmodified";
|
|
41
|
-
}
|
|
42
|
-
fs.writeFileSync(configPath, transformed, "utf-8");
|
|
43
|
-
return "updated";
|
|
44
|
-
}
|
|
45
|
-
export {
|
|
46
|
-
transformPrismaConfig,
|
|
47
|
-
updatePrismaConfig
|
|
48
|
-
};
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { getSchemaPath, getPaths } from "@cedarjs/project-config";
|
|
4
|
-
const NEW_GENERATOR_BLOCK = `generator client {
|
|
5
|
-
provider = "prisma-client"
|
|
6
|
-
output = "./generated/prisma"
|
|
7
|
-
moduleFormat = "cjs"
|
|
8
|
-
generatedFileExtension = "mts"
|
|
9
|
-
importFileExtension = "mts"
|
|
10
|
-
}`;
|
|
11
|
-
function isAlreadyMigrated(source) {
|
|
12
|
-
return /generator\s+client\s*\{[^}]*provider\s*=\s*["']prisma-client["'][^}]*\}/.test(
|
|
13
|
-
source
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
function transformSchema(source) {
|
|
17
|
-
let directUrlEnvVar = null;
|
|
18
|
-
let customBinaryTargets = null;
|
|
19
|
-
const result = source.replace(
|
|
20
|
-
/(datasource\s+\w+\s*\{)([^}]*?)(\})/g,
|
|
21
|
-
(_fullMatch, open, body, close) => {
|
|
22
|
-
const directUrlMatch = body.match(
|
|
23
|
-
/directUrl\s*=\s*env\(["']([^"']+)["']\)/
|
|
24
|
-
);
|
|
25
|
-
if (directUrlMatch) {
|
|
26
|
-
directUrlEnvVar = directUrlMatch[1];
|
|
27
|
-
}
|
|
28
|
-
const cleaned = body.replace(/^[ \t]*url\s*=\s*.+\n?/gm, "").replace(/^[ \t]*directUrl\s*=\s*.+\n?/gm, "").replace(/\n{3,}/g, "\n\n");
|
|
29
|
-
return `${open}${cleaned}${close}`;
|
|
30
|
-
}
|
|
31
|
-
).replace(
|
|
32
|
-
/generator\s+client\s*\{([^}]*)\}/g,
|
|
33
|
-
(_fullMatch, body) => {
|
|
34
|
-
const binaryMatch = body.match(
|
|
35
|
-
/binaryTargets\s*=\s*(\[[^\]]*\]|"[^"]*"|'[^']*')/
|
|
36
|
-
);
|
|
37
|
-
if (binaryMatch) {
|
|
38
|
-
const val = binaryMatch[1];
|
|
39
|
-
if (!/^\s*["']native["']\s*$/.test(val)) {
|
|
40
|
-
customBinaryTargets = val;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return NEW_GENERATOR_BLOCK;
|
|
44
|
-
}
|
|
45
|
-
);
|
|
46
|
-
return { result, directUrlEnvVar, customBinaryTargets };
|
|
47
|
-
}
|
|
48
|
-
async function updateSchemaFile(schemaPath) {
|
|
49
|
-
if (!fs.existsSync(schemaPath)) {
|
|
50
|
-
return { status: "skipped", warnings: [] };
|
|
51
|
-
}
|
|
52
|
-
const source = fs.readFileSync(schemaPath, "utf-8");
|
|
53
|
-
const warnings = [];
|
|
54
|
-
if (isAlreadyMigrated(source)) {
|
|
55
|
-
return { status: "unmodified", warnings };
|
|
56
|
-
}
|
|
57
|
-
const { result, directUrlEnvVar, customBinaryTargets } = transformSchema(source);
|
|
58
|
-
if (directUrlEnvVar) {
|
|
59
|
-
warnings.push(
|
|
60
|
-
`A directUrl was found in your schema.prisma and has been removed. In Prisma v7 the \`url\` field in prisma.config.cjs is used by the CLI for migrations (replacing directUrl). Update api/prisma.config.cjs to use your direct URL value there:
|
|
61
|
-
datasource: {
|
|
62
|
-
url: env('${directUrlEnvVar}'),
|
|
63
|
-
},`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
if (customBinaryTargets) {
|
|
67
|
-
warnings.push(
|
|
68
|
-
`binaryTargets (${customBinaryTargets}) has been removed from your schema.prisma. binaryTargets is no longer needed in Prisma v7 as the new driver is written in TypeScript.`
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
if (result === source) {
|
|
72
|
-
return { status: "unmodified", warnings };
|
|
73
|
-
}
|
|
74
|
-
fs.writeFileSync(schemaPath, result, "utf-8");
|
|
75
|
-
return { status: "updated", warnings };
|
|
76
|
-
}
|
|
77
|
-
async function runUpdateSchemaFile() {
|
|
78
|
-
const paths = getPaths();
|
|
79
|
-
const schemaPath = await getSchemaPath(paths.api.prismaConfig);
|
|
80
|
-
const results = [];
|
|
81
|
-
if (schemaPath) {
|
|
82
|
-
const schemaDir = path.dirname(schemaPath);
|
|
83
|
-
const siblings = fs.existsSync(schemaDir) ? fs.readdirSync(schemaDir).filter((f) => f.endsWith(".prisma")).map((f) => path.join(schemaDir, f)) : [];
|
|
84
|
-
const filesToProcess = [
|
|
85
|
-
schemaPath,
|
|
86
|
-
...siblings.filter((f) => f !== schemaPath)
|
|
87
|
-
];
|
|
88
|
-
for (const filePath of filesToProcess) {
|
|
89
|
-
const result = await updateSchemaFile(filePath);
|
|
90
|
-
results.push({ path: filePath, ...result });
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return { results };
|
|
94
|
-
}
|
|
95
|
-
export {
|
|
96
|
-
runUpdateSchemaFile as default,
|
|
97
|
-
updateSchemaFile
|
|
98
|
-
};
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
function transformTsConfig(source) {
|
|
3
|
-
if (/["']allowImportingTsExtensions["']/.test(source)) {
|
|
4
|
-
return source;
|
|
5
|
-
}
|
|
6
|
-
const afterModuleResolution = source.replace(
|
|
7
|
-
/("moduleResolution"\s*:\s*"[^"]*")(,?)(\s*\n)/,
|
|
8
|
-
(match, prop, comma, ws) => {
|
|
9
|
-
const lineStart = source.lastIndexOf("\n", source.indexOf(match)) + 1;
|
|
10
|
-
const indentMatch = source.slice(lineStart).match(/^([ \t]+)/);
|
|
11
|
-
const indent = indentMatch ? indentMatch[1] : " ";
|
|
12
|
-
const trailingComma = comma || ",";
|
|
13
|
-
return `${prop}${trailingComma}${ws}${indent}"allowImportingTsExtensions": true,
|
|
14
|
-
`;
|
|
15
|
-
}
|
|
16
|
-
);
|
|
17
|
-
if (afterModuleResolution !== source) {
|
|
18
|
-
return afterModuleResolution;
|
|
19
|
-
}
|
|
20
|
-
const afterModule = source.replace(
|
|
21
|
-
/("module"\s*:\s*"[^"]*")(,?)(\s*\n)/,
|
|
22
|
-
(match, prop, comma, ws) => {
|
|
23
|
-
const lineStart = source.lastIndexOf("\n", source.indexOf(match)) + 1;
|
|
24
|
-
const indentMatch = source.slice(lineStart).match(/^([ \t]+)/);
|
|
25
|
-
const indent = indentMatch ? indentMatch[1] : " ";
|
|
26
|
-
const trailingComma = comma || ",";
|
|
27
|
-
return `${prop}${trailingComma}${ws}${indent}"allowImportingTsExtensions": true,
|
|
28
|
-
`;
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
if (afterModule !== source) {
|
|
32
|
-
return afterModule;
|
|
33
|
-
}
|
|
34
|
-
return source.replace(
|
|
35
|
-
/("compilerOptions"\s*:\s*\{)(\s*\n)/,
|
|
36
|
-
(match, open, ws) => {
|
|
37
|
-
const lineStart = source.lastIndexOf("\n", source.indexOf(match)) + 1;
|
|
38
|
-
const indentMatch = source.slice(lineStart).match(/^([ \t]+)/);
|
|
39
|
-
const outerIndent = indentMatch ? indentMatch[1] : " ";
|
|
40
|
-
const innerIndent = outerIndent + " ";
|
|
41
|
-
return `${open}${ws}${innerIndent}"allowImportingTsExtensions": true,
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
async function updateTsConfig(tsConfigPath) {
|
|
47
|
-
if (!fs.existsSync(tsConfigPath)) {
|
|
48
|
-
return "skipped";
|
|
49
|
-
}
|
|
50
|
-
const source = fs.readFileSync(tsConfigPath, "utf-8");
|
|
51
|
-
if (/["']allowImportingTsExtensions["']/.test(source)) {
|
|
52
|
-
return "unmodified";
|
|
53
|
-
}
|
|
54
|
-
const transformed = transformTsConfig(source);
|
|
55
|
-
if (transformed === source) {
|
|
56
|
-
return "unmodified";
|
|
57
|
-
}
|
|
58
|
-
fs.writeFileSync(tsConfigPath, transformed, "utf-8");
|
|
59
|
-
return "updated";
|
|
60
|
-
}
|
|
61
|
-
async function updateTsConfigs(paths) {
|
|
62
|
-
const [api, scripts, web] = await Promise.all([
|
|
63
|
-
updateTsConfig(paths.apiTsConfig),
|
|
64
|
-
updateTsConfig(paths.scriptsTsConfig),
|
|
65
|
-
updateTsConfig(paths.webTsConfig)
|
|
66
|
-
]);
|
|
67
|
-
return { api, scripts, web };
|
|
68
|
-
}
|
|
69
|
-
export {
|
|
70
|
-
transformTsConfig,
|
|
71
|
-
updateTsConfig,
|
|
72
|
-
updateTsConfigs
|
|
73
|
-
};
|