VSCode Typescript intellisense wrong - javascript

I have been trying to create ServiceWorker for my website using SvelteKit, but am running into an issue here. I created a file /src/service-worker.ts and in there, I put the following code
import { build, files, prerendered, version } from '$service-worker';
const applicationCache = `applicationCache-v${version}`;
const staticCache = `staticCache-v${version}`;
const returnSSRpage = (path) =>
caches.open("ssrCache").then((cache) => cache.match(path));
// Caches the svelte app (not the data)
self.addEventListener("install", (event) => {
event.waitUntil(
Promise.all([
caches
.open("ssrCache")
.then((cache) => cache.addAll(["/"])),
caches
.open(applicationCache)
.then((cache) => cache.addAll(build)),
caches
.open(staticCache)
.then((cache) => cache.addAll(files))
])
.then(self.skipWaiting()),
)
})
... reduced code
When running npm run build this code compiles perfectly fine and the code runs in the browser. However, my VSCode intellisense gets some stuff wrong. Most notably, it says that the waitUntil property of event does not exist.
Property 'waitUntil' does not exist on type 'Event'.ts(2339) among other things, such as Property 'skipWaiting' does not exist on type 'Window & typeof globalThis'.ts(2339) and Cannot find name 'clients'.ts(2304).
Now, I am quite new to Javascript and Typescript, but from my experience, the Intellisense should not output an error that doesn't also appear during compilation. Why does this happen?
I am unsure of what information to provide. My TS version is 4.7.4 which is also the version VSCode is using for Intellisense. I have installed the ESLint extension for JS and TS.
What could be the problem here?
Thanks!

You can add "WebWorker" to the compilerOptions.lib in tsconfig.json and declare the type of self in the service worker file:
declare var self: ServiceWorkerGlobalScope;
This will lead to the event types automatically being inferred without further annotations via the event name.
You may need to restart the TS server (there is a command for that: TypeScript: Restart TS Server).
Still, odd that it would build as is...

Related

Simple Web Worker not working in SvelteKit on Firefox 106.0.5

Inside my main file, I have
const loadWorker = async () => {
const SyncWorker = await import("$lib/canvas.worker?worker");
syncWorker = new SyncWorker.default();
syncWorker?.postMessage({});
};
Then in my unmount I have
onMount(() => {
console.log("Canvas: mounted");
loadWorker();
});
Then in my canvas.worker.ts file, I have a simple
onmessage = () => {
console.log("Hello from the worker!");
};
export {};
This message prints successfully in Chrome, but in firefox all I get is
SyntaxError: import declarations may only appear at top level of a module
Is this because the worker is stored on my local system, and maybe there's a special flag to allow loading of system files as workers (as that seems it may be a security concern)? Firefox docs say that my browser should support workers.
Well, I should've read the documentation better.
service workers only work in the production build, not in development.
To test it locally, use vite preview
https://kit.svelte.dev/docs/service-workers
Or in my case, "npm run build && npm run preview" worked.

How to use the TypeScript Compiler API to type-check modules imported using `require()`?

I am using TypeChecker from the TypeScript Compiler API in order to extract (inferred) type information for every node in the AST of my program. In particular, I try to find out the return values from imported module functions such as:
var vec3 = require('gl-matrix/vec3')
var myVec = vec3.fromValues(1, 2, 3) // $ExpectedType vec3
This works well for modules that were imported using the import { … } from '…' statement, but unfortunately, modules that were imported using require() like above are not recognized correctly, I only receive the type any for them. However, I have set both compiler options allowJs and checkJs.
Why are the types form require()d modules not inferred correctly? VS Code (which AFAIK relies on the same API?) is able to infer the types from require() statements as well, so I'd guess that in general, tsc is able of handling them. Are there any other compiler options that I need to set differently? Or is this indeed not supported and I need to use some other package for this?
Here is a minimum script to reproduce, I have also put it on repl.it together with two example files: https://replit.com/#LinqLover/typecheck-js
var ts = require("typescript")
// Run `node index.js sample-import.js`` to see the working TypeScript analysis
const files = process.argv[1] != "/run_dir/interp.js" ? process.argv.slice(2) : ["sample-require.js"]
console.log(`Analyzing ${files}:`)
const program = ts.createProgram(files, {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS,
allowJs: true,
checkJs: true
})
const checker = program.getTypeChecker()
for (const sourceFile of program.getSourceFiles()) {
if (!sourceFile.isDeclarationFile) {
ts.forEachChild(sourceFile, visit)
}
}
function visit(node) {
try {
const type = checker.getTypeAtLocation(node)
console.log(checker.typeToString(type))
} catch (e) {
// EAFP
}
ts.forEachChild(node, visit)
}
Thank you so much in advance!
For follow-up, this turned out to be an issue with the type definitions for gl-matrix. I should better have tried out multiple packages before suspecting that the TypeScript engine itself could be broken ...
gl-matrix issue: https://github.com/toji/gl-matrix/issues/429

