@kubun/provider-google 0.16.0 → 0.17.1
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 +32 -0
- package/lib/api.js +61 -0
- package/lib/index.d.ts +11 -3
- package/lib/index.js +23 -3
- package/package.json +4 -4
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,7 +1,15 @@
|
|
|
1
|
-
import type { OAuthProviderDefinition } from '@
|
|
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';
|
|
3
|
+
export declare const googleAuthorizationParams: Record<string, string>;
|
|
2
4
|
type CreateGoogleProviderParams = {
|
|
5
|
+
mode: 'confidential';
|
|
3
6
|
clientID: string;
|
|
4
7
|
clientSecret: string;
|
|
8
|
+
} | {
|
|
9
|
+
mode: 'native';
|
|
10
|
+
clientID: string;
|
|
11
|
+
clientSecret?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function createGoogleProvider(params: CreateGoogleProviderParams): OAuthProviderDefinition & {
|
|
14
|
+
authorizationParams?: Record<string, string>;
|
|
5
15
|
};
|
|
6
|
-
export declare function createGoogleProvider(params: CreateGoogleProviderParams): OAuthProviderDefinition;
|
|
7
|
-
export {};
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
export { createGoogleAPIClient, parseGoogleErrorBody } from './api.js';
|
|
2
|
+
export const googleAuthorizationParams = {
|
|
3
|
+
// Offline access requests a refresh token (issuance stays provider-dependent);
|
|
4
|
+
// consent keeps that guarantee for repeat authorizations. select_account forces
|
|
5
|
+
// the account chooser, avoiding the multi-account authuser dead-end.
|
|
6
|
+
access_type: 'offline',
|
|
7
|
+
prompt: 'select_account consent'
|
|
8
|
+
};
|
|
1
9
|
export function createGoogleProvider(params) {
|
|
2
10
|
if (!params.clientID) {
|
|
3
11
|
throw new Error('Google provider requires a non-empty clientID');
|
|
4
12
|
}
|
|
5
|
-
if (!params.clientSecret) {
|
|
6
|
-
throw new Error('Google provider requires a non-empty clientSecret');
|
|
13
|
+
if (params.mode === 'confidential' && !params.clientSecret) {
|
|
14
|
+
throw new Error('A confidential Google provider requires a non-empty clientSecret');
|
|
7
15
|
}
|
|
8
|
-
|
|
16
|
+
const base = {
|
|
9
17
|
name: 'google',
|
|
10
18
|
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
11
19
|
tokenEndpoint: 'https://oauth2.googleapis.com/token',
|
|
@@ -14,7 +22,19 @@ export function createGoogleProvider(params) {
|
|
|
14
22
|
'profile',
|
|
15
23
|
'email'
|
|
16
24
|
],
|
|
25
|
+
authorizationParams: googleAuthorizationParams
|
|
26
|
+
};
|
|
27
|
+
return params.mode === 'confidential' ? {
|
|
28
|
+
...base,
|
|
29
|
+
mode: 'confidential',
|
|
17
30
|
clientID: params.clientID,
|
|
18
31
|
clientSecret: params.clientSecret
|
|
32
|
+
} : {
|
|
33
|
+
...base,
|
|
34
|
+
mode: 'native',
|
|
35
|
+
clientID: params.clientID,
|
|
36
|
+
...params.clientSecret ? {
|
|
37
|
+
clientSecret: params.clientSecret
|
|
38
|
+
} : {}
|
|
19
39
|
};
|
|
20
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/provider-google",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
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
|
-
"@
|
|
18
|
+
"@kokuin/oauth": "^0.1.1"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
25
25
|
"build:clean": "del lib",
|
|
26
|
-
"build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
27
|
-
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
26
|
+
"build:js": "del 'lib/**/*.js' && swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
27
|
+
"build:types": "del 'lib/**/*.d.ts' 'lib/**/*.d.ts.map' && tsc --emitDeclarationOnly --skipLibCheck",
|
|
28
28
|
"build:types:ci": "tsc --emitDeclarationOnly --declarationMap false",
|
|
29
29
|
"test": "pnpm run test:types && pnpm run test:unit",
|
|
30
30
|
"test:types": "tsc --noEmit -p tsconfig.test.json",
|