Access a Meteor App's unique .id - meteor

I'm writing a Meteor package that needs to know the id of the app that includes it -- the value that is saved in the .meteor/.id file relative to the project directory.
How can I access the id safely in development AND in production?

This is doable from server-side code using NPM. I just tested the following on my local project and it works:
// server-side code
// FYI, Npm.require works in packages only. Use meteorhacks:npm to use
// in non-package code. In meteor shell you can just use `require`.
var fs = Npm.require('fs');
var path = Npm.require('path');
var idPath = path.join(process.env.PWD, '.meteor/.id');
var fileContent = fs.readFileSync(idPath);
var fileContentLines = fileContent.toString().split('\n');
// this will contain the ID
var theId = fileContentLines[fileContentLines.length - 2];
Now, keep in mind that in production, you don't have the .meteor directory. After running a grep for the id in the build folder, it seems to me like that ID is not stored in any file within the build. Therefore, you will need to create a build plugin which makes sure to make it accessible somewhere during the build process. I may not have looked hard enough, so I would definitely take a look at the source for the build tool and see what it does with that ID during build.

In Meteor 1.2.1, (and 1.3) the appId is accessible via the __meteor_runtime_config__.appId variable on the client and server in development mode. This is undocumented so we don't know if it will be available in future versions.
The .appId property of __meteor_runtime_config__ is NOT available:
In production mode (when Meteor.isProduction)
In test mode (when Meteor.isTest)
In app test mode (when Meteor.isAppTest)

How about using Meteor Settings file http://docs.meteor.com/#/full/meteor_settings? It should be the right way to do that, Otherwise you will have to use Node.js to access the file directly

Related

SBT - watch different sources depending on Task

In a cross Scala JS server / client project, I want changes of some sources to restart the server and other sources to trigger the packaging process, but without the restart. Different tasks will not help because they will simply do one or the other and I want both at the same time.
In more detail:
I've got a Scala.js crossProject. I'm using the following to ensure the server can serve the built JavScript:
val app = crossProject.settings(...)
lazy val appJS = app.js
lazy val jsFile = fastOptJS in(appJS, Compile)
lazy val appJVM = app.jvm.settings(
(resources in Compile) += jsFile.value.data,
(resources in Compile) += jsFile.value.data.toPath.resolveSibling(jsFile.value.data.name+".map").toFile,
(resources in Compile) += (packageJSDependencies in(appJS, Compile)).value
)
If I run ~ appJVM/compile:packageBin::packageConfiguration then changes to the JavaScript source are immediately compiled and placed in the appJVM target/classes dir, so a refresh of the browser gets my new code - brilliant.
However, I would also like to use the sbt-revolver plugin to restart the server if I edit server-side code. But there's the rub - if I use ~ ;appJVM/compile:packageBin::packageConfiguration;appJVM/reStart then changes to the client side source restart the server, which I don't want. But if I remove the client side project from the transitive watch then it no longer notices if I change the client side project.
Is there a way to define watchTransitiveSources differently per task?
~ is actually a command that watches the transitive sources of the base project and then synchronously runs everything passed as an argument to it when those change, before re-running the original input (including ~). It does not make any information about what has changed available to those command line inputs (difficult to see how it could).
Consequently the solution I came to is to write a new watch command. It also needs to watch all sources, but then conditionally choose what to do based on which files have changed.
I've hacked something ugly as anything together that does this, but will look at making it more legible, general, tested and a Plugin. However, in the meantime anyone trying to follow my path can use this public gist: https://gist.github.com/LeisureMonitoringAdmin/0eb2e775e47b40f07d9e6d58d17b6d52
Are you sure you are using sbt-resolver not sbt-revolver ?
Because the second one allows controlling the triggered resources using
watchSources - defines the files for a single project that are
monitored for changes. By default, a project watches resources and
Scala and Java sources.
watchTransitiveSources - then combines the
watchSources for the current project and all execution and classpath
dependencies (see .scala build definition for details on interProject
dependencies).
Source: http://www.scala-sbt.org/0.13/docs/Triggered-Execution.html

How to read Meteor settings from a build plugin

