@stuntman/server 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/api/api.d.ts +25 -0
- package/dist/api/api.d.ts.map +1 -0
- package/dist/api/api.js +212 -0
- package/dist/api/api.js.map +1 -0
- package/dist/api/utils.d.ts +5 -0
- package/dist/api/utils.d.ts.map +1 -0
- package/dist/api/utils.js +61 -0
- package/dist/api/utils.js.map +1 -0
- package/dist/api/validators.d.ts +4 -0
- package/dist/api/validators.d.ts.map +1 -0
- package/dist/api/validators.js +125 -0
- package/dist/api/validators.js.map +1 -0
- package/dist/api/webgui/rules.pug +147 -0
- package/dist/api/webgui/style.css +28 -0
- package/dist/api/webgui/traffic.pug +38 -0
- package/dist/bin/stuntman.d.ts +3 -0
- package/dist/bin/stuntman.d.ts.map +1 -0
- package/dist/bin/stuntman.js +8 -0
- package/dist/bin/stuntman.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/ipUtils.d.ts +18 -0
- package/dist/ipUtils.d.ts.map +1 -0
- package/dist/ipUtils.js +102 -0
- package/dist/ipUtils.js.map +1 -0
- package/dist/mock.d.ts +32 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +306 -0
- package/dist/mock.js.map +1 -0
- package/dist/requestContext.d.ts +10 -0
- package/dist/requestContext.d.ts.map +1 -0
- package/dist/requestContext.js +19 -0
- package/dist/requestContext.js.map +1 -0
- package/dist/ruleExecutor.d.ts +23 -0
- package/dist/ruleExecutor.d.ts.map +1 -0
- package/dist/ruleExecutor.js +189 -0
- package/dist/ruleExecutor.js.map +1 -0
- package/dist/rules/catchAll.d.ts +3 -0
- package/dist/rules/catchAll.d.ts.map +1 -0
- package/dist/rules/catchAll.js +16 -0
- package/dist/rules/catchAll.js.map +1 -0
- package/dist/rules/echo.d.ts +3 -0
- package/dist/rules/echo.d.ts.map +1 -0
- package/dist/rules/echo.js +16 -0
- package/dist/rules/echo.js.map +1 -0
- package/dist/rules/index.d.ts +4 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +71 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/storage.d.ts +5 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +43 -0
- package/dist/storage.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
doctype html
|
|
2
|
+
html
|
|
3
|
+
head
|
|
4
|
+
title Stuntman - rule editor
|
|
5
|
+
script(src='https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.35.0/min/vs/loader.min.js')
|
|
6
|
+
style
|
|
7
|
+
include style.css
|
|
8
|
+
body(style='color: rgb(204, 204, 204); background-color: rgb(50, 50, 50)')
|
|
9
|
+
button#newRule(type='button', onclick='window.newRule()') New rule
|
|
10
|
+
button#saveRule(type='button', onclick='window.saveRule()', disabled) Save rule
|
|
11
|
+
div(style='width: 100%; overflow: hidden')
|
|
12
|
+
div(style='width: 230px; float: left')
|
|
13
|
+
h3 Rules
|
|
14
|
+
ul#ruleKeys.no-bullets
|
|
15
|
+
each ruleId in ruleKeys
|
|
16
|
+
li
|
|
17
|
+
button.rule(
|
|
18
|
+
type='button',
|
|
19
|
+
onclick='window.setRuleModel(this.getAttribute("data-rule-id"))',
|
|
20
|
+
data-rule-id=ruleId
|
|
21
|
+
)= ruleId
|
|
22
|
+
div(style='margin-left: 240px')
|
|
23
|
+
#container(style='height: 400px')
|
|
24
|
+
script.
|
|
25
|
+
/* eslint no-undef: 0 */
|
|
26
|
+
const uuidv4 = () => {
|
|
27
|
+
function getRandomSymbol(symbol) {
|
|
28
|
+
var array;
|
|
29
|
+
|
|
30
|
+
if (symbol === 'y') {
|
|
31
|
+
array = ['8', '9', 'a', 'b'];
|
|
32
|
+
return array[Math.floor(Math.random() * array.length)];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
array = new Uint8Array(1);
|
|
36
|
+
window.crypto.getRandomValues(array);
|
|
37
|
+
return (array[0] % 16).toString(16);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, getRandomSymbol);
|
|
41
|
+
};
|
|
42
|
+
require.config({
|
|
43
|
+
paths: {
|
|
44
|
+
vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.35.0/min/vs',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
require(['vs/editor/editor.main'], function () {
|
|
48
|
+
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
|
|
49
|
+
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
|
50
|
+
noSemanticValidation: false,
|
|
51
|
+
noSyntaxValidation: false,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// compiler options
|
|
55
|
+
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
|
56
|
+
target: monaco.languages.typescript.ScriptTarget.ES6,
|
|
57
|
+
allowNonTsExtensions: true,
|
|
58
|
+
noLib: true,
|
|
59
|
+
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
|
60
|
+
module: monaco.languages.typescript.ModuleKind.CommonJS,
|
|
61
|
+
noEmit: true,
|
|
62
|
+
checkJs: true,
|
|
63
|
+
allowJs: true,
|
|
64
|
+
isolatedModules: true,
|
|
65
|
+
typeRoots: ['node_modules/@types'],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
monaco.languages.typescript.typescriptDefaults.addExtraLib(`!{INDEX_DTS}`, 'file:///node_modules/@types/stuntman/index.d.ts');
|
|
69
|
+
const models = {};
|
|
70
|
+
const rules = eval('(!{rules})');
|
|
71
|
+
for (const ruleId of Object.keys(rules)) {
|
|
72
|
+
models[ruleId] = monaco.editor.createModel("import type * as Stuntman from 'stuntman';\n\nvar STUNTMAN_RULE: Stuntman.Rule = " + rules[ruleId] + ';', 'typescript', `file:///${ruleId}.ts`);
|
|
73
|
+
}
|
|
74
|
+
const editor = monaco.editor.create(document.getElementById('container'), {
|
|
75
|
+
theme: 'vs-dark',
|
|
76
|
+
formatOnPaste: true,
|
|
77
|
+
formatOnType: true,
|
|
78
|
+
automaticLayout: true,
|
|
79
|
+
autoIndent: true,
|
|
80
|
+
tabSize: 2,
|
|
81
|
+
});
|
|
82
|
+
editor.onDidChangeModel((event) => {
|
|
83
|
+
const isInternal = /^file:\/\/\/internal\/.+/.test(event.newModelUrl);
|
|
84
|
+
if (isInternal) {
|
|
85
|
+
document.getElementById('saveRule').setAttribute('disabled', 'true');
|
|
86
|
+
} else {
|
|
87
|
+
document.getElementById('saveRule').removeAttribute('disabled');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
editor.getAction('editor.action.formatDocument').run();
|
|
92
|
+
}, 100);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
window.setRuleModel = (ruleId) => {
|
|
96
|
+
if (history.pushState) {
|
|
97
|
+
const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}?ruleId=${encodeURIComponent(ruleId)}`;
|
|
98
|
+
window.history.pushState({ path: newUrl }, '', newUrl);
|
|
99
|
+
}
|
|
100
|
+
editor.setModel(models[ruleId]);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
104
|
+
if (urlSearchParams.has('ruleId') && urlSearchParams.get('ruleId') in models) {
|
|
105
|
+
editor.setModel(models[urlSearchParams.get('ruleId')]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
window.saveRule = () => {
|
|
109
|
+
document.getElementById('saveRule').setAttribute('disabled', 'true');
|
|
110
|
+
const modelUri = editor.getModel().uri;
|
|
111
|
+
const result = monaco.languages.typescript.getTypeScriptWorker();
|
|
112
|
+
result.then((worker) => {
|
|
113
|
+
worker(modelUri).then(function (client) {
|
|
114
|
+
client.getEmitOutput(modelUri.toString()).then((output) => {
|
|
115
|
+
const ruleFunctionText = output.outputFiles[0].text.replace(/^export .+$/im, '');
|
|
116
|
+
const newId = new Function(ruleFunctionText + '\n return STUNTMAN_RULE;')().id;
|
|
117
|
+
fetch('/webgui/rules/unsafesave', {
|
|
118
|
+
method: 'POST',
|
|
119
|
+
headers: { 'content-type': 'text/plain' },
|
|
120
|
+
body: ruleFunctionText + '\n return STUNTMAN_RULE;',
|
|
121
|
+
}).then((response) => {
|
|
122
|
+
if (response.ok) {
|
|
123
|
+
const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}?ruleId=${encodeURIComponent(newId)}`;
|
|
124
|
+
window.history.pushState({ path: newUrl }, '', newUrl);
|
|
125
|
+
window.location.reload();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
alert('Error when saving rule');
|
|
129
|
+
document.getElementById('saveRule').removeAttribute('disabled');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
window.newRule = () => {
|
|
137
|
+
const ruleId = uuidv4();
|
|
138
|
+
const emptyRule = `import type * as Stuntman from 'stuntman';\n\nvar STUNTMAN_RULE: Stuntman.Rule = { id: '${ruleId}', matches: (req: Stuntman.Request) => true, ttlSeconds: 600, actions: { mockResponse: { status: '200', body: '${ruleId}' }} };`;
|
|
139
|
+
models[ruleId] = monaco.editor.createModel(emptyRule, 'typescript', `file:///${ruleId}.ts`);
|
|
140
|
+
const ruleKeyNode = document.getElementById('ruleKeys').firstChild;
|
|
141
|
+
const ruleKeyNodeClone = ruleKeyNode.cloneNode(true);
|
|
142
|
+
ruleKeyNodeClone.getElementsByTagName('button')[0].setAttribute('data-rule-id', ruleId);
|
|
143
|
+
ruleKeyNodeClone.getElementsByTagName('button')[0].innerText = ruleId;
|
|
144
|
+
document.getElementById('ruleKeys').appendChild(ruleKeyNodeClone);
|
|
145
|
+
window.setRuleModel(ruleId);
|
|
146
|
+
};
|
|
147
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
div#container {
|
|
2
|
+
resize: vertical;
|
|
3
|
+
overflow: auto;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
body {
|
|
7
|
+
font-family: Menlo, Monaco, 'Courier New', monospace;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
button.rule {
|
|
11
|
+
font-family: Menlo, Monaco, 'Courier New', monospace;
|
|
12
|
+
background: none !important;
|
|
13
|
+
border: none;
|
|
14
|
+
padding: 0 !important;
|
|
15
|
+
color: #aaa;
|
|
16
|
+
text-decoration: underline;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
margin-top: 10px;
|
|
19
|
+
font-size: x-small;
|
|
20
|
+
text-align: left;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
ul.no-bullets {
|
|
24
|
+
list-style-type: none;
|
|
25
|
+
padding: 0;
|
|
26
|
+
margin: 0;
|
|
27
|
+
text-align: left;
|
|
28
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
doctype html
|
|
2
|
+
html
|
|
3
|
+
head
|
|
4
|
+
title Stuntman - rule editor
|
|
5
|
+
script(src='https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.35.0/min/vs/loader.min.js')
|
|
6
|
+
style
|
|
7
|
+
include style.css
|
|
8
|
+
body(style='color: rgb(204, 204, 204); background-color: rgb(50, 50, 50)')
|
|
9
|
+
div(style='width: 100%; overflow: hidden')
|
|
10
|
+
div(style='width: 200px; float: left')
|
|
11
|
+
h3 Traffic log
|
|
12
|
+
div(style='margin-left: 220px')
|
|
13
|
+
#container(style='height: 800px')
|
|
14
|
+
script.
|
|
15
|
+
/* eslint no-undef: 0 */
|
|
16
|
+
require.config({
|
|
17
|
+
paths: {
|
|
18
|
+
vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.35.0/min/vs',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
require(['vs/editor/editor.main'], function () {
|
|
22
|
+
const traffic = !{ traffic };
|
|
23
|
+
const model = monaco.editor.createModel(JSON.stringify(traffic, null, 2), 'json');
|
|
24
|
+
const editor = monaco.editor.create(document.getElementById('container'), {
|
|
25
|
+
theme: 'vs-dark',
|
|
26
|
+
autoIndent: true,
|
|
27
|
+
formatOnPaste: true,
|
|
28
|
+
formatOnType: true,
|
|
29
|
+
automaticLayout: true,
|
|
30
|
+
readOnly: true,
|
|
31
|
+
});
|
|
32
|
+
editor.onDidChangeModel((event) => {
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
editor.getAction('editor.action.formatDocument').run();
|
|
35
|
+
}, 100);
|
|
36
|
+
});
|
|
37
|
+
editor.setModel(model);
|
|
38
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuntman.d.ts","sourceRoot":"","sources":["../../src/bin/stuntman.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const mock_1 = require("../mock");
|
|
5
|
+
const shared_1 = require("@stuntman/shared");
|
|
6
|
+
const mock = new mock_1.Mock(shared_1.stuntmanConfig);
|
|
7
|
+
mock.start();
|
|
8
|
+
//# sourceMappingURL=stuntman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuntman.js","sourceRoot":"","sources":["../../src/bin/stuntman.ts"],"names":[],"mappings":";;;AAEA,kCAA+B;AAC/B,6CAAkD;AAElD,MAAM,IAAI,GAAG,IAAI,WAAI,CAAC,uBAAc,CAAC,CAAC;AAEtC,IAAI,CAAC,KAAK,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StuntmanMock = void 0;
|
|
4
|
+
var mock_1 = require("./mock");
|
|
5
|
+
Object.defineProperty(exports, "StuntmanMock", { enumerable: true, get: function () { return mock_1.Mock; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+BAA8C;AAArC,oGAAA,IAAI,OAAgB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import dns from 'node:dns';
|
|
3
|
+
export declare class IPUtils {
|
|
4
|
+
protected dnsResolutionCache: import("lru-cache")<string, string>;
|
|
5
|
+
protected mockUuid: string;
|
|
6
|
+
externalDns: dns.Resolver | null;
|
|
7
|
+
constructor(options: {
|
|
8
|
+
mockUuid: string;
|
|
9
|
+
externalDns?: string[];
|
|
10
|
+
});
|
|
11
|
+
isLocalhostIP(ip: string): boolean;
|
|
12
|
+
private resolveIPs;
|
|
13
|
+
resolveIP(hostname: string, options?: {
|
|
14
|
+
useExternalDns?: true;
|
|
15
|
+
}): Promise<string>;
|
|
16
|
+
isIP(hostname: string): boolean;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=ipUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipUtils.d.ts","sourceRoot":"","sources":["../src/ipUtils.ts"],"names":[],"mappings":";AACA,OAAO,GAAgC,MAAM,UAAU,CAAC;AAmBxD,qBAAa,OAAO;IAChB,SAAS,CAAC,kBAAkB,sCAAC;IAC7B,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAQ;gBAE5B,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IASjE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;YAIpB,UAAU;IAiClB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAQvF,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGlC"}
|
package/dist/ipUtils.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.IPUtils = void 0;
|
|
27
|
+
const os_1 = require("os");
|
|
28
|
+
const node_dns_1 = __importStar(require("node:dns"));
|
|
29
|
+
const storage_1 = require("./storage");
|
|
30
|
+
const shared_1 = require("@stuntman/shared");
|
|
31
|
+
const localhostIPs = ['127.0.0.1'];
|
|
32
|
+
const IP_WITH_OPTIONAL_PORT_REGEX = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]+)?$/i;
|
|
33
|
+
for (const nets of Object.values((0, os_1.networkInterfaces)())) {
|
|
34
|
+
if (!nets) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
for (const net of nets) {
|
|
38
|
+
const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4;
|
|
39
|
+
if (net.family === familyV4Value && !localhostIPs.includes(net.address)) {
|
|
40
|
+
localhostIPs.push(net.address);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
class IPUtils {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
var _a;
|
|
47
|
+
this.externalDns = null;
|
|
48
|
+
this.mockUuid = options.mockUuid;
|
|
49
|
+
if ((_a = options.externalDns) === null || _a === void 0 ? void 0 : _a.length) {
|
|
50
|
+
this.externalDns = new node_dns_1.Resolver();
|
|
51
|
+
this.externalDns.setServers(options.externalDns);
|
|
52
|
+
}
|
|
53
|
+
this.dnsResolutionCache = (0, storage_1.getDnsResolutionCache)(this.mockUuid);
|
|
54
|
+
}
|
|
55
|
+
isLocalhostIP(ip) {
|
|
56
|
+
return localhostIPs.includes(ip);
|
|
57
|
+
}
|
|
58
|
+
async resolveIPs(hostname, options) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const callback = (error, addresses) => {
|
|
61
|
+
if (error) {
|
|
62
|
+
shared_1.logger.debug({ error, hostname }, 'error resolving hostname');
|
|
63
|
+
reject(error);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (typeof addresses === 'string') {
|
|
67
|
+
shared_1.logger.debug({ ip: [addresses], hostname }, 'resolved hostname');
|
|
68
|
+
resolve([addresses]);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!addresses || addresses.length === 0) {
|
|
72
|
+
shared_1.logger.debug({ hostname }, 'missing IPs');
|
|
73
|
+
reject(new Error('No addresses found'));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
shared_1.logger.debug({ ip: addresses, hostname }, 'resolved hostname');
|
|
77
|
+
resolve([addresses[0], ...addresses.slice(1)]);
|
|
78
|
+
};
|
|
79
|
+
if (options === null || options === void 0 ? void 0 : options.useExternalDns) {
|
|
80
|
+
if (!this.externalDns) {
|
|
81
|
+
reject(new Error('external dns servers not set'));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.externalDns.resolve(hostname, callback);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
node_dns_1.default.lookup(hostname, callback);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async resolveIP(hostname, options) {
|
|
91
|
+
const cachedIP = this.dnsResolutionCache.get(hostname);
|
|
92
|
+
if (cachedIP) {
|
|
93
|
+
return cachedIP;
|
|
94
|
+
}
|
|
95
|
+
return (await this.resolveIPs(hostname, options))[0];
|
|
96
|
+
}
|
|
97
|
+
isIP(hostname) {
|
|
98
|
+
return IP_WITH_OPTIONAL_PORT_REGEX.test(hostname);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.IPUtils = IPUtils;
|
|
102
|
+
//# sourceMappingURL=ipUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipUtils.js","sourceRoot":"","sources":["../src/ipUtils.ts"],"names":[],"mappings":"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"}
|
package/dist/mock.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import http from 'http';
|
|
4
|
+
import https from 'https';
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import type * as Stuntman from '@stuntman/shared';
|
|
7
|
+
import { IPUtils } from './ipUtils';
|
|
8
|
+
import LRUCache from 'lru-cache';
|
|
9
|
+
import { API } from './api/api';
|
|
10
|
+
export declare class Mock {
|
|
11
|
+
readonly mockUuid: string;
|
|
12
|
+
protected options: Stuntman.Config;
|
|
13
|
+
protected mockApp: express.Express | null;
|
|
14
|
+
protected MOCK_DOMAIN_REGEX: RegExp;
|
|
15
|
+
protected URL_PORT_REGEX: RegExp;
|
|
16
|
+
protected server: http.Server | null;
|
|
17
|
+
protected serverHttps: https.Server | null;
|
|
18
|
+
protected trafficStore: LRUCache<string, Stuntman.LogEntry>;
|
|
19
|
+
protected ipUtils: IPUtils | null;
|
|
20
|
+
private _api;
|
|
21
|
+
get apiServer(): API | null;
|
|
22
|
+
get ruleExecutor(): Stuntman.RuleExecutorInterface;
|
|
23
|
+
constructor(options: Stuntman.Config);
|
|
24
|
+
private requestHandler;
|
|
25
|
+
init(): void;
|
|
26
|
+
private proxyRequest;
|
|
27
|
+
start(): void;
|
|
28
|
+
stop(): void;
|
|
29
|
+
protected unproxyRequest(req: express.Request): Stuntman.BaseRequest;
|
|
30
|
+
protected removeProxyPort(req: Stuntman.Request): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":";;AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAQhC,qBAAa,IAAI;IACb,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC;IACnC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAQ;IACjD,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAQ;IAC5C,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAQ;IAClD,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5D,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAQ;IACzC,OAAO,CAAC,IAAI,CAAoB;IAEhC,IAAI,SAAS,eAQZ;IAED,IAAW,YAAY,IAAI,QAAQ,CAAC,qBAAqB,CAExD;gBAEW,OAAO,EAAE,QAAQ,CAAC,MAAM;YA4BtB,cAAc;IAqI5B,IAAI;YA+BU,YAAY;IAkDnB,KAAK;IA6BL,IAAI;IAaX,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,WAAW;IAepE,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,GAAG,IAAI;CAYzD"}
|