Using mysql types in typescript - node.js

I have a nodejs typescript project that requires the use of mysqljs (https://www.npmjs.com/package/mysql), I've imported the DefinitelyTyped package (https://www.npmjs.com/package/#types/mysql) and included them in my tsconfig file
tsconfig.json
{
"compilerOptions": {
"noImplicitAny": false,
"module": "commonjs",
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es6"
},
"exclude": [
"node_modules"
],
"typeRoots": [
"node_modules/#types",
"Scripts/typings/node"
],
"types": [
"mysql",
"node"
]
}
I can correctly use the mysql module functions but I cannot access the types (IConnection, IQuery, etc).
I can also see the parameter and return types from intellisense.
Example
import * as mysql from 'mysql'
...
getUser(username: string): User {
mysql.createConnection({ host: "...", user: "...", password: "..." });
}
But I'd like to make a method that returns a type defined in the mysql typings (IQuery for example)
Something like
getUser(username:string): IQuery{
}
Being a beginner in typescript coming from a c# background, I don't see what's going on here.
Thanks for the help.
EDIT:
I have tried prefixing he type without any success as well as importing through this format import {IConnection} from 'mysql'
Thanks again.

It seems as though ReSharper was my issue, I still haven't found how to omit the errors or fix them though.
I reinstalled Visual Studio 2017 and it worked without Resharper, but when I did install it, I started having problems again.
Thanks for the help!
I'll edit this if I can find a solution.

You can access it by prefixing the interface with mysql:
getUser(username:string): mysql.IQuery {
}

Related

Custom Dashboard for AdminJS not working in production

I have a Koa nodejs server which I added AdminJS to and it's working beautifully locally. My goal is to override the Dashboard component. I did so successfully when not running in production. However when I run in production mode (NODE_ENV=production node ./dist/server.js) it fails silently.
const componentLoader = new ComponentLoader();
const Components = {
Dashboard: componentLoader.add("Dashboard", "./admin/dashboard"),
};
const admin = new AdminJS({
componentLoader,
dashboard: {
component: Components.Dashboard,
}
});
My dashboard.tsx file is in src/admin/ and admin is a folder on the same level as src/server.ts. Also, my componentLoader when I inspect it is showing the correct filePath that ends with dist/admin/dashboard
Also, when I check dist/admin/dashboard.js I see my React code. So my tsconfig seems to be correct and the dashboard.tsx has a default export.
What confuses me is when I run nodemon --watch src --exec node -r esbuild-register src/server.ts is works correctly so it seems in general I have things hooked up correctly.
Lastly, here's my tsconfig.json.
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"jsx": "react",
"lib": [
"es6"
],
"target": "es2017",
"module": "commonjs",
"esModuleInterop": true,
"resolveJsonModule": true,
"strict": true,
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"allowJs": false,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"strictNullChecks": true,
"moduleResolution": "node",
"inlineSources": true,
"sourceRoot": "/",
"sourceMap": true,
"isolatedModules": true,
"outDir": "./dist",
"rootDir": "./src",
"composite": true,
"baseUrl": ".",
"paths": {
"src/*": [
"src/*"
]
}
},
"exclude": [
"node_modules",
"./node_modules/*"
],
"files": [
"./src/server.ts"
],
"include": [
"./src/**/*",
"./src/*"
]
}
UPDATE:
I did notice that the components.bundle.js file was missing when navigating to my adminjs dashboard. Since I am using GCP App Engine, I know that that file will not able to be built and saved on the fly in the file system so I have integrated #adminjs/bundler which creates the missing files. However the piece I still haven't put together is how to integrate it into the build pipeline (in particular I'm not sure what the destination of the components.bundle.js should be).
Before I explain my solution here are a few pieces of context:
When using NODE_ENV=production, adminjs does a few things differently, in particular the components.bundle.js file gets served differently. In production, it looks for the file at ./.adminjs/bundle.js
That's when the bundler comes in (which is necessary anyway for certain cloud environments like GCP App Engine). You have to create your own components.bundler.js file which they have a tool for.
First, I created a file which bundles the frontend components. I have not tried doing that with the ComponentLoader so I wouldn't need duplicate code yet, but here's what I know for certain works:
import AdminJS, { OverridableComponent } from "adminjs";
const bundle = (path: string, componentName: string) =>
AdminJS.bundle(`./${path}`, componentName as OverridableComponent);
export const DashboardComponent = bundle("../src/dashboard", "Dashboard");
I believe if I were to create a file which creates the ComponentLoader and adds the components that it would be equivalent (it would export the Components and the componentLoader for use by the AdminJS configuration).
Note ../src/dashboard is simply the location of the dashboard.tsx file I chose. And Dashboard is the name of the component.
Then, I created a script which uses #adminjs/bundler to actually create the bundles. (I named it bundler.ts).
import { bundle } from "#adminjs/bundler";
/**
* yarn admin:bundle invokes this script.
* This file is used to bundle AdminJS files. It is used at compile time
* to generate the frontend component bundles that are used in AdminJS.
*/
void (async () => {
await bundle({
customComponentsInitializationFilePath: "./components.ts",
destinationDir: "./.adminjs",
});
})();
I added a script to my package.json which does the following:
ts-node ./bundler.ts && mv ./.adminjs/components.bundle.js ./.adminjs/bundle.js
Now, when I run this script (which I do when I run before doing node ./dist/server.js), the adminjs router is going to be able to find the previously missing file.
Note that when running your server you'll also want to make sure you set ADMIN_JS_SKIP_BUNDLE='true'.
I hope this helps the next person. I also do hope some documentation and better tooling is on its way. This is kind of messy but solved my issue for now.

