mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-21 22:57:59 -04:00
feat: add pre-request script sdk
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { Property } from './object-base';
|
||||
|
||||
type AuthType = 'none' | 'apikey' | 'bearer' | 'jwt' | 'basic';
|
||||
|
||||
export class RequestAuth extends Property {
|
||||
private authType: AuthType;
|
||||
|
||||
constructor(options: { type: string }, parent?: Property) {
|
||||
super();
|
||||
this.authType = options.type as AuthType;
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
// static isValidType(type: string) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// clear(type) {
|
||||
|
||||
// }
|
||||
|
||||
// defined
|
||||
// describe(content, typeopt)
|
||||
// findInParents(property, customizeropt) → {*| undefined }
|
||||
// forEachParent(options, iterator)
|
||||
// meta() → {*}
|
||||
// parent() → {*| undefined }
|
||||
|
||||
// undefined
|
||||
// parameters() → { VariableList }
|
||||
// toJSON()
|
||||
// update(options, typeopt)
|
||||
// use(type, options)
|
||||
}
|
||||
388
packages/insomnia/src/renderers/utility-process/object-base.ts
Normal file
388
packages/insomnia/src/renderers/utility-process/object-base.ts
Normal file
@@ -0,0 +1,388 @@
|
||||
import clone from 'clone';
|
||||
import equal from 'deep-equal';
|
||||
|
||||
export interface JSONer {
|
||||
toJSON: () => object;
|
||||
}
|
||||
|
||||
export class PropertyBase {
|
||||
public kind = 'PropertyBase';
|
||||
protected description: string;
|
||||
protected _parent: PropertyBase | undefined = undefined;
|
||||
|
||||
constructor(def: { description: string }) {
|
||||
this.description = def.description;
|
||||
}
|
||||
|
||||
// static propertyIsMeta(_value: any, _key: string) {
|
||||
// // always return false because no meta is defined in Insomnia
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// static propertyUnprefixMeta(_value, _key) {
|
||||
// // no meta key is enabled
|
||||
// // so no op here
|
||||
// }
|
||||
|
||||
static toJSON(obj: JSONer) {
|
||||
return obj.toJSON();
|
||||
}
|
||||
|
||||
meta() {
|
||||
return {};
|
||||
};
|
||||
|
||||
parent() {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
forEachParent(_options: { withRoot?: boolean }, iterator: (obj: PropertyBase) => boolean) {
|
||||
const currentParent = this.parent();
|
||||
if (!currentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const queue: PropertyBase[] = [currentParent];
|
||||
const parents: PropertyBase[] = [];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const ancester = queue.shift();
|
||||
if (!ancester) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: check options
|
||||
const cloned = clone(ancester);
|
||||
const keepIterating = iterator(cloned);
|
||||
parents.push(cloned);
|
||||
if (!keepIterating) {
|
||||
break;
|
||||
}
|
||||
|
||||
const olderAncester = ancester.parent();
|
||||
if (olderAncester) {
|
||||
queue.push(olderAncester);
|
||||
}
|
||||
}
|
||||
|
||||
return parents;
|
||||
}
|
||||
|
||||
findInParents(property: string, customizer?: (ancester: PropertyBase) => boolean): PropertyBase | undefined {
|
||||
const currentParent = this.parent();
|
||||
if (!currentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const queue: PropertyBase[] = [currentParent];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const ancester = queue.shift();
|
||||
if (!ancester) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: check options
|
||||
const cloned = clone(ancester);
|
||||
const hasProperty = Object.keys(cloned.meta()).includes(property);
|
||||
if (!hasProperty) {
|
||||
// keep traversing until parent has the property
|
||||
// no op
|
||||
} else {
|
||||
if (customizer) {
|
||||
if (customizer(cloned)) {
|
||||
// continue until customizer returns a truthy value
|
||||
return cloned;
|
||||
}
|
||||
} else {
|
||||
// customizer is not specified, stop at the first parent that contains the property
|
||||
return cloned;
|
||||
}
|
||||
}
|
||||
|
||||
const olderAncester = ancester.parent();
|
||||
if (olderAncester) {
|
||||
queue.push(olderAncester);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const entriesToExport = Object
|
||||
.entries(this)
|
||||
.filter((kv: [string, any]) =>
|
||||
typeof kv[1] !== 'function' && typeof kv[1] !== 'undefined'
|
||||
);
|
||||
|
||||
return Object.fromEntries(entriesToExport);
|
||||
}
|
||||
|
||||
toObject() {
|
||||
return this.toJSON();
|
||||
}
|
||||
|
||||
toString() {
|
||||
return JSON.stringify(this.toJSON());
|
||||
}
|
||||
}
|
||||
|
||||
export class Property extends PropertyBase {
|
||||
id?: string;
|
||||
name?: string;
|
||||
disabled?: boolean;
|
||||
info?: object;
|
||||
|
||||
constructor(def?: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
disabled?: boolean;
|
||||
info?: object;
|
||||
}) {
|
||||
super({ description: 'Property' });
|
||||
this.id = def?.id || '';
|
||||
this.name = def?.name || '';
|
||||
this.disabled = def?.disabled || false;
|
||||
this.info = def?.info || {};
|
||||
}
|
||||
|
||||
// static replaceSubstitutions(_str: string, _variables: object): string {
|
||||
// // TODO: unsupported
|
||||
// return '';
|
||||
// }
|
||||
|
||||
// static replaceSubstitutionsIn(obj: string, variables: object): object {
|
||||
// // TODO: unsupported
|
||||
// return {};
|
||||
// }
|
||||
|
||||
describe(content: string, typeName: string) {
|
||||
this.kind = typeName;
|
||||
this.description = content;
|
||||
}
|
||||
}
|
||||
|
||||
export class PropertyList<T extends Property> {
|
||||
kind: string = 'PropertyList';
|
||||
protected _parent: PropertyList<T> | undefined = undefined;
|
||||
protected list: T[] = [];
|
||||
|
||||
constructor(
|
||||
// public readonly typeClass: { new(...arg: any): T },
|
||||
// public readonly parent: string,
|
||||
populate: T[],
|
||||
) {
|
||||
this.list = populate;
|
||||
}
|
||||
|
||||
static isPropertyList(obj: object) {
|
||||
return 'kind' in obj && obj.kind === 'PropertyList';
|
||||
}
|
||||
|
||||
add(item: T) {
|
||||
this.list.push(item);
|
||||
}
|
||||
|
||||
all() {
|
||||
return new Map(
|
||||
this.list.map(
|
||||
pp => [pp.id, pp.toJSON()]
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
append(item: T) {
|
||||
// it doesn't move item to the end of list for avoiding side effect
|
||||
this.add(item);
|
||||
}
|
||||
|
||||
assimilate(source: T[] | PropertyList<T>, prune?: boolean) {
|
||||
// it doesn't update values from a source list
|
||||
if (prune) {
|
||||
this.clear();
|
||||
}
|
||||
if ('list' in source) { // it is PropertyList<T>
|
||||
this.list.push(...source.list);
|
||||
} else {
|
||||
this.list.push(...source);
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.list = [];
|
||||
}
|
||||
|
||||
count() {
|
||||
return this.list.length;
|
||||
}
|
||||
|
||||
each(iterator: (item: T) => void, context: object) {
|
||||
interface Iterator {
|
||||
context?: object;
|
||||
(item: T): void;
|
||||
}
|
||||
const it: Iterator = iterator;
|
||||
it.context = context;
|
||||
|
||||
this.list.forEach(it);
|
||||
}
|
||||
|
||||
// TODO: unsupported
|
||||
// eachParent(iterator, contextopt) {}
|
||||
|
||||
filter(rule: (item: T) => boolean, context: object) {
|
||||
interface Iterator {
|
||||
context?: object;
|
||||
(item: T): boolean;
|
||||
}
|
||||
const it: Iterator = rule;
|
||||
it.context = context;
|
||||
|
||||
return this.list.filter(it);
|
||||
}
|
||||
|
||||
// TODO: support returning {Item|ItemGroup}
|
||||
find(rule: (item: T) => boolean, context?: object) {
|
||||
interface Finder {
|
||||
context?: object;
|
||||
(item: T): boolean;
|
||||
}
|
||||
const finder: Finder = rule;
|
||||
finder.context = context;
|
||||
|
||||
return this.list.find(finder);
|
||||
}
|
||||
|
||||
// it does not return underlying type of the item because they are not supported
|
||||
get(key: string) {
|
||||
return this.one(key);
|
||||
}
|
||||
|
||||
// TODO: value is not used as its usage is unknown
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
has(item: T, _value: any) {
|
||||
return this.indexOf(item) >= 0;
|
||||
}
|
||||
|
||||
idx(index: number) {
|
||||
if (index <= this.list.length - 1) {
|
||||
return this.list[index];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
indexOf(item: string | T) {
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
if (typeof item === 'string') {
|
||||
if (item === this.list[i].id) {
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
if (equal(item, this.list[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
insert(item: T, before?: number) {
|
||||
if (before && before <= this.list.length - 1) {
|
||||
this.list = [...this.list.slice(0, before), item, ...this.list.slice(before)];
|
||||
} else {
|
||||
this.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
insertAfter(item: T, after?: number) {
|
||||
if (after && after <= this.list.length - 1) {
|
||||
this.list = [...this.list.slice(0, after + 1), item, ...this.list.slice(after + 1)];
|
||||
} else {
|
||||
this.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
map(iterator: (item: T) => any, context: object) {
|
||||
interface Iterator {
|
||||
context?: object;
|
||||
(item: T): any;
|
||||
}
|
||||
const it: Iterator = iterator;
|
||||
it.context = context;
|
||||
|
||||
return this.list.map(it);
|
||||
}
|
||||
|
||||
one(id: string) {
|
||||
for (let i = this.list.length - 1; i >= 0; i--) {
|
||||
if (this.list[i].id === id) {
|
||||
return this.list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
populate(items: T[]) {
|
||||
this.list = [...this.list, ...items];
|
||||
}
|
||||
|
||||
prepend(item: T) {
|
||||
this.list = [item, ...this.list];
|
||||
}
|
||||
|
||||
reduce(iterator: ((acc: any, item: T) => any), accumulator: any, context: object) {
|
||||
interface Iterator {
|
||||
context?: object;
|
||||
(acc: any, item: T): any;
|
||||
}
|
||||
const it: Iterator = iterator;
|
||||
it.context = context;
|
||||
|
||||
this.list.reduce(it, accumulator);
|
||||
}
|
||||
|
||||
remove(predicate: T | ((item: T) => boolean), context: object) {
|
||||
if (typeof predicate === 'function') {
|
||||
this.list = this.filter(predicate, context);
|
||||
} else {
|
||||
this.list = this.filter(item => equal(predicate, item), context);
|
||||
}
|
||||
}
|
||||
|
||||
repopulate(items: T[]) {
|
||||
this.clear();
|
||||
this.populate(items);
|
||||
}
|
||||
|
||||
// unsupportd as _postman_propertyIndexKey is not supported
|
||||
// toObject(excludeDisabled?: boolean, caseSensitive?: boolean, multiValue?: boolean, sanitizeKeys?: boolean) {
|
||||
// const itemObjects = this.list
|
||||
// .filter(item => {
|
||||
// if (excludeDisabled) {
|
||||
// return !item.disabled;
|
||||
// }
|
||||
// return true;
|
||||
// })
|
||||
// .map(item => {
|
||||
// return item.toJSON();
|
||||
// });
|
||||
// }
|
||||
|
||||
toString() {
|
||||
const itemStrs = this.list.map(item => item.toString());
|
||||
return `[${itemStrs.join(',')}]`;
|
||||
}
|
||||
|
||||
upsert(item: T): boolean {
|
||||
const itemIdx = this.indexOf(item);
|
||||
if (itemIdx >= 0) {
|
||||
this.list = [...this.list.splice(0, itemIdx), item, ...this.list.splice(itemIdx + 1)];
|
||||
return false;
|
||||
}
|
||||
|
||||
this.add(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import { Property, PropertyList } from './object-base';
|
||||
|
||||
export interface CookieDef {
|
||||
key: string;
|
||||
value: string;
|
||||
expires?: Date | string;
|
||||
maxAge?: Number;
|
||||
domain?: string;
|
||||
path?: string;
|
||||
secure?: Boolean;
|
||||
httpOnly?: Boolean;
|
||||
hostOnly?: Boolean;
|
||||
session?: Boolean;
|
||||
extensions?: { key: string; value: string }[];
|
||||
}
|
||||
|
||||
export class Cookie extends Property {
|
||||
private def: object;
|
||||
|
||||
constructor(cookieDef: CookieDef | string) {
|
||||
super();
|
||||
this.kind = 'Cookie';
|
||||
this.description = 'Cookie';
|
||||
|
||||
if (typeof cookieDef === 'string') {
|
||||
this.def = Cookie.parse(cookieDef);
|
||||
} else {
|
||||
this.def = cookieDef;
|
||||
}
|
||||
}
|
||||
|
||||
static isCookie(obj: Property) {
|
||||
return obj.kind === 'Cookie';
|
||||
}
|
||||
|
||||
static parse(cookieStr: string) {
|
||||
const parts = cookieStr.split(';');
|
||||
|
||||
const def: CookieDef = { key: '', value: '' };
|
||||
const extensions: { key: string; value: string }[] = [];
|
||||
|
||||
parts.forEach((part, i) => {
|
||||
const kvParts = part.split('=');
|
||||
const key = kvParts[0];
|
||||
|
||||
if (i === 0) {
|
||||
const value = kvParts.length > 1 ? kvParts[1] : '';
|
||||
def.key, def.value = key, value;
|
||||
} else {
|
||||
switch (key) {
|
||||
case 'Expires':
|
||||
// TODO: it should be timestamp
|
||||
const expireVal = kvParts.length > 1 ? kvParts[1] : '0';
|
||||
def.expires = expireVal;
|
||||
break;
|
||||
case 'Max-Age':
|
||||
let maxAgeVal = 0;
|
||||
if (kvParts.length > 1) {
|
||||
maxAgeVal = parseInt(kvParts[1], 10);
|
||||
}
|
||||
def.maxAge = maxAgeVal;
|
||||
break;
|
||||
case 'Domain':
|
||||
const domainVal = kvParts.length > 1 ? kvParts[1] : '';
|
||||
def.domain = domainVal;
|
||||
break;
|
||||
case 'Path':
|
||||
const pathVal = kvParts.length > 1 ? kvParts[1] : '';
|
||||
def.path = pathVal;
|
||||
break;
|
||||
case 'Secure':
|
||||
def.secure = true;
|
||||
break;
|
||||
case 'HttpOnly':
|
||||
def.httpOnly = true;
|
||||
break;
|
||||
case 'HostOnly':
|
||||
def.hostOnly = true;
|
||||
break;
|
||||
case 'Session':
|
||||
def.session = true;
|
||||
break;
|
||||
default:
|
||||
const value = kvParts.length > 1 ? kvParts[1] : '';
|
||||
extensions.push({ key, value });
|
||||
def.extensions = extensions;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
static stringify(cookie: Cookie) {
|
||||
return cookie.toString();
|
||||
}
|
||||
|
||||
static unparseSingle(cookie: Cookie) {
|
||||
return cookie.toString();
|
||||
}
|
||||
|
||||
// TODO: support PropertyList
|
||||
static unparse(cookies: Cookie[]) {
|
||||
const cookieStrs = cookies.map(cookie => cookie.toString());
|
||||
return cookieStrs.join(';');
|
||||
}
|
||||
|
||||
toString = () => {
|
||||
// Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
|
||||
const cookieDef = this.def as CookieDef;
|
||||
const kvPair = `${cookieDef.key}=${cookieDef.value};`;
|
||||
const expires = cookieDef.expires ? `Expires=${cookieDef.expires?.toString()};` : '';
|
||||
const maxAge = cookieDef.maxAge ? `Max-Age=${cookieDef.maxAge};` : '';
|
||||
const domain = cookieDef.domain ? `Domain=${cookieDef.domain};` : '';
|
||||
const path = cookieDef.path ? `Path=${cookieDef.path};` : '';
|
||||
const secure = cookieDef.secure ? 'Secure;' : '';
|
||||
const httpOnly = cookieDef.httpOnly ? 'HttpOnly;' : '';
|
||||
// TODO: SameSite, Partitioned is not suported
|
||||
|
||||
const hostOnly = cookieDef.hostOnly ? 'HostOnly;' : '';
|
||||
const session = cookieDef.session ? 'Session;' : '';
|
||||
|
||||
// TODO: extension key may be conflict with pre-defined keys
|
||||
const extensions = cookieDef.extensions ?
|
||||
cookieDef.extensions
|
||||
.map((kv: { key: string; value: string }) => `${kv.key}=${kv.value}`)
|
||||
.join(';') : ''; // the last field doesn't have ';'
|
||||
|
||||
return `${kvPair} ${expires} ${maxAge} ${domain} ${path} ${secure} ${httpOnly} ${hostOnly} ${session} ${extensions}`;
|
||||
};
|
||||
|
||||
valueOf = () => {
|
||||
return (this.def as CookieDef).value;
|
||||
};
|
||||
}
|
||||
|
||||
export class CookieList extends PropertyList<Cookie> {
|
||||
kind: string = 'CookieList';
|
||||
cookies: Cookie[];
|
||||
|
||||
constructor(parent: CookieList, cookies: Cookie[]) {
|
||||
super(
|
||||
// Cookie, parent.toString()
|
||||
cookies
|
||||
);
|
||||
this._parent = parent;
|
||||
this.cookies = cookies;
|
||||
}
|
||||
|
||||
static isCookieList(obj: object) {
|
||||
return 'kind' in obj && obj.kind === 'CookieList';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import { Property, PropertyList } from './object-base';
|
||||
|
||||
export class Header extends Property {
|
||||
kind: string = 'Header';
|
||||
type: string = '';
|
||||
key: string;
|
||||
value: string;
|
||||
|
||||
constructor(
|
||||
opts: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
disabled?: boolean;
|
||||
key: string;
|
||||
value: string;
|
||||
} | string,
|
||||
name?: string, // if it is defined, it overrides 'key' (not 'name')
|
||||
) {
|
||||
super();
|
||||
|
||||
if (typeof opts === 'string') {
|
||||
const obj = Header.parseSingle(opts);
|
||||
this.key = obj.key;
|
||||
this.value = obj.value;
|
||||
} else {
|
||||
this.id = opts.id ? opts.id : '';
|
||||
this.key = opts.key ? opts.key : '';
|
||||
this.name = name ? name : (opts.name ? opts.name : '');
|
||||
this.value = opts.value ? opts.value : '';
|
||||
this.type = opts.type ? opts.type : '';
|
||||
this.disabled = opts ? opts.disabled : false;
|
||||
}
|
||||
}
|
||||
|
||||
static create(input?: { key: string; value: string } | string, name?: string): Header {
|
||||
return new Header(input || { key: '', value: '' }, name);
|
||||
}
|
||||
|
||||
static isHeader(obj: object) {
|
||||
return 'kind' in obj && obj.kind === 'Header';
|
||||
}
|
||||
|
||||
// example: 'Content-Type: application/json\nUser-Agent: MyClientLibrary/2.0\n'
|
||||
static parse(headerString: string): { key: string; value: string }[] {
|
||||
return headerString
|
||||
.split('\n')
|
||||
.map(kvPart => Header.parseSingle(kvPart));
|
||||
}
|
||||
|
||||
static parseSingle(headerStr: string): { key: string; value: string } {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
|
||||
// the first colon is the separator
|
||||
const separatorPos = headerStr.indexOf(':');
|
||||
const key = headerStr.slice(0, separatorPos);
|
||||
const value = headerStr.slice(separatorPos + 1);
|
||||
|
||||
return { key, value };
|
||||
}
|
||||
|
||||
static unparse(headers: { key: string; value: string }[] | PropertyList<Header>, separator?: string): string {
|
||||
const headerStrs = headers.map(
|
||||
header => this.unparseSingle(header), {}
|
||||
);
|
||||
|
||||
return headerStrs.join(separator || '\n');
|
||||
}
|
||||
|
||||
static unparseSingle(header: { key: string; value: string } | Header): string {
|
||||
// both PropertyList and object contains 'key' and 'value'
|
||||
return `${header.key}: ${header.value}`;
|
||||
}
|
||||
|
||||
update(newHeader: { key: string; value: string }) {
|
||||
this.key = newHeader.key;
|
||||
this.value = newHeader.value;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
export class HeaderList<T extends Header> extends PropertyList<T> {
|
||||
constructor(parent: PropertyList<T> | undefined, populate: T[]) {
|
||||
super(populate);
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
static isHeaderList(obj: any) {
|
||||
return 'kind' in obj && obj.kind === 'HeaderList';
|
||||
}
|
||||
|
||||
// unsupported
|
||||
// eachParent(iterator, contextopt)
|
||||
// toObject(excludeDisabledopt, nullable, caseSensitiveopt, nullable, multiValueopt, nullable, sanitizeKeysopt) → {Object}
|
||||
|
||||
contentSize(): number {
|
||||
return this.list
|
||||
.map(header => header.toString())
|
||||
.map(headerStr => headerStr.length) // TODO: handle special characters
|
||||
.reduce((totalSize, headerSize) => totalSize + headerSize, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import { Property, PropertyList } from './object-base';
|
||||
|
||||
export class ProxyConfig extends Property {
|
||||
kind: string = 'ProxyConfig';
|
||||
type: string;
|
||||
|
||||
host: string;
|
||||
match: string;
|
||||
port: number;
|
||||
tunnel: boolean;
|
||||
authenticate: boolean;
|
||||
username: string;
|
||||
password: string;
|
||||
|
||||
static authenticate: boolean;
|
||||
// static bypass: UrlMatchPatternList;
|
||||
static host: string;
|
||||
static match: string;
|
||||
static password: string;
|
||||
static port: number;
|
||||
static tunnel: boolean; // unsupported
|
||||
static username: string;
|
||||
|
||||
static {
|
||||
ProxyConfig.authenticate = false;
|
||||
// ProxyConfig.bypass: UrlMatchPatternList;
|
||||
ProxyConfig.host = '';
|
||||
ProxyConfig.match = '';
|
||||
ProxyConfig.password = '';
|
||||
ProxyConfig.port = 0;
|
||||
ProxyConfig.tunnel = false;
|
||||
ProxyConfig.username = '';
|
||||
}
|
||||
|
||||
constructor(def: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
disabled?: boolean;
|
||||
|
||||
host: string;
|
||||
match: string;
|
||||
port: number;
|
||||
tunnel: boolean;
|
||||
authenticate: boolean;
|
||||
username: string;
|
||||
password: string;
|
||||
|
||||
}) {
|
||||
super();
|
||||
|
||||
this.id = def.id ? def.id : '';
|
||||
this.name = def.name ? def.name : '';
|
||||
this.type = def.type ? def.type : '';
|
||||
this.disabled = def.disabled ? def.disabled : false;
|
||||
|
||||
this.host = def.host;
|
||||
this.match = def.match;
|
||||
this.port = def.port;
|
||||
this.tunnel = def.tunnel;
|
||||
this.authenticate = def.authenticate;
|
||||
this.username = def.username;
|
||||
this.password = def.password;
|
||||
}
|
||||
|
||||
static isProxyConfig(obj: object) {
|
||||
return 'kind' in obj && obj.kind === 'ProxyConfig';
|
||||
}
|
||||
|
||||
// TODO: should not read from match?
|
||||
getProtocols(): string[] {
|
||||
// match field example: 'http+https://example.com/*'
|
||||
const protoSeparator = this.match.indexOf('://');
|
||||
if (protoSeparator <= 0 || protoSeparator >= this.match.length) {
|
||||
return []; // invalid match value
|
||||
}
|
||||
|
||||
return this.match
|
||||
.slice(0, protoSeparator)
|
||||
.split('+');
|
||||
}
|
||||
|
||||
getProxyUrl(): string {
|
||||
const protos = this.getProtocols();
|
||||
// TODO: how to pick up a protocol?
|
||||
if (protos.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// http://proxy_username:proxy_password@proxy.com:8080
|
||||
if (this.authenticate) {
|
||||
return `protos[0]://${this.username}:${this.password}@${this.host}:${this.port}`;
|
||||
}
|
||||
return `protos[0]://${this.host}:${this.port}`;
|
||||
}
|
||||
|
||||
// TODO: unsupported yet
|
||||
// test(urlStropt)
|
||||
|
||||
update(options: {
|
||||
host: string;
|
||||
match: string;
|
||||
port: number;
|
||||
tunnel: boolean;
|
||||
authenticate: boolean;
|
||||
username: string;
|
||||
password: string;
|
||||
}) {
|
||||
this.host = options.host;
|
||||
this.match = options.match;
|
||||
this.port = options.port;
|
||||
this.tunnel = options.tunnel;
|
||||
this.authenticate = options.authenticate;
|
||||
this.username = options.username;
|
||||
this.password = options.password;
|
||||
}
|
||||
|
||||
updateProtocols(protocols: string[]) {
|
||||
const protoSeparator = this.match.indexOf('://');
|
||||
if (protoSeparator <= 0 || protoSeparator >= this.match.length) {
|
||||
return; // invalid match value
|
||||
}
|
||||
|
||||
this.match = protocols.join('+') + this.match.slice(protoSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
// myProxyConfig = new ProxyConfigList({}, [
|
||||
// {match: 'https://example.com/*', host: 'proxy.com', port: 8080, tunnel: true},
|
||||
// {match: 'http+https://example2.com/*', host: 'proxy2.com'},
|
||||
// ]);
|
||||
|
||||
export class ProxyConfigList<T extends ProxyConfig> extends PropertyList<T> {
|
||||
constructor(parent: PropertyList<T> | undefined, populate: T[]) {
|
||||
super(populate);
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
static isProxyConfigList(obj: any) {
|
||||
return 'kind' in obj && obj.kind === 'ProxyConfigList';
|
||||
}
|
||||
|
||||
// TODO: need support URL at first
|
||||
// resolve(url?: URL) {
|
||||
// return {
|
||||
// host: string;
|
||||
// match: string;
|
||||
// port: number;
|
||||
// tunnel: boolean;
|
||||
// authenticate: boolean;
|
||||
// username: string;
|
||||
// password: string;
|
||||
// }
|
||||
// }
|
||||
|
||||
// toObject(excludeDisabledopt, nullable, caseSensitiveopt, nullable, multiValueopt, nullable, sanitizeKeysopt) → {Object}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { Property, PropertyList } from './object-base';
|
||||
|
||||
export class Variable extends Property {
|
||||
key: string;
|
||||
value: any;
|
||||
type: string;
|
||||
kind: string = 'Variable';
|
||||
|
||||
constructor(def?: {
|
||||
id: string;
|
||||
key: string;
|
||||
name: string;
|
||||
value: string;
|
||||
type: string;
|
||||
disabled: boolean;
|
||||
}) {
|
||||
super();
|
||||
|
||||
this.id = def ? def.id : '';
|
||||
this.key = def ? def.key : '';
|
||||
this.name = def ? def.name : '';
|
||||
this.value = def ? def.value : '';
|
||||
this.type = def ? def.type : '';
|
||||
this.disabled = def ? def.disabled : false;
|
||||
}
|
||||
|
||||
// unknown usage and unsupported
|
||||
// static readonly types() => {
|
||||
// }
|
||||
|
||||
// cast typecasts a value to the Variable.types of this Variable.
|
||||
cast(value: any) {
|
||||
if ('kind' in value && value.kind === 'Variable') {
|
||||
return value.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
set(value: any) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
export class VariableList<T extends Variable> extends PropertyList<T> {
|
||||
constructor(parent: PropertyList<T> | undefined, populate: T[]) {
|
||||
super(populate);
|
||||
this._parent = parent;
|
||||
}
|
||||
|
||||
static isVariableList(obj: any) {
|
||||
return 'kind' in obj && obj.kind === 'VariableList';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user