Skip to content

Commit

Permalink
refactor: linting and code improvement (google#873)
Browse files Browse the repository at this point in the history
  • Loading branch information
PopGoesTheWza authored Aug 30, 2021
1 parent 598d60c commit e851215
Show file tree
Hide file tree
Showing 23 changed files with 1,305 additions and 705 deletions.
1,751 changes: 1,186 additions & 565 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,17 @@
"author": "Grant Timmerman",
"license": "Apache-2.0",
"dependencies": {
"@sindresorhus/is": "^4.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"cli-truncate": "^2.1.0",
"cli-truncate": "^3.0.0",
"commander": "^8.1.0",
"debounce": "^1.2.1",
"dotf": "^2.0.1",
"find-up": "^5.0.0",
"dotf": "^2.0.2",
"find-up": "^6.0.0",
"fs-extra": "^10.0.0",
"fuzzy": "^0.1.3",
"google-auth-library": "^7.5.0",
"google-auth-library": "^7.6.2",
"googleapis": "^84.0.0",
"inquirer": "^8.1.2",
"inquirer-autocomplete-prompt-ipt": "^2.0.0",
Expand All @@ -80,35 +81,34 @@
"multimatch": "^5.0.0",
"normalize-newline": "^4.1.0",
"open": "^8.2.1",
"ora": "^5.4.1",
"ora": "^6.0.0",
"p-map": "^5.1.0",
"read-pkg-up": "^8.0.0",
"recursive-readdir": "^2.2.2",
"server-destroy": "^1.0.1",
"split-lines": "^3.0.0",
"strip-bom": "^5.0.0",
"ts2gas": "^4.1.0",
"typescript": "^4.3.5",
"wtfnode": "^0.9.1"
"ts2gas": "^4.2.0",
"typescript": "^4.4.2"
},
"devDependencies": {
"@types/chai": "^4.2.21",
"@types/debounce": "^1.2.0",
"@types/fs-extra": "^9.0.12",
"@types/inquirer": "^7.3.3",
"@types/mocha": "^9.0.0",
"@types/node": "^12.20.19",
"@types/node": "^12.20.21",
"@types/recursive-readdir": "^2.2.0",
"@types/server-destroy": "^1.0.1",
"@types/tmp": "^0.2.1",
"@types/wtfnode": "^0.7.0",
"chai": "^4.3.4",
"coveralls": "^3.1.1",
"gts": "^3.1.0",
"mocha": "^9.0.3",
"mocha": "^9.1.1",
"nyc": "^15.1.0",
"prettier": "^2.3.2",
"tmp": "^0.2.1",
"type-fest": "^2.0.0"
"type-fest": "^2.1.0"
}
}
25 changes: 7 additions & 18 deletions src/apiutils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fuzzy from 'fuzzy';
import {script_v1 as scriptV1} from 'googleapis';
import type {ReadonlyDeep} from 'type-fest';

import {loadAPICredentials, serviceUsage} from './auth.js';
import {ClaspError} from './clasp-error.js';
Expand All @@ -8,10 +9,6 @@ import {enableOrDisableAdvanceServiceInManifest} from './manifest.js';
import {ERROR} from './messages.js';
import {getProjectId, spinner, stopSpinner} from './utils.js';

import type {ReadonlyDeep} from 'type-fest';

type TypeFunction = Readonly<scriptV1.Schema$GoogleAppsScriptTypeFunction>;

/**
* Prompts for the function name.
*/
Expand All @@ -24,18 +21,15 @@ export const getFunctionNames = async (script: ReadonlyDeep<scriptV1.Script>, sc
}

const {files = []} = content.data;
const functionNames: string[] = files
.reduce(
(functions: ReadonlyArray<TypeFunction>, file: Readonly<scriptV1.Schema$File>) =>
file.functionSet && file.functionSet.values ? [...functions, ...file.functionSet.values] : functions,
[]
)
.map((func: TypeFunction) => func.name) as string[];
const functionNames = files
.filter(file => file.functionSet?.values)
.flatMap(file => file.functionSet!.values!)
.map(func => func.name!);

// Returns a Promise
// https://www.npmjs.com/package/inquirer-autocomplete-prompt-ipt#options
// Example: https://github.com/ruyadorno/inquirer-autocomplete-prompt/blob/master/example.js#L76
const source: functionNameSource = async (_answers: object, input = '') =>
const source: functionNameSource = async (_answers: unknown, input = '') =>
fuzzy.filter(input, functionNames).map(element => element.original);