Mongoose + Typescript - Unable to require file: mongodb\index.ts

I have a Node + Express application with Typescript, which was running fine, until I decided to include Mongoose in the equation. When I try running it, I get the following error:
TypeError: Unable to require file: mongodb\index.ts
This is usually the result of a faulty configuration or import. Make sure there is a '.js', '.json' or other executable extension with loader attached before 'ts-node' available.
I'm running the application with Nodemon, and have the following configuration in nodemon.json:
{
"execMap": {
"ts": "ts-node"
}
}
Here's my tsconfig.json:
{
"compilerOptions": {
"esModuleInterop": true,
"moduleResolution":"node",
"baseUrl": ".",
"target": "es6",
"paths": {
"#controllers/*": ["./controllers/*"],
"#services/*": ["./services/*"],
"#routes/*": ["./routes/*"],
"#customTypes/*": ["./types/*"],
"#utils/*": ["./utils/*"],
"#graphql/*": ["./graphql/*"]
}
}
}
I'm kind of new to Node with Typescript, so I probably made some mistakes, but cannot find any info regarding what exactly is wrong.
Tried downgrading Mongoose, installing MongoDB manually and changed versions of #types/mongoose, but to no avail.

Nodejs Typescript type only package is not exporting all types properly

The package I'm building (https://github.com/plastikfan/xiberia/tree/develop) is a type only package (I'm not using DefinitelyTyped and this question is not about DT).
The package essentially is just a single file (index.ts) which contains various exported types such as:
export interface IYargsFailHandler {
(msg: string, err: Error, inst: yargs.Argv, command: any): yargs.Argv;
}
The problem is, when I use this in a client app, most of the types are missing and the only type that appears by intellisense is:
export const CoercivePrimitiveStrArray = ['boolean', 'number', 'symbol'];
All the other types are missing.
When I look at the corresponding index.js file, all it contains is:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CoercivePrimitiveStrArray = ['boolean', 'number', 'symbol'];
// -----------------------------------------------------------------------------
//# sourceMappingURL=index.js.map
The generated index.d.ts looks correct and contains all the types, (well there is one very weird definition that I can't account for at the end of the file):
export {};
My typescript config file is:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"module": "commonjs",
"moduleResolution": "Node",
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es5",
"declaration": true,
"declarationDir": "./dist",
"outDir": "./dist",
"diagnostics": true,
"lib": [
"es5",
"es2015",
"es6",
"dom"
],
"types": [
"node", "yargs"
],
},
"include": [
"./index.ts"
],
"exclude": [
"node_modules",
"dist"
]
}
So why are most of the types missing and how do I correct it, thanks.
EDIT: OOPS, I just made a really silly mistake. The types should not be in the resultant .js file. The only valid js is indeed the CoercivePrimitiveStrArrayCoercivePrimitiveStrArray which is being exported.
But that doesnt explain why the types that are being exported are not shown by intellisense on the clienbt side.
So on the client, this is what I have:
in a client file:
import * as xiberia from 'xiberia';
When I type, "xiberia.", I would expect to see all the types being exported, but I don't see any.
I read up on the triple slash directive and it appears they are not appropriate for this situation.
So what other config setting do i need for te intellisense to work as expected?
I fixed this problem by simplifying the package as much as possible. Previously, I was building artefacts into the 'dist' folder, a pattern which is widely used. I have removed this (this is a simple single file package, so using a dist folder is overkill) and simply build out the resultant index.d.ts, index.js and the .map files into the root directory. This also required explicity specifiying these files in the 'files' property in package.json (this ensures that these files are included in the resultant package tarball built when performing npm pack via the publish mechanism).
I don't understand why now intellisense is working as a result of these actions; perhaps somebody who knows better can comment.

