Prisma seed - cannot read properties of undefined (reading 'findFirst') - node.js

I have a weird issue using prisma seed that I've never faced before and struggling to understand what causes it. The app is hosted in a nextjs full-stack project.
I have the following prisma init script:
const prisma = new PrismaClient();
export default prisma;
When using prisma in my app (next dev), everything works and the queries are being executed.
When I try to run the seed script however, it fails with TypeError: Cannot read properties of undefined (reading 'findFirst')
Here is the seed script:
async function main() {
const existingUser = await db.user.findFirst();
// ...not relevant
}
main()
.then(async () => await db.$disconnect())
.catch(async e => {
console.error(e);
await db.$disconnect();
process.exit(1);
});
package.json prisma section:
"prisma": {
"seed": "ts-node src/server/db/seed.ts",
"schema": "src/server/db/schema.prisma"
},
tsconfig.json ts-node section:
"ts-node": {
"require": ["tsconfig-paths/register"],
"transpileOnly": true,
"compilerOptions": {
"module": "commonjs"
}
},
Printing the prisma client on the seed script returns {}, instead of the actual instance that I can see while printing in dev mode.
Any ideas are welcome, thanks!

A few debugging hours later, I finally found the issue. This code fragment is located in the prisma runtime config:
const dmmfModelKeys = Object.keys(client._baseDmmf.modelMap);
const jsModelKeys = dmmfModelKeys.map(dmmfToJSModelName);
const allKeys = [...new Set(dmmfModelKeys.concat(jsModelKeys))];
I have seen that while the first 2 variables were outputting a result, creating a new Set was actually returning an empty array, instead of the real value.
By default, NextJS uses es5 as a target in tsconfig. ES5 however does not yet have the Set construct, which was causing the problem.
Upgrading to es2015 solved the problem.
I was just expecting some kind of an error, instead of silent fail..

Related

Evaluate a Cypress configuration file

