From 2670c2f8b563bb2ddcbf292172af0c57ed02c16f Mon Sep 17 00:00:00 2001 From: Ferris <3579192+code-ape@users.noreply.github.com> Date: Sun, 1 May 2022 15:02:44 -0400 Subject: [PATCH] Add development support Typescript source files (#5144) --- .github/workflows/coverage.yml | 2 + .github/workflows/integration-tests.yml | 2 + .github/workflows/unit-tests.yml | 2 + CONTRIBUTING.md | 10 +++ lib/.gitignore | 10 +++ lib/dialects/{index.js => index.ts} | 18 ++--- package.json | 11 ++- scripts/update_gitignore_for_tsc_output.js | 85 ++++++++++++++++++++++ tsconfig.json | 22 ++++++ 9 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 lib/.gitignore rename lib/dialects/{index.js => index.ts} (80%) create mode 100755 scripts/update_gitignore_for_tsc_output.js create mode 100644 tsconfig.json diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 317592d2f4..a40f981b34 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -36,6 +36,8 @@ jobs: - name: Install pg-native run: npm i pg-native + - run: npm run build + - name: Run Tests run: npm run test:coverage || true env: diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index bc8f18bc42..f1bab091c2 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -62,6 +62,8 @@ jobs: run: ./scripts/oracledb-install-driver-libs.sh run if: matrix.database-type == 'oracledb' + - run: npm run build + - name: Run Tests run: npm run test:db if: matrix.database-type != 'oracledb' diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 0eb5758871..47053054af 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -34,6 +34,8 @@ jobs: - name: Run npm install run: npm install + - run: npm run build + - name: Run Tests run: npm run test:unit env: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 342e5b593d..6b7873fac6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -169,6 +169,16 @@ Once this is done, check it works by attempting to login: psql -h localhost -U postgres -d knex_test ``` +## Typescript source files + +> TL;DR: Starting with release 2.0.0 Knex is adding support for Typescript source files. Thus to develop in this repo you will need to run `npm run build` to generate the resulting `.js` files, even when developing in Javascript. It is encouraged that new functionality and sources be written in Typescript but this is not required. + +Starting with release 2.0.0, Knex is support source additions in Typescript! This allows for better safety in the code added. However, pre-2.0.0 Knex was always written in pure Javascript and thus a "hybrid" approach is being used for 2.0.0 to allow for the new `.ts` files to exist along `.js` files that make up the majority of this repository. + +To develop in this repository use the `npm run build` command. If you wish to have the `tsc` compiled watch and recompile on changes then run `npm run build:ts -- --watch`. Note that for easy integration with Javascript the outputted files are done in a "side-by-side" manner meaning that `lib/foo/bar.ts` will result in `lib/foo/bar.js`. + +The script file `./scripts/update_gitignore_for_tsc_output.js` file is called as part of the `npm run build` command which will update the `lib/.gitignore` file which is used to ensure generated `.js` and related files from `tsc` compilation are not checked into the git repo. + ## Want to be Collaborator? There is always room for more collaborators. Be active on resolving github issues / sending pull requests / reviewing code and we will ask you to join. diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000000..6907100de1 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,10 @@ +# DO NOT EDIT, GENERATED BY: scripts/update_gitignore_for_tsc_output.js + +# Do not include tsc generated type definitions +**/*.d.ts + +# Do not include tsc source maps +**/*.js.map + +# Do not include .js files from .ts files +dialects/index.js diff --git a/lib/dialects/index.js b/lib/dialects/index.ts similarity index 80% rename from lib/dialects/index.js rename to lib/dialects/index.ts index 4f2b3ae8c8..5132a8507a 100644 --- a/lib/dialects/index.js +++ b/lib/dialects/index.ts @@ -1,6 +1,6 @@ -const { resolveClientNameWithAliases } = require('../util/helpers'); +const { resolveClientNameWithAliases } = require('../util/helpers') -const dbNameToDialectLoader = Object.freeze({ +const dbNameToDialectLoader: Record any> = Object.freeze({ 'better-sqlite3': () => require('./better-sqlite3'), cockroachdb: () => require('./cockroachdb'), mssql: () => require('./mssql'), @@ -12,7 +12,7 @@ const dbNameToDialectLoader = Object.freeze({ postgres: () => require('./postgres'), redshift: () => require('./redshift'), sqlite3: () => require('./sqlite3'), -}); +}) /** * Gets the Dialect object with the given client name or throw an @@ -21,15 +21,11 @@ const dbNameToDialectLoader = Object.freeze({ * NOTE: This is a replacement for prior practice of doing dynamic * string construction for imports of Dialect objects. */ -function getDialectByNameOrAlias(clientName) { - const resolvedClientName = resolveClientNameWithAliases(clientName); - const dialectLoader = dbNameToDialectLoader[resolvedClientName]; +export function getDialectByNameOrAlias(clientName: string) { + const resolvedClientName = resolveClientNameWithAliases(clientName) + const dialectLoader = dbNameToDialectLoader[resolvedClientName] if (!dialectLoader) { - throw new Error(`Invalid clientName given: ${clientName}`); + throw new Error(`Invalid clientName given: ${clientName}`) } return dialectLoader(); } - -module.exports = { - getDialectByNameOrAlias, -}; diff --git a/package.json b/package.json index 5da13c9ab4..84a6322335 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ "node": ">=12" }, "scripts": { + "build": "npm run build:gitignore && npm run build:ts", + "build:ts": "tsc", + "build:gitignore": "./scripts/update_gitignore_for_tsc_output.js run", "format": "prettier --write \"{lib,bin,scripts,test}/**/*.js\"", "debug:test": "mocha --inspect-brk --exit -t 0 test/all-tests-suite.js", "debug:tape": "node --inspect-brk test/tape/index.js", @@ -52,7 +55,8 @@ "stress:init": "docker-compose -f scripts/stress-test/docker-compose.yml up --no-start && docker-compose -f scripts/stress-test/docker-compose.yml start", "stress:test": "node scripts/stress-test/knex-stress-test.js | grep -A 5 -B 60 -- '- STATS '", "stress:destroy": "docker-compose -f scripts/stress-test/docker-compose.yml stop", - "prepare": "husky install" + "prepare": "husky install", + "prepublishOnly": "npm run build" }, "dependencies": { "colorette": "2.0.16", @@ -100,6 +104,7 @@ ] }, "devDependencies": { + "@tsconfig/recommended": "^1.0.1", "@types/node": "^17.0.25", "better-sqlite3": "^7.5.1", "chai": "^4.3.6", @@ -215,6 +220,10 @@ "files": [ "bin/*", "lib/*", + "!lib/**/*.ts", + "!lib/**/*.d.ts", + "!lib/**/*.js.map", + "!lib/.gitignore", "scripts/*", "types/index.d.ts", "types/result.d.ts", diff --git a/scripts/update_gitignore_for_tsc_output.js b/scripts/update_gitignore_for_tsc_output.js new file mode 100755 index 0000000000..4200263712 --- /dev/null +++ b/scripts/update_gitignore_for_tsc_output.js @@ -0,0 +1,85 @@ +#!/usr/bin/env node + +const path = require('path') +const fs = require('fs') + +// Directory constants +const scriptDirectory = __dirname +const repoDirectory = path.join(scriptDirectory, '..') +const libDirectory = path.join(repoDirectory, 'lib') + +const helpText = ` +Helper script to update lib/.gitignore for all .js files from .ts files. + + update_gitignore_for_tsc_output.js COMMAND + + COMMAND: + run: Update lib/.gitignore file. + help: Print this menu. + + NOTES FOR USAGE: + 1. This script is tested to work on Ubuntu 18.04 LTS. +` + +const gitignoreHeader = `# DO NOT EDIT, GENERATED BY: scripts/update_gitignore_for_tsc_output.js + +# Do not include tsc generated type definitions +**/*.d.ts + +# Do not include tsc source maps +**/*.js.map + +# Do not include .js files from .ts files +` + +function main(cliCommand) { + if (cliCommand === 'run') { + console.log('Generating lib/.gitignore ...') + + // Find all .ts files in lib/ + const directoriesToProcess = [libDirectory] + const tsFiles = [] + while (directoriesToProcess.length > 0) { + const directory = directoriesToProcess.pop() + if (!fs.existsSync(directory)) { + throw new Error("Directory doesn't exist:", directory) + } + + const files = fs.readdirSync(directory) + files.forEach((file) => { + const filename = path.join(directory, file) + const stat = fs.lstatSync(filename) + if (stat.isDirectory()) { + directoriesToProcess.push(filename) + } else if (filename.endsWith('.ts') && !filename.endsWith('.d.ts')) { + tsFiles.push(filename) + console.log('Found .ts file:', filename) + } + }) + } + + // Get paths of .js files to ignore + const jsFilesToIgnore = tsFiles.map((filepath) => { + // Cuts off `${libDirectory}/` + const relativeTsPath = filepath.slice(libDirectory.length + 1) + // Swaps .ts for .js file ending + const relativeJsPath = relativeTsPath.slice(0, relativeTsPath.length - 3) + '.js' + return relativeJsPath + }) + const jsFilesToIgnoreString = jsFilesToIgnore.join('\n') + const libGitignorePath = path.join(libDirectory, '.gitignore') + fs.writeFileSync(libGitignorePath, gitignoreHeader + jsFilesToIgnoreString + '\n') + console.log('DONE') + } else if (['help', '--help', '-h', undefined].includes(cliCommand)) { + console.log(helpText) + } else { + console.log(`Unsupported command: ${cliCommand}`) + console.log("Try running with 'help' to see supported commands.") + process.exit(1) + } +} + +// Main script logic +const cliCommand = process.argv[2] +// Start the bash app's main function +main(cliCommand) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..9980025eb3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "@tsconfig/node12/tsconfig.json", + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "declaration": false, + "rootDirs": [ + "lib" + ], + "importHelpers": false, + "sourceMap": true, + "baseUrl": ".", + }, + "include": [ + "lib/**/*.ts" + ], + "exclude": [ + "node_modules", + ] +} \ No newline at end of file