how to make some lines in index.ts not executed? - node.js

so in my index.ts I initially have code like this
export * as users from "./firestore/triggers/users/users_triggers";
export * as auth from "./firebase_authentication/triggers/firebase_auth_triggers";
and then I have another export in my index.ts, but I want this export only executed if it meets some criteria. so in my index.ts will be like this
export * as users from "./firestore/triggers/users/users_triggers";
export * as auth from "./firebase_authentication/triggers/firebase_auth_triggers";
const meetSomeCriteria = true;
if (meetSomeCriteria) return;
// if it meets some criteria, then I expect the code below won't be triggered
export * as utilities from "./utilities/emulators/http_triggers/for_testing_via_firestore_emulators";
but I will have error if I have return like that
so how to make some lines in index.ts not executed?
those export utilities is actually some functions that I will be used only for Firebase Emulators. I want to avoid those functions to be deployed in production

There are no conditional imports or exports in typescript. Ie you cannot write something like
if (acondition)
import x from "module"
But you can workaround it like this
import * as utilimport from "./your/module";
export const utilities = meetSomeCriteria
? utilimport
: undefined
;

Related

Behavior of export and export default in JavaScript

I am creating a NodeJS and Express app and want a module for configuration that runs once on start up then makes a serverConfig object available to any other module that needs these values. So far I have something like this:
const loadConfig = () => {
// logic to load configuration from environment variables, AWS Secrets Manager, etc.
}
export default loadConfig()
Now I can do
import serverConfig from 'config'
When I do this in multiple files will loadConfig() be called each time? Or will I have access to a reference to a single object from all of my imports? I only want this loadConfig() function to execute once on start up. These config values should not change during execution. And I don't want to repeat the (perhaps) time consuming logic in loadConfig() multiple times during each request to my API.
If not, what is the correct way to call loadConfig() once on server start up and create an object that all other modules can import and reference.
Everything in file scope executes once. Once the exports of a file are resolved, they are directly used by reference for any subsequent imports.
Any function call that is is not inside function itself will be executed exactly once when that file is imported when your program first starts up.
// a.ts
console.log('foo')
// b.ts
import './a'
// c.ts
import './a'
// main.ts
import './b'
import './c'
If you compile and run main.ts you will get exactly one output of "foo" to the console.
Given that, your example could be rewritten as:
const loadConfig = () => {
// logic to load configuration from environment variables, AWS Secrets Manager, etc.
}
const config = loadConfig()
export default config
Now its pretty clear that loadConfig() is called from the file scope and so only executes once.
This version:
export default loadConfig()
just avoids the intermediary variable but otherwise functions exactly the same.
If you did want to run that logic multiple times, you just need to export a function to do it for you.
// config.ts
export const loadConfig = () => {
// ...
}
// main.ts
import { loadConfig } from './config'
loadConfig()
loadConfig() // now do it again.
That doesn't sound like what you want, but I list it here to make it clear what the difference is.

NodeJS - using require works import does not work

I'm trying to understand why require works while import does not for an npm package. The package is r7insight_node and allows us to send our logs to their product, Rapid7. When we use require as per their instructions things work fine, but don't when I use import.
Their library has an src/index.js file that looks like:
// Use codependency for dynamically loading winston
const requirePeer = codependency.register(module);
// Import winston
const winston = requirePeer('winston', {optional: true});
const Transport = requirePeer('winston-transport', {optional: true});
// If we have successfully loaded winston (user has it)
// we initialize our InsightTransport
if (winston) {
provisionWinston(winston, Transport);
}
// Logger is default export
module.exports = Logger;
// Export as `bunyanStream` to not break existing integration
module.exports.bunyanStream = buildBunyanStream;
module.exports.provisionWinston = provisionWinston;
My understanding is that require is synchronous and is "computed" whereas import is asynchronous and is NOT "computed" as written here. Is this the reason for why require works while import does not?
Does "computed" mean in that the index.js file is executed and hence the if (winston) block is checked and executed in a require but not in an import? Is there a way to achieve the same using import statements?
Thanks in advance
for the package to work with the ES6 import way, it has to be written to it, it has to be exported as eg:export default Logger and not module.exports = Logger, hope my answer helped you