In my build scripts I need to evaluate a Cypress configuration file. I'm using the following script:
let appdata = process.env.LOCALAPPDATA;
let version = `11.0.1`;
let src = `${appdata}/Cypress/Cache/${version}/Cypress/resources/app/node_modules/#packages/data-context/src`;
const DataContext = require(`${src}/DataContext.js`).DataContext;
const ProjectConfigManager = require(`${src}/data/ProjectConfigManager.js`).ProjectConfigManager;
(async() => {
const ctx = new DataContext({
schema: null,
schemaCloud: null,
modeOptions: "run",
appApi: {},
localSettingsApi: {},
authApi: {
} ,
configApi: {
},
projectApi: {
} ,
electronApi: {
} ,
browserApi: {
},
})
let configManager = new ProjectConfigManager({
ctx,
configFile: 'C:\\work\\sample\\sample.config.ts',
projectRoot: 'C:\\work\\sample',
handlers: [],
hasCypressEnvFile: false,
eventRegistrar: null/*new EventRegistrar()*/,
onError: (error) => {},
onInitialConfigLoaded: () => {},
onFinalConfigLoaded: () => Promise.resolve(),
refreshLifecycle: () => Promise.resolve(),
})
configManager.configFilePath = "sample.config.ts"
configManager.setTestingType('e2e')
let cfg = await configManager.getConfigFileContents()
console.log(JSON.stringify(cfg));
})();
It works well for Cypress 10 version.
However, Cypress 11 has introduced some changes that break this script. Though I adjusted the paths, I'm still unable to make it work again.
It currently fails with this error:
Error: Cannot find module 'C:\Users\mbolotov\AppData\Local\Cypress\Cache\11.0.1\Cypress\resources\app\node_modules\graphql\index'. Please verify that the package.json has a valid "main" entry
How can I fix this problem (without making changes to the Cypress installation)?
OR
Is there any other way to evaluate a Cypress configuration file (say from the command line) and obtain its values?
The exact usage is unclear to me, but making some assumptions - a nodejs script in the /scripts folder of the project can compile and resolve the config using the Cypress module API.
It would need a test to run, a "null-test" can be generated from inside the script.
Note, the null-test must conform to the spec pattern of the project (below it's the std .cy.js)
const cypress = require('cypress')
const fs = require('fs')
fs.writeFileSync('../cypress/e2e/null-test.cy.js', 'it("", ()=>{})')
cypress.run({
project: '..',
spec: '../cypress/e2e/null-test.cy.js',
quiet: true
}).then(results => {
if (results.status === 'failed') {
console.log(results)
} else {
console.log(results.config.resolved) // output resolved config
}
})
I haven't attempted to duplicate everything you have in your code, as it's using Cypress internals and not publicly documented.
This may be because of Changelog 11.0.0
We have also massively improved our startup performance by shipping a snapshot of our binary instead of the source files.
Looking inside the cache folder for v10.11.0 (${process.env.CYPRESS_CACHE_FOLDER}/10.11.0/Cypress/resources/app), the /node_modules is fully populated and /node_modules/graphql/index.js exists.
But in v11.0.1 /node_modules/graphql is not fully populated.

uuid is not a function while using jest

I have the following setup:
// uuid-wrapper.ts
import { v4 as uuidV4 } from 'uuid';
const uuid: () => string = uuidV4;
export { uuid };
// uuid-wrapper.spec.ts
import { uuid } from './uuid-wrapper';
describe('uuid-wrapper', () => {
console.log(uuid());
});
This works fine runtime, but it breaks in test. I'm trying to migrate to Jest 29 and I'm getting the following error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { default as v1 } from './v1.js';
^^^^^^
SyntaxError: Unexpected token 'export'
From uuid's repo I found a workaround which, after applied and my jest.config.js looks like this:
module.exports = {
moduleNameMapper: {
uuid: require.resolve("uuid"),
},
};
This gives me a different error but I still have no idea what it means:
> jest uuid-wrapper --no-coverage
FAIL src/uuid-wrapper/uuid-wrapper.spec.ts
● Test suite failed to run
TypeError: (0 , uuid_wrapper_1.uuid) is not a function
In fact, any function I export from this file (uuid-wrapper.ts) is not resolved. I have other tests that follow a similar pattern of reexporting packages but only this one breaks. I'm using uuid 9.0.0 and jest 29.1.2.
Edit: After a bit more testing, it turns out that anything I import into the test is "not a function".
uuid ships as an ESModule and Jest should not need to transform it. Add it to your transformIgnorePatterns in your Jest config:
module.exports = {
transformIgnorePatterns: ['node_modules/(?!(uuid))'],
}
Edit: After a bit more testing, it turns out that anything I import into the test is "not a function".
I had very similar symptoms once: builds and works as excepted, yet ...is not function in jest. The culprit was a circular dependency I accidentally introduced with my story. Maybe check for that.
As I suspected, the issue was in the naming. Renaming the files and directory to just wrapper solved the issue.

throw new TypeError(`${relative(cwd, fileName)}: Emit skipped`)

Hello I have the following typescript code:
import { getConnection } from "typeorm";
import { GraphQLClient } from "graphql-request";
import got from "got";
import database from "./utils/database";
...
When I execute:
cross-env NODE_ENV=development ts-node src/scripts/createApp.ts http://localhost:3010/graphql
I get the following error:
throw new TypeError(`${relative(cwd, fileName)}: Emit skipped`)
^
TypeError: src/scripts/utils/database.js: Emit skipped
database.js
import { createConnection, getConnectionOptions, getConnection } from "typeorm";
export default {
async connect(): Promise<void> {
const connectionOptions = await getConnectionOptions(process.env.NODE_ENV);
await createConnection({
...connectionOptions,
name: "default",
});
},
disconnect(): Promise<void> {
return getConnection().close();
},
};
Where is the error?, How can I solve it?
Thanks
The solution was set this variable in tsconfig
"allowJs": false,
I had a similar problem but in my case, I needed allowJs to be set to true in tsconfig.json because I do have some auto-generated js-code in my codebase (pre-compiled validators for JSON Schema files) that I need to be included in the output.
The problem was indeed caused by JS files generated by incorrectly compiling TS files to JS files in the same directory. When I cleared my workspace the ts-node began to work properly with both TS files and those few auto-generated JS files.
On my side it was due to version after update issue solved
yarn add ts-node --dev
# npm i --save-dev ts-node

Create a TypeScript Library and use it from Node.js with ES6 and TypeScript

I want to create a TypeScript library as private npm package which can be used in Node.js (including 6.x) using ES6 with #types support and TypeScript.
The goal of the library is to extend the Request type from express and provide additional properties.
I created a new Node.js project and add this tsconfig.json:
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"sourceMap": true,
"declaration": true,
"outDir": "./dist",
"strict": true,
"types": ["mocha"]
}
}
These are the relevant parts of the package.json:
{
"name": "#myscope/my-lib",
"main": "dist",
"scripts": {
"build": "rm -rf ./dist && ./node_modules/.bin/tsc",
"test": "./node_modules/.bin/mocha test"
},
"private": true,
"dependencies": {
"joi": "11.4.0"
},
"devDependencies": {
"mocha": "^5.2.0",
"express": "^4.16.4",
"#types/express": "^4.16.1",
"#types/joi": "^14.3.0",
"#types/mocha": "^5.2.5",
"typescript": "^3.2.4"
}
}
My folder structure is this:
- dist
- src
- http
- security
- test
I created a new TypeScript file AuthenticatedRequest.ts in src/http:
import {Request} from "express";
import {UserReference} from "../security/UserReference";
export interface AuthenticatedRequest extends Request {
user: UserReference
}
src/security contains a UserReference.ts:
import {Claim} from "./Claim";
export interface UserReference {
claims: Claim[];
}
and a Claim.ts:
import {IClaim} from "./IClaim";
export class Claim implements IClaim {
type: string;
value: string;
constructor(type: string, value: string) {
this.type = type;
this.value = value;
}
}
IClaim.ts looks like this:
export interface IClaim {
type: string,
value: string
}
In test, I created AuthenticatedRequestTests.js (plain ES6, no TypeScript here to validation code completion and usage from ES6):
'use strict';
const assert = require('assert');
const Claim = require("../dist/security/Claim").Claim;
describe('req', () => {
it('should ', done => {
/** #type {AuthenticatedRequest} */
const req = {};
req.user = { claims: [new Claim('tenantId', '123')] };
assert.equal(req.user.claims[ 0 ].type, 'tenantId');
assert.equal(req.user.claims[ 0 ].value, '123');
return done();
});
});
Now I have sevaral questions:
Is this the expected TypeScript way to solve this?
Is it possible to just use require("../dist/security/Claim"); instead of require("../dist/security/Claim").Claim;?
Instead of using this jsdoc statement /** #type {AuthenticatedRequest} */ I would like to use /** #type {myLib.http.AuthenticatedRequest} */
I also created a local test project for integration and installed my library via npm link.
But instead of using
const Claim = require("#scope/my-lib/security/Claim").Claim; I have to use
const Claim = require("#scope/my-lib/dist/security/Claim").Claim;
How can I get rid of the dist folder name here?
Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:
package.json
There should be a field called types (or typings) telling your library consumers where are the type definitions for your project. If they are generated by TypeScript and saved to dist/index.d.ts, then that's the path that should be used.
"types": "./dist/index.d.ts"
There should be a field called files containing an array of files/directories that will be delivered to your end users.
Running tests
Is this the expected TypeScript way to solve this?
If you're using TypeScript to develop your library, there is no reason not to use TypeScript for your tests. There are TypeScript-compliant test runners out there (ts-jest used to be popular, and now Jest is capable of understanding TypeScript out of the box).
Is it possible to just use require("../dist/security/Claim"); instead of require("../dist/security/Claim").Claim;?
With TypeScript, a few kinds of syntax are possible. You could export Claim using a default export and do:
import Claim from "../dist/security/Claim";
or:
const Claim = require("../dist/security/Claim");
Instead of using this jsdoc statement /** #type {AuthenticatedRequest} */ I would like to use /** #type {myLib.http.AuthenticatedRequest} */.
You will need an import type. They look like that:
/**
* #type {import('path/to/AuthenticatedRequest')}
*/
const req {}
The path can be relative or absolute. If you'd like to treat the local codebase as if it were installed from npm, you can create another package.json file in your test directory and use a relative path to resolve your library module.
"dependencies": {
"my-library": "../path/to/the/root"
}
Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:
That's also solved by import types. Unless a type is not in the global scope, you need to import it before you can use it. Use import('path/to/AuthenticatedRequest') instead.
There are a few things going on. If you could create a public repository to demonstrate your problems, I'm sure it would be easier for us to help you address them.
I have an alternate answer for one part of your question. You asked
instead of using
const Claim = require("#scope/my-lib/security/Claim").Claim; I have to use
const Claim = require("#scope/my-lib/dist/security/Claim").Claim;
How can I get rid of the dist folder name here?
As Karol points out, you can use files in package.json so that when your library is published, you send the dist directory as the package root (plus package.json, README, etc). This is a great, established pattern, but has some downsides: installing the package from github: instead of NPM won't work, nor will npm link for local development.
As of very recent Node versions, you can use the exports property instead:
{
"exports": {
"./": "./dist/"
}
}
Now, require("my_lib/security/Claim") resolves to node_modules/my_lib/dist/security/Claim. It would be great if Typescript handled this automatically, but as far as I can tell you also have to specify a baseUrl and paths in your tsconfig.json, at least for now.