How to get Jest to see the functions I am writing for MongoDB Stitch?

I am trying out Stitch, a serverless/hosted JavaScript environment from MongoDB. My main purpose is to help me learn modern JavaScript, but I am trying to write a useful app as well.
I have written the following function, and saved it in my Stitch app. I believe this follows the documented way to write functions in Stitch, and I have tested it from the Stitch administration console:
exports = function(query){
const http = context.services.get("HTTP");
const urlBase = context.values.get("stackOverflowApiUrl");
const options = [
'order=desc',
'sort=activity',
'site=stackoverflow',
'q=' + encodeURIComponent(query),
'user=472495',
'filter=!--uPQ.wqQ0zW'
];
return http
.get({ url: urlBase + '?' + options.join('&') })
.then(response => {
// The response body is encoded as raw BSON.Binary. Parse it to JSON.
const ejson_body = EJSON.parse(response.body.text());
return ejson_body.total;
});
};
This code is pretty simple - it obtains an http object for making external API fetches, and obtains a configuration value for a URL urlBase to contact (resolving to https://api.stackexchange.com/2.2/search/excerpts) and then makes a call to the Stack Overflow Data API. This runs a search query against my user and returns the number of results.
So far so good. Now, I want to call this function locally, in Jest. To do this, I have installed Node and Jest in a local Docker container, and have written the following test function:
const callApi = require('./source');
test('Simple fetch with no user', () => {
expect(callApi('hello')).toBe(123);
});
This fails, with the following error:
~ # jest
FAIL functions/callApi/source.test.js
✕ Simple fetch with no user (3ms)
● Simple fetch with no user
TypeError: callApi is not a function
2 |
3 | test('Simple fetch with no user', () => {
> 4 | expect(callApi('hello')).toBe(123);
| ^
5 | });
6 |
at Object.<anonymous>.test (functions/callApi/source.test.js:4:12)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.418s
Ran all test suites.
(In fact I was expecting it to fail, since it contains a global object context that Jest does not have access to. I will work out how to mock that later, but for now Jest cannot even see the function at all).
I suspect I can see the reason - in the Jest introduction docs, one has to do this for the SUT:
module.exports = function() { ... }
However the Stitch docs seem to require functions to be defined as:
exports = function() { ... }
I do not have a background in JavaScript to understand the difference. I could try module.exports in Stitch, but I would rather not, since this would either not work now, or cause a breakage in the future. Can Jest be instructed to "see" bare exports without the module prefix?
Incidentally, I have picked Jest because it is popular, and because some of my JavaScript colleagues vouch for it. However, I am not wedded to it, and would be happy to use something else if it is known to be better for Stitch development.
Update
Following the useful answer from jperl below, I find that the following construction is not possible in Stitch:
module.exports = exports = function() {}
I also cannot do this:
exports = function() {}
module.exports = exports
If I try either, I get the following error:
runtime error during function validation
So it looks like I have to get Jest to work without module.exports, or create a glue file that imports the exports version into module.exports, with the main file being used by Stitch, and the glue importer being used by Jest.
I suggest you to read this thread. And you're right in thinking it has to do with modules.exports vs exports. The thing is that module.exports and exports first point to the same thing. So something like this works:
//modify the same object that modules.exports is pointing to
exports.a = {}
exports.b = {}
but this won't:
exports = {}
Why? Because now exports points to something else than module.exports so what you're doing has no effect at all.
Update
Following some updates in the comments, we came to the view that Stitch does not seem to support the export format that Jest requires.
This is an addendum to jperl's answer, to show how I got Jest working while respecting Stitch's limitations.
Firstly, it is worth noting how a Stitch application is laid out. This is determined by the import/export format.
auth_providers/
functions/
function_name_1/
config.json
source.js
function_name_2/
config.json
source.js
...
services/
values/
The config.json file is created by Stitch remotely, and is obtained through a export. This contains ID information to uniquely identify the function in the same folder.
I believe it is common JavaScript practice to mix tests with source code, so I am following that style (I am new to modern JS, and I confess I find this style untidy, but I am running with it nevertheless). Thus I add a source.test.js file in each function folder.
Finally, since there is a discrepancy between what Stitch requires and what Jest requires, I have written a script to create a source code file under _source.js in each function folder.
So, each folder will contain these files (the underscore files will probably be ignored by Git, as they will always be generated):
_source.js
config.json
source.js
source.test.js
In order to create the underscored copies, I am using this shell script:
#!/bin/bash
# Copy all source.js files as _source.js
for f in $(find functions/ -name source.js); do cp -- "$f" "$(dirname $f)/_$(basename $f)"; done
# Search and replace in all _source.js files
for f in $(find functions/ -name _source.js); do sed -i -e 's/exports =/module.exports =/g' $f; done
A bit hacky perhaps, but it works!

Cypress custom command is not recognized when invoked

I've created the following custom command in my cypress/support/commands.js file.
Cypress.Commands.add("login", (username, password) => {
cy.request({
method: 'POST',
form: true,
url: '/test/login/',
body: {'username': username, 'password': password}
})
})
I had tests passing and login working before moving the login functionality to this custom command. I'm invoking it in my spec with cy.login(testuser, testpwd), but I'm getting the following error message: TypeError: cy.login is not a function. The docs say that /cypress/support/commands.js is loaded before any test files are evaluated, so I assumed that simply placing a custom command in there would make the command available. I'm running the tests through the local (GUI) test runner.
All the code and referenced modules in index.js are loaded before your test file. So you need to refer(require) commands.js in your index.js file.
You can however import commands.js module directly in your test file but then you need to include it every test file.
Recommended approach is to include it in index.js file and you are not worried about explicitly refer in your test files.
To expand on #Dinesh Kumar's excellent answer, it's also important you haven't disabled support for the default support file (I know, unfortunate naming scheme in this case) inside your cypress.json by adding the line: supportFile: false.
Delete that line from your cypress.json if it's there. You can also specify a different path if you're not happy using the default path of cypress/support/index.js.
Working index.js with commands.js file - both in the support folder:
// index.js
const customCommands = require('./commands.js')
module.exports = {
commands: customCommands
}
And double check your settings:
// cypress.json
{
"baseUrl": "http://demo.your-domain.test",
"supportFile": false, // <-- delete this line present
...
}
It may help to put a line import './commands.js' into index.js.
For me it worked when I added the type signature of the custom command in the file cypress/support/index.d.ts. For more information visit: Cypress example - Custom Commands
declare namespace Cypress {
interface Chainable {
clearLocalStorageIframe(): void
}
}
I am using 7.2.0 Cypress and command.ts and index.ts file extension I have changed it to .ts
TL;DR: Check if your IDE tried to resolve cy
I slipped into this problem, because my IDE's autocomplete feature added a dependency to resolve the undeclared cy object – that gets injected by cypress.
const { default: cy } = require('date-fns/esm/locale/cy/index.js');
This was very unfortunate, as there is an ongoing (in 2022) issue with the custom commands and you can find a tons of hints..
Removing
import { cy } from "date-fns/locale";
or similar import
from the test file, resolved this. This gets added automatically to resolve undeclared cy objects
Permanent Solution: Add the following to cypress.json
"compilerOptions": {
"types": ["cypress"]
}
I added at the top of commands.js.
/// <reference types="cypress" />
export{}
//CUSTOM COMMANDS...
This then exported and exposed the custom commands after cy. .

JavaScript fails to require a file from a concat string

I write a function which will load a file using require():
function loadFromName(name) {
const filename = `./${name}.initialState`;
return require(filename).default;
}
When I call this method, it will fail to find the file:
loadFromName('tab')
> Requiring unknown module "./tab.initialState". If you are sure the module is there, try restarting the packager or running "npm install".
I tried two kinds of inline require(). One is success; one is failed.
let initialState;
const name = 'tab';
initialState = require('./tab.initialState'); // success
const filename = './' + 'tab' + '.initialState';
initialState = require(filename); // failed
Why and how to fix it?
NOTE: I use this in React-Native development
Dynamic require is not supported on react native. There are lot of similar questions on stack overflow React Native - Image Require Module using Dynamic Names

Categories

Resources