-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: treat fist package.json as project root (#1034)
closes #1012 BREAKING CHANGE: When invoking the CLI within a Nexus project, it will use the location of the package.json as its project root rather than blindly use the real CWD. Mostly this should just fix things but some users might have learnt the previous behaviour.
- Loading branch information
Jason Kuhrt
committed
Jun 12, 2020
1 parent
db6cce9
commit 19bb322
Showing
14 changed files
with
448 additions
and
427 deletions.
There are no files selected for viewing
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
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
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
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
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,118 @@ | ||
import * as Path from 'path' | ||
import { START_MODULE_NAME } from '../../runtime/start/start-module' | ||
import { ScanResult } from './layout' | ||
|
||
/** | ||
* The temporary ts build folder used when bundling is enabled | ||
* | ||
* Note: It **should not** be nested in a sub-folder. This might "corrupt" the relative paths of the bundle build. | ||
*/ | ||
export const TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = '.tmp_build' | ||
|
||
export const DEFAULT_BUILD_DIR_PATH_RELATIVE_TO_PROJECT_ROOT = '.nexus/build' | ||
|
||
export type BuildLayout = { | ||
startModuleOutPath: string | ||
startModuleInPath: string | ||
tsOutputDir: string | ||
bundleOutputDir: string | null | ||
/** | ||
* The final path to the start module. When bundling disbaled, same as `startModuleOutPath`. | ||
*/ | ||
startModule: string | ||
/** | ||
* The final output dir. If bundler is enabled then this is `bundleOutputDir`. | ||
* Otherwise it is `tsOutputDir`. | ||
* | ||
* When bundle case, this accounts for the bundle environment, which makes it | ||
* **DIFFERENT** than the source root. For example: | ||
* | ||
* ``` | ||
* <out_root>/node_modules/ | ||
* <out_root>/api/app.ts | ||
* <out_root>/api/index.ts | ||
* ``` | ||
*/ | ||
root: string | ||
/** | ||
* If bundler is enabled then the final output dir where the **source** is | ||
* located. Otherwise same as `tsOutputDir`. | ||
* | ||
* When bundle case, this is different than `root` because it tells you where | ||
* the source starts, not the build environment. | ||
* | ||
* For example, here `source_root` is `<out_root>/api` becuase the user has | ||
* set their root dir to `api`: | ||
* | ||
* ``` | ||
* <out_root>/node_modules/ | ||
* <out_root>/api/app.ts | ||
* <out_root>/api/index.ts | ||
* ``` | ||
* | ||
* But here, `source_root` is `<out_root>` because the user has set their root | ||
* dir to `.`: | ||
* | ||
* ``` | ||
* <out_source_root>/node_modules/ | ||
* <out_source_root>/app.ts | ||
* <out_source_root>/index.ts | ||
* ``` | ||
*/ | ||
sourceRoot: string | ||
} | ||
|
||
export function getBuildLayout( | ||
buildOutput: string | undefined, | ||
scanResult: ScanResult, | ||
asBundle?: boolean | ||
): BuildLayout { | ||
const tsOutputDir = getBuildOutputDir(scanResult.projectRoot, buildOutput, scanResult) | ||
const startModuleInPath = Path.join(scanResult.sourceRoot, START_MODULE_NAME + '.ts') | ||
const startModuleOutPath = Path.join(tsOutputDir, START_MODULE_NAME + '.js') | ||
|
||
if (!asBundle) { | ||
return { | ||
tsOutputDir, | ||
startModuleInPath, | ||
startModuleOutPath, | ||
bundleOutputDir: null, | ||
startModule: startModuleOutPath, | ||
root: tsOutputDir, | ||
sourceRoot: tsOutputDir, | ||
} | ||
} | ||
|
||
const tsBuildInfo = getBuildLayout(TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, scanResult, false) | ||
const relativeRootDir = Path.relative(scanResult.projectRoot, scanResult.tsConfig.content.options.rootDir!) | ||
const sourceRoot = Path.join(tsOutputDir, relativeRootDir) | ||
|
||
return { | ||
...tsBuildInfo, | ||
bundleOutputDir: tsOutputDir, | ||
root: tsOutputDir, | ||
startModule: Path.join(sourceRoot, START_MODULE_NAME + '.js'), | ||
sourceRoot, | ||
} | ||
} | ||
|
||
/** | ||
* Get the absolute build output dir | ||
* Precedence: User's input > tsconfig.json's outDir > default | ||
*/ | ||
function getBuildOutputDir( | ||
projectRoot: string, | ||
buildOutput: string | undefined, | ||
scanResult: ScanResult | ||
): string { | ||
const output = | ||
buildOutput ?? | ||
scanResult.tsConfig.content.options.outDir ?? | ||
DEFAULT_BUILD_DIR_PATH_RELATIVE_TO_PROJECT_ROOT | ||
|
||
if (Path.isAbsolute(output)) { | ||
return output | ||
} | ||
|
||
return Path.join(projectRoot, output) | ||
} |
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,32 @@ | ||
import { Either, right } from 'fp-ts/lib/Either' | ||
import { rootLogger } from '../nexus-logger' | ||
import { create, createFromData, Data, Layout } from './layout' | ||
|
||
const ENV_VAR_DATA_NAME = 'NEXUS_LAYOUT' | ||
|
||
const log = rootLogger.child('layout') | ||
|
||
export function saveDataForChildProcess(layout: Layout): { NEXUS_LAYOUT: string } { | ||
return { | ||
[ENV_VAR_DATA_NAME]: JSON.stringify(layout.data), | ||
} | ||
} | ||
|
||
/** | ||
* Load the layout data from a serialized version stored in the environment. If | ||
* it is not found then a warning will be logged and it will be recalculated. | ||
* For this reason the function is async however under normal circumstances it | ||
* should be as-if sync. | ||
*/ | ||
export async function loadDataFromParentProcess(): Promise<Either<Error, Layout>> { | ||
const savedData: undefined | string = process.env[ENV_VAR_DATA_NAME] | ||
if (!savedData) { | ||
log.trace( | ||
'WARNING an attempt to load saved layout data was made but no serialized data was found in the environment. This may represent a bug. Layout is being re-calculated as a fallback solution. This should result in the same layout data (if not, another probably bug, compounding confusion) but at least adds latentency to user experience.' | ||
) | ||
return create({}) // todo no build output... | ||
} else { | ||
// todo guard against corrupted env data | ||
return right(createFromData(JSON.parse(savedData) as Data)) | ||
} | ||
} |
Oops, something went wrong.