return (await functionNamePrompt(source)).functionName;
Expand Down Expand Up @@ -75,12 +69,7 @@ export const enableOrDisableAPI = async (serviceName: string, enable: boolean):

const name = `projects/${await getProjectIdOrDie()}/services/${serviceName}.googleapis.com`;
try {
if (enable) {
await serviceUsage.services.enable({name});
} else {
await serviceUsage.services.disable({name});
}

await (enable ? serviceUsage.services.enable({name}) : serviceUsage.services.disable({name}));
await enableOrDisableAdvanceServiceInManifest(serviceName, enable);
console.log(`${enable ? 'Enable' : 'Disable'}d ${serviceName} API.`);
} catch (error) {
Expand Down
15 changes: 6 additions & 9 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ import {google, script_v1 as scriptV1} from 'googleapis';
import {createServer} from 'http';
import open from 'open';
import readline from 'readline';
import {URL} from 'url';

import {ClaspError} from './clasp-error.js';
import {DOTFILE} from './dotfile.js';
import {ERROR, LOG} from './messages.js';
import {checkIfOnlineOrDie, getOAuthSettings} from './utils.js';

import enableDestroy from 'server-destroy';
import type {Credentials, GenerateAuthUrlOpts, OAuth2ClientOptions} from 'google-auth-library';
import type {IncomingMessage, Server, ServerResponse} from 'http';
import type {AddressInfo} from 'net';
import type {ReadonlyDeep} from 'type-fest';

import {ClaspError} from './clasp-error.js';
import {DOTFILE} from './dotfile.js';
import {ERROR, LOG} from './messages.js';
import {checkIfOnlineOrDie, getOAuthSettings} from './utils.js';
import type {ClaspToken} from './dotfile';
import type {ClaspCredentials} from './utils';
import enableDestroy from 'server-destroy';

/**
* Authentication with Google's APIs.
Expand Down Expand Up @@ -240,7 +237,7 @@ const authorizeWithLocalhost = async (
});
const authUrl = client.generateAuthUrl(oAuth2ClientAuthUrlOptions);
console.log(LOG.AUTHORIZE(authUrl));
(async () => await open(authUrl))();
(async () => open(authUrl))();
});
server.destroy();

Expand Down
19 changes: 10 additions & 9 deletions src/commands/apis.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {discovery_v1 as discoveryV1, serviceusage_v1 as serviceUsageV1} from 'googleapis';
import open from 'open';
import type {ReadonlyDeep} from 'type-fest';

import {PUBLIC_ADVANCED_SERVICES} from '../apis.js';
import {enableOrDisableAPI} from '../apiutils.js';
Expand All @@ -9,8 +10,6 @@ import {ERROR} from '../messages.js';
import {URL} from '../urls.js';
import {checkIfOnlineOrDie, getProjectId} from '../utils.js';

import type {ReadonlyDeep} from 'type-fest';

type DirectoryItem = Unpacked<discoveryV1.Schema$DirectoryList['items']>;
type PublicAdvancedService = ReadonlyDeep<Required<NonNullable<DirectoryItem>>>;

Expand All @@ -28,14 +27,14 @@ export default async (options: CommandOption): Promise<void> => {

// clasp apis --open
if (options.open) {
return await openApiUrl();
return openApiUrl();
}

const [_bin, _sourcePath, ...args] = process.argv;
const [_command, subCommand, serviceName] = args;

// The apis subcommands.
const apiSubCommands: {[key: string]: () => Promise<void>} = {
const apiSubCommands: Record<string, () => Promise<void>> = {
disable: async () => enableOrDisableAPI(serviceName, false),
enable: async () => enableOrDisableAPI(serviceName, true),
list: async () => {
Expand All @@ -60,10 +59,10 @@ export default async (options: CommandOption): Promise<void> => {
const enabledAPIs = serviceList.filter(
(service: Readonly<serviceUsageV1.Schema$GoogleApiServiceusageV1Service>) => service.state === 'ENABLED'
);
for (const enabledAPI of enabledAPIs) {
if (enabledAPI.config && enabledAPI.config.documentation) {
const name = enabledAPI.config.name ?? 'Unknown name.';
console.log(`${name.slice(0, name.indexOf('.'))} - ${enabledAPI.config.documentation.summary}`);
for (const {config} of enabledAPIs) {
if (config?.documentation) {
const name = config.name ?? 'Unknown name.';
console.log(`${name.slice(0, name.indexOf('.'))} - ${config.documentation.summary!}`);
}
}

Expand All @@ -88,7 +87,9 @@ export default async (options: CommandOption): Promise<void> => {
publicServices.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));

// Format the list
publicServices.forEach(service => console.log(`${service.name.padEnd(25)} - ${service.description.padEnd(60)}`));
for (const service of publicServices) {
console.log(`${service.name.padEnd(25)} - ${service.description.padEnd(60)}`);
}
},
undefined: async () => {
await apiSubCommands.list();
Expand Down
13 changes: 7 additions & 6 deletions src/commands/create.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import is from '@sindresorhus/is';
import {SCRIPT_TYPES} from '../apis.js';
import {drive, loadAPICredentials, script} from '../auth.js';
import {ClaspError} from '../clasp-error.js';
Expand Down Expand Up @@ -49,11 +50,11 @@ export default async (options: CommandOption): Promise<void> => {
const {parentId: optionParentId, title: name = getDefaultProjectName(), type: optionType} = options;
let parentId = optionParentId;

const filetype = optionType ?? (!optionParentId ? (await scriptTypePrompt()).type : '');
const filetype = optionType ?? (optionParentId ? '' : (await scriptTypePrompt()).type);

// Create files with MIME type.
// https://developers.google.com/drive/api/v3/mime-types
const DRIVE_FILE_MIMETYPES: {[key: string]: string} = {
const DRIVE_FILE_MIMETYPES: Record<string, string> = {
[SCRIPT_TYPES.DOCS]: 'application/vnd.google-apps.document',
[SCRIPT_TYPES.FORMS]: 'application/vnd.google-apps.form',
[SCRIPT_TYPES.SHEETS]: 'application/vnd.google-apps.spreadsheet',
Expand All @@ -66,19 +67,19 @@ export default async (options: CommandOption): Promise<void> => {
const {
data: {id: newParentId},
} = await drive.files.create({requestBody: {mimeType, name}});
parentId = newParentId as string;
parentId = newParentId!;

stopSpinner();

console.log(LOG.CREATE_DRIVE_FILE_FINISH(filetype, parentId as string));
console.log(LOG.CREATE_DRIVE_FILE_FINISH(filetype, parentId));
}

// CLI Spinner
spinner.start(LOG.CREATE_PROJECT_START(name));

let projectExist: boolean;
try {
projectExist = typeof (await getProjectSettings()).scriptId === 'string';
projectExist = is.string((await getProjectSettings()).scriptId);
} catch {
process.exitCode = 0; // To reset `exitCode` that was overriden in ClaspError constructor.
projectExist = false;
Expand All @@ -90,7 +91,7 @@ export default async (options: CommandOption): Promise<void> => {

// Create a new Apps Script project
const {data, status, statusText} = await script.projects.create({
requestBody: {parentId: parentId, title: name},
requestBody: {parentId, title: name},
});

stopSpinner();
Expand Down
8 changes: 4 additions & 4 deletions src/commands/default.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {ClaspError} from '../clasp-error.js';
import {ERROR} from '../messages.js';

import type {Command} from 'commander';
import type {ReadonlyDeep} from 'type-fest';

import {ClaspError} from '../clasp-error.js';
import {ERROR} from '../messages.js';

/**
* Displays a default message when an unknown command is typed.
* @param command {string} The command that was typed.
*/
export default async (_: object, command: ReadonlyDeep<Command>): Promise<void> => {
export default async (_: unknown, command: ReadonlyDeep<Command>): Promise<void> => {
throw new ClaspError(ERROR.COMMAND_DNE(command.args.join(' ')));
};
2 changes: 1 addition & 1 deletion src/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default async (options: CommandOption): Promise<void> => {

if (files.length > 0) {
for (const file of files) {
console.log(`${!options.noShorten ? ellipsize(file.name!, 20) : file.name} - ${URL.SCRIPT(file.id ?? '')}`);
console.log(`${options.noShorten ? file.name! : ellipsize(file.name!, 20)} - ${URL.SCRIPT(file.id ?? '')}`);
}
} else {
console.log(LOG.FINDING_SCRIPTS_DNE);
Expand Down
3 changes: 2 additions & 1 deletion src/commands/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {FS_OPTIONS} from '../constants.js';
import {readManifest} from '../manifest.js';
import {ERROR, LOG} from '../messages.js';
import {checkIfOnlineOrDie, hasOauthClientSettings, safeIsOnline} from '../utils.js';
import type {ClaspCredentials} from '../utils.js';

const {readJsonSync} = fs;

Expand Down Expand Up @@ -69,7 +70,7 @@ export default async (options: CommandOption): Promise<void> => {
File > Project Properties > Scopes\n`);

// Read credentials file.
const creds = readJsonSync(options.creds, FS_OPTIONS);
const creds = readJsonSync(options.creds, FS_OPTIONS) as Readonly<ClaspCredentials>;
await authorize({creds, scopes, useLocalhost});
await enableAppsScriptAPI();

Expand Down
17 changes: 10 additions & 7 deletions src/commands/logout.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {Conf} from '../conf.js';
import fs from 'fs-extra';

import {Conf} from '../conf.js';

const config = Conf.get();

const deleteIfExists = (file: string | undefined) => {
if (file && fs.existsSync(file)) {
fs.unlinkSync(file);
}
};

/**
* Logs out the user by deleting credentials.
*/
export default async (): Promise<void> => {
if (config.auth && fs.existsSync(config.auth)) {
fs.unlinkSync(config.auth);
}
if (config.authLocal && fs.existsSync(config.authLocal)) {
fs.unlinkSync(config.authLocal);
}
deleteIfExists(config.auth);
deleteIfExists(config.authLocal);
};
15 changes: 8 additions & 7 deletions src/commands/logs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import is from '@sindresorhus/is';
import chalk from 'chalk';
import {logging_v2 as loggingV2} from 'googleapis';
import open from 'open';
Expand Down Expand Up @@ -57,10 +58,10 @@ export default async (options: CommandOption): Promise<void> => {
// Otherwise, if not opening StackDriver, load StackDriver logs.
if (options.watch) {
const POLL_INTERVAL = 6000; // 6s
setInterval(() => {
setInterval(async () => {
const startDate = new Date();
startDate.setSeconds(startDate.getSeconds() - (10 * POLL_INTERVAL) / 1000);
fetchAndPrintLogs(json, simplified, projectId, startDate);
await fetchAndPrintLogs(json, simplified, projectId, startDate);
}, POLL_INTERVAL);
} else {
await fetchAndPrintLogs(json, simplified, projectId);
Expand All @@ -74,9 +75,9 @@ export default async (options: CommandOption): Promise<void> => {
* rather than filter server-side.
* @see logs.data.entries[0].insertId
*/
const logEntryCache: {[key: string]: boolean} = {};
const logEntryCache: Record<string, boolean> = {};

const severityColor: {[key: string]: chalk.Chalk} = {
const severityColor: Record<string, chalk.Chalk> = {
ERROR: chalk.red,
INFO: chalk.cyan,
DEBUG: chalk.green, // Includes timeEnd
Expand All @@ -99,7 +100,7 @@ const printLogs = (
if (resource?.labels) {
let {function_name: functionName = ERROR.NO_FUNCTION_NAME} = resource.labels;
functionName = functionName.padEnd(15);
let payloadData: string | {[key: string]: unknown} = '';
let payloadData: string | Record<string, unknown> = '';
if (formatJson) {
payloadData = JSON.stringify(entry, null, 2);
} else {
Expand Down Expand Up @@ -134,12 +135,12 @@ const obscure = (entry: Readonly<loggingV2.Schema$LogEntry>, functionName: strin
((jsonPayload ? JSON.stringify(jsonPayload).slice(0, 255) : '') || protoPayload) ??
ERROR.PAYLOAD_UNKNOWN;

if (typeof payloadData !== 'string' && protoPayload!['@type'] === 'type.googleapis.com/google.cloud.audit.AuditLog') {
if (!is.string(payloadData) && protoPayload!['@type'] === 'type.googleapis.com/google.cloud.audit.AuditLog') {
payloadData = LOG.STACKDRIVER_SETUP;
functionName = (protoPayload!.methodName as string).padEnd(15);
}

if (payloadData && typeof payloadData === 'string') {
if (is.string(payloadData)) {
payloadData = payloadData.padEnd(20);
}

Expand Down
Loading

0 comments on commit e851215

Please sign in to comment.