@anmiles/google-api-wrapper 17.0.9 → 18.0.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.
Files changed (67) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.js +23 -7
  3. package/.vscode/settings.json +1 -0
  4. package/CHANGELOG.md +6 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/api.d.ts +16 -16
  9. package/dist/lib/api.d.ts.map +1 -1
  10. package/dist/lib/api.js +9 -7
  11. package/dist/lib/api.js.map +1 -1
  12. package/dist/lib/auth.d.ts +3 -3
  13. package/dist/lib/auth.d.ts.map +1 -1
  14. package/dist/lib/auth.js +1 -1
  15. package/dist/lib/auth.js.map +1 -1
  16. package/dist/lib/paths.d.ts +5 -5
  17. package/dist/lib/paths.d.ts.map +1 -1
  18. package/dist/lib/paths.js +1 -1
  19. package/dist/lib/paths.js.map +1 -1
  20. package/dist/lib/profiles.d.ts +4 -4
  21. package/dist/lib/profiles.d.ts.map +1 -1
  22. package/dist/lib/profiles.js +4 -4
  23. package/dist/lib/profiles.js.map +1 -1
  24. package/dist/lib/renderer.d.ts +2 -2
  25. package/dist/lib/renderer.d.ts.map +1 -1
  26. package/dist/lib/renderer.js +1 -1
  27. package/dist/lib/renderer.js.map +1 -1
  28. package/dist/lib/secrets.d.ts +14 -13
  29. package/dist/lib/secrets.d.ts.map +1 -1
  30. package/dist/lib/secrets.js +13 -12
  31. package/dist/lib/secrets.js.map +1 -1
  32. package/dist/types/options.d.ts +9 -0
  33. package/dist/types/options.d.ts.map +1 -0
  34. package/dist/types/{common.js → options.js} +1 -1
  35. package/dist/types/options.js.map +1 -0
  36. package/dist/types/secrets.d.ts +2 -5
  37. package/dist/types/secrets.d.ts.map +1 -1
  38. package/jest.config.js +3 -11
  39. package/package.json +63 -56
  40. package/src/index.ts +2 -0
  41. package/src/lib/__tests__/api.test.ts +30 -24
  42. package/src/lib/__tests__/auth.test.ts +4 -5
  43. package/src/lib/__tests__/paths.test.ts +6 -5
  44. package/src/lib/__tests__/profiles.test.ts +17 -27
  45. package/src/lib/__tests__/renderer.test.ts +7 -7
  46. package/src/lib/__tests__/secrets.test.ts +54 -77
  47. package/src/lib/api.ts +36 -26
  48. package/src/lib/auth.ts +5 -5
  49. package/src/lib/paths.ts +8 -8
  50. package/src/lib/profiles.ts +6 -6
  51. package/src/lib/renderer.ts +8 -9
  52. package/src/lib/secrets.ts +22 -19
  53. package/src/types/options.ts +10 -0
  54. package/src/types/secrets.ts +9 -13
  55. package/tsconfig.build.json +2 -2
  56. package/tsconfig.json +5 -5
  57. package/tsconfig.test.json +3 -3
  58. package/.github/workflows/ci.yml +0 -94
  59. package/dist/types/common.d.ts +0 -4
  60. package/dist/types/common.d.ts.map +0 -1
  61. package/dist/types/common.js.map +0 -1
  62. package/dist/types/index.d.ts +0 -3
  63. package/dist/types/index.d.ts.map +0 -1
  64. package/dist/types/index.js +0 -19
  65. package/dist/types/index.js.map +0 -1
  66. package/src/types/common.ts +0 -3
  67. package/src/types/index.ts +0 -2
@@ -2,8 +2,6 @@ import fs from 'fs';
2
2
  import renderer from './renderer';
3
3
  import { getTemplateFile } from './paths';
4
4
 
