@anmiles/google-api-wrapper 14.0.0 → 14.2.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/CHANGELOG.md +10 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/paths.d.ts +4 -1
- package/dist/lib/paths.js +8 -2
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/profiles.d.ts +3 -1
- package/dist/lib/profiles.js +16 -2
- package/dist/lib/profiles.js.map +1 -1
- package/dist/lib/renderer.d.ts +31 -0
- package/dist/lib/renderer.js +51 -0
- package/dist/lib/renderer.js.map +1 -0
- package/dist/lib/secrets.js +3 -12
- package/dist/lib/secrets.js.map +1 -1
- package/dist/templates/auth.html +6 -0
- package/dist/templates/done.html +3 -0
- package/dist/templates/page.html +109 -0
- package/dist/templates/scope.html +1 -0
- package/package.json +4 -2
- package/src/index.ts +1 -1
- package/src/lib/__tests__/paths.test.ts +15 -3
- package/src/lib/__tests__/profiles.test.ts +49 -10
- package/src/lib/__tests__/renderer.test.ts +108 -0
- package/src/lib/__tests__/secrets.test.ts +14 -18
- package/src/lib/paths.ts +11 -4
- package/src/lib/profiles.ts +20 -2
- package/src/lib/renderer.ts +56 -0
- package/src/lib/secrets.ts +3 -13
- package/src/templates/auth.html +6 -0
- package/src/templates/done.html +3 -0
- package/src/templates/page.html +109 -0
- package/src/templates/scope.html +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [14.2.0](../../tags/v14.2.0) - 2023-09-11
|
|
9
|
+
### Changed
|
|
10
|
+
- Beautify authorization page
|
|
11
|
+
|
|
12
|
+
## [14.1.0](../../tags/v14.1.0) - 2023-08-06
|
|
13
|
+
### Added
|
|
14
|
+
- Filtering profiles
|
|
15
|
+
|
|
8
16
|
## [14.0.0](../../tags/v14.0.0) - 2023-06-11
|
|
9
17
|
### Added
|
|
10
18
|
- Warn if trying to store non-readonly credentials in a file
|
|
@@ -21,7 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
21
29
|
- All existing google APIs are now available
|
|
22
30
|
### Changed
|
|
23
31
|
- Single entry point for creating any APIs
|
|
24
|
-
- BEFORE:
|
|
32
|
+
- BEFORE:
|
|
25
33
|
```
|
|
26
34
|
import { getCalendarAPI } from '@anmiles/google-api-wrapper';
|
|
27
35
|
const calendarAPI = getCalendarAPI(profile);
|
|
@@ -32,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
32
40
|
const calendarAPI = getAPI('calendar', profile);
|
|
33
41
|
```
|
|
34
42
|
- Changed signature for `getItems`. Also explicit types are now redundant.
|
|
35
|
-
- BEFORE:
|
|
43
|
+
- BEFORE:
|
|
36
44
|
```
|
|
37
45
|
const events = await getItems<GoogleApis.calendar_v3.Schema$Event, GoogleApis.calendar_v3.Params$Resource$Events$List>(calendarAPI.events, { ...args });
|
|
38
46
|
```
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAuth = exports.login = exports.getProfiles = exports.createProfile = exports.getAPI = void 0;
|
|
3
|
+
exports.getAuth = exports.login = exports.filterProfiles = exports.getProfiles = exports.createProfile = exports.getAPI = void 0;
|
|
4
4
|
var api_1 = require("./lib/api");
|
|
5
5
|
Object.defineProperty(exports, "getAPI", { enumerable: true, get: function () { return api_1.getAPI; } });
|
|
6
6
|
var profiles_1 = require("./lib/profiles");
|
|
7
7
|
Object.defineProperty(exports, "createProfile", { enumerable: true, get: function () { return profiles_1.createProfile; } });
|
|
8
8
|
Object.defineProperty(exports, "getProfiles", { enumerable: true, get: function () { return profiles_1.getProfiles; } });
|
|
9
|
+
Object.defineProperty(exports, "filterProfiles", { enumerable: true, get: function () { return profiles_1.filterProfiles; } });
|
|
9
10
|
var auth_1 = require("./lib/auth");
|
|
10
11
|
Object.defineProperty(exports, "login", { enumerable: true, get: function () { return auth_1.login; } });
|
|
11
12
|
Object.defineProperty(exports, "getAuth", { enumerable: true, get: function () { return auth_1.getAuth; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAAmC;AAA1B,6FAAA,MAAM,OAAA;AACf,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,iCAAmC;AAA1B,6FAAA,MAAM,OAAA;AACf,2CAA4E;AAAnE,yGAAA,aAAa,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,0GAAA,cAAc,OAAA;AACnD,mCAA4C;AAAnC,6FAAA,KAAK,OAAA;AAAE,+FAAA,OAAO,OAAA"}
|
package/dist/lib/paths.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import type { templates } from './renderer';
|
|
2
|
+
export { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile, getTemplateFile };
|
|
2
3
|
declare const _default: {
|
|
3
4
|
getProfilesFile: typeof getProfilesFile;
|
|
4
5
|
getScopesFile: typeof getScopesFile;
|
|
5
6
|
getSecretsFile: typeof getSecretsFile;
|
|
6
7
|
getCredentialsFile: typeof getCredentialsFile;
|
|
8
|
+
getTemplateFile: typeof getTemplateFile;
|
|
7
9
|
};
|
|
8
10
|
export default _default;
|
|
9
11
|
declare function getProfilesFile(): string;
|
|
10
12
|
declare function getScopesFile(): string;
|
|
11
13
|
declare function getSecretsFile(profile: string): string;
|
|
12
14
|
declare function getCredentialsFile(profile: string): string;
|
|
15
|
+
declare function getTemplateFile(templateName: keyof typeof templates): string;
|
package/dist/lib/paths.js
CHANGED
|
@@ -3,12 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCredentialsFile = exports.getSecretsFile = exports.getScopesFile = exports.getProfilesFile = void 0;
|
|
6
|
+
exports.getTemplateFile = exports.getCredentialsFile = exports.getSecretsFile = exports.getScopesFile = exports.getProfilesFile = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
|
-
exports.default = { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile };
|
|
8
|
+
exports.default = { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile, getTemplateFile };
|
|
9
9
|
const dirPaths = {
|
|
10
10
|
input: 'input',
|
|
11
11
|
secrets: 'secrets',
|
|
12
|
+
// TODO: Remove this hack after moving to React
|
|
13
|
+
templates: 'node_modules/@anmiles/google-api-wrapper/dist/templates',
|
|
12
14
|
};
|
|
13
15
|
function getProfilesFile() {
|
|
14
16
|
return path_1.default.join(dirPaths.input, 'profiles.json');
|
|
@@ -26,4 +28,8 @@ function getCredentialsFile(profile) {
|
|
|
26
28
|
return path_1.default.join(dirPaths.secrets, `${profile}.credentials.json`);
|
|
27
29
|
}
|
|
28
30
|
exports.getCredentialsFile = getCredentialsFile;
|
|
31
|
+
function getTemplateFile(templateName) {
|
|
32
|
+
return path_1.default.join(dirPaths.templates, `${templateName}.html`);
|
|
33
|
+
}
|
|
34
|
+
exports.getTemplateFile = getTemplateFile;
|
|
29
35
|
//# sourceMappingURL=paths.js.map
|
package/dist/lib/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAIxB,kBAAe,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,CAAC;AAEvG,MAAM,QAAQ,GAAG;IAChB,KAAK,EAAO,OAAO;IACnB,OAAO,EAAK,SAAS;IACrB,+CAA+C;IAC/C,SAAS,EAAG,yDAAyD;CACrE,CAAC;AAEF,SAAS,eAAe;IACvB,OAAO,cAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAZQ,0CAAe;AAcxB,SAAS,aAAa;IACrB,OAAO,aAAa,CAAC;AACtB,CAAC;AAhByB,sCAAa;AAkBvC,SAAS,cAAc,CAAC,OAAe;IACtC,OAAO,cAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;AACvD,CAAC;AApBwC,wCAAc;AAsBvD,SAAS,kBAAkB,CAAC,OAAe;IAC1C,OAAO,cAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,OAAO,mBAAmB,CAAC,CAAC;AACnE,CAAC;AAxBwD,gDAAkB;AA0B3E,SAAS,eAAe,CAAC,YAAoC;IAC5D,OAAO,cAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,YAAY,OAAO,CAAC,CAAC;AAC9D,CAAC;AA5B4E,0CAAe"}
|
package/dist/lib/profiles.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import '@anmiles/prototypes';
|
|
2
|
-
export { getProfiles, setProfiles, createProfile };
|
|
2
|
+
export { getProfiles, setProfiles, createProfile, filterProfiles };
|
|
3
3
|
declare const _default: {
|
|
4
4
|
getProfiles: typeof getProfiles;
|
|
5
5
|
setProfiles: typeof setProfiles;
|
|
6
6
|
createProfile: typeof createProfile;
|
|
7
|
+
filterProfiles: typeof filterProfiles;
|
|
7
8
|
};
|
|
8
9
|
export default _default;
|
|
9
10
|
declare function getProfiles(): string[];
|
|
10
11
|
declare function setProfiles(profiles: string[]): void;
|
|
11
12
|
declare function createProfile(profile: string): void;
|
|
13
|
+
declare function filterProfiles(profile?: string): string[];
|
package/dist/lib/profiles.js
CHANGED
|
@@ -3,12 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createProfile = exports.setProfiles = exports.getProfiles = void 0;
|
|
6
|
+
exports.filterProfiles = exports.createProfile = exports.setProfiles = exports.getProfiles = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
require("@anmiles/prototypes");
|
|
9
9
|
const paths_1 = require("./paths");
|
|
10
10
|
const profiles_1 = __importDefault(require("./profiles"));
|
|
11
|
-
exports.default = { getProfiles, setProfiles, createProfile };
|
|
11
|
+
exports.default = { getProfiles, setProfiles, createProfile, filterProfiles };
|
|
12
12
|
function getProfiles() {
|
|
13
13
|
const profilesFile = (0, paths_1.getProfilesFile)();
|
|
14
14
|
return fs_1.default.getJSON(profilesFile, () => []);
|
|
@@ -31,4 +31,18 @@ function createProfile(profile) {
|
|
|
31
31
|
profiles_1.default.setProfiles(existingProfiles);
|
|
32
32
|
}
|
|
33
33
|
exports.createProfile = createProfile;
|
|
34
|
+
function filterProfiles(profile) {
|
|
35
|
+
const existingProfiles = profiles_1.default.getProfiles();
|
|
36
|
+
if (existingProfiles.length === 0) {
|
|
37
|
+
throw 'Please `npm run create` at least one profile';
|
|
38
|
+
}
|
|
39
|
+
if (!profile) {
|
|
40
|
+
return existingProfiles;
|
|
41
|
+
}
|
|
42
|
+
if (existingProfiles.includes(profile)) {
|
|
43
|
+
return [profile];
|
|
44
|
+
}
|
|
45
|
+
throw `Profile '${profile}' does not exist`;
|
|
46
|
+
}
|
|
47
|
+
exports.filterProfiles = filterProfiles;
|
|
34
48
|
//# sourceMappingURL=profiles.js.map
|
package/dist/lib/profiles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/lib/profiles.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,+BAA6B;AAC7B,mCAA0C;AAE1C,0DAAkC;AAGlC,kBAAe,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/lib/profiles.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,+BAA6B;AAC7B,mCAA0C;AAE1C,0DAAkC;AAGlC,kBAAe,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAE3E,SAAS,WAAW;IACnB,MAAM,YAAY,GAAG,IAAA,uBAAe,GAAE,CAAC;IACvC,OAAO,YAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAC3C,CAAC;AANQ,kCAAW;AAQpB,SAAS,WAAW,CAAC,QAAkB;IACtC,MAAM,YAAY,GAAG,IAAA,uBAAe,GAAE,CAAC;IACvC,YAAE,CAAC,SAAS,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAXqB,kCAAW;AAajC,SAAS,aAAa,CAAC,OAAe;IACrC,IAAI,CAAC,OAAO,EAAE;QACb,MAAM,kFAAkF,CAAC;KACzF;IAED,MAAM,gBAAgB,GAAG,kBAAQ,CAAC,WAAW,EAAE,CAAC;IAEhD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACvC,OAAO;KACP;IAED,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,kBAAQ,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;AACxC,CAAC;AA1BkC,sCAAa;AA4BhD,SAAS,cAAc,CAAC,OAAgB;IACvC,MAAM,gBAAgB,GAAG,kBAAQ,CAAC,WAAW,EAAE,CAAC;IAEhD,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,MAAM,8CAA8C,CAAC;KACrD;IAED,IAAI,CAAC,OAAO,EAAE;QACb,OAAO,gBAAgB,CAAC;KACxB;IAED,IAAI,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACvC,OAAO,CAAE,OAAO,CAAE,CAAC;KACnB;IAED,MAAM,YAAY,OAAO,kBAAkB,CAAC;AAC7C,CAAC;AA5CiD,wCAAc"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export { templates, renderAuth, renderDone };
|
|
2
|
+
declare const templates: {
|
|
3
|
+
readonly page: readonly ["content"];
|
|
4
|
+
readonly auth: readonly ["profile", "authUrl", "scopesList"];
|
|
5
|
+
readonly scope: readonly ["type", "name"];
|
|
6
|
+
readonly done: readonly ["profile"];
|
|
7
|
+
};
|
|
8
|
+
type TemplateName = keyof typeof templates;
|
|
9
|
+
declare function renderAuth({ profile, authUrl, scope }: {
|
|
10
|
+
profile: string;
|
|
11
|
+
authUrl: string;
|
|
12
|
+
scope: string[];
|
|
13
|
+
}): string;
|
|
14
|
+
declare function renderDone({ profile }: {
|
|
15
|
+
profile: string;
|
|
16
|
+
}): string;
|
|
17
|
+
declare function render<T extends TemplateName>(templateName: T, values: Record<typeof templates[T][number], string>): string;
|
|
18
|
+
declare function getTemplate(templateName: TemplateName): string;
|
|
19
|
+
declare const _default: {
|
|
20
|
+
templates: {
|
|
21
|
+
readonly page: readonly ["content"];
|
|
22
|
+
readonly auth: readonly ["profile", "authUrl", "scopesList"];
|
|
23
|
+
readonly scope: readonly ["type", "name"];
|
|
24
|
+
readonly done: readonly ["profile"];
|
|
25
|
+
};
|
|
26
|
+
render: typeof render;
|
|
27
|
+
getTemplate: typeof getTemplate;
|
|
28
|
+
renderAuth: typeof renderAuth;
|
|
29
|
+
renderDone: typeof renderDone;
|
|
30
|
+
};
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderDone = exports.renderAuth = exports.templates = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const renderer_1 = __importDefault(require("./renderer"));
|
|
9
|
+
const paths_1 = require("./paths");
|
|
10
|
+
const templates = {
|
|
11
|
+
page: ['content'],
|
|
12
|
+
auth: ['profile', 'authUrl', 'scopesList'],
|
|
13
|
+
scope: ['type', 'name'],
|
|
14
|
+
done: ['profile'],
|
|
15
|
+
};
|
|
16
|
+
exports.templates = templates;
|
|
17
|
+
const allHTML = {};
|
|
18
|
+
function renderAuth({ profile, authUrl, scope }) {
|
|
19
|
+
const scopesList = scope.map((s) => render('scope', {
|
|
20
|
+
name: s.split('/').pop(),
|
|
21
|
+
type: s.endsWith('.readonly') ? 'readonly' : '',
|
|
22
|
+
})).join('\n');
|
|
23
|
+
const content = render('auth', { profile, authUrl, scopesList });
|
|
24
|
+
return render('page', { content });
|
|
25
|
+
}
|
|
26
|
+
exports.renderAuth = renderAuth;
|
|
27
|
+
function renderDone({ profile }) {
|
|
28
|
+
const content = render('done', { profile });
|
|
29
|
+
return render('page', { content });
|
|
30
|
+
}
|
|
31
|
+
exports.renderDone = renderDone;
|
|
32
|
+
// TODO: Use react
|
|
33
|
+
function render(templateName, values) {
|
|
34
|
+
let html = renderer_1.default.getTemplate(templateName);
|
|
35
|
+
const allValues = values;
|
|
36
|
+
for (const variable of templates[templateName]) {
|
|
37
|
+
const value = allValues[variable] || '';
|
|
38
|
+
html = html.replace(`\${${variable}}`, value);
|
|
39
|
+
}
|
|
40
|
+
return html;
|
|
41
|
+
}
|
|
42
|
+
function getTemplate(templateName) {
|
|
43
|
+
if (!(templateName in allHTML)) {
|
|
44
|
+
const file = (0, paths_1.getTemplateFile)(templateName);
|
|
45
|
+
const template = fs_1.default.readFileSync(file).toString();
|
|
46
|
+
allHTML[templateName] = template;
|
|
47
|
+
}
|
|
48
|
+
return allHTML[templateName];
|
|
49
|
+
}
|
|
50
|
+
exports.default = { templates, render, getTemplate, renderAuth, renderDone };
|
|
51
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/lib/renderer.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,0DAAkC;AAClC,mCAA0C;AAI1C,MAAM,SAAS,GAAG;IACjB,IAAI,EAAI,CAAE,SAAS,CAAW;IAC9B,IAAI,EAAI,CAAE,SAAS,EAAE,SAAS,EAAE,YAAY,CAAE;IAC9C,KAAK,EAAG,CAAE,MAAM,EAAE,MAAM,CAAW;IACnC,IAAI,EAAI,CAAE,SAAS,CAAW;CACrB,CAAC;AAPF,8BAAS;AAWlB,MAAM,OAAO,GAAG,EAAkC,CAAC;AAEnD,SAAS,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAyD;IACrG,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE;QACnD,IAAI,EAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAY;QACnC,IAAI,EAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;KAChD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEf,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACjE,OAAO,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACpC,CAAC;AArBmB,gCAAU;AAuB9B,SAAS,UAAU,CAAC,EAAE,OAAO,EAAuB;IACnD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;AACpC,CAAC;AA1B+B,gCAAU;AA4B1C,kBAAkB;AAClB,SAAS,MAAM,CAAyB,YAAe,EAAE,MAAmD;IAC3G,IAAI,IAAI,GAAU,kBAAQ,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,MAAgE,CAAC;IAEnF,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,YAAY,CAAC,EAAE;QAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,GAAU,IAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;KACrD;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,YAA0B;IAC9C,IAAI,CAAC,CAAC,YAAY,IAAI,OAAO,CAAC,EAAE;QAC/B,MAAM,IAAI,GAAc,IAAA,uBAAe,EAAC,YAAY,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAU,YAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACzD,OAAO,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAC;KACjC;IAED,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;AAC9B,CAAC;AAED,kBAAe,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/lib/secrets.js
CHANGED
|
@@ -11,6 +11,7 @@ const open_1 = __importDefault(require("open"));
|
|
|
11
11
|
const logger_1 = require("@anmiles/logger");
|
|
12
12
|
require("@anmiles/prototypes");
|
|
13
13
|
const paths_1 = require("./paths");
|
|
14
|
+
const renderer_1 = require("./renderer");
|
|
14
15
|
const secrets_1 = __importDefault(require("./secrets"));
|
|
15
16
|
exports.default = { getScopes, getSecrets, getCredentials, validateCredentials, createCredentials, deleteCredentials, checkSecrets, getSecretsError, getScopesError };
|
|
16
17
|
const port = 6006;
|
|
@@ -82,11 +83,10 @@ async function createCredentials(profile, auth, options, prompt) {
|
|
|
82
83
|
const url = new URL(`http://${request.headers.host}${request.url}`);
|
|
83
84
|
const code = url.searchParams.get('code');
|
|
84
85
|
if (!code) {
|
|
85
|
-
|
|
86
|
-
response.end(formatMessage(`<p>Please open <a href="${authUrl}">auth page</a> using <strong>${profile}</strong> google profile</p>\n<p>Required scopes:</p>\n<ul>${scopesList}</ul>`));
|
|
86
|
+
response.end((0, renderer_1.renderAuth)({ profile, authUrl, scope }));
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
-
response.end(
|
|
89
|
+
response.end((0, renderer_1.renderDone)({ profile }));
|
|
90
90
|
server.destroy();
|
|
91
91
|
const { tokens } = await auth.getToken(code);
|
|
92
92
|
resolve(tokens);
|
|
@@ -113,15 +113,6 @@ function deleteCredentials(profile) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
exports.deleteCredentials = deleteCredentials;
|
|
116
|
-
function formatMessage(message) {
|
|
117
|
-
return [
|
|
118
|
-
'<div style="width: 100%;height: 100%;display: flex;align-items: start;justify-content: center">',
|
|
119
|
-
'<div style="padding: 0 1em;border: 1px solid black;font-family: Arial, sans-serif;margin: 1em;">',
|
|
120
|
-
message,
|
|
121
|
-
'</div>',
|
|
122
|
-
'</div>',
|
|
123
|
-
].join('\n');
|
|
124
|
-
}
|
|
125
116
|
function checkSecrets(profile, secretsObject, secretsFile) {
|
|
126
117
|
if (secretsObject.web.redirect_uris[0] === callbackURI) {
|
|
127
118
|
return true;
|
package/dist/lib/secrets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,oEAA2C;AAC3C,gDAAwB;AAExB,4CAAuC;AAEvC,+BAA6B;AAC7B,mCAA4E;
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<style type="text/css">
|
|
2
|
+
* {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
html, body {
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body {
|
|
14
|
+
font-family: Arial, sans-serif;
|
|
15
|
+
font-size: 17px;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
padding: 30px 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.box {
|
|
23
|
+
width: 450px;
|
|
24
|
+
min-height: 500px;
|
|
25
|
+
max-height: 100%;
|
|
26
|
+
padding: 78px 40px 28px 40px;
|
|
27
|
+
margin: 1em;
|
|
28
|
+
border: 1px solid #dadce0;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
position: relative;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.box:before {
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 34px;
|
|
39
|
+
border-bottom: 1px solid #dadce0;
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: 0;
|
|
42
|
+
display: block;
|
|
43
|
+
content: '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ul {
|
|
47
|
+
width: 100%;
|
|
48
|
+
margin: 23px 0 30px 0;
|
|
49
|
+
padding-left: 0;
|
|
50
|
+
list-style-type: none;
|
|
51
|
+
overflow: auto;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
li {
|
|
55
|
+
line-height: 48px;
|
|
56
|
+
color: brown;
|
|
57
|
+
border-bottom: 1px solid #dadce0;
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
li:before {
|
|
63
|
+
content: 'W';
|
|
64
|
+
width: 28px;
|
|
65
|
+
height: 28px;
|
|
66
|
+
border-radius: 50%;
|
|
67
|
+
border: 2px solid currentColor;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
margin-right: 10px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
li.readonly {
|
|
76
|
+
color: darkgreen;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
li.readonly:before {
|
|
80
|
+
content: 'R';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
a {
|
|
84
|
+
width: 50%;
|
|
85
|
+
line-height: 2em;
|
|
86
|
+
margin: auto;
|
|
87
|
+
color: #ffffff;
|
|
88
|
+
background: #0057e7;
|
|
89
|
+
border-radius: 10em;
|
|
90
|
+
display: block;
|
|
91
|
+
text-align: center;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
h1 {
|
|
96
|
+
font-size: 24px;
|
|
97
|
+
line-height: 48px;
|
|
98
|
+
font-weight: normal;
|
|
99
|
+
margin: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
p {
|
|
103
|
+
line-height: 24px;
|
|
104
|
+
margin: 0;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
107
|
+
<div class="box">
|
|
108
|
+
${content}
|
|
109
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<li class="${type}">${name}</li>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anmiles/google-api-wrapper",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.2.0",
|
|
4
4
|
"description": "Provides quick interface for getting google API data",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"google",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"main": "dist/index.js",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "rimraf dist && tsc",
|
|
19
|
+
"build": "rimraf dist && tsc && copyfiles -u 1 src/templates/* dist/",
|
|
20
20
|
"lint": "eslint --ext .js,.ts .",
|
|
21
21
|
"lint:fix": "npm run lint -- --fix",
|
|
22
22
|
"test": "jest --verbose",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"login": "node ./dist/login.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@anmiles/google-api-wrapper": "file:.",
|
|
32
33
|
"@anmiles/logger": "^3.0.0",
|
|
33
34
|
"@anmiles/prototypes": "^2.0.1",
|
|
34
35
|
"@anmiles/sleep": "^1.0.2",
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
"@types/server-destroy": "^1.0.1",
|
|
45
46
|
"@typescript-eslint/eslint-plugin": "^5.59.2",
|
|
46
47
|
"@typescript-eslint/parser": "^5.59.2",
|
|
48
|
+
"copyfiles": "^2.4.1",
|
|
47
49
|
"eslint": "^8.40.0",
|
|
48
50
|
"eslint-plugin-align-assignments": "^1.1.2",
|
|
49
51
|
"eslint-plugin-import": "^2.27.5",
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ jest.mock<typeof paths>('../paths', () => ({
|
|
|
8
8
|
getScopesFile : jest.fn().mockImplementation(() => scopesFile),
|
|
9
9
|
getSecretsFile : jest.fn().mockImplementation(() => secretsFile),
|
|
10
10
|
getCredentialsFile : jest.fn().mockImplementation(() => credentialsFile),
|
|
11
|
+
getTemplateFile : jest.fn().mockImplementation(() => templateFile),
|
|
11
12
|
}));
|
|
12
13
|
|
|
13
14
|
jest.mock<Partial<typeof fs>>('fs', () => ({
|
|
@@ -17,15 +18,17 @@ jest.mock<Partial<typeof fs>>('fs', () => ({
|
|
|
17
18
|
}));
|
|
18
19
|
|
|
19
20
|
jest.mock<Partial<typeof path>>('path', () => ({
|
|
20
|
-
join
|
|
21
|
-
dirname : jest.fn().mockImplementation((arg) => arg.split('/').slice(0, -1).join('/')),
|
|
21
|
+
join : jest.fn().mockImplementation((...args) => args.join('/')),
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
|
-
const profile
|
|
24
|
+
const profile = 'username';
|
|
25
|
+
const templateName = 'auth';
|
|
26
|
+
|
|
25
27
|
const profilesFile = 'input/profiles.json';
|
|
26
28
|
const scopesFile = 'scopes.json';
|
|
27
29
|
const secretsFile = 'secrets/username.json';
|
|
28
30
|
const credentialsFile = 'secrets/username.credentials.json';
|
|
31
|
+
const templateFile = 'node_modules/@anmiles/google-api-wrapper/dist/templates/auth.html';
|
|
29
32
|
|
|
30
33
|
let exists: boolean;
|
|
31
34
|
|
|
@@ -61,4 +64,13 @@ describe('src/lib/paths', () => {
|
|
|
61
64
|
expect(result).toEqual(credentialsFile);
|
|
62
65
|
});
|
|
63
66
|
});
|
|
67
|
+
|
|
68
|
+
describe('getTemplateFile', () => {
|
|
69
|
+
|
|
70
|
+
it('should return credentials file', () => {
|
|
71
|
+
const result = original.getTemplateFile(templateName);
|
|
72
|
+
|
|
73
|
+
expect(result).toEqual(templateFile);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
64
76
|
});
|
|
@@ -5,9 +5,10 @@ import paths from '../paths';
|
|
|
5
5
|
import profiles from '../profiles';
|
|
6
6
|
const original = jest.requireActual('../profiles').default as typeof profiles;
|
|
7
7
|
jest.mock<typeof profiles>('../profiles', () => ({
|
|
8
|
-
getProfiles
|
|
9
|
-
setProfiles
|
|
10
|
-
createProfile
|
|
8
|
+
getProfiles : jest.fn().mockImplementation(() => existingProfiles),
|
|
9
|
+
setProfiles : jest.fn(),
|
|
10
|
+
createProfile : jest.fn(),
|
|
11
|
+
filterProfiles : jest.fn(),
|
|
11
12
|
}));
|
|
12
13
|
|
|
13
14
|
jest.mock<Partial<typeof fs>>('fs', () => ({
|
|
@@ -26,13 +27,13 @@ jest.mock<Partial<typeof paths>>('../paths', () => ({
|
|
|
26
27
|
getProfilesFile : jest.fn().mockImplementation(() => profilesFile),
|
|
27
28
|
}));
|
|
28
29
|
|
|
29
|
-
const json
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const allProfiles = [ profile1, profile2 ];
|
|
30
|
+
const json = { key : 'value' };
|
|
31
|
+
const profilesFile = 'profilesFile';
|
|
32
|
+
const profile1 = 'username1';
|
|
33
|
+
const profile2 = 'username2';
|
|
34
|
+
const allProfiles = [ profile1, profile2 ];
|
|
35
35
|
|
|
36
|
+
let existingProfiles: string[];
|
|
36
37
|
let existingFiles: string[] = [];
|
|
37
38
|
|
|
38
39
|
let getJSONSpy: jest.SpyInstance;
|
|
@@ -46,7 +47,9 @@ beforeAll(() => {
|
|
|
46
47
|
beforeEach(() => {
|
|
47
48
|
getJSONSpy.mockImplementation(() => json);
|
|
48
49
|
writeJSONSpy.mockImplementation();
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
existingFiles = [];
|
|
52
|
+
existingProfiles = [ 'username1', 'username2' ];
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
afterAll(() => {
|
|
@@ -118,4 +121,40 @@ describe('src/lib/profiles', () => {
|
|
|
118
121
|
expect(profiles.setProfiles).toHaveBeenCalledWith([ 'username1', 'username2', 'newProfile' ]);
|
|
119
122
|
});
|
|
120
123
|
});
|
|
124
|
+
|
|
125
|
+
describe('filterProfiles', () => {
|
|
126
|
+
it('should get profiles', () => {
|
|
127
|
+
original.filterProfiles();
|
|
128
|
+
|
|
129
|
+
expect(profiles.getProfiles).toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should output error if no profiles', () => {
|
|
133
|
+
existingProfiles = [];
|
|
134
|
+
|
|
135
|
+
const func = () => original.filterProfiles();
|
|
136
|
+
|
|
137
|
+
expect(func).toThrow('Please `npm run create` at least one profile');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should output error if profile does not exist', () => {
|
|
141
|
+
const newProfile = 'newProfile';
|
|
142
|
+
|
|
143
|
+
const func = () => original.filterProfiles(newProfile);
|
|
144
|
+
|
|
145
|
+
expect(func).toThrow(`Profile '${newProfile}' does not exist`);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should return array with requested profile if it exists', () => {
|
|
149
|
+
const found = original.filterProfiles(profile1);
|
|
150
|
+
|
|
151
|
+
expect(found).toEqual([ profile1 ]);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should return all profiles if nothing requested', () => {
|
|
155
|
+
const found = original.filterProfiles();
|
|
156
|
+
|
|
157
|
+
expect(found).toEqual(existingProfiles);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
121
160
|
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import paths from '../paths';
|
|
4
|
+
import renderer from '../renderer';
|
|
5
|
+
|
|
6
|
+
const original = jest.requireActual('../renderer').default as typeof renderer;
|
|
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((...args) => args.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
|
+
page : 'page content = (${content})',
|
|
40
|
+
auth : 'auth profile = (${profile}) authUrl = (${authUrl}) scopesList = (${scopesList})',
|
|
41
|
+
scope : 'scope type = (${type}) name = (${name})',
|
|
42
|
+
done : 'done profile = (${profile})',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const authUrl = 'https://authUrl';
|
|
46
|
+
const profile = 'username';
|
|
47
|
+
const scope = [ 'namespace/scope1.readonly', 'namespace/scope2' ];
|
|
48
|
+
|
|
49
|
+
describe('src/lib/renderer', () => {
|
|
50
|
+
describe('renderAuth', () => {
|
|
51
|
+
it('should return auth page', () => {
|
|
52
|
+
const result = original.renderAuth({ authUrl, profile, scope });
|
|
53
|
+
expect(result).toEqual('page content = (auth profile = (username) authUrl = (https://authUrl) scopesList = (scope type = (readonly) name = (scope1.readonly)\nscope type = () name = (scope2)))');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('renderDone', () => {
|
|
58
|
+
it('should return done page', () => {
|
|
59
|
+
const result = original.renderDone({ profile });
|
|
60
|
+
expect(result).toEqual('page content = (done profile = (username))');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('render', () => {
|
|
65
|
+
it('should replace all template variables with their values', () => {
|
|
66
|
+
const values = { type : 'readonly', name : 'scope.readonly' };
|
|
67
|
+
|
|
68
|
+
const result = original.render('scope', values);
|
|
69
|
+
|
|
70
|
+
expect(result).toEqual('scope type = (readonly) name = (scope.readonly)');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should replace non-existing template variable with empty string', () => {
|
|
74
|
+
const values = { name : 'scope.readonly' };
|
|
75
|
+
|
|
76
|
+
const result = original.render('scope', values as any);
|
|
77
|
+
|
|
78
|
+
expect(result).toEqual('scope type = () name = (scope.readonly)');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('getTemplate', () => {
|
|
83
|
+
for (const templateName in original.templates) {
|
|
84
|
+
it(`should return contents of '${templateName}' template file`, () => {
|
|
85
|
+
const template = original.getTemplate(templateName as TemplateName);
|
|
86
|
+
expect(fs.readFileSync).toHaveBeenCalledTimes(1);
|
|
87
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(`${templateName}.html`);
|
|
88
|
+
expect(template).toEqual(mockTemplates[templateName as TemplateName]);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
it('should cache templates', () => {
|
|
93
|
+
original.getTemplate('template1' as TemplateName);
|
|
94
|
+
|
|
95
|
+
original.getTemplate('template2' as TemplateName);
|
|
96
|
+
original.getTemplate('template2' as TemplateName);
|
|
97
|
+
original.getTemplate('template2' as TemplateName);
|
|
98
|
+
|
|
99
|
+
original.getTemplate('template3' as TemplateName);
|
|
100
|
+
|
|
101
|
+
expect(fs.readFileSync).toHaveBeenCalledWith('template1.html');
|
|
102
|
+
expect(fs.readFileSync).toHaveBeenCalledWith('template2.html');
|
|
103
|
+
expect(fs.readFileSync).toHaveBeenCalledWith('template3.html');
|
|
104
|
+
|
|
105
|
+
expect(fs.readFileSync).toHaveBeenCalledTimes(3);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -5,6 +5,7 @@ import open from 'open';
|
|
|
5
5
|
import type GoogleApis from 'googleapis';
|
|
6
6
|
import logger from '@anmiles/logger';
|
|
7
7
|
import emitter from 'event-emitter';
|
|
8
|
+
import renderer from '../renderer';
|
|
8
9
|
import paths from '../paths';
|
|
9
10
|
import type { Secrets } from '../../types';
|
|
10
11
|
import '@anmiles/prototypes';
|
|
@@ -23,6 +24,11 @@ jest.mock<typeof secrets>('../secrets', () => ({
|
|
|
23
24
|
getSecretsError : jest.fn().mockImplementation(() => secretsError),
|
|
24
25
|
}));
|
|
25
26
|
|
|
27
|
+
jest.mock<Partial<typeof renderer>>('../renderer', () => ({
|
|
28
|
+
renderAuth : jest.fn().mockImplementation(({ profile, authUrl, scope } : { profile: string, authUrl: string, scope: string[] }) => `content = profile = ${profile} authUrl = ${authUrl} scope = ${scope.join('|')}`),
|
|
29
|
+
renderDone : jest.fn().mockImplementation(() => 'content = done'),
|
|
30
|
+
}));
|
|
31
|
+
|
|
26
32
|
jest.mock<Partial<typeof http>>('http', () => ({
|
|
27
33
|
createServer : jest.fn().mockImplementation(() => server),
|
|
28
34
|
}));
|
|
@@ -60,6 +66,7 @@ jest.mock<Partial<typeof paths>>('../paths', () => ({
|
|
|
60
66
|
getScopesFile : jest.fn().mockImplementation(() => scopesFile),
|
|
61
67
|
getSecretsFile : jest.fn().mockImplementation(() => secretsFile),
|
|
62
68
|
getCredentialsFile : jest.fn().mockImplementation(() => credentialsFile),
|
|
69
|
+
getTemplateFile : jest.fn().mockImplementation(() => templateFile),
|
|
63
70
|
}));
|
|
64
71
|
|
|
65
72
|
jest.useFakeTimers();
|
|
@@ -72,6 +79,7 @@ const profile = 'username1';
|
|
|
72
79
|
const scopesFile = 'scopes.json';
|
|
73
80
|
const secretsFile = 'secrets/username1.json';
|
|
74
81
|
const credentialsFile = 'secrets/username1.credentials.json';
|
|
82
|
+
const templateFile = 'templates/template.json';
|
|
75
83
|
const wrongRedirectURI = 'wrong_redirect_uri';
|
|
76
84
|
|
|
77
85
|
const scopesError = 'scopesError';
|
|
@@ -79,7 +87,7 @@ const secretsError = 'secretsError';
|
|
|
79
87
|
|
|
80
88
|
const scopesJSON: string[] = [
|
|
81
89
|
'https://www.googleapis.com/auth/calendar.calendars.readonly',
|
|
82
|
-
'https://www.googleapis.com/auth/calendar.events
|
|
90
|
+
'https://www.googleapis.com/auth/calendar.events',
|
|
83
91
|
];
|
|
84
92
|
|
|
85
93
|
const secretsJSON: Secrets = {
|
|
@@ -371,7 +379,7 @@ describe('src/lib/secrets', () => {
|
|
|
371
379
|
prompt : undefined,
|
|
372
380
|
scope : [
|
|
373
381
|
'https://www.googleapis.com/auth/calendar.calendars.readonly',
|
|
374
|
-
'https://www.googleapis.com/auth/calendar.events
|
|
382
|
+
'https://www.googleapis.com/auth/calendar.events',
|
|
375
383
|
],
|
|
376
384
|
});
|
|
377
385
|
});
|
|
@@ -386,7 +394,7 @@ describe('src/lib/secrets', () => {
|
|
|
386
394
|
prompt : 'consent',
|
|
387
395
|
scope : [
|
|
388
396
|
'https://www.googleapis.com/auth/calendar.calendars.readonly',
|
|
389
|
-
'https://www.googleapis.com/auth/calendar.events
|
|
397
|
+
'https://www.googleapis.com/auth/calendar.events',
|
|
390
398
|
],
|
|
391
399
|
});
|
|
392
400
|
});
|
|
@@ -442,14 +450,7 @@ describe('src/lib/secrets', () => {
|
|
|
442
450
|
makeRequest('/');
|
|
443
451
|
await Promise.resolve();
|
|
444
452
|
|
|
445
|
-
expect(endSpy).toHaveBeenCalledWith(
|
|
446
|
-
<div style="width: 100%;height: 100%;display: flex;align-items: start;justify-content: center">\n\
|
|
447
|
-
<div style="padding: 0 1em;border: 1px solid black;font-family: Arial, sans-serif;margin: 1em;">\n\
|
|
448
|
-
<p>Please open <a href="${authUrl}">auth page</a> using <strong>${profile}</strong> google profile</p>\n\
|
|
449
|
-
<p>Required scopes:</p>\n\
|
|
450
|
-
<ul><li>https://www.googleapis.com/auth/calendar.calendars.readonly</li><li>https://www.googleapis.com/auth/calendar.events.readonly</li></ul>\n\
|
|
451
|
-
</div>\n\
|
|
452
|
-
</div>`);
|
|
453
|
+
expect(endSpy).toHaveBeenCalledWith('content = profile = username1 authUrl = https://authUrl scope = https://www.googleapis.com/auth/calendar.calendars.readonly|https://www.googleapis.com/auth/calendar.events');
|
|
453
454
|
});
|
|
454
455
|
|
|
455
456
|
it('should ask to close webpage', async () => {
|
|
@@ -457,12 +458,7 @@ describe('src/lib/secrets', () => {
|
|
|
457
458
|
makeRequest(tokenUrl);
|
|
458
459
|
await Promise.resolve();
|
|
459
460
|
|
|
460
|
-
expect(endSpy).toHaveBeenCalledWith('
|
|
461
|
-
<div style="width: 100%;height: 100%;display: flex;align-items: start;justify-content: center">\n\
|
|
462
|
-
<div style="padding: 0 1em;border: 1px solid black;font-family: Arial, sans-serif;margin: 1em;">\n\
|
|
463
|
-
<p>Please close this page and return to application</p>\n\
|
|
464
|
-
</div>\n\
|
|
465
|
-
</div>');
|
|
461
|
+
expect(endSpy).toHaveBeenCalledWith('content = done');
|
|
466
462
|
});
|
|
467
463
|
|
|
468
464
|
it('should close server and destroy all connections if request.url is truthy', async () => {
|
|
@@ -577,7 +573,7 @@ Here is how to obtain it:\n\
|
|
|
577
573
|
Specify your email as user support email and as developer contact information on the very bottom\n\
|
|
578
574
|
Click "Save and continue"\n\
|
|
579
575
|
Click "Add or remove scopes"\n\
|
|
580
|
-
Add scopes: https://www.googleapis.com/auth/calendar.calendars.readonly,https://www.googleapis.com/auth/calendar.events
|
|
576
|
+
Add scopes: https://www.googleapis.com/auth/calendar.calendars.readonly,https://www.googleapis.com/auth/calendar.events\n\
|
|
581
577
|
Click "Save and continue"\n\
|
|
582
578
|
Click "Add users"\n\
|
|
583
579
|
Add your email\n\
|
package/src/lib/paths.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import type { templates } from './renderer';
|
|
2
3
|
|
|
3
|
-
export { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile };
|
|
4
|
-
export default { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile };
|
|
4
|
+
export { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile, getTemplateFile };
|
|
5
|
+
export default { getProfilesFile, getScopesFile, getSecretsFile, getCredentialsFile, getTemplateFile };
|
|
5
6
|
|
|
6
7
|
const dirPaths = {
|
|
7
|
-
input
|
|
8
|
-
secrets
|
|
8
|
+
input : 'input',
|
|
9
|
+
secrets : 'secrets',
|
|
10
|
+
// TODO: Remove this hack after moving to React
|
|
11
|
+
templates : 'node_modules/@anmiles/google-api-wrapper/dist/templates',
|
|
9
12
|
};
|
|
10
13
|
|
|
11
14
|
function getProfilesFile() {
|
|
@@ -23,3 +26,7 @@ function getSecretsFile(profile: string) {
|
|
|
23
26
|
function getCredentialsFile(profile: string) {
|
|
24
27
|
return path.join(dirPaths.secrets, `${profile}.credentials.json`);
|
|
25
28
|
}
|
|
29
|
+
|
|
30
|
+
function getTemplateFile(templateName: keyof typeof templates) {
|
|
31
|
+
return path.join(dirPaths.templates, `${templateName}.html`);
|
|
32
|
+
}
|
package/src/lib/profiles.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { getProfilesFile } from './paths';
|
|
|
4
4
|
|
|
5
5
|
import profiles from './profiles';
|
|
6
6
|
|
|
7
|
-
export { getProfiles, setProfiles, createProfile };
|
|
8
|
-
export default { getProfiles, setProfiles, createProfile };
|
|
7
|
+
export { getProfiles, setProfiles, createProfile, filterProfiles };
|
|
8
|
+
export default { getProfiles, setProfiles, createProfile, filterProfiles };
|
|
9
9
|
|
|
10
10
|
function getProfiles(): string[] {
|
|
11
11
|
const profilesFile = getProfilesFile();
|
|
@@ -31,3 +31,21 @@ function createProfile(profile: string): void {
|
|
|
31
31
|
existingProfiles.push(profile);
|
|
32
32
|
profiles.setProfiles(existingProfiles);
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
function filterProfiles(profile?: string): string[] {
|
|
36
|
+
const existingProfiles = profiles.getProfiles();
|
|
37
|
+
|
|
38
|
+
if (existingProfiles.length === 0) {
|
|
39
|
+
throw 'Please `npm run create` at least one profile';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!profile) {
|
|
43
|
+
return existingProfiles;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (existingProfiles.includes(profile)) {
|
|
47
|
+
return [ profile ];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw `Profile '${profile}' does not exist`;
|
|
51
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import renderer from './renderer';
|
|
3
|
+
import { getTemplateFile } from './paths';
|
|
4
|
+
|
|
5
|
+
export { templates, renderAuth, renderDone };
|
|
6
|
+
|
|
7
|
+
const templates = {
|
|
8
|
+
page : [ 'content' ] as const,
|
|
9
|
+
auth : [ 'profile', 'authUrl', 'scopesList' ],
|
|
10
|
+
scope : [ 'type', 'name' ] as const,
|
|
11
|
+
done : [ 'profile' ] as const,
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
type TemplateName = keyof typeof templates;
|
|
15
|
+
|
|
16
|
+
const allHTML = {} as Record<TemplateName, string>;
|
|
17
|
+
|
|
18
|
+
function renderAuth({ profile, authUrl, scope }: { profile: string, authUrl: string, scope: string[] }) {
|
|
19
|
+
const scopesList = scope.map((s) => render('scope', {
|
|
20
|
+
name : s.split('/').pop() as string,
|
|
21
|
+
type : s.endsWith('.readonly') ? 'readonly' : '',
|
|
22
|
+
})).join('\n');
|
|
23
|
+
|
|
24
|
+
const content = render('auth', { profile, authUrl, scopesList });
|
|
25
|
+
return render('page', { content });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function renderDone({ profile }: { profile: string }): string {
|
|
29
|
+
const content = render('done', { profile });
|
|
30
|
+
return render('page', { content });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// TODO: Use react
|
|
34
|
+
function render<T extends TemplateName>(templateName: T, values: Record<typeof templates[T][number], string>): string {
|
|
35
|
+
let html = renderer.getTemplate(templateName);
|
|
36
|
+
const allValues = values as Record<typeof templates[TemplateName][number], string>;
|
|
37
|
+
|
|
38
|
+
for (const variable of templates[templateName]) {
|
|
39
|
+
const value = allValues[variable] || '';
|
|
40
|
+
html = html.replace(`\${${variable}}`, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return html;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getTemplate(templateName: TemplateName) {
|
|
47
|
+
if (!(templateName in allHTML)) {
|
|
48
|
+
const file = getTemplateFile(templateName);
|
|
49
|
+
const template = fs.readFileSync(file).toString();
|
|
50
|
+
allHTML[templateName] = template;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return allHTML[templateName];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default { templates, render, getTemplate, renderAuth, renderDone };
|
package/src/lib/secrets.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { warn } from '@anmiles/logger';
|
|
|
7
7
|
import type { Secrets, AuthOptions } from '../types';
|
|
8
8
|
import '@anmiles/prototypes';
|
|
9
9
|
import { getScopesFile, getSecretsFile, getCredentialsFile } from './paths';
|
|
10
|
+
import { renderAuth, renderDone } from './renderer';
|
|
10
11
|
|
|
11
12
|
import secrets from './secrets';
|
|
12
13
|
|
|
@@ -96,12 +97,11 @@ async function createCredentials(profile: string, auth: GoogleApis.Auth.OAuth2Cl
|
|
|
96
97
|
const code = url.searchParams.get('code');
|
|
97
98
|
|
|
98
99
|
if (!code) {
|
|
99
|
-
|
|
100
|
-
response.end(formatMessage(`<p>Please open <a href="${authUrl}">auth page</a> using <strong>${profile}</strong> google profile</p>\n<p>Required scopes:</p>\n<ul>${scopesList}</ul>`));
|
|
100
|
+
response.end(renderAuth({ profile, authUrl, scope }));
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
response.end(
|
|
104
|
+
response.end(renderDone({ profile }));
|
|
105
105
|
server.destroy();
|
|
106
106
|
const { tokens } = await auth.getToken(code);
|
|
107
107
|
resolve(tokens);
|
|
@@ -132,16 +132,6 @@ function deleteCredentials(profile: string): void {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function formatMessage(message: string): string {
|
|
136
|
-
return [
|
|
137
|
-
'<div style="width: 100%;height: 100%;display: flex;align-items: start;justify-content: center">',
|
|
138
|
-
'<div style="padding: 0 1em;border: 1px solid black;font-family: Arial, sans-serif;margin: 1em;">',
|
|
139
|
-
message,
|
|
140
|
-
'</div>',
|
|
141
|
-
'</div>',
|
|
142
|
-
].join('\n');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
135
|
function checkSecrets(profile: string, secretsObject: Secrets, secretsFile: string): true | void {
|
|
146
136
|
if (secretsObject.web.redirect_uris[0] === callbackURI) {
|
|
147
137
|
return true;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<style type="text/css">
|
|
2
|
+
* {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
html, body {
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 100%;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body {
|
|
14
|
+
font-family: Arial, sans-serif;
|
|
15
|
+
font-size: 17px;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
padding: 30px 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.box {
|
|
23
|
+
width: 450px;
|
|
24
|
+
min-height: 500px;
|
|
25
|
+
max-height: 100%;
|
|
26
|
+
padding: 78px 40px 28px 40px;
|
|
27
|
+
margin: 1em;
|
|
28
|
+
border: 1px solid #dadce0;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
position: relative;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.box:before {
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 34px;
|
|
39
|
+
border-bottom: 1px solid #dadce0;
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: 0;
|
|
42
|
+
display: block;
|
|
43
|
+
content: '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ul {
|
|
47
|
+
width: 100%;
|
|
48
|
+
margin: 23px 0 30px 0;
|
|
49
|
+
padding-left: 0;
|
|
50
|
+
list-style-type: none;
|
|
51
|
+
overflow: auto;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
li {
|
|
55
|
+
line-height: 48px;
|
|
56
|
+
color: brown;
|
|
57
|
+
border-bottom: 1px solid #dadce0;
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
li:before {
|
|
63
|
+
content: 'W';
|
|
64
|
+
width: 28px;
|
|
65
|
+
height: 28px;
|
|
66
|
+
border-radius: 50%;
|
|
67
|
+
border: 2px solid currentColor;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
margin-right: 10px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
li.readonly {
|
|
76
|
+
color: darkgreen;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
li.readonly:before {
|
|
80
|
+
content: 'R';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
a {
|
|
84
|
+
width: 50%;
|
|
85
|
+
line-height: 2em;
|
|
86
|
+
margin: auto;
|
|
87
|
+
color: #ffffff;
|
|
88
|
+
background: #0057e7;
|
|
89
|
+
border-radius: 10em;
|
|
90
|
+
display: block;
|
|
91
|
+
text-align: center;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
h1 {
|
|
96
|
+
font-size: 24px;
|
|
97
|
+
line-height: 48px;
|
|
98
|
+
font-weight: normal;
|
|
99
|
+
margin: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
p {
|
|
103
|
+
line-height: 24px;
|
|
104
|
+
margin: 0;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
107
|
+
<div class="box">
|
|
108
|
+
${content}
|
|
109
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<li class="${type}">${name}</li>
|