/
item.js
137 lines (116 loc) 路 3.68 KB
/
item.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
// @flow
import type { PluginTarget, PluginOptions } from "./validation/options";
import path from "path";
import {
createDescriptor,
type UnloadedDescriptor,
} from "./config-descriptors";
export function createItemFromDescriptor(desc: UnloadedDescriptor): ConfigItem {
return new ConfigItem(desc);
}
/**
* Create a config item using the same value format used in Babel's config
* files. Items returned from this function should be cached by the caller
* ideally, as recreating the config item will mean re-resolving the item
* and re-evaluating the plugin/preset function.
*/
export function createConfigItem(
value:
| PluginTarget
| [PluginTarget, PluginOptions]
| [PluginTarget, PluginOptions, string | void],
{
dirname = ".",
type,
}: {
dirname?: string,
type?: "preset" | "plugin",
} = {},
): ConfigItem {
const descriptor = createDescriptor(value, path.resolve(dirname), {
type,
alias: "programmatic item",
});
return createItemFromDescriptor(descriptor);
}
export function getItemDescriptor(item: mixed): UnloadedDescriptor | void {
if (item?.[Symbol.for("@babel/core@7 - ConfigItem")] === true) {
return item._descriptor;
}
return undefined;
}
export type { ConfigItem };
/**
* A public representation of a plugin/preset that will _eventually_ be load.
* Users can use this to interact with the results of a loaded Babel
* configuration.
*
* Any changes to public properties of this class should be considered a
* breaking change to Babel's API.
*/
class ConfigItem {
/**
* The private underlying descriptor that Babel actually cares about.
* If you access this, you are a bad person.
*/
_descriptor: UnloadedDescriptor;
// TODO(Babel 8): Check if this symbol needs to be updated
/**
* Used to detect ConfigItem instances from other Babel instances.
*/
[Symbol.for("@babel/core@7 - ConfigItem")] = true;
/**
* The resolved value of the item itself.
*/
value: {} | Function;
/**
* The options, if any, that were passed to the item.
* Mutating this will lead to undefined behavior.
*
* "false" means that this item has been disabled.
*/
options: {} | void | false;
/**
* The directory that the options for this item are relative to.
*/
dirname: string;
/**
* Get the name of the plugin, if the user gave it one.
*/
name: string | void;
/**
* Data about the file that the item was loaded from, if Babel knows it.
*/
file: {
// The requested path, e.g. "@babel/env".
request: string,
// The resolved absolute path of the file.
resolved: string,
} | void;
constructor(descriptor: UnloadedDescriptor) {
// Make people less likely to stumble onto this if they are exploring
// programmatically, and also make sure that if people happen to
// pass the item through JSON.stringify, it doesn't show up.
this._descriptor = descriptor;
Object.defineProperty(this, "_descriptor", ({ enumerable: false }: any));
Object.defineProperty(this, Symbol.for("@babel/core@7 - ConfigItem"), ({
enumerable: false,
value: true
}: any));
this.value = this._descriptor.value;
this.options = this._descriptor.options;
this.dirname = this._descriptor.dirname;
this.name = this._descriptor.name;
this.file = this._descriptor.file
? {
request: this._descriptor.file.request,
resolved: this._descriptor.file.resolved,
}
: undefined;
// Freeze the object to make it clear that people shouldn't expect mutating
// this object to do anything. A new item should be created if they want
// to change something.
Object.freeze(this);
}
}
Object.freeze(ConfigItem.prototype);