From 5c43c1fc373294b9ac9d4fca373b51c882e5f97c Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 1 Sep 2022 00:06:19 -0600 Subject: [PATCH] lint+feat: add types + minor ws-ish refactor --- bin/localize-types | 14 +++++++++ index.js | 70 ++++++++++++++++++++++++------------------ jsconfig.json | 76 ++++++++++++++++++++++++++++++++++++++++++++++ local-types.js | 5 +++ package.json | 9 ++++-- types.js | 34 +++++++++++++++++++++ 6 files changed, 177 insertions(+), 31 deletions(-) create mode 100755 bin/localize-types create mode 100644 jsconfig.json create mode 100644 local-types.js create mode 100644 types.js diff --git a/bin/localize-types b/bin/localize-types new file mode 100755 index 0000000..66f102e --- /dev/null +++ b/bin/localize-types @@ -0,0 +1,14 @@ +#!/bin/sh + +my_typedefs="$( + grep typedef ./types.js | cut -d ' ' -f5 +)" + +rm -f ./local-types.js +{ + echo '/**' + for my_type in $my_typedefs; do + echo " * @typedef {import('./types.js').${my_type}} ${my_type}" + done + echo ' */' +} >> ./local-types.js diff --git a/index.js b/index.js index 52de083..f7bba7b 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,35 @@ var os = require('os'); var pkg = require('./package.json'); var fs = require('fs'); // only for streams +var _defaults = { + sendImmediately: true, + method: '', + headers: {}, + useQuerystring: false, + followRedirect: true, + followAllRedirects: false, + followOriginalHttpMethod: false, + maxRedirects: 10, + removeRefererHeader: false, + // encoding: undefined, + // stream: false, // TODO allow a stream? + gzip: false + //, body: undefined + //, json: undefined +}; + +var _keys = Object.keys(_defaults).concat([ + 'encoding', + 'stream', + 'body', + 'json', + 'form', + 'auth', + 'formData', + 'FormData', + 'userAgent' // non-standard for request.js +]); + function debug() { if (module.exports.debug) { console.log.apply(console, arguments); @@ -165,10 +194,16 @@ function handleResponse(resp, opts, cb) { }); } +/** + * @param {any} defs - TODO enumerate defaults + * @returns {Request} + */ function setDefaults(defs) { defs = defs || {}; + /** @type {Request} */ function urequestHelper(opts, cb) { + //jshint maxcomplexity:42 debug('\n[urequest] processed options:'); debug(opts); @@ -522,7 +557,7 @@ function setDefaults(defs) { opts = { url: opts }; } - module.exports._keys.forEach(function (key) { + _keys.forEach(function (key) { if (key in opts && 'undefined' !== typeof opts[key]) { reqOpts[key] = opts[key]; } else if (key in defs) { @@ -653,35 +688,12 @@ function getUserAgent(additional) { return ua; } -var _defaults = { - sendImmediately: true, - method: '', - headers: {}, - useQuerystring: false, - followRedirect: true, - followAllRedirects: false, - followOriginalHttpMethod: false, - maxRedirects: 10, - removeRefererHeader: false, - // encoding: undefined, - // stream: false, // TODO allow a stream? - gzip: false - //, body: undefined - //, json: undefined -}; -module.exports = setDefaults(_defaults); +exports.request = setDefaults(_defaults); +exports._keys = _keys; + +module.exports = exports.request; +module.exports._keys = _keys; -module.exports._keys = Object.keys(_defaults).concat([ - 'encoding', - 'stream', - 'body', - 'json', - 'form', - 'auth', - 'formData', - 'FormData', - 'userAgent' // non-standard for request.js -]); module.exports.debug = -1 !== (process.env.NODE_DEBUG || '').split(/\s+/g).indexOf('urequest'); diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..39150df --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,76 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + "target": "es2021" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, + "module": "commonjs", + // "lib": [], /* Specify library files to be included in the compilation. */ + "allowJs": true /* Allow javascript files to be compiled. */, + "checkJs": true /* Report errors in .js files. */, + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + "noEmit": true /* Do not emit outputs. */, + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */, + + /* Additional Checks */ + "noUnusedLocals": true /* Report errors on unused locals. */, + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + "typeRoots": [ + "./typings", + "./node_modules/@types" + ] /* List of folders to include type definitions from. */, + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "preserveSymlinks": false /* Do not resolve the real path of symlinks. */, + "maxNodeModuleJsDepth": 20, + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["index.js", "browser.js", "./types.js", "./local-types.js", "lib/**/*.js", "bin/**/*.js"], + "exclude": ["node_modules"] +} diff --git a/local-types.js b/local-types.js new file mode 100644 index 0000000..e52085c --- /dev/null +++ b/local-types.js @@ -0,0 +1,5 @@ +/** + * @typedef {import('./types.js').RequestOptions} RequestOptions + * @typedef {import('./types.js').Response} Response + * @typedef {import('./types.js').Headers} Headers + */ diff --git a/package.json b/package.json index 1c963a7..050ef0a 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,18 @@ "index.js": "browser.js" }, "files": [ - "lib" + "browser.js", + "jsconfig.json", + "lib", + "local-types.js", + "types.js" ], "directories": { "example": "examples" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "prepublish": "./bin/localize-types" }, "repository": { "type": "git", diff --git a/types.js b/types.js new file mode 100644 index 0000000..4a75e07 --- /dev/null +++ b/types.js @@ -0,0 +1,34 @@ +'use strict'; + +module.exports._typesOnly = true; + +/** + * @callback Request + * @param {RequestOptions} opts + * @returns {Response} + */ + +/** + * @typedef {Object} RequestOptions + * @prop {any} [opts.body] + * @prop {Object.} [opts.form] + * @prop {Headers} [opts.headers] + * @prop {String} [opts.method] + * @prop {Boolean | any} [opts.json] + * @prop {String} opts.url + */ + +/** + * @typedef {Object} Response + * @prop {any} body + * @prop {Headers} headers + * @prop {Boolean} ok + * @prop {any} [response] - TODO (browser only) + * @prop {any} [request] - TODO + * @prop {String} status + * @prop {Number} statusCode + */ + +/** + * @typedef {Object.>} Headers + */