5
- export { templates, renderAuth, renderDone };
6
-
7
5
  const templates = {
8
6
  page : [ 'css', 'content' ] as const,
9
7
  css : [ ] as const,
@@ -16,9 +14,9 @@ type TemplateName = keyof typeof templates;
16
14
 
17
15
  const allHTML = {} as Record<TemplateName, string>;
18
16
 
19
- function renderAuth({ profile, authUrl, scope }: { profile: string, authUrl: string, scope: string[] }) {
17
+ function renderAuth({ profile, authUrl, scope }: { profile : string; authUrl : string; scope : string[] }): string {
20
18
  const scopesList = scope.map((s) => render('scope', {
21
- name : s.split('/').pop() as string,
19
+ name : s.split('/').pop()!,
22
20
  title : s.endsWith('.readonly') ? 'Readonly (cannot change or delete your data)' : 'Writable (can change or delete your data)',
23
21
  type : s.endsWith('.readonly') ? 'readonly' : '',
24
22
  })).join('\n');
@@ -28,26 +26,26 @@ function renderAuth({ profile, authUrl, scope }: { profile: string, authUrl: str
28
26
  return render('page', { css, content });
29
27
  }
30
28
 
31
- function renderDone({ profile }: { profile: string }): string {
29
+ function renderDone({ profile }: { profile : string }): string {
32
30
  const css = render('css', {});
33
31
  const content = render('done', { profile });
34
32
  return render('page', { css, content });
35
33
  }
36
34
 
37
35
  // TODO: Use react
38
- function render<T extends TemplateName>(templateName: T, values: Record<typeof templates[T][number], string>): string {
36
+ function render<T extends TemplateName>(templateName: T, values: Record<typeof templates[T][number], string | undefined>): string {
39
37
  let html = renderer.getTemplate(templateName);
40
- const allValues = values as Record<typeof templates[TemplateName][number], string>;
38
+ const allValues = values as Record<typeof templates[TemplateName][number], string | undefined>;
41
39
 
42
40
  for (const variable of templates[templateName]) {
43
- const value = allValues[variable] || '';
41
+ const value = allValues[variable] ?? '';
44
42
  html = html.replace(`\${${variable}}`, value);
45
43
  }
46
44
 
47
45
  return html;
48
46
  }
49
47
 
50
- function getTemplate(templateName: TemplateName) {
48
+ function getTemplate(templateName: TemplateName): string {
51
49
  if (!(templateName in allHTML)) {
52
50
  const file = getTemplateFile(templateName);
53
51
  const template = fs.readFileSync(file).toString();
@@ -57,4 +55,5 @@ function getTemplate(templateName: TemplateName) {
57
55
  return allHTML[templateName];
58
56
  }
59
57
 
58
+ export { templates, renderAuth, renderDone };
60
59
  export default { templates, render, getTemplate, renderAuth, renderDone };
@@ -4,16 +4,14 @@ import { open } from 'out-url';
4
4
  import enableDestroy from 'server-destroy';
5
5
  import type GoogleApis from 'googleapis';
6
6
  import { warn } from '@anmiles/logger';
7
- import type { Secrets, AuthOptions } from '../types';
7
+ import type { Secrets } from '../types/secrets';
8
+ import type { AuthOptions } from '../types/options';
8
9
  import '@anmiles/prototypes';
9
10
  import { getScopesFile, getSecretsFile, getCredentialsFile } from './paths';
10
11
  import { renderAuth, renderDone } from './renderer';
11
12
 
12
13
  import secrets from './secrets';
13
14
 
14
- export { getSecrets, getCredentials, deleteCredentials };
15
- export default { getScopes, getSecrets, getCredentials, validateCredentials, createCredentials, deleteCredentials, checkSecrets, getSecretsError, getScopesError };
16
-
17
15
  const port = 6006;
18
16
  const host = `localhost:${port}`;
19
17
  const startURI = `http://${host}/`;
@@ -24,7 +22,7 @@ const serverRetryInterval = 1000;
24
22
  function getScopes(): string[] {
25
23
  const scopesFile = getScopesFile();
26
24
  const scopes = fs.getJSON<string[]>(scopesFile, () => {
27
- throw secrets.getScopesError(scopesFile);
25
+ throw new Error(secrets.getScopesError(scopesFile));
28
26
  });
29
27
  return scopes;
30
28
  }
@@ -32,7 +30,7 @@ function getScopes(): string[] {
32
30
  function getSecrets(profile: string): Secrets {
33
31
  const secretsFile = getSecretsFile(profile);
34
32
  const secretsObject = fs.getJSON<Secrets>(secretsFile, () => {
35
- throw secrets.getSecretsError(profile, secretsFile);
33
+ throw new Error(secrets.getSecretsError(profile, secretsFile));
36
34
  });
37
35
  secrets.checkSecrets(profile, secretsObject, secretsFile);
38
36
  return secretsObject;
@@ -48,12 +46,12 @@ async function getCredentials(profile: string, auth: GoogleApis.Common.OAuth2Cli
48
46
  return fs.getJSONAsync(credentialsFile, async () => {
49
47
  const refreshToken = fs.existsSync(credentialsFile) ? fs.readJSON<GoogleApis.Auth.Credentials>(credentialsFile).refresh_token : undefined;
50
48
  const credentials = await secrets.createCredentials(profile, auth, options, refreshToken ? undefined : 'consent');
51
- // eslint-disable-next-line camelcase
52
49
  return { refresh_token : refreshToken, ...credentials };
53
50
  }, secrets.validateCredentials);
54
51
  }
55
52
 
56
- async function validateCredentials(credentials: GoogleApis.Auth.Credentials): Promise<{ isValid: boolean, validationError?: string}> {
53
+ // eslint-disable-next-line @typescript-eslint/require-await -- pass sync function into async context
54
+ async function validateCredentials(credentials: GoogleApis.Auth.Credentials): Promise<{ isValid : boolean; validationError? : string }> {
57
55
  if (!credentials.access_token) {
58
56
  return { isValid : false, validationError : 'Credentials does not have access_token' };
59
57
  }
@@ -74,11 +72,10 @@ async function validateCredentials(credentials: GoogleApis.Auth.Credentials): Pr
74
72
  }
75
73
 
76
74
  async function createCredentials(profile: string, auth: GoogleApis.Auth.OAuth2Client, options?: AuthOptions, prompt?: GoogleApis.Auth.GenerateAuthUrlOpts['prompt']): Promise<GoogleApis.Auth.Credentials> {
77
- const scope = options?.scopes || secrets.getScopes();
75
+ const scope = options?.scopes ?? secrets.getScopes();
78
76
 
79
77
  return new Promise((resolve) => {
80
78
  const authUrl = auth.generateAuthUrl({
81
- // eslint-disable-next-line camelcase
82
79
  access_type : 'offline',
83
80
  prompt,
84
81
  scope,
@@ -87,7 +84,7 @@ async function createCredentials(profile: string, auth: GoogleApis.Auth.OAuth2Cl
87
84
  const server = http.createServer();
88
85
  enableDestroy(server);
89
86
 
90
- server.on('request', async (request, response) => {
87
+ server.on('request', (request, response) => {
91
88
  if (!request.url) {
92
89
  response.end('');
93
90
  return;
@@ -103,8 +100,11 @@ async function createCredentials(profile: string, auth: GoogleApis.Auth.OAuth2Cl
103
100
 
104
101
  response.end(renderDone({ profile }));
105
102
  server.destroy();
106
- const { tokens } = await auth.getToken(code);
107
- resolve(tokens);
103
+
104
+ void (async () => {
105
+ const { tokens } = await auth.getToken(code);
106
+ resolve(tokens);
107
+ })();
108
108
  });
109
109
 
110
110
  server.on('error', (error: NodeJS.ErrnoException) => {
@@ -115,9 +115,9 @@ async function createCredentials(profile: string, auth: GoogleApis.Auth.OAuth2Cl
115
115
  }
116
116
  });
117
117
 
118
- server.once('listening', async () => {
118
+ server.once('listening', () => {
119
119
  warn('Please check your browser for further actions');
120
- open(startURI);
120
+ void open(startURI);
121
121
  });
122
122
 
123
123
  server.listen(port);
@@ -132,21 +132,21 @@ function deleteCredentials(profile: string): void {
132
132
  }
133
133
  }
134
134
 
135
- function checkSecrets(profile: string, secretsObject: Secrets, secretsFile: string): true | void {
135
+ function checkSecrets(profile: string, secretsObject: Secrets, secretsFile: string): true {
136
136
  if (secretsObject.web.redirect_uris[0] === callbackURI) {
137
137
  return true;
138
138
  }
139
- throw `Error in credentials file: redirect URI should be ${callbackURI}.\n${secrets.getSecretsError(profile, secretsFile)}`;
139
+ throw new Error(`Error in credentials file: redirect URI should be ${callbackURI}.\n${secrets.getSecretsError(profile, secretsFile)}`);
140
140
  }
141
141
 
142
- function getScopesError(scopesFile: string) {
142
+ function getScopesError(scopesFile: string): string {
143
143
  return [
144
144
  `File ${scopesFile} not found!`,
145
145
  `This application had to have pre-defined file ${scopesFile} that will declare needed scopes`,
146
146
  ].join('\n');
147
147
  }
148
148
 
149
- function getSecretsError(profile: string, secretsFile: string) {
149
+ function getSecretsError(profile: string, secretsFile: string): string {
150
150
  return [
151
151
  `File ${secretsFile} not found!`,
152
152
  'Here is how to obtain it:',
@@ -182,3 +182,6 @@ function getSecretsError(profile: string, secretsFile: string) {
182
182
  'Then start this script again',
183
183
  ].join('\n');
184
184
  }
185
+
186
+ export { getSecrets, getCredentials, deleteCredentials };
187
+ export default { getScopes, getSecrets, getCredentials, validateCredentials, createCredentials, deleteCredentials, checkSecrets, getSecretsError, getScopesError };
@@ -0,0 +1,10 @@
1
+ interface CommonOptions {
2
+ hideProgress? : boolean;
3
+ }
4
+
5
+ interface AuthOptions {
6
+ temporary? : boolean;
7
+ scopes? : string[];
8
+ }
9
+
10
+ export type { CommonOptions, AuthOptions };
@@ -1,17 +1,13 @@
1
- export interface Secrets {
1
+ interface Secrets {
2
2
  web: {
3
- client_id: `${string}.apps.googleusercontent.com`;
4
- project_id: string;
5
- auth_uri: 'https://accounts.google.com/o/oauth2/auth';
6
- token_uri: 'https://oauth2.googleapis.com/token';
7
- auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs';
8
- client_secret: string;
9
- redirect_uris: string[];
3
+ client_id : `${string}.apps.googleusercontent.com`;
4
+ project_id : string;
5
+ auth_uri : 'https://accounts.google.com/o/oauth2/auth';
6
+ token_uri : 'https://oauth2.googleapis.com/token';
7
+ auth_provider_x509_cert_url : 'https://www.googleapis.com/oauth2/v1/certs';
8
+ client_secret : string;
9
+ redirect_uris : string[];
10
10
  };
11
11
  }
12
12
 
13
- export interface AuthOptions {
14
- temporary?: boolean;
15
- scopes?: string[];
16
- }
17
-
13
+ export type { Secrets };
@@ -1,7 +1,7 @@
1
1
  {
2
- "extends": "./tsconfig.json",
2
+ "extends" : "./tsconfig.json",
3
3
 
4
- "exclude": [
4
+ "exclude" : [
5
5
  "**/__tests__/",
6
6
  ],
7
7
  }
package/tsconfig.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "extends": "./node_modules/@anmiles/tsconfig/tsconfig.json",
2
+ "extends" : "./node_modules/@anmiles/tsconfig/tsconfig.json",
3
3
 
4
- "compilerOptions": {
5
- "rootDir": "./src",
6
- "outDir": "./dist",
4
+ "compilerOptions" : {
5
+ "rootDir" : "./src",
6
+ "outDir" : "./dist",
7
7
  },
8
8
 
9
- "include": [
9
+ "include" : [
10
10
  "src",
11
11
  ],
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "extends": "./tsconfig.json",
2
+ "extends" : "./tsconfig.json",
3
3
 
4
- "compilerOptions": {
5
- "moduleResolution": "Node",
4
+ "compilerOptions" : {
5
+ "moduleResolution" : "Node",
6
6
  },
7
7
  }
@@ -1,94 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- pull_request:
8
- workflow_dispatch:
9
-
10
- concurrency:
11
- group: "${{ github.workflow }}-${{ github.ref }}"
12
- cancel-in-progress: true
13
-
14
- jobs:
15
- install:
16
- runs-on: ubuntu-latest
17
- container:
18
- image: node:18.14
19
- timeout-minutes: 30
20
- steps:
21
- - uses: actions/checkout@v4
22
- - uses: actions/cache@v4
23
- with:
24
- path: node_modules
25
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
26
- lookup-only: true
27
- - run: npm ci
28
-
29
- build:
30
- needs: install
31
- runs-on: ubuntu-latest
32
- container:
33
- image: node:18.14
34
- timeout-minutes: 30
35
- steps:
36
- - uses: actions/checkout@v4
37
- - uses: actions/cache@v4
38
- with:
39
- path: node_modules
40
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
41
- - run: npm run build:ci
42
-
43
- lint:
44
- needs: build
45
- runs-on: ubuntu-latest
46
- container:
47
- image: node:18.14
48
- timeout-minutes: 30
49
- steps:
50
- - uses: actions/checkout@v4
51
- - uses: actions/cache@v4
52
- with:
53
- path: node_modules
54
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
55
- - run: npm run lint
56
-
57
- test:
58
- needs: build
59
- runs-on: ubuntu-latest
60
- container:
61
- image: node:18.14
62
- timeout-minutes: 30
63
- steps:
64
- - uses: actions/checkout@v4
65
- - uses: actions/cache@v4
66
- with:
67
- path: node_modules
68
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
69
- - uses: actions/cache@v4
70
- with:
71
- path: coverage
72
- key: "coverage-${{ hashFiles('package-lock.json') }}"
73
- lookup-only: true
74
- - run: npm run test:ci
75
-
76
- coverage:
77
- needs:
78
- - lint
79
- - test
80
- runs-on: ubuntu-latest
81
- container:
82
- image: node:18.14
83
- timeout-minutes: 30
84
- steps:
85
- - uses: actions/checkout@v4
86
- - uses: actions/cache@v4
87
- with:
88
- path: node_modules
89
- key: "node_modules-${{ hashFiles('package-lock.json') }}"
90
- - uses: actions/cache@v4
91
- with:
92
- path: coverage
93
- key: "coverage-${{ hashFiles('package-lock.json') }}"
94
- - run: npm run test:report:coverage
@@ -1,4 +0,0 @@
1
- export interface CommonOptions {
2
- hideProgress?: boolean;
3
- }
4
- //# sourceMappingURL=common.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAA;CACtB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- export * from './common';
2
- export * from './secrets';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./common"), exports);
18
- __exportStar(require("./secrets"), exports);
19
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,4CAA0B"}
@@ -1,3 +0,0 @@
1
- export interface CommonOptions {
2
- hideProgress?: boolean
3
- }
@@ -1,2 +0,0 @@
1
- export * from './common';
2
- export * from './secrets';