1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
18 const fs
= require('fs');
19 const path
= require(`path`);
20 const pump
= require(`stream`).pipeline
;
21 const child_process
= require(`child_process`);
22 const { targets
, modules
} = require('./argv');
25 empty
: ObservableEmpty
,
26 throwError
: ObservableThrow
,
27 fromEvent
: ObservableFromEvent
35 } = require('rxjs/operators');
36 const asyncDone
= require('util').promisify(require('async-done'));
38 const mainExport
= `Arrow`;
39 const npmPkgName
= `apache-arrow`;
40 const npmOrgName
= `@${npmPkgName}`;
42 const releasesRootDir
= `targets`;
43 const knownTargets
= [`es5`, `es2015`, `esnext`];
44 const knownModules
= [`cjs`, `esm`, `cls`, `umd`];
45 const tasksToSkipPerTargetOrFormat
= {
46 src
: { clean
: true, build
: true },
47 cls
: { test
: true, package: true }
49 const packageJSONFields
= [
50 `version`, `license`, `description`,
51 `author`, `homepage`, `repository`,
52 `bugs`, `keywords`, `dependencies`,
56 const metadataFiles
= [`LICENSE.txt`, `NOTICE.txt`, `README.md`].map((filename
) => {
57 let prefixes
= [`./`, `../`];
58 let p
= prefixes
.find((prefix
) => {
60 fs
.statSync(path
.resolve(path
.join(prefix
, filename
)));
61 } catch (e
) { return false; }
65 throw new Error(`Couldn't find ${filename} in ./ or ../`);
67 return path
.join(p
, filename
);
70 // see: https://github.com/google/closure-compiler/blob/c1372b799d94582eaf4b507a4a22558ff26c403c/src/com/google/javascript/jscomp/CompilerOptions.java#L2988
71 const gCCLanguageNames
= {
73 es2015
: `ECMASCRIPT_2015`,
74 es2016
: `ECMASCRIPT_2016`,
75 es2017
: `ECMASCRIPT_2017`,
76 es2018
: `ECMASCRIPT_2018`,
77 es2019
: `ECMASCRIPT_2019`,
78 esnext
: `ECMASCRIPT_NEXT`
81 function taskName(target
, format
) {
82 return !format
? target
: `${target}:${format}`;
85 function packageName(target
, format
) {
86 return !format
? target
: `${target}-${format}`;
89 function tsconfigName(target
, format
) {
90 return !format
? target
: `${target}.${format}`;
93 function targetDir(target
, format
) {
94 return path
.join(releasesRootDir
, ...(!format
? [target
] : [target
, format
]));
97 function shouldRunInChildProcess(target
, format
) {
98 // If we're building more than one module/target, then yes run this task in a child process
99 if (targets
.length
> 1 || modules
.length
> 1) { return true; }
100 // If the target we're building *isn't* the target the gulp command was configured to run, then yes run that in a child process
101 if (targets
[0] !== target
|| modules
[0] !== format
) { return true; }
102 // Otherwise no need -- either gulp was run for just one target, or we've been spawned as the child of a multi-target parent gulp
106 const gulp
= path
.join(path
.parse(require
.resolve(`gulp`)).dir
, `bin/gulp.js`);
107 function spawnGulpCommandInChildProcess(command
, target
, format
) {
108 const args
= [gulp
, command
, '-t', target
, '-m', format
, `--silent`];
110 stdio
: [`ignore`, `inherit`, `inherit`],
111 env
: { ...process
.env
, NODE_NO_WARNINGS
: `1` }
113 return asyncDone(() => child_process
.spawn(`node`, args
, opts
))
114 .catch((e
) => { throw `Error in "${command}:${taskName(target, format)}" task`; });
117 const logAndDie
= (e
) => { if (e
) { process
.exit(1) } };
118 function observableFromStreams(...streams
) {
119 if (streams
.length
<= 0) { return ObservableEmpty(); }
120 const pumped
= streams
.length
<= 1 ? streams
[0] : pump(...streams
, logAndDie
);
121 const fromEvent
= ObservableFromEvent
.bind(null, pumped
);
122 const streamObs
= fromEvent(`data`).pipe(
123 mergeWith(fromEvent(`error`).pipe(flatMap((e
) => ObservableThrow(e
)))),
124 takeUntil(fromEvent(`end`).pipe(mergeWith(fromEvent(`close`)))),
125 defaultIfEmpty(`empty stream`),
126 share({ connector
: () => new ReplaySubject(), resetOnError
: false, resetOnComplete
: false, resetOnRefCountZero
: false })
128 streamObs
.stream
= pumped
;
129 streamObs
.observable
= streamObs
;
133 function* combinations(_targets
, _modules
) {
134 const targets
= known(knownTargets
, _targets
|| [`all`]);
135 const modules
= known(knownModules
, _modules
|| [`all`]);
137 if (_targets
.includes(`src`)) {
142 if (_targets
.includes(`all`) && _modules
.includes(`all`)) {
145 yield [npmPkgName
, ``];
148 for (const format
of modules
) {
149 for (const target
of targets
) {
150 yield [target
, format
];
154 function known(known
, values
) {
155 return values
.includes(`all`) ? known
156 : values
.includes(`src`) ? [`src`]
158 values
.reduce((map
, arg
) => ((
159 (known
.includes(arg
)) &&
160 (map
[arg
.toLowerCase()] = true)
163 ).sort((a
, b
) => known
.indexOf(a
) - known
.indexOf(b
));
167 const publicModulePaths
= (dir
) => [
168 `${dir}/${mainExport}.dom.js`,
169 `${dir}/util/int.js`,
170 `${dir}/compute/predicate.js`,
173 const esmRequire
= require(`esm`)(module
, {
176 /* A boolean for storing ES modules in require.cache. */
178 /* A boolean for respecting require.extensions in ESM. */
180 /* A boolean for __esModule interoperability. */
182 /* A boolean for importing named exports of CJS modules. */
184 /* A boolean for following CJS path rules in ESM. */
186 /* A boolean for __dirname, __filename, and require in ESM. */
192 mainExport
, npmPkgName
, npmOrgName
, metadataFiles
, packageJSONFields
,
194 knownTargets
, knownModules
, tasksToSkipPerTargetOrFormat
, gCCLanguageNames
,
196 taskName
, packageName
, tsconfigName
, targetDir
, combinations
, observableFromStreams
,
197 publicModulePaths
, esmRequire
, shouldRunInChildProcess
, spawnGulpCommandInChildProcess
,
199 targetAndModuleCombinations
: [...combinations(targets
, modules
)]