blob: 2635459cf54f75253410e00c9e4b789e5ad1735e [file] [log] [blame]
#!/usr/bin/env node
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const path = require("path")
const fs = require("fs")
const execFileSync = require('child_process').execFileSync;
// write a file creating intermediate directories
function write_file(file, body, executable) {
fs.mkdirSync(path.dirname(file), { recursive: true })
fs.writeFileSync(file, body)
if (executable) {
fs.chmodSync(file, 0755)
}
}
// copy a file eventually replacing a substring
function copy_replace(src, dst, match, replacement) {
let body = fs.readFileSync(src, "utf-8")
if (match) {
body = body.replace(match, replacement)
}
write_file(dst, body)
}
function deext(filename) {
const pos = filename.lastIndexOf(".")
filename = pos > -1 ? filename.substring(0, pos) : filename
return filename
}
// resolve dependencies from package.json - return the main file
function dependencies(src_dir) {
const pkg_config = src_dir + "/package.json"
const node_modules = src_dir + "/node_modules"
if (fs.existsSync(pkg_config)) {
if (!fs.existsSync(node_modules)) {
execFileSync("yarn", [], {
"cwd": src_dir
})
}
const config = JSON.parse(fs.readFileSync(pkg_config, "utf-8"))
if ("main" in config) {
return deext(config["main"])
}
}
return "index"
}
// assemble sources
function sources(launcher, main_file, main_func, src_dir) {
// init config
const src_config = src_dir + "/tsconfig.json"
const config = {}
if (fs.existsSync(src_config)) {
config = JSON.parse(fs.readFileSync(src_config, "utf-8"))
}
if (!("files" in config)) {
config["files"] = []
}
if (!("compilerOptions" in config)) {
config["compilerOptions"] = {}
}
config["compilerOptions"]["inlineSourceMap"] = true
if ("sourceMap" in config["compilerOptions"]) {
delete config["compilerOptions"]["sourceMap"]
}
if (!("outDir" in config["compilerOptions"])) {
config["compilerOptions"]["outDir"] = "."
}
// copy main src file if any (and use it as main)
const src_file = src_dir + "/exec"
const tgt_file = src_dir + "/" + main_file + ".ts"
if (fs.existsSync(src_file) && !fs.existsSync(tgt_file)) {
const re = RegExp('(?<!export\\s+)function\\s+' + main_func)
copy_replace(src_file, tgt_file, re, "export function " + main_func)
config["files"].push(main_file + ".ts")
}
// copy launcher and replace main
copy_replace(launcher,
src_dir + "/exec__.ts",
'require("./main__").main',
'require("./' + main_file + '").' + main_func)
// complete tsconfig.json
config["files"].push("exec__.ts")
write_file(src_config, JSON.stringify(config))
}
function build(src_dir, bin_dir) {
try {
fs.rmdirSync(bin_dir)
fs.renameSync(src_dir, bin_dir)
execFileSync("tsc", [], {
cwd: bin_dir,
stdio: 'inherit',
stderr: 'inherit'
})
write_file(bin_dir + "/exec",
'#!/bin/bash\n' +
'if [ "$(cat $0.env)" != "$__OW_EXECUTION_ENV" ]\n' +
'then cd "$(dirname $0)"\n' +
' echo "Execution Environment Mismatch"\n' +
' echo "Expected: $(cat $0.env)"\n' +
' echo "Actual: $__OW_EXECUTION_ENV"\n' +
' exit 1\n' +
'fi\n' +
'cd "$(dirname $0)"\n' +
'if [ -z "$__OW_DEBUG_PORT" ]\n' +
'then node exec__.js\n' +
'else node --inspect=":$__OW_DEBUG_PORT" exec__.js\n' +
'fi\n', true)
write_file(bin_dir + "/exec.env", process.env["__OW_EXECUTION_ENV"])
} catch (err) {
console.log("syntax error:", err.message)
}
}
function compile() {
if (process.argv.length < 4) {
console.log("usage: <main-function> <source-dir> <target-dir>")
process.exit(1)
}
const launcher = path.dirname(path.dirname(process.argv[1])) + "/lib/launcher.ts"
const src_dir = path.resolve(process.argv[3])
const bin_dir = path.resolve(process.argv[4])
let main_func = process.argv[2]
let main_file = dependencies(src_dir)
const pieces = main_func.split(".")
if (pieces.length > 1) {
main_file = pieces.shift()
main_func = pieces.join(".")
}
sources(launcher, main_file, main_func, src_dir)
build(src_dir, bin_dir)
}
if (require.main === module) {
compile()
}