From 29686476029a24cfe866275ad1702199a470e387 Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Thu, 14 May 2020 16:18:15 +0200 Subject: [PATCH 1/6] feat: make runtime never import typescript --- src/cli/commands/create/app.ts | 18 +++++++++++------- src/lib/layout/layout.ts | 2 +- src/lib/plugin/lens.ts | 2 +- src/lib/plugin/utils.ts | 33 +-------------------------------- src/lib/plugin/worktime.ts | 33 +++++++++++++++++++++++++++++++++ src/lib/report.ts | 7 ++++--- src/runtime/app.ts | 2 +- src/runtime/schema/schema.ts | 4 ++-- src/runtime/testing.ts | 7 ++++--- 9 files changed, 58 insertions(+), 50 deletions(-) create mode 100644 src/lib/plugin/worktime.ts diff --git a/src/cli/commands/create/app.ts b/src/cli/commands/create/app.ts index 54bc213d8..b07596f40 100644 --- a/src/cli/commands/create/app.ts +++ b/src/cli/commands/create/app.ts @@ -9,7 +9,8 @@ import { tsconfigTemplate } from '../../../lib/layout/tsconfig' import { rootLogger } from '../../../lib/nexus-logger' import { ownPackage } from '../../../lib/own-package' import * as PackageManager from '../../../lib/package-manager' -import * as Plugin from '../../../lib/plugin' +import * as PluginRuntime from '../../../lib/plugin' +import * as PluginWorktime from '../../../lib/plugin/worktime' import * as proc from '../../../lib/process' import { createGitRepository, CWDProjectNameOrGenerate } from '../../../lib/utils' @@ -52,8 +53,8 @@ export async function runLocalHandOff(): Promise { const parentData = await loadDataFromParentProcess() const layout = await Layout.create() - const pluginM = await Plugin.getUsedPlugins(layout) - const plugins = Plugin.importAndLoadWorktimePlugins(pluginM, layout) + const pluginM = await PluginWorktime.getUsedPlugins(layout) + const plugins = PluginRuntime.importAndLoadWorktimePlugins(pluginM, layout) log.trace('plugins', { plugins }) // TODO select a template @@ -466,7 +467,9 @@ async function scaffoldBaseFiles(options: InternalConfig) { // Having at least one of these satisfies minimum Nexus requirements. // We put both to setup vscode debugger config with an entrypoint that is // unlikely to change. - fs.writeAsync(appEntrypointPath, stripIndent` + fs.writeAsync( + appEntrypointPath, + stripIndent` /** * This file is your server entrypoint. Don't worry about its emptyness, Nexus handles everything for you. * However, if you need to add settings, enable plugins, schema middleware etc, this is place to do it. @@ -507,7 +510,8 @@ async function scaffoldBaseFiles(options: InternalConfig) { // import { prisma } from 'nexus-plugin-prisma' // // use(prisma()) - `), + ` + ), fs.writeAsync(path.join(options.sourceRoot, Layout.schema.CONVENTIONAL_SCHEMA_FILE_NAME), ''), // An exhaustive .gitignore tailored for Node can be found here: // https://github.com/github/gitignore/blob/master/Node.gitignore @@ -580,8 +584,8 @@ async function scaffoldBaseFiles(options: InternalConfig) { const ENV_PARENT_DATA = 'NEXUS_CREATE_DATA' type ParentData = { - database?: Plugin.OnAfterBaseSetupLens['database'] - connectionURI?: Plugin.OnAfterBaseSetupLens['connectionURI'] + database?: PluginRuntime.OnAfterBaseSetupLens['database'] + connectionURI?: PluginRuntime.OnAfterBaseSetupLens['connectionURI'] } async function loadDataFromParentProcess(): Promise { diff --git a/src/lib/layout/layout.ts b/src/lib/layout/layout.ts index d72d2ae80..397ac576b 100644 --- a/src/lib/layout/layout.ts +++ b/src/lib/layout/layout.ts @@ -3,7 +3,7 @@ import { stripIndent } from 'common-tags' import * as FS from 'fs-jetpack' import * as Path from 'path' import { PackageJson } from 'type-fest' -import { ParsedCommandLine } from 'typescript' +import type { ParsedCommandLine } from 'typescript' import { findFile, findFileRecurisvelyUpwardSync } from '../../lib/fs' import { START_MODULE_NAME } from '../../runtime/start/start-module' import { rootLogger } from '../nexus-logger' diff --git a/src/lib/plugin/lens.ts b/src/lib/plugin/lens.ts index af36467a5..2de762c3a 100644 --- a/src/lib/plugin/lens.ts +++ b/src/lib/plugin/lens.ts @@ -2,7 +2,7 @@ import prompts from 'prompts' import * as Layout from '../layout' import { rootLogger } from '../nexus-logger' import * as Process from '../process' -import { isReflectionStage } from '../reflection' +import { isReflectionStage } from '../reflection/stage' import { Lens, RuntimeLens, WorktimeLens } from './types' const log = rootLogger.child('plugin') diff --git a/src/lib/plugin/utils.ts b/src/lib/plugin/utils.ts index 073823f01..1e0b68dca 100644 --- a/src/lib/plugin/utils.ts +++ b/src/lib/plugin/utils.ts @@ -1,12 +1,7 @@ import { stripIndent } from 'common-tags' import { PackageJson } from 'type-fest' -import * as Layout from '../layout' -import { rootLogger } from '../nexus-logger' import { fatal } from '../process' import { Manifest, Plugin } from './types' -import * as Reflection from '../reflection/reflect' - -const log = rootLogger.child('plugin') /** * Normalize a raw plugin manifest. @@ -42,30 +37,4 @@ export function entrypointToManifest(plugin: Plugin): Manifest { { plugin } ) } -} - -/** - * This gets all the plugins in use in the app. - * - * @remarks - * - * This is useful for the CLI to get worktime plugins. This will run the app in - * data mode, in this process. - */ -export async function getUsedPlugins(layout: Layout.Layout): Promise { - try { - const reflection = await Reflection.reflect(layout, { usedPlugins: true, onMainThread: true }) - - if (!reflection.success) { - throw reflection.error - } - - log.trace('got used plugins', { validPlugins: reflection.plugins }) - - return reflection.plugins - } catch (e) { - fatal('Failed to scan app for used plugins because there is a runtime error in the app', { - error: e, - }) - } -} +} \ No newline at end of file diff --git a/src/lib/plugin/worktime.ts b/src/lib/plugin/worktime.ts new file mode 100644 index 000000000..77b61176c --- /dev/null +++ b/src/lib/plugin/worktime.ts @@ -0,0 +1,33 @@ +import { Plugin } from './types' +import * as Layout from '../layout' +import * as Reflection from '../reflection/reflect' +import * as Process from '../process' +import { rootLogger } from '../nexus-logger' + +const log = rootLogger.child('plugin') + +/** + * This gets all the plugins in use in the app. + * + * @remarks + * + * This is useful for the CLI to get worktime plugins. This will run the app in + * data mode, in this process. + */ +export async function getUsedPlugins(layout: Layout.Layout): Promise { + try { + const reflection = await Reflection.reflect(layout, { usedPlugins: true, onMainThread: true }) + + if (!reflection.success) { + throw reflection.error + } + + log.trace('got used plugins', { validPlugins: reflection.plugins }) + + return reflection.plugins + } catch (e) { + Process.fatal('Failed to scan app for used plugins because there is a runtime error in the app', { + error: e, + }) + } +} diff --git a/src/lib/report.ts b/src/lib/report.ts index 1a960866e..668c26f21 100644 --- a/src/lib/report.ts +++ b/src/lib/report.ts @@ -5,7 +5,8 @@ import os from 'os' import { PackageJson } from 'type-fest' -import * as Plugin from '../lib/plugin' +import * as PluginWorktime from './plugin/worktime' +import * as PluginRuntime from './plugin' import { Layout } from './layout' interface Report { @@ -33,8 +34,8 @@ export async function getNexusReport(layout: Layout): Promise { return ent[0] !== 'nexus' && !ent[0].startsWith('nexus-plugin') }) ) - const pluginEntrypoints = await Plugin.getUsedPlugins(layout) - const pluginManifests = pluginEntrypoints.map(Plugin.entrypointToManifest) + const pluginEntrypoints = await PluginWorktime.getUsedPlugins(layout) + const pluginManifests = pluginEntrypoints.map(PluginRuntime.entrypointToManifest) return { node: process.version, diff --git a/src/runtime/app.ts b/src/runtime/app.ts index 0cb59746c..b1e0bd822 100644 --- a/src/runtime/app.ts +++ b/src/runtime/app.ts @@ -2,7 +2,7 @@ import * as Logger from '@nexus/logger' import type { MissingType, NexusGraphQLSchema } from '@nexus/schema/dist/core' import * as Plugin from '../lib/plugin' import { RuntimeContributions } from '../lib/plugin' -import * as Reflection from '../lib/reflection' +import * as Reflection from '../lib/reflection/stage' import { Index } from '../lib/utils' import * as Schema from './schema' import * as Server from './server' diff --git a/src/runtime/schema/schema.ts b/src/runtime/schema/schema.ts index d84e3125a..7c34b68b9 100644 --- a/src/runtime/schema/schema.ts +++ b/src/runtime/schema/schema.ts @@ -4,7 +4,7 @@ import { core } from '@nexus/schema' import type { CreateFieldResolverInfo, MissingType, NexusGraphQLSchema } from '@nexus/schema/dist/core' import { GraphQLFieldResolver, GraphQLResolveInfo } from 'graphql' import * as HTTP from 'http' -import * as Layout from '../../lib/layout' +import { emptyExceptionMessage } from '../../lib/layout/schema-modules' import { createNexusSchemaStateful, NexusSchemaStatefulBuilders } from '../../lib/nexus-schema-stateful' import { RuntimeContributions } from '../../lib/plugin' import { Index, MaybePromise } from '../../lib/utils' @@ -117,7 +117,7 @@ export function create(appState: AppState): SchemaInternal { checks() { NexusSchema.core.assertNoMissingTypes(appState.assembled!.schema, appState.assembled!.missingTypes) if (statefulNexusSchema.state.types.length === 0) { - log.warn(Layout.schema.emptyExceptionMessage()) + log.warn(emptyExceptionMessage()) } }, }, diff --git a/src/runtime/testing.ts b/src/runtime/testing.ts index b8ee18b85..baf0a8150 100644 --- a/src/runtime/testing.ts +++ b/src/runtime/testing.ts @@ -2,7 +2,8 @@ import getPort from 'get-port' import * as Lo from 'lodash' import { GraphQLClient } from '../lib/graphql-client' import * as Layout from '../lib/layout' -import * as Plugin from '../lib/plugin' +import * as PluginRuntime from '../lib/plugin' +import * as PluginWorktime from '../lib/plugin/worktime' import { PrivateApp } from './app' import { createDevAppRunner } from './start' @@ -77,7 +78,7 @@ export async function createTestContext(opts?: CreateTestContextOptions): Promis // todo figure out some caching system here, e.g. imagine jest --watch mode const layout = await Layout.create({ entrypointPath: opts?.entrypointPath }) - const pluginManifests = await Plugin.getUsedPlugins(layout) + const pluginManifests = await PluginWorktime.getUsedPlugins(layout) const randomPort = await getPort({ port: getPort.makeRange(4000, 6000) }) const app = require('../index').default as PrivateApp @@ -118,7 +119,7 @@ export async function createTestContext(opts?: CreateTestContextOptions): Promis }, } - const testContextContributions = Plugin.importAndLoadTesttimePlugins(pluginManifests) + const testContextContributions = PluginRuntime.importAndLoadTesttimePlugins(pluginManifests) for (const testContextContribution of testContextContributions) { Lo.merge(testContextCore, testContextContribution) From 257d03bd9ec09d62935d958856c962561ccd8745 Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Fri, 15 May 2020 17:00:17 +0200 Subject: [PATCH 2/6] feat(build): treeshake output --- package.json | 3 +- src/cli/commands/build.ts | 3 + src/lib/build/build.ts | 29 ++- src/lib/build/bundle.spec.ts | 63 ++++++ src/lib/build/bundle.ts | 165 ++++++++++++++ src/lib/build/deploy-target.ts | 4 +- src/lib/layout/index.spec.ts | 29 +-- src/lib/layout/layout.ts | 69 ++++-- src/lib/tsc.ts | 12 +- src/runtime/start/start-module.ts | 2 +- yarn.lock | 346 +++++++++++++++++++++++++++++- 11 files changed, 667 insertions(+), 58 deletions(-) create mode 100644 src/lib/build/bundle.spec.ts create mode 100644 src/lib/build/bundle.ts diff --git a/package.json b/package.json index 7351a27e9..6cb12c7c2 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@types/express": "^4.17.2", "@types/node-fetch": "^2.5.5", "@types/prompts": "^2.0.3", + "@zeit/node-file-trace": "^0.5.1", "anymatch": "^3.1.1", "arg": "^4.1.3", "chalk": "^4.0.0", @@ -41,7 +42,7 @@ "dotenv": "^8.2.0", "express": "^4.17.1", "fp-ts": "^2.5.4", - "fs-jetpack": "^2.2.3", + "fs-jetpack": "^2.4.0", "get-port": "^5.1.0", "graphql": "^14.5.8", "http-errors": "^1.7.3", diff --git a/src/cli/commands/build.ts b/src/cli/commands/build.ts index 503568cf5..6da32052e 100644 --- a/src/cli/commands/build.ts +++ b/src/cli/commands/build.ts @@ -14,6 +14,7 @@ const BUILD_ARGS = { '--stage': String, '--entrypoint': String, '-e': '--entrypoint', + '--no-bundle': Boolean, '--help': Boolean, '-h': '--help', } @@ -36,6 +37,7 @@ export class Build implements Command { output: args['--output'], stage: args['--stage'], entrypoint: args['--entrypoint'], + asBundle: args['--no-bundle'] !== true, }) } @@ -49,6 +51,7 @@ export class Build implements Command { -o, --output Relative path to output directory -e, --entrypoint Custom entrypoint to your app (default: app.ts) -d, --deployment Enable custom build for some deployment platforms (${formattedSupportedDeployTargets}) + --no-bundle Do not output build as a bundle -h, --help Show this help message ` } diff --git a/src/lib/build/build.ts b/src/lib/build/build.ts index fe4cd25a8..da6f86b1c 100644 --- a/src/lib/build/build.ts +++ b/src/lib/build/build.ts @@ -2,7 +2,7 @@ import { stripIndent } from 'common-tags' import * as FS from 'fs-jetpack' import * as Path from 'path' import * as Layout from '../../lib/layout' -import { compile, createTSProgram, deleteTSIncrementalFile } from '../../lib/tsc' +import { emitTSProgram, createTSProgram, deleteTSIncrementalFile } from '../../lib/tsc' import { createStartModuleContent, prepareStartModule, @@ -18,6 +18,7 @@ import { normalizeTarget, validateTarget, } from './deploy-target' +import { bundle } from './bundle' const log = rootLogger.child('build') @@ -26,6 +27,8 @@ interface BuildSettings { output?: string stage?: string entrypoint?: string + asBundle: boolean, + cwd?: string } export async function buildNexusApp(settings: BuildSettings) { @@ -36,8 +39,10 @@ export async function buildNexusApp(settings: BuildSettings) { const buildOutput = settings.output ?? computeBuildOutputFromTarget(deploymentTarget) ?? undefined const layout = await Layout.create({ - buildOutput, + buildOutputDir: buildOutput, + asBundle: settings.asBundle, entrypointPath: settings.entrypoint, + cwd: settings.cwd }) /** @@ -85,7 +90,7 @@ export async function buildNexusApp(settings: BuildSettings) { // incremental builder type of program so that the cache from the previous // run of TypeScript should make re-building up this one cheap. - compile(tsBuilder, layout, { removePreviousBuild: false }) + emitTSProgram(tsBuilder, layout, { removePreviousBuild: false }) const runtimePluginManifests = plugins.map(Plugin.entrypointToManifest).filter((pm) => pm.runtime) @@ -101,12 +106,22 @@ export async function buildNexusApp(settings: BuildSettings) { }) ), }) + + if (layout.build.bundleOutputDir) { + await bundle({ + base: layout.projectRoot, + entrypoint: layout.build.startModuleOutPath, + outputDir: layout.build.bundleOutputDir, + plugins: pluginReflection.plugins, + }) + await FS.removeAsync(layout.build.outputDir) + } } const buildOutputLog = layout.tsConfig.content.options.noEmit === true ? 'no emit' - : Path.relative(layout.projectRoot, layout.buildOutput) + : Path.relative(layout.projectRoot, layout.build.bundleOutputDir ?? layout.build.outputDir) log.info('success', { buildOutput: buildOutputLog, @@ -134,9 +149,9 @@ export async function writeStartModule({ // module. For example we can alias it, or, we can rename it e.g. // `index_original.js`. For now we just error out and ask the user to not name // their module index.ts. - if (FS.exists(layout.startModuleInPath)) { + if (FS.exists(layout.build.startModuleInPath)) { fatal(stripIndent` - Found ${layout.startModuleInPath} + Found ${layout.build.startModuleInPath} Nexus reserves the source root module name ${START_MODULE_NAME}.js for its own use. Please change your app layout to not have this module. This is a temporary limitation that we intend to remove in the future. @@ -145,5 +160,5 @@ export async function writeStartModule({ } log.trace('Writing start module to disk') - await FS.writeAsync(layout.startModuleOutPath, startModule) + await FS.writeAsync(layout.build.startModuleOutPath, startModule) } diff --git a/src/lib/build/bundle.spec.ts b/src/lib/build/bundle.spec.ts new file mode 100644 index 000000000..2728e253d --- /dev/null +++ b/src/lib/build/bundle.spec.ts @@ -0,0 +1,63 @@ +import { NodeFileTraceReasons } from '@zeit/node-file-trace' +import * as Path from 'path' +import { traceFiles } from './bundle' + +const base = Path.dirname(require.resolve('../../../package.json')) +const entrypoint = Path.join(base, 'dist', 'index.js') + +it('should not bundle typescript', async () => { + const { reasons } = await traceFiles({ + base, + entrypoint, + plugins: [], + }) + const isTypescriptBundled = isModuleBundled('node_modules/typescript/lib/typescript.js', reasons) + + expect(isTypescriptBundled).toMatchInlineSnapshot(`false`) +}) + +it('should not bundle any of cli', async () => { + const { files } = await traceFiles({ + base, + entrypoint, + plugins: [], + }) + + const cliFiles = Array.from(files.keys()).filter((f) => f.includes('dist/cli')) + + expect(cliFiles).toMatchInlineSnapshot(`Array []`) +}) + +function walkParents(parents: string[], reasons: NodeFileTraceReasons, path: Array): void { + if (parents.length === 0) { + return + } + + if (parents.length === 1) { + path.push(parents[0]) + } else { + path.push(parents) + } + + parents.forEach((p) => { + const module = reasons[p] + walkParents(module.parents, reasons, path) + }) +} + +export function isModuleBundled( + moduleId: string, + reasons: NodeFileTraceReasons +): false | { reason: Array } { + const module = reasons[moduleId] + + if (!module) { + return false + } + + let path: (string | string[])[] = [moduleId] + + walkParents(module.parents, reasons, path) + + return { reason: path.reverse() } +} diff --git a/src/lib/build/bundle.ts b/src/lib/build/bundle.ts new file mode 100644 index 000000000..68025a61b --- /dev/null +++ b/src/lib/build/bundle.ts @@ -0,0 +1,165 @@ +import * as fs from 'fs' +import * as fsJetpack from 'fs-jetpack' +import fileTrace from '@zeit/node-file-trace' +import * as path from 'path' +import { Plugin } from '../plugin' +import { rootLogger } from '../nexus-logger' +import { fatal } from '../process' + +const log = rootLogger.child('cli').child('build').child('bundle') + +type Entry = { source: string | Buffer; mode?: number } | null +type SourceCache = Map + +interface BundleOptions { + base: string + entrypoint: string + outputDir: string + plugins: Plugin[] +} + +export async function bundle(opts: BundleOptions): Promise { + log.trace('starting bundle') + + // delete previous bundle before tracing files + fsJetpack.remove(opts.outputDir) + + const { files } = await traceFiles({ + base: opts.base, + entrypoint: opts.entrypoint, + plugins: opts.plugins, + }) + + await writeToFS({ + files, + outputDir: opts.outputDir, + base: opts.base, + }) + + log.trace('done bundling') +} + +export async function traceFiles(opts: Omit) { + const sourceCache = new Map() + const worktimeTesttimePluginPaths = getWorktimeAndTesttimePluginPaths(opts.base, opts.plugins) + + const { fileList, reasons } = await fileTrace([opts.entrypoint], { + ts: true, + mixedModules: true, + base: opts.base, + /** + * - We ignore `prettier` because `@nexus/schema` requires it as a optional peer dependency + * - We ignore `@prisma/client/scripts` because `nexus-prisma` causes node-file-trace to include these scripts which causes ncc to be traces as well + */ + ignore: ['node_modules/prettier/index.js', 'node_modules/@prisma/client/scripts/**/*'], + readFile(fsPath: string): Buffer | string | null { + const relPath = path.relative(opts.base, fsPath) + const cached = sourceCache.get(relPath) + if (cached) return cached.toString() + // null represents a not found + if (cached === null) return null + try { + /** + * Stub the worktime and testtime plugins so that they can keep being resolved + * in the plugin entrypoints but don't bring any of their dependencies to the bundle + */ + if (worktimeTesttimePluginPaths.includes(relPath)) { + console.log({ stubbing: relPath.toString(), fsPath }) + sourceCache.set(relPath, { source: '' }) + return '' + } + const source: string | Buffer = fs.readFileSync(fsPath) + const { mode } = fs.lstatSync(fsPath) + sourceCache.set(relPath, { source, mode }) + return source.toString() + } catch (e) { + if (e.code === 'ENOENT' || e.code === 'EISDIR') { + sourceCache.set(relPath, null) + return null + } + throw e + } + }, + }) + + console.log(fileList) + + /** + * Remove files that were read but not added to the fileList by node-file-trace + */ + for (const relPath of sourceCache.keys()) { + if (reasons[relPath] === undefined || reasons[relPath].ignored === true) { + sourceCache.delete(relPath) + } + } + /** + * Add files that were added to the file list but not read + */ + for (const relPath of fileList) { + if (!sourceCache.has(relPath)) { + const absPath = path.resolve(opts.base, relPath) + try { + const source = fs.readFileSync(absPath) + const { mode } = fs.lstatSync(absPath) + sourceCache.set(relPath, { source, mode }) + } catch (e) { + if (e.code === 'ENOENT' || e.code === 'EISDIR') { + sourceCache.set(relPath, null) + } else { + fatal('error', { error: e }) + } + } + } + } + if (process.env.NEXUS_FILE_TRACE_DEBUG) { + fs.writeFileSync('file-trace.json', JSON.stringify(fileList, null, 2)) + fs.writeFileSync('file-trace-reasons.json', JSON.stringify(reasons, null, 2)) + fs.writeFileSync('file-trace-cache.json', JSON.stringify(Array.from(sourceCache.keys()).sort(), null, 2)) + } + + log.trace('gathered files for bundle') + + return { + files: sourceCache, + reasons, + } +} + +/** + * Write gathered files by node-file-trace to the file system + */ +async function writeToFS(opts: { files: SourceCache; outputDir: string; base: string }): Promise { + const writePromises = [] + + for (const [relPath, entry] of opts.files.entries()) { + if (entry === null) { + continue + } + + const to = path.resolve(opts.outputDir, relPath) + + const promise = fsJetpack.write(to, entry.source, entry.mode ? { mode: entry.mode } : {}) + writePromises.push(promise) + } + + await Promise.all(writePromises) +} + +/** + * Gathers all the worktime & testtime plugin module relative paths + */ +function getWorktimeAndTesttimePluginPaths(base: string, plugins: Plugin[]) { + const paths: string[] = [] + + for (const p of plugins) { + if (p.worktime) { + paths.push(path.relative(base, p.worktime.module)) + } + + if (p.testtime) { + paths.push(path.relative(base, p.testtime.module)) + } + } + + return paths +} diff --git a/src/lib/build/deploy-target.ts b/src/lib/build/deploy-target.ts index 6a851c862..67de384dd 100644 --- a/src/lib/build/deploy-target.ts +++ b/src/lib/build/deploy-target.ts @@ -75,7 +75,7 @@ interface NowJson { */ function validateNow(layout: Layout): ValidatorResult { const maybeNowJson = findFileRecurisvelyUpwardSync('now.json', { cwd: layout.projectRoot }) - const startModulePath = `${layout.buildOutput}/${START_MODULE_NAME}.js` + const startModulePath = `${layout.build.outputDir}/${START_MODULE_NAME}.js` let isValid = true // Make sure there's a now.json file @@ -191,7 +191,7 @@ function validateHeroku(layout: Layout): ValidatorResult { isValid = false } - const relativeBuildOutput = Path.relative(layout.packageJson.dir, layout.buildOutput) + const relativeBuildOutput = Path.relative(layout.packageJson.dir, layout.build.outputDir) // Make sure there's a start script if (!pcfg.scripts?.start) { diff --git a/src/lib/layout/index.spec.ts b/src/lib/layout/index.spec.ts index 87507273d..bac1b833c 100644 --- a/src/lib/layout/index.spec.ts +++ b/src/lib/layout/index.spec.ts @@ -57,7 +57,8 @@ const layoutContext = TestContext.create((input: TestContext.TmpDirContribution) const data = await Layout.create({ cwd: input.tmpDir, entrypointPath: opts?.entrypointPath, - buildOutput: opts?.buildOutput, + buildOutputDir: opts?.buildOutput, + asBundle: false, }) mockedStdoutBuffer = mockedStdoutBuffer.split(input.tmpDir).join('__DYNAMIC__') return repalceInObject(input.tmpDir, '__DYNAMIC__', data.data) @@ -365,14 +366,14 @@ describe('build output', () => { const result = await ctx.scan() expect({ - buildOutput: result.buildOutput, - startModuleInPath: result.startModuleInPath, - startModuleOutPath: result.startModuleOutPath, + outputDir: result.build.outputDir, + startModuleInPath: result.build.startModuleInPath, + startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "buildOutput": "__DYNAMIC__/node_modules/.build", + "outputDir": "__DYNAMIC__/.nexus/build", "startModuleInPath": "__DYNAMIC__/index.ts", - "startModuleOutPath": "__DYNAMIC__/node_modules/.build/index.js", + "startModuleOutPath": "__DYNAMIC__/.nexus/build/index.js", } `) }) @@ -391,12 +392,12 @@ describe('build output', () => { const result = await ctx.scan() expect({ - buildOutput: result.buildOutput, - startModuleInPath: result.startModuleInPath, - startModuleOutPath: result.startModuleOutPath, + outputDir: result.build.outputDir, + startModuleInPath: result.build.startModuleInPath, + startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "buildOutput": "__DYNAMIC__/dist", + "outputDir": "__DYNAMIC__/dist", "startModuleInPath": "__DYNAMIC__/index.ts", "startModuleOutPath": "__DYNAMIC__/dist/index.js", } @@ -416,12 +417,12 @@ describe('build output', () => { const result = await ctx.scan({ buildOutput: 'custom-output' }) expect({ - buildOutput: result.buildOutput, - startModuleInPath: result.startModuleInPath, - startModuleOutPath: result.startModuleOutPath, + outputDir: result.build.outputDir, + startModuleInPath: result.build.startModuleInPath, + startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "buildOutput": "__DYNAMIC__/custom-output", + "outputDir": "__DYNAMIC__/custom-output", "startModuleInPath": "__DYNAMIC__/index.ts", "startModuleOutPath": "__DYNAMIC__/custom-output/index.js", } diff --git a/src/lib/layout/layout.ts b/src/lib/layout/layout.ts index 397ac576b..b04b3f324 100644 --- a/src/lib/layout/layout.ts +++ b/src/lib/layout/layout.ts @@ -12,7 +12,8 @@ import { fatal } from '../process' import * as Schema from './schema-modules' import { readOrScaffoldTsconfig } from './tsconfig' -export const DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = 'node_modules/.build' +export const DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = '.nexus/build' +export const DEFAULT_TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = 'build' const log = rootLogger.child('layout') @@ -69,15 +70,18 @@ export type ScanResult = { // } } +type OutputInfo = { + startModuleOutPath: string + startModuleInPath: string + outputDir: string + bundleOutputDir: string | null +} + /** * The combination of manual datums the user can specify about the layout plus * the dynamic scan results. */ -export type Data = ScanResult & { - buildOutput: string - startModuleOutPath: string - startModuleInPath: string -} +export type Data = ScanResult & { build: OutputInfo } /** * Layout represents the important edges of the project to support things like @@ -100,9 +104,19 @@ interface Options { /** * The place to output the build, relative to project root. */ - buildOutput?: string + buildOutputDir?: string + /** + * Path to the nexus entrypoint. Can be absolute or relative. + */ entrypointPath?: string + /** + * Directory in which the layout should be performed + */ cwd?: string + /** + * Whether the build should be outputted as a bundle + */ + asBundle?: boolean } const optionDefaults = { @@ -118,18 +132,13 @@ export async function create(options?: Options): Promise { // TODO lodash merge defaults or something const scanResult = await scan({ cwd, entrypointPath: normalizedEntrypoint }) - const buildOutput = getBuildOutput(options?.buildOutput, scanResult) - const outputInfo = { - buildOutput, - startModuleInPath: Path.join(scanResult.sourceRoot, START_MODULE_NAME + '.ts'), - startModuleOutPath: Path.join(buildOutput, START_MODULE_NAME + '.js'), - } + const buildInfo = getBuildInfo(options?.buildOutputDir, scanResult, options?.asBundle) - log.trace('additional layout data', { data: outputInfo }) + log.trace('layout build info', { data: buildInfo }) const layout = createFromData({ ...scanResult, - ...outputInfo, + build: buildInfo, }) /** @@ -410,3 +419,33 @@ function getBuildOutput(buildOutput: string | undefined, scanResult: ScanResult) return Path.join(scanResult.projectRoot, output) } + +function getBuildInfo( + buildOutput: string | undefined, + scanResult: ScanResult, + asBundle?: boolean +): OutputInfo { + const outputDir = getBuildOutput(buildOutput, scanResult) + const startModuleInPath = Path.join(scanResult.sourceRoot, START_MODULE_NAME + '.ts') + const startModuleOutPath = Path.join(outputDir, START_MODULE_NAME + '.js') + + if (!asBundle) { + return { + outputDir, + startModuleInPath, + startModuleOutPath, + bundleOutputDir: null, + } + } + + const tsBuildInfo = getBuildInfo( + DEFAULT_TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, + scanResult, + false + ) + + return { + ...tsBuildInfo, + bundleOutputDir: outputDir, + } +} diff --git a/src/lib/tsc.ts b/src/lib/tsc.ts index 9e9839556..ba49f84a3 100644 --- a/src/lib/tsc.ts +++ b/src/lib/tsc.ts @@ -33,7 +33,7 @@ export function createTSProgram( options: { ...compilerCacheOptions, ...layout.tsConfig.content.options, - outDir: layout.buildOutput, + outDir: layout.build.outputDir, }, }) @@ -76,17 +76,17 @@ interface CompileOptions { /** * compile a program. Throws an error if the program does not type check. */ -export function compile( +export function emitTSProgram( builder: ts.EmitAndSemanticDiagnosticsBuilderProgram, layout: Layout, options?: CompileOptions ): void { if (options?.removePreviousBuild === true) { log.trace('remove previous build folder if present') - fs.remove(layout.buildOutput) + fs.remove(layout.build.outputDir) } - log.trace('emit transpiled modules') + log.trace('emit transpiled modules', { dest: layout.build.outputDir }) const emitResult = builder.emit() log.trace('done', { filesEmitted: emitResult.emittedFiles?.length ?? 0 }) @@ -142,9 +142,7 @@ function createTSError(diagnostics: ReadonlyArray) { * * This is strictly about transpilation, no type checking is done. */ -export function registerTypeScriptTranspile( - compilerOptions?: ts.CompilerOptions, -) { +export function registerTypeScriptTranspile(compilerOptions?: ts.CompilerOptions) { addHook( (source, fileName) => { const transpiled = ts.transpileModule(source, { diff --git a/src/runtime/start/start-module.ts b/src/runtime/start/start-module.ts index d90a63421..2f83329c9 100644 --- a/src/runtime/start/start-module.ts +++ b/src/runtime/start/start-module.ts @@ -105,7 +105,7 @@ export function createStartModuleContent(config: StartModuleConfig): string { require('${ config.absoluteModuleImports ? config.layout.packageJson.path - : Path.relative(config.layout.buildOutput, config.layout.packageJson.path) + : Path.relative(config.layout.build.outputDir, config.layout.packageJson.path) }') ` } diff --git a/yarn.lock b/yarn.lock index 84b199524..353e83c46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -975,11 +975,38 @@ dependencies: "@types/yargs-parser" "*" +"@zeit/node-file-trace@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@zeit/node-file-trace/-/node-file-trace-0.5.1.tgz#3badd7516fd91f78860e698edbb41107dfc841f4" + integrity sha512-BlZDokGcOIKu5R2Qs3bZGjXRptbKqBYQ7iBnSDjJhJqP4d4hbRPPBQQnrihLOVNsauX845I+CUgRY+OOpd2jFA== + dependencies: + acorn "^6.1.1" + acorn-bigint "^0.3.1" + acorn-class-fields "^0.3.1" + acorn-dynamic-import "^4.0.0" + acorn-export-ns-from "^0.1.0" + acorn-import-meta "^1.0.0" + acorn-private-methods "^0.3.0" + bindings "^1.4.0" + estree-walker "^0.6.0" + glob "^7.1.3" + graceful-fs "^4.1.15" + micromatch "^4.0.2" + mkdirp "^0.5.1" + node-pre-gyp "^0.13.0" + resolve-from "^5.0.0" + rollup-pluginutils "^2.8.2" + abab@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -988,6 +1015,28 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +acorn-bigint@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/acorn-bigint/-/acorn-bigint-0.3.1.tgz#edb40a414dcaf5a09c2933db6bed79454b3ff46a" + integrity sha512-WT9LheDC4/d/sD/jgC6L5UMq4U9X3KNMy0JrXp/MdJL83ZqcuPQuMkj50beOX0dMub8IoZUYycfN7bIVZuU5zg== + +acorn-class-fields@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/acorn-class-fields/-/acorn-class-fields-0.3.2.tgz#70b832bb0c1419069155cef61a4aaef8e6099f7d" + integrity sha512-wyqXoqzXSOF42uxHo40TMuC/KfloI66AZz6S1TeK8D2HjKzI7Boq1mSH2pB5RwKEJWgHqnewGpRFRZwR0qQCyQ== + dependencies: + acorn-private-class-elements "^0.2.5" + +acorn-dynamic-import@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" + integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== + +acorn-export-ns-from@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/acorn-export-ns-from/-/acorn-export-ns-from-0.1.0.tgz#192687869bba3bcb2ef1a1ba196486ea7e100e5c" + integrity sha512-QDQJBe2DfxNBIMxs+19XY2i/XXilJn+kPgX30HWNYK4IXoNj3ACNSWPU7szL0SzqjFyOG4zoZxG9P7JfNw5g7A== + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -996,11 +1045,33 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" +acorn-import-meta@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/acorn-import-meta/-/acorn-import-meta-1.1.0.tgz#c384423462ee7d4721d4de83231021a36cb09def" + integrity sha512-pshgiVR5mhpjFVdizKTN+kAGRqjJFUOEB3TvpQ6kiAutb1lvHrIVVcGoe5xzMpJkVNifCeymMG7/tsDkWn8CdQ== + +acorn-private-class-elements@^0.2.4, acorn-private-class-elements@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/acorn-private-class-elements/-/acorn-private-class-elements-0.2.5.tgz#5082582395d2dabbbb1ddf6397244fdaa61cded6" + integrity sha512-3eApRrJmPjaxWB3XidP8YMeVq9pcswPFE0KsSWVuhceCU68ZS8fkcf0fTXGhCmnNd7n48NWWV27EKMFPeCoJLg== + +acorn-private-methods@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/acorn-private-methods/-/acorn-private-methods-0.3.1.tgz#b9347ea32321c0df6dcdd2bd11e23bcd312bcb69" + integrity sha512-IV5XZInFQaQK5ucjJy/HAk2UYvt+Buax00evzwo8NSuo8zhOBhW5v6VOjAljYUhAzQ/Hosi+Kaz6xJmvPiSM4Q== + dependencies: + acorn-private-class-elements "^0.2.4" + acorn-walk@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e" integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ== +acorn@^6.1.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== + acorn@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" @@ -1093,6 +1164,19 @@ anymatch@^3.0.3, anymatch@^3.1.1, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + arg@^4.1.0, arg@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -1305,7 +1389,7 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== -bindings@^1.5.0: +bindings@^1.4.0, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -1560,6 +1644,11 @@ chokidar@^3.3.0: optionalDependencies: fsevents "~2.1.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1634,6 +1723,11 @@ code-block-writer@^10.1.0: resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-10.1.0.tgz#54fc410ebef2af836d9c2314ac40af7d7b37eee9" integrity sha512-RG9hpXtWFeUWhuUav1YuP/vGcyncW+t90yJLk9fNZs1De2OuHTHKAKThVCokt29PYq5RoJ0QSZaIZ+rvPO23hA== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + collapse-white-space@^1.0.2: version "1.0.6" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" @@ -1725,6 +1819,11 @@ connect@^3.6.0: parseurl "~1.3.3" utils-merge "1.0.1" +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -1856,6 +1955,13 @@ debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" +debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -1944,6 +2050,11 @@ delegate@^3.1.2: resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1959,6 +2070,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -2222,6 +2338,11 @@ estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estree-walker@^0.6.0, estree-walker@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" + integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2577,6 +2698,21 @@ fs-jetpack@^2.2.3: minimatch "^3.0.2" rimraf "^2.6.3" +fs-jetpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-2.4.0.tgz#6080c4ab464a019d37a404baeb47f32af8835026" + integrity sha512-S/o9Dd7K9A7gicVU32eT8G0kHcmSu0rCVdP79P0MWInKFb8XpTc8Syhoo66k9no+HDshtlh4pUJTws8X+8fdFQ== + dependencies: + minimatch "^3.0.2" + rimraf "^2.6.3" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2595,6 +2731,20 @@ fsevents@^2.1.2, fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + gensync@^1.0.0-beta.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" @@ -2736,7 +2886,7 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== -graceful-fs@^4.2.4: +graceful-fs@^4.1.15, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -2783,6 +2933,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2889,13 +3044,20 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + ignore@^5.1.1, ignore@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" @@ -3082,6 +3244,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -4130,6 +4299,21 @@ minimisted@^2.0.0: dependencies: minimist "^1.2.0" +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -4143,6 +4327,13 @@ mkdirp@1.x: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4196,6 +4387,15 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +needle@^2.2.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a" + integrity sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -4238,6 +4438,22 @@ node-notifier@^7.0.0: uuid "^7.0.3" which "^2.0.2" +node-pre-gyp@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" + integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + node-pty@0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.9.0.tgz#8f9bcc0d1c5b970a3184ffd533d862c7eb6590a6" @@ -4245,6 +4461,14 @@ node-pty@0.9.0: dependencies: nan "^2.14.0" +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -4272,6 +4496,27 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== +npm-bundled@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -4286,6 +4531,21 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -4296,6 +4556,11 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -4369,6 +4634,11 @@ optionator@^0.8.1: resolved "https://registry.yarnpkg.com/opts/-/opts-1.2.7.tgz#4de4721d592c96901dae623a438c988e9ea7779f" integrity sha512-hwZhzGGG/GQ7igxAVFOEun2N4fWul31qE9nfBdCnZGQCB5+L7tN9xZ+94B4aUpLOJx/of3zZs5XsuubayQYQjA== +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + os-name@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" @@ -4377,6 +4647,19 @@ os-name@^3.1.0: macos-release "^2.2.0" windows-release "^3.1.0" +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -4707,7 +4990,7 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.8: +rc@^1.2.7, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -4741,7 +5024,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.2: +readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -4955,7 +5238,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.6.3: +rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4969,6 +5252,13 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" +rollup-pluginutils@^2.8.2: + version "2.8.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" + integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== + dependencies: + estree-walker "^0.6.1" + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -5023,6 +5313,11 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + saxes@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" @@ -5042,7 +5337,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -5093,7 +5388,7 @@ serve-static@1.14.1, serve-static@^1.12.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -5354,7 +5649,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^2.1.1: +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5394,7 +5698,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0: +strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= @@ -5488,6 +5792,19 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tar@^4: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -6060,6 +6377,13 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + widest-line@^2.0.0, widest-line@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" @@ -6177,7 +6501,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.2: +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From ad67addd8c76adcc7649f94f6b80cccd5a6a650d Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Fri, 15 May 2020 17:16:53 +0200 Subject: [PATCH 3/6] fix tests --- src/cli/commands/create/app.ts | 2 +- src/lib/build/bundle.spec.ts | 2 +- src/lib/build/bundle.ts | 3 --- src/lib/layout/index.spec.ts | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cli/commands/create/app.ts b/src/cli/commands/create/app.ts index b07596f40..cc415d24d 100644 --- a/src/cli/commands/create/app.ts +++ b/src/cli/commands/create/app.ts @@ -536,7 +536,7 @@ async function scaffoldBaseFiles(options: InternalConfig) { format: "npx prettier --write './**/*.{ts,md}'", dev: 'nexus dev', build: 'nexus build', - start: 'node node_modules/.build', + start: 'node .nexus/build', }, prettier: { semi: false, diff --git a/src/lib/build/bundle.spec.ts b/src/lib/build/bundle.spec.ts index 2728e253d..7bc82f5ee 100644 --- a/src/lib/build/bundle.spec.ts +++ b/src/lib/build/bundle.spec.ts @@ -16,7 +16,7 @@ it('should not bundle typescript', async () => { expect(isTypescriptBundled).toMatchInlineSnapshot(`false`) }) -it('should not bundle any of cli', async () => { +it('should not bundle any of the cli', async () => { const { files } = await traceFiles({ base, entrypoint, diff --git a/src/lib/build/bundle.ts b/src/lib/build/bundle.ts index 68025a61b..a055f429d 100644 --- a/src/lib/build/bundle.ts +++ b/src/lib/build/bundle.ts @@ -64,7 +64,6 @@ export async function traceFiles(opts: Omit) { * in the plugin entrypoints but don't bring any of their dependencies to the bundle */ if (worktimeTesttimePluginPaths.includes(relPath)) { - console.log({ stubbing: relPath.toString(), fsPath }) sourceCache.set(relPath, { source: '' }) return '' } @@ -82,8 +81,6 @@ export async function traceFiles(opts: Omit) { }, }) - console.log(fileList) - /** * Remove files that were read but not added to the fileList by node-file-trace */ diff --git a/src/lib/layout/index.spec.ts b/src/lib/layout/index.spec.ts index bac1b833c..4262cb616 100644 --- a/src/lib/layout/index.spec.ts +++ b/src/lib/layout/index.spec.ts @@ -361,7 +361,7 @@ it('does not take custom entrypoint as schema module if its inside a graphql/ fo }) describe('build output', () => { - it(`defaults to node_modules/.build`, async () => { + it(`defaults to .nexus/build`, async () => { await ctx.setup({ ...fsTsConfig, 'graphql.ts': '' }) const result = await ctx.scan() From 760fa9bae71fb16840402a576a705703f32d910f Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Fri, 15 May 2020 17:17:02 +0200 Subject: [PATCH 4/6] update docs --- docs/architecture.md | 2 +- docs/getting-started/migrate-from-nexus-schema.md | 2 +- docs/guides/project-layout.md | 2 +- docs/references/recipes.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 14ae23a21..984f550df 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -25,7 +25,7 @@ todo 1. A new TypeScript instance is created so that the types generated in the previous step are picked up by the checker. This should be faster because it reuses the TypeScript cache created in the previous step. 1. The app is type checked 1. The app is transpiled -1. The app is emitted into `node_modules/.build`. This convention keeps derived files in a well known generally ignored location. +1. The app is emitted into `.nexus/build`. This convention keeps derived files in a well known generally ignored location. 1. A production-oriented start module is generated differing in the following ways: - paths are relative - typescript not hooked into module extensions diff --git a/docs/getting-started/migrate-from-nexus-schema.md b/docs/getting-started/migrate-from-nexus-schema.md index c2009af07..f5c8b0a9b 100644 --- a/docs/getting-started/migrate-from-nexus-schema.md +++ b/docs/getting-started/migrate-from-nexus-schema.md @@ -108,7 +108,7 @@ You should only be working with the `nexus` CLI. Below shows the example scripts - "dev": "ts-node-dev --no-notify --respawn --transpileOnly src/server", + "dev": "nexus dev", + "build": "nexus build", -+ "start": "node node_modules/.build" ++ "start": "node .nexus/build" }, ``` diff --git a/docs/guides/project-layout.md b/docs/guides/project-layout.md index 54f464b10..159141786 100644 --- a/docs/guides/project-layout.md +++ b/docs/guides/project-layout.md @@ -21,7 +21,7 @@ - Out Root is the place where the transpiled TypeScript (to JavaScript) modules will be emitted to. The folder structure mimicks that of the source root. - Out Root is defined by setting `compilerOptions.outDir`. -- If you do not specify it then Nexus will default to `node_modules/.build`. Unlike with `rootDir` Nexus will not scaffold the default into your `tsconfig.json` because its presence has no impact upon VSCode. +- If you do not specify it then Nexus will default to `.nexus/build`. Unlike with `rootDir` Nexus will not scaffold the default into your `tsconfig.json` because its presence has no impact upon VSCode. - You can override its value interactively with `nexus build --out`. ##### Check-Only Builds diff --git a/docs/references/recipes.md b/docs/references/recipes.md index b38829b93..94255a6f3 100644 --- a/docs/references/recipes.md +++ b/docs/references/recipes.md @@ -137,7 +137,7 @@ If you don't want to use a docker, here are some links to alternative approaches ```diff +++ package.json - + "start": "node node_modules/.build" + + "start": "node .nexus/build" ``` 3. In many cases this will be enough. Many deployment platforms will call into these scripts by default. You can customize where `build` outputs to if your deployment platform requires it. There are built in guides for `zeit` and `heroku` which will check your project is prepared for deployment to those respective platforms. Take advantage of them if applicable: From 0f44560cb588e60ab52f35f275cda31a4ef0cbb0 Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Mon, 18 May 2020 12:30:25 +0200 Subject: [PATCH 5/6] fix: bundle output takes symmetry with the project --- src/lib/build/build.ts | 15 +++--- src/lib/build/bundle.ts | 89 +++++++++++++++++++++++++------ src/lib/build/deploy-target.ts | 4 +- src/lib/layout/index.spec.ts | 12 ++--- src/lib/layout/index.ts | 1 + src/lib/layout/layout.ts | 23 ++++---- src/lib/tsc.ts | 6 +-- src/runtime/start/start-module.ts | 15 ------ 8 files changed, 106 insertions(+), 59 deletions(-) diff --git a/src/lib/build/build.ts b/src/lib/build/build.ts index da6f86b1c..ba93cbd2d 100644 --- a/src/lib/build/build.ts +++ b/src/lib/build/build.ts @@ -27,7 +27,7 @@ interface BuildSettings { output?: string stage?: string entrypoint?: string - asBundle: boolean, + asBundle: boolean cwd?: string } @@ -42,7 +42,7 @@ export async function buildNexusApp(settings: BuildSettings) { buildOutputDir: buildOutput, asBundle: settings.asBundle, entrypointPath: settings.entrypoint, - cwd: settings.cwd + cwd: settings.cwd, }) /** @@ -108,23 +108,26 @@ export async function buildNexusApp(settings: BuildSettings) { }) if (layout.build.bundleOutputDir) { + log.info('bundling app') await bundle({ base: layout.projectRoot, + bundleOutputDir: layout.build.bundleOutputDir, entrypoint: layout.build.startModuleOutPath, - outputDir: layout.build.bundleOutputDir, + tsOutputDir: layout.build.tsOutputDir, + tsRootDir: layout.tsConfig.content.options.rootDir!, plugins: pluginReflection.plugins, }) - await FS.removeAsync(layout.build.outputDir) + await FS.removeAsync(layout.build.tsOutputDir) } } const buildOutputLog = layout.tsConfig.content.options.noEmit === true ? 'no emit' - : Path.relative(layout.projectRoot, layout.build.bundleOutputDir ?? layout.build.outputDir) + : Path.relative(layout.projectRoot, layout.build.bundleOutputDir ?? layout.build.tsOutputDir) log.info('success', { - buildOutput: buildOutputLog, + buildOutput, time: Date.now() - startTime, }) diff --git a/src/lib/build/bundle.ts b/src/lib/build/bundle.ts index a055f429d..f7391ddf0 100644 --- a/src/lib/build/bundle.ts +++ b/src/lib/build/bundle.ts @@ -1,9 +1,10 @@ +import fileTrace from '@zeit/node-file-trace' import * as fs from 'fs' import * as fsJetpack from 'fs-jetpack' -import fileTrace from '@zeit/node-file-trace' import * as path from 'path' -import { Plugin } from '../plugin' +import * as Layout from '../../lib/layout' import { rootLogger } from '../nexus-logger' +import { Plugin } from '../plugin' import { fatal } from '../process' const log = rootLogger.child('cli').child('build').child('bundle') @@ -12,34 +13,56 @@ type Entry = { source: string | Buffer; mode?: number } | null type SourceCache = Map interface BundleOptions { + /** + * Base path against which relative paths should be computed. + * Should usually be `layout.projectRoot`. + */ base: string + /** + * Absolute path of the output bundle directory. + */ + bundleOutputDir: string + /** + * Absolute path to the transpiled Javascript entrypoint. + */ entrypoint: string - outputDir: string + /** + * Absolute path of the output typescript directory. + */ + tsOutputDir: string + /** + * Absolute path of the tsconfig.json rootDir property. + */ + tsRootDir: string + /** + * List of Nexus plugins. + */ plugins: Plugin[] } +/** + * Bundle the transpiled output of Typescript into a treeshaked output. + * The treeshake is done at the module level, not function level. + * A new node_modules folder will be outputted in `bundleOutputDir` containing only the required packages + * for the runtime to work. + */ export async function bundle(opts: BundleOptions): Promise { log.trace('starting bundle') // delete previous bundle before tracing files - fsJetpack.remove(opts.outputDir) + fsJetpack.remove(opts.bundleOutputDir) - const { files } = await traceFiles({ - base: opts.base, - entrypoint: opts.entrypoint, - plugins: opts.plugins, - }) + const { files } = await traceFiles(opts) await writeToFS({ files, - outputDir: opts.outputDir, - base: opts.base, + ...opts }) log.trace('done bundling') } -export async function traceFiles(opts: Omit) { +export async function traceFiles(opts: Pick) { const sourceCache = new Map() const worktimeTesttimePluginPaths = getWorktimeAndTesttimePluginPaths(opts.base, opts.plugins) @@ -49,11 +72,12 @@ export async function traceFiles(opts: Omit) { base: opts.base, /** * - We ignore `prettier` because `@nexus/schema` requires it as a optional peer dependency - * - We ignore `@prisma/client/scripts` because `nexus-prisma` causes node-file-trace to include these scripts which causes ncc to be traces as well + * - We ignore `@prisma/client/scripts` because `nexus-prisma` causes node-file-trace to include these scripts which causes `ncc` to be traces as well */ ignore: ['node_modules/prettier/index.js', 'node_modules/@prisma/client/scripts/**/*'], readFile(fsPath: string): Buffer | string | null { const relPath = path.relative(opts.base, fsPath) + const cached = sourceCache.get(relPath) if (cached) return cached.toString() // null represents a not found @@ -125,15 +149,44 @@ export async function traceFiles(opts: Omit) { /** * Write gathered files by node-file-trace to the file system */ -async function writeToFS(opts: { files: SourceCache; outputDir: string; base: string }): Promise { +async function writeToFS(params: { + base: string + tsOutputDir: string + tsRootDir: string + bundleOutputDir: string + files: SourceCache +}): Promise { const writePromises = [] - for (const [relPath, entry] of opts.files.entries()) { + for (const [relPath, entry] of params.files.entries()) { if (entry === null) { continue } - const to = path.resolve(opts.outputDir, relPath) + let to: string + + // Calc absolute path of the file + const absPath = path.resolve(params.base, relPath) + + // If the file is inside the tsOutputDir + if (pathIsInside({ base: params.tsOutputDir, target: absPath })) { + // Calc relative path of the file to tsOutputDir + const relativeToTsOutputDir = path.relative(params.tsOutputDir, relPath) + // Calc relative path of the rootDir to base + const relativeRootDir = path.relative(params.base, params.tsRootDir) + /** + * Transform path + * + * from: + * from val: /project/.nexus/tmp/folder/filename.js + * + * to: // + * to val: /project/.nexus/build/api /folder/filename.js + */ + to = path.resolve(params.bundleOutputDir, relativeRootDir, relativeToTsOutputDir) + } else { + to = path.resolve(params.bundleOutputDir, relPath) + } const promise = fsJetpack.write(to, entry.source, entry.mode ? { mode: entry.mode } : {}) writePromises.push(promise) @@ -160,3 +213,7 @@ function getWorktimeAndTesttimePluginPaths(base: string, plugins: Plugin[]) { return paths } + +function pathIsInside(params: { base: string; target: string }) { + return !path.relative(params.base, params.target).startsWith('..') +} diff --git a/src/lib/build/deploy-target.ts b/src/lib/build/deploy-target.ts index 67de384dd..0399d94f7 100644 --- a/src/lib/build/deploy-target.ts +++ b/src/lib/build/deploy-target.ts @@ -75,7 +75,7 @@ interface NowJson { */ function validateNow(layout: Layout): ValidatorResult { const maybeNowJson = findFileRecurisvelyUpwardSync('now.json', { cwd: layout.projectRoot }) - const startModulePath = `${layout.build.outputDir}/${START_MODULE_NAME}.js` + const startModulePath = `${layout.build.tsOutputDir}/${START_MODULE_NAME}.js` let isValid = true // Make sure there's a now.json file @@ -191,7 +191,7 @@ function validateHeroku(layout: Layout): ValidatorResult { isValid = false } - const relativeBuildOutput = Path.relative(layout.packageJson.dir, layout.build.outputDir) + const relativeBuildOutput = Path.relative(layout.packageJson.dir, layout.build.tsOutputDir) // Make sure there's a start script if (!pcfg.scripts?.start) { diff --git a/src/lib/layout/index.spec.ts b/src/lib/layout/index.spec.ts index 4262cb616..5d393d936 100644 --- a/src/lib/layout/index.spec.ts +++ b/src/lib/layout/index.spec.ts @@ -366,14 +366,14 @@ describe('build output', () => { const result = await ctx.scan() expect({ - outputDir: result.build.outputDir, + tsOutputDir: result.build.tsOutputDir, startModuleInPath: result.build.startModuleInPath, startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "outputDir": "__DYNAMIC__/.nexus/build", "startModuleInPath": "__DYNAMIC__/index.ts", "startModuleOutPath": "__DYNAMIC__/.nexus/build/index.js", + "tsOutputDir": "__DYNAMIC__/.nexus/build", } `) }) @@ -392,14 +392,14 @@ describe('build output', () => { const result = await ctx.scan() expect({ - outputDir: result.build.outputDir, + tsOutputDir: result.build.tsOutputDir, startModuleInPath: result.build.startModuleInPath, startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "outputDir": "__DYNAMIC__/dist", "startModuleInPath": "__DYNAMIC__/index.ts", "startModuleOutPath": "__DYNAMIC__/dist/index.js", + "tsOutputDir": "__DYNAMIC__/dist", } `) }) @@ -417,14 +417,14 @@ describe('build output', () => { const result = await ctx.scan({ buildOutput: 'custom-output' }) expect({ - outputDir: result.build.outputDir, + tsOutputDir: result.build.tsOutputDir, startModuleInPath: result.build.startModuleInPath, startModuleOutPath: result.build.startModuleOutPath, }).toMatchInlineSnapshot(` Object { - "outputDir": "__DYNAMIC__/custom-output", "startModuleInPath": "__DYNAMIC__/index.ts", "startModuleOutPath": "__DYNAMIC__/custom-output/index.js", + "tsOutputDir": "__DYNAMIC__/custom-output", } `) }) diff --git a/src/lib/layout/index.ts b/src/lib/layout/index.ts index bf9e24527..1a2535d94 100644 --- a/src/lib/layout/index.ts +++ b/src/lib/layout/index.ts @@ -3,6 +3,7 @@ export { createFromData, Data, DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, + TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, findAppModule, Layout, loadDataFromParentProcess, diff --git a/src/lib/layout/layout.ts b/src/lib/layout/layout.ts index b04b3f324..f50ce173b 100644 --- a/src/lib/layout/layout.ts +++ b/src/lib/layout/layout.ts @@ -13,7 +13,12 @@ import * as Schema from './schema-modules' import { readOrScaffoldTsconfig } from './tsconfig' export const DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = '.nexus/build' -export const DEFAULT_TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT = 'build' +/** + * 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' const log = rootLogger.child('layout') @@ -73,7 +78,7 @@ export type ScanResult = { type OutputInfo = { startModuleOutPath: string startModuleInPath: string - outputDir: string + tsOutputDir: string bundleOutputDir: string | null } @@ -425,27 +430,23 @@ function getBuildInfo( scanResult: ScanResult, asBundle?: boolean ): OutputInfo { - const outputDir = getBuildOutput(buildOutput, scanResult) + const tsOutputDir = getBuildOutput(buildOutput, scanResult) const startModuleInPath = Path.join(scanResult.sourceRoot, START_MODULE_NAME + '.ts') - const startModuleOutPath = Path.join(outputDir, START_MODULE_NAME + '.js') + const startModuleOutPath = Path.join(tsOutputDir, START_MODULE_NAME + '.js') if (!asBundle) { return { - outputDir, + tsOutputDir, startModuleInPath, startModuleOutPath, bundleOutputDir: null, } } - const tsBuildInfo = getBuildInfo( - DEFAULT_TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, - scanResult, - false - ) + const tsBuildInfo = getBuildInfo(TMP_TS_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, scanResult, false) return { ...tsBuildInfo, - bundleOutputDir: outputDir, + bundleOutputDir: tsOutputDir, } } diff --git a/src/lib/tsc.ts b/src/lib/tsc.ts index ba49f84a3..d713ae6b4 100644 --- a/src/lib/tsc.ts +++ b/src/lib/tsc.ts @@ -33,7 +33,7 @@ export function createTSProgram( options: { ...compilerCacheOptions, ...layout.tsConfig.content.options, - outDir: layout.build.outputDir, + outDir: layout.build.tsOutputDir, }, }) @@ -83,10 +83,10 @@ export function emitTSProgram( ): void { if (options?.removePreviousBuild === true) { log.trace('remove previous build folder if present') - fs.remove(layout.build.outputDir) + fs.remove(layout.build.tsOutputDir) } - log.trace('emit transpiled modules', { dest: layout.build.outputDir }) + log.trace('emit transpiled modules', { dest: layout.build.tsOutputDir }) const emitResult = builder.emit() log.trace('done', { filesEmitted: emitResult.emittedFiles?.length ?? 0 }) diff --git a/src/runtime/start/start-module.ts b/src/runtime/start/start-module.ts index 2f83329c9..65b18f207 100644 --- a/src/runtime/start/start-module.ts +++ b/src/runtime/start/start-module.ts @@ -95,21 +95,6 @@ export function createStartModuleContent(config: StartModuleConfig): string { ` } - if (config.layout.packageJson) { - content += EOL + EOL + EOL - content += stripIndent` - // package.json is needed for plugin auto-import system. - // On the Zeit Now platform, builds and dev copy source into - // new directory. Copying follows paths found in source. Give one here - // to package.json to make sure Zeit Now brings it along. - require('${ - config.absoluteModuleImports - ? config.layout.packageJson.path - : Path.relative(config.layout.build.outputDir, config.layout.packageJson.path) - }') - ` - } - // This MUST come after nexus package has been imported for its side-effects const staticImports = printStaticImports(config.layout, { absolutePaths: config.absoluteModuleImports, From f7783fc95e954525af4fb20c94394e561248dad8 Mon Sep 17 00:00:00 2001 From: Flavian DESVERNE Date: Mon, 18 May 2020 14:09:29 +0200 Subject: [PATCH 6/6] fix: init start script --- src/cli/commands/create/app.ts | 5 +++-- src/lib/build/build.ts | 2 +- test/__helpers/e2e/kitchen-sink.ts | 9 ++------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/cli/commands/create/app.ts b/src/cli/commands/create/app.ts index cc415d24d..07e0cd043 100644 --- a/src/cli/commands/create/app.ts +++ b/src/cli/commands/create/app.ts @@ -461,6 +461,7 @@ const templates: Record = { */ async function scaffoldBaseFiles(options: InternalConfig) { const appEntrypointPath = path.join(options.sourceRoot, 'app.ts') + const sourceRootRelative = path.relative(options.projectRoot, options.sourceRoot) await Promise.all([ // Empty app and graphql module. @@ -536,7 +537,7 @@ async function scaffoldBaseFiles(options: InternalConfig) { format: "npx prettier --write './**/*.{ts,md}'", dev: 'nexus dev', build: 'nexus build', - start: 'node .nexus/build', + start: `node .nexus/build/${sourceRootRelative}`, }, prettier: { semi: false, @@ -551,7 +552,7 @@ async function scaffoldBaseFiles(options: InternalConfig) { fs.writeAsync( 'tsconfig.json', tsconfigTemplate({ - sourceRootRelative: path.relative(options.projectRoot, options.sourceRoot), + sourceRootRelative, outRootRelative: Layout.DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT, }) ), diff --git a/src/lib/build/build.ts b/src/lib/build/build.ts index e6523d798..87b9edd54 100644 --- a/src/lib/build/build.ts +++ b/src/lib/build/build.ts @@ -131,7 +131,7 @@ export async function buildNexusApp(settings: BuildSettings) { : Path.relative(layout.projectRoot, layout.build.bundleOutputDir ?? layout.build.tsOutputDir) log.info('success', { - buildOutput, + buildOutput: buildOutputLog, time: Date.now() - startTime, }) diff --git a/test/__helpers/e2e/kitchen-sink.ts b/test/__helpers/e2e/kitchen-sink.ts index 15d412621..f2a391b2d 100644 --- a/test/__helpers/e2e/kitchen-sink.ts +++ b/test/__helpers/e2e/kitchen-sink.ts @@ -224,7 +224,7 @@ export async function e2eKitchenSink(app: E2EContext) { log.warn('run built app and query graphql api') - proc = app.node([DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT]) + proc = app.spawn(['npm', 'run', 'start']) sub = proc.connect() await proc.pipe(takeUntilServerListening).toPromise() @@ -251,11 +251,6 @@ export async function e2eKitchenSink(app: E2EContext) { log.warn('run built app from a different CWD than the project root') - await app - .node([app.fs.path(DEFAULT_BUILD_FOLDER_PATH_RELATIVE_TO_PROJECT_ROOT)], { - cwd: '/', - }) - .pipe(refCount(), takeUntilServerListening) - .toPromise() + await app.spawn(['npm', 'run', 'start']).pipe(refCount(), takeUntilServerListening).toPromise() } }