-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
217 additions
and
1 deletion.
There are no files selected for viewing
109 changes: 109 additions & 0 deletions
109
packages/build-config/src/-private/utils/detect-module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* eslint-disable no-console */ | ||
import path from 'path'; | ||
import fs from 'fs'; | ||
import { createRequire } from 'module'; | ||
const require = createRequire(import.meta.url); | ||
|
||
// TODO: lint this list against the actual package.json in the monorepo | ||
const DEFAULT_PACKAGES_FOR_EMBER_DATA = new Set([ | ||
'ember-data', | ||
'@ember-data/store', | ||
'@ember-data/model', | ||
'@ember-data/adapter', | ||
'@ember-data/serializer', | ||
'@ember-data/debug', | ||
'@ember-data/json-api', | ||
'@ember-data/graph', | ||
'@ember-data/request', | ||
'@ember-data/request-utils', | ||
'@ember-data/tracking', | ||
'@ember-data/legacy-compat', | ||
'@warp-drive/core-types', | ||
]); | ||
|
||
function moduleSurelyExists(modulePath) { | ||
try { | ||
fs.statSync(path.join(modulePath, 'package.json')); | ||
return true; | ||
} catch { | ||
return false; | ||
} | ||
} | ||
|
||
function log(str) { | ||
if (process.env.DEBUG_MODULE_RESOLUTION) { | ||
console.log(str); | ||
} | ||
} | ||
|
||
function bustCache(require) { | ||
Object.keys(require.cache).forEach((key) => { | ||
if (key.includes('ember-data') || key.includes('warp-drive')) { | ||
delete require.cache[key]; | ||
} | ||
}); | ||
} | ||
|
||
// do our best to detect being present | ||
// Note: when this is not enough, consuming apps may need | ||
// to "hoist" peer-deps or specify us as a direct dependency | ||
// in order to deal with peer-dep bugs in package managers | ||
export function detectModule(require, moduleName, baseDir, pkg) { | ||
const pkgName = pkg.name; | ||
if (moduleName === pkgName) { | ||
return true; | ||
} | ||
const isDeclaredDependency = pkg.dependencies?.[moduleName] || pkg.peerDependencies?.[moduleName]; | ||
|
||
if (!isDeclaredDependency) { | ||
return false; | ||
} | ||
|
||
log(`\n\n${pkgName} >> ${moduleName} in ${baseDir}`); | ||
|
||
const expectedLocation = path.join(baseDir, '../../', moduleName); | ||
if (moduleSurelyExists(expectedLocation)) { | ||
log(`\t✅ FOUND in Expected Location`); | ||
return true; | ||
} else { | ||
log(`\tMISSING in ${expectedLocation}`); | ||
} | ||
|
||
bustCache(require); | ||
|
||
try { | ||
// try default algorithm first | ||
require.resolve(moduleName); | ||
log('\t✅ FOUND via normal resolution'); | ||
return true; | ||
} catch { | ||
try { | ||
bustCache(require); | ||
// package managers have peer-deps bugs where another library | ||
// bringing a peer-dependency doesn't necessarily result in all | ||
// versions of the dependent getting the peer-dependency | ||
// | ||
// so we resolve from project as well as from our own location | ||
require.resolve(moduleName, { paths: [baseDir, process.cwd()] }); | ||
log('\t✅ FOUND via custom paths'); | ||
return true; | ||
} catch { | ||
if (!DEFAULT_PACKAGES_FOR_EMBER_DATA.has(moduleName)) { | ||
log('\t🙈 NOT FOUND'); | ||
return false; | ||
} | ||
try { | ||
bustCache(require); | ||
// ember-data brings all packages so if present we are present | ||
// | ||
// eslint-disable-next-line n/no-missing-require | ||
require.resolve('ember-data', { paths: [baseDir, path.join(baseDir, '../'), process.cwd()] }); | ||
log('\t✅ FOUND ember-data'); | ||
return true; | ||
} catch { | ||
log('\t🙈 NOT FOUND'); | ||
return false; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export function getEnv() { | ||
const { EMBER_ENV, IS_TESTING, EMBER_CLI_TEST_COMMAND, NODE_ENV } = process.env; | ||
const PRODUCTION = EMBER_ENV === 'production' || (!EMBER_ENV && NODE_ENV === 'production'); | ||
const DEBUG = !PRODUCTION; | ||
const TESTING = DEBUG || Boolean(EMBER_ENV === 'test' || IS_TESTING || EMBER_CLI_TEST_COMMAND); | ||
|
||
return { | ||
TESTING, | ||
PRODUCTION, | ||
DEBUG, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,103 @@ | ||
import { MacrosConfig } from '@embroider/macros/src/node'; | ||
import { detectModule } from './-private/utils/detect-module'; | ||
import { getEnv } from './-private/utils/get-env'; | ||
|
||
export type WarpDriveConfig = { | ||
debug?: Partial<InternalWarpDriveConfig['debug']>; | ||
polyfillUUID?: boolean; | ||
includeDataAdapterInProduction?: boolean; | ||
compatWith?: `${number}.${number}`; | ||
deprecations?: Partial<InternalWarpDriveConfig['deprecations']>; | ||
features?: Partial<InternalWarpDriveConfig['features']>; | ||
}; | ||
|
||
type InternalWarpDriveConfig = { | ||
debug: { | ||
LOG_PAYLOADS: boolean; | ||
LOG_OPERATIONS: boolean; | ||
LOG_MUTATIONS: boolean; | ||
LOG_REQUESTS: boolean; | ||
LOG_REQEST_STATUS: boolean; | ||
LOG_IDENTIFIERS: boolean; | ||
LOG_GRAPH: boolean; | ||
LOG_INSTANCE_CACHE: boolean; | ||
}; | ||
polyfillUUID: boolean; | ||
includeDataAdapter: boolean; | ||
compatWith: `${number}.${number}`; | ||
deprecations: { | ||
DEPRECATE_CATCH_ALL: boolean; | ||
DEPRECATE_COMPUTED_CHAINS: boolean; | ||
DEPRECATE_NON_STRICT_TYPES: boolean; | ||
DEPRECATE_NON_STRICT_ID: boolean; | ||
DEPRECATE_LEGACY_IMPORTS: boolean; | ||
DEPRECATE_NON_UNIQUE_PAYLOADS: boolean; | ||
DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE: boolean; | ||
DEPRECATE_MANY_ARRAY_DUPLICATES: boolean; | ||
}; | ||
features: {}; | ||
packages: { | ||
HAS_ADAPTER_PACKAGE: boolean; | ||
HAS_COMPAT_PACKAGE: boolean; | ||
HAS_DEBUG_PACKAGE: boolean; | ||
HAS_EMBER_DATA_PACKAGE: boolean; | ||
HAS_GRAPH_PACKAGE: boolean; | ||
HAS_JSON_API_PACKAGE: boolean; | ||
HAS_MODEL_PACKAGE: boolean; | ||
HAS_REQUEST_PACKAGE: boolean; | ||
HAS_SERIALIZER_PACKAGE: boolean; | ||
HAS_STORE_PACKAGE: boolean; | ||
HAS_TRACKING_PACKAGE: boolean; | ||
}; | ||
env: { | ||
TESTING: boolean; | ||
PRODUCTION: boolean; | ||
DEBUG: boolean; | ||
}; | ||
}; | ||
|
||
export type WarpDriveConfig = {}; | ||
export function setConfig(context: object, config: WarpDriveConfig) { | ||
const macros = MacrosConfig.for(context); | ||
|
||
if (macros.getGlobalConfig<InternalWarpDriveConfig>('WarpDrive')) { | ||
return; | ||
} | ||
|
||
const debugOptions: InternalWarpDriveConfig['debug'] = Object.assign( | ||
{ | ||
LOG_PAYLOADS: false, | ||
LOG_OPERATIONS: false, | ||
LOG_MUTATIONS: false, | ||
LOG_REQUESTS: false, | ||
LOG_REQEST_STATUS: false, | ||
LOG_IDENTIFIERS: false, | ||
LOG_GRAPH: false, | ||
LOG_INSTANCE_CACHE: false, | ||
}, | ||
config.debug | ||
); | ||
|
||
const HAS_DEBUG_PACKAGE = detectModule(require, '@ember-data/debug', __dirname, pkg); | ||
const HAS_EMBER_DATA_PACKAGE = detectModule(require, 'ember-data', __dirname, pkg); | ||
const env = getEnv(); | ||
|
||
const DEPRECATIONS = require('@ember-data/private-build-infra/src/deprecations')(hostOptions.compatWith || null); | ||
const FEATURES = require('@ember-data/private-build-infra/src/features')(isProd); | ||
|
||
const ALL_PACKAGES = requireModule('@ember-data/private-build-infra/virtual-packages/packages.js'); | ||
const MACRO_PACKAGE_FLAGS = Object.assign({}, ALL_PACKAGES.default); | ||
delete MACRO_PACKAGE_FLAGS['HAS_DEBUG_PACKAGE']; | ||
|
||
Object.keys(MACRO_PACKAGE_FLAGS).forEach((key) => { | ||
MACRO_PACKAGE_FLAGS[key] = detectModule(require, MACRO_PACKAGE_FLAGS[key], __dirname, pkg); | ||
}); | ||
|
||
const includeDataAdapterInProduction = | ||
typeof options.includeDataAdapterInProduction === 'boolean' | ||
? options.includeDataAdapterInProduction | ||
: HAS_META_PACKAGE; | ||
const includeDataAdapter = HAS_DEBUG_PACKAGE ? (isProd ? includeDataAdapterInProduction : true) : false; | ||
|
||
const finalizedConfig = config; | ||
macros.setGlobalConfig(import.meta.file, 'WarpDrive', finalizedConfig); | ||
} |