I'm currently working on a package for Meteor that includes a build plugin. I need to access configurations from the settings file.
However Meteor.settings doesn't work (Meteor is not defined) and process.env.METEOR_SETTINGS also doesn't exist.
Is there any way for my plugin to access the settings file?
It appears that despite the documentation discussing the use of --settings, it doesn't work in a production environment, as often command line options are not available.
So the solution is to use environment variables, which are available only on the server.
server code, meteor methods:
eor methods
Meteor.methods({
getPJS: function() {
return process.env.PEERJS_SERVER;
},
client code
var PJS = Meteor.call("getPJS");
So you can make those environment variables available on the client if you need them.

SBT credentials file with multiple realm

We run an artifactory server, that has moved to a different endpoint (artifactory-b.example.com). To make it backwards compatible, the old url (artifactory-a.example.com) is being proxied to the new one.
However, publishing with sbt uses a .ivy2/.credentials file with the following layout
realm=Artfactory realm
host=artifactory-a.example.com
user=artifactory-user
password=P4ssw0rdH4sh
however, I would like to change this so new builds will publish to the correct endpoint
realm=Artfactory realm
host=artifactory-d.example.com
user=artifactory-user
password=P4ssw0rdH4sh
Is it possible to add multiple realms in one file? That sbt will try the first, if it does not work (Forbidden|Not Found) the second? So that my .ivy2/.credentials file looks like
# old instance for backwards compatibility
realm=Artfactory realm
host=artifactory-a.example.com
user=artifactory-user
password=P4ssw0rdH4sh
# New spiffy instance
realm=Artfactory realm
host=artifactory-b.example.com
user=artifactory-user
password=P4ssw0rdH4sh
Anyone any experience with this, or am I bound to using two files, and change the reference in my repo to the second file (i.e. .ivy2/.credentials2).
P.S. The realms are in a file, because multiple repos use these credentials to publish.
So important here is that the realms have the same name, only a different endpoint (unlike this post):
May there is no way to have multiple realms within a credential file, but you could have multiple realms within multiple credential files, each realm in a separate credential file.
In ~/.ivy/.credentials will be:
realm=Sonatype Nexus Repository Manager
host=mvn.nexus1.org
user=readonly
password=readonlyPass
And in ~/.ivy/.credentials.deploy will be:
realm=Sonatype Nexus Repository Manager
host=deploy.nexus2.org
user=deployment
password=deploymentPass
So then you will have these lines in your build.sbt:
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials.deploy")
Turns out that what I want is not possible using a properties file, because that is just not how property files work.
Maybe there is another way, but the solution I want can not be achieved in this way, unfortunately

Meteor with dotenv package for environment variables: "process" is not defined

I'm adding security for my API keys with the Meteor package dotenv: https://github.com/okgrow/meteor-dotenv
as per instructions, I:
1. created a file named ".env" in my root
2. entered two keys in the style "THIS_KEY=BLAH12345" in the file
3. made a meteor call function returning process.env.THIS_KEY for the client side to use.
I'm getting Referenceerror: process.env is not defined. For just plain node there are a lot of answers out there, but not so for Meteor. Did I name my file incorrectly? Need to use a Meteor command to activate something?
I ran into this same problem, and have made it work by putting the
var secretThing = process.env.SECRET_THING
server side, inside the if (Meteor.isServer) and then passing the variable as a parameter to the method that needs to use the secret thing.
Meteor.call("apiCall", secretThing);
Then the receiving method looks like this:
apiCall: function (secretThing) {
console.log(secretThing);
}
DotEnv is designed to read environment variables from a .env file, normally located in the root of your NodeJS application.
DotEnv just makes the variables it finds in the .env file available with the rest of the host systems environment variables through process.env
The problem is, I don't believe meteor supports .env files. This is probably due to the age of the application. I personally believe they should make rectifying this a priority.
The only way you can use process.env in a meteor app is to set the variables you want to use on the host system. If you are using linux it would be something like
export DB_PASSWORD=12345
You should then be able to use process.env to read DB_PASSWORD when your application is running.
// You can only run process.env in server code
if (Meteor.isServer) {
const myDBPassword = process.env.DB_PASSWORD
}

Air: Possible? Writing into installed application package

This is probably a bad idea or whatever you wan't to call it. Nevertheless, curious to know if Air can write inside it's own installed package. I'm referring to the OSX '.app' files found in great numbers in the applications folder. Since every one of these can be opened as a regular folder, i'm guessing that's what they are.
What other fancy filewriting tricks am i missing out on?
It's definitely a bad idea. That said, it looks like it's probably possible. Something like (untested):
var appDir:File = File.applicationDirectory; // uses app: URI, can't be written to
var appPath:String = appDir.nativePath;
var writeableAppDir:File = new File(appPath);
var newFile:File = writeableAppDir.resolvePath("writeme.txt");
The nativePath and applicationDirectory documentation in the File class are full of warnings against this. Follow them.
From the docs:
Modifying content in the application
directory is a bad practice, for
security reasons. If you want to store
application-specific data, consider
using the application storage
directory
(File.applicationStorageDirectory). If
you want any of the content in the
application storage directory to have
access to the application-priveleged
functionality (AIR APIs), you can
expose that functionality by using a
sandbox bridge.

Resources