@anmiles/google-api-wrapper 18.0.3 → 19.0.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.
Files changed (108) hide show
  1. package/.nycrc.json +27 -0
  2. package/CHANGELOG.md +32 -21
  3. package/README.md +1 -1
  4. package/cspell.json +22 -0
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +4 -3
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/api.d.ts +5 -11
  10. package/dist/lib/api.d.ts.map +1 -1
  11. package/dist/lib/api.js +5 -6
  12. package/dist/lib/api.js.map +1 -1
  13. package/dist/lib/auth.d.ts +2 -9
  14. package/dist/lib/auth.d.ts.map +1 -1
  15. package/dist/lib/auth.js +3 -23
  16. package/dist/lib/auth.js.map +1 -1
  17. package/dist/lib/credentials/generator.d.ts +4 -0
  18. package/dist/lib/credentials/generator.d.ts.map +1 -0
  19. package/dist/lib/credentials/generator.js +60 -0
  20. package/dist/lib/credentials/generator.js.map +1 -0
  21. package/dist/lib/credentials/index.d.ts +5 -0
  22. package/dist/lib/credentials/index.d.ts.map +1 -0
  23. package/dist/lib/credentials/index.js +42 -0
  24. package/dist/lib/credentials/index.js.map +1 -0
  25. package/dist/lib/credentials/validator.d.ts +7 -0
  26. package/dist/lib/credentials/validator.d.ts.map +1 -0
  27. package/dist/lib/credentials/validator.js +20 -0
  28. package/dist/lib/credentials/validator.js.map +1 -0
  29. package/dist/lib/login.d.ts +3 -0
  30. package/dist/lib/login.d.ts.map +1 -0
  31. package/dist/lib/login.js +19 -0
  32. package/dist/lib/login.js.map +1 -0
  33. package/dist/lib/profiles.d.ts +4 -12
  34. package/dist/lib/profiles.d.ts.map +1 -1
  35. package/dist/lib/profiles.js +8 -11
  36. package/dist/lib/profiles.js.map +1 -1
  37. package/dist/lib/renderer.d.ts +7 -25
  38. package/dist/lib/renderer.d.ts.map +1 -1
  39. package/dist/lib/renderer.js +26 -23
  40. package/dist/lib/renderer.js.map +1 -1
  41. package/dist/lib/scopes.d.ts +2 -0
  42. package/dist/lib/scopes.d.ts.map +1 -0
  43. package/dist/lib/scopes.js +22 -0
  44. package/dist/lib/scopes.js.map +1 -0
  45. package/dist/lib/secrets.d.ts +2 -28
  46. package/dist/lib/secrets.d.ts.map +1 -1
  47. package/dist/lib/secrets.js +15 -115
  48. package/dist/lib/secrets.js.map +1 -1
  49. package/dist/lib/utils/paths.d.ts +7 -0
  50. package/dist/lib/utils/paths.d.ts.map +1 -0
  51. package/dist/lib/{paths.js → utils/paths.js} +6 -8
  52. package/dist/lib/utils/paths.js.map +1 -0
  53. package/dist/templates/auth.html +1 -1
  54. package/dist/templates/index.html +6 -1
  55. package/dist/templates/page.html +1 -2
  56. package/dist/templates/script.html +0 -0
  57. package/{src/templates/css.html → dist/templates/style.html} +2 -2
  58. package/dist/types/options.d.ts +2 -3
  59. package/dist/types/options.d.ts.map +1 -1
  60. package/dist/types/secrets.d.ts +1 -2
  61. package/dist/types/secrets.d.ts.map +1 -1
  62. package/eslint.config.mts +43 -0
  63. package/jest.config.js +9 -9
  64. package/package.json +40 -30
  65. package/src/index.ts +3 -2
  66. package/src/lib/__tests__/__snapshots__/renderer.test.ts.snap +273 -0
  67. package/src/lib/__tests__/__snapshots__/scopes.test.ts.snap +6 -0
  68. package/src/lib/__tests__/__snapshots__/secrets.test.ts.snap +38 -0
  69. package/src/lib/__tests__/api.test.ts +72 -74
  70. package/src/lib/__tests__/auth.test.ts +38 -114
  71. package/src/lib/__tests__/login.test.ts +71 -0
  72. package/src/lib/__tests__/profiles.test.ts +50 -93
  73. package/src/lib/__tests__/renderer.test.ts +16 -89
  74. package/src/lib/__tests__/scopes.test.ts +41 -0
  75. package/src/lib/__tests__/secrets.test.ts +47 -541
  76. package/src/lib/api.ts +19 -21
  77. package/src/lib/auth.ts +5 -25
  78. package/src/lib/credentials/__tests__/generator.test.ts +249 -0
  79. package/src/lib/credentials/__tests__/index.test.ts +213 -0
  80. package/src/lib/credentials/__tests__/validator.test.ts +43 -0
  81. package/src/lib/credentials/generator.ts +70 -0
  82. package/src/lib/credentials/index.ts +50 -0
  83. package/src/lib/credentials/validator.ts +29 -0
  84. package/src/lib/login.ts +22 -0
  85. package/src/lib/profiles.ts +9 -12
  86. package/src/lib/renderer.ts +32 -27
  87. package/src/lib/scopes.ts +18 -0
  88. package/src/lib/secrets.ts +21 -141
  89. package/src/lib/utils/paths.ts +30 -0
  90. package/src/templates/auth.html +1 -1
  91. package/src/templates/index.html +6 -1
  92. package/src/templates/page.html +1 -2
  93. package/src/templates/script.html +0 -0
  94. package/{dist/templates/css.html → src/templates/style.html} +2 -2
  95. package/src/types/options.ts +5 -7
  96. package/src/types/secrets.ts +8 -10
  97. package/tsconfig.build.json +6 -0
  98. package/tsconfig.json +0 -5
  99. package/tsconfig.test.json +1 -1
  100. package/.eslintignore +0 -2
  101. package/.eslintrc.js +0 -30
  102. package/.vscode/settings.json +0 -9
  103. package/coverage.config.js +0 -8
  104. package/dist/lib/paths.d.ts +0 -16
  105. package/dist/lib/paths.d.ts.map +0 -1
  106. package/dist/lib/paths.js.map +0 -1
  107. package/src/lib/__tests__/paths.test.ts +0 -77
  108. package/src/lib/paths.ts +0 -32
