Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open
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
1 change: 1 addition & 0 deletions 1 RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ You can use [this saved search](https://github.com/ember-cli/ember-cli/pulls?q=i
pnpm dlx update-blueprint-deps --filter '@ember-tooling/.*' --tag latest ./package.json ./packages/*-blueprint/**/*ackage.json
pnpm dlx update-blueprint-deps --filter '.*' ./package.json ./packages/*-blueprint/**/*ackage.json ./tests/fixtures/*/package.json ./tests/fixtures/*/*/package.json
```

- run `pnpm install` to update your pacakge.lock and download any new dependencies
- run `pnpm lint:fix`
- update the @ember/app-blueprint dependency `pnpm i -w @ember/app-blueprint@latest`
Expand Down
2 changes: 1 addition & 1 deletion 2 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
"eslint-plugin-mocha": "^10.5.0",
"eslint-plugin-n": "^17.24.0",
"fixturify": "^3.0.0",
"fixturify-project": "^2.1.1",
"fixturify-project": "^7.1.3",
"jsdom": "^21.1.2",
"latest-version": "^9.0.0",
"mocha": "^11.7.6",
Expand Down
1,176 changes: 1,133 additions & 43 deletions 1,176 pnpm-lock.yaml

Large diffs are not rendered by default.

125 changes: 48 additions & 77 deletions 125 tests/helpers/fixturify-project.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use strict';

const path = require('path');
const fs = require('fs-extra');
const merge = require('lodash/merge');
// this is a test-only dependency
// eslint-disable-next-line n/no-unpublished-require
const FixturifyProject = require('fixturify-project');
const { Project: FixturifyProject } = require('fixturify-project');
const Project = require('../../lib/models/project');
const MockCLI = require('./mock-cli');

Expand Down Expand Up @@ -45,49 +46,44 @@ function getOptionsObjectWithCallbackFunction(defaultOptions, optionsOrCallback)
);
}

// Essentially a copy of the function in node-fixturify-project, converted from TS to JS.
// We need this for use during toJSON().
function parseScoped(name) {
let matched = name.match(/(@[^@/]+)\/(.*)/);
if (matched) {
return {
scope: matched[1],
name: matched[2],
};
}
return null;
}

module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
writeSync() {
super.writeSync(...arguments);
async write() {
await super.write(...arguments);

// in-repo addons are not real dependencies (they live in `lib/`, not
// `node_modules/`), so they are not written by the upstream `write`;
// write each one into `lib/<name>` ourselves
for (let inRepoAddon of this._inRepoAddons || []) {
inRepoAddon.baseDir = path.join(this.baseDir, 'lib', inRepoAddon.name);
await inRepoAddon.write();
}

this._hasWritten = true;
}

addFiles(filesObj) {
merge(this.files, filesObj);
}

buildProjectModel(ProjectClass = ProjectWithoutInternalAddons) {
async buildProjectModel(ProjectClass = ProjectWithoutInternalAddons) {
if (!this._hasWritten) {
this.writeSync();
await this.write();
}

let pkg = JSON.parse(this.toJSON('package.json'));
let pkg = fs.readJsonSync(path.join(this.baseDir, 'package.json'));
let cli = new MockCLI();
let root = path.join(this.root, this.name);

return new ProjectClass(root, pkg, cli.ui, cli);
return new ProjectClass(this.baseDir, pkg, cli.ui, cli);
}

buildProjectModelForInRepoAddon(addonName, ProjectClass = ProjectWithoutInternalAddons) {
async buildProjectModelForInRepoAddon(addonName, ProjectClass = ProjectWithoutInternalAddons) {
if (!this._hasWritten) {
this.writeSync();
await this.write();
}

let pkg = JSON.parse(this.files.lib[addonName]['package.json']);
let root = path.join(this.baseDir, 'lib', addonName);
let pkg = fs.readJsonSync(path.join(root, 'package.json'));
let cli = new MockCLI();
let root = path.join(this.root, this.name, 'lib', addonName);

return new ProjectClass(root, pkg, cli.ui, cli);
}
Expand All @@ -96,6 +92,10 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
* Add an entry for this object's `dependencies` list. When this object is written out, the
* dependency will also then write out appropriate files in this object's `node_modules' subdirectory.
*
* The new dependency is created as an instance of this class (upstream would create a plain
* fixturify-project `Project`), so that ember-cli-specific helpers (`addAddon`,
* `addReferenceDependency`, etc.) are available on nested dependencies.
*
* @param {String} name name of the dependency to add
* @param {String} version version of the dependency to add
* @param {Object|Function} optionsOrCallback options to configure the new FixturifyProject, or a callback function to call after creating
Expand All @@ -105,15 +105,16 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
*/
addDependency(name, version, optionsOrCallback) {
const options = getOptionsObjectWithCallbackFunction(optionsOrCallback);
return super.addDependency(name, version, options.callback);
return super.addDependency(new this.constructor(name, version), options.callback);
}

/**
* Add a 'reference' entry to this object's `dependencies` list. A 'reference' dependency is
* an entry in `dependencies` where the caller knows the dependency's source files are being
* created elsewhere in the project tree, so no source files should be created locally in
* `node_modules`, which is the standard FixturifyProject (and node-fixturify-project) behavior.
* We do this by adding the necessary reference to `dependencies` during `toJSON`.
* We do this by adding the necessary reference to `dependencies` when `package.json` is
* generated during `write`.
*
* This is used when two addons wish to share a single definition on disk for a dependency (various parts of
* ember-cli optimize processing based on paths on disk.)
Expand All @@ -136,6 +137,8 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
* Add an entry to this object's `devDependencies` list. When this object is written out, the
* dependency will also then write out appropriate files in this object's `node_modules' subdirectory.
*
* As with `addDependency`, the new dependency is created as an instance of this class.
*
* @param {String} name name of the dev dependency to add
* @param {String} version version of the dev dependency to add
* @param {Object|Function} optionsOrCallback options to configure the new FixturifyProject, or a callback function to call after creating
Expand All @@ -145,15 +148,16 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
*/
addDevDependency(name, version, optionsOrCallback) {
const options = getOptionsObjectWithCallbackFunction(optionsOrCallback);
return super.addDevDependency(name, version, options.callback);
return super.addDevDependency(new this.constructor(name, version), options.callback);
}

/**
* Add a 'reference' entry to this object's `devDependencies` list. A 'reference' devDependency is
* an entry in `devDependencies` where the caller knows the dependency's source files are being
* created elsewhere in the project tree, so no source files should be created locally in
* `node_modules`, which is the standard FixturifyProject (and node-fixturify-project) behavior.
* We do this by adding the necessary reference to `devDependencies` during `toJSON`.
* We do this by adding the necessary reference to `devDependencies` when `package.json` is
* generated during `write`.
*
* This is used when two addons wish to share a single definition on disk for a devDependency
* (various parts of ember-cli optimize processing based on paths on disk.)
Expand Down Expand Up @@ -287,24 +291,21 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {

// configure the current project to have an ember-addon configured at the
// appropriate path, i.e. under a common root directory (lib).
const addonRootDir = 'lib';
const addonPath = `lib/${name}`;

// Add to ember-addon.paths list
let addon = (this.pkg['ember-addon'] = this.pkg['ember-addon'] || {});
addon.paths = addon.paths || [];

const addonPath = `${addonRootDir}/${name}`;

if (addon.paths.find((path) => path.toLowerCase() === addonPath.toLowerCase())) {
throw new Error(`project: ${this.name} already contains the in-repo-addon: ${name}`);
}

addon.paths.push(addonPath);

this.files[addonRootDir] = this.files[addonRootDir] || {};
this._inRepoAddons = this._inRepoAddons || [];
this._inRepoAddons.push(inRepoAddon);

let addonJSON = inRepoAddon.toJSON();
Object.assign(this.files[addonRootDir], addonJSON);
return inRepoAddon;
}

Expand Down Expand Up @@ -343,54 +344,24 @@ module.exports = class EmberCLIFixturifyProject extends FixturifyProject {
}

/**
* Convert the object into a data structure suitable for passing to `fixturify`.
* Applies the 'reference' dependencies (see `addReferenceDependency` and
* `addReferenceDevDependency`) to the generated `package.json` contents when this
* project is written to disk.
*
* @param {String} key optional key. If specified, the object will be run through toJSON, then the given
* property extracted and returned.
* @returns {Object} the `toJSON` value of the object (wrapped) or the toJSON value of the specified field
* (not wrapped.)
* This overrides a private fixturify-project method, as there is no public hook for
* customizing the generated `package.json`.
*/
toJSON(key) {
if (key) {
return super.toJSON(key);
}

let jsonData = super.toJSON();

let scoped = parseScoped(this.name);

// Allowing for scoped names, get the object in the JSON structure that corresponds
// to this FixturifyProject.
let container = scoped ? jsonData[scoped.scope][scoped.name] : jsonData[this.name];

if (this._referenceDependencies || this._referenceDevDependencies) {
let pkg = JSON.parse(container['package.json']);

if (this._referenceDependencies) {
if (!pkg.dependencies) {
pkg.dependencies = {};
}

Object.assign(pkg.dependencies, this._referenceDependencies);
}

if (this._referenceDevDependencies) {
if (!pkg.devDependencies) {
pkg.devDependencies = {};
}

Object.assign(pkg.devDependencies, this._referenceDevDependencies);
}
pkgJSONWithDeps(resolvedLinks) {
const pkg = super.pkgJSONWithDeps(resolvedLinks);

container['package.json'] = JSON.stringify(pkg, undefined, 2);
if (this._referenceDependencies) {
pkg.dependencies = Object.assign({}, pkg.dependencies, this._referenceDependencies);
}

// an optimization to remove any node_modules declaration that has nothing in it,
// to avoid creating extra directories for no reason.
if (container['node_modules'] && Object.keys(container['node_modules']).length === 0) {
delete container['node_modules'];
if (this._referenceDevDependencies) {
pkg.devDependencies = Object.assign({}, pkg.devDependencies, this._referenceDevDependencies);
}

return jsonData;
return pkg;
}
};
26 changes: 8 additions & 18 deletions 26 tests/helpers/per-bundle-addon-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,47 +113,37 @@ function countAddons(projectOrAddon, config = { byName: {}, proxyCount: 0, realA
function createStandardCacheFixture() {
let project = new FixturifyProject('test-ember-project', '1.0.0');

// these two addons are defined in PROJECT/lib but the project doesn't depend
// on them directly (their entries in the project's `ember-addon.paths` are
// removed below); the addons and engines that follow share these two
// definitions on disk by relative path
project.addInRepoAddon('test-addon-dep', '1.0.0');
project.addInRepoAddon('test-engine-dep', '1.0.0');
project.pkg['ember-addon'].paths = [];

project.addInRepoAddon('test-addon-a', '1.0.0', {
callback: (addonA) => {
addonA.addInRepoAddon('test-addon-dep', '1.0.0');

// At this point, TAD has been run through toJSON inside of TAA.
// TAD itself has no issues.
// in TAA, we want to store all the inrepo addons, at any level, in
// PROJ/lib, so move TAD from TAA and change its path in TAA.
addonA.pkg['ember-addon'].paths = ['../test-addon-dep'];
project.files.lib = project.files.lib || {};
project.files.lib['test-addon-dep'] = addonA.files.lib['test-addon-dep'];
delete addonA.files.lib;
},
});

project.addInRepoEngine('lazy-engine-a', '1.0.0', {
enableLazyLoading: true,
callback: (lazyEngineA) => {
lazyEngineA.addInRepoAddon('test-engine-dep', '1.0.0');

// Similar to above
lazyEngineA.pkg['ember-addon'].paths = ['../test-engine-dep'];
project.files.lib['test-engine-dep'] = lazyEngineA.files.lib['test-engine-dep'];
delete lazyEngineA.files.lib;
},
});

project.addInRepoEngine('lazy-engine-b', '1.0.0', {
enableLazyLoading: true,
callback: (lazyEngineB) => {
// These two addon definitions have already been moved to project, so just
// fix the ember-addon.paths and remove the files.lib entry.
lazyEngineB.pkg['ember-addon'].paths = ['../test-engine-dep', '../test-addon-dep'];
delete lazyEngineB.files.lib;
},
});

project.addInRepoEngine('regular-engine-c', '1.0.0', {
callback: (regularEngineC) => {
regularEngineC.pkg['ember-addon'].paths = ['../test-engine-dep'];
delete regularEngineC.files.lib;
},
});

Expand Down
12 changes: 6 additions & 6 deletions 12 tests/unit/broccoli/ember-app-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1001,17 +1001,17 @@ describe('EmberApp', function () {
fixturifyProject.dispose();
});

it('throws an error if an addon `include` is specified', function () {
it('throws an error if an addon `include` is specified', async function () {
fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
callback: (inRepoAddon) => {
inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
},
});

fixturifyProject.writeSync();
await fixturifyProject.write();

let projectWithBundleCaching = fixturifyProject.buildProjectModel();
let projectWithBundleCaching = await fixturifyProject.buildProjectModel();
projectWithBundleCaching.initializeAddons();
projectWithBundleCaching.addons.push(EMBER_SOURCE_ADDON);

Expand All @@ -1032,17 +1032,17 @@ describe('EmberApp', function () {
);
});

it('throws an error if an addon `exclude` is specified', function () {
it('throws an error if an addon `exclude` is specified', async function () {
fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
callback: (inRepoAddon) => {
inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
},
});

fixturifyProject.writeSync();
await fixturifyProject.write();

let projectWithBundleCaching = fixturifyProject.buildProjectModel();
let projectWithBundleCaching = await fixturifyProject.buildProjectModel();
projectWithBundleCaching.initializeAddons();
projectWithBundleCaching.addons.push(EMBER_SOURCE_ADDON);

Expand Down
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.