@cedarjs/cli 7.0.0-canary.3259 → 7.0.0-rc.123
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/commands/build/buildHandler.js +1 -2
- package/dist/commands/build.js +1 -1
- package/dist/commands/check.js +1 -2
- package/dist/commands/deploy/baremetal/baremetalHandler.js +1 -1
- package/dist/commands/deploy/baremetal.js +1 -1
- package/dist/commands/deploy/flightcontrolHandler.js +1 -1
- package/dist/commands/deploy/helpers/deployHandler.js +1 -1
- package/dist/commands/deploy/netlify.js +1 -1
- package/dist/commands/deploy/renderHandler.js +1 -1
- package/dist/commands/deploy/serverlessHandler.js +1 -2
- package/dist/commands/deploy/vercel.js +1 -1
- package/dist/commands/destroy/handlerHelpers.js +1 -1
- package/dist/commands/destroy/page/pageHandler.js +1 -2
- package/dist/commands/destroy/scaffold/scaffoldHandler.js +1 -2
- package/dist/commands/destroy/sdl/sdlHandler.js +1 -2
- package/dist/commands/dev/devHandler.js +4 -3
- package/dist/commands/dev/packageWatchCommands.js +3 -8
- package/dist/commands/dev.js +1 -1
- package/dist/commands/execHandler.js +1 -2
- package/dist/commands/experimental/live-queries/liveQueries.js +1 -1
- package/dist/commands/experimental/live-queries/liveQueriesHandler.js +3 -3
- package/dist/commands/experimental/setupInngest.js +1 -1
- package/dist/commands/experimental/setupInngestHandler.js +1 -1
- package/dist/commands/experimental/setupOpentelemetry.js +1 -1
- package/dist/commands/experimental/setupOpentelemetryHandler.js +1 -2
- package/dist/commands/experimental/setupReactCompiler.js +1 -1
- package/dist/commands/experimental/setupReactCompilerHandler.js +4 -4
- package/dist/commands/experimental/setupRsc.js +1 -1
- package/dist/commands/experimental/setupRscHandler.js +1 -2
- package/dist/commands/experimental/setupStreamingSsr.js +1 -1
- package/dist/commands/experimental/setupStreamingSsrHandler.js +2 -3
- package/dist/commands/generate/cell/cell.js +0 -20
- package/dist/commands/generate/cell/cellHandler.js +20 -68
- package/dist/commands/generate/cell/templates/cell.tsx.template +2 -21
- package/dist/commands/generate/cell/templates/cellList.tsx.template +2 -21
- package/dist/commands/generate/cell/templates/test.js.template +1 -1
- package/dist/commands/generate/dataMigration/dataMigration.js +1 -2
- package/dist/commands/generate/dbAuth/dbAuthHandler.js +3 -23
- package/dist/commands/generate/directive/directiveHandler.js +1 -2
- package/dist/commands/generate/function/functionHandler.js +1 -2
- package/dist/commands/generate/job/jobHandler.js +1 -2
- package/dist/commands/generate/model/modelHandler.js +1 -2
- package/dist/commands/generate/ogImage/ogImageHandler.js +1 -2
- package/dist/commands/generate/package/filesTask.js +12 -9
- package/dist/commands/generate/package/packageHandler.js +4 -3
- package/dist/commands/generate/page/pageHandler.js +1 -2
- package/dist/commands/generate/realtime/realtime.js +1 -1
- package/dist/commands/generate/realtime/realtimeHandler.js +9 -2
- package/dist/commands/generate/realtime/templates/subscriptions/blank/blank.ts.template +1 -1
- package/dist/commands/generate/scaffold/scaffoldHandler.js +5 -10
- package/dist/commands/generate/scaffold/templates/components/NameForm.tsx.template +3 -3
- package/dist/commands/generate/scaffold/templates/lib/formatters.test.tsx.template +0 -11
- package/dist/commands/generate/scaffold/templates/lib/formatters.tsx.template +1 -13
- package/dist/commands/generate/script/scriptHandler.js +1 -2
- package/dist/commands/generate/sdl/sdlHandler.js +1 -2
- package/dist/commands/generate/secret/secret.js +1 -1
- package/dist/commands/generate/service/serviceHandler.js +38 -47
- package/dist/commands/generate/service/templates/service.ts.template +8 -22
- package/dist/commands/generate/service/templates/test.ts.template +1 -1
- package/dist/commands/generate/yargsCommandHelpers.js +1 -1
- package/dist/commands/generate/yargsHandlerHelpers.js +1 -2
- package/dist/commands/generate.js +1 -1
- package/dist/commands/info.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/prerenderHandler.js +4 -11
- package/dist/commands/prismaHandler.js +2 -7
- package/dist/commands/record/init.js +1 -1
- package/dist/commands/serve.js +1 -2
- package/dist/commands/setup/auth/auth.js +4 -2
- package/dist/commands/setup/cache/cache.js +1 -1
- package/dist/commands/setup/cache/cacheHandler.js +1 -2
- package/dist/commands/setup/database/postgres.js +1 -1
- package/dist/commands/setup/database/postgresHandler.js +1 -3
- package/dist/commands/setup/deploy/providers/baremetalHandler.js +1 -2
- package/dist/commands/setup/deploy/providers/coherence.js +1 -1
- package/dist/commands/setup/deploy/providers/coherenceHandler.js +6 -7
- package/dist/commands/setup/deploy/providers/flightcontrolHandler.js +1 -2
- package/dist/commands/setup/deploy/providers/netlifyHandler.js +1 -2
- package/dist/commands/setup/deploy/providers/renderHandler.js +1 -2
- package/dist/commands/setup/deploy/providers/serverlessHandler.js +1 -2
- package/dist/commands/setup/deploy/providers/universalDeployHandler.js +6 -4
- package/dist/commands/setup/deploy/providers/vercelHandler.js +1 -2
- package/dist/commands/setup/docker/docker.js +1 -1
- package/dist/commands/setup/docker/dockerHandler.js +1 -2
- package/dist/commands/setup/generator/generator.js +1 -1
- package/dist/commands/setup/generator/generatorHandler.js +1 -1
- package/dist/commands/setup/graphql/features/fragments/fragments.js +1 -1
- package/dist/commands/setup/graphql/features/fragments/fragmentsHandler.js +5 -3
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocuments.js +1 -1
- package/dist/commands/setup/graphql/features/trustedDocuments/trustedDocumentsHandler.js +1 -2
- package/dist/commands/setup/i18n/i18n.js +1 -1
- package/dist/commands/setup/i18n/i18nHandler.js +1 -1
- package/dist/commands/setup/jobs/jobs.js +1 -1
- package/dist/commands/setup/jobs/jobsHandler.js +1 -2
- package/dist/commands/setup/mailer/mailer.js +1 -1
- package/dist/commands/setup/mailer/mailerHandler.js +1 -2
- package/dist/commands/setup/middleware/ogImage/ogImage.js +1 -1
- package/dist/commands/setup/middleware/ogImage/ogImageHandler.js +1 -2
- package/dist/commands/setup/monitoring/sentry/sentry.js +1 -1
- package/dist/commands/setup/monitoring/sentry/sentryHandler.js +7 -8
- package/dist/commands/setup/neon/neon.js +1 -1
- package/dist/commands/setup/neon/neonHandler.js +9 -5
- package/dist/commands/setup/package/package.js +1 -1
- package/dist/commands/setup/package/packageHandler.js +4 -4
- 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 +16 -4
- 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 +1 -2
- package/dist/commands/setup/ui/libraries/chakra-uiHandler.js +1 -2
- package/dist/commands/setup/ui/libraries/mantineHandler.js +1 -2
- package/dist/commands/setup/ui/libraries/tailwindcssHandler.js +1 -2
- package/dist/commands/setup/uploads/dbCodemod.js +28 -0
- package/dist/commands/setup/uploads/templates/signedUrl.ts.template +21 -0
- package/dist/commands/setup/uploads/templates/srcLibUploads.ts.template +24 -23
- package/dist/commands/setup/uploads/uploads.js +7 -49
- package/dist/commands/setup/uploads/uploadsHandler.js +69 -256
- package/dist/commands/setup.js +1 -2
- package/dist/commands/studio.js +1 -1
- package/dist/commands/test/testHandler.js +71 -25
- package/dist/commands/test/testHandlerEsm.js +100 -0
- package/dist/commands/test.js +18 -10
- package/dist/commands/testEsm.js +41 -0
- package/dist/commands/type-checkHandler.js +1 -1
- package/dist/commands/upgrade/preUpgradeScripts.js +3 -3
- package/dist/commands/upgrade/upgrade.js +1 -1
- package/dist/commands/upgrade/upgradeHandler.js +1 -2
- package/dist/index.js +8 -5
- package/dist/lib/exit.js +1 -1
- package/dist/lib/index.js +25 -6
- package/dist/lib/loadEnvFiles.js +1 -1
- package/dist/lib/plugin.js +1 -1
- package/dist/lib/test.js +1 -1
- package/dist/lib/updateCheck.js +4 -4
- package/dist/middleware/checkNodeVersion.js +4 -4
- package/package.json +18 -18
- package/dist/commands/generate/cell/templates/cellFragment.tsx.template +0 -43
- package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +0 -23
- package/dist/commands/generate/cell/templates/testFragment.js.template +0 -30
- package/dist/commands/generate/dbAuth/templates/login.oauth.tsx.template +0 -164
- package/dist/commands/generate/dbAuth/templates/signup.oauth.tsx.template +0 -147
- package/dist/commands/setup/tenancy/authCodemod.js +0 -66
- package/dist/commands/setup/tenancy/dbCodemod.js +0 -64
- package/dist/commands/setup/tenancy/graphqlCodemod.js +0 -88
- package/dist/commands/setup/tenancy/preflight.js +0 -49
- package/dist/commands/setup/tenancy/schemaPrisma.js +0 -81
- package/dist/commands/setup/tenancy/signupCodemod.js +0 -153
- package/dist/commands/setup/tenancy/templates/InvitePage.tsx.template +0 -63
- package/dist/commands/setup/tenancy/templates/OrgScope.tsx.template +0 -40
- package/dist/commands/setup/tenancy/templates/ensureDefaultOrganizations.dataMigration.ts.template +0 -39
- package/dist/commands/setup/tenancy/templates/organizations.scenarios.ts.template +0 -59
- package/dist/commands/setup/tenancy/templates/organizations.sdl.ts.template +0 -89
- package/dist/commands/setup/tenancy/templates/organizations.test.ts.template +0 -389
- package/dist/commands/setup/tenancy/templates/organizations.ts.template +0 -394
- package/dist/commands/setup/tenancy/templates/requireMembership.test.ts.template +0 -35
- package/dist/commands/setup/tenancy/templates/requireMembership.ts.template +0 -25
- package/dist/commands/setup/tenancy/tenancy.js +0 -30
- package/dist/commands/setup/tenancy/tenancyHandler.js +0 -425
- package/dist/commands/setup/uploads/schemaPrisma.js +0 -41
- package/dist/commands/setup/uploads/serverFile.js +0 -151
- package/dist/commands/setup/uploads/templates/requireUploadToken.ts.template +0 -15
- package/dist/commands/setup/uploads/templates/uploads.sdl.ts.template +0 -79
- package/dist/commands/setup/uploads/templates/uploads.ts.template +0 -89
- package/dist/commands/setup/uploads/templates/withDataUri.ts.template +0 -14
- package/dist/commands/setup/uploads/templates/withSignedUrl.ts.template +0 -16
- package/dist/commands/test/viteVersionCheck.js +0 -75
|
@@ -2,9 +2,8 @@ import path from "node:path";
|
|
|
2
2
|
import { paramCase } from "change-case";
|
|
3
3
|
import { Listr } from "listr2";
|
|
4
4
|
import { terminalLink } from "termi-link";
|
|
5
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
5
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
6
6
|
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
7
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
8
7
|
import { getDataMigrationsPath } from "@cedarjs/project-config";
|
|
9
8
|
import {
|
|
10
9
|
generateTemplate,
|
|
@@ -4,10 +4,9 @@ import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
|
4
4
|
import { camelCase } from "camel-case";
|
|
5
5
|
import { Listr } from "listr2";
|
|
6
6
|
import { titleCase } from "title-case";
|
|
7
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
7
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
8
8
|
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
9
9
|
import { runBinSync } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
10
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
11
10
|
import {
|
|
12
11
|
addRoutesToRouterTask,
|
|
13
12
|
addScaffoldImport,
|
|
@@ -76,14 +75,12 @@ const files = async ({
|
|
|
76
75
|
skipReset,
|
|
77
76
|
skipSignup,
|
|
78
77
|
webauthn,
|
|
79
|
-
oauth,
|
|
80
78
|
usernameLabel,
|
|
81
79
|
passwordLabel
|
|
82
80
|
}) => {
|
|
83
81
|
const filesList = [];
|
|
84
82
|
usernameLabel = usernameLabel || "username";
|
|
85
83
|
passwordLabel = passwordLabel || "password";
|
|
86
|
-
const oauthEnabled = oauth ?? isOAuthEnabled();
|
|
87
84
|
const templateVars = {
|
|
88
85
|
usernameLowerCase: usernameLabel.toLowerCase(),
|
|
89
86
|
usernameCamelCase: camelCase(usernameLabel),
|
|
@@ -113,7 +110,7 @@ const files = async ({
|
|
|
113
110
|
extension: typescript ? ".tsx" : ".jsx",
|
|
114
111
|
webPathSection: "pages",
|
|
115
112
|
generator: "dbAuth",
|
|
116
|
-
templatePath:
|
|
113
|
+
templatePath: webauthn ? "login.webAuthn.tsx.template" : "login.tsx.template",
|
|
117
114
|
templateVars
|
|
118
115
|
})
|
|
119
116
|
);
|
|
@@ -139,7 +136,7 @@ const files = async ({
|
|
|
139
136
|
extension: typescript ? ".tsx" : ".jsx",
|
|
140
137
|
webPathSection: "pages",
|
|
141
138
|
generator: "dbAuth",
|
|
142
|
-
templatePath:
|
|
139
|
+
templatePath: "signup.tsx.template",
|
|
143
140
|
templateVars
|
|
144
141
|
})
|
|
145
142
|
);
|
|
@@ -381,23 +378,6 @@ function isWebAuthnEnabled() {
|
|
|
381
378
|
);
|
|
382
379
|
return webPackageJson.includes('"@simplewebauthn/browser": ');
|
|
383
380
|
}
|
|
384
|
-
function isOAuthEnabled() {
|
|
385
|
-
const apiPackageJsonPath = path.join(getPaths().base, "api", "package.json");
|
|
386
|
-
if (!fs.existsSync(apiPackageJsonPath)) {
|
|
387
|
-
return false;
|
|
388
|
-
}
|
|
389
|
-
const apiPackageJson = fs.readFileSync(apiPackageJsonPath, "utf-8");
|
|
390
|
-
return apiPackageJson.includes('"@cedarjs/auth-dbauth-oauth": ');
|
|
391
|
-
}
|
|
392
|
-
function loginTemplatePath(webauthn, oauth) {
|
|
393
|
-
if (webauthn) {
|
|
394
|
-
return "login.webAuthn.tsx.template";
|
|
395
|
-
}
|
|
396
|
-
if (oauth) {
|
|
397
|
-
return "login.oauth.tsx.template";
|
|
398
|
-
}
|
|
399
|
-
return "login.tsx.template";
|
|
400
|
-
}
|
|
401
381
|
export {
|
|
402
382
|
files,
|
|
403
383
|
handler
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import camelcase from "camelcase";
|
|
2
2
|
import { Listr } from "listr2";
|
|
3
3
|
import prompts from "prompts";
|
|
4
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
4
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
5
5
|
import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
6
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
7
6
|
import { getConfig } from "@cedarjs/project-config";
|
|
8
7
|
import { writeFilesTask, transformTSToJSMap } from "../../../lib/index.js";
|
|
9
8
|
import {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Listr } from "listr2";
|
|
2
2
|
import { terminalLink } from "termi-link";
|
|
3
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
4
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
3
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
5
4
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
6
5
|
import { transformTSToJSMap, writeFilesTask } from "../../../lib/index.js";
|
|
7
6
|
import { prepareForRollback } from "../../../lib/rollback.js";
|
|
@@ -2,9 +2,8 @@ import path from "node:path";
|
|
|
2
2
|
import { pathToFileURL } from "node:url";
|
|
3
3
|
import * as changeCase from "change-case";
|
|
4
4
|
import { Listr } from "listr2";
|
|
5
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
5
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
6
6
|
import { runBinSync } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
7
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
8
7
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
9
8
|
import {
|
|
10
9
|
getPaths,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import { Listr } from "listr2";
|
|
3
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
4
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
3
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
5
4
|
import {
|
|
6
5
|
getPaths,
|
|
7
6
|
writeFilesTask,
|
|
@@ -2,8 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import fg from "fast-glob";
|
|
4
4
|
import { Listr } from "listr2";
|
|
5
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
6
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
5
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
7
6
|
import { ensurePosixPath } from "@cedarjs/project-config";
|
|
8
7
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
9
8
|
import {
|
|
@@ -8,6 +8,7 @@ const files = async ({
|
|
|
8
8
|
fileName,
|
|
9
9
|
typescript,
|
|
10
10
|
tests: generateTests = true,
|
|
11
|
+
esm = false,
|
|
11
12
|
...rest
|
|
12
13
|
}) => {
|
|
13
14
|
const extension = typescript ? ".ts" : ".js";
|
|
@@ -58,15 +59,17 @@ const files = async ({
|
|
|
58
59
|
outputPath: path.join(folderName, "src", `${fileName}.test${extension}`)
|
|
59
60
|
});
|
|
60
61
|
outputFiles.push(testFile);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
if (esm) {
|
|
63
|
+
const vitestConfigFile = await templateForFile({
|
|
64
|
+
name,
|
|
65
|
+
side: "packages",
|
|
66
|
+
generator: "package",
|
|
67
|
+
templatePath: "vitest.config.ts.template",
|
|
68
|
+
templateVars: { folderName, ...rest },
|
|
69
|
+
outputPath: path.join(folderName, `vitest.config${extension}`)
|
|
70
|
+
});
|
|
71
|
+
outputFiles.push(vitestConfigFile);
|
|
72
|
+
}
|
|
70
73
|
}
|
|
71
74
|
return outputFiles.reduce(async (accP, [outputPath, content]) => {
|
|
72
75
|
const acc = await accP;
|
|
@@ -6,13 +6,12 @@ import { modify, applyEdits } from "jsonc-parser";
|
|
|
6
6
|
import { Listr } from "listr2";
|
|
7
7
|
import { terminalLink } from "termi-link";
|
|
8
8
|
import ts from "typescript";
|
|
9
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
9
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
10
10
|
import { workspacePackageSpecifier } from "@cedarjs/cli-helpers/packageManager";
|
|
11
11
|
import { runScript, runBinSync } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
12
12
|
import { installPackages } from "@cedarjs/cli-helpers/packageManager/packages";
|
|
13
13
|
import { addWorkspaceDir } from "@cedarjs/cli-helpers/packageManager/workspaces";
|
|
14
|
-
import {
|
|
15
|
-
import { getConfig } from "@cedarjs/project-config";
|
|
14
|
+
import { getConfig, projectIsEsm } from "@cedarjs/project-config";
|
|
16
15
|
import { getPackageManager } from "@cedarjs/project-config/packageManager";
|
|
17
16
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
18
17
|
import { getPaths, writeFilesTask } from "../../../lib/index.js";
|
|
@@ -343,6 +342,8 @@ const handler = async ({
|
|
|
343
342
|
task: async (ctx) => {
|
|
344
343
|
packageFiles = await files({
|
|
345
344
|
...ctx.nameVariants,
|
|
345
|
+
// Only Vitest projects get a config generated for them
|
|
346
|
+
esm: projectIsEsm(),
|
|
346
347
|
...rest
|
|
347
348
|
});
|
|
348
349
|
return writeFilesTask(packageFiles, { overwriteExisting: force });
|
|
@@ -2,8 +2,7 @@ import { execSync } from "child_process";
|
|
|
2
2
|
import camelcase from "camelcase";
|
|
3
3
|
import { Listr } from "listr2";
|
|
4
4
|
import pascalcase from "pascalcase";
|
|
5
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
6
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
5
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
7
6
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
8
7
|
import { getConfig } from "@cedarjs/project-config";
|
|
9
8
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers
|
|
1
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
2
2
|
const command = "realtime <name>";
|
|
3
3
|
const description = "Generate a subscription or live query used with RedwoodJS Realtime";
|
|
4
4
|
function builder(yargs) {
|
|
@@ -4,8 +4,9 @@ import { Listr } from "listr2";
|
|
|
4
4
|
import pascalcase from "pascalcase";
|
|
5
5
|
import pluralize from "pluralize";
|
|
6
6
|
import prompts from "prompts";
|
|
7
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
7
|
+
import { colors as c } from "@cedarjs/cli-helpers";
|
|
8
8
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
9
|
+
import { projectIsEsm } from "@cedarjs/project-config";
|
|
9
10
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
10
11
|
import {
|
|
11
12
|
generateTemplate,
|
|
@@ -119,10 +120,16 @@ async function handler({
|
|
|
119
120
|
exampleFile,
|
|
120
121
|
exampleSubscriptionTemplateContent
|
|
121
122
|
);
|
|
122
|
-
|
|
123
|
+
let blankTemplateContent = await generateTemplate(
|
|
123
124
|
setupScriptContent,
|
|
124
125
|
templateVariables(name)
|
|
125
126
|
);
|
|
127
|
+
if (projectIsEsm()) {
|
|
128
|
+
blankTemplateContent = blankTemplateContent.replace(
|
|
129
|
+
"import gql from 'graphql-tag'",
|
|
130
|
+
"import { gql } from 'graphql-tag'"
|
|
131
|
+
);
|
|
132
|
+
}
|
|
126
133
|
return [
|
|
127
134
|
writeFile(
|
|
128
135
|
sdlFile,
|
|
@@ -5,15 +5,14 @@ import { paramCase } from "change-case";
|
|
|
5
5
|
import humanize from "humanize-string";
|
|
6
6
|
import { Listr } from "listr2";
|
|
7
7
|
import pascalcase from "pascalcase";
|
|
8
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
8
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
9
9
|
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
10
10
|
import {
|
|
11
11
|
addWorkspacePackages,
|
|
12
12
|
removeWorkspacePackages
|
|
13
13
|
} from "@cedarjs/cli-helpers/packageManager/packages";
|
|
14
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
15
14
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
16
|
-
import { getConfig
|
|
15
|
+
import { getConfig } from "@cedarjs/project-config";
|
|
17
16
|
import { pluralize, singularize } from "@cedarjs/utils/cedarPluralize";
|
|
18
17
|
import {
|
|
19
18
|
generateTemplate,
|
|
@@ -190,7 +189,6 @@ const assetFiles = async (name, tailwind) => {
|
|
|
190
189
|
}
|
|
191
190
|
return fileList;
|
|
192
191
|
};
|
|
193
|
-
const isDateTimeParsed = () => getParsedScalars().DateTime === "Date";
|
|
194
192
|
const formatters = async (name, isTypescript) => {
|
|
195
193
|
const outputPath = path.join(
|
|
196
194
|
getPaths().web.src,
|
|
@@ -212,8 +210,7 @@ const formatters = async (name, isTypescript) => {
|
|
|
212
210
|
templatePath: path.join("lib", "formatters.tsx.template")
|
|
213
211
|
}),
|
|
214
212
|
{
|
|
215
|
-
name
|
|
216
|
-
parsedDateTime: isDateTimeParsed()
|
|
213
|
+
name
|
|
217
214
|
}
|
|
218
215
|
);
|
|
219
216
|
const templateTest = await generateTemplate(
|
|
@@ -223,8 +220,7 @@ const formatters = async (name, isTypescript) => {
|
|
|
223
220
|
templatePath: path.join("lib", "formatters.test.tsx.template")
|
|
224
221
|
}),
|
|
225
222
|
{
|
|
226
|
-
name
|
|
227
|
-
parsedDateTime: isDateTimeParsed()
|
|
223
|
+
name
|
|
228
224
|
}
|
|
229
225
|
);
|
|
230
226
|
return {
|
|
@@ -344,8 +340,7 @@ const modelRelatedVariables = (model) => {
|
|
|
344
340
|
fieldsToImport,
|
|
345
341
|
editableColumns,
|
|
346
342
|
listFormattersImports,
|
|
347
|
-
formattersImports
|
|
348
|
-
parsedDateTime: isDateTimeParsed()
|
|
343
|
+
formattersImports
|
|
349
344
|
};
|
|
350
345
|
};
|
|
351
346
|
const layoutFiles = async (name, force, generateTypescript, templateStrings) => {
|
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
|
|
13
13
|
<% if (fieldsToImport.includes('DatetimeLocalField')) { %>
|
|
14
14
|
/**
|
|
15
|
-
* Formats a DateTime
|
|
15
|
+
* Formats a DateTime string from the API, which is a UTC timestamp, for use as
|
|
16
16
|
* the value of a `datetime-local` input. The input takes `YYYY-MM-DDTHH:mm` in
|
|
17
17
|
* the user's local time, with no seconds, milliseconds or timezone, and the
|
|
18
18
|
* form reads its value back as local time when it is submitted.
|
|
19
19
|
*/
|
|
20
|
-
function formatDatetime(value:
|
|
20
|
+
function formatDatetime(value: string | undefined | null) {
|
|
21
21
|
if (!value) {
|
|
22
22
|
return undefined
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const date =
|
|
25
|
+
const date = new Date(value)
|
|
26
26
|
|
|
27
27
|
if (Number.isNaN(date.getTime())) {
|
|
28
28
|
return undefined
|
|
@@ -83,25 +83,14 @@ describe('jsonTruncate', () => {
|
|
|
83
83
|
|
|
84
84
|
describe('timeTag', () => {
|
|
85
85
|
it('renders a date', async () => {
|
|
86
|
-
<% if (parsedDateTime) { %>
|
|
87
|
-
render(<div>{timeTag(new Date('1970-08-20'))}</div>)
|
|
88
|
-
<% } else { %>
|
|
89
86
|
render(<div>{timeTag(new Date('1970-08-20').toUTCString())}</div>)
|
|
90
|
-
<% } %>
|
|
91
87
|
|
|
92
88
|
await waitFor(() => screen.getByText(/1970.*00:00:00/))
|
|
93
89
|
})
|
|
94
90
|
|
|
95
|
-
<% if (parsedDateTime) { %>
|
|
96
|
-
it('can take an empty input', async () => {
|
|
97
|
-
expect(timeTag(null)).toEqual('')
|
|
98
|
-
expect(timeTag(undefined)).toEqual('')
|
|
99
|
-
})
|
|
100
|
-
<% } else { %>
|
|
101
91
|
it('can take an empty input string', async () => {
|
|
102
92
|
expect(timeTag('')).toEqual('')
|
|
103
93
|
})
|
|
104
|
-
<% } %>
|
|
105
94
|
})
|
|
106
95
|
|
|
107
96
|
describe('jsonDisplay', () => {
|
|
@@ -39,27 +39,15 @@ export const jsonTruncate = (obj: unknown) => {
|
|
|
39
39
|
return truncate(JSON.stringify(obj, null, 2))
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function timeTag(dateTime:
|
|
42
|
+
export function timeTag(dateTime: string | undefined | null) {
|
|
43
43
|
let output: string | React.JSX.Element = ''
|
|
44
44
|
|
|
45
45
|
if (dateTime) {
|
|
46
|
-
<% if (parsedDateTime) { %>
|
|
47
|
-
if (!Number.isNaN(dateTime.getTime())) {
|
|
48
|
-
const isoString = dateTime.toISOString()
|
|
49
|
-
|
|
50
|
-
output = (
|
|
51
|
-
<time dateTime={isoString} title={isoString}>
|
|
52
|
-
{dateTime.toUTCString()}
|
|
53
|
-
</time>
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
<% } else { %>
|
|
57
46
|
output = (
|
|
58
47
|
<time dateTime={dateTime} title={dateTime}>
|
|
59
48
|
{new Date(dateTime).toUTCString()}
|
|
60
49
|
</time>
|
|
61
50
|
)
|
|
62
|
-
<% } %>
|
|
63
51
|
}
|
|
64
52
|
|
|
65
53
|
return output
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Listr } from "listr2";
|
|
4
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
5
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
4
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
6
5
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
7
6
|
import {
|
|
8
7
|
getPaths,
|
|
@@ -2,9 +2,8 @@ import ansis from "ansis";
|
|
|
2
2
|
import boxen from "boxen";
|
|
3
3
|
import camelcase from "camelcase";
|
|
4
4
|
import { Listr } from "listr2";
|
|
5
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
5
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
6
6
|
import { formatCedarCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
7
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
8
7
|
import { generate as generateTypes } from "@cedarjs/internal/dist/generate/generate";
|
|
9
8
|
import { getConfig } from "@cedarjs/project-config";
|
|
10
9
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { terminalLink } from "termi-link";
|
|
3
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers
|
|
3
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
4
4
|
const DEFAULT_LENGTH = 32;
|
|
5
5
|
const generateSecret = (length = DEFAULT_LENGTH) => {
|
|
6
6
|
return crypto.randomBytes(Math.trunc(length)).toString("base64");
|
|
@@ -250,10 +250,6 @@ const getIdName = async (model) => {
|
|
|
250
250
|
if (!isServiceModel(schemaResult)) {
|
|
251
251
|
return void 0;
|
|
252
252
|
}
|
|
253
|
-
if (schemaResult.primaryKey?.fields.length) {
|
|
254
|
-
const { fields, name } = schemaResult.primaryKey;
|
|
255
|
-
return { fields, whereArg: name || fields.join("_") };
|
|
256
|
-
}
|
|
257
253
|
return schemaResult.fields.find((field) => field.isId)?.name;
|
|
258
254
|
};
|
|
259
255
|
const files = async ({
|
|
@@ -266,11 +262,6 @@ const files = async ({
|
|
|
266
262
|
const componentName = camelcase(pluralize(name));
|
|
267
263
|
const model = name;
|
|
268
264
|
const idName = await getIdName(model);
|
|
269
|
-
if (tests && rest.crud && idName !== void 0 && typeof idName !== "string") {
|
|
270
|
-
throw new Error(
|
|
271
|
-
`Cannot generate CRUD tests for "${model}": it has a compound primary key (@@id([${idName.fields.join(", ")}])), which isn't supported by the generated test file yet. Re-run with \`--tests=false\`.`
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
265
|
const prismaImportSource = "src/lib/db";
|
|
275
266
|
let modelRelations;
|
|
276
267
|
if (relations) {
|
|
@@ -295,46 +286,46 @@ const files = async ({
|
|
|
295
286
|
...rest
|
|
296
287
|
}
|
|
297
288
|
});
|
|
289
|
+
const testFile = await templateForFile({
|
|
290
|
+
name,
|
|
291
|
+
side: "api",
|
|
292
|
+
sidePathSection: "services",
|
|
293
|
+
generator: "service",
|
|
294
|
+
outputPath: path.join(componentName, componentName + ".test.ts"),
|
|
295
|
+
templatePath: "test.ts.template",
|
|
296
|
+
templateVars: {
|
|
297
|
+
relations: relations || [],
|
|
298
|
+
create: await fieldsToInput(model),
|
|
299
|
+
update: await fieldsToUpdate(model),
|
|
300
|
+
types: await fieldTypes(model),
|
|
301
|
+
prismaImport: (await parseSchema(model)).scalarFields.some(
|
|
302
|
+
(field) => field.type === "Decimal"
|
|
303
|
+
),
|
|
304
|
+
prismaModel: model,
|
|
305
|
+
idName,
|
|
306
|
+
prismaImportSource,
|
|
307
|
+
...rest
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
const scenariosFile = await templateForFile({
|
|
311
|
+
name,
|
|
312
|
+
side: "api",
|
|
313
|
+
sidePathSection: "services",
|
|
314
|
+
generator: "service",
|
|
315
|
+
outputPath: path.join(componentName, componentName + ".scenarios.ts"),
|
|
316
|
+
templatePath: "scenarios.ts.template",
|
|
317
|
+
templateVars: {
|
|
318
|
+
scenario: await buildScenario(model),
|
|
319
|
+
stringifiedScenario: await buildStringifiedScenario(model),
|
|
320
|
+
prismaModel: model,
|
|
321
|
+
idName,
|
|
322
|
+
relations: modelRelations,
|
|
323
|
+
prismaImportSource,
|
|
324
|
+
...rest
|
|
325
|
+
}
|
|
326
|
+
});
|
|
298
327
|
const files2 = [serviceFile];
|
|
299
328
|
if (tests) {
|
|
300
|
-
const testFile = await templateForFile({
|
|
301
|
-
name,
|
|
302
|
-
side: "api",
|
|
303
|
-
sidePathSection: "services",
|
|
304
|
-
generator: "service",
|
|
305
|
-
outputPath: path.join(componentName, componentName + ".test.ts"),
|
|
306
|
-
templatePath: "test.ts.template",
|
|
307
|
-
templateVars: {
|
|
308
|
-
relations: relations || [],
|
|
309
|
-
create: await fieldsToInput(model),
|
|
310
|
-
update: await fieldsToUpdate(model),
|
|
311
|
-
types: await fieldTypes(model),
|
|
312
|
-
prismaImport: (await parseSchema(model)).scalarFields.some(
|
|
313
|
-
(field) => field.type === "Decimal"
|
|
314
|
-
),
|
|
315
|
-
prismaModel: model,
|
|
316
|
-
idName,
|
|
317
|
-
prismaImportSource,
|
|
318
|
-
...rest
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
const scenariosFile = await templateForFile({
|
|
322
|
-
name,
|
|
323
|
-
side: "api",
|
|
324
|
-
sidePathSection: "services",
|
|
325
|
-
generator: "service",
|
|
326
|
-
outputPath: path.join(componentName, componentName + ".scenarios.ts"),
|
|
327
|
-
templatePath: "scenarios.ts.template",
|
|
328
|
-
templateVars: {
|
|
329
|
-
scenario: await buildScenario(model),
|
|
330
|
-
stringifiedScenario: await buildStringifiedScenario(model),
|
|
331
|
-
prismaModel: model,
|
|
332
|
-
idName,
|
|
333
|
-
relations: modelRelations,
|
|
334
|
-
prismaImportSource,
|
|
335
|
-
...rest
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
329
|
files2.push(testFile);
|
|
339
330
|
files2.push(scenariosFile);
|
|
340
331
|
}
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
import type { QueryResolvers<% if (crud) { %>, MutationResolvers<% } %><% if (relations.length) { %>, ${singularPascalName}RelationResolvers<% } %> } from 'types/graphql'
|
|
2
2
|
|
|
3
3
|
import { db } from 'src/lib/db'
|
|
4
|
-
|
|
5
|
-
// A compound `@@id([...])` key comes through as `{ fields, whereArg }`
|
|
6
|
-
// instead of a single field name -- build the destructure/where-clause
|
|
7
|
-
// snippets for both shapes here so the rest of the template can stay
|
|
8
|
-
// shape-agnostic.
|
|
9
|
-
const idIsComposite = idName != null && typeof idName === 'object'
|
|
10
|
-
const idFields = idIsComposite ? idName.fields : [idName]
|
|
11
|
-
const idArgs = idFields.join(', ')
|
|
12
|
-
const idWhere = idIsComposite
|
|
13
|
-
? `${idName.whereArg}: { ${idFields.join(', ')} }`
|
|
14
|
-
: idName
|
|
15
|
-
const idWhereFromRoot = idIsComposite
|
|
16
|
-
? `${idName.whereArg}: { ${idFields.map((f) => `${f}: root?.${f}`).join(', ')} }`
|
|
17
|
-
: `${idName}: root?.${idName}`
|
|
18
|
-
%>
|
|
4
|
+
|
|
19
5
|
export const ${pluralCamelName}: QueryResolvers['${pluralCamelName}'] = () => {
|
|
20
6
|
return db.${singularCamelName}.findMany()
|
|
21
7
|
}<% if (crud || relations.length) { %>
|
|
22
8
|
|
|
23
|
-
export const ${singularCamelName}: QueryResolvers['${singularCamelName}'] = ({ ${
|
|
9
|
+
export const ${singularCamelName}: QueryResolvers['${singularCamelName}'] = ({ ${idName} }) => {
|
|
24
10
|
return db.${singularCamelName}.findUnique({
|
|
25
|
-
where: { ${
|
|
11
|
+
where: { ${idName} },
|
|
26
12
|
})
|
|
27
13
|
}<% } %><% if (crud) { %>
|
|
28
14
|
|
|
@@ -32,21 +18,21 @@ export const create${singularPascalName}: MutationResolvers['create${singularPas
|
|
|
32
18
|
})
|
|
33
19
|
}
|
|
34
20
|
|
|
35
|
-
export const update${singularPascalName}: MutationResolvers['update${singularPascalName}'] = ({ ${
|
|
21
|
+
export const update${singularPascalName}: MutationResolvers['update${singularPascalName}'] = ({ ${idName}, input }) => {
|
|
36
22
|
return db.${singularCamelName}.update({
|
|
37
23
|
data: input,
|
|
38
|
-
where: { ${
|
|
24
|
+
where: { ${idName} },
|
|
39
25
|
})
|
|
40
26
|
}
|
|
41
27
|
|
|
42
|
-
export const delete${singularPascalName}: MutationResolvers['delete${singularPascalName}'] = ({ ${
|
|
28
|
+
export const delete${singularPascalName}: MutationResolvers['delete${singularPascalName}'] = ({ ${idName} }) => {
|
|
43
29
|
return db.${singularCamelName}.delete({
|
|
44
|
-
where: { ${
|
|
30
|
+
where: { ${idName} },
|
|
45
31
|
})
|
|
46
32
|
}<% } %><% if (relations.length) { %>
|
|
47
33
|
|
|
48
34
|
export const ${singularPascalName}: ${singularPascalName}RelationResolvers = {<% relations.forEach(relation => { %>
|
|
49
35
|
${relation}: (_obj, { root }) => {
|
|
50
|
-
return db.${singularCamelName}.findUnique({ where: { ${
|
|
36
|
+
return db.${singularCamelName}.findUnique({ where: { ${idName}: root?.${idName} } }).${relation}()
|
|
51
37
|
},<% }) %>
|
|
52
38
|
}<% } %>
|
|
@@ -40,7 +40,7 @@ import type { StandardScenario } from './${pluralCamelName}.scenarios.js'
|
|
|
40
40
|
// and can fail without adjustments, e.g. Float.
|
|
41
41
|
// Please refer to the RedwoodJS Testing Docs:
|
|
42
42
|
// https://cedarjs.com/docs/testing#testing-services
|
|
43
|
-
// https://cedarjs.com/docs/testing#expect-type-considerations
|
|
43
|
+
// https://cedarjs.com/docs/testing#jest-expect-type-considerations
|
|
44
44
|
|
|
45
45
|
describe('${pluralCamelName}', () => {
|
|
46
46
|
scenario('returns all ${pluralCamelName}', async (scenario: StandardScenario) => {
|
|
@@ -3,8 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { camelCase } from "change-case";
|
|
4
4
|
import { Listr } from "listr2";
|
|
5
5
|
import pascalcase from "pascalcase";
|
|
6
|
-
import { colors as c } from "@cedarjs/cli-helpers
|
|
7
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
6
|
+
import { recordTelemetryAttributes, colors as c } from "@cedarjs/cli-helpers";
|
|
8
7
|
import { ensurePosixPath, getConfig } from "@cedarjs/project-config";
|
|
9
8
|
import { errorTelemetry } from "@cedarjs/telemetry";
|
|
10
9
|
import { generateTemplate, getPaths, writeFilesTask } from "../../lib/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { terminalLink } from "termi-link";
|
|
2
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
2
3
|
import { runBinSync } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
3
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
4
4
|
import * as generateCell from "./generate/cell/cell.js";
|
|
5
5
|
import * as generateComponent from "./generate/component/component.js";
|
|
6
6
|
import * as generateDataMigration from "./generate/dataMigration/dataMigration.js";
|
package/dist/commands/info.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import envinfo from "envinfo";
|
|
4
4
|
import { terminalLink } from "termi-link";
|
|
5
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers
|
|
5
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
6
6
|
import { getConfigPath } from "@cedarjs/project-config";
|
|
7
7
|
const command = "info";
|
|
8
8
|
const description = "Print your system environment information";
|
package/dist/commands/lint.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { terminalLink } from "termi-link";
|
|
3
|
+
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers";
|
|
3
4
|
import { runBin } from "@cedarjs/cli-helpers/packageManager/exec";
|
|
4
|
-
import { recordTelemetryAttributes } from "@cedarjs/cli-helpers/telemetry";
|
|
5
5
|
import { getPaths } from "@cedarjs/project-config";
|
|
6
6
|
const command = "lint [paths..]";
|
|
7
7
|
const description = "Lint your files";
|