@cedarjs/cli 6.0.0-rc.312 → 6.0.0
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/generate/cell/templates/cellFragment.tsx.template +43 -0
- package/dist/commands/generate/cell/templates/storiesFragment.tsx.template +23 -0
- package/dist/commands/generate/cell/templates/testFragment.js.template +30 -0
- package/dist/commands/lintPreflight.js +133 -0
- package/dist/commands/setup/uploads/uploadsHandler.js +1 -1
- package/dist/commands/upgrade/preUpgradeScripts.js +9 -9
- package/dist/commands/upgrade/upgradeHandler.js +42 -32
- package/dist/lib/background.js +20 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +17 -17
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ${fragmentName} } from 'types/graphql'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
CellSuccessProps,<% if (afterQuery || isEmpty) { %>
|
|
5
|
+
DataObject,<% } %>
|
|
6
|
+
} from '@cedarjs/web'
|
|
7
|
+
|
|
8
|
+
// A parent Cell spreads this fragment by name in its own QUERY, and passes
|
|
9
|
+
// the matching field down as the `${camelName}` prop - no import needed,
|
|
10
|
+
// just render <${pascalName}Cell />:
|
|
11
|
+
//
|
|
12
|
+
// query FindSomething($id: Int!) {
|
|
13
|
+
// something(id: $id) {
|
|
14
|
+
// id
|
|
15
|
+
// ...${fragmentName}
|
|
16
|
+
// }
|
|
17
|
+
// }
|
|
18
|
+
//
|
|
19
|
+
// <${pascalName}Cell ${camelName}={something} />
|
|
20
|
+
export const FRAGMENT = gql`
|
|
21
|
+
fragment ${fragmentName} on ${fragmentOnType} {
|
|
22
|
+
id
|
|
23
|
+
}
|
|
24
|
+
`
|
|
25
|
+
<% if (isEmpty) { %>
|
|
26
|
+
export const isEmpty = (
|
|
27
|
+
data: DataObject,
|
|
28
|
+
{ isDataEmpty }: { isDataEmpty: (data: DataObject) => boolean },
|
|
29
|
+
) => {
|
|
30
|
+
return isDataEmpty(data)
|
|
31
|
+
}
|
|
32
|
+
<% } %><% if (afterQuery) { %>
|
|
33
|
+
export const afterQuery = (data: DataObject): DataObject => {
|
|
34
|
+
return data
|
|
35
|
+
}
|
|
36
|
+
<% } %>
|
|
37
|
+
export const Empty = () => <div>Empty</div>
|
|
38
|
+
|
|
39
|
+
export const Success = ({
|
|
40
|
+
${camelName},
|
|
41
|
+
}: CellSuccessProps<{ ${camelName}: ${fragmentName} }>) => {
|
|
42
|
+
return <div>{JSON.stringify(${camelName})}</div>
|
|
43
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
|
|
3
|
+
import { Empty, Success } from './${pascalName}Cell'
|
|
4
|
+
import { standard } from './${pascalName}Cell.mock'
|
|
5
|
+
|
|
6
|
+
const meta: Meta = {
|
|
7
|
+
title: 'Cells/${pascalName}Cell',
|
|
8
|
+
tags: ['autodocs']
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default meta
|
|
12
|
+
|
|
13
|
+
export const empty: StoryObj<typeof Empty> = {
|
|
14
|
+
render: () => {
|
|
15
|
+
return Empty ? <Empty /> : <></>
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const success: StoryObj<typeof Success> = {
|
|
20
|
+
render: (args) => {
|
|
21
|
+
return Success ? <Success {...standard()} {...args} /> : <></>
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { render } from '@cedarjs/testing/web'
|
|
2
|
+
|
|
3
|
+
import { Empty, Success } from './${pascalName}Cell'
|
|
4
|
+
import { standard } from './${pascalName}Cell.mock'
|
|
5
|
+
|
|
6
|
+
// Generated boilerplate tests do not account for all circumstances
|
|
7
|
+
// and can fail without adjustments, e.g. Float and DateTime types.
|
|
8
|
+
// Please refer to the RedwoodJS Testing Docs:
|
|
9
|
+
// https://cedarjs.com/docs/testing#testing-cells
|
|
10
|
+
// https://cedarjs.com/docs/testing#jest-expect-type-considerations
|
|
11
|
+
|
|
12
|
+
describe('${pascalName}Cell', () => {
|
|
13
|
+
it('renders Empty successfully', async () => {
|
|
14
|
+
expect(() => {
|
|
15
|
+
render(<Empty />)
|
|
16
|
+
}).not.toThrow()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// When you're ready to test the actual output of your component render
|
|
20
|
+
// you could test that, for example, certain text is present:
|
|
21
|
+
//
|
|
22
|
+
// 1. import { screen } from '@cedarjs/testing/web'
|
|
23
|
+
// 2. Add test: expect(screen.getByText('Hello, world')).toBeInTheDocument()
|
|
24
|
+
|
|
25
|
+
it('renders Success successfully', async () => {
|
|
26
|
+
expect(() => {
|
|
27
|
+
render(<Success ${camelName}={standard().${camelName}} />)
|
|
28
|
+
}).not.toThrow()
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { colors } from "@cedarjs/cli-helpers";
|
|
4
|
+
import { formatAddRootPackagesCommand } from "@cedarjs/cli-helpers/packageManager/display";
|
|
5
|
+
import { getPaths } from "@cedarjs/project-config";
|
|
6
|
+
const FLAT_CONFIG_FILENAMES = [
|
|
7
|
+
"eslint.config.js",
|
|
8
|
+
"eslint.config.mjs",
|
|
9
|
+
"eslint.config.cjs",
|
|
10
|
+
"eslint.config.ts",
|
|
11
|
+
"eslint.config.mts",
|
|
12
|
+
"eslint.config.cts"
|
|
13
|
+
];
|
|
14
|
+
const LEGACY_CONFIG_FILENAMES = [
|
|
15
|
+
".eslintrc",
|
|
16
|
+
".eslintrc.js",
|
|
17
|
+
".eslintrc.cjs",
|
|
18
|
+
".eslintrc.mjs",
|
|
19
|
+
".eslintrc.json",
|
|
20
|
+
".eslintrc.yaml",
|
|
21
|
+
".eslintrc.yml"
|
|
22
|
+
];
|
|
23
|
+
const MIGRATION_GUIDE_URL = "https://github.com/cedarjs/cedar/blob/main/packages/eslint-config/README.md#migrating-from-legacy-eslintrcjs-config";
|
|
24
|
+
function findFlatConfig(base) {
|
|
25
|
+
return FLAT_CONFIG_FILENAMES.map(
|
|
26
|
+
(filename) => path.join(base, filename)
|
|
27
|
+
).find((configPath) => fs.existsSync(configPath));
|
|
28
|
+
}
|
|
29
|
+
function readRootPackageJson(base) {
|
|
30
|
+
try {
|
|
31
|
+
const contents = fs.readFileSync(path.join(base, "package.json"), "utf-8");
|
|
32
|
+
const parsed = JSON.parse(contents);
|
|
33
|
+
if (parsed && typeof parsed === "object") {
|
|
34
|
+
return parsed;
|
|
35
|
+
}
|
|
36
|
+
return void 0;
|
|
37
|
+
} catch {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function hasLegacyConfig(base, packageJson) {
|
|
42
|
+
const hasLegacyConfigFile = LEGACY_CONFIG_FILENAMES.some(
|
|
43
|
+
(filename) => fs.existsSync(path.join(base, filename))
|
|
44
|
+
);
|
|
45
|
+
return hasLegacyConfigFile || Boolean(packageJson?.["eslintConfig"]);
|
|
46
|
+
}
|
|
47
|
+
function listsEslintConfigPackage(packageJson) {
|
|
48
|
+
return ["dependencies", "devDependencies"].some((field) => {
|
|
49
|
+
const deps = packageJson[field];
|
|
50
|
+
return deps !== null && typeof deps === "object" && "@cedarjs/eslint-config" in deps;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function formatAddConfigPackageCommand() {
|
|
54
|
+
let version = "";
|
|
55
|
+
try {
|
|
56
|
+
const packageJson = await import("../../package.json", { with: { type: "json" } });
|
|
57
|
+
version = "@" + packageJson.default.version;
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return formatAddRootPackagesCommand(
|
|
62
|
+
["@cedarjs/eslint-config" + version],
|
|
63
|
+
true
|
|
64
|
+
);
|
|
65
|
+
} catch {
|
|
66
|
+
return "yarn add -D @cedarjs/eslint-config" + version;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function legacyConfigMessage(packageJson) {
|
|
70
|
+
const needsConfigPackage = !packageJson || !listsEslintConfigPackage(packageJson);
|
|
71
|
+
return [
|
|
72
|
+
colors.error("Cedar no longer supports ESLint's legacy config format"),
|
|
73
|
+
"",
|
|
74
|
+
"Support for `.eslintrc.*` and the `eslintConfig` field in package.json",
|
|
75
|
+
"was removed in v6. Create an `eslint.config.mjs` in your project root",
|
|
76
|
+
'(`eslint.config.js` if your project is ESM, i.e. has `"type": "module"`):',
|
|
77
|
+
"",
|
|
78
|
+
colors.tip(" import cedarConfig from '@cedarjs/eslint-config'"),
|
|
79
|
+
"",
|
|
80
|
+
colors.tip(" export default await cedarConfig()"),
|
|
81
|
+
"",
|
|
82
|
+
"Then delete your `.eslintrc.*` file and remove the `eslintConfig` field",
|
|
83
|
+
"from package.json, moving any custom rules you had into an extra config",
|
|
84
|
+
"object after `cedarConfig()`.",
|
|
85
|
+
...needsConfigPackage ? [
|
|
86
|
+
"",
|
|
87
|
+
"You'll also need `@cedarjs/eslint-config` itself, which is no longer",
|
|
88
|
+
"installed for you:",
|
|
89
|
+
"",
|
|
90
|
+
colors.tip(" " + await formatAddConfigPackageCommand())
|
|
91
|
+
] : [],
|
|
92
|
+
"",
|
|
93
|
+
"Full migration guide: " + colors.link(MIGRATION_GUIDE_URL)
|
|
94
|
+
].join("\n");
|
|
95
|
+
}
|
|
96
|
+
async function missingConfigPackageMessage(flatConfigPath) {
|
|
97
|
+
return [
|
|
98
|
+
colors.error("Cannot find `@cedarjs/eslint-config`"),
|
|
99
|
+
"",
|
|
100
|
+
`Your ${path.basename(flatConfigPath)} uses \`@cedarjs/eslint-config\`, but`,
|
|
101
|
+
"the package isn't listed in your project's package.json. As of v6,",
|
|
102
|
+
"`@cedarjs/core` no longer depends on it, so projects have to declare it",
|
|
103
|
+
"themselves:",
|
|
104
|
+
"",
|
|
105
|
+
colors.tip(" " + await formatAddConfigPackageCommand()),
|
|
106
|
+
"",
|
|
107
|
+
colors.info(
|
|
108
|
+
"`@cedarjs/eslint-config` brings its own ESLint, so you do not need to add `eslint` separately."
|
|
109
|
+
)
|
|
110
|
+
].join("\n");
|
|
111
|
+
}
|
|
112
|
+
async function getEslintSetupError() {
|
|
113
|
+
const base = getPaths().base;
|
|
114
|
+
const packageJson = readRootPackageJson(base);
|
|
115
|
+
const flatConfigPath = findFlatConfig(base);
|
|
116
|
+
if (!flatConfigPath) {
|
|
117
|
+
if (!hasLegacyConfig(base, packageJson)) {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
return legacyConfigMessage(packageJson);
|
|
121
|
+
}
|
|
122
|
+
if (!packageJson || listsEslintConfigPackage(packageJson)) {
|
|
123
|
+
return void 0;
|
|
124
|
+
}
|
|
125
|
+
const flatConfig = fs.readFileSync(flatConfigPath, "utf-8");
|
|
126
|
+
if (!flatConfig.includes("@cedarjs/eslint-config")) {
|
|
127
|
+
return void 0;
|
|
128
|
+
}
|
|
129
|
+
return missingConfigPackageMessage(flatConfigPath);
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
getEslintSetupError
|
|
133
|
+
};
|
|
@@ -83,7 +83,7 @@ const handler = async ({ force }) => {
|
|
|
83
83
|
if (transformResult.error) {
|
|
84
84
|
if (transformResult.error === "RW_CODEMOD_ERR_OLD_FORMAT") {
|
|
85
85
|
throw new Error(
|
|
86
|
-
"It looks like your src/lib/db file is using the old format. Please update it as per the v8 upgrade guide: https://cedarjs.com/docs/upgrade-guides/v8#database-file-structure-change. And run again. \n\nYou can also manually modify your api/src/lib/db to include the prisma extension: https://cedarjs.com/docs/uploads/#attaching-the-prisma-extension"
|
|
86
|
+
"It looks like your src/lib/db file is using the old format. Please update it as per the v8 upgrade guide: https://cedarjs.com/docs/8.x/upgrade-guides/v8#database-file-structure-change. And run again. \n\nYou can also manually modify your api/src/lib/db to include the prisma extension: https://cedarjs.com/docs/uploads/#attaching-the-prisma-extension"
|
|
87
87
|
);
|
|
88
88
|
}
|
|
89
89
|
throw new Error(
|
|
@@ -4,6 +4,7 @@ import os from "node:os";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import execa from "execa";
|
|
6
6
|
import semver from "semver";
|
|
7
|
+
const MAIN_BRANCH_PRERELEASE_TAGS = ["canary"];
|
|
7
8
|
function isExecaError(e) {
|
|
8
9
|
return e instanceof Error && ("stdout" in e || "stderr" in e || "exitCode" in e);
|
|
9
10
|
}
|
|
@@ -33,8 +34,15 @@ async function runPreUpgradeScripts(ctx, task, { verbose, force }) {
|
|
|
33
34
|
if (!Array.isArray(manifest) || manifest.length === 0) {
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
37
|
+
const prereleaseTag = parsed?.prerelease[0];
|
|
38
|
+
const isMainBranchPrerelease = typeof prereleaseTag === "string" && MAIN_BRANCH_PRERELEASE_TAGS.includes(prereleaseTag);
|
|
36
39
|
const checkLevels = [];
|
|
37
|
-
if (parsed &&
|
|
40
|
+
if (parsed && isMainBranchPrerelease) {
|
|
41
|
+
checkLevels.push({
|
|
42
|
+
id: "tag",
|
|
43
|
+
candidates: [`${prereleaseTag}.ts`, `${prereleaseTag}/index.ts`]
|
|
44
|
+
});
|
|
45
|
+
} else if (parsed) {
|
|
38
46
|
checkLevels.push({
|
|
39
47
|
id: "exact",
|
|
40
48
|
candidates: [`${version}.ts`, `${version}/index.ts`]
|
|
@@ -50,14 +58,6 @@ async function runPreUpgradeScripts(ctx, task, { verbose, force }) {
|
|
|
50
58
|
id: "minor",
|
|
51
59
|
candidates: [`${parsed.major}.x.ts`, `${parsed.major}.x/index.ts`]
|
|
52
60
|
});
|
|
53
|
-
} else if (parsed && parsed.prerelease.length > 0) {
|
|
54
|
-
checkLevels.push({
|
|
55
|
-
id: "tag",
|
|
56
|
-
candidates: [
|
|
57
|
-
`${parsed.prerelease[0]}.ts`,
|
|
58
|
-
`${parsed.prerelease[0]}/index.ts`
|
|
59
|
-
]
|
|
60
|
-
});
|
|
61
61
|
}
|
|
62
62
|
const scriptsToRun = [];
|
|
63
63
|
for (const level of checkLevels) {
|
|
@@ -33,6 +33,7 @@ const handler = async (upgradeOptions) => {
|
|
|
33
33
|
});
|
|
34
34
|
let preUpgradeMessage = "";
|
|
35
35
|
let preUpgradeError = "";
|
|
36
|
+
const notBlockedByPreUpgradeChecks = (ctx) => force || !ctx.preUpgradeError;
|
|
36
37
|
const tasks = new Listr(
|
|
37
38
|
[
|
|
38
39
|
{
|
|
@@ -87,39 +88,46 @@ const handler = async (upgradeOptions) => {
|
|
|
87
88
|
{
|
|
88
89
|
title: "Updating your CedarJS version",
|
|
89
90
|
task: (ctx) => updateCedarJSDepsForAllSides(ctx, { dryRun, verbose }),
|
|
90
|
-
enabled: (ctx) => !!ctx.versionToUpgradeTo &&
|
|
91
|
+
enabled: (ctx) => !!ctx.versionToUpgradeTo && notBlockedByPreUpgradeChecks(ctx)
|
|
91
92
|
},
|
|
92
93
|
{
|
|
93
94
|
title: "Updating other packages in your package.json(s)",
|
|
94
95
|
task: (ctx) => updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }),
|
|
95
|
-
|
|
96
|
+
// Canary only. This forces the template's dependency versions onto the
|
|
97
|
+
// project and adds back any the project is missing, which resurrects
|
|
98
|
+
// packages people have deliberately removed — a project that moved off
|
|
99
|
+
// SQLite gets better-sqlite3 back, for example. That's too blunt for
|
|
100
|
+
// regular upgrades, but people running canary are already signed up
|
|
101
|
+
// for rougher edges.
|
|
102
|
+
// https://github.com/redwoodjs/redwood/pull/8855
|
|
103
|
+
enabled: (ctx) => String(ctx.versionToUpgradeTo).includes("canary") && notBlockedByPreUpgradeChecks(ctx)
|
|
96
104
|
},
|
|
97
105
|
{
|
|
98
106
|
title: "Downloading yarn patches",
|
|
99
107
|
task: (ctx) => downloadYarnPatches(ctx, { dryRun, verbose }),
|
|
100
|
-
enabled: (ctx) => String(ctx.versionToUpgradeTo).includes("canary") &&
|
|
108
|
+
enabled: (ctx) => String(ctx.versionToUpgradeTo).includes("canary") && notBlockedByPreUpgradeChecks(ctx)
|
|
101
109
|
},
|
|
102
110
|
{
|
|
103
111
|
title: "Removing CLI cache",
|
|
104
112
|
task: () => removeCliCache({ dryRun, verbose }),
|
|
105
|
-
enabled: (ctx) =>
|
|
113
|
+
enabled: (ctx) => notBlockedByPreUpgradeChecks(ctx)
|
|
106
114
|
},
|
|
107
115
|
{
|
|
108
116
|
title: `Running ${getPackageManager()} ${install()}`,
|
|
109
117
|
task: () => packageManagerInstall({ verbose }),
|
|
110
|
-
enabled: (ctx) =>
|
|
118
|
+
enabled: (ctx) => notBlockedByPreUpgradeChecks(ctx),
|
|
111
119
|
skip: () => !!dryRun
|
|
112
120
|
},
|
|
113
121
|
{
|
|
114
122
|
title: "Refreshing the Prisma client",
|
|
115
123
|
task: (_ctx, task) => refreshPrismaClient(task, { verbose }),
|
|
116
|
-
enabled: (ctx) =>
|
|
124
|
+
enabled: (ctx) => notBlockedByPreUpgradeChecks(ctx),
|
|
117
125
|
skip: () => !!dryRun
|
|
118
126
|
},
|
|
119
127
|
{
|
|
120
128
|
title: "De-duplicating dependencies",
|
|
121
129
|
skip: () => !!dryRun || !dedupe2,
|
|
122
|
-
enabled: (ctx) => dedupeIsSupported() &&
|
|
130
|
+
enabled: (ctx) => dedupeIsSupported() && notBlockedByPreUpgradeChecks(ctx),
|
|
123
131
|
task: (_ctx, task) => dedupeDeps(task, { verbose })
|
|
124
132
|
},
|
|
125
133
|
{
|
|
@@ -303,6 +311,22 @@ function updateCedarJSDepsForAllSides(ctx, options) {
|
|
|
303
311
|
})
|
|
304
312
|
);
|
|
305
313
|
}
|
|
314
|
+
function mergeTemplateDependencies(field, templatePackageJson, localPackageJson, messages, { dryRun, verbose } = {}) {
|
|
315
|
+
const templateDeps = templatePackageJson[field];
|
|
316
|
+
if (!templateDeps) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
for (const [depName, depVersion] of Object.entries(templateDeps)) {
|
|
320
|
+
if (depName.startsWith("@cedarjs/")) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const localDeps = localPackageJson[field] ??= {};
|
|
324
|
+
if (verbose || dryRun) {
|
|
325
|
+
messages.push(` - ${depName}: ${localDeps[depName]} => ${depVersion}`);
|
|
326
|
+
}
|
|
327
|
+
localDeps[depName] = depVersion;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
306
330
|
async function updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }) {
|
|
307
331
|
if (!ctx.versionToUpgradeTo) {
|
|
308
332
|
throw new Error("Failed to upgrade");
|
|
@@ -338,30 +362,15 @@ async function updatePackageVersionsFromTemplate(ctx, { dryRun, verbose }) {
|
|
|
338
362
|
const localPackageJsonText = fs.readFileSync(pkgJsonPath, "utf-8");
|
|
339
363
|
const localPackageJson = JSON.parse(localPackageJsonText);
|
|
340
364
|
const messages = [];
|
|
341
|
-
|
|
342
|
-
(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
);
|
|
353
|
-
Object.entries(templatePackageJson.devDependencies || {}).forEach(
|
|
354
|
-
([depName, depVersion]) => {
|
|
355
|
-
if (!depName.startsWith("@cedarjs/")) {
|
|
356
|
-
if (verbose || dryRun) {
|
|
357
|
-
messages.push(
|
|
358
|
-
` - ${depName}: ${localPackageJson.devDependencies[depName]} => ${depVersion}`
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
localPackageJson.devDependencies[depName] = depVersion;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
);
|
|
365
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
366
|
+
mergeTemplateDependencies(
|
|
367
|
+
field,
|
|
368
|
+
templatePackageJson,
|
|
369
|
+
localPackageJson,
|
|
370
|
+
messages,
|
|
371
|
+
{ dryRun, verbose }
|
|
372
|
+
);
|
|
373
|
+
}
|
|
365
374
|
if (messages.length > 0) {
|
|
366
375
|
task.title = task.title + "\n" + messages.join("\n");
|
|
367
376
|
}
|
|
@@ -469,5 +478,6 @@ async function dedupeDeps(_task, { verbose }) {
|
|
|
469
478
|
await packageManagerInstall({ verbose });
|
|
470
479
|
}
|
|
471
480
|
export {
|
|
472
|
-
handler
|
|
481
|
+
handler,
|
|
482
|
+
mergeTemplateDependencies
|
|
473
483
|
};
|
package/dist/lib/background.js
CHANGED
|
@@ -3,6 +3,23 @@ import fs from "node:fs";
|
|
|
3
3
|
import os from "os";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { getPaths } from "@cedarjs/project-config";
|
|
6
|
+
function quoteForWindowsShell(arg) {
|
|
7
|
+
let quoted = '"';
|
|
8
|
+
let backslashes = 0;
|
|
9
|
+
for (const char of arg) {
|
|
10
|
+
if (char === "\\") {
|
|
11
|
+
backslashes += 1;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (char === '"') {
|
|
15
|
+
quoted += "\\".repeat(backslashes * 2 + 1) + '"';
|
|
16
|
+
} else {
|
|
17
|
+
quoted += "\\".repeat(backslashes) + char;
|
|
18
|
+
}
|
|
19
|
+
backslashes = 0;
|
|
20
|
+
}
|
|
21
|
+
return quoted + "\\".repeat(backslashes * 2) + '"';
|
|
22
|
+
}
|
|
6
23
|
function spawnBackgroundProcess(name, cmd, args) {
|
|
7
24
|
const logDirectory = path.join(getPaths().generated.base, "logs");
|
|
8
25
|
fs.mkdirSync(logDirectory, { recursive: true });
|
|
@@ -37,7 +54,8 @@ function spawnBackgroundProcess(name, cmd, args) {
|
|
|
37
54
|
shell: true,
|
|
38
55
|
stdio: ["ignore", stdout, stderr]
|
|
39
56
|
};
|
|
40
|
-
const
|
|
57
|
+
const command = [cmd, ...args].map(quoteForWindowsShell).join(" ");
|
|
58
|
+
const child = spawn(command, spawnOptions);
|
|
41
59
|
child.unref();
|
|
42
60
|
} else {
|
|
43
61
|
const spawnOptions = {
|
|
@@ -51,5 +69,6 @@ function spawnBackgroundProcess(name, cmd, args) {
|
|
|
51
69
|
fs.closeSync(stderr);
|
|
52
70
|
}
|
|
53
71
|
export {
|
|
72
|
+
quoteForWindowsShell,
|
|
54
73
|
spawnBackgroundProcess
|
|
55
74
|
};
|