Skip to content

Commit 9ee4ba8

Browse files
committed
Generate common class methods
1 parent 2211871 commit 9ee4ba8

4 files changed

Lines changed: 189 additions & 3 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
client: Client
2+
readonly defaults: Required<SeamHttpRequestOptions>
3+
readonly ltsVersion = seamApiLtsVersion
4+
static ltsVersion = seamApiLtsVersion
5+
6+
constructor(apiKeyOrOptions: string | SeamHttpOptions = {}) {
7+
const options = parseOptions(apiKeyOrOptions)
8+
this.client = 'client' in options ? options.client : createClient(options)
9+
this.defaults = limitToSeamHttpRequestOptions(options)
10+
}
11+
12+
static fromClient(
13+
client: SeamHttpOptionsWithClient['client'],
14+
options: Omit<SeamHttpOptionsWithClient, 'client'> = {},
15+
): {{className}} {
16+
const constructorOptions = { ...options, client }
17+
if (!isSeamHttpOptionsWithClient(constructorOptions)) {
18+
throw new SeamHttpInvalidOptionsError('Missing client')
19+
}
20+
return new {{className}}(constructorOptions)
21+
}
22+
23+
static fromApiKey(
24+
apiKey: SeamHttpOptionsWithApiKey['apiKey'],
25+
options: Omit<SeamHttpOptionsWithApiKey, 'apiKey'> = {},
26+
): {{className}} {
27+
const constructorOptions = { ...options, apiKey }
28+
if (!isSeamHttpOptionsWithApiKey(constructorOptions)) {
29+
throw new SeamHttpInvalidOptionsError('Missing apiKey')
30+
}
31+
return new {{className}}(constructorOptions)
32+
}
33+
34+
static fromClientSessionToken(
35+
clientSessionToken: SeamHttpOptionsWithClientSessionToken['clientSessionToken'],
36+
options: Omit<
37+
SeamHttpOptionsWithClientSessionToken,
38+
'clientSessionToken'
39+
> = {},
40+
): {{className}} {
41+
const constructorOptions = { ...options, clientSessionToken }
42+
if (!isSeamHttpOptionsWithClientSessionToken(constructorOptions)) {
43+
throw new SeamHttpInvalidOptionsError('Missing clientSessionToken')
44+
}
45+
return new {{className}}(constructorOptions)
46+
}
47+
48+
static async fromPublishableKey(
49+
publishableKey: string,
50+
userIdentifierKey: string,
51+
options: SeamHttpFromPublishableKeyOptions = {},
52+
): Promise<{{className}}> {
53+
warnOnInsecureuserIdentifierKey(userIdentifierKey)
54+
const clientOptions = parseOptions({ ...options, publishableKey })
55+
if (isSeamHttpOptionsWithClient(clientOptions)) {
56+
throw new SeamHttpInvalidOptionsError(
57+
'The client option cannot be used with {{className}}.fromPublishableKey',
58+
)
59+
}
60+
const client = createClient(clientOptions)
61+
const clientSessions = SeamHttpClientSessions.fromClient(client)
62+
const { token } = await clientSessions.getOrCreate({
63+
user_identifier_key: userIdentifierKey,
64+
})
65+
return {{className}}.fromClientSessionToken(token, options)
66+
}
67+
68+
static fromConsoleSessionToken(
69+
consoleSessionToken: SeamHttpOptionsWithConsoleSessionToken['consoleSessionToken'],
70+
workspaceId: SeamHttpOptionsWithConsoleSessionToken['workspaceId'],
71+
options: Omit<
72+
SeamHttpOptionsWithConsoleSessionToken,
73+
'consoleSessionToken' | 'workspaceId'
74+
> = {},
75+
): {{className}} {
76+
const constructorOptions = { ...options, consoleSessionToken, workspaceId }
77+
if (!isSeamHttpOptionsWithConsoleSessionToken(constructorOptions)) {
78+
throw new SeamHttpInvalidOptionsError(
79+
'Missing consoleSessionToken or workspaceId',
80+
)
81+
}
82+
return new {{className}}(constructorOptions)
83+
}
84+
85+
static fromPersonalAccessToken(
86+
personalAccessToken: SeamHttpOptionsWithPersonalAccessToken['personalAccessToken'],
87+
workspaceId: SeamHttpOptionsWithPersonalAccessToken['workspaceId'],
88+
options: Omit<
89+
SeamHttpOptionsWithPersonalAccessToken,
90+
'personalAccessToken' | 'workspaceId'
91+
> = {},
92+
): {{className}} {
93+
const constructorOptions = { ...options, personalAccessToken, workspaceId }
94+
if (!isSeamHttpOptionsWithPersonalAccessToken(constructorOptions)) {
95+
throw new SeamHttpInvalidOptionsError(
96+
'Missing personalAccessToken or workspaceId',
97+
)
98+
}
99+
return new {{className}}(constructorOptions)
100+
}
101+
102+
createPaginator<const TResponse, const TResponseKey extends keyof TResponse>(
103+
request: SeamHttpRequest<TResponse, TResponseKey>,
104+
): SeamPaginator<TResponse, TResponseKey> {
105+
return new SeamPaginator<TResponse, TResponseKey>(this, request)
106+
}
107+
108+
async updateClientSessionToken(
109+
clientSessionToken: SeamHttpOptionsWithClientSessionToken['clientSessionToken'],
110+
): Promise<void> {
111+
const { headers } = this.client.defaults
112+
const authHeaders = getAuthHeadersForClientSessionToken({
113+
clientSessionToken,
114+
})
115+
for (const key of Object.keys(authHeaders)) {
116+
if (headers[key] == null) {
117+
throw new Error(
118+
'Cannot update a clientSessionToken on a client created without a clientSessionToken',
119+
)
120+
}
121+
}
122+
this.client.defaults.headers = { ...headers, ...authHeaders }
123+
const clientSessions = SeamHttpClientSessions.fromClient(this.client)
124+
await clientSessions.get()
125+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type {
2+
RouteRequestBody,
3+
RouteRequestParams,
4+
RouteResponse,
5+
} from '@seamapi/types/connect'
6+
import type { SetNonNullable } from 'lib/types.js'
7+
8+
import {
9+
getAuthHeadersForClientSessionToken,
10+
warnOnInsecureuserIdentifierKey,
11+
} from 'lib/seam/connect/auth.js'
12+
import {
13+
type Client,
14+
type ClientOptions,
15+
createClient,
16+
} from 'lib/seam/connect/client.js'
17+
import {
18+
isSeamHttpOptionsWithApiKey,
19+
isSeamHttpOptionsWithClient,
20+
isSeamHttpOptionsWithClientSessionToken,
21+
isSeamHttpOptionsWithConsoleSessionToken,
22+
isSeamHttpOptionsWithPersonalAccessToken,
23+
type SeamHttpFromPublishableKeyOptions,
24+
SeamHttpInvalidOptionsError,
25+
type SeamHttpOptions,
26+
type SeamHttpOptionsWithApiKey,
27+
type SeamHttpOptionsWithClient,
28+
type SeamHttpOptionsWithClientSessionToken,
29+
type SeamHttpOptionsWithConsoleSessionToken,
30+
type SeamHttpOptionsWithPersonalAccessToken,
31+
type SeamHttpRequestOptions,
32+
} from 'lib/seam/connect/options.js'
33+
import {
34+
limitToSeamHttpRequestOptions,
35+
parseOptions
36+
} from 'lib/seam/connect/parse-options.js'
37+
import { SeamHttpRequest } from 'lib/seam/connect/seam-http-request.js'
38+
import { SeamPaginator } from 'lib/seam/connect/seam-paginator.js'
39+
40+
{{#if isClientSessionRoute}}
41+
import { SeamHttpClientSessions } from './client-sessions.js'
42+
{{/if}}
43+
44+
{{#if needsActionAttempts}}
45+
import {
46+
resolveActionAttempt,
47+
} from 'lib/seam/connect/resolve-action-attempt.js'
48+
{{#unless isActionAttemptsRoute}}
49+
import { SeamHttpActionAttempts } from './action-attempts.js'
50+
{{/unless}}
51+
{{/if}}

codegen/layouts/route.hbs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
{{contents}}
1+
{{> route-imports }}
2+
3+
class {{routeName}} {
4+
{{> route-class-methods }}
5+
}

codegen/lib/connect.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@ export const connect = (
3232
}
3333

3434
interface RouteLayoutContext {
35-
routeName: string
35+
className: string
36+
isClientSessionRoute: boolean
37+
isActionAttemptsRoute: boolean
38+
needsActionAttempts: boolean
3639
}
3740

3841
const setRouteLayoutContext = (
3942
file: Partial<RouteLayoutContext>,
4043
route: Route,
4144
_blueprint: Blueprint,
4245
): void => {
43-
file.routeName = pascalCase(route.name)
46+
file.className = `SeamHttp${pascalCase(route.name)}`
47+
file.needsActionAttempts = false
48+
file.isClientSessionRoute = route.name === '/client_sessions'
49+
file.isActionAttemptsRoute = route.name === '/action_attempts'
4450
}

0 commit comments

Comments
 (0)