How to access a package variable from somewhere else in the application? - meteor

I have developed two Meteor packages that I have added into my Meteor application.
Each package has a log collection that I am trying to query from the Meteor Application. However, it seems I am unable to access those collections from the main application:
// pkg_1_log is defined in pkg_1 package.
pkg_1_log.find().count();
ReferenceError: Can't find variable: pkg_1_log
// pkg_2_log is defined in pkg_2 package.
pkg_2_log.find().count();
ReferenceError: Can't find variable: pkg_2_log
What do I need to tweak in order for that to work?

To provide access to a package-scoped variable (defined without var), you need to export it:
api.export('myVar');
You can specify the target architecture in the second argument.
You may then meteor add your package to get this exported variable to the whole application but also api.use it in another package or even api.imply it. If you are unsure as to what the difference between "using" and "implying" is then you should check saimeunt's answer.

Related

Is there a fix for InheritanceManager breaking static type checking?

I have added django-model-utils to an existing (large) project, and the build is now failing, as part of the build includes static type checking with mypy.
It complains that models that I have added objects = InheritanceManager() to, don't have attributes for reverse ForeignKeys, if the reverse FK is accessed in a method on that model. For example, take the following:
class Student(Model):
school = ForeignKey(School, related_name='students')
class School(Model):
objects = InheritanceManager() # IRL School is a subclass of some other model
def something(self):
return self.students.filter(...)
Then running mypy on it, will return:
error: "School" has no attribute "students"
And even if I remove the related_name, and use self.student_set (i.e. the default django relation), it will still produce the same type of error. Only removing the InheritanceManager fixes the static type checking. Of course, I'm using it for a reason as I need to select_subclasses elsewhere in the code.
Has anyone come across this, or have a fix?
django-stubs uses plugin to add all managers. This plugin is triggered only if added manager is a "subclass" (not just real subclass, but also recognizable by mypy as such) of models.Manager.
django-model-utils is untyped, so InheritanceManager is in fact Any for mypy, and plugin does not see it. To solve exactly this issue I was adding py.typed marker to django-model-utils as a CI stage after package installation. You can also use a fork with py.typed or create a stub package for django-model-utils. This can result in other issues and doesn't give good type checking (all unannotated methods have Any as implicit arguments and return type), but is better than nothing. For my needs the marker was sufficient.
py.typed marker is an empty file located in package root (venv/lib/.../django_model_utils/py.typed) - it tells mypy that package does not need separate stubs and contains all necessary types.

Using using dynamically

I want to use modules dynamically and I know their name, but creating a module and then applying using like this:
using PyPlot
a = Module(:Plots)
using a
will yield an excpetion telling me that a is not definied. Which is a very unintuitive error message, since when you do this on the repl you can use 'a' afterwards. Just in combination with using it tells you that it is not defined.
The error message is emitted by Base.require, so you should use using Main.a or using .a instead:
require(module::Symbol)
This function is part of the implementation of using / import, if a module is not already
defined in Main. It can also be called directly to force reloading a module, regardless of
whether it has been loaded before (for example, when interactively developing libraries).
...
When searching for files, require first looks for package code under Pkg.dir(), then tries paths
in the global array LOAD_PATH. require is case-sensitive on all platforms, including those with
case-insensitive filesystems like macOS and Windows.
Or just use module keyword to define a module on the fly:
module A
...
end
using A
For an existing module, you could also dynamically use it via eval(using module-name).

Using an exported variable from another Meteor package

I'm trying to wrap an extension for Chart.js in a package for Meteor. Inside the extension, the author tries to access the global Chart variable.
Is exposing the variable like this in an export.js file (loaded before the extension) considered a proper solution?
this.Chart = Package['chart:chart'].Chart;

In Meteor, using an object (defined in one file) in another file without global scoping?

I've got a prices.js file with a ShoppingCartContents object that is defined in this file.
I'd like to access this ShoppingCartContents object inside my helpers.js file, where I will be using it to create a global helper.
I can easily do this by just setting ShoppingCartContents to global, but I don't want to do that. Is there a better way? According to the docs there's package scope and file scope. These two scopes don't seem granular enough to me (there's also a package export feature but I'm doing everything inside one package)
Things can only be scoped to:
one and only one file
the entire package
Shouldn't there be a file export feature maybe?
If you're working inside a package, make the variable global. That way you can access it in all your files, for your package.
If you want a truly global variable, you have to explicitly export it, so there's no problem in using globals.

Share code between package.js in Meteor?

I have a number of packages, with a package.js file inside each. In those package.js files, I have a couple of helper functions. Right now, when I create a new package, I have to duplicate those helper functions.
Is there a way to put those helper functions in one place and use it from every package.js?
Found this question randomly over google,
just create a global helpers package for example: username:global-heleprs
example code:
heleprs = {
formattedTimeStramp: function (date) {
return moment(date).format('dddd');
},
more...
}
use api.export('helpers', ['server', 'client']); to export helpers object to make it available outside the package
if you want to use it on different package just do on this your different package package.js file it will give you access to helpers
api.use('username:global-heleprs', ['client','server']);
if you want to use it on the meteor application itself on any file (outside of packages)
meteor add username:global-helpers
p.s if you don't add it using meteor add username:global-helpers the access to the helpers is only to the packages that require it with api.use that's pretty good avoid sharing the helpers with the main app.

Resources