reqwise-core 1.0.0 → 1.1.1

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/src/client.ts DELETED
@@ -1,163 +0,0 @@
1
- import { ReqwiseEntry, ReqwiseConfig, RequestConfig } from './types'
2
- import storage from './storage'
3
- import filter from './filter'
4
- import i18n from './i18n'
5
-
6
- const START_TS = Symbol('reqwise_start_ts')
7
-
8
- let cfg: ReqwiseConfig = {
9
- theme: 'dark',
10
- placement: 'right',
11
- defaultOpen: false,
12
- enabled: true,
13
- maxItems: 200,
14
- persistHistory: true,
15
- defaultLang: 'en',
16
- }
17
-
18
- export function initClient(c?: Partial<ReqwiseConfig>) {
19
- if (c) cfg = { ...(cfg || {}), ...c }
20
- storage.initStorage(cfg)
21
- filter.setConfig(cfg)
22
- if (c && c.defaultLang) i18n.setLanguage(c.defaultLang)
23
- }
24
-
25
- function makeId(): string {
26
- return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 9)}`
27
- }
28
-
29
- function buildEntry(base: Partial<ReqwiseEntry>): ReqwiseEntry {
30
- return {
31
- id: base.id || makeId(),
32
- source: base.source || 'auto',
33
- page: base.page || (typeof location !== 'undefined' ? location.href : 'unknown'),
34
- timestamp: base.timestamp || new Date().toISOString(),
35
- method: (base.method || 'GET') as any,
36
- url: base.url || '',
37
- params: base.params,
38
- requestHeaders: base.requestHeaders,
39
- requestBody: base.requestBody,
40
- status: base.status,
41
- statusText: base.statusText,
42
- responseHeaders: base.responseHeaders,
43
- responseBody: base.responseBody,
44
- duration: base.duration,
45
- error: base.error,
46
- }
47
- }
48
-
49
- export function recordPartial(entry: Partial<ReqwiseEntry>) {
50
- const e = buildEntry(entry)
51
- storage.saveEntry(e)
52
- }
53
-
54
- // Axios adapter (optional)
55
- export function wrapAxios(instance: any) {
56
- if (!instance || typeof instance.interceptors !== 'object') return
57
-
58
- instance.interceptors.request.use((req: any) => {
59
- try {
60
- (req as any)[START_TS] = Date.now()
61
- } catch (e) {}
62
- return req
63
- })
64
-
65
- instance.interceptors.response.use(
66
- (res: any) => {
67
- try {
68
- const req = res.config || {}
69
- const start = req[START_TS] || Date.now()
70
- const duration = Date.now() - start
71
- const entry = buildEntry({
72
- method: (req.method || 'GET').toUpperCase(),
73
- url: req.url || req.baseURL || '',
74
- requestHeaders: filter.maskHeaders(req.headers),
75
- requestBody: filter.maskFields(req.data),
76
- status: res.status,
77
- statusText: res.statusText,
78
- responseHeaders: filter.maskHeaders(res.headers),
79
- responseBody: filter.maskFields(res.data),
80
- duration,
81
- })
82
- if (!filter.shouldIgnore(entry.url)) storage.saveEntry(entry)
83
- } catch (e) {}
84
- return res
85
- },
86
- (err: any) => {
87
- try {
88
- const req = err?.config || {}
89
- const start = req[START_TS] || Date.now()
90
- const duration = Date.now() - start
91
- const response = err?.response || {}
92
- const entry = buildEntry({
93
- method: (req.method || 'GET').toUpperCase(),
94
- url: req.url || req.baseURL || '',
95
- requestHeaders: filter.maskHeaders(req.headers),
96
- requestBody: filter.maskFields(req.data),
97
- status: response.status,
98
- statusText: response.statusText,
99
- responseHeaders: filter.maskHeaders(response.headers),
100
- responseBody: filter.maskFields(response.data),
101
- duration,
102
- error: { message: err.message || 'Error' },
103
- })
104
- if (!filter.shouldIgnore(entry.url)) storage.saveEntry(entry)
105
- } catch (e) {}
106
- return Promise.reject(err)
107
- }
108
- )
109
- }
110
-
111
- // Fetch wrapper
112
- export async function fetchWithRecord(input: RequestInfo, init?: RequestInit & RequestConfig) {
113
- const url = typeof input === 'string' ? input : String((input as Request).url || '')
114
- if (filter.shouldIgnore(url)) return fetch(input, init)
115
- const start = Date.now()
116
- try {
117
- const res = await fetch(input, init as any)
118
- const cloned = res.clone()
119
- let body: any = null
120
- try {
121
- body = await cloned.json().catch(() => cloned.text())
122
- } catch (e) {
123
- body = undefined
124
- }
125
- const duration = Date.now() - start
126
- const headers: Record<string, string> = {}
127
- res.headers.forEach((v, k) => (headers[k] = v))
128
- const entry = buildEntry({
129
- method: (init?.method || 'GET') as any,
130
- url,
131
- requestHeaders: filter.maskHeaders((init && (init.headers as any)) || {}),
132
- requestBody: filter.maskFields(init && (init as any).body),
133
- status: res.status,
134
- statusText: res.statusText,
135
- responseHeaders: filter.maskHeaders(headers),
136
- responseBody: filter.maskFields(body),
137
- duration,
138
- })
139
- storage.saveEntry(entry)
140
- return res
141
- } catch (err: any) {
142
- const duration = Date.now() - start
143
- const entry = buildEntry({
144
- method: (init?.method || 'GET') as any,
145
- url,
146
- requestHeaders: filter.maskHeaders((init && (init.headers as any)) || {}),
147
- requestBody: filter.maskFields(init && (init as any).body),
148
- duration,
149
- error: { message: err?.message || String(err) },
150
- })
151
- storage.saveEntry(entry)
152
- throw err
153
- }
154
- }
155
-
156
- const ReqwiseClient = {
157
- init: initClient,
158
- wrapAxios,
159
- fetch: fetchWithRecord,
160
- record: recordPartial,
161
- }
162
-
163
- export default ReqwiseClient
package/src/filter.ts DELETED
@@ -1,96 +0,0 @@
1
- import { ReqwiseConfig } from './types'
2
-
3
- let cfg: Partial<ReqwiseConfig> = {}
4
-
5
- let ignorePatterns: string[] = [
6
- 'node_modules',
7
- '.map',
8
- '.css',
9
- '.png',
10
- '.jpg',
11
- 'chrome-extension:',
12
- ]
13
-
14
- let maskHeaderKeys: string[] = ['authorization', 'cookie']
15
- let maskFieldKeys: string[] = ['password', 'token', 'secret']
16
-
17
- function normalizeKey(k: string) {
18
- return String(k || '').toLowerCase()
19
- }
20
-
21
- function patternToRegExp(p: string): RegExp {
22
- // simple heuristic: if contains * treat as wildcard, otherwise escape and match substring
23
- if (p.includes('*')) {
24
- const esc = p.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\\\*/g, '.*')
25
- return new RegExp(esc)
26
- }
27
- try {
28
- return new RegExp(p)
29
- } catch (e) {
30
- // fallback to substring
31
- return new RegExp(p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
32
- }
33
- }
34
-
35
- export function setConfig(c: Partial<ReqwiseConfig>) {
36
- cfg = { ...cfg, ...c }
37
- if (c.ignore) ignorePatterns = c.ignore.slice()
38
- if (c.maskHeaders) maskHeaderKeys = c.maskHeaders.slice()
39
- if (c.maskFields) maskFieldKeys = c.maskFields.slice()
40
- }
41
-
42
- export function addIgnorePattern(p: string) {
43
- ignorePatterns.push(p)
44
- }
45
-
46
- export function removeIgnorePattern(p: string) {
47
- ignorePatterns = ignorePatterns.filter(x => x !== p)
48
- }
49
-
50
- export function shouldIgnore(url: string): boolean {
51
- if (!url) return true
52
- for (const p of ignorePatterns) {
53
- const re = patternToRegExp(p)
54
- if (re.test(url)) return true
55
- if (url.indexOf(p) !== -1) return true
56
- }
57
- return false
58
- }
59
-
60
- export function maskHeaders(headers?: Record<string, string> | null): Record<string, string> | undefined {
61
- if (!headers) return undefined
62
- const out: Record<string, string> = {}
63
- for (const k of Object.keys(headers)) {
64
- const nk = normalizeKey(k)
65
- if (maskHeaderKeys.includes(nk)) out[k] = '****'
66
- else out[k] = headers[k] as string
67
- }
68
- return out
69
- }
70
-
71
- function maskObject(obj: any): any {
72
- if (obj === null || obj === undefined) return obj
73
- if (typeof obj !== 'object') return obj
74
- if (Array.isArray(obj)) return obj.map(maskObject)
75
- const out: any = {}
76
- for (const k of Object.keys(obj)) {
77
- const nk = normalizeKey(k)
78
- if (maskFieldKeys.includes(nk)) out[k] = '****'
79
- else out[k] = maskObject(obj[k])
80
- }
81
- return out
82
- }
83
-
84
- export function maskFields(payload?: any) {
85
- if (payload === undefined) return payload
86
- return maskObject(payload)
87
- }
88
-
89
- export default {
90
- setConfig,
91
- addIgnorePattern,
92
- removeIgnorePattern,
93
- shouldIgnore,
94
- maskHeaders,
95
- maskFields,
96
- }