@graphcommerce/graphql 6.0.2-canary.1 → 6.0.2-canary.10
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/CHANGELOG.md +22 -0
- package/lib/hyperlinker.ts +84 -0
- package/measurePerformanceLink.ts +61 -30
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 6.0.2-canary.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1883](https://github.com/graphcommerce-org/graphcommerce/pull/1883) [`ede93ae7f`](https://github.com/graphcommerce-org/graphcommerce/commit/ede93ae7f1d9239d1e827cce574085a1c264890b) - Added clickable links to measurePerformanceLink ([@paales](https://github.com/paales))
|
|
8
|
+
|
|
9
|
+
## 6.0.2-canary.9
|
|
10
|
+
|
|
11
|
+
## 6.0.2-canary.8
|
|
12
|
+
|
|
13
|
+
## 6.0.2-canary.7
|
|
14
|
+
|
|
15
|
+
## 6.0.2-canary.6
|
|
16
|
+
|
|
17
|
+
## 6.0.2-canary.5
|
|
18
|
+
|
|
19
|
+
## 6.0.2-canary.4
|
|
20
|
+
|
|
21
|
+
## 6.0.2-canary.3
|
|
22
|
+
|
|
23
|
+
## 6.0.2-canary.2
|
|
24
|
+
|
|
3
25
|
## 6.0.2-canary.1
|
|
4
26
|
|
|
5
27
|
## 6.0.2-canary.0
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
A hyperlink is opened upon encountering an OSC 8 escape sequence with the target URI. The syntax is
|
|
5
|
+
OSC 8 ; params ; URI BEL|ST
|
|
6
|
+
Following this, all subsequent cells that are painted are hyperlinks to this target. A hyperlink is closed with the same escape sequence, omitting the parameters and the URI but keeping the separators:
|
|
7
|
+
OSC 8 ; ; BEL|ST
|
|
8
|
+
const ST = '\u001B\\';
|
|
9
|
+
*/
|
|
10
|
+
const OSC = '\u001B]'
|
|
11
|
+
const BEL = '\u0007'
|
|
12
|
+
const SEP = ';'
|
|
13
|
+
|
|
14
|
+
const hyperlinker = (text: string, uri: string) =>
|
|
15
|
+
[OSC, '8', SEP, SEP, uri, BEL, text, OSC, '8', SEP, SEP, BEL].join('')
|
|
16
|
+
|
|
17
|
+
function parseVersion(versionString: string): { major: number; minor: number; patch: number } {
|
|
18
|
+
if (/^\d{3,4}$/.test(versionString)) {
|
|
19
|
+
// Env var doesn't always use dots. example: 4601 => 46.1.0
|
|
20
|
+
const m = /(\d{1,2})(\d{2})/.exec(versionString) || []
|
|
21
|
+
return {
|
|
22
|
+
major: 0,
|
|
23
|
+
minor: parseInt(m[1], 10),
|
|
24
|
+
patch: parseInt(m[2], 10),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const versions = (versionString || '').split('.').map((n) => parseInt(n, 10))
|
|
29
|
+
return {
|
|
30
|
+
major: versions[0],
|
|
31
|
+
minor: versions[1],
|
|
32
|
+
patch: versions[2],
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function supportsHyperlink(): boolean {
|
|
37
|
+
const {
|
|
38
|
+
CI,
|
|
39
|
+
FORCE_HYPERLINK,
|
|
40
|
+
NETLIFY,
|
|
41
|
+
TEAMCITY_VERSION,
|
|
42
|
+
TERM_PROGRAM,
|
|
43
|
+
TERM_PROGRAM_VERSION,
|
|
44
|
+
VTE_VERSION,
|
|
45
|
+
VERCEL,
|
|
46
|
+
} = process.env
|
|
47
|
+
|
|
48
|
+
if (FORCE_HYPERLINK) {
|
|
49
|
+
return !(FORCE_HYPERLINK.length > 0 && parseInt(FORCE_HYPERLINK, 10) === 0)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (NETLIFY) return true
|
|
53
|
+
if (process.stdout.isTTY || process.stderr.isTTY) return false
|
|
54
|
+
if (process.platform === 'win32') return false
|
|
55
|
+
if (CI) return false
|
|
56
|
+
if (VERCEL) return false
|
|
57
|
+
if (TEAMCITY_VERSION) return false
|
|
58
|
+
|
|
59
|
+
if (TERM_PROGRAM) {
|
|
60
|
+
const version = parseVersion(TERM_PROGRAM_VERSION || '')
|
|
61
|
+
|
|
62
|
+
switch (TERM_PROGRAM) {
|
|
63
|
+
case 'iTerm.app':
|
|
64
|
+
if (version.major === 3) return version.minor >= 1
|
|
65
|
+
return version.major > 3
|
|
66
|
+
case 'WezTerm':
|
|
67
|
+
return version.major >= 20200620
|
|
68
|
+
case 'vscode':
|
|
69
|
+
return version.major > 1 || (version.major === 1 && version.minor >= 72)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (VTE_VERSION) {
|
|
74
|
+
// 0.50.0 was supposed to support hyperlinks, but throws a segfault
|
|
75
|
+
if (VTE_VERSION === '0.50.0') return false
|
|
76
|
+
const version = parseVersion(VTE_VERSION)
|
|
77
|
+
return version.major > 0 || version.minor >= 50
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const cliHyperlink = (text: string, uri: string) =>
|
|
84
|
+
supportsHyperlink() ? hyperlinker(text, uri) : text
|
|
@@ -1,34 +1,26 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { ApolloLink } from '@apollo/client'
|
|
3
|
+
import type { MeshFetchHTTPInformation } from '@graphql-mesh/plugin-http-details-extensions'
|
|
4
|
+
import { print } from 'graphql'
|
|
5
|
+
import { cliHyperlink } from './lib/hyperlinker'
|
|
3
6
|
|
|
4
7
|
const running = new Map<
|
|
5
8
|
string,
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
endTime: string
|
|
13
|
-
duration: number
|
|
14
|
-
execution: {
|
|
15
|
-
resolvers: {
|
|
16
|
-
path: (string | number)[]
|
|
17
|
-
parentType: string
|
|
18
|
-
fieldName: string
|
|
19
|
-
returnType: string
|
|
20
|
-
startOffset: number
|
|
21
|
-
duration: number
|
|
22
|
-
}[]
|
|
9
|
+
{
|
|
10
|
+
start: Date
|
|
11
|
+
end?: Date
|
|
12
|
+
internalStart?: Date
|
|
13
|
+
operationName: [string, string]
|
|
14
|
+
additional?: [string, string]
|
|
23
15
|
}
|
|
24
|
-
|
|
16
|
+
>()
|
|
25
17
|
|
|
26
18
|
const renderLine = (line: {
|
|
27
19
|
serverStart: number
|
|
28
20
|
requestStart: number
|
|
29
21
|
requestEnd: number
|
|
30
22
|
colDivider: number
|
|
31
|
-
additional: string[]
|
|
23
|
+
additional: (string | [string, string])[]
|
|
32
24
|
}) => {
|
|
33
25
|
const duration = line.requestEnd - line.requestStart
|
|
34
26
|
const serverDuration = duration - line.serverStart
|
|
@@ -88,19 +80,20 @@ export const flushMeasurePerf = () => {
|
|
|
88
80
|
value.operationName,
|
|
89
81
|
// `${duration - (duration - serverStart)}ms`,
|
|
90
82
|
`${duration - serverStart}ms`,
|
|
83
|
+
value.additional ?? '',
|
|
91
84
|
],
|
|
92
85
|
colDivider,
|
|
93
86
|
})
|
|
94
87
|
})
|
|
95
88
|
|
|
96
89
|
const items = [
|
|
97
|
-
['Operation', 'Mesh', 'Timeline'],
|
|
90
|
+
['Operation', 'Mesh', ' Source', 'Timeline'],
|
|
98
91
|
...lines,
|
|
99
92
|
renderLine({
|
|
100
93
|
serverStart: 0,
|
|
101
94
|
requestStart: 0,
|
|
102
95
|
requestEnd: end,
|
|
103
|
-
additional: [`Total time`, `${end}ms
|
|
96
|
+
additional: [`Total time`, `${end}ms`, ''],
|
|
104
97
|
colDivider,
|
|
105
98
|
}),
|
|
106
99
|
]
|
|
@@ -109,16 +102,22 @@ export const flushMeasurePerf = () => {
|
|
|
109
102
|
const colWidths: number[] = Array(items[0].length).fill(0)
|
|
110
103
|
items.forEach((item) => {
|
|
111
104
|
item.forEach((t, index) => {
|
|
112
|
-
colWidths[index] = Math.max(colWidths[index], t.length)
|
|
105
|
+
colWidths[index] = Math.max(colWidths[index], Array.isArray(t) ? t[0].length : t.length)
|
|
113
106
|
})
|
|
114
107
|
})
|
|
115
108
|
|
|
116
109
|
// padd the items to the max length
|
|
117
110
|
items.forEach((item) => {
|
|
118
111
|
item.forEach((_, index) => {
|
|
119
|
-
|
|
120
|
-
index
|
|
121
|
-
|
|
112
|
+
const [str, link] = (
|
|
113
|
+
Array.isArray(item[index]) ? item[index] : [item[index], item[index]]
|
|
114
|
+
) as [string, string]
|
|
115
|
+
|
|
116
|
+
const val = (Array.isArray(item[index]) ? item[index][1] : item[index]) as string
|
|
117
|
+
|
|
118
|
+
const padLength = colWidths[index] + (val.length - str.length)
|
|
119
|
+
|
|
120
|
+
item[index] = `${val.padEnd(padLength, ' ')}${index !== item.length - 1 ? `` : ''}`
|
|
122
121
|
})
|
|
123
122
|
})
|
|
124
123
|
|
|
@@ -147,19 +146,51 @@ export const measurePerformanceLink = new ApolloLink((operation, forward) => {
|
|
|
147
146
|
Object.keys(operation.variables).length > 0 ? `(${JSON.stringify(operation.variables)})` : ''
|
|
148
147
|
const operationString = `${operation.operationName}${vars}`
|
|
149
148
|
|
|
150
|
-
running.set(operationString, {
|
|
149
|
+
running.set(operationString, {
|
|
150
|
+
start: new Date(),
|
|
151
|
+
operationName: [operation.operationName, operation.operationName],
|
|
152
|
+
})
|
|
151
153
|
markTimeout()
|
|
152
154
|
|
|
153
|
-
// console.info(`GraphQL start ${operationString}`)
|
|
154
155
|
return forward(operation).map((data) => {
|
|
155
|
-
const
|
|
156
|
+
const httpDetails: MeshFetchHTTPInformation[] | undefined = data.extensions?.httpDetails
|
|
157
|
+
|
|
158
|
+
let additional = [``, ``] as [string, string]
|
|
159
|
+
if (httpDetails) {
|
|
160
|
+
httpDetails.forEach((d) => {
|
|
161
|
+
const requestUrl = new URL(d.request.url)
|
|
162
|
+
requestUrl.searchParams.delete('extensions')
|
|
163
|
+
const title = `${d.sourceName} ${d.responseTime}ms`
|
|
164
|
+
additional = [
|
|
165
|
+
`${additional[0]} ${title}`,
|
|
166
|
+
`${additional[1]} ${cliHyperlink(title, requestUrl.toString().replace(/\+/g, '%20'))}`,
|
|
167
|
+
]
|
|
168
|
+
})
|
|
169
|
+
}
|
|
156
170
|
|
|
157
171
|
// Called after server responds
|
|
172
|
+
const query = [
|
|
173
|
+
`# Variables: ${JSON.stringify(operation.variables)}`,
|
|
174
|
+
`# Headers: ${JSON.stringify(operation.getContext().headers)}`,
|
|
175
|
+
print(operation.query),
|
|
176
|
+
].join('\n')
|
|
177
|
+
|
|
178
|
+
const meshUrl = new URL(`${import.meta.graphCommerce.canonicalBaseUrl}/api/graphql`)
|
|
179
|
+
meshUrl.searchParams.set('query', query)
|
|
180
|
+
|
|
158
181
|
running.set(operationString, {
|
|
159
|
-
internalStart: tracing ? new Date(tracing.startTime) : undefined,
|
|
160
182
|
start: operation.getContext().measurePerformanceLinkStart as Date,
|
|
161
183
|
end: new Date(),
|
|
162
|
-
operationName: operation.operationName,
|
|
184
|
+
operationName: [operation.operationName, operation.operationName],
|
|
185
|
+
additional,
|
|
186
|
+
// [
|
|
187
|
+
// operation.operationName,
|
|
188
|
+
// cliHyperlink(operation.operationName, meshUrl.toString()),
|
|
189
|
+
// ],
|
|
190
|
+
// additional: [
|
|
191
|
+
// `🔗 ${additional[0]}`,
|
|
192
|
+
// `${cliHyperlink('🔗', meshUrl.toString())} ${additional[1]}`,
|
|
193
|
+
// ],
|
|
163
194
|
})
|
|
164
195
|
|
|
165
196
|
markTimeout()
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/graphql",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "6.0.2-canary.
|
|
5
|
+
"version": "6.0.2-canary.10",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@apollo/client": "^3.7.10",
|
|
17
|
-
"@graphcommerce/graphql-codegen-near-operation-file": "6.0.2-canary.
|
|
18
|
-
"@graphcommerce/graphql-codegen-relay-optimizer-plugin": "6.0.2-canary.
|
|
17
|
+
"@graphcommerce/graphql-codegen-near-operation-file": "6.0.2-canary.10",
|
|
18
|
+
"@graphcommerce/graphql-codegen-relay-optimizer-plugin": "6.0.2-canary.10",
|
|
19
19
|
"@graphql-codegen/add": "4.0.1",
|
|
20
20
|
"@graphql-codegen/fragment-matcher": "4.0.1",
|
|
21
21
|
"@graphql-codegen/introspection": "3.0.1",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"graphql": "16.6.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@graphcommerce/eslint-config-pwa": "6.0.2-canary.
|
|
33
|
-
"@graphcommerce/prettier-config-pwa": "6.0.2-canary.
|
|
34
|
-
"@graphcommerce/typescript-config-pwa": "6.0.2-canary.
|
|
32
|
+
"@graphcommerce/eslint-config-pwa": "6.0.2-canary.10",
|
|
33
|
+
"@graphcommerce/prettier-config-pwa": "6.0.2-canary.10",
|
|
34
|
+
"@graphcommerce/typescript-config-pwa": "6.0.2-canary.10"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": "^18.2.0",
|