Skip to content

Commit b854652

Browse files
authored
feat(graph): update graph helpers to work better with next.js (#354)
* feat(graph): update graph helpers to work better with next.js * chore(graph): update type
1 parent b51b391 commit b854652

File tree

5 files changed

+77
-39
lines changed

5 files changed

+77
-39
lines changed

src/function/event.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ export interface Event {
2525
multiValueQueryStringParameters: EventMultiValueQueryStringParameters | null
2626
body: string | null
2727
isBase64Encoded: boolean
28+
netlifyGraphToken: string | undefined
2829
}

src/function/index.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,13 @@ export { Context as HandlerContext } from './context'
22
export { Event as HandlerEvent } from './event'
33
export { Handler, HandlerCallback } from './handler'
44
export { Response as HandlerResponse } from './response'
5-
export { getSecrets, withSecrets, getNetlifyGraphToken, GraphTokenResponse, HasHeaders } from '../lib/graph'
5+
export {
6+
getSecrets,
7+
getSecretsForBuild,
8+
withSecrets,
9+
getNetlifyGraphToken,
10+
getNetlifyGraphTokenForBuild,
11+
GraphTokenResponse,
12+
HasHeaders,
13+
} from '../lib/graph'
614
export { NetlifySecrets } from '../lib/secrets_helper'

src/lib/graph.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { Response } from '../function/response'
55

66
import { getSecrets, NetlifySecrets } from './secrets_helper'
77
// Fine-grained control during the preview, less necessary with a more proactive OneGraph solution
8-
export { getSecrets } from './secrets_helper'
9-
export { getNetlifyGraphToken, GraphTokenResponse, HasHeaders } from './graph_token'
8+
export { getSecrets, getSecretsForBuild } from './secrets_helper'
9+
export { getNetlifyGraphToken, getNetlifyGraphTokenForBuild, GraphTokenResponse, HasHeaders } from './graph_token'
1010

1111
export interface ContextWithSecrets extends Context {
1212
secrets: NetlifySecrets

src/lib/graph_token.ts

+30-16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type GraphTokenResponse = {
1111
}
1212

1313
const TOKEN_HEADER = 'X-Nf-Graph-Token'
14+
const TOKEN_HEADER_NORMALIZED = 'x-nf-graph-token'
1415

1516
// Matches Web API Headers type (https://developer.mozilla.org/en-US/docs/Web/API/Headers)
1617
interface RequestHeaders {
@@ -33,21 +34,37 @@ const hasRequestStyleHeaders = function (headers: RequestHeaders | IncomingHttpH
3334
const graphTokenFromIncomingHttpStyleHeaders = function (
3435
headers: RequestHeaders | IncomingHttpHeaders,
3536
): string | null | undefined {
36-
if (TOKEN_HEADER in headers) {
37-
const header = headers[TOKEN_HEADER]
38-
if (header == null || typeof header === 'string') {
39-
return header
37+
if (TOKEN_HEADER in headers || TOKEN_HEADER_NORMALIZED in headers) {
38+
const header = headers[TOKEN_HEADER] || headers[TOKEN_HEADER_NORMALIZED]
39+
if (Array.isArray(header)) {
40+
return header[0]
4041
}
41-
return header[0]
42+
return header
4243
}
4344
}
4445

45-
// Backwards compatibility with older version of cli that doesn't inject header
46-
const authlifyTokenFallback = function (event: HasHeaders): GraphTokenResponse {
47-
const token = (event as { authlifyToken?: string | null })?.authlifyToken
46+
const graphTokenFromEnv = function (): GraphTokenResponse {
47+
// _NETLIFY_GRAPH_TOKEN injected by next plugin
48+
// eslint-disable-next-line no-underscore-dangle
49+
const token = env._NETLIFY_GRAPH_TOKEN || env.NETLIFY_GRAPH_TOKEN
4850
return { token }
4951
}
5052

53+
const tokenFallback = function (event: HasHeaders): GraphTokenResponse {
54+
// Backwards compatibility with older version of cli that doesn't inject header
55+
const token = (event as { authlifyToken?: string | null })?.authlifyToken
56+
if (token) {
57+
return { token }
58+
}
59+
60+
// If we're in dev-mode with next.js, the plugin won't be there to inject
61+
// secrets, so we need to get the token from the environment
62+
if (env.NETLIFY_DEV === 'true') {
63+
return graphTokenFromEnv()
64+
}
65+
return { token: null }
66+
}
67+
5168
const graphTokenFromEvent = function (event: HasHeaders): GraphTokenResponse {
5269
const { headers } = event
5370
// Check if object first in case there is a header with key `get`
@@ -60,14 +77,7 @@ const graphTokenFromEvent = function (event: HasHeaders): GraphTokenResponse {
6077
return { token: headers.get(TOKEN_HEADER) }
6178
}
6279

63-
return authlifyTokenFallback(event)
64-
}
65-
66-
const graphTokenFromEnv = function (): GraphTokenResponse {
67-
// _NETLIFY_GRAPH_TOKEN injected by next plugin
68-
// eslint-disable-next-line no-underscore-dangle
69-
const token = env._NETLIFY_GRAPH_TOKEN || env.NETLIFY_GRAPH_TOKEN
70-
return { token }
80+
return tokenFallback(event)
7181
}
7282

7383
const isEventRequired = function (): boolean {
@@ -125,3 +135,7 @@ export const getNetlifyGraphToken = function (
125135

126136
return event ? graphTokenFromEvent(event) : graphTokenFromEnv()
127137
}
138+
139+
export const getNetlifyGraphTokenForBuild = function (): GraphTokenResponse {
140+
return graphTokenFromEnv()
141+
}

src/lib/secrets_helper.ts

+35-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { graphRequest } from './graph_request'
2-
import { getNetlifyGraphToken, GraphTokenResponseError, HasHeaders } from './graph_token'
2+
import { getNetlifyGraphToken, getNetlifyGraphTokenForBuild, GraphTokenResponseError, HasHeaders } from './graph_token'
33

44
const services = {
55
gitHub: null,
@@ -102,23 +102,11 @@ const logErrors = function (errors: GraphTokenResponseError[]) {
102102
}
103103
}
104104

105-
// Note: We may want to have configurable "sets" of secrets,
106-
// e.g. "dev" and "prod"
107-
export const getSecrets = async (event?: HasHeaders | null | undefined): Promise<NetlifySecrets> => {
108-
const graphTokenResponse = getNetlifyGraphToken(event, true)
109-
const graphToken = graphTokenResponse.token
110-
if (!graphToken) {
111-
if (graphTokenResponse.errors) {
112-
logErrors(graphTokenResponse.errors)
113-
}
114-
return {}
115-
}
116-
117-
// We select for more than we typeically need here
118-
// in order to allow for some metaprogramming for
119-
// consumers downstream. Also, the data is typically
120-
// static and shouldn't add any measurable overhead.
121-
const doc = `query FindLoggedInServicesQuery {
105+
// We select for more than we typically need here
106+
// in order to allow for some metaprogramming for
107+
// consumers downstream. Also, the data is typically
108+
// static and shouldn't add any measurable overhead.
109+
const findLoggedInServicesQuery = `query FindLoggedInServicesQuery {
122110
me {
123111
serviceMetadata {
124112
loggedInServices {
@@ -143,13 +131,40 @@ export const getSecrets = async (event?: HasHeaders | null | undefined): Promise
143131
}
144132
}`
145133

146-
const body = JSON.stringify({ query: doc })
134+
const getSecretsForToken = async (token: string): Promise<NetlifySecrets> => {
135+
const body = JSON.stringify({ query: findLoggedInServicesQuery })
147136

148137
// eslint-disable-next-line node/no-unsupported-features/node-builtins
149-
const resultBody = await graphRequest(graphToken, new TextEncoder().encode(body))
138+
const resultBody = await graphRequest(token, new TextEncoder().encode(body))
150139
const result: GraphSecretsResponse = JSON.parse(resultBody)
151140

152141
const newSecrets = formatSecrets(result)
153142

154143
return newSecrets
155144
}
145+
146+
export const getSecrets = async (event?: HasHeaders | null | undefined): Promise<NetlifySecrets> => {
147+
const graphTokenResponse = getNetlifyGraphToken(event, true)
148+
const graphToken = graphTokenResponse.token
149+
if (!graphToken) {
150+
if (graphTokenResponse.errors) {
151+
logErrors(graphTokenResponse.errors)
152+
}
153+
return {}
154+
}
155+
156+
return await getSecretsForToken(graphToken)
157+
}
158+
159+
export const getSecretsForBuild = async (): Promise<NetlifySecrets> => {
160+
const graphTokenResponse = getNetlifyGraphTokenForBuild()
161+
const graphToken = graphTokenResponse.token
162+
if (!graphToken) {
163+
if (graphTokenResponse.errors) {
164+
logErrors(graphTokenResponse.errors)
165+
}
166+
return {}
167+
}
168+
169+
return await getSecretsForToken(graphToken)
170+
}

0 commit comments

Comments
 (0)