@@ -1,150 +1,107 @@
1
1
  import fs from 'fs';
2
- import type logger from '@anmiles/logger';
3
- import type paths from '../paths';
4
-
5
- import profiles from '../profiles';
6
-
7
- const original = jest.requireActual<{ default : typeof profiles }>('../profiles').default;
8
- jest.mock<typeof profiles>('../profiles', () => ({
9
- getProfiles : jest.fn().mockImplementation(() => existingProfiles),
10
- setProfiles : jest.fn(),
11
- createProfile : jest.fn(),
12
- filterProfiles : jest.fn(),
13
- }));
14
-
15
- jest.mock<Partial<typeof fs>>('fs', () => ({
16
- mkdirSync : jest.fn(),
17
- renameSync : jest.fn(),
18
- writeFileSync : jest.fn(),
19
- existsSync : jest.fn().mockImplementation((file: string) => existingFiles.includes(file)),
20
- }));
21
-
22
- jest.mock<Partial<typeof logger>>('@anmiles/logger', () => ({
23
- log : jest.fn(),
24
- warn : jest.fn(),
25
- }));
26
-
27
- jest.mock<Partial<typeof paths>>('../paths', () => ({
28
- getProfilesFile : jest.fn().mockImplementation(() => profilesFile),
29
- }));
30
-
31
- const json = { key : 'value' };
32
- const profilesFile = 'profilesFile';
33
- const profile1 = 'username1';
34
- const profile2 = 'username2';
35
- const allProfiles = [ profile1, profile2 ];
36
-
37
- let existingProfiles: string[];
38
- let existingFiles: string[] = [];
39
-
40
- const getJSONSpy = jest.spyOn(fs, 'getJSON').mockImplementation(() => json);
41
- const writeJSONSpy = jest.spyOn(fs, 'writeJSON').mockImplementation();
2
+
3
+ import '@anmiles/prototypes';
4
+ import mockFs from 'mock-fs';
5
+
6
+ import { createProfile, filterProfiles, getProfiles, setProfiles } from '../profiles';
7
+ import { getProfilesFile } from '../utils/paths';
8
+
9
+ jest.mock('@anmiles/logger');
10
+
11
+ const profilesFile = getProfilesFile();
12
+
13
+ const profile1 = 'username1';
14
+ const profile2 = 'username2';
15
+ const profiles = [ profile1, profile2 ];
42
16
 
