Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions packages/create-apostrophe/src/core/steps/install.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Step: install dependencies with npm. Standalone installs once in the app
// root; an external-frontend project installs in backend/ and frontend/.
// A non-npm manager is rejected up front. Failure → 'dependency_install'.
// root; an external-frontend project installs in backend/ and frontend/, and
// — if the project root ships its own package.json — also at the root (some
// Astro kits put orchestration deps like `concurrently` there to power a
// single `npm run dev`). A non-npm manager is rejected up front. Failure →
// 'dependency_install'.

import { join } from 'node:path';
import { existsSync } from 'node:fs';
Expand Down Expand Up @@ -41,6 +44,9 @@ export async function install(
if (existsSync(frontendDir)) {
dirs.push(frontendDir);
}
if (existsSync(join(projectDir, 'package.json'))) {
dirs.push(projectDir);
}
}

for (const cwd of dirs) {
Expand Down
30 changes: 30 additions & 0 deletions packages/create-apostrophe/test/core/install.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,36 @@ describe('core/steps/install', function () {
]);
});

it('external frontend + root package.json: backend → frontend → root', async function () {
// Newer Astro kits ship a root package.json with orchestration deps
// (concurrently) so a single `npm run dev` runs both apps. Without
// installing the root, `npm run dev` fails with "concurrently: not found".
const projectDir = join(dir, 'proj');
const appRoot = join(projectDir, 'backend');
mkdirSync(appRoot, { recursive: true });
mkdirSync(join(projectDir, 'frontend'), { recursive: true });
writeFileSync(join(projectDir, 'package.json'), '{}');

const calls = [];
await install(
{
projectDir,
appRoot,
frontend: 'astro',
packageManager: 'npm'
},
{ run: fakeRunFactory(calls) }
);

// Root install runs LAST so its (potentially redundant) recursion into
// workspaces hits an already-warm cache.
assert.deepEqual(calls.map((c) => [ c.command, c.cwd ]), [
[ 'npm', appRoot ],
[ 'npm', join(projectDir, 'frontend') ],
[ 'npm', projectDir ]
]);
});

it('unknown pm runs npm, reports \'unknown\'', async function () {
const projectDir = join(dir, 'proj');
mkdirSync(projectDir, { recursive: true });
Expand Down
Loading