Example #1
0
  beforeEach(async () => {
    const registry = new schema.CoreSchemaRegistry();
    registry.addPostTransform(schema.transforms.addUndefinedDefaults);
    testArchitectHost = new TestingArchitectHost();
    architect = new Architect(testArchitectHost, registry);

    options = {};
    called = 0;
    testArchitectHost.addBuilder('package:test', createBuilder(async o => {
      called++;
      options = o;

      return new Promise<BuilderOutput>(resolve => {
        setTimeout(() => resolve({ success: true }), 10);
      });
    }));
    testArchitectHost.addBuilder('package:test-options', createBuilder(o => {
      options = o;

      return { success: true };
    }));

    testArchitectHost.addTarget(target1, 'package:test');
    testArchitectHost.addTarget(target2, 'package:test');
  });
export async function generateBrowserWebpackConfigFromContext(
  options: BrowserBuilderSchema,
  context: BuilderContext,
  webpackPartialGenerator: (wco: BrowserWebpackConfigOptions) => webpack.Configuration[],
  host: virtualFs.Host<fs.Stats> = new NodeJsSyncHost(),
): Promise<{ workspace: experimental.workspace.Workspace, config: webpack.Configuration[] }> {
  const registry = new schema.CoreSchemaRegistry();
  registry.addPostTransform(schema.transforms.addUndefinedDefaults);

  const workspace = await experimental.workspace.Workspace.fromPath(
    host,
    normalize(context.workspaceRoot),
    registry,
  );

  const projectName = context.target ? context.target.project : workspace.getDefaultProjectName();

  if (!projectName) {
    throw new Error('Must either have a target from the context or a default project.');
  }

  const config = await generateBrowserWebpackConfigFromWorkspace(
    options,
    context,
    projectName,
    workspace,
    host,
    webpackPartialGenerator,
    context.logger,
  );

  return { workspace, config };
}
  beforeEach(() => {
    registry = new schema.CoreSchemaRegistry([]);
    registry.registerUriHandler((uri: string) => {
      if (uri.startsWith('ng-cli://')) {
        const content = readFileSync(
          join(__dirname, '..', uri.substr('ng-cli://'.length)), 'utf-8');

        return Promise.resolve(JSON.parse(content));
      } else {
        return null;
      }
    });
  });
Example #4
0
  beforeEach(async () => {
    await host.initialize().toPromise();

    const registry = new schema.CoreSchemaRegistry();
    registry.addPostTransform(schema.transforms.addUndefinedDefaults);

    const workspace = await experimental.workspace.Workspace.fromPath(host, host.root(), registry);
    const architectHost = new TestingArchitectHost(
      host.root(),
      host.root(),
      new WorkspaceNodeModulesArchitectHost(workspace, host.root()),
    );
    architect = new Architect(architectHost, registry);
  });
Example #5
0
async function main(args: string[]): Promise<number> {
  /** Parse the command line. */
  const argv = minimist(args, { boolean: ['help'] });

  /** Create the DevKit Logger used through the CLI. */
  const logger = createConsoleLogger(argv['verbose']);

  // Check the target.
  const targetStr = argv._[0] || '';
  if (!targetStr || argv.help) {
    // Show architect usage if there's no target.
    usage(logger);
  }

  // Load workspace configuration file.
  const currentPath = process.cwd();
  const configFileNames = [
    'angular.json',
    '.angular.json',
    'workspace.json',
    '.workspace.json',
  ];

  const configFilePath = findUp(configFileNames, currentPath);

  if (!configFilePath) {
    logger.fatal(`Workspace configuration file (${configFileNames.join(', ')}) cannot be found in `
      + `'${currentPath}' or in parent directories.`);

    return 3;
  }

  const root = path.dirname(configFilePath);
  const configContent = readFileSync(configFilePath, 'utf-8');
  const workspaceJson = JSON.parse(configContent);

  const registry = new schema.CoreSchemaRegistry();
  registry.addPostTransform(schema.transforms.addUndefinedDefaults);

  const host = new NodeJsSyncHost();
  const workspace = new experimental.workspace.Workspace(normalize(root), host);

  await workspace.loadWorkspaceFromJson(workspaceJson).toPromise();

  // Clear the console.
  process.stdout.write('\u001Bc');

  return await _executeTarget(logger, workspace, root, argv, registry);
}
export function formatValidator(
  data: JsonValue,
  dataSchema: JsonObject,
  formats: schema.SchemaFormat[],
): Observable<schema.SchemaValidatorResult> {
  const registry = new schema.CoreSchemaRegistry();

  for (const format of formats) {
    registry.addFormat(format);
  }

  return registry
    .compile(dataSchema)
    .pipe(mergeMap(validator => validator(data)));
}
Example #7
0
  async function createArchitect(workspaceRoot: string) {
    vfHost = new NodeJsSyncHost();
    const configContent = fs.readFileSync(path.join(workspaceRoot, 'angular.json'), 'utf-8');
    const workspaceJson = JSON.parse(configContent);

    const registry = new schema.CoreSchemaRegistry();
    registry.addPostTransform(schema.transforms.addUndefinedDefaults);

    const workspace = new experimental.workspace.Workspace(normalize(workspaceRoot), vfHost);
    await workspace.loadWorkspaceFromJson(workspaceJson).toPromise();

    testArchitectHost = new TestingArchitectHost(workspaceRoot, workspaceRoot,
      new WorkspaceNodeModulesArchitectHost(workspace, workspaceRoot));
    architect = new Architect(testArchitectHost, registry);
  }
