@kubun/provider-google 0.17.0 → 0.18.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/lib/api.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ export type GoogleErrorBody = {
2
+ message: string;
3
+ status?: string;
4
+ };
5
+ export type GoogleAPIFailure = {
6
+ httpStatus: number;
7
+ message: string;
8
+ googleStatus?: string;
9
+ };
10
+ export type GoogleAPIClientConfig = {
11
+ api: string;
12
+ accessToken: string;
13
+ fetch?: typeof globalThis.fetch;
14
+ toError: (failure: GoogleAPIFailure) => Error;
15
+ };
16
+ export type GoogleAPIGetOptions = {
17
+ signal?: AbortSignal;
18
+ };
19
+ export type GoogleAPISendOptions = {
20
+ method: string;
21
+ body?: unknown;
22
+ headers?: Record<string, string>;
23
+ signal?: AbortSignal;
24
+ };
25
+ export type GoogleAPIClient = {
26
+ get<T>(url: string, options?: GoogleAPIGetOptions): Promise<T>;
27
+ send<T>(url: string, options: GoogleAPISendOptions): Promise<T>;
28
+ request(url: string, options?: GoogleAPISendOptions): Promise<Response>;
29
+ fail(response: Response): Promise<never>;
30
+ };
31
+ export declare function parseGoogleErrorBody(response: Response): Promise<GoogleErrorBody>;
32
+ export declare function createGoogleAPIClient(config: GoogleAPIClientConfig): GoogleAPIClient;
package/lib/api.js ADDED
@@ -0,0 +1,61 @@
1
+ export async function parseGoogleErrorBody(response) {
2
+ try {
3
+ const body = await response.json();
4
+ return {
5
+ message: body.error?.message ?? `${response.status} ${response.statusText}`,
6
+ status: body.error?.status
7
+ };
8
+ } catch {
9
+ return {
10
+ message: `${response.status} ${response.statusText}`
11
+ };
12
+ }
13
+ }
14
+ export function createGoogleAPIClient(config) {
15
+ const fetchFn = config.fetch ?? globalThis.fetch;
16
+ async function request(url, options) {
17
+ return fetchFn(url, {
18
+ ...options?.method != null ? {
19
+ method: options.method
20
+ } : {},
21
+ headers: {
22
+ Authorization: `Bearer ${config.accessToken}`,
23
+ ...options?.body !== undefined ? {
24
+ 'Content-Type': 'application/json'
25
+ } : {},
26
+ ...options?.headers
27
+ },
28
+ ...options?.body !== undefined ? {
29
+ body: JSON.stringify(options.body)
30
+ } : {},
31
+ signal: options?.signal
32
+ });
33
+ }
34
+ async function fail(response) {
35
+ const detail = await parseGoogleErrorBody(response);
36
+ throw config.toError({
37
+ httpStatus: response.status,
38
+ message: `${config.api} error: ${detail.message}`,
39
+ googleStatus: detail.status
40
+ });
41
+ }
42
+ async function get(url, options) {
43
+ const response = await request(url, {
44
+ method: 'GET',
45
+ signal: options?.signal
46
+ });
47
+ if (!response.ok) return fail(response);
48
+ return await response.json();
49
+ }
50
+ async function send(url, options) {
51
+ const response = await request(url, options);
52
+ if (!response.ok) return fail(response);
53
+ return await response.json();
54
+ }
55
+ return {
56
+ get,
57
+ send,
58
+ request,
59
+ fail
60
+ };
61
+ }
package/lib/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import type { OAuthProviderDefinition } from '@kokuin/oauth';
2
+ export { createGoogleAPIClient, type GoogleAPIClient, type GoogleAPIClientConfig, type GoogleAPIFailure, type GoogleAPIGetOptions, type GoogleAPISendOptions, type GoogleErrorBody, parseGoogleErrorBody, } from './api.js';
2
3
  export declare const googleAuthorizationParams: Record<string, string>;
4
+ type GoogleExistingCredential = {
5
+ accessToken: string;
6
+ scopes: Array<string>;
7
+ metadata?: Record<string, unknown>;
8
+ };
3
9
  type CreateGoogleProviderParams = {
4
10
  mode: 'confidential';
5
11
  clientID: string;
@@ -11,5 +17,5 @@ type CreateGoogleProviderParams = {
11
17
  };
12
18
  export declare function createGoogleProvider(params: CreateGoogleProviderParams): OAuthProviderDefinition & {
13
19
  authorizationParams?: Record<string, string>;
20
+ incrementalAuthorizationParams?: (existing: GoogleExistingCredential) => Record<string, string>;
14
21
  };
15
- export {};
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { createGoogleAPIClient, parseGoogleErrorBody } from './api.js';
1
2
  export const googleAuthorizationParams = {
2
3
  // Offline access requests a refresh token (issuance stays provider-dependent);
3
4
  // consent keeps that guarantee for repeat authorizations. select_account forces
@@ -21,7 +22,14 @@ export function createGoogleProvider(params) {
21
22
  'profile',
22
23
  'email'
23
24
  ],
24
- authorizationParams: googleAuthorizationParams
25
+ authorizationParams: googleAuthorizationParams,
26
+ incrementalAuthorizationParams: (existing)=>({
27
+ include_granted_scopes: 'true',
28
+ prompt: 'consent',
29
+ ...typeof existing.metadata?.googleAccountEmail === 'string' ? {
30
+ login_hint: existing.metadata.googleAccountEmail
31
+ } : {}
32
+ })
25
33
  };
26
34
  return params.mode === 'confidential' ? {
27
35
  ...base,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/provider-google",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -15,7 +15,7 @@
15
15
  "LICENSE.md"
16
16
  ],
17
17
  "dependencies": {
18
- "@kokuin/oauth": "^0.1.0"
18
+ "@kokuin/oauth": "^0.1.1"
19
19
  },
20
20
  "publishConfig": {
21
21
  "access": "public"