Skip to content

Unexpected promisified pipeline behavior when the plugin is included #660

Open
@Oaphi

Description

@Oaphi

Expected behavior:

Pipeline completion without issues.

Actual behavior:

The task fails upon the promisified pipeline reaching an instance of CompileStream the plugin's createProject method returns with the error (as the task is still registered):

Did you forget to signal async completion?

I narrowed down the issue to the gulp-typescript plugin, as the same promisified pipeline finishes successfully without it.
Non-promisified version of the pipeline also fails. However, the same task but connected via chaining of pipe methods works as expected.

Since CompileStream inherits from stream.Duplex, I am not sure what can be the problem. finish and end events are emitted. Order of events is also normal for the pipeline flow (pipe -> resume -> finish -> unpipe -> end -> pause).

Your gulpfile:

import { dest, series, src, watch } from "gulp";
import * as aprep from "gulp-append-prepend";
import * as rename from "gulp-rename";
import * as ts from "gulp-typescript";
import * as ug from "gulp-uglify";
import { pipeline } from "stream";
import { promisify } from "util";
import GulpClient = require("gulp");

const asyncPipe = promisify(pipeline);

const config = {
  globs: {
    front: {
      src: ["src/js/**/*", "!src/js/**/*.json"],
      dest: "html/",
    },
  },
  tsconfig: {
    front: "./src/js/",
  },
};

const projectPath = `${config.tsconfig.front}tsconfig.json`;

const project = ts.createProject(projectPath);

const transpileFrontendJs: GulpClient.TaskFunction = async () => {
  await asyncPipe(
    src(config.globs.front.src),
    project(),
    ug({ output: { webkit: true } }),
    rename({
      extname: ".html", //apps script treats .js files as .gs
    }),
    aprep.prependText(`<script type="text/javascript">`),
    aprep.appendText(`</script>`),
    dest(config.globs.front.dest)
  );
};

export const frontend = series(transpileFrontendJs);

const watchOpts: GulpClient.WatchOptions = { ignoreInitial: false, delay: 2e3 };

export default () => {
  return watch(config.globs.front.src, watchOpts, frontend);
};

tsconfig.json

Parent tsconfig.json:

{
  "compilerOptions": {
    "noImplicitThis": true,
    "forceConsistentCasingInFileNames": true,
    "removeComments": true,
    "module": "none",
    "moduleResolution": "node",
    "types": ["node", "google-apps-script", "materialize-css"],
    "target": "es2019",
    "lib": ["ESNext"],
    "pretty": true,
    "experimentalDecorators": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitReturns": true,
    "strict": true,
    "noErrorTruncation": true,
    "checkJs": true
  },
  "exclude": ["clsp.js", "src/js"]
}

Child tsconfig.json:

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "types": ["gapi", "materialize-css"],
    "lib": ["DOM", "ESNext"],
    "module": "none",
    "target": "es5",
    "moduleResolution": "node"
  },
  "include": ["*.ts"],
  "exclude": []
}

Environment

Relevant dependencies:

"devDependencies": {
    "gulp": "^4.0.2",
    "gulp-append-prepend": "^1.0.8",
    "gulp-autoprefixer": "^7.0.1",
    "gulp-inject": "^5.0.5",
    "gulp-rename": "^2.0.0",
    "gulp-typescript": "^6.0.0-alpha.1",
    "gulp-uglify": "^3.0.2",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.2",
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions