@cedarjs/cli 9.0.0-canary.1784 → 9.0.0-canary.3124
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/README.md +7 -10
- package/dist/cfw.js +10 -6
- package/dist/commands/build/buildHandler.js +220 -45
- package/dist/commands/build/buildPackagesTask.js +21 -20
- package/dist/commands/build.js +13 -2
- package/dist/commands/check.js +4 -6
- package/dist/commands/console.js +6 -4
- package/dist/commands/deploy/baremetal/SshExecutor.js +13 -4
- package/dist/commands/deploy/baremetal/baremetalHandler.js +116 -50
- package/dist/commands/deploy/baremetal.js +11 -4
- package/dist/commands/deploy/flightcontrolHandler.js +28 -15
- package/dist/commands/deploy/helpers/deployHandler.js +11 -6
- package/dist/commands/deploy/netlify.js +1 -1
- package/dist/commands/deploy/packing/nft.js +1 -2
- package/dist/commands/deploy/render.js +1 -1
- package/dist/commands/deploy/renderHandler.js +24 -13
- package/dist/commands/deploy/serverlessHandler.js +69 -27
- package/dist/commands/deploy/vercel.js +1 -1
- package/dist/commands/destroy/component/component.js +2 -3
- package/dist/commands/destroy/directive/directive.js +1 -3
- package/dist/commands/destroy/directive/directiveHandler.js +2 -4
- package/dist/commands/destroy/function/function.js +1 -3
- package/dist/commands/destroy/handlerHelpers.js +17 -17
- package/dist/commands/destroy/helpers.js +8 -2
- package/dist/commands/destroy/layout/layout.js +1 -2
- package/dist/commands/destroy/page/pageHandler.js +3 -3
- package/dist/commands/destroy/scaffold/scaffoldHandler.js +31 -12
- package/dist/commands/destroy/sdl/sdlHandler.js +3 -3
- package/dist/commands/dev/apiDebugFlag.js +5 -4
- package/dist/commands/dev/devHandler.js +219 -68
- package/dist/commands/dev/packageWatchCommands.js +8 -3
- package/dist/commands/dev.js +16 -6
- package/dist/commands/execHandler.js +49 -29
- package/dist/commands/experimental/live-queries/liveQueries.js +32 -0
- package/dist/commands/experimental/live-queries/liveQueriesHandler.js +448 -0
- package/dist/commands/experimental/live-queries/templates/liveQueriesListener.ts.template +153 -0
- package/dist/commands/experimental/live-queries/templates/migration.sql.template +100 -0
- package/dist/commands/experimental/setupInngest.js +2 -2
- package/dist/commands/experimental/setupInngestHandler.js +13 -12
- package/dist/commands/experimental/setupOpentelemetry.js +2 -2
- package/dist/commands/experimental/setupOpentelemetryHandler.js +14 -10
- package/dist/commands/experimental/setupReactCompiler.js +2 -2
- package/dist/commands/experimental/setupReactCompilerHandler.js +48 -33
- package/dist/commands/experimental/setupRsc.js +1 -1
- package/dist/commands/experimental/setupRscHandler.js +20 -16
- package/dist/commands/experimental/setupStreamingSsr.js +2 -2
- package/dist/commands/experimental/setupStreamingSsrHandler.js +49 -34
- package/dist/commands/experimental/templates/opentelemetry.ts.template +2 -1
- package/dist/commands/experimental/templates/rsc/Document.tsx.template +1 -1
- package/dist/commands/experimental/templates/rsc/entry.client.tsx.template +8 -8
- package/dist/commands/experimental/templates/streamingSsr/Document.tsx.template +1 -1
- package/dist/commands/experimental/templates/streamingSsr/entry.client.tsx.template +6 -6
- package/dist/commands/experimental/templates/streamingSsr/tsconfig.json.template +6 -6
- package/dist/commands/experimental/util.js +27 -25
- package/dist/commands/experimental.js +3 -2
- package/dist/commands/generate/cell/cell.js +20 -0
- package/dist/commands/generate/cell/cellHandler.js +89 -40
- package/dist/commands/generate/cell/templates/cell.tsx.template +21 -2
- package/dist/commands/generate/cell/templates/cellFragment.tsx.template +43 -0
- package/dist/commands/generate/cell/templates/cellList.tsx.template +21 -2
- package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +23 -0
- package/dist/commands/generate/cell/templates/test.js.template +1 -1
- package/dist/commands/generate/cell/templates/testFragment.js.template +30 -0
- package/dist/commands/generate/component/componentHandler.js +14 -16
- package/dist/commands/generate/dataMigration/dataMigration.js +36 -18
- package/dist/commands/generate/dataMigration/templates/dataMigration.js.template +1 -1
- package/dist/commands/generate/dataMigration/templates/dataMigration.ts.template +1 -1
- package/dist/commands/generate/dbAuth/dbAuth.js +1 -0
- package/dist/commands/generate/dbAuth/dbAuthHandler.js +63 -34
- package/dist/commands/generate/dbAuth/templates/login.oauth.tsx.template +164 -0
- package/dist/commands/generate/dbAuth/templates/signup.oauth.tsx.template +147 -0
- package/dist/commands/generate/directive/directiveHandler.js +14 -16
- package/dist/commands/generate/function/function.js +1 -0
- package/dist/commands/generate/function/functionHandler.js +14 -19
- package/dist/commands/generate/helpers.js +34 -18
- package/dist/commands/generate/job/job.js +1 -0
- package/dist/commands/generate/job/jobHandler.js +20 -24
- package/dist/commands/generate/layout/layoutHandler.js +13 -16
- package/dist/commands/generate/model/model.js +1 -0
- package/dist/commands/generate/model/modelHandler.js +11 -5
- package/dist/commands/generate/ogImage/ogImage.js +1 -0
- package/dist/commands/generate/ogImage/ogImageHandler.js +18 -11
- package/dist/commands/generate/package/filesTask.js +9 -0
- package/dist/commands/generate/package/packageHandler.js +50 -61
- package/dist/commands/generate/package/templates/test.ts.template +2 -2
- package/dist/commands/generate/package/templates/vitest.config.ts.template +9 -0
- package/dist/commands/generate/page/pageHandler.js +27 -24
- package/dist/commands/generate/realtime/realtime.js +2 -2
- package/dist/commands/generate/realtime/realtimeHandler.js +51 -32
- package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +1 -1
- package/dist/commands/generate/scaffold/scaffold.js +1 -0
- package/dist/commands/generate/scaffold/scaffoldHandler.js +176 -49
- package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +1 -1
- package/dist/commands/generate/script/script.js +1 -0
- package/dist/commands/generate/script/scriptHandler.js +10 -6
- package/dist/commands/generate/script/templates/script.ts.template +9 -4
- package/dist/commands/generate/script/templates/tsconfig.json.template +16 -2
- package/dist/commands/generate/sdl/sdl.js +4 -3
- package/dist/commands/generate/sdl/sdlHandler.js +135 -46
- package/dist/commands/generate/sdl/stubFiles.js +132 -0
- package/dist/commands/generate/sdl/templates/sdl.js.template +2 -1
- package/dist/commands/generate/sdl/templates/sdl.ts.template +2 -1
- package/dist/commands/generate/secret/secret.js +20 -20
- package/dist/commands/generate/service/service.js +5 -5
- package/dist/commands/generate/service/serviceHandler.js +126 -61
- package/dist/commands/generate/service/templates/scenarios.ts.template +4 -2
- package/dist/commands/generate/service/templates/service.ts.template +22 -8
- package/dist/commands/generate/service/templates/test.ts.template +2 -2
- package/dist/commands/generate/yargsCommandHelpers.js +7 -2
- package/dist/commands/generate/yargsHandlerHelpers.js +20 -18
- package/dist/commands/generate.js +4 -4
- package/dist/commands/info.js +2 -2
- package/dist/commands/jobsHandler.js +7 -4
- package/dist/commands/lint.js +26 -69
- package/dist/commands/prerenderHandler.js +95 -58
- package/dist/commands/prismaHandler.js +51 -26
- package/dist/commands/record/init.js +2 -2
- package/dist/commands/record.js +4 -3
- package/dist/commands/serve.js +245 -31
- package/dist/commands/serveApiHandler.js +7 -6
- package/dist/commands/serveBothHandler.js +22 -13
- package/dist/commands/serveWebHandler.js +3 -2
- package/dist/commands/setup/auth/auth.js +15 -11
- package/dist/commands/setup/cache/cache.js +1 -1
- package/dist/commands/setup/cache/cacheHandler.js +15 -9
- package/dist/commands/setup/database/database.js +15 -0
- package/dist/commands/setup/database/postgres.js +19 -0
- package/dist/commands/setup/database/postgresHandler.js +196 -0
- package/dist/commands/setup/database/templates/db.ts.template +32 -0
- package/dist/commands/setup/deploy/deploy.js +4 -3
- package/dist/commands/setup/deploy/helpers/helpers.js +5 -1
- package/dist/commands/setup/deploy/helpers/index.js +132 -6
- package/dist/commands/setup/deploy/providers/baremetalHandler.js +28 -6
- package/dist/commands/setup/deploy/providers/coherence.js +1 -1
- package/dist/commands/setup/deploy/providers/coherenceHandler.js +60 -31
- package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +69 -51
- package/dist/commands/setup/deploy/providers/netlify.js +6 -0
- package/dist/commands/setup/deploy/providers/netlifyHandler.js +114 -13
- package/dist/commands/setup/deploy/providers/renderHandler.js +44 -41
- package/dist/commands/setup/deploy/providers/serverlessHandler.js +7 -5
- package/dist/commands/setup/deploy/providers/universal-deploy.js +11 -0
- package/dist/commands/setup/deploy/providers/universalDeployHandler.js +186 -0
- package/dist/commands/setup/deploy/providers/vercel.js +6 -0
- package/dist/commands/setup/deploy/providers/vercelHandler.js +115 -14
- package/dist/commands/setup/deploy/templates/baremetal.js +3 -2
- package/dist/commands/setup/deploy/templates/flightcontrol.js +60 -49
- package/dist/commands/setup/deploy/templates/netlify.js +2 -1
- package/dist/commands/setup/deploy/templates/netlifyUD.js +31 -0
- package/dist/commands/setup/deploy/templates/render.js +32 -17
- package/dist/commands/setup/docker/docker.js +2 -2
- package/dist/commands/setup/docker/dockerHandler.js +74 -39
- package/dist/commands/setup/docker/templates/Dockerfile.npm +119 -0
- package/dist/commands/setup/docker/templates/Dockerfile.pnpm +112 -0
- package/dist/commands/setup/docker/templates/{Dockerfile → Dockerfile.yarn} +4 -7
- package/dist/commands/setup/docker/templates/docker-compose.dev.yml +3 -3
- package/dist/commands/setup/docker/templates/docker-compose.prod.yml +2 -5
- package/dist/commands/setup/docker/templates/dockerignore +1 -0
- package/dist/commands/setup/generator/generator.js +1 -1
- package/dist/commands/setup/generator/generatorHandler.js +5 -4
- package/dist/commands/setup/graphql/features/fragments/appGqlConfigTransform.js +6 -3
- package/dist/commands/setup/graphql/features/fragments/fragments.js +1 -1
- package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +5 -7
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +1 -1
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +4 -3
- package/dist/commands/setup/i18n/i18n.js +1 -1
- package/dist/commands/setup/i18n/i18nHandler.js +21 -17
- package/dist/commands/setup/jobs/jobs.js +1 -1
- package/dist/commands/setup/jobs/jobsHandler.js +17 -12
- package/dist/commands/setup/mailer/mailer.js +1 -1
- package/dist/commands/setup/mailer/mailerHandler.js +13 -11
- package/dist/commands/setup/middleware/ogImage/ogImage.js +1 -1
- package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +2 -1
- package/dist/commands/setup/monitoring/sentry/sentry.js +1 -1
- package/dist/commands/setup/monitoring/sentry/sentryHandler.js +18 -12
- package/dist/commands/setup/neon/neon.js +35 -0
- package/dist/commands/setup/neon/neonHandler.js +264 -0
- package/dist/commands/setup/package/package.js +1 -1
- package/dist/commands/setup/package/packageHandler.js +18 -14
- package/dist/commands/setup/realtime/addRealtimeToGraphql.js +1 -1
- package/dist/commands/setup/realtime/realtime.js +1 -1
- package/dist/commands/setup/realtime/realtimeHandler.js +26 -37
- package/dist/commands/setup/realtime/templates/realtime.ts.template +1 -1
- package/dist/commands/setup/realtime/templates/subscriptions/countdown/countdown.ts.template +1 -1
- package/dist/commands/setup/realtime/templates/subscriptions/newMessage/newMessage.ts.template +1 -1
- package/dist/commands/setup/server-file/serverFile.js +1 -1
- package/dist/commands/setup/server-file/serverFileHandler.js +18 -10
- package/dist/commands/setup/tenancy/authCodemod.js +66 -0
- package/dist/commands/setup/tenancy/dbCodemod.js +64 -0
- package/dist/commands/setup/tenancy/graphqlCodemod.js +88 -0
- package/dist/commands/setup/tenancy/preflight.js +49 -0
- package/dist/commands/setup/tenancy/schemaPrisma.js +81 -0
- package/dist/commands/setup/tenancy/signupCodemod.js +153 -0
- package/dist/commands/setup/tenancy/templates/InvitePage.tsx.template +63 -0
- package/dist/commands/setup/tenancy/templates/OrgScope.tsx.template +40 -0
- package/dist/commands/setup/tenancy/templates/ensureDefaultOrganizations.dataMigration.ts.template +39 -0
- package/dist/commands/setup/tenancy/templates/organizations.scenarios.ts.template +59 -0
- package/dist/commands/setup/tenancy/templates/organizations.sdl.ts.template +89 -0
- package/dist/commands/setup/tenancy/templates/organizations.test.ts.template +389 -0
- package/dist/commands/setup/tenancy/templates/organizations.ts.template +394 -0
- package/dist/commands/setup/tenancy/templates/requireMembership.test.ts.template +35 -0
- package/dist/commands/setup/tenancy/templates/requireMembership.ts.template +25 -0
- package/dist/commands/setup/tenancy/tenancy.js +30 -0
- package/dist/commands/setup/tenancy/tenancyHandler.js +425 -0
- package/dist/commands/setup/ui/helpers/helpers.js +5 -1
- package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +16 -8
- package/dist/commands/setup/ui/libraries/mantineHandler.js +26 -16
- package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +40 -29
- package/dist/commands/setup/uploads/schemaPrisma.js +41 -0
- package/dist/commands/setup/uploads/serverFile.js +151 -0
- package/dist/commands/setup/uploads/templates/requireUploadToken.ts.template +15 -0
- package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +23 -24
- package/dist/commands/setup/uploads/templates/uploads.sdl.ts.template +79 -0
- package/dist/commands/setup/uploads/templates/uploads.ts.template +89 -0
- package/dist/commands/setup/uploads/templates/withDataUri.ts.template +14 -0
- package/dist/commands/setup/uploads/templates/withSignedUrl.ts.template +16 -0
- package/dist/commands/setup/uploads/uploads.js +49 -7
- package/dist/commands/setup/uploads/uploadsHandler.js +266 -72
- package/dist/commands/setup.js +5 -4
- package/dist/commands/studio.js +1 -1
- package/dist/commands/studioHandler.js +2 -2
- package/dist/commands/test/datasourceWarning.js +42 -0
- package/dist/commands/test/testHandler.js +104 -0
- package/dist/commands/test/viteVersionCheck.js +75 -0
- package/dist/commands/test.js +16 -19
- package/dist/commands/type-check.js +2 -1
- package/dist/commands/type-checkHandler.js +25 -18
- package/dist/commands/upgrade/preUpgradeScripts.js +11 -11
- package/dist/commands/upgrade/upgrade.js +4 -2
- package/dist/commands/upgrade/upgradeHandler.js +97 -73
- package/dist/index.js +15 -11
- package/dist/lib/background.js +22 -1
- package/dist/lib/configureStorybook.js +2 -2
- package/dist/lib/exec.js +68 -63
- package/dist/lib/exit.js +20 -5
- package/dist/lib/extendFile.js +23 -13
- package/dist/lib/generatePrismaClient.js +48 -12
- package/dist/lib/index.js +137 -106
- package/dist/lib/loadEnvFiles.js +1 -1
- package/dist/lib/locking.js +8 -4
- package/dist/lib/merge/algorithms.js +4 -1
- package/dist/lib/merge/index.js +78 -41
- package/dist/lib/merge/semanticIdentity.js +18 -6
- package/dist/lib/merge/strategy.js +86 -36
- package/dist/lib/packages.js +23 -13
- package/dist/lib/plugin.js +13 -7
- package/dist/lib/pluralHelpers.js +6 -2
- package/dist/lib/project.js +3 -1
- package/dist/lib/rollback.js +7 -7
- package/dist/lib/schemaHelpers.js +16 -19
- package/dist/lib/test.js +20 -5
- package/dist/lib/updateCheck.js +47 -18
- package/dist/middleware/checkNodeVersion.js +9 -4
- package/dist/middleware/{detectProjectRxVersion.js → detectProjectCedarVersion.js} +2 -2
- package/dist/plugin.js +18 -12
- package/dist/telemetry/exporter.js +12 -5
- package/dist/telemetry/index.js +4 -3
- package/dist/telemetry/resource.js +9 -12
- package/dist/telemetry/send.js +14 -10
- package/dist/testLib/cells.js +5 -3
- package/package.json +44 -41
- package/LICENSE +0 -21
- package/dist/commands/consoleHandler.js +0 -68
- package/dist/commands/setup/tsconfig/tsconfig.js +0 -25
- package/dist/commands/setup/tsconfig/tsconfigHandler.js +0 -59
- package/dist/commands/setup/uploads/dbCodemod.js +0 -28
- package/dist/commands/setup/uploads/templates/signedUrl.ts.template +0 -21
- package/dist/commands/setup/vite/templates/vite.config.ts.template +0 -19
- package/dist/commands/setup/vite/vite.js +0 -38
- package/dist/commands/setup/vite/viteHandler.js +0 -83
- package/dist/commands/testEsm.js +0 -36
- package/dist/commands/testHandler.js +0 -137
- package/dist/commands/testHandlerEsm.js +0 -85
- package/dist/commands/ts-to-js.js +0 -20
- package/dist/lib/cedarPluralize.js +0 -56
- package/dist/lib/colors.js +0 -18
- package/dist/testLib/getFilesWithPattern.js +0 -21
- /package/dist/{index.d.js → global.d.js} +0 -0
|
@@ -1,26 +1,68 @@
|
|
|
1
|
-
import
|
|
1
|
+
import prompts from "prompts";
|
|
2
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
3
|
+
import { requireTTYOrExit } from "@cedarjs/cli-helpers/tty";
|
|
2
4
|
const command = "uploads";
|
|
3
|
-
const description = "
|
|
5
|
+
const description = "Set up file uploads and storage: storage targets, upload profiles, the upload routes, and the GraphQL API";
|
|
6
|
+
const TARGET_CHOICES = ["fs", "db", "s3"];
|
|
7
|
+
const TARGET_DESCRIPTIONS = {
|
|
8
|
+
fs: "Local filesystem, uploaded through the api server (development, single-server deploys)",
|
|
9
|
+
db: "Inline in the database, for small files like avatars and thumbnails",
|
|
10
|
+
s3: "S3 or S3-compatible storage, uploaded straight from the browser with presigned URLs"
|
|
11
|
+
};
|
|
4
12
|
const builder = (yargs) => {
|
|
5
|
-
yargs.option("
|
|
13
|
+
return yargs.option("targets", {
|
|
14
|
+
choices: TARGET_CHOICES,
|
|
15
|
+
description: "Storage targets to configure: fs (local filesystem), db (inline in the database), s3 (direct-to-S3 presigned uploads). Prompts when omitted.",
|
|
16
|
+
type: "array"
|
|
17
|
+
}).option("force", {
|
|
6
18
|
alias: "f",
|
|
7
19
|
default: false,
|
|
8
20
|
description: "Overwrite existing configuration",
|
|
9
21
|
type: "boolean"
|
|
10
22
|
});
|
|
11
23
|
};
|
|
24
|
+
function toTargetChoices(values) {
|
|
25
|
+
const choices = TARGET_CHOICES;
|
|
26
|
+
return [...new Set(values)].filter(
|
|
27
|
+
(t) => choices.includes(t)
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
async function promptForTargets() {
|
|
31
|
+
requireTTYOrExit("--targets");
|
|
32
|
+
const response = await prompts({
|
|
33
|
+
type: "multiselect",
|
|
34
|
+
name: "targets",
|
|
35
|
+
message: "Which storage targets do you want to configure?",
|
|
36
|
+
instructions: false,
|
|
37
|
+
hint: "Space to toggle, enter to confirm",
|
|
38
|
+
min: 1,
|
|
39
|
+
choices: TARGET_CHOICES.map((value) => ({
|
|
40
|
+
title: value,
|
|
41
|
+
description: TARGET_DESCRIPTIONS[value],
|
|
42
|
+
value,
|
|
43
|
+
selected: value !== "s3"
|
|
44
|
+
}))
|
|
45
|
+
});
|
|
46
|
+
if (response.targets === void 0) {
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
return toTargetChoices(response.targets);
|
|
50
|
+
}
|
|
12
51
|
const handler = async (options) => {
|
|
52
|
+
const targets = options.targets?.length ? toTargetChoices(options.targets) : await promptForTargets();
|
|
13
53
|
recordTelemetryAttributes({
|
|
14
54
|
command: "setup uploads",
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
targets: targets.join(","),
|
|
56
|
+
force: options.force
|
|
17
57
|
});
|
|
18
58
|
const { handler: handler2 } = await import("./uploadsHandler.js");
|
|
19
|
-
return handler2(options);
|
|
59
|
+
return handler2({ targets, force: options.force });
|
|
20
60
|
};
|
|
21
61
|
export {
|
|
62
|
+
TARGET_CHOICES,
|
|
22
63
|
builder,
|
|
23
64
|
command,
|
|
24
65
|
description,
|
|
25
|
-
handler
|
|
66
|
+
handler,
|
|
67
|
+
toTargetChoices
|
|
26
68
|
};
|
|
@@ -1,87 +1,265 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
3
4
|
import { Listr } from "listr2";
|
|
4
5
|
import { format } from "prettier";
|
|
5
|
-
import {
|
|
6
|
+
import { terminalLink } from "termi-link";
|
|
7
|
+
import { colors as c } from "@cedarjs/cli-helpers/colors";
|
|
8
|
+
import { getPrettierOptions } from "@cedarjs/cli-helpers/fileHelpers";
|
|
9
|
+
import {
|
|
10
|
+
addApiPackages,
|
|
11
|
+
addWebPackages
|
|
12
|
+
} from "@cedarjs/cli-helpers/installHelpers";
|
|
13
|
+
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
14
|
+
import { addEnvVar } from "@cedarjs/cli-helpers/project";
|
|
15
|
+
import { getSchemaPath } from "@cedarjs/project-config";
|
|
6
16
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
7
|
-
import c from "../../../lib/colors.js";
|
|
8
17
|
import { getPaths, transformTSToJS, writeFile } from "../../../lib/index.js";
|
|
9
18
|
import { isTypeScriptProject } from "../../../lib/project.js";
|
|
10
|
-
import {
|
|
11
|
-
|
|
19
|
+
import { generateSecret } from "../../generate/secret/secret.js";
|
|
20
|
+
import { setupServerFileTasks } from "../server-file/serverFileHandler.js";
|
|
21
|
+
import { addUploadModel } from "./schemaPrisma.js";
|
|
22
|
+
import {
|
|
23
|
+
addUploadsPlugin,
|
|
24
|
+
detectServerAuth,
|
|
25
|
+
hasUploadsPlugin
|
|
26
|
+
} from "./serverFile.js";
|
|
27
|
+
const UPPY_VERSION = "^6.0.0";
|
|
28
|
+
const S3_IMPORTS = `import { S3Client } from '@aws-sdk/client-s3'
|
|
29
|
+
|
|
30
|
+
import { createS3Provider } from '@cedarjs/uploads/s3'
|
|
31
|
+
`;
|
|
32
|
+
const S3_CLIENT = `
|
|
33
|
+
// Your own S3 client. It stays available for S3-specific work (lifecycle
|
|
34
|
+
// rules, CORS, and so on) alongside the storage target below. Credentials
|
|
35
|
+
// come from the SDK's default chain: AWS_ACCESS_KEY_ID and
|
|
36
|
+
// AWS_SECRET_ACCESS_KEY in .env, or an IAM role, SSO, or container
|
|
37
|
+
// credentials in production. For an S3-compatible service, add \`endpoint\`
|
|
38
|
+
// and \`forcePathStyle: true\`.
|
|
39
|
+
export const s3Client = new S3Client({
|
|
40
|
+
region: process.env.AWS_REGION,
|
|
41
|
+
})
|
|
42
|
+
`;
|
|
43
|
+
const TARGET_BLOCKS = {
|
|
44
|
+
fs: ` // Files uploaded through the api server and stored on local disk. Good for
|
|
45
|
+
// development and single-server deploys.
|
|
46
|
+
local: createFsProvider({
|
|
47
|
+
uploadDir: path.join(getPaths().api.base, '.uploads'),
|
|
48
|
+
serveBaseUrl: process.env.UPLOAD_SERVE_BASE_URL,
|
|
49
|
+
signSecret: process.env.UPLOAD_TOKEN_SECRET,
|
|
50
|
+
}),
|
|
51
|
+
`,
|
|
52
|
+
db: ` // Small files stored inline in the Upload row (avatars, thumbnails).
|
|
53
|
+
thumbnails: createDbProvider(),
|
|
54
|
+
`,
|
|
55
|
+
s3: ` // Files uploaded straight from the browser to S3 with presigned URLs.
|
|
56
|
+
files: createS3Provider({
|
|
57
|
+
client: s3Client,
|
|
58
|
+
bucket: process.env.S3_BUCKET_UPLOADS,
|
|
59
|
+
region: process.env.AWS_REGION,
|
|
60
|
+
keyPrefix: 'uploads/',
|
|
61
|
+
}),
|
|
62
|
+
`
|
|
63
|
+
};
|
|
64
|
+
const PROFILE_BLOCKS = {
|
|
65
|
+
fs: ` attachment: {
|
|
66
|
+
target: 'local',
|
|
67
|
+
allowedMimeTypes: ['application/pdf', 'image/png', 'image/jpeg'],
|
|
68
|
+
maxFileSize: 25 * 1024 * 1024,
|
|
69
|
+
maxFiles: 10,
|
|
70
|
+
},
|
|
71
|
+
`,
|
|
72
|
+
db: ` avatar: {
|
|
73
|
+
target: 'thumbnails',
|
|
74
|
+
allowedMimeTypes: ['image/png', 'image/jpeg'],
|
|
75
|
+
maxFileSize: DB_MAX_FILE_SIZE,
|
|
76
|
+
maxFiles: 1,
|
|
77
|
+
},
|
|
78
|
+
`,
|
|
79
|
+
s3: ` document: {
|
|
80
|
+
target: 'files',
|
|
81
|
+
allowedMimeTypes: ['application/pdf', 'image/*'],
|
|
82
|
+
maxFileSize: 100 * 1024 * 1024,
|
|
83
|
+
maxFiles: 5,
|
|
84
|
+
},
|
|
85
|
+
`
|
|
86
|
+
};
|
|
87
|
+
const handler = async ({ targets, force }) => {
|
|
88
|
+
const paths = getPaths();
|
|
12
89
|
const projectIsTypescript = isTypeScriptProject();
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
90
|
+
const ext = projectIsTypescript ? "ts" : "js";
|
|
91
|
+
const wantsFs = targets.includes("fs");
|
|
92
|
+
const wantsDb = targets.includes("db");
|
|
93
|
+
const wantsS3 = targets.includes("s3");
|
|
94
|
+
const wantsUppy = wantsFs || wantsS3;
|
|
95
|
+
const packageJson = await import(pathToFileURL(path.join(paths.base, "package.json")).href, { with: { type: "json" } });
|
|
96
|
+
const cedarVersion = packageJson.default.devDependencies["@cedarjs/core"] ?? "latest";
|
|
97
|
+
const serverFilePath = path.join(paths.api.src, `server.${ext}`);
|
|
98
|
+
const writeTemplateFile = async (templateFile, outputPath, replacements = {}) => {
|
|
99
|
+
const templatePath = path.resolve(
|
|
100
|
+
import.meta.dirname,
|
|
101
|
+
"templates",
|
|
102
|
+
templateFile
|
|
103
|
+
);
|
|
104
|
+
let templateContent = fs.readFileSync(templatePath, "utf-8");
|
|
105
|
+
for (const [token, value] of Object.entries(replacements)) {
|
|
106
|
+
templateContent = templateContent.replaceAll(token, value);
|
|
107
|
+
}
|
|
108
|
+
const content = projectIsTypescript ? templateContent : await transformTSToJS(outputPath, templateContent);
|
|
109
|
+
return writeFile(outputPath, content, { overwriteExisting: force });
|
|
110
|
+
};
|
|
111
|
+
const apiPackages = [`@cedarjs/uploads@${cedarVersion}`];
|
|
112
|
+
const webPackages = [`@cedarjs/uploads@${cedarVersion}`];
|
|
113
|
+
if (wantsS3) {
|
|
114
|
+
apiPackages.push("@aws-sdk/client-s3", "@aws-sdk/s3-request-presigner");
|
|
115
|
+
}
|
|
116
|
+
if (wantsUppy) {
|
|
117
|
+
webPackages.push(
|
|
118
|
+
`@uppy/core@${UPPY_VERSION}`,
|
|
119
|
+
`@uppy/react@${UPPY_VERSION}`,
|
|
120
|
+
`@uppy/dashboard@${UPPY_VERSION}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (wantsFs) {
|
|
124
|
+
webPackages.push(`@uppy/xhr-upload@${UPPY_VERSION}`);
|
|
125
|
+
}
|
|
126
|
+
if (wantsS3) {
|
|
127
|
+
webPackages.push(`@uppy/aws-s3@${UPPY_VERSION}`);
|
|
128
|
+
}
|
|
16
129
|
const tasks = new Listr(
|
|
17
130
|
[
|
|
18
131
|
{
|
|
19
|
-
|
|
132
|
+
...addApiPackages(apiPackages),
|
|
133
|
+
title: "Adding @cedarjs/uploads to your api side..."
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
...addWebPackages(webPackages),
|
|
137
|
+
title: "Adding @cedarjs/uploads to your web side..."
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
title: "Adding the Upload model to schema.prisma...",
|
|
20
141
|
task: async () => {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
142
|
+
const schemaPath = await getSchemaPath(paths.api.prismaConfig);
|
|
143
|
+
const schema = fs.readFileSync(schemaPath, "utf-8");
|
|
144
|
+
fs.writeFileSync(schemaPath, addUploadModel(schema));
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
title: `Adding api/src/lib/uploads.${ext}...`,
|
|
149
|
+
task: async () => {
|
|
150
|
+
await writeTemplateFile(
|
|
151
|
+
"srcLibUploads.ts.template",
|
|
152
|
+
path.join(paths.api.lib, `uploads.${ext}`),
|
|
153
|
+
{
|
|
154
|
+
__S3_IMPORTS__: wantsS3 ? S3_IMPORTS : "",
|
|
155
|
+
__S3_CLIENT__: wantsS3 ? S3_CLIENT : "",
|
|
156
|
+
__FS_IMPORT__: wantsFs ? "createFsProvider," : "",
|
|
157
|
+
__DB_IMPORT__: wantsDb ? "createDbProvider," : "",
|
|
158
|
+
__DB_MAX_IMPORT__: wantsDb ? "DB_MAX_FILE_SIZE," : "",
|
|
159
|
+
__PATH_IMPORT__: wantsFs ? "import path from 'node:path'\n\n" : "",
|
|
160
|
+
__GET_PATHS_IMPORT__: wantsFs ? "import { getPaths } from '@cedarjs/project-config'\n" : "",
|
|
161
|
+
__TARGETS__: targets.map((t) => TARGET_BLOCKS[t]).join("\n"),
|
|
162
|
+
__PROFILES__: targets.map((t) => PROFILE_BLOCKS[t]).join("\n")
|
|
163
|
+
}
|
|
33
164
|
);
|
|
34
|
-
const uploadsContent = projectIsTypescript ? templateContent : await transformTSToJS(uploadsPath, templateContent);
|
|
35
|
-
return writeFile(uploadsPath, uploadsContent, {
|
|
36
|
-
overwriteExisting: force
|
|
37
|
-
});
|
|
38
165
|
}
|
|
39
166
|
},
|
|
40
167
|
{
|
|
41
|
-
title:
|
|
168
|
+
title: "Adding the uploads SDL and service...",
|
|
42
169
|
task: async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"signedUrl.ts.template"
|
|
170
|
+
await writeTemplateFile(
|
|
171
|
+
"uploads.sdl.ts.template",
|
|
172
|
+
path.join(paths.api.graphql, `uploads.sdl.${ext}`)
|
|
47
173
|
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
const uploadsPath = path.join(
|
|
53
|
-
getPaths().api.functions,
|
|
54
|
-
`signedUrl.${projectIsTypescript ? "ts" : "js"}`
|
|
174
|
+
await writeTemplateFile(
|
|
175
|
+
"uploads.ts.template",
|
|
176
|
+
path.join(paths.api.services, "uploads", `uploads.${ext}`)
|
|
55
177
|
);
|
|
56
|
-
const uploadsContent = projectIsTypescript ? templateContent : await transformTSToJS(uploadsPath, templateContent);
|
|
57
|
-
return writeFile(uploadsPath, uploadsContent, {
|
|
58
|
-
overwriteExisting: force
|
|
59
|
-
});
|
|
60
178
|
}
|
|
61
179
|
},
|
|
62
180
|
{
|
|
63
|
-
...
|
|
64
|
-
|
|
181
|
+
title: "Adding the upload directives...",
|
|
182
|
+
task: async () => {
|
|
183
|
+
const directives = ["requireUploadToken", "withSignedUrl"];
|
|
184
|
+
if (wantsDb) {
|
|
185
|
+
directives.push("withDataUri");
|
|
186
|
+
}
|
|
187
|
+
for (const name of directives) {
|
|
188
|
+
await writeTemplateFile(
|
|
189
|
+
`${name}.ts.template`,
|
|
190
|
+
path.join(paths.api.directives, name, `${name}.${ext}`)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
65
194
|
},
|
|
66
195
|
{
|
|
67
|
-
title: "
|
|
68
|
-
task:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
196
|
+
title: "Adding the server file...",
|
|
197
|
+
task: (_ctx, task) => task.newListr(setupServerFileTasks({ force: false })),
|
|
198
|
+
skip: () => fs.existsSync(serverFilePath) ? "api/src/server already exists; skipping." : false
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
title: "Registering the upload plugin in api/src/server...",
|
|
202
|
+
task: async (_ctx, task) => {
|
|
203
|
+
const source = fs.readFileSync(serverFilePath, "utf-8");
|
|
204
|
+
if (hasUploadsPlugin(source)) {
|
|
205
|
+
task.skip("The upload plugin is already registered; skipping.");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const graphqlPath = path.join(paths.api.functions, `graphql.${ext}`);
|
|
209
|
+
const authPath = path.join(paths.api.lib, `auth.${ext}`);
|
|
210
|
+
const auth = fs.existsSync(graphqlPath) && fs.existsSync(authPath) && fs.readFileSync(authPath, "utf-8").includes("getCurrentUser") ? detectServerAuth(fs.readFileSync(graphqlPath, "utf-8")) : null;
|
|
211
|
+
let updated;
|
|
212
|
+
try {
|
|
213
|
+
updated = addUploadsPlugin(source, { auth });
|
|
214
|
+
} catch {
|
|
83
215
|
throw new Error(
|
|
84
|
-
|
|
216
|
+
`Could not find \`await server.start()\` in ${path.relative(
|
|
217
|
+
paths.base,
|
|
218
|
+
serverFilePath
|
|
219
|
+
)}. Register the plugin by hand before the server starts:
|
|
220
|
+
|
|
221
|
+
import { cedarUploadsPlugin } from '@cedarjs/uploads'
|
|
222
|
+
import { db } from 'src/lib/db'
|
|
223
|
+
import { targets } from 'src/lib/uploads'
|
|
224
|
+
|
|
225
|
+
await server.register(cedarUploadsPlugin, {
|
|
226
|
+
tokenSecret: process.env.UPLOAD_TOKEN_SECRET,
|
|
227
|
+
targets,
|
|
228
|
+
db,
|
|
229
|
+
})
|
|
230
|
+
`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
fs.writeFileSync(serverFilePath, updated);
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
title: "Adding environment variables to .env...",
|
|
238
|
+
task: () => {
|
|
239
|
+
addEnvVar(
|
|
240
|
+
"UPLOAD_TOKEN_SECRET",
|
|
241
|
+
generateSecret(),
|
|
242
|
+
"Signs upload tokens and file-serving URLs. Keep it secret and use a different value per environment."
|
|
243
|
+
);
|
|
244
|
+
if (wantsFs) {
|
|
245
|
+
addEnvVar(
|
|
246
|
+
"UPLOAD_SERVE_BASE_URL",
|
|
247
|
+
"http://localhost:8911",
|
|
248
|
+
"Origin the api server is reachable at, used to build signed URLs for locally stored files."
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
if (wantsS3) {
|
|
252
|
+
addEnvVar(
|
|
253
|
+
"AWS_REGION",
|
|
254
|
+
"us-east-1",
|
|
255
|
+
"Region of the uploads bucket."
|
|
256
|
+
);
|
|
257
|
+
addEnvVar("AWS_ACCESS_KEY_ID", "replace-me", "");
|
|
258
|
+
addEnvVar("AWS_SECRET_ACCESS_KEY", "replace-me", "");
|
|
259
|
+
addEnvVar(
|
|
260
|
+
"S3_BUCKET_UPLOADS",
|
|
261
|
+
"replace-me",
|
|
262
|
+
"Bucket direct uploads land in."
|
|
85
263
|
);
|
|
86
264
|
}
|
|
87
265
|
}
|
|
@@ -90,10 +268,10 @@ const handler = async ({ force }) => {
|
|
|
90
268
|
title: "Prettifying changed files",
|
|
91
269
|
task: async (_ctx, task) => {
|
|
92
270
|
const prettifyPaths = [
|
|
93
|
-
|
|
94
|
-
path.join(
|
|
95
|
-
path.join(
|
|
96
|
-
path.join(
|
|
271
|
+
serverFilePath,
|
|
272
|
+
path.join(paths.api.lib, `uploads.${ext}`),
|
|
273
|
+
path.join(paths.api.graphql, `uploads.sdl.${ext}`),
|
|
274
|
+
path.join(paths.api.services, "uploads", `uploads.${ext}`)
|
|
97
275
|
];
|
|
98
276
|
for (const prettifyPath of prettifyPaths) {
|
|
99
277
|
try {
|
|
@@ -102,11 +280,11 @@ const handler = async ({ force }) => {
|
|
|
102
280
|
}
|
|
103
281
|
const source = fs.readFileSync(prettifyPath, "utf-8");
|
|
104
282
|
const prettierOptions = await getPrettierOptions();
|
|
105
|
-
const
|
|
283
|
+
const prettified = await format(source, {
|
|
106
284
|
...prettierOptions,
|
|
107
285
|
parser: "babel-ts"
|
|
108
286
|
});
|
|
109
|
-
fs.writeFileSync(prettifyPath,
|
|
287
|
+
fs.writeFileSync(prettifyPath, prettified, "utf-8");
|
|
110
288
|
} catch {
|
|
111
289
|
task.output = "Couldn't prettify the changes. Please reformat the files manually if needed.";
|
|
112
290
|
}
|
|
@@ -116,16 +294,30 @@ const handler = async ({ force }) => {
|
|
|
116
294
|
{
|
|
117
295
|
title: "One more thing...",
|
|
118
296
|
task: (_ctx, task) => {
|
|
297
|
+
const migrate = c.highlight(
|
|
298
|
+
formatCedarCommand(["prisma", "migrate", "dev"])
|
|
299
|
+
);
|
|
300
|
+
const types = c.highlight(formatCedarCommand(["generate", "types"]));
|
|
119
301
|
task.title = `One more thing...
|
|
120
302
|
|
|
121
|
-
${c.success("
|
|
303
|
+
${c.success("Uploads configured!")}
|
|
122
304
|
|
|
123
|
-
|
|
305
|
+
Next steps:
|
|
124
306
|
|
|
307
|
+
1. Apply the schema change: ${migrate}
|
|
308
|
+
2. Regenerate types: ${types}
|
|
309
|
+
3. Review the storage targets and upload profiles in api/src/lib/uploads.${ext}${wantsS3 ? "\n 4. Fill in the AWS_* and S3_BUCKET_UPLOADS values in .env" : ""}
|
|
125
310
|
|
|
126
|
-
|
|
127
|
-
|
|
311
|
+
Upload tokens are bound to the logged-in user when the app has auth.
|
|
312
|
+
If you add auth later, pass
|
|
313
|
+
\`authenticate: createUploadAuthenticator({ authDecoder, getCurrentUser })\`
|
|
314
|
+
to the plugin in api/src/server.${ext}.
|
|
128
315
|
|
|
316
|
+
Schedule cleanupStaleUploads() from a recurring job to sweep uploads
|
|
317
|
+
that never completed.
|
|
318
|
+
|
|
319
|
+
Check out the docs for more info:
|
|
320
|
+
${terminalLink("", "https://cedarjs.com/docs/uploads")}
|
|
129
321
|
`;
|
|
130
322
|
}
|
|
131
323
|
}
|
|
@@ -137,9 +329,11 @@ const handler = async ({ force }) => {
|
|
|
137
329
|
try {
|
|
138
330
|
await tasks.run();
|
|
139
331
|
} catch (e) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
process.
|
|
332
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
333
|
+
const exitCode = e instanceof Error && "exitCode" in e && typeof e.exitCode === "number" ? e.exitCode : 1;
|
|
334
|
+
errorTelemetry(process.argv, message);
|
|
335
|
+
console.error(c.error(message));
|
|
336
|
+
process.exit(exitCode);
|
|
143
337
|
}
|
|
144
338
|
};
|
|
145
339
|
export {
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { terminalLink } from "termi-link";
|
|
2
|
-
import
|
|
2
|
+
import { detectCedarVersion } from "../middleware/detectProjectCedarVersion.js";
|
|
3
3
|
import * as setupAuth from "./setup/auth/auth.js";
|
|
4
4
|
import * as setupCache from "./setup/cache/cache.js";
|
|
5
|
+
import * as setupDatabase from "./setup/database/database.js";
|
|
5
6
|
import * as setupDeploy from "./setup/deploy/deploy.js";
|
|
6
7
|
import * as setupDocker from "./setup/docker/docker.js";
|
|
7
8
|
import * as setupGenerator from "./setup/generator/generator.js";
|
|
@@ -11,16 +12,16 @@ import * as setupJobs from "./setup/jobs/jobs.js";
|
|
|
11
12
|
import * as setupMailer from "./setup/mailer/mailer.js";
|
|
12
13
|
import * as setupMiddleware from "./setup/middleware/middleware.js";
|
|
13
14
|
import * as setupMonitoring from "./setup/monitoring/monitoring.js";
|
|
15
|
+
import * as setupNeon from "./setup/neon/neon.js";
|
|
14
16
|
import * as setupPackage from "./setup/package/package.js";
|
|
15
17
|
import * as setupRealtime from "./setup/realtime/realtime.js";
|
|
16
18
|
import * as setupServerFile from "./setup/server-file/serverFile.js";
|
|
17
|
-
import * as
|
|
19
|
+
import * as setupTenancy from "./setup/tenancy/tenancy.js";
|
|
18
20
|
import * as setupUi from "./setup/ui/ui.js";
|
|
19
21
|
import * as setupUploads from "./setup/uploads/uploads.js";
|
|
20
|
-
import * as setupVite from "./setup/vite/vite.js";
|
|
21
22
|
const command = "setup <command>";
|
|
22
23
|
const description = "Initialize project config and install packages";
|
|
23
|
-
const builder = (yargs) => yargs.command(setupAuth).command(setupCache).command(setupDeploy).command(setupDocker).command(setupGenerator).command(setupGraphql).command(setupI18n).command(setupJobs).command(setupMailer).command(setupMiddleware).command(setupMonitoring).command(setupPackage).command(setupRealtime).command(setupServerFile).command(
|
|
24
|
+
const builder = (yargs) => yargs.command(setupAuth).command(setupCache).command(setupDatabase).command(setupDeploy).command(setupDocker).command(setupGenerator).command(setupGraphql).command(setupI18n).command(setupJobs).command(setupMailer).command(setupMiddleware).command(setupMonitoring).command(setupNeon).command(setupPackage).command(setupRealtime).command(setupServerFile).command(setupTenancy).command(setupUi).command(setupUploads).demandCommand().middleware(detectCedarVersion).epilogue(
|
|
24
25
|
`Also see the ${terminalLink(
|
|
25
26
|
"CedarJS CLI Reference",
|
|
26
27
|
"https://cedarjs.com/docs/cli-commands#setup"
|
package/dist/commands/studio.js
CHANGED
|
@@ -22,9 +22,9 @@ const handler = async (options) => {
|
|
|
22
22
|
}
|
|
23
23
|
const { serve } = await import("@cedarjs/studio");
|
|
24
24
|
await serve({ open: options.open, enableWeb: true });
|
|
25
|
-
} catch (
|
|
25
|
+
} catch (error) {
|
|
26
26
|
console.log("Cannot start the development studio");
|
|
27
|
-
console.log(
|
|
27
|
+
console.log(error);
|
|
28
28
|
process.exit(1);
|
|
29
29
|
}
|
|
30
30
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import Enquirer from "enquirer";
|
|
3
|
+
import { getPaths } from "@cedarjs/project-config";
|
|
4
|
+
async function warnIfNonStandardDatasourceUrl({ force } = {}) {
|
|
5
|
+
const cedarPaths = getPaths();
|
|
6
|
+
if (!fs.existsSync(cedarPaths.api.prismaConfig)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const prismaConfig = await fs.promises.readFile(
|
|
10
|
+
cedarPaths.api.prismaConfig,
|
|
11
|
+
"utf-8"
|
|
12
|
+
);
|
|
13
|
+
const prismaConfigLines = prismaConfig.split("\n");
|
|
14
|
+
for (const line of prismaConfigLines) {
|
|
15
|
+
const envVarName = (line.match(
|
|
16
|
+
/^\s*url: process\.env\.(\w+),?(\s*\/\/.*)?$/
|
|
17
|
+
) ?? line.match(/^\s*url: env\(['"](\w+)['"]\),?(\s*\/\/.*)?$/) ?? line.match(/[{,] url: process\.env\.(\w+)(?:,| })/) ?? line.match(/[{,] url: env\(['"](\w+)['"]\)(?:,| })/))?.[1];
|
|
18
|
+
if (envVarName && envVarName !== "DATABASE_URL") {
|
|
19
|
+
if (force) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.warn(
|
|
23
|
+
`Found a non-standard prisma config datasource url env var: "${envVarName}".
|
|
24
|
+
Cedar will not override this env var, potentially running destructive commands against your production database.`
|
|
25
|
+
);
|
|
26
|
+
const { proceed } = await Enquirer.prompt({
|
|
27
|
+
type: "confirm",
|
|
28
|
+
name: "proceed",
|
|
29
|
+
message: "Are you sure you want to run tests against this database?",
|
|
30
|
+
initial: false
|
|
31
|
+
});
|
|
32
|
+
if (!proceed) {
|
|
33
|
+
console.log("Aborting.");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
warnIfNonStandardDatasourceUrl
|
|
42
|
+
};
|