UNPKG

3.82 kBPlain TextView Raw
1import * as os from "os";
2import * as path from "path";
3import startsWith = require("lodash/startsWith");
4import { ThenableAsyncGenerator, ThenableGenerator } from 'thenable-generator';
5import * as util from "check-iterable";
6
7const WinPipe = "\\\\?\\pipe\\";
8
9export const local = Symbol("local");
10export const remotized = Symbol("remotized");
11export const noLocal = Symbol("noLocal");
12
13export function absPath(filename: string, withPipe?: boolean): string {
14 // resolve path to be absolute
15 if (!path.isAbsolute(filename)) {
16 filename = path.resolve(process.cwd(), filename);
17 }
18
19 if (withPipe && os.platform() == "win32" && !startsWith(filename, WinPipe)) {
20 filename = WinPipe + filename;
21 }
22
23 return filename;
24}
25
26export function set(target: any, prop: any, value: any, writable = false) {
27 Object.defineProperty(target, prop, {
28 configurable: true,
29 enumerable: false,
30 writable,
31 value
32 });
33}
34
35export function getInstance<T>(mod: ModuleProxy<T>, instantiate = true): T {
36 let ins: T;
37 let { ctor } = mod;
38
39 if (ctor) {
40 if (instantiate) {
41 if (typeof ctor.getInstance === "function") {
42 ins = ctor.getInstance();
43 } else {
44 ins = mod.create();
45 }
46 } else {
47 // Create instance without instantiating, used for remote instance.
48 ins = Object.create(ctor.prototype);
49 }
50 } else {
51 ins = <any>mod.proto;
52 }
53
54 return ins;
55}
56
57export function mergeFnProperties(fn: Function, origin: Function) {
58 set(fn, "proxified", true);
59 set(fn, "name", origin.name);
60 set(fn, "length", origin.length);
61 set(fn, "toString", function toString() {
62 return Function.prototype.toString.call(origin);
63 }, true);
64
65 return fn;
66}
67
68export function createRemoteInstance(
69 mod: ModuleProxy<any>,
70 fnCreator: (prop: string) => Function
71) {
72
73 // Generate a proxified singleton instance to the module, so that it can
74 // be used for remote requests. the remote instance should only return
75 // methods.
76 return new Proxy(getInstance(mod, false), {
77 get: (ins, prop: string) => {
78 let type = typeof ins[prop];
79 let isFn = type === "function";
80
81 if (isFn && !ins[prop].proxified
82 && !(<Object>ins).hasOwnProperty(prop)
83 ) {
84 set(ins, prop, mergeFnProperties(fnCreator(prop), ins[prop]));
85 }
86
87 return isFn ? ins[prop] : (type === "undefined" ? undefined : null);
88 },
89 has: (ins, prop: string) => {
90 return typeof ins[prop] === "function";
91 }
92 });
93}
94
95export function createLocalInstance(mod: ModuleProxy<any>) {
96 return new Proxy(getInstance(mod), {
97 get: (ins, prop: string) => {
98 if (typeof ins[prop] === "function"
99 && !ins[prop].proxified
100 && !(<Object>ins).hasOwnProperty(prop)
101 ) {
102 let origin: Function = ins[prop];
103
104 set(ins, prop, mergeFnProperties(generable(origin), origin), true);
105 }
106
107 return ins[prop];
108 }
109 });
110}
111
112function generable(origin: Function) {
113 return function (this: any, ...args: any[]) {
114 try {
115 let res = origin.apply(this, args);
116
117 if (res && util.isAsyncGenerator(res)) {
118 return new ThenableAsyncGenerator(res);
119 } else if (res && util.isGenerator(res)) {
120 return new ThenableGenerator(res);
121 } else {
122 return res;
123 }
124 } catch (err) {
125 throw err;
126 }
127 };
128}
\No newline at end of file