TypeScript compilation error, importing non default interface with curly braces

When compiling my TypeScript project, the compiler is throwing the following error:
node_modules/#types/domutils/index.d.ts:6:10 - error TS2614: Module '"../../domhandler/lib"' has no exported member 'DomElement'. Did you mean to use 'import DomElement from "../../domhandler/lib"' instead?
The offending line is:
import { DomElement } from "domhandler";
The problem is, in the typing file it is trying to import from, the DomElement interface is a non default exported interface as follows:
export interface DomElement {
attribs?: {[s: string]: string};
children?: DomElement[];
data?: any;
name?: string;
next?: DomElement;
parent?: DomElement;
prev?: DomElement;
type?: string;
}
If I remove the curly braces it does in fact work, but that seems problematic to me:
I was under the impression that only default exports can be imported without curly braces. Why is this import required without curly braces?
This issue is occurring in type definitions in the node-modules folder as provided by DefinitelyTyped. I do not want to change a dependency file. There are no related open issues in Github, so I assume it does work. In fact it works for a colleague with an older version of Node (v8) but that doesn't seem like it should make a difference.
Versions:
Node.js - 12.14.0
List item
TypeScript 3.7.2 (also tested not working on 3.7.4)
Type definitions for domhandler 2.4 (https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/domhandler)
Type definitions for domutils 1.7 (https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/domutils)
UPDATE
Here is my tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*"
]
}
},
"include": [
"src/**/*"
]
}
Based on info from aluanhaddad at GitHub I managed to get it compiling (and working), though I don't like the solution (because it's actually turning any checking for that module off).
I have removed typings to sanitize-html (and related domhandler etc.). TSC cries that it doesn't know "sanitize-html" module, so I've added a dummy module declaration inside my src folder.
src/sanitize-html.d.ts
declare module 'sanitize-html';
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"lib": [
"es6",
"dom"
],
"include": [
"src/**/*",
"index.ts"
],
"exclude": [
"**/*.spec.ts"
]
}
build command:
tsc

Error importing node modules in TypeScript

I had a problem this morning that was driving me crazy. I'll explain the issue and then I'll provide my answer below (so that others who come across this can get to a solution sooner).
It is very easy to duplicate the issue by just issuing these commands:
tsd query react --action install
mkdir src
echo "import React = require('react');" > src/foo.ts
I also included the following tsconfig.json file in src:
{
"version": "1.6.2",
"compilerOptions": {
"outDir": "./tsdir",
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"isolatedModules": false,
"jsx": "react",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": true,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"preserveConstEnums": true,
"suppressImplicitAnyIndexErrors": true
},
"files": [
"foo.ts"
]
}
If I try to compile this by simply running the tsc (version 1.6.2) command inside src, I get:
foo.ts(1,24): error TS2307: Cannot find module 'react'.
What I find baffling here is that I've installed the react bindings with tsd but when I run tsc, I get this error. It looks like I've done everything right, so why the error?
So what I eventually figured out was that I need to explicitly include the typings file in my list of "files", i.e.,
{
"version": "1.6.2",
"compilerOptions": {
...
},
"files": [
"foo.ts",
"../typings/react/react.d.ts"
]
}
In other words, I had to include the typings files explicitly in the "files". I don't really know why. I thought tsc was smart enough to look for them itself.
If there is a better solution that doesn't involve having to list all the .d.ts files explicitly in "files", I'm all ears. But I just wanted to point out that this is at least a workaround.

Resources