43
17
  beforeEach(() => {
44
- existingFiles = [];
45
- existingProfiles = [ 'username1', 'username2' ];
18
+ mockFs({
19
+ [profilesFile]: JSON.stringify(profiles),
20
+ });
21
+ });
22
+
23
+ afterAll(() => {
24
+ mockFs.restore();
46
25
  });
47
26
 
48
27
  describe('src/lib/profiles', () => {
49
28
 
50
29
  describe('getProfiles', () => {
51
- it('should get json from profiles file', () => {
52
- original.getProfiles();
30
+ it('should return profiles', () => {
31
+ const result = getProfiles();
53
32
 
54
- expect(getJSONSpy).toHaveBeenCalled();
55
- expect(getJSONSpy.mock.calls[0]?.[0]).toEqual(profilesFile);
33
+ expect(result).toEqual(profiles);
56
34
  });
57
35
 
58
- it('should fallback to empty profiles array', () => {
59
- original.getProfiles();
60
-
61
- const fallback = getJSONSpy.mock.calls[0]?.[1];
62
-
63
- expect(fallback?.()).toEqual([]);
64
- });
36
+ it('should return empty array and create profiles file if not exists', () => {
37
+ mockFs({});
65
38
 
66
- it('should return JSON', () => {
67
- const result = original.getProfiles();
39
+ const result = getProfiles();
68
40
 
69
- expect(result).toEqual(json);
41
+ expect(result).toEqual([]);
42
+ expect(fs.existsSync(profilesFile)).toBe(true);
70
43
  });
71
44
  });
72
45
 
73
46
  describe('setProfiles', () => {
74
47
  it('should write json to profiles file', () => {
75
- original.setProfiles(allProfiles);
48
+ setProfiles(profiles);
76
49
 
77
- expect(writeJSONSpy).toHaveBeenCalledWith(profilesFile, allProfiles);
50
+ expect(fs.getJSON(profilesFile, () => [])).toEqual([ 'username1', 'username2' ]);
78
51
  });
79
52
  });
80
53
 
81
54
  describe('createProfile', () => {
82
55
  it('should output error and do nothing if profile is falsy', () => {
83
- const func = (): void => {
84
- original.createProfile('');
85
- };
56
+ const func = (): void => createProfile('');
86
57
 
87
58
  expect(func).toThrow('Usage: `npm run create <profile>` where `profile` - is any profile name you want');
88
59
  });
89
60
 
90
- it('should get profiles', () => {
91
- const newProfile = 'username1';
61
+ it('should add new profile if not exists', () => {
62
+ const newProfile = 'newProfile';
92
63
 
93
- original.createProfile(newProfile);
64
+ createProfile(newProfile);
94
65
 
95
- expect(profiles.getProfiles).toHaveBeenCalledWith();
66
+ expect(fs.getJSON(profilesFile, () => [])).toEqual([ 'username1', 'username2', 'newProfile' ]);
96
67
  });
97
68
 
98
- it('should not save profiles if profile already exists', () => {
69
+ it('should not add duplicate', () => {
99
70
  const newProfile = 'username1';
100
71
 
101
- original.createProfile(newProfile);
72
+ createProfile(newProfile);
102
73
 
103
- expect(profiles.setProfiles).not.toHaveBeenCalled();
104
- });
105
-
106
- it('should add new profile if not exists', () => {
107
- const newProfile = 'newProfile';
108
-
109
- original.createProfile(newProfile);
110
-
111
- expect(profiles.setProfiles).toHaveBeenCalledWith([ 'username1', 'username2', 'newProfile' ]);
74
+ expect(fs.getJSON(profilesFile, () => [])).toEqual([ 'username1', 'username2' ]);
112
75
  });
113
76
  });
114
77
 
115
78
  describe('filterProfiles', () => {
116
- it('should get profiles', () => {
117
- original.filterProfiles();
79
+ it('should return all profiles', () => {
80
+ const result = filterProfiles();
118
81
 
119
- expect(profiles.getProfiles).toHaveBeenCalled();
82
+ expect(result).toEqual([ 'username1', 'username2' ]);
120
83
  });
121
84
 
122
- it('should output error if no profiles', () => {
123
- existingProfiles = [];
85
+ it('should return array with requested profile if exists', () => {
86
+ const result = filterProfiles(profile1);
124
87
 
125
- const func = (): string[] => original.filterProfiles();
126
-
127
- expect(func).toThrow(new Error('Please `npm run create` at least one profile'));
88
+ expect(result).toEqual([ profile1 ]);
128
89
  });
129
90
 
130
91
  it('should output error if profile does not exist', () => {
131
92
  const newProfile = 'newProfile';
132
93
 
133
- const func = (): string[] => original.filterProfiles(newProfile);
94
+ const func = (): string[] => filterProfiles(newProfile);
134
95
 
135
96
  expect(func).toThrow(new Error(`Profile '${newProfile}' does not exist`));
136
97
  });
137
98
 
138
- it('should return array with requested profile if it exists', () => {
139
- const found = original.filterProfiles(profile1);
140
-
141
- expect(found).toEqual([ profile1 ]);
142
- });
99
+ it('should output error if no profiles', () => {
100
+ mockFs({});
143
101
 
144
- it('should return all profiles if nothing requested', () => {
145
- const found = original.filterProfiles();
102
+ const func = (): string[] => filterProfiles();
146
103
 
147
- expect(found).toEqual(existingProfiles);
104
+ expect(func).toThrow(new Error('Please `npm run create` at least one profile'));
148
105
  });
149
106
  });
150
107
  });
@@ -1,48 +1,4 @@
1
- import fs from 'fs';
2
- import type path from 'path';
3
- import type paths from '../paths';
4
- import type renderer from '../renderer';
5
-
6
- const original = jest.requireActual<{ default : typeof renderer }>('../renderer').default;
7
-
8
- type TemplateName = keyof typeof original.templates;
9
- type GetFileName<T extends TemplateName> = `${T}.html`;
10
-
11
- type FileName = GetFileName<TemplateName>;
12
- type GetTemplateName<F> = F extends `${infer T}.html` ? T : never;
13
-
14
- function getFileName<T extends TemplateName>(templateName: T): GetFileName<T> {
15
- return `${templateName}.html`;
16
- }
17
-
18
- function getTemplateName<F extends FileName>(file: F): GetTemplateName<F> {
19
- return file.replace('.html', '') as GetTemplateName<F>;
20
- }
21
-
22
- jest.mock<Partial<typeof renderer>>('../renderer', () => ({
23
- getTemplate : jest.fn().mockImplementation((templateName: TemplateName) => mockTemplates[templateName]),
24
- }));
25
-
26
- jest.mock<Partial<typeof fs>>('fs', () => ({
27
- readFileSync : jest.fn().mockImplementation((file: FileName) => mockTemplates[getTemplateName(file)] || ''),
28
- }));
29
-
30
- jest.mock<Partial<typeof path>>('path', () => ({
31
- join : jest.fn().mockImplementation((...paths: string[]) => paths.join('/')),
32
- }));
33
-
34
- jest.mock<Partial<typeof paths>>('../paths', () => ({
35
- getTemplateFile : jest.fn().mockImplementation((templateName) => getFileName(templateName)),
36
- }));
37
-
38
- const mockTemplates: Record<TemplateName, string> = {
39
- index : 'index page = (${page})',
40
- page : 'page css = (${css}) content = (${content})',
41
- css : 'css',
42
- auth : 'auth profile = (${profile}) authUrl = (${authUrl}) scopesList = (${scopesList})',
43
- scope : 'scope type = (${type}) title = (${title}) name = (${name})',
44
- done : 'done profile = (${profile})',
45
- };
1
+ import { renderAuth, renderDone } from '../renderer';
46
2
 
47
3
  const authUrl = 'https://authUrl';
48
4
  const profile = 'username';
@@ -51,60 +7,31 @@ const scope = [ 'namespace/scope1.readonly', 'namespace/scope2' ];
51
7
  describe('src/lib/renderer', () => {
52
8
  describe('renderAuth', () => {
53
9
  it('should return auth page', () => {
54
- const result = original.renderAuth({ authUrl, profile, scope });
55
- expect(result).toEqual('index page = (page css = (css) content = (auth profile = (username) authUrl = (https://authUrl) scopesList = (scope type = (readonly) title = (Readonly (cannot change or delete your data)) name = (scope1.readonly)\nscope type = () title = (Writable (can change or delete your data)) name = (scope2))))');
56
- });
57
- });
10
+ const result = renderAuth({ profile, authUrl, scope });
58
11
 
59
- describe('renderDone', () => {
60
- it('should return done page', () => {
61
- const result = original.renderDone({ profile });
62
- expect(result).toEqual('index page = (page css = (css) content = (done profile = (username)))');
63
- });
64
- });
65
-
66
- describe('render', () => {
67
- it('should replace all template variables with their values', () => {
68
- const values = { type : 'readonly', title : 'Readonly scope', name : 'scope.readonly' };
69
-
70
- const result = original.render('scope', values);
71
-
72
- expect(result).toEqual('scope type = (readonly) title = (Readonly scope) name = (scope.readonly)');
12
+ expect(result).toMatchSnapshot();
73
13
  });
74
14
 
75
- it('should replace non-existing template variable with empty string', () => {
76
- const values = { name : 'scope.readonly', type : undefined, title : undefined };
15
+ it('should throw error if property missing', () => {
16
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
17
+ const func = (): string => renderAuth({ scope } as unknown as Parameters<typeof renderAuth>[0]);
77
18
 
78
- const result = original.render('scope', values);
79
-
80
- expect(result).toEqual('scope type = () title = () name = (scope.readonly)');
19
+ expect(func).toThrow('Missing required value \'profile\' while rendering template \'auth\'');
81
20
  });
82
21
  });
83
22
 
84
- describe('getTemplate', () => {
85
- for (const templateName in original.templates) {
86
- it(`should return contents of '${templateName}' template file`, () => {
87
- const template = original.getTemplate(templateName as TemplateName);
88
- expect(fs.readFileSync).toHaveBeenCalledTimes(1);
89
- expect(fs.readFileSync).toHaveBeenCalledWith(`${templateName}.html`);
90
- expect(template).toEqual(mockTemplates[templateName as TemplateName]);
91
- });
92
- }
93
-
94
- it('should cache templates', () => {
95
- original.getTemplate('template1' as TemplateName);
96
-
97
- original.getTemplate('template2' as TemplateName);
98
- original.getTemplate('template2' as TemplateName);
99
- original.getTemplate('template2' as TemplateName);
23
+ describe('renderDone', () => {
24
+ it('should return done page', () => {
25
+ const result = renderDone({ profile });
100
26
 
101
- original.getTemplate('template3' as TemplateName);
27
+ expect(result).toMatchSnapshot();
28
+ });
102
29
 
103
- expect(fs.readFileSync).toHaveBeenCalledWith('template1.html');
104
- expect(fs.readFileSync).toHaveBeenCalledWith('template2.html');
105
- expect(fs.readFileSync).toHaveBeenCalledWith('template3.html');
30
+ it('should throw error if property missing', () => {
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
32
+ const func = (): string => renderDone({} as unknown as Parameters<typeof renderAuth>[0]);
106
33
 
107
- expect(fs.readFileSync).toHaveBeenCalledTimes(3);
34
+ expect(func).toThrow('Missing required value \'profile\' while rendering template \'done\'');
108
35
  });
109
36
  });
110
37
  });
@@ -0,0 +1,41 @@
1
+ import '@anmiles/prototypes';
2
+ import mockFs from 'mock-fs';
3
+
4
+ import { getScopes } from '../scopes';
5
+ import { getScopesFile } from '../utils/paths';
6
+
7
+ const scopesFile = getScopesFile();
8
+
9
+ const scopes = [
10
+ 'https://www.googleapis.com/auth/calendar.calendars.readonly',
11
+ 'https://www.googleapis.com/auth/calendar.events',
12
+ ];
13
+
14
+ beforeEach(() => {
15
+ mockFs({
16
+ [scopesFile]: JSON.stringify(scopes),
17
+ });
18
+ });
19
+
20
+ afterAll(() => {
21
+ mockFs.restore();
22
+ });
23
+
24
+ describe('src/lib/scopes', () => {
25
+ describe('getScopes', () => {
26
+
27
+ it('should return scopes', () => {
28
+ const result = getScopes();
29
+
30
+ expect(result).toEqual(scopes);
31
+ });
32
+
33
+ it('should throw if scopes file does not exist', () => {
34
+ mockFs({});
35
+
36
+ const func = (): string[] => getScopes();
37
+
38
+ expect(func).toThrowErrorMatchingSnapshot();
39
+ });
40
+ });
41
+ });