Browse Source

Split buildutils into buildutils and builder

The new builder package is used to build extensions. buildutils now contains repo-specific utilities.

Fixes #8857
Jason Grout 4 years ago
parent
commit
9cbbe2cb0a

+ 6 - 0
builder/README.md

@@ -0,0 +1,6 @@
+# @jupyterlab/builder
+
+A JupyterLab package which provides functions that are used to compile
+and build JupyterLab extensions.
+
+This package is only intended for use within Node.js environments.

+ 79 - 0
builder/metadata_schema.json

@@ -0,0 +1,79 @@
+{
+  "title": "JupyterLab Package Metadata",
+  "version": "0.1.0",
+  "description": "JupyterLab package.json settings.",
+  "definitions": {
+    "extension": {
+      "type": ["boolean", "string"]
+    },
+    "relativePath": {
+      "type": ["string", "null"]
+    }
+  },
+  "properties": {
+    "extension": {
+      "title": "Extension",
+      "description": "Presence of or relative path to a standard JupyterLab extension",
+      "$ref": "#/definitions/extension",
+      "default": false
+    },
+    "mimeExtension": {
+      "title": "Mime extension",
+      "description": "Presence of or relative path to a JupyterLab MIME renderer extension",
+      "$ref": "#/definitions/extension",
+      "default": false
+    },
+    "themePath": {
+      "title": "Theme path",
+      "description": "The relative path to theme files",
+      "$ref": "#/definitions/relativePath",
+      "default": null
+    },
+    "schemaDir": {
+      "title": "Schema directory",
+      "description": "The relative path to schema files",
+      "$ref": "#/definitions/relativePath",
+      "default": null
+    },
+    "outputDir": {
+      "title": "Output directory",
+      "description": "The relative path to the static assets",
+      "$ref": "#/definitions/relativePath",
+      "default": "static"
+    },
+    "sharedPackages": {
+      "title": "Shared packages",
+      "description": "Packages that should be shared (in addition to core shared packages)",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
+    },
+    "nonSharedPackages": {
+      "title": "Non-shared packages",
+      "description": "Packages that should not be shared (which can include core packages)",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
+    },
+    "singletonPackages": {
+      "title": "Singleton packages",
+      "description": "Packages that should be singletons (in addition to core singleton packages)",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
+    },
+    "nonSingleltonPackages": {
+      "title": "Non-singleton packages",
+      "description": "Packages that should not be singletons (which can include core packages)",
+      "type": "array",
+      "items": {
+        "type": "string"
+      }
+    }
+  },
+  "additionalProperties": false,
+  "type": "object"
+}

+ 91 - 0
builder/package.json