Can't use Worker-Loader with Vuejs and Webpack

I am trying to get web workers up and running with Vue cli3 and I'm having trouble getting it to work.
I want to use the following package, worker-loader (and not vue-worker), as it looks well maintained and with more contributions.
Following their tutorial I attempted to modify webpack using the vue cli as follows:
module.exports = {
chainWebpack: config => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end()
}
}
which I hope should match their
{
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
}
]
}
}
which can be read here (https://github.com/webpack-contrib/worker-loader). I tried to follow the documentation for vue cli3 as best I could (found here: https://cli.vuejs.org/guide/webpack.html#simple-configuration).
My component is pretty simple:
import Worker from 'worker-loader!./../../sharedComponents/equations/recurringTimeComposer.js';
<...>
watch:{
recurringPaymentReturnObj: function(newVal, oldVal){
const myWorker = new Worker;
myWorker.postMessage({ hellothere: 'sailor' });
myWorker.onmessage = (e) => {
console.log('value of e from message return', e.data);
}
}
<...>
and in my ./../../sharedComponents/equations/recurringTimeComposer.js file I have:
onmessage = function(e) {
console.log('Message received from main script: ', e.data);
// var workerResult = 'Result: ' + e.data;
// console.log('Posting message back to main script');
postMessage('hello back handsome');
close();
}
I keep getting the error message:
ReferenceError: window is not defined a162426ab2892af040c5.worker.js:2:15
After some googling I came across this post: https://github.com/webpack/webpack/issues/6642, which suggests that the best way to fix this is to add the following to webpack:
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
publicPath: 'http://localhost:3000',
globalObject: 'this'
},
After modifying my vue.config.js file I have:
module.exports = {
chainWebpack: config => {
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end()
config
.output
.path(path.join(__dirname, 'dist'))
.filename('bundle.js')
.publicPath('http://localhost:8080')
.globalObject('this')
}
}
...but still I am getting the window is not defined error.
Does anyone know what is going wrong? It seems to be a weird error in webpack.
Thanks!
EDIT: oh yeah, here is the MDN page for webworker as well: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers.
Being new to Javascript I kept coming back to this issue when trying to use web workers with VueJS. I never managed to make it work with vue-worker or worker-loader.
It is now 2020 and Google has released worker-plugin.
To use it create a module my-worker with two files index.js and worker.js.
index.js creates the module:
const worker = new Worker('./worker.js', { type: 'module' });
const send = message => worker.postMessage({
message
})
export default {
worker,
send
}
worker.js contains the logic:
import _ from 'lodash'
addEventListener("message", async event => {
let arrayToReverse = event.data.message.array
let reversedArray = _.reverse(arrayToReverse)
// Send the reversed array
postMessage(reversedArray)
});
You will also need to update your vue.config.js to use the WorkerPlugin:
const WorkerPlugin = require('worker-plugin')
module.exports = {
configureWebpack: {
output: {
globalObject: "this"
},
plugins: [
new WorkerPlugin()
]
}
};
Now you can use you worker in your components:
Import it with import worker from '#/my-worker'.
Setup a listener in the mounted() lifecycle hook with worker.worker.onmessage = event => { // do something when receiving postMessage }
Start the worker with worker.send(payload).
I set up a starter code on github. I still haven't managed to make HMR work though...
This works for me (note the first line):
config.module.rule('js').exclude.add(/\.worker\.js$/)
config.module
.rule('worker-loader')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
The first line excludes worker.js files, so two loaders wouldn't fight over the same js file
is this what you need ? Vue issue with worker-loader
Updating from the classic vue & webpack config, I found out that to make this one work, I needed to deactivate parallelization.
// vue.config.js
module.exports = {
parallel: false,
chainWebpack: (config) => {
config.module
.rule('worker')
.test(/\.worker\.js$/)
.use('worker-loader')
.loader('worker-loader')
.end();
}
};
I tried add web worker to a vue-cli4 project, and here is what I found:
using worker-loader and make configs in chainWebpack:
HMR works fine, but sourcemap broke, it show babel transformed code.
using worker-plugin as #braincoke mentioned:
HMR broke, but sourcemap works fined. and eslint broke while suggested disable all worker js file eslint instead.
Finally, My solution is tossing vue-cli away, and embrace vite.It support worker natively, and all just go fine now. (I think upgrade webpack to v5 can solve this, but i never tried.)

Resources