-
-
Notifications
You must be signed in to change notification settings - Fork 132
/
types.ts
220 lines (201 loc) · 5.39 KB
/
types.ts
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import { validate } from "./fastidious/index";
/**
* Finicky Configuration Reference.
*/
/**
* This represents the full `.finicky.js` `module.exports` object.
*
* Example:
*
* ```js
* module.exports = {
* defaultBrowser: "Google Chrome",
* options: {
* hideIcon: false
* },
* handlers: [{
* match: finicky.matchHostnames("example.com'),
* browser: "Firefox"
* }]
* }
* ```
*/
export interface FinickyConfig {
/** The default browser or app to open for urls where no other handler
* matches.
*/
defaultBrowser: Browser | BrowserFunction | Array<Browser | BrowserFunction>;
options?: {
/** Whether or not to hide the finicky icon in the menu bar */
hideIcon?: boolean;
/** An array of domain names to replace the built in list of url
* shortener domains. Note that using this option replaces the list
* completely.
*
* Example:
* ```js
* module.exports = {
* options: {
* urlShorteners: ["another-url-shortener-service.com"]
* }
* }
* ```
*/
urlShorteners?: string[];
};
/** An array of Rewriters that can change the url being opened */
rewrite?: Rewriter[];
/** An array of Handlers to select which browser to open for urls */
handlers?: Handler[];
}
export type BrowserResult =
| Browser
| BrowserFunction
| Array<Browser | BrowserFunction>;
/**
* A handler contains a matcher and a browser. If the matcher matches when opening a url, the browser in the handler will be opened.
*/
export interface Handler {
match: Matcher | Matcher[];
browser: BrowserResult;
}
/**
* A rewriter contains a matcher and a url. If the matcher matches when opening a url, the final url will be changed to whatever the url property is.
*/
export interface Rewriter {
match: Matcher | Matcher[];
url: Url | UrlFunction;
}
/**
* Matches urls (or other properties) to decide if to change the url or open a browser.
*
* If the matcher is a string, if the url equals the string exactly, it will match.
* If the matcher is a regular expression, if it matches any part of the url, it will match.
* If the matcher is a [[MatcherFunction]], it will match if the function returns `true`
*
*/
export type Matcher = string | RegExp | MatcherFunction;
export type MatcherFunction = (options: Options) => boolean;
/**
* Represents a browser or app that finicky could start
*/
export type Browser = string | BrowserObject;
/**
* Represents a browser or app to open
*/
export interface BrowserObject {
name: string;
appType?: "appName" | "bundleId" | "none";
openInBackground?: boolean;
}
/**
* A function that returns a browser to open
*/
type BrowserFunction = (options: Options) => Browser;
/**
* Represents a url that will be handled by finicky
*/
export type Url = string | UrlObject;
/**
* An object that represents a url
*/
export interface UrlObject {
protocol: string;
username?: string;
password?: string;
host: string;
port?: number;
pathname?: string;
search?: string;
hash?: string;
}
/**
* A function that returns a url
*/
export type UrlFunction = (options: Options) => Url;
/**
* Options sent as the argument to [[ProcessUrl]]
*/
export interface ProcessOptions {
/** If opened in from an app, this string contains the bundle identifier from that app */
sourceBundleIdentifier?: string;
/** The state of keyboard state. E.g. shift === true if pressed. */
keys: {
shift: boolean;
option: boolean;
command: boolean;
control: boolean;
capsLock: boolean;
function: boolean;
};
}
/**
* Options sent as the argument to [[MatcherFunction]], [[BrowserFunction]] and [[UrlFunction]]
*/
export interface Options extends ProcessOptions {
/** The url being opened */
urlString: string;
/** The url being opened as an object */
url: UrlObject;
}
export const urlSchema = {
url: validate.oneOf([
validate.string,
validate.shape({
protocol: validate.string.isRequired,
username: validate.string,
password: validate.string,
host: validate.string.isRequired,
port: validate.oneOf([validate.number, validate.value(null)]),
pathname: validate.string,
search: validate.string,
hash: validate.string
})
]).isRequired
};
const browserSchema = validate.oneOf([
validate.string,
validate.shape({
name: validate.string.isRequired,
appType: validate.oneOf(["appName", "bundleId"]),
openInBackground: validate.boolean
}),
validate.function("options"),
validate.value(null)
]);
const multipleBrowsersSchema = validate.oneOf([
browserSchema,
validate.arrayOf(browserSchema.isRequired)
]);
const matchSchema = validate.oneOf([
validate.string,
validate.function("options"),
validate.regex,
validate.arrayOf(
validate.oneOf([
validate.string,
validate.function("options"),
validate.regex
])
)
]);
export const finickyConfigSchema = {
defaultBrowser: multipleBrowsersSchema.isRequired,
options: validate.shape({
hideIcon: validate.boolean,
urlShorteners: validate.arrayOf(validate.string)
}),
rewrite: validate.arrayOf(
validate.shape({
match: matchSchema.isRequired,
url: validate.oneOf([validate.string, validate.function("options")])
.isRequired
}).isRequired
),
handlers: validate.arrayOf(
validate.shape({
match: matchSchema.isRequired,
browser: multipleBrowsersSchema.isRequired
})
)
};