@@ -0,0 +1,91 @@
+{
+  "name": "@jupyterlab/builder",
+  "version": "3.0.0-alpha.11",
+  "description": "JupyterLab - Extension Builder",
+  "homepage": "https://github.com/jupyterlab/jupyterlab",
+  "bugs": {
+    "url": "https://github.com/jupyterlab/jupyterlab/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/jupyterlab/jupyterlab.git"
+  },
+  "license": "BSD-3-Clause",
+  "author": "Project Jupyter",
+  "files": [
+    "metadata_schema.json",
+    "lib/*.d.ts",
+    "lib/*.js.map",
+    "lib/*.js",
+    "template/package.json",
+    "template/tsconfig.json",
+    "template/src/index.ts"
+  ],
+  "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "bin": {
+    "build-labextension": "./lib/build-extension.js",
+    "ensure-max-old-space": "./lib/ensure-max-old-space.js"
+  },
+  "directories": {
+    "lib": "lib/"
+  },
+  "scripts": {
+    "build": "tsc",
+    "clean": "rimraf lib && rimraf tsconfig.tsbuildinfo",
+    "prepublishOnly": "npm run build",
+    "watch": "tsc -w --listEmittedFiles"
+  },
+  "dependencies": {
+    "@babel/core": "^7.10.2",
+    "@babel/preset-env": "^7.10.2",
+    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@lumino/algorithm": "^1.2.3",
+    "@lumino/application": "^1.8.4",
+    "@lumino/commands": "^1.10.1",
+    "@lumino/coreutils": "^1.4.3",
+    "@lumino/disposable": "^1.3.5",
+    "@lumino/domutils": "^1.1.7",
+    "@lumino/dragdrop": "^1.5.1",
+    "@lumino/messaging": "^1.3.3",
+    "@lumino/properties": "^1.1.6",
+    "@lumino/signaling": "^1.3.5",
+    "@lumino/virtualdom": "^1.6.1",
+    "@lumino/widgets": "^1.11.1",
+    "ajv": "^6.12.3",
+    "babel-loader": "^8.0.6",
+    "child_process": "~1.0.2",
+    "commander": "~4.0.1",
+    "css-loader": "~3.2.0",
+    "duplicate-package-checker-webpack-plugin": "^3.0.0",
+    "file-loader": "~5.0.2",
+    "fs": "~0.0.1-security",
+    "fs-extra": "^8.1.0",
+    "glob": "~7.1.6",
+    "mini-css-extract-plugin": "~0.10.0",
+    "path": "~0.12.7",
+    "raw-loader": "~4.0.0",
+    "style-loader": "~1.0.1",
+    "svg-url-loader": "~3.0.3",
+    "terser-webpack-plugin": "^2.3.0",
+    "to-string-loader": "^1.1.6",
+    "url-loader": "~3.0.0",
+    "webpack": "~5.0.0-beta.26",
+    "webpack-cli": "^3.3.10",
+    "webpack-merge": "^5.1.2",
+    "which": "^2.0.2",
+    "worker-loader": "^2.0.0"
+  },
+  "devDependencies": {
+    "@types/fs-extra": "^8.0.1",
+    "@types/glob": "^7.1.1",
+    "@types/node": "^12.12.17",
+    "@types/webpack": "^4.41.0",
+    "@types/which": "^1.3.2",
+    "rimraf": "~3.0.0",
+    "typescript": "~3.9.2"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}

+ 1 - 1
buildutils/src/build-extension.ts → builder/src/build-extension.ts

@@ -16,7 +16,7 @@
 
 import * as path from 'path';
 import commander from 'commander';
-import { run } from './utils';
+import { run } from '@jupyterlab/buildutils';
 
 commander
   .description('Build an extension')

+ 4 - 4
buildutils/src/build.ts → builder/src/build.ts

@@ -9,7 +9,7 @@ import * as webpack from 'webpack';
 import * as fs from 'fs-extra';
 import * as glob from 'glob';
 import * as path from 'path';
-import * as utils from './utils';
+import { readJSONFile } from '@jupyterlab/buildutils';
 
 /**
  *  A namespace for JupyterLab build utilities.
@@ -127,7 +127,7 @@ export namespace Build {
         path.join(packagePath, 'package.json')
       );
       const packageDir = path.dirname(packageDataPath);
-      const data = utils.readJSONFile(packageDataPath);
+      const data = readJSONFile(packageDataPath);
       const name = data.name;
       const extension = normalizeExtension(data);
 
@@ -153,7 +153,7 @@ export namespace Build {
         if (fs.existsSync(destination)) {
           try {
             const oldPackagePath = path.join(destination, 'package.json.orig');
-            const oldPackageData = utils.readJSONFile(oldPackagePath);
+            const oldPackageData = readJSONFile(oldPackagePath);
             if (oldPackageData.version === data.version) {
               fs.removeSync(destination);
             }
@@ -222,7 +222,7 @@ export namespace Build {
     cssImports = cssImports.sort((a, b) => a.localeCompare(b));
     let cssContents = '/* This is a generated file of CSS imports */';
     cssContents +=
-      '\n/* It was generated by @jupyterlab/buildutils in Build.ensureAssets() */';
+      '\n/* It was generated by @jupyterlab/builder in Build.ensureAssets() */';
     cssContents += `\n@import url('~${appCSS}');`;
     cssImports.forEach(cssImport => {
       cssContents += `\n@import url('~${cssImport}');`;

+ 0 - 0
buildutils/src/duplicate-package-checker-webpack-plugin.d.ts → builder/src/duplicate-package-checker-webpack-plugin.d.ts


+ 32 - 0
builder/src/ensure-max-old-space.ts

@@ -0,0 +1,32 @@
+#!/usr/bin/env node
+/* -----------------------------------------------------------------------------
+| Copyright (c) Jupyter Development Team.
+| Distributed under the terms of the Modified BSD License.
+|----------------------------------------------------------------------------*/
+
+/**
+ * This file is a temporary workaround to ensure that we can set
+ * max_old_space by default but allow others to override it.
+ *
+ * When node 10 support is dropped, we can remove this file as node 12
+ * should just grow as required.
+ *
+ * See: https://github.com/jupyterlab/jupyterlab/issues/7175
+ *
+ * @example
+ * node ensure-max-old-space.js real-cli.js arg1 arg2
+ */
+import { execFileSync } from 'child_process';
+import * as which from 'which';
+
+const MAX_OLD_SPACE = '--max_old_space_size=4096';
+
+if (!process.env.NODE_OPTIONS) {
+  process.env.NODE_OPTIONS = MAX_OLD_SPACE;
+} else if (!/--max[_\-]old[_\-]space[_\-]size/.test(process.env.NODE_OPTIONS)) {
+  process.env.NODE_OPTIONS += ` ${MAX_OLD_SPACE}`;
+}
+
+const program = which.sync(process.argv[2]);
+const args = process.argv.slice(3);
+execFileSync(program, args, { env: process.env, stdio: 'inherit' });

+ 7 - 0
builder/src/index.ts

@@ -0,0 +1,7 @@
+/* -----------------------------------------------------------------------------
+| Copyright (c) Jupyter Development Team.
+| Distributed under the terms of the Modified BSD License.
+|----------------------------------------------------------------------------*/
+
+export * from './build';
+export * from './webpack-plugins';

+ 0 - 0
buildutils/src/mini-css-extract-plugin.d.ts → builder/src/mini-css-extract-plugin.d.ts


+ 0 - 0
buildutils/src/webpack-plugins.ts → builder/src/webpack-plugins.ts


+ 0 - 0
buildutils/src/webpack.config.base.ts → builder/src/webpack.config.base.ts


+ 0 - 0
buildutils/src/webpack.config.ext.ts → builder/src/webpack.config.ext.ts


+ 14 - 0
builder/tsconfig.json

@@ -0,0 +1,14 @@
+{
+  "extends": "../tsconfigbase",
+  "compilerOptions": {
+    "outDir": "lib",
+    "rootDir": "src",
+    "module": "commonjs"
+  },
+  "include": ["src/*"],
+  "references": [
+    {
+      "path": "../buildutils"
+    }
+  ]
+}

+ 1 - 33
buildutils/package.json

@@ -24,8 +24,6 @@
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
   "bin": {
-    "build-labextension": "./lib/build-extension.js",
-    "ensure-max-old-space": "./lib/ensure-max-old-space.js",
     "get-dependency": "./lib/get-dependency.js",
     "remove-dependency": "./lib/remove-dependency.js",
     "update-dependency": "./lib/update-dependency.js",
@@ -41,52 +39,22 @@
     "watch": "tsc -w --listEmittedFiles"
   },
   "dependencies": {
-    "@babel/core": "^7.10.2",
-    "@babel/preset-env": "^7.10.2",
-    "@lumino/algorithm": "^1.2.3",
-    "@lumino/application": "^1.8.4",
-    "@lumino/commands": "^1.10.1",
     "@lumino/coreutils": "^1.4.3",
-    "@lumino/disposable": "^1.3.5",
-    "@lumino/domutils": "^1.1.7",
-    "@lumino/dragdrop": "^1.5.1",
-    "@lumino/messaging": "^1.3.3",
-    "@lumino/properties": "^1.1.6",
-    "@lumino/signaling": "^1.3.5",
-    "@lumino/virtualdom": "^1.6.1",
-    "@lumino/widgets": "^1.11.1",
     "@yarnpkg/lockfile": "^1.1.0",
-    "ajv": "^6.12.3",
-    "babel-loader": "^8.0.6",
     "child_process": "~1.0.2",
     "commander": "~4.0.1",
     "crypto": "~1.0.1",
-    "css-loader": "~3.2.0",
     "dependency-graph": "^0.8.1",
-    "duplicate-package-checker-webpack-plugin": "^3.0.0",
-    "file-loader": "~5.0.2",
-    "fs": "~0.0.1-security",
     "fs-extra": "^8.1.0",
     "glob": "~7.1.6",
     "inquirer": "^7.0.0",
-    "mini-css-extract-plugin": "~0.10.0",
     "package-json": "^6.5.0",
     "path": "~0.12.7",
     "prettier": "^1.19.1",
-    "raw-loader": "~4.0.0",
     "semver": "^6.3.0",
     "sort-package-json": "~1.31.0",
-    "style-loader": "~1.0.1",
-    "svg-url-loader": "~3.0.3",
-    "terser-webpack-plugin": "^2.3.0",
-    "to-string-loader": "^1.1.6",
     "typescript": "~3.9.2",
-    "url-loader": "~3.0.0",
-    "webpack": "~5.0.0-beta.26",
-    "webpack-cli": "^3.3.10",
-    "webpack-merge": "^5.1.2",
-    "which": "^2.0.2",
-    "worker-loader": "^2.0.0"
+    "which": "^2.0.2"
   },
   "devDependencies": {
     "@types/fs-extra": "^8.0.1",

+ 3 - 3
buildutils/src/ensure-repo.ts

@@ -24,7 +24,7 @@ type Dict<T> = { [key: string]: T };
 
 // Data to ignore.
 const MISSING: Dict<string[]> = {
-  '@jupyterlab/buildutils': ['path'],
+  '@jupyterlab/buildutils': ['path', 'webpack'],
   '@jupyterlab/testutils': ['fs'],
   '@jupyterlab/vega5-extension': ['vega-embed']
 };
@@ -34,11 +34,11 @@ const UNUSED: Dict<string[]> = {
   '@jupyterlab/apputils': ['@types/react', 'buffer', 'url'],
   '@jupyterlab/application': ['@fortawesome/fontawesome-free'],
   '@jupyterlab/apputils-extension': ['es6-promise'],
-  '@jupyterlab/buildutils': [
-    // For the phosphor shim
+  '@jupyterlab/builder': [
     '@lumino/algorithm',
     '@lumino/application',
     '@lumino/commands',
+    '@lumino/coreutils',
     '@lumino/disposable',
     '@lumino/domutils',
     '@lumino/dragdrop',

+ 0 - 2
buildutils/src/index.ts

@@ -3,8 +3,6 @@
 | Distributed under the terms of the Modified BSD License.
 |----------------------------------------------------------------------------*/
 
-export * from './build';
 export * from './ensure-package';
 export * from './get-dependency';
 export * from './utils';
-export * from './webpack-plugins';

+ 1 - 1
dev_mode/imports.css

@@ -1,5 +1,5 @@
 /* This is a generated file of CSS imports */
-/* It was generated by @jupyterlab/buildutils in Build.ensureAssets() */
+/* It was generated by @jupyterlab/builder in Build.ensureAssets() */
 @import url('~@jupyterlab/application-extension/style/index.css');
 @import url('~@jupyterlab/apputils-extension/style/index.css');
 @import url('~@jupyterlab/celltags-extension/style/index.css');

+ 2 - 0
dev_mode/package.json

@@ -62,6 +62,7 @@
     "@jupyterlab/vega5-extension": "~3.0.0-alpha.11"
   },
   "devDependencies": {
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "@jupyterlab/buildutils": "^3.0.0-alpha.11",
     "chokidar": "^3.4.0",
     "css-loader": "~3.2.0",
@@ -386,6 +387,7 @@
       "@jupyterlab/vdom": "../packages/vdom",
       "@jupyterlab/vdom-extension": "../packages/vdom-extension",
       "@jupyterlab/vega5-extension": "../packages/vega5-extension",
+      "@jupyterlab/builder": "../builder",
       "@jupyterlab/buildutils": "../buildutils",
       "@jupyterlab/template": "../buildutils/template",
       "@jupyterlab/testutils": "../testutils"

+ 3 - 3
dev_mode/webpack.config.js

@@ -11,11 +11,11 @@ const webpack = require('webpack');
 const merge = require('webpack-merge').default;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
   .BundleAnalyzerPlugin;
-const baseConfig = require('@jupyterlab/buildutils/lib/webpack.config.base');
+const baseConfig = require('@jupyterlab/builder/lib/webpack.config.base');
 const { ModuleFederationPlugin } = webpack.container;
 
-const Build = require('@jupyterlab/buildutils').Build;
-const WPPlugin = require('@jupyterlab/buildutils').WPPlugin;
+const Build = require('@jupyterlab/builder').Build;
+const WPPlugin = require('@jupyterlab/builder').WPPlugin;
 const package_data = require('./package.json');
 
 // Handle the extensions.

+ 1 - 1
docs/source/developer/extension_dev.rst

@@ -41,7 +41,7 @@ Implementation
   - The assets include a module federation ``remoteEntry.js``, generated bundles, and some other files that we use
   - ``package.orig.json`` is the original ``package.json`` file that we use to gather metadata about the package
   - ``build_log.json`` has all of the webpack options used to build the extension, for debugging purposes
-  - we use the existing ``@jupyterlab/buildutils -> build`` to generate the ``imports.css``, ``schemas`` and ``themes`` file structure
+  - we use the existing ``@jupyterlab/builder -> build`` to generate the ``imports.css``, ``schemas`` and ``themes`` file structure
 - We add a schema for the valid ``jupyterlab`` metadata for an extension's ``package.json`` describing the available options
 - We add a ``labextensions`` handler in ``jupyterlab_server`` that loads static assets from ``labextensions`` paths, following a similar logic to how ``nbextensions`` are discovered and loaded from disk
 - We augment the ``settings`` and ``themes`` handlers in ``jupyterlab_server`` to load from the new ``labextensions`` locations, favoring the dynamic extension locations over the bundled ones

+ 1 - 1
examples/app/package.json

@@ -11,7 +11,7 @@
     "@jupyterlab/application": "^3.0.0-alpha.11",
     "@jupyterlab/application-extension": "^3.0.0-alpha.11",
     "@jupyterlab/apputils-extension": "^3.0.0-alpha.11",
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "@jupyterlab/codemirror-extension": "^3.0.0-alpha.11",
     "@jupyterlab/completer-extension": "^3.0.0-alpha.11",
     "@jupyterlab/console-extension": "^3.0.0-alpha.11",

+ 1 - 1
examples/app/webpack.config.js

@@ -2,7 +2,7 @@
 // Distributed under the terms of the Modified BSD License.
 const data = require('./package.json');
 const webpack = require('webpack');
-const Build = require('@jupyterlab/buildutils').Build;
+const Build = require('@jupyterlab/builder').Build;
 
 const names = Object.keys(data.dependencies).filter(function(name) {
   const packageData = require(name + '/package.json');

+ 1 - 1
examples/federated/core_package/package.json

@@ -52,7 +52,7 @@
     "@jupyterlab/vega5-extension": "^3.0.0-alpha.11"
   },
   "devDependencies": {
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "copy-webpack-plugin": "^6.0.1",
     "css-loader": "~3.2.0",
     "file-loader": "~5.0.2",

+ 2 - 2
examples/federated/core_package/webpack.config.js

@@ -1,10 +1,10 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 const data = require('./package.json');
-const Build = require('@jupyterlab/buildutils').Build;
+const Build = require('@jupyterlab/builder').Build;
 const webpack = require('webpack');
 const merge = require('webpack-merge').default;
-const baseConfig = require('@jupyterlab/buildutils/lib/webpack.config.base');
+const baseConfig = require('@jupyterlab/builder/lib/webpack.config.base');
 const { ModuleFederationPlugin } = webpack.container;
 const fs = require('fs-extra');
 const path = require('path');

+ 1 - 1
examples/federated/md_package/package.json

@@ -15,7 +15,7 @@
     "@lumino/widgets": "^1.11.1"
   },
   "devDependencies": {
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "rimraf": "~3.0.0"
   },
   "jupyterlab": {

+ 1 - 1
examples/federated/middle_package/package.json

@@ -10,7 +10,7 @@
     "@lumino/coreutils": "^1.4.3"
   },
   "devDependencies": {
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "rimraf": "~3.0.0"
   },
   "publishConfig": {

+ 1 - 1
examples/federated/phosphor_package/package.json

@@ -11,7 +11,7 @@
     "@phosphor/coreutils": "^1.0.0"
   },
   "devDependencies": {
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11",
+    "@jupyterlab/builder": "^3.0.0-alpha.11",
     "rimraf": "~3.0.0"
   },
   "publishConfig": {

+ 10 - 10
jupyterlab/dynamic_labextensions.py

@@ -195,31 +195,31 @@ def watch_labextension(path, app_dir=None, logger=None):
 def _ensure_builder(ext_path, core_path):
     """Ensure that we can build the extension and return the builder script path
     """
-    # Test for compatible dependency on @jupyterlab/buildutils
+    # Test for compatible dependency on @jupyterlab/builder
     with open(osp.join(core_path, 'package.json')) as fid:
         core_data = json.load(fid)
     with open(osp.join(ext_path, 'package.json')) as fid:
         ext_data = json.load(fid)
-    depVersion1 = core_data['devDependencies']['@jupyterlab/buildutils']
-    depVersion2 = ext_data.get('devDependencies', dict()).get('@jupyterlab/buildutils')
-    depVersion2 = depVersion2 or ext_data.get('dependencies', dict()).get('@jupyterlab/buildutils')
+    depVersion1 = core_data['devDependencies']['@jupyterlab/builder']
+    depVersion2 = ext_data.get('devDependencies', dict()).get('@jupyterlab/builder')
+    depVersion2 = depVersion2 or ext_data.get('dependencies', dict()).get('@jupyterlab/builder')
     if depVersion2 is None:
-        raise ValueError('Extensions require a devDependency on @jupyterlab/buildutils@%s' % depVersion1)
+        raise ValueError('Extensions require a devDependency on @jupyterlab/builder@%s' % depVersion1)
     overlap = _test_overlap(depVersion1, depVersion2, drop_prerelease1=True)
     if not overlap:
-        raise ValueError('Extensions require a devDependency on @jupyterlab/buildutils@%s' % depVersion1)
+        raise ValueError('Extensions require a devDependency on @jupyterlab/builder@%s' % depVersion1)
     if not osp.exists(osp.join(ext_path, 'node_modules')):
         subprocess.check_call(['jlpm'], cwd=ext_path)
 
-    # Find @jupyterlab/buildutils using node module resolution
+    # Find @jupyterlab/builder using node module resolution
     # We cannot use a script because the script path is a shell script on Windows
     target = ext_path
-    while not osp.exists(osp.join(target, 'node_modules', '@jupyterlab', 'buildutils')):
+    while not osp.exists(osp.join(target, 'node_modules', '@jupyterlab', 'builder')):
         if osp.dirname(target) == target:
-            raise ValueError('Could not find @jupyterlab/buildutils')
+            raise ValueError('Could not find @jupyterlab/builder')
         target = osp.dirname(target)
 
-    return osp.join(target, 'node_modules', '@jupyterlab', 'buildutils', 'lib', 'build-extension.js')
+    return osp.join(target, 'node_modules', '@jupyterlab', 'builder', 'lib', 'build-extension.js')
     
 
 def _should_copy(src, dest, logger=None):

+ 1 - 1
jupyterlab/tests/mock_packages/extension/package.json

@@ -6,7 +6,7 @@
     "@jupyterlab/launcher": "^3.0.0-alpha.11"
   },
   "devDependencies": {
-    "@jupyterlab/buildutils": "^3.0.0-alpha.11"
+    "@jupyterlab/builder": "^3.0.0-alpha.11"
   },
   "jupyterlab": {
     "extension": true

+ 2 - 0
package.json

@@ -9,6 +9,7 @@
       "packages/services/examples/node",
       "packages/services/examples/browser",
       "packages/services/examples/typescript-browser-with-output",
+      "builder",
       "buildutils",
       "buildutils/template",
       "buildutils/test-template",
@@ -24,6 +25,7 @@
     "analyze:dev": "cd dev_mode && jlpm run build --analyze",
     "analyze:prod": "cd dev_mode && jlpm run build:prod --analyze",
     "build": "jlpm run build:dev",
+    "build:builder": "cd builder && jlpm run build",
     "build:core": "cd jupyterlab/staging && jlpm && (jlpm deduplicate || jlpm) && jlpm run build",
     "build:dev": "jlpm run integrity && jlpm run build:packages && cd dev_mode && jlpm run build",
     "build:dev:prod": "jlpm run integrity && jlpm run build:packages && cd dev_mode && jlpm run build:prod",

+ 1 - 1
packages/extensionmanager-extension/examples/listings/webpack.config.js

@@ -1,7 +1,7 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 var data = require('./package.json');
-var Build = require('@jupyterlab/buildutils').Build;
+var Build = require('@jupyterlab/builder').Build;
 
 var names = Object.keys(data.dependencies).filter(function(name) {
   var packageData = require(name + '/package.json');

+ 47 - 42
scripts/ensure-buildutils.js

@@ -10,55 +10,60 @@ const glob = require('glob');
 const path = require('path');
 const childProcess = require('child_process');
 
-const basePath = path.join(path.resolve('.'), 'buildutils');
+function ensurePackage(p) {
+  const basePath = path.join(path.resolve('.'), p);
 
-// Make sure that buildutils is built and current
-let current = true;
-if (fs.existsSync(path.join(basePath, 'lib'))) {
-  const srcFiles = glob.sync(path.join(basePath, 'src', '*'));
-  const libFiles = glob.sync(path.join(basePath, 'lib', '*'));
-  srcFiles.forEach(function(srcPath) {
-    // bail early if already not current
-    if (!current) {
-      return;
-    }
+  // Make sure that buildutils is built and current
+  let current = true;
+  if (fs.existsSync(path.join(basePath, 'lib'))) {
+    const srcFiles = glob.sync(path.join(basePath, 'src', '*'));
+    const libFiles = glob.sync(path.join(basePath, 'lib', '*'));
+    srcFiles.forEach(function(srcPath) {
+      // bail early if already not current
+      if (!current) {
+        return;
+      }
 
-    if (srcPath.endsWith('.d.ts')) {
-      // bail if this is a src declarations file
-      return;
-    }
+      if (srcPath.endsWith('.d.ts')) {
+        // bail if this is a src declarations file
+        return;
+      }
 
-    const name = path.basename(srcPath);
-    const ext = path.extname(name);
-    if (ext !== '.ts') {
-      current = false;
-      return;
-    }
+      const name = path.basename(srcPath);
+      const ext = path.extname(name);
+      if (ext !== '.ts') {
+        current = false;
+        return;
+      }
 
-    const libPath = path.join(basePath, 'lib', name.replace('.ts', '.js'));
-    if (libFiles.indexOf(libPath) === -1) {
-      current = false;
-      return;
-    }
-    const srcTime = fs.statSync(srcPath).mtime;
-    const libTime = fs.statSync(libPath).mtime;
-    if (libTime < srcTime) {
-      current = false;
-    }
-  });
-} else {
-  current = false;
-}
+      const libPath = path.join(basePath, 'lib', name.replace('.ts', '.js'));
+      if (libFiles.indexOf(libPath) === -1) {
+        current = false;
+        return;
+      }
+      const srcTime = fs.statSync(srcPath).mtime;
+      const libTime = fs.statSync(libPath).mtime;
+      if (libTime < srcTime) {
+        current = false;
+      }
+    });
+  } else {
+    current = false;
+  }
 
-if (!current) {
-  // This must be "npm" because it is run during `pip install -e .` before
-  // jlpm is installed.
-  childProcess.execSync('npm run build', {
-    stdio: [0, 1, 2],
-    cwd: path.resolve('./buildutils')
-  });
+  if (!current) {
+    // This must be "npm" because it is run during `pip install -e .` before
+    // jlpm is installed.
+    childProcess.execSync('npm run build', {
+      stdio: [0, 1, 2],
+      cwd: path.resolve('./' + p)
+    });
+  }
 }
 
+ensurePackage('buildutils');
+ensurePackage('builder');
+
 // uncomment to time script
 // var end = new Date() - start;
 // console.info('Execution time: %dms', end);

+ 1 - 0
tsconfig.eslint.json

@@ -4,6 +4,7 @@
     "packages/**/src/**/*",
     "packages/**/test/**/*",
     "testutils/src/*",
+    "builder/**/*",
     "buildutils/**/*",
     "tests/**/*",
     "dev_mode/*",