1 | import * as os from "os";
|
2 | import * as path from "path";
|
3 | import startsWith = require("lodash/startsWith");
|
4 | import { ThenableAsyncGenerator, ThenableGenerator } from 'thenable-generator';
|
5 | import * as util from "check-iterable";
|
6 |
|
7 | const WinPipe = "\\\\?\\pipe\\";
|
8 |
|
9 | export const local = Symbol("local");
|
10 | export const remotized = Symbol("remotized");
|
11 | export const noLocal = Symbol("noLocal");
|
12 |
|
13 | export function absPath(filename: string, withPipe?: boolean): string {
|
14 |
|
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 |
|
26 | export 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 |
|
35 | export 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 |
|
48 | ins = Object.create(ctor.prototype);
|
49 | }
|
50 | } else {
|
51 | ins = <any>mod.proto;
|
52 | }
|
53 |
|
54 | return ins;
|
55 | }
|
56 |
|
57 | export 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 |
|
68 | export function createRemoteInstance(
|
69 | mod: ModuleProxy<any>,
|
70 | fnCreator: (prop: string) => Function
|
71 | ) {
|
72 |
|
73 |
|
74 |
|
75 |
|
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 |
|
95 | export 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 |
|
112 | function 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 |