@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.
- package/.nycrc.json +27 -0
- package/CHANGELOG.md +32 -21
- package/README.md +1 -1
- package/cspell.json +22 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +5 -11
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +5 -6
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/auth.d.ts +2 -9
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +3 -23
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/credentials/generator.d.ts +4 -0
- package/dist/lib/credentials/generator.d.ts.map +1 -0
- package/dist/lib/credentials/generator.js +60 -0
- package/dist/lib/credentials/generator.js.map +1 -0
- package/dist/lib/credentials/index.d.ts +5 -0
- package/dist/lib/credentials/index.d.ts.map +1 -0
- package/dist/lib/credentials/index.js +42 -0
- package/dist/lib/credentials/index.js.map +1 -0
- package/dist/lib/credentials/validator.d.ts +7 -0
- package/dist/lib/credentials/validator.d.ts.map +1 -0
- package/dist/lib/credentials/validator.js +20 -0
- package/dist/lib/credentials/validator.js.map +1 -0
- package/dist/lib/login.d.ts +3 -0
- package/dist/lib/login.d.ts.map +1 -0
- package/dist/lib/login.js +19 -0
- package/dist/lib/login.js.map +1 -0
- package/dist/lib/profiles.d.ts +4 -12
- package/dist/lib/profiles.d.ts.map +1 -1
- package/dist/lib/profiles.js +8 -11
- package/dist/lib/profiles.js.map +1 -1
- package/dist/lib/renderer.d.ts +7 -25
- package/dist/lib/renderer.d.ts.map +1 -1
- package/dist/lib/renderer.js +26 -23
- package/dist/lib/renderer.js.map +1 -1
- package/dist/lib/scopes.d.ts +2 -0
- package/dist/lib/scopes.d.ts.map +1 -0
- package/dist/lib/scopes.js +22 -0
- package/dist/lib/scopes.js.map +1 -0
- package/dist/lib/secrets.d.ts +2 -28
- package/dist/lib/secrets.d.ts.map +1 -1
- package/dist/lib/secrets.js +15 -115
- package/dist/lib/secrets.js.map +1 -1
- package/dist/lib/utils/paths.d.ts +7 -0
- package/dist/lib/utils/paths.d.ts.map +1 -0
- package/dist/lib/{paths.js → utils/paths.js} +6 -8
- package/dist/lib/utils/paths.js.map +1 -0
- package/dist/templates/auth.html +1 -1
- package/dist/templates/index.html +6 -1
- package/dist/templates/page.html +1 -2
- package/dist/templates/script.html +0 -0
- package/{src/templates/css.html → dist/templates/style.html} +2 -2
- package/dist/types/options.d.ts +2 -3
- package/dist/types/options.d.ts.map +1 -1
- package/dist/types/secrets.d.ts +1 -2
- package/dist/types/secrets.d.ts.map +1 -1
- package/eslint.config.mts +43 -0
- package/jest.config.js +9 -9
- package/package.json +40 -30
- package/src/index.ts +3 -2
- package/src/lib/__tests__/__snapshots__/renderer.test.ts.snap +273 -0
- package/src/lib/__tests__/__snapshots__/scopes.test.ts.snap +6 -0
- package/src/lib/__tests__/__snapshots__/secrets.test.ts.snap +38 -0
- package/src/lib/__tests__/api.test.ts +72 -74
- package/src/lib/__tests__/auth.test.ts +38 -114
- package/src/lib/__tests__/login.test.ts +71 -0
- package/src/lib/__tests__/profiles.test.ts +50 -93
- package/src/lib/__tests__/renderer.test.ts +16 -89
- package/src/lib/__tests__/scopes.test.ts +41 -0
- package/src/lib/__tests__/secrets.test.ts +47 -541
- package/src/lib/api.ts +19 -21
- package/src/lib/auth.ts +5 -25
- package/src/lib/credentials/__tests__/generator.test.ts +249 -0
- package/src/lib/credentials/__tests__/index.test.ts +213 -0
- package/src/lib/credentials/__tests__/validator.test.ts +43 -0
- package/src/lib/credentials/generator.ts +70 -0
- package/src/lib/credentials/index.ts +50 -0
- package/src/lib/credentials/validator.ts +29 -0
- package/src/lib/login.ts +22 -0
- package/src/lib/profiles.ts +9 -12
- package/src/lib/renderer.ts +32 -27
- package/src/lib/scopes.ts +18 -0
- package/src/lib/secrets.ts +21 -141
- package/src/lib/utils/paths.ts +30 -0
- package/src/templates/auth.html +1 -1
- package/src/templates/index.html +6 -1
- package/src/templates/page.html +1 -2
- package/src/templates/script.html +0 -0
- package/{dist/templates/css.html → src/templates/style.html} +2 -2
- package/src/types/options.ts +5 -7
- package/src/types/secrets.ts +8 -10
- package/tsconfig.build.json +6 -0
- package/tsconfig.json +0 -5
- package/tsconfig.test.json +1 -1
- package/.eslintignore +0 -2
- package/.eslintrc.js +0 -30
- package/.vscode/settings.json +0 -9
- package/coverage.config.js +0 -8
- package/dist/lib/paths.d.ts +0 -16
- package/dist/lib/paths.d.ts.map +0 -1
- package/dist/lib/paths.js.map +0 -1
- package/src/lib/__tests__/paths.test.ts +0 -77
- package/src/lib/paths.ts +0 -32
|
@@ -1,150 +1,107 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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
|
|
52
|
-
|
|
30
|
+
it('should return profiles', () => {
|
|
31
|
+
const result = getProfiles();
|
|
53
32
|
|
|
54
|
-
expect(
|
|
55
|
-
expect(getJSONSpy.mock.calls[0]?.[0]).toEqual(profilesFile);
|
|
33
|
+
expect(result).toEqual(profiles);
|
|
56
34
|
});
|
|
57
35
|
|
|
58
|
-
it('should
|
|
59
|
-
|
|
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
|
-
|
|
67
|
-
const result = original.getProfiles();
|
|
39
|
+
const result = getProfiles();
|
|
68
40
|
|
|
69
|
-
expect(result).toEqual(
|
|
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
|
-
|
|
48
|
+
setProfiles(profiles);
|
|
76
49
|
|
|
77
|
-
expect(
|
|
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
|
|
91
|
-
const newProfile = '
|
|
61
|
+
it('should add new profile if not exists', () => {
|
|
62
|
+
const newProfile = 'newProfile';
|
|
92
63
|
|
|
93
|
-
|
|
64
|
+
createProfile(newProfile);
|
|
94
65
|
|
|
95
|
-
expect(
|
|
66
|
+
expect(fs.getJSON(profilesFile, () => [])).toEqual([ 'username1', 'username2', 'newProfile' ]);
|
|
96
67
|
});
|
|
97
68
|
|
|
98
|
-
it('should not
|
|
69
|
+
it('should not add duplicate', () => {
|
|
99
70
|
const newProfile = 'username1';
|
|
100
71
|
|
|
101
|
-
|
|
72
|
+
createProfile(newProfile);
|
|
102
73
|
|
|
103
|
-
expect(
|
|
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
|
|
117
|
-
|
|
79
|
+
it('should return all profiles', () => {
|
|
80
|
+
const result = filterProfiles();
|
|
118
81
|
|
|
119
|
-
expect(
|
|
82
|
+
expect(result).toEqual([ 'username1', 'username2' ]);
|
|
120
83
|
});
|
|
121
84
|
|
|
122
|
-
it('should
|
|
123
|
-
|
|
85
|
+
it('should return array with requested profile if exists', () => {
|
|
86
|
+
const result = filterProfiles(profile1);
|
|
124
87
|
|
|
125
|
-
|
|
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[] =>
|
|
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
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
expect(found).toEqual([ profile1 ]);
|
|
142
|
-
});
|
|
99
|
+
it('should output error if no profiles', () => {
|
|
100
|
+
mockFs({});
|
|
143
101
|
|
|
144
|
-
|
|
145
|
-
const found = original.filterProfiles();
|
|
102
|
+
const func = (): string[] => filterProfiles();
|
|
146
103
|
|
|
147
|
-
expect(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
76
|
-
|
|
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
|
-
|
|
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('
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
27
|
+
expect(result).toMatchSnapshot();
|
|
28
|
+
});
|
|
102
29
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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(
|
|
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
|
+
});
|