How to fix/disable seemingly erroneous "No named exports found in module" error?

I'm linting my code and I'm getting this in a couple places:
/Users/zane/playground/react-waiter/js/components/index.js
1:15 error No named exports found in module './utils' import/export
2:15 error No named exports found in module './widgets' import/export
/Users/zane/playground/react-waiter/js/index.js
1:15 error No named exports found in module './components' import/export
I believe the report is a false positive because when I run the code, everything works fine and I can indeed import the exported items.
The code:
// js/index.js
export * from './components'
export * from './settings'
export * from './utils'
// js/components/index.js
export * from './utils'
export * from './widgets'
// js/components/utils/index.js
export * from './Waiter'
// js/components/utils/Waiter.jsx
...
const Waiter = (props) => { ... }
export { Waiter }
Then the same pattern for the widgets module, a single constant exported from the file and re-exported from the index. I did
try export const Waiter = ..., and export * from './utils/index' with the same result.
I use this pattern a lot, and the problem occurs when re-exporting an index file and nothing else.
As a workaround, I set the eslint config to change these to warnings so they don't stop the CI process, but true problems still get reported.
I assume at some point the (apparent) bug will be fixed. This would be a minor issue, but /* eslint-disable import/export */ seems to have no effect.
Any insight would be greatly appreciated. Is there a way to disable the rule on a per-line basis and/or "jiggle" things so eslint properly reports things?
To disable this rule your .eslintrc.js should have:
module.exports = {
'rules': {
'import/export': 0
}
}

What does Babel do to let me use any name to import a node module that exports a function

An example will make my question clearer, say I want to import debug module to my vuejs codes
Debug module export createDebug function like this,
module.exports = require('./browser.js');
...
exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
function createDebug(namespace) { ... }
When I use import to import debug module, I can give it any name I want, like
import debug from 'debug' // or any name I want, e.g
import debugjs from 'debug'
I understand if export default anonymous function I can then import it with any name I want, but this is not the case here.
So why can I use any name to import it?
---------------- update -----------------
One takeaway from the answer is that import "any name" work for both default export anonymous function and named function.
but this is not the case here.
It kind of is. You are trying to import a module that has no ES6 exports. You are trying to import a CommonJS module. So Babel has to make a decision how to handle that case.
There are two common ways to export something from a CommonJS module:
Assign a property to exports (or module.expoets), for example exports.answer = 42;
Overwrite the value of module.exports, e.g. module.exports = 42;.
In the second case you end up exporting only a single value from the module. That's basically what a default export is (since there can only be one) and that's what you are doing in your code.
So in other words, when importing a CommonJS module via ES6 import statements, then the value of module.exports is used as the default export value.
We can confirm that by looking at how Babel converts the code:
// import foo from 'bar'; becomes
var _bar = require('bar');
var _bar2 = _interopRequireDefault(_bar);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
// ^^^^^^^^^^^^^^^^
}

Pass on all exports from a module object

I've got the following js file:
// db.js
export default /* ... */;
export const tableName = /* ... */;
And the following mock for it (using jest):
const MockDb = jest.genMockFromModule('../db.js');
export default MockDb.default;
export const { tableName } = MockDb;
Now, if I add an export to my original db.js file, I have to also touch the mock accordingly. I'd rather have the mock file just automatically export all exports from the MockDb object (which is a module object generated by jest holding a default key and other named properties for each export).
According to MDN, the export * from X
syntax only works, when X is a string referring to a module. Can I somehow export * from <moduleObject>?
Thanks!
Can I somehow export * from <moduleObject>?
No, you can't. The export names must be statically declared, they can't be determined at runtime from an object.
The correct approach would a module loader plugin which automatically calls Jest when you do something like import … from '../db.js!jest';.

Resources