-
Notifications
You must be signed in to change notification settings - Fork 0
/
polyfill.js
145 lines (121 loc) · 3.71 KB
/
polyfill.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// This is a not-production-ready polyfill of the WinterCG CLI API proposal.
// The proposal is highly likely to have breaking changes in the future!
// https://github.com/wintercg/proposal-cli-api
// Implemented:
// - args
// - env
// - exit
// Supported runtimes:
// - Node, or other runtimes implementing `process` (Bun, etc)
// - Deno
const NAMESPACE = 'CLI';
const ensureString = (v, badRet = undefined) => {
if (typeof v !== 'string') return badRet;
return true;
};
if (typeof process !== 'undefined') {
// Node, or other runtimes implementing `process` (Bun, etc):
// process.argv already excludes arguments used by the runtime,
// but still has the runtime binary path and script path.
// process.env is mostly there but we are more strict with checks.
// process.exit is ~identical.
const { argv, env } = process;
globalThis[NAMESPACE] = {
args: argv.slice(2),
exit: n => process.exit(n ?? 0),
env: new Proxy({}, {
get: (_, p) => {
if (typeof p !== 'string') return undefined;
return env[p];
},
set: (_, p, v) => {
if (typeof p !== 'string') return false;
env[p] = String(v);
return true;
},
has: (_, p) => {
if (typeof p !== 'string') return false;
return Object.prototype.hasOwnProperty.call(env, p);
},
deleteProperty: (_, p) => {
if (typeof p !== 'string') return false;
delete env[p];
return true;
},
getOwnPropertyDescriptor: (_, p) => {
if (typeof p !== 'string') return undefined;
return { value: env[p], writable: true, enumerable: true, configurable: true };
},
ownKeys: () => Object.keys(env),
})
};
} else if (typeof Deno !== 'undefined') {
// Deno:
// Deno.args is already as specified.
// Deno.env is Map-like instead of Object-like
// so we polyfill it into CLI.env as specified.
// Deno.exit is ~identical.
const { args, exit, env } = Deno;
globalThis[NAMESPACE] = {
args,
exit: n => exit(n ?? 0),
env: new Proxy({}, {
get: (_, p) => {
if (typeof p !== 'string') return undefined;
return env.get(p);
},
set: (_, p, v) => {
if (typeof p !== 'string') return false;
env.set(p, String(v));
return true;
},
has: (_, p) => {
if (typeof p !== 'string') return false;
return env.has(p);
},
deleteProperty: (_, p) => {
if (typeof p !== 'string') return false;
env.delete(p);
return true;
},
getOwnPropertyDescriptor: (_, p) => {
if (typeof p !== 'string') return undefined;
return { value: env.get(p), writable: true, enumerable: true, configurable: true };
},
ownKeys: () => Object.keys(env.toObject()),
})
};
} else {
// Unknown runtime:
// Warn and create mock API.
console.warn('[cli-api-polyfill] Unknown runtime!');
globalThis[NAMESPACE] = {
args: [],
exit: () => {},
env: new Proxy({}, {
get: (_, p) => {
if (typeof p !== 'string') return undefined;
return _[p];
},
set: (_, p, v) => {
if (typeof p !== 'string') return false;
_[p] = String(v);
return true;
},
has: (_, p) => {
if (typeof p !== 'string') return false;
return Object.prototype.hasOwnProperty.call(_, p);
},
deleteProperty: (_, p) => {
if (typeof p !== 'string') return false;
delete _[p];
return true;
},
getOwnPropertyDescriptor: (_, p) => {
if (typeof p !== 'string') return undefined;
return { value: _[p], writable: true, enumerable: true, configurable: true };
},
ownKeys: () => Object.keys(env),
})
};
}