Example #8
0
export async function createArchitect(workspaceRoot: Path) {
  const registry = new schema.CoreSchemaRegistry();
  registry.addPostTransform(schema.transforms.addUndefinedDefaults);
  const workspaceSysPath = getSystemPath(workspaceRoot);

  const workspace = await experimental.workspace.Workspace.fromPath(host, host.root(), registry);
  const architectHost = new TestingArchitectHost(
    workspaceSysPath,
    workspaceSysPath,
    new WorkspaceNodeModulesArchitectHost(workspace, workspaceSysPath),
  );
  const architect = new Architect(architectHost, registry);

  return {
    workspace,
    architectHost,
    architect,
  };
}
Example #9
0
export async function runCommand(
  args: string[],
  logger: logging.Logger,
  workspace: CommandWorkspace,
  commands?: CommandMapOptions,
): Promise<number | void> {
  if (commands === undefined) {
    const commandMapPath = findUp('commands.json', __dirname);
    if (commandMapPath === null) {
      throw new Error('Unable to find command map.');
    }
    const cliDir = dirname(commandMapPath);
    const commandsText = readFileSync(commandMapPath).toString('utf-8');
    const commandJson = json.parseJson(
      commandsText,
      JsonParseMode.Loose,
      { path: commandMapPath },
    );
    if (!isJsonObject(commandJson)) {
      throw Error('Invalid command.json');
    }

    commands = {};
    for (const commandName of Object.keys(commandJson)) {
      const commandValue = commandJson[commandName];
      if (typeof commandValue == 'string') {
        commands[commandName] = resolve(cliDir, commandValue);
      }
    }
  }

  // This registry is exclusively used for flattening schemas, and not for validating.
  const registry = new schema.CoreSchemaRegistry([]);
  registry.registerUriHandler((uri: string) => {
    if (uri.startsWith('ng-cli://')) {
      const content = readFileSync(join(__dirname, '..', uri.substr('ng-cli://'.length)), 'utf-8');

      return Promise.resolve(JSON.parse(content));
    } else {
      return null;
    }
  });

  // Normalize the commandMap
  const commandMap: CommandDescriptionMap = {};
  for (const name of Object.keys(commands)) {
    const schemaPath = commands[name];
    const schemaContent = readFileSync(schemaPath, 'utf-8');
    const schema = json.parseJson(schemaContent, JsonParseMode.Loose, { path: schemaPath });
    if (!isJsonObject(schema)) {
      throw new Error('Invalid command JSON loaded from ' + JSON.stringify(schemaPath));
    }

    commandMap[name] =
      await parseJsonSchemaToCommandDescription(name, schemaPath, registry, schema);
  }

  let commandName: string | undefined = undefined;
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];

    if (arg in commandMap) {
      commandName = arg;
      args.splice(i, 1);
      break;
    } else if (!arg.startsWith('-')) {
      commandName = arg;
      args.splice(i, 1);
      break;
    }
  }

  // if no commands were found, use `help`.
  if (commandName === undefined) {
    if (args.length === 1 && args[0] === '--version') {
      commandName = 'version';
    } else {
      commandName = 'help';
    }
  }

  let description: CommandDescription | null = null;

  if (commandName !== undefined) {
    if (commandMap[commandName]) {
      description = commandMap[commandName];
    } else {
      Object.keys(commandMap).forEach(name => {
        const commandDescription = commandMap[name];
        const aliases = commandDescription.aliases;

        let found = false;
        if (aliases) {
          if (aliases.some(alias => alias === commandName)) {
            found = true;
          }
        }

        if (found) {
          if (description) {
            throw new Error('Found multiple commands with the same alias.');
          }
          commandName = name;
          description = commandDescription;
        }
      });
    }
  }

  if (!commandName) {
    logger.error(tags.stripIndent`
        We could not find a command from the arguments and the help command seems to be disabled.
        This is an issue with the CLI itself. If you see this comment, please report it and
        provide your repository.
      `);

    return 1;
  }

  if (!description) {
    const commandsDistance = {} as { [name: string]: number };
    const name = commandName;
    const allCommands = Object.keys(commandMap).sort((a, b) => {
      if (!(a in commandsDistance)) {
        commandsDistance[a] = strings.levenshtein(a, name);
      }
      if (!(b in commandsDistance)) {
        commandsDistance[b] = strings.levenshtein(b, name);
      }

      return commandsDistance[a] - commandsDistance[b];
    });

    logger.error(tags.stripIndent`
        The specified command ("${commandName}") is invalid. For a list of available options,
        run "ng help".

        Did you mean "${allCommands[0]}"?
    `);

    return 1;
  }

  try {
    const parsedOptions = parser.parseArguments(args, description.options, logger);
    Command.setCommandMap(commandMap);
    const command = new description.impl({ workspace }, description, logger);

    return await command.validateAndRun(parsedOptions);
  } catch (e) {
    if (e instanceof parser.ParseArgumentException) {
      logger.fatal('Cannot parse arguments. See below for the reasons.');
      logger.fatal('    ' + e.comments.join('\n    '));

      return 1;
    } else {
      throw e;
    }
  }
}
Example #10
0
async function _renderUniversal(
  options: BuildWebpackAppShellSchema,
  context: BuilderContext,
  browserResult: BrowserBuilderOutput,
  serverResult: ServerBuilderOutput,
): Promise<BrowserBuilderOutput> {
  const browserIndexOutputPath = path.join(browserResult.outputPath || '', 'index.html');
  const indexHtml = fs.readFileSync(browserIndexOutputPath, 'utf8');
  const serverBundlePath = await _getServerModuleBundlePath(options, context, serverResult);

  const root = context.workspaceRoot;
  requireProjectModule(root, 'zone.js/dist/zone-node');

  const renderModuleFactory = requireProjectModule(
    root,
    '@angular/platform-server',
  ).renderModuleFactory;
  const AppServerModuleNgFactory = require(serverBundlePath).AppServerModuleNgFactory;
  const outputIndexPath = options.outputIndexPath
    ? path.join(root, options.outputIndexPath)
    : browserIndexOutputPath;

  // Render to HTML and overwrite the client index file.
  const html = await renderModuleFactory(AppServerModuleNgFactory, {
    document: indexHtml,
    url: options.route,
  });

  fs.writeFileSync(outputIndexPath, html);

  const browserTarget = targetFromTargetString(options.browserTarget);
  const rawBrowserOptions = await context.getTargetOptions(browserTarget);
  const browserBuilderName = await context.getBuilderNameForTarget(browserTarget);
  const browserOptions = await context.validateOptions<JsonObject & BrowserBuilderSchema>(
    rawBrowserOptions,
    browserBuilderName,
  );

  if (browserOptions.serviceWorker) {
    const host = new NodeJsSyncHost();
    // Create workspace.
    const registry = new schema.CoreSchemaRegistry();
    registry.addPostTransform(schema.transforms.addUndefinedDefaults);

    const workspace = await experimental.workspace.Workspace.fromPath(
      host,
      normalize(context.workspaceRoot),
      registry,
    );
    const projectName = context.target ? context.target.project : workspace.getDefaultProjectName();

    if (!projectName) {
      throw new Error('Must either have a target from the context or a default project.');
    }
    const projectRoot = resolve(
      workspace.root,
      normalize(workspace.getProject(projectName).root),
    );

    await augmentAppWithServiceWorker(
      host,
      normalize(root),
      projectRoot,
      join(normalize(root), browserOptions.outputPath),
      browserOptions.baseHref || '/',
      browserOptions.ngswConfigPath,
    );
  }

  return browserResult;
}