@openstax/ts-utils 1.7.0 → 1.8.0
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/dist/cjs/{fetch.d.ts → fetch/index.d.ts} +1 -1
- package/dist/{esm/middleware.d.ts → cjs/middleware/index.d.ts} +2 -2
- package/dist/cjs/{pagination.d.ts → pagination/index.d.ts} +1 -1
- package/dist/cjs/{pagination.js → pagination/index.js} +3 -3
- package/dist/cjs/routing/index.d.ts +0 -3
- package/dist/cjs/routing/index.js +7 -9
- package/dist/cjs/services/authProvider/decryption.js +5 -5
- package/dist/cjs/services/authProvider/index.d.ts +0 -2
- package/dist/cjs/services/authProvider/subrequest.js +6 -6
- package/dist/cjs/services/exercisesGateway/index.d.ts +3 -6
- package/dist/cjs/services/exercisesGateway/index.js +7 -7
- package/dist/cjs/services/versionedDocumentStore/dynamodb.d.ts +1 -4
- package/dist/cjs/services/versionedDocumentStore/dynamodb.js +13 -13
- package/dist/cjs/services/versionedDocumentStore/file-system.d.ts +1 -4
- package/dist/cjs/services/versionedDocumentStore/file-system.js +13 -13
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +4 -0
- package/dist/esm/{fetch.d.ts → fetch/index.d.ts} +1 -1
- package/dist/{cjs/middleware.d.ts → esm/middleware/index.d.ts} +2 -2
- package/dist/esm/{pagination.d.ts → pagination/index.d.ts} +1 -1
- package/dist/esm/{pagination.js → pagination/index.js} +3 -3
- package/dist/esm/routing/index.d.ts +0 -3
- package/dist/esm/routing/index.js +7 -9
- package/dist/esm/services/authProvider/decryption.js +5 -5
- package/dist/esm/services/authProvider/index.d.ts +0 -2
- package/dist/esm/services/authProvider/subrequest.js +6 -6
- package/dist/esm/services/exercisesGateway/index.d.ts +3 -6
- package/dist/esm/services/exercisesGateway/index.js +7 -7
- package/dist/esm/services/versionedDocumentStore/dynamodb.d.ts +1 -4
- package/dist/esm/services/versionedDocumentStore/dynamodb.js +13 -13
- package/dist/esm/services/versionedDocumentStore/file-system.d.ts +1 -4
- package/dist/esm/services/versionedDocumentStore/file-system.js +13 -13
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +4 -0
- package/package.json +108 -13
- package/dist/cjs/profile.d.ts +0 -61
- package/dist/cjs/profile.js +0 -199
- package/dist/esm/profile.d.ts +0 -61
- package/dist/esm/profile.js +0 -191
- /package/dist/cjs/{assertions.d.ts → assertions/index.d.ts} +0 -0
- /package/dist/cjs/{assertions.js → assertions/index.js} +0 -0
- /package/dist/cjs/{errors.d.ts → errors/index.d.ts} +0 -0
- /package/dist/cjs/{errors.js → errors/index.js} +0 -0
- /package/dist/cjs/{fetch.js → fetch/index.js} +0 -0
- /package/dist/cjs/{guards.d.ts → guards/index.d.ts} +0 -0
- /package/dist/cjs/{guards.js → guards/index.js} +0 -0
- /package/dist/cjs/{middleware.js → middleware/index.js} +0 -0
- /package/dist/esm/{assertions.d.ts → assertions/index.d.ts} +0 -0
- /package/dist/esm/{assertions.js → assertions/index.js} +0 -0
- /package/dist/esm/{errors.d.ts → errors/index.d.ts} +0 -0
- /package/dist/esm/{errors.js → errors/index.js} +0 -0
- /package/dist/esm/{fetch.js → fetch/index.js} +0 -0
- /package/dist/esm/{guards.d.ts → guards/index.d.ts} +0 -0
- /package/dist/esm/{guards.js → guards/index.js} +0 -0
- /package/dist/esm/{middleware.js → middleware/index.js} +0 -0
package/dist/esm/types.d.ts
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* There may be a better way to do this; `T1 extends T2` doesn't work
|
|
8
8
|
*/
|
|
9
9
|
export declare type TupleExtends<T1, T2> = T1 extends [infer T1Head, ...infer T1Tail] ? T2 extends [infer T2Head, ...infer T2Tail] ? T1Head extends T2Head ? TupleExtends<T1Tail, T2Tail> extends 'yes' ? 'yes' : 'no' : 'no' : T2 extends [] ? 'yes' : 'no' : T1 extends [] ? T2 extends [] ? 'yes' : 'no' : 'no';
|
|
10
|
+
/**
|
|
11
|
+
* unions each member of the tuple
|
|
12
|
+
*/
|
|
13
|
+
export declare type TupleZip<T1, T2> = T1 extends [infer T1Head, ...infer T1Tail] ? T2 extends [infer T2Head, ...infer T2Tail] ? [T1Head & T2Head, ...TupleZip<T1Tail, T2Tail>] : T2 extends [] ? T1 : never : T1 extends [] ? T2 extends any[] ? T2 : never : never;
|
|
10
14
|
/**
|
|
11
15
|
* If `R` is `Promise<I>`, returns `I`, otherwise returns `R`
|
|
12
16
|
* @deprecated use TypeScript builtin Awaited instead:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openstax/ts-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"ts-utils": "./script/bin-entry.bash"
|
|
6
6
|
},
|
|
@@ -50,20 +50,115 @@
|
|
|
50
50
|
"import": "./dist/esm/index.js",
|
|
51
51
|
"require": "./dist/cjs/index.js"
|
|
52
52
|
},
|
|
53
|
-
"
|
|
54
|
-
"browser": "./dist/cjs
|
|
55
|
-
"import": "./dist/esm
|
|
56
|
-
"require": "./dist/cjs
|
|
53
|
+
"./*": {
|
|
54
|
+
"browser": "./dist/cjs/*.js",
|
|
55
|
+
"import": "./dist/esm/*.js",
|
|
56
|
+
"require": "./dist/cjs/*.js"
|
|
57
57
|
},
|
|
58
|
-
"
|
|
59
|
-
"browser": "./dist/cjs
|
|
60
|
-
"import": "./dist/esm
|
|
61
|
-
"require": "./dist/cjs
|
|
58
|
+
"./assertions": {
|
|
59
|
+
"browser": "./dist/cjs/assertions/index.js",
|
|
60
|
+
"import": "./dist/esm/assertions/index.js",
|
|
61
|
+
"require": "./dist/cjs/assertions/index.js"
|
|
62
62
|
},
|
|
63
|
-
"
|
|
64
|
-
"browser": "./dist/cjs
|
|
65
|
-
"import": "./dist/esm
|
|
66
|
-
"require": "./dist/cjs
|
|
63
|
+
"./aws": {
|
|
64
|
+
"browser": "./dist/cjs/aws/index.js",
|
|
65
|
+
"import": "./dist/esm/aws/index.js",
|
|
66
|
+
"require": "./dist/cjs/aws/index.js"
|
|
67
|
+
},
|
|
68
|
+
"./config": {
|
|
69
|
+
"browser": "./dist/cjs/config/index.js",
|
|
70
|
+
"import": "./dist/esm/config/index.js",
|
|
71
|
+
"require": "./dist/cjs/config/index.js"
|
|
72
|
+
},
|
|
73
|
+
"./errors": {
|
|
74
|
+
"browser": "./dist/cjs/errors/index.js",
|
|
75
|
+
"import": "./dist/esm/errors/index.js",
|
|
76
|
+
"require": "./dist/cjs/errors/index.js"
|
|
77
|
+
},
|
|
78
|
+
"./fetch": {
|
|
79
|
+
"browser": "./dist/cjs/fetch/index.js",
|
|
80
|
+
"import": "./dist/esm/fetch/index.js",
|
|
81
|
+
"require": "./dist/cjs/fetch/index.js"
|
|
82
|
+
},
|
|
83
|
+
"./guards": {
|
|
84
|
+
"browser": "./dist/cjs/guards/index.js",
|
|
85
|
+
"import": "./dist/esm/guards/index.js",
|
|
86
|
+
"require": "./dist/cjs/guards/index.js"
|
|
87
|
+
},
|
|
88
|
+
"./middleware": {
|
|
89
|
+
"browser": "./dist/cjs/middleware/index.js",
|
|
90
|
+
"import": "./dist/esm/middleware/index.js",
|
|
91
|
+
"require": "./dist/cjs/middleware/index.js"
|
|
92
|
+
},
|
|
93
|
+
"./misc": {
|
|
94
|
+
"browser": "./dist/cjs/misc/index.js",
|
|
95
|
+
"import": "./dist/esm/misc/index.js",
|
|
96
|
+
"require": "./dist/cjs/misc/index.js"
|
|
97
|
+
},
|
|
98
|
+
"./pagination": {
|
|
99
|
+
"browser": "./dist/cjs/pagination/index.js",
|
|
100
|
+
"import": "./dist/esm/pagination/index.js",
|
|
101
|
+
"require": "./dist/cjs/pagination/index.js"
|
|
102
|
+
},
|
|
103
|
+
"./routing": {
|
|
104
|
+
"browser": "./dist/cjs/routing/index.js",
|
|
105
|
+
"import": "./dist/esm/routing/index.js",
|
|
106
|
+
"require": "./dist/cjs/routing/index.js"
|
|
107
|
+
},
|
|
108
|
+
"./services": {
|
|
109
|
+
"browser": "./dist/cjs/services/index.js",
|
|
110
|
+
"import": "./dist/esm/services/index.js",
|
|
111
|
+
"require": "./dist/cjs/services/index.js"
|
|
112
|
+
},
|
|
113
|
+
"./services/launchParams": {
|
|
114
|
+
"browser": "./dist/cjs/services/launchParams/index.js",
|
|
115
|
+
"import": "./dist/esm/services/launchParams/index.js",
|
|
116
|
+
"require": "./dist/cjs/services/launchParams/index.js"
|
|
117
|
+
},
|
|
118
|
+
"./services/exercisesGateway": {
|
|
119
|
+
"browser": "./dist/cjs/services/exercisesGateway/index.js",
|
|
120
|
+
"import": "./dist/esm/services/exercisesGateway/index.js",
|
|
121
|
+
"require": "./dist/cjs/services/exercisesGateway/index.js"
|
|
122
|
+
},
|
|
123
|
+
"./services/accountsGateway": {
|
|
124
|
+
"browser": "./dist/cjs/services/accountsGateway/index.js",
|
|
125
|
+
"import": "./dist/esm/services/accountsGateway/index.js",
|
|
126
|
+
"require": "./dist/cjs/services/accountsGateway/index.js"
|
|
127
|
+
},
|
|
128
|
+
"./services/logger": {
|
|
129
|
+
"browser": "./dist/cjs/services/logger/index.js",
|
|
130
|
+
"import": "./dist/esm/services/logger/index.js",
|
|
131
|
+
"require": "./dist/cjs/services/logger/index.js"
|
|
132
|
+
},
|
|
133
|
+
"./services/searchProvider": {
|
|
134
|
+
"browser": "./dist/cjs/services/searchProvider/index.js",
|
|
135
|
+
"import": "./dist/esm/services/searchProvider/index.js",
|
|
136
|
+
"require": "./dist/cjs/services/searchProvider/index.js"
|
|
137
|
+
},
|
|
138
|
+
"./services/versionedDocumentStore": {
|
|
139
|
+
"browser": "./dist/cjs/services/versionedDocumentStore/index.js",
|
|
140
|
+
"import": "./dist/esm/services/versionedDocumentStore/index.js",
|
|
141
|
+
"require": "./dist/cjs/services/versionedDocumentStore/index.js"
|
|
142
|
+
},
|
|
143
|
+
"./services/lrsGateway": {
|
|
144
|
+
"browser": "./dist/cjs/services/lrsGateway/index.js",
|
|
145
|
+
"import": "./dist/esm/services/lrsGateway/index.js",
|
|
146
|
+
"require": "./dist/cjs/services/lrsGateway/index.js"
|
|
147
|
+
},
|
|
148
|
+
"./services/authProvider": {
|
|
149
|
+
"browser": "./dist/cjs/services/authProvider/index.js",
|
|
150
|
+
"import": "./dist/esm/services/authProvider/index.js",
|
|
151
|
+
"require": "./dist/cjs/services/authProvider/index.js"
|
|
152
|
+
},
|
|
153
|
+
"./services/authProvider/utils": {
|
|
154
|
+
"browser": "./dist/cjs/services/authProvider/utils/index.js",
|
|
155
|
+
"import": "./dist/esm/services/authProvider/utils/index.js",
|
|
156
|
+
"require": "./dist/cjs/services/authProvider/utils/index.js"
|
|
157
|
+
},
|
|
158
|
+
"./services/apiGateway": {
|
|
159
|
+
"browser": "./dist/cjs/services/apiGateway/index.js",
|
|
160
|
+
"import": "./dist/esm/services/apiGateway/index.js",
|
|
161
|
+
"require": "./dist/cjs/services/apiGateway/index.js"
|
|
67
162
|
}
|
|
68
163
|
},
|
|
69
164
|
"files": [
|
package/dist/cjs/profile.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { GenericFetch } from './fetch';
|
|
2
|
-
import { ApiResponse, HttpHeaders } from './routing';
|
|
3
|
-
import { Logger } from './services/logger';
|
|
4
|
-
export interface Call {
|
|
5
|
-
start: number;
|
|
6
|
-
end?: number;
|
|
7
|
-
children: Array<Profile | ProfileData>;
|
|
8
|
-
}
|
|
9
|
-
export declare type ProfileFunction = <Fn extends (...args: any[]) => any>(trackName: string, fn: (p: Track) => Fn) => Fn;
|
|
10
|
-
export interface Track {
|
|
11
|
-
track: ProfileFunction;
|
|
12
|
-
trackFetch: <F extends GenericFetch>(fetch: F) => F;
|
|
13
|
-
setTracing: (tracing: boolean | Promise<boolean>) => void;
|
|
14
|
-
getTracing: () => Promise<undefined | boolean>;
|
|
15
|
-
data: () => Call;
|
|
16
|
-
report: () => CallReport;
|
|
17
|
-
adopt: (child: Profile) => void;
|
|
18
|
-
}
|
|
19
|
-
export interface ProfileData {
|
|
20
|
-
name: string;
|
|
21
|
-
calls: Call[];
|
|
22
|
-
}
|
|
23
|
-
export interface Profile extends ProfileData {
|
|
24
|
-
report: () => ProfileReport;
|
|
25
|
-
start: () => Track & {
|
|
26
|
-
end: () => void;
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
interface CallReport {
|
|
30
|
-
time: number | string;
|
|
31
|
-
children: ProfileReport[];
|
|
32
|
-
coverage: 'unknown' | {
|
|
33
|
-
accountedTime: number;
|
|
34
|
-
unaccountedTime: number;
|
|
35
|
-
accountedPercent: number;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
interface ProfileReport {
|
|
39
|
-
name: string;
|
|
40
|
-
time: 'unknown' | {
|
|
41
|
-
total: number;
|
|
42
|
-
min: number;
|
|
43
|
-
max: number;
|
|
44
|
-
avg: number;
|
|
45
|
-
};
|
|
46
|
-
calls: CallReport[];
|
|
47
|
-
}
|
|
48
|
-
export declare const createProfile: (name: string, options?: {
|
|
49
|
-
trace?: boolean | Promise<boolean>;
|
|
50
|
-
}) => Profile;
|
|
51
|
-
export declare const makeProfileApiResponseMiddleware: <Ri extends {
|
|
52
|
-
headers: HttpHeaders;
|
|
53
|
-
}>(showReport: (request: Ri) => string | boolean) => () => (responsePromise: Promise<ApiResponse<number, any>> | undefined, { request, profile }: {
|
|
54
|
-
request: Ri;
|
|
55
|
-
profile: Track;
|
|
56
|
-
logger: Logger;
|
|
57
|
-
}) => Promise<ApiResponse<number, any>> | undefined;
|
|
58
|
-
export declare const makeHtmlReport: (report: CallReport) => string;
|
|
59
|
-
export declare const makeHtmlProfileReport: (report: ProfileReport) => string;
|
|
60
|
-
export declare const makeHtmlCallReport: (report: CallReport, index: number) => string;
|
|
61
|
-
export {};
|
package/dist/cjs/profile.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeHtmlCallReport = exports.makeHtmlProfileReport = exports.makeHtmlReport = exports.makeProfileApiResponseMiddleware = exports.createProfile = void 0;
|
|
4
|
-
const guards_1 = require("./guards");
|
|
5
|
-
const routing_1 = require("./routing");
|
|
6
|
-
const _1 = require(".");
|
|
7
|
-
const callReport = (call) => {
|
|
8
|
-
const time = call.start && call.end
|
|
9
|
-
? call.end - call.start
|
|
10
|
-
: 'unknown';
|
|
11
|
-
const children = call.children
|
|
12
|
-
.filter(profile => profile.calls.length > 0)
|
|
13
|
-
.map(profileReport);
|
|
14
|
-
const accountedTime = children.reduce((result, profile) => typeof profile.time === 'string' ? result : result + profile.time.total, 0);
|
|
15
|
-
const coverage = typeof time === 'number' && children.length > 0 ? {
|
|
16
|
-
accountedTime,
|
|
17
|
-
unaccountedTime: time - accountedTime,
|
|
18
|
-
accountedPercent: (0, _1.roundToPrecision)(accountedTime / time, -2),
|
|
19
|
-
} : 'unknown';
|
|
20
|
-
return { time, children, coverage };
|
|
21
|
-
};
|
|
22
|
-
const profileReport = (profile) => {
|
|
23
|
-
const calls = profile.calls.map(callReport);
|
|
24
|
-
const times = calls
|
|
25
|
-
.map(call => call.time)
|
|
26
|
-
.filter(guards_1.isNumber);
|
|
27
|
-
const time = times.length > 0 ? {
|
|
28
|
-
total: times.reduce((result, item) => result + item, 0),
|
|
29
|
-
min: Math.min(...times),
|
|
30
|
-
max: Math.max(...times),
|
|
31
|
-
avg: Math.round(times.reduce((result, item) => result + item, 0) / times.length),
|
|
32
|
-
} : 'unknown';
|
|
33
|
-
return {
|
|
34
|
-
name: profile.name, calls, time
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
const createProfile = (name, options = {}) => {
|
|
38
|
-
const profile = {
|
|
39
|
-
name,
|
|
40
|
-
calls: [],
|
|
41
|
-
report: () => profileReport(profile),
|
|
42
|
-
start: () => {
|
|
43
|
-
const call = { start: Date.now(), children: [] };
|
|
44
|
-
profile.calls.push(call);
|
|
45
|
-
return {
|
|
46
|
-
end: () => { call.end = Date.now(); },
|
|
47
|
-
report: () => callReport({ end: Date.now(), ...call }),
|
|
48
|
-
data: () => ({ end: Date.now(), ...call }),
|
|
49
|
-
adopt: (childProfile) => { call.children.push(childProfile); },
|
|
50
|
-
setTracing: (tracing) => { options.trace = tracing; },
|
|
51
|
-
getTracing: async () => options.trace,
|
|
52
|
-
trackFetch: (fetch) => {
|
|
53
|
-
const trackProfile = (0, exports.createProfile)('fetch', options);
|
|
54
|
-
call.children.push(trackProfile);
|
|
55
|
-
return (async (url, config) => {
|
|
56
|
-
const { end, ...track } = trackProfile.start();
|
|
57
|
-
const fetchConfig = await options.trace
|
|
58
|
-
? (0, _1.merge)(config || {}, {
|
|
59
|
-
headers: { 'x-application-profile': 'trace' }
|
|
60
|
-
})
|
|
61
|
-
: config;
|
|
62
|
-
return fetch(url, fetchConfig).then(response => {
|
|
63
|
-
const fetchProfileJson = response.headers.get('x-application-profile');
|
|
64
|
-
const fetchProfile = fetchProfileJson ? JSON.parse(fetchProfileJson) : undefined;
|
|
65
|
-
end();
|
|
66
|
-
if (fetchProfile) {
|
|
67
|
-
const subrequestProfile = (0, exports.createProfile)(url, options);
|
|
68
|
-
subrequestProfile.calls.push(fetchProfile);
|
|
69
|
-
track.adopt(subrequestProfile);
|
|
70
|
-
}
|
|
71
|
-
return response;
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
},
|
|
75
|
-
track: (trackName, fn) => {
|
|
76
|
-
const trackProfile = (0, exports.createProfile)(trackName, options);
|
|
77
|
-
call.children.push(trackProfile);
|
|
78
|
-
return ((...args) => {
|
|
79
|
-
const { end, ...track } = trackProfile.start();
|
|
80
|
-
const result = fn(track)(...args);
|
|
81
|
-
if (result instanceof Promise) {
|
|
82
|
-
return result.finally(() => { end(); });
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
end();
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
return profile;
|
|
94
|
-
};
|
|
95
|
-
exports.createProfile = createProfile;
|
|
96
|
-
const makeProfileApiResponseMiddleware = (showReport) => () => (responsePromise, { request, profile }) => {
|
|
97
|
-
if (responsePromise) {
|
|
98
|
-
return responsePromise.then(async (response) => {
|
|
99
|
-
const reportFormat = showReport(request);
|
|
100
|
-
const enabled = await profile.getTracing();
|
|
101
|
-
// profiling is disabled, return original response
|
|
102
|
-
if (!enabled) {
|
|
103
|
-
return response;
|
|
104
|
-
}
|
|
105
|
-
// there is no report format, return original response but
|
|
106
|
-
// add sub-request trace response if necessary
|
|
107
|
-
if (reportFormat === false) {
|
|
108
|
-
if ((0, routing_1.getHeader)(request.headers, 'x-application-profile')) {
|
|
109
|
-
return {
|
|
110
|
-
...response,
|
|
111
|
-
headers: {
|
|
112
|
-
...response.headers,
|
|
113
|
-
'x-application-profile': JSON.stringify(profile.data())
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
return response;
|
|
118
|
-
// override response with html report
|
|
119
|
-
}
|
|
120
|
-
else if (reportFormat === 'html') {
|
|
121
|
-
return (0, routing_1.apiHtmlResponse)(200, (0, exports.makeHtmlReport)(profile.report()));
|
|
122
|
-
}
|
|
123
|
-
// override response with json report
|
|
124
|
-
return (0, routing_1.apiJsonResponse)(200, profile.report());
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return responsePromise;
|
|
128
|
-
};
|
|
129
|
-
exports.makeProfileApiResponseMiddleware = makeProfileApiResponseMiddleware;
|
|
130
|
-
const makeHtmlReport = (report) => `
|
|
131
|
-
<head>
|
|
132
|
-
<style>
|
|
133
|
-
table {
|
|
134
|
-
border-collapse: collapse;
|
|
135
|
-
}
|
|
136
|
-
table td,th {
|
|
137
|
-
border: 1px solid #ccc;
|
|
138
|
-
padding: 10px;
|
|
139
|
-
}
|
|
140
|
-
summary {
|
|
141
|
-
padding: 10px 0;
|
|
142
|
-
}
|
|
143
|
-
</style>
|
|
144
|
-
</head>
|
|
145
|
-
<body>
|
|
146
|
-
${(0, exports.makeHtmlCallReport)(report, 0)}
|
|
147
|
-
</body>
|
|
148
|
-
`;
|
|
149
|
-
exports.makeHtmlReport = makeHtmlReport;
|
|
150
|
-
const makeHtmlProfileReport = (report) => `
|
|
151
|
-
<details>
|
|
152
|
-
<summary>Profile: ${report.name}</summary>
|
|
153
|
-
<table>
|
|
154
|
-
<thead>
|
|
155
|
-
<tr>
|
|
156
|
-
<th>call #</th>
|
|
157
|
-
<th>children</th>
|
|
158
|
-
<th>time</th>
|
|
159
|
-
<th>time coverage (accounted/unaccounted/percent)</th>
|
|
160
|
-
</tr>
|
|
161
|
-
</thead>
|
|
162
|
-
<tbody>
|
|
163
|
-
${report.calls.map((call, i) => `<tr>
|
|
164
|
-
<td>${i + 1}</td>
|
|
165
|
-
<td>${call.children.length}</td>
|
|
166
|
-
<td>${call.time}</td>
|
|
167
|
-
<td>${typeof call.coverage === 'string' ? call.coverage : `${call.coverage.accountedTime}/${call.coverage.unaccountedTime}/${call.coverage.accountedPercent}`}</td>
|
|
168
|
-
</tr>`)}
|
|
169
|
-
</tbody>
|
|
170
|
-
</table>
|
|
171
|
-
<div style="padding-left: 20px; border-left: 1px solid #ccc;">
|
|
172
|
-
${report.calls.map(exports.makeHtmlCallReport).join('')}
|
|
173
|
-
</div>
|
|
174
|
-
</details>
|
|
175
|
-
`;
|
|
176
|
-
exports.makeHtmlProfileReport = makeHtmlProfileReport;
|
|
177
|
-
const makeHtmlCallReport = (report, index) => `
|
|
178
|
-
<h4>call # ${index + 1} children<h4>
|
|
179
|
-
<table>
|
|
180
|
-
<thead>
|
|
181
|
-
<tr>
|
|
182
|
-
<th>name</th>
|
|
183
|
-
<th>calls</th>
|
|
184
|
-
<th>time (total (min/max/avg))</th>
|
|
185
|
-
</tr>
|
|
186
|
-
</thead>
|
|
187
|
-
<tbody>
|
|
188
|
-
${report.children.map(profile => `<tr>
|
|
189
|
-
<td>${profile.name}</td>
|
|
190
|
-
<td>${profile.calls.length}</td>
|
|
191
|
-
<td>${typeof profile.time === 'string' ? profile.time : `${profile.time.total} (${profile.time.min}/${profile.time.max}/${profile.time.avg})`}</td>
|
|
192
|
-
</tr>`).join('')}
|
|
193
|
-
</tbody>
|
|
194
|
-
</table>
|
|
195
|
-
<div style="margin-left: 20px">
|
|
196
|
-
${report.children.map(exports.makeHtmlProfileReport).join('')}
|
|
197
|
-
</div>
|
|
198
|
-
`;
|
|
199
|
-
exports.makeHtmlCallReport = makeHtmlCallReport;
|
package/dist/esm/profile.d.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { GenericFetch } from './fetch';
|
|
2
|
-
import { ApiResponse, HttpHeaders } from './routing';
|
|
3
|
-
import { Logger } from './services/logger';
|
|
4
|
-
export interface Call {
|
|
5
|
-
start: number;
|
|
6
|
-
end?: number;
|
|
7
|
-
children: Array<Profile | ProfileData>;
|
|
8
|
-
}
|
|
9
|
-
export declare type ProfileFunction = <Fn extends (...args: any[]) => any>(trackName: string, fn: (p: Track) => Fn) => Fn;
|
|
10
|
-
export interface Track {
|
|
11
|
-
track: ProfileFunction;
|
|
12
|
-
trackFetch: <F extends GenericFetch>(fetch: F) => F;
|
|
13
|
-
setTracing: (tracing: boolean | Promise<boolean>) => void;
|
|
14
|
-
getTracing: () => Promise<undefined | boolean>;
|
|
15
|
-
data: () => Call;
|
|
16
|
-
report: () => CallReport;
|
|
17
|
-
adopt: (child: Profile) => void;
|
|
18
|
-
}
|
|
19
|
-
export interface ProfileData {
|
|
20
|
-
name: string;
|
|
21
|
-
calls: Call[];
|
|
22
|
-
}
|
|
23
|
-
export interface Profile extends ProfileData {
|
|
24
|
-
report: () => ProfileReport;
|
|
25
|
-
start: () => Track & {
|
|
26
|
-
end: () => void;
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
interface CallReport {
|
|
30
|
-
time: number | string;
|
|
31
|
-
children: ProfileReport[];
|
|
32
|
-
coverage: 'unknown' | {
|
|
33
|
-
accountedTime: number;
|
|
34
|
-
unaccountedTime: number;
|
|
35
|
-
accountedPercent: number;
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
interface ProfileReport {
|
|
39
|
-
name: string;
|
|
40
|
-
time: 'unknown' | {
|
|
41
|
-
total: number;
|
|
42
|
-
min: number;
|
|
43
|
-
max: number;
|
|
44
|
-
avg: number;
|
|
45
|
-
};
|
|
46
|
-
calls: CallReport[];
|
|
47
|
-
}
|
|
48
|
-
export declare const createProfile: (name: string, options?: {
|
|
49
|
-
trace?: boolean | Promise<boolean>;
|
|
50
|
-
}) => Profile;
|
|
51
|
-
export declare const makeProfileApiResponseMiddleware: <Ri extends {
|
|
52
|
-
headers: HttpHeaders;
|
|
53
|
-
}>(showReport: (request: Ri) => string | boolean) => () => (responsePromise: Promise<ApiResponse<number, any>> | undefined, { request, profile }: {
|
|
54
|
-
request: Ri;
|
|
55
|
-
profile: Track;
|
|
56
|
-
logger: Logger;
|
|
57
|
-
}) => Promise<ApiResponse<number, any>> | undefined;
|
|
58
|
-
export declare const makeHtmlReport: (report: CallReport) => string;
|
|
59
|
-
export declare const makeHtmlProfileReport: (report: ProfileReport) => string;
|
|
60
|
-
export declare const makeHtmlCallReport: (report: CallReport, index: number) => string;
|
|
61
|
-
export {};
|
package/dist/esm/profile.js
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { isNumber } from './guards';
|
|
2
|
-
import { apiHtmlResponse, apiJsonResponse, getHeader } from './routing';
|
|
3
|
-
import { merge, roundToPrecision } from '.';
|
|
4
|
-
const callReport = (call) => {
|
|
5
|
-
const time = call.start && call.end
|
|
6
|
-
? call.end - call.start
|
|
7
|
-
: 'unknown';
|
|
8
|
-
const children = call.children
|
|
9
|
-
.filter(profile => profile.calls.length > 0)
|
|
10
|
-
.map(profileReport);
|
|
11
|
-
const accountedTime = children.reduce((result, profile) => typeof profile.time === 'string' ? result : result + profile.time.total, 0);
|
|
12
|
-
const coverage = typeof time === 'number' && children.length > 0 ? {
|
|
13
|
-
accountedTime,
|
|
14
|
-
unaccountedTime: time - accountedTime,
|
|
15
|
-
accountedPercent: roundToPrecision(accountedTime / time, -2),
|
|
16
|
-
} : 'unknown';
|
|
17
|
-
return { time, children, coverage };
|
|
18
|
-
};
|
|
19
|
-
const profileReport = (profile) => {
|
|
20
|
-
const calls = profile.calls.map(callReport);
|
|
21
|
-
const times = calls
|
|
22
|
-
.map(call => call.time)
|
|
23
|
-
.filter(isNumber);
|
|
24
|
-
const time = times.length > 0 ? {
|
|
25
|
-
total: times.reduce((result, item) => result + item, 0),
|
|
26
|
-
min: Math.min(...times),
|
|
27
|
-
max: Math.max(...times),
|
|
28
|
-
avg: Math.round(times.reduce((result, item) => result + item, 0) / times.length),
|
|
29
|
-
} : 'unknown';
|
|
30
|
-
return {
|
|
31
|
-
name: profile.name, calls, time
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
export const createProfile = (name, options = {}) => {
|
|
35
|
-
const profile = {
|
|
36
|
-
name,
|
|
37
|
-
calls: [],
|
|
38
|
-
report: () => profileReport(profile),
|
|
39
|
-
start: () => {
|
|
40
|
-
const call = { start: Date.now(), children: [] };
|
|
41
|
-
profile.calls.push(call);
|
|
42
|
-
return {
|
|
43
|
-
end: () => { call.end = Date.now(); },
|
|
44
|
-
report: () => callReport({ end: Date.now(), ...call }),
|
|
45
|
-
data: () => ({ end: Date.now(), ...call }),
|
|
46
|
-
adopt: (childProfile) => { call.children.push(childProfile); },
|
|
47
|
-
setTracing: (tracing) => { options.trace = tracing; },
|
|
48
|
-
getTracing: async () => options.trace,
|
|
49
|
-
trackFetch: (fetch) => {
|
|
50
|
-
const trackProfile = createProfile('fetch', options);
|
|
51
|
-
call.children.push(trackProfile);
|
|
52
|
-
return (async (url, config) => {
|
|
53
|
-
const { end, ...track } = trackProfile.start();
|
|
54
|
-
const fetchConfig = await options.trace
|
|
55
|
-
? merge(config || {}, {
|
|
56
|
-
headers: { 'x-application-profile': 'trace' }
|
|
57
|
-
})
|
|
58
|
-
: config;
|
|
59
|
-
return fetch(url, fetchConfig).then(response => {
|
|
60
|
-
const fetchProfileJson = response.headers.get('x-application-profile');
|
|
61
|
-
const fetchProfile = fetchProfileJson ? JSON.parse(fetchProfileJson) : undefined;
|
|
62
|
-
end();
|
|
63
|
-
if (fetchProfile) {
|
|
64
|
-
const subrequestProfile = createProfile(url, options);
|
|
65
|
-
subrequestProfile.calls.push(fetchProfile);
|
|
66
|
-
track.adopt(subrequestProfile);
|
|
67
|
-
}
|
|
68
|
-
return response;
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
},
|
|
72
|
-
track: (trackName, fn) => {
|
|
73
|
-
const trackProfile = createProfile(trackName, options);
|
|
74
|
-
call.children.push(trackProfile);
|
|
75
|
-
return ((...args) => {
|
|
76
|
-
const { end, ...track } = trackProfile.start();
|
|
77
|
-
const result = fn(track)(...args);
|
|
78
|
-
if (result instanceof Promise) {
|
|
79
|
-
return result.finally(() => { end(); });
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
end();
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
return profile;
|
|
91
|
-
};
|
|
92
|
-
export const makeProfileApiResponseMiddleware = (showReport) => () => (responsePromise, { request, profile }) => {
|
|
93
|
-
if (responsePromise) {
|
|
94
|
-
return responsePromise.then(async (response) => {
|
|
95
|
-
const reportFormat = showReport(request);
|
|
96
|
-
const enabled = await profile.getTracing();
|
|
97
|
-
// profiling is disabled, return original response
|
|
98
|
-
if (!enabled) {
|
|
99
|
-
return response;
|
|
100
|
-
}
|
|
101
|
-
// there is no report format, return original response but
|
|
102
|
-
// add sub-request trace response if necessary
|
|
103
|
-
if (reportFormat === false) {
|
|
104
|
-
if (getHeader(request.headers, 'x-application-profile')) {
|
|
105
|
-
return {
|
|
106
|
-
...response,
|
|
107
|
-
headers: {
|
|
108
|
-
...response.headers,
|
|
109
|
-
'x-application-profile': JSON.stringify(profile.data())
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
return response;
|
|
114
|
-
// override response with html report
|
|
115
|
-
}
|
|
116
|
-
else if (reportFormat === 'html') {
|
|
117
|
-
return apiHtmlResponse(200, makeHtmlReport(profile.report()));
|
|
118
|
-
}
|
|
119
|
-
// override response with json report
|
|
120
|
-
return apiJsonResponse(200, profile.report());
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
return responsePromise;
|
|
124
|
-
};
|
|
125
|
-
export const makeHtmlReport = (report) => `
|
|
126
|
-
<head>
|
|
127
|
-
<style>
|
|
128
|
-
table {
|
|
129
|
-
border-collapse: collapse;
|
|
130
|
-
}
|
|
131
|
-
table td,th {
|
|
132
|
-
border: 1px solid #ccc;
|
|
133
|
-
padding: 10px;
|
|
134
|
-
}
|
|
135
|
-
summary {
|
|
136
|
-
padding: 10px 0;
|
|
137
|
-
}
|
|
138
|
-
</style>
|
|
139
|
-
</head>
|
|
140
|
-
<body>
|
|
141
|
-
${makeHtmlCallReport(report, 0)}
|
|
142
|
-
</body>
|
|
143
|
-
`;
|
|
144
|
-
export const makeHtmlProfileReport = (report) => `
|
|
145
|
-
<details>
|
|
146
|
-
<summary>Profile: ${report.name}</summary>
|
|
147
|
-
<table>
|
|
148
|
-
<thead>
|
|
149
|
-
<tr>
|
|
150
|
-
<th>call #</th>
|
|
151
|
-
<th>children</th>
|
|
152
|
-
<th>time</th>
|
|
153
|
-
<th>time coverage (accounted/unaccounted/percent)</th>
|
|
154
|
-
</tr>
|
|
155
|
-
</thead>
|
|
156
|
-
<tbody>
|
|
157
|
-
${report.calls.map((call, i) => `<tr>
|
|
158
|
-
<td>${i + 1}</td>
|
|
159
|
-
<td>${call.children.length}</td>
|
|
160
|
-
<td>${call.time}</td>
|
|
161
|
-
<td>${typeof call.coverage === 'string' ? call.coverage : `${call.coverage.accountedTime}/${call.coverage.unaccountedTime}/${call.coverage.accountedPercent}`}</td>
|
|
162
|
-
</tr>`)}
|
|
163
|
-
</tbody>
|
|
164
|
-
</table>
|
|
165
|
-
<div style="padding-left: 20px; border-left: 1px solid #ccc;">
|
|
166
|
-
${report.calls.map(makeHtmlCallReport).join('')}
|
|
167
|
-
</div>
|
|
168
|
-
</details>
|
|
169
|
-
`;
|
|
170
|
-
export const makeHtmlCallReport = (report, index) => `
|
|
171
|
-
<h4>call # ${index + 1} children<h4>
|
|
172
|
-
<table>
|
|
173
|
-
<thead>
|
|
174
|
-
<tr>
|
|
175
|
-
<th>name</th>
|
|
176
|
-
<th>calls</th>
|
|
177
|
-
<th>time (total (min/max/avg))</th>
|
|
178
|
-
</tr>
|
|
179
|
-
</thead>
|
|
180
|
-
<tbody>
|
|
181
|
-
${report.children.map(profile => `<tr>
|
|
182
|
-
<td>${profile.name}</td>
|
|
183
|
-
<td>${profile.calls.length}</td>
|
|
184
|
-
<td>${typeof profile.time === 'string' ? profile.time : `${profile.time.total} (${profile.time.min}/${profile.time.max}/${profile.time.avg})`}</td>
|
|
185
|
-
</tr>`).join('')}
|
|
186
|
-
</tbody>
|
|
187
|
-
</table>
|
|
188
|
-
<div style="margin-left: 20px">
|
|
189
|
-
${report.children.map(makeHtmlProfileReport).join('')}
|
|
190
|
-
</div>
|
|
191
|
-
`;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|