Skip to content

Commit 69c1ce2

Browse files
authored
feat: bundled builds (#49)
* Bundler WIP * blueprints: update app blueprint for bundled output * refactor bin/denali.ts to simplify, make more robust * remove extraneous commented code, add pkg-dir * use generic names for bundled output files * wrap unit tests with a bundle reference * Bundler WIP * lazy load jscodeshift to reduce CLI startup time * rework ejections to ensure we avoid race conditions in command acceptance tests * fix: improve debug output, avoid circular deps when creating builders
1 parent aed47cf commit 69c1ce2

40 files changed

+1422
-1455
lines changed

.vscode/settings.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"eslint.enable": false
2+
"eslint.enable": false,
3+
"workbench.colorCustomizations": {
4+
"titleBar.activeBackground": "#1d8da8",
5+
"titleBar.activeForeground": "#ffffff"
6+
}
37
}

.vscode/tasks.json

+7-34
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,16 @@
11
{
22
// See https://go.microsoft.com/fwlink/?LinkId=733558
33
// for the documentation about the tasks.json format
4-
"version": "0.1.0",
5-
"command": "npm",
6-
"isShellCommand": true,
7-
"showOutput": "always",
8-
"suppressTaskName": true,
4+
"version": "2.0.0",
95
"tasks": [
106
{
11-
"taskName": "build",
12-
"args": ["run", "build"],
13-
"isBuildCommand": true
14-
},
15-
{
16-
"taskName": "lint",
17-
"args": ["run", "lint"],
18-
"problemMatcher": {
19-
"owner": "external",
20-
"fileLocation": [
21-
"relative",
22-
"${workspaceRoot}"
23-
],
24-
"severity": "warning",
25-
"pattern": {
26-
"regexp": "^(\\S.*)\\[(\\d+), (\\d+)\\]:\\s+(.*)$",
27-
"file": 1,
28-
"line": 2,
29-
"column": 3,
30-
"message": 4
31-
}
7+
"type": "npm",
8+
"script": "build",
9+
"problemMatcher": [],
10+
"group": {
11+
"kind": "build",
12+
"isDefault": true
3213
}
33-
},
34-
{
35-
"taskName": "update",
36-
"args": ["update"]
37-
},
38-
{
39-
"taskName": "test",
40-
"args": ["run", "test"]
4114
}
4215
]
4316
}

bin/denali.ts

+29-41
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,53 @@
11
#!/usr/bin/env node
2-
import 'main-dir';
3-
import SourceMapSupport = require('source-map-support');
2+
43
import { satisfies } from 'semver';
54
import * as chalk from 'chalk';
65
import * as path from 'path';
76
import * as fs from 'fs';
87
import * as NestedError from 'nested-error-stacks';
98
import * as resolve from 'resolve';
10-
import findup = require('findup-sync');
9+
import { sync as readPkgUp } from 'read-pkg-up';
10+
import * as pkgDir from 'pkg-dir';
1111

1212
/* tslint:disable:no-console */
1313

14-
SourceMapSupport.install();
15-
1614
process.title = 'denali';
1715

1816
let version = process.version;
1917

2018
if (!satisfies(process.version, '>=7.6')) {
21-
console.error(chalk.red('`denali` requires node version >= 7.6, you used ' + version));
22-
process.exit(1);
19+
throw new Error(`Denali requires node version >= 7.6, you used ${ version }`);
2320
}
2421

25-
let pkgPath = findup('package.json');
22+
let projectPkg: any = null;
23+
let cliPkg: any;
24+
let cliBootstrapPath: string;
25+
let source: string;
2626

27-
/**
28-
* Load the globally installed version of the CLI and kick it off from there. Commands will be
29-
* loaded from the global package namespace.
30-
*/
31-
function loadGlobalCli() {
32-
let pkg = require('../../package.json');
33-
process.stdout.write(`cli v${ pkg.version } [global] `);
27+
try {
3428
try {
35-
require('../lib/bootstrap').default();
36-
} catch (error) {
37-
throw new NestedError('Globally installed CLI failed to load', error);
29+
projectPkg = readPkgUp().pkg;
30+
let projectDir = pkgDir();
31+
let localCliMain = resolve.sync('denali-cli', { basedir: projectDir });
32+
let localCliDir = pkgDir(localCliMain);
33+
cliPkg = readPkgUp({ cwd: localCliMain });
34+
process.chdir(projectDir);
35+
source = fs.lstatSync(localCliDir).isSymbolicLink() ? 'linked' : 'local';
36+
cliBootstrapPath = path.join(localCliDir, 'dist/lib/bootstrap');
37+
} catch (e) {
38+
cliPkg = readPkgUp({ cwd: __dirname }).pkg;
39+
cliBootstrapPath = path.join(__dirname, '../lib/bootstrap');
40+
source = 'global';
3841
}
39-
}
4042

41-
// No package.json found, revert to global install
42-
if (!pkgPath) {
43-
loadGlobalCli();
44-
// Package.json found
45-
} else {
46-
let pkg = require(pkgPath);
47-
let pkgDir = path.dirname(path.resolve(pkgPath));
48-
// If a local copy of denali exists, use that, unless we are actually running
49-
// this in the denali repo itself
43+
process.stdout.write(`cli v${ cliPkg.version } [${ source }]`);
44+
5045
try {
51-
let localCliMain = resolve.sync('denali-cli', { basedir: pkgDir });
52-
let localCliDir = path.dirname(findup('package.json', { cwd: localCliMain }));
53-
let cliPkgType = fs.lstatSync(localCliDir).isSymbolicLink() ? 'linked' : 'local';
54-
let localCliPkg = require(path.join(localCliDir, 'package.json'));
55-
process.stdout.write(`cli v${ localCliPkg.version } [${ cliPkgType }] `);
56-
try {
57-
process.chdir(pkgDir);
58-
require(path.join(localCliDir, 'dist', 'lib', 'bootstrap')).default(pkg);
59-
} catch (error) {
60-
throw new NestedError('Error encountered while starting up denali-cli', error);
61-
}
62-
} catch (e) {
63-
loadGlobalCli();
46+
require(cliBootstrapPath).default(projectPkg);
47+
} catch (error) {
48+
throw new NestedError('\nError encountered while starting up denali-cli', error);
6449
}
50+
} catch (e) {
51+
console.error(chalk.red(e.stack || e.message || e));
52+
process.exit(1);
6553
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
const { Builder } = require('denali-cli');
1+
const { AddonBuilder } = require('denali-cli');
22

3-
module.exports = class <%= className %>Builder extends Builder {};
3+
module.exports = class <%= className %>Builder extends AddonBuilder {};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { DummyBuilder } = require('denali-cli');
2+
3+
module.exports = class extends DummyBuilder {};

blueprints/app/files/__name__/app/index.js

-15
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import MemoryAdapter from 'denali';
1+
import { MemoryAdapter } from 'denali';
22

33
export default MemoryAdapter;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
const { Builder } = require('denali-cli');
1+
const { AppBuilder } = require('denali-cli');
22

3-
module.exports = class <%= className %>Builder extends Builder {};
3+
module.exports = class <%= className %>Builder extends AppBuilder {};
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const bundle = require('./dist/<%= name %>.runtime');
2+
const container = bundle();
3+
4+
const Application = container.lookup('app:application');
5+
const application = new Application(container.loader, { environment: process.env.NODE_ENV || 'development' });
6+
application.start();
7+
8+
module.exports = application;
9+

lib/blueprint.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { execSync, ExecSyncOptions } from 'child_process';
1212
import { sync as commandExists } from 'command-exists';
1313
import * as chalk from 'chalk';
1414
import * as walk from 'walk-sync';
15-
import * as codeshift from 'jscodeshift';
1615
import * as mkdirp from 'mkdirp';
1716
import * as rimraf from 'rimraf';
1817
import * as yargs from 'yargs';
@@ -330,8 +329,8 @@ export default class Blueprint extends Command {
330329
ui.warn(`Attempted to add "${ method.toUpperCase() } ${ urlPattern } -> ${ actionPath }" route, but config/routes.js does not exist. Skipping ...`);
331330
return;
332331
}
333-
let j = codeshift;
334-
let ast = codeshift(routesSource);
332+
let j = require('jscodeshift');
333+
let ast = j(routesSource);
335334
let drawRoutesFunction = ast.find(j.ExportDefaultDeclaration).get().value.declaration;
336335
let routerArgName = drawRoutesFunction.params[0].name;
337336
let drawRoutesFunctionBody = j(drawRoutesFunction.body);
@@ -377,8 +376,8 @@ export default class Blueprint extends Command {
377376
ui.warn(`Attempted to remove "${ method.toUpperCase() } ${ urlPattern } -> ${ actionPath }" route, but config/routes.js does not exist. Skipping ...`);
378377
return;
379378
}
380-
let j = codeshift;
381-
let ast = codeshift(routesSource);
379+
let j = require('codeshift');
380+
let ast = j(routesSource);
382381
let drawRoutesFunction = ast.find(j.ExportDefaultDeclaration).get().value.declaration;
383382
let routerArgName = drawRoutesFunction.params[0].name;
384383
let drawRoutesFunctionBody = j(drawRoutesFunction.body);

lib/bootstrap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default function run(projectPkg?: any) {
5454

5555
debug(`found ${ keys(addonCommands).length } commands from ${ addon.pkg.name }: [ ${ keys(addonCommands).join(', ') } ] `);
5656
if (addon.pkg.name === 'denali') {
57-
assert(keys(addonCommands).length > 0, 'Denali package was found, but unable to load core commands - is your Denali installation corrupted?');
57+
assert(keys(addonCommands).length > 0, 'Denali package was found, but no core commands were found. Is your Denali installation corrupted?');
5858
coreCommands = addonCommands;
5959

6060
let denaliInstallType: string;

0 commit comments

Comments
 (0)