From 3fbeb10acbb6e5113b6389aba174f9271591706c Mon Sep 17 00:00:00 2001 From: Jay Gischer Date: Wed, 20 Mar 2024 11:19:00 -0700 Subject: [PATCH 1/4] Updated to reflect new realities. Now instead of shipping a mongo binary, we will use the exact mongo binary that Meteor uses to run in development mode. This doesn't seem ideal, but it does work. --- meteor-spk | 102 +++++++++++++++++++++++++++++++++++---- package-lock.json | 120 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 13 +++-- start.js | 3 +- 4 files changed, 222 insertions(+), 16 deletions(-) create mode 100644 package-lock.json diff --git a/meteor-spk b/meteor-spk index c56fe35..d4bc8b3 100755 --- a/meteor-spk +++ b/meteor-spk @@ -23,23 +23,48 @@ # This script wrap's Sandstorm's `spk` tool and adds convenience functionality # specific to Meteor apps. See the readme for more info. +# This script gathers all of the binaries and libraries needed to run Meteor, +# but which aren't part of a normal Meteor bundle. +# +# We pull Node.js from the Meteor tools installation. We also pull mongod from +# the meteor tools installation. We no longer build a custom version of +# MongoDB since the flags to build the smaller version have been removed. +# +# (It would be nice to replace Mongo entirely with an in-process database; maybe +# based on Meteor's own "minimongo"...) +# +# We pull any needed libraries straight from the local system. +# +# So the strategy is to use exactly the same tools as were used to +# run the Meteor app in development mode. We gather them into the bundle, +# build Meteor, then apply spk. +# set -euo pipefail -DEPS_DIR=$(readlink -f "${BASH_SOURCE[0]}").deps +SOURCE_DIR=$(dirname "${BASH_SOURCE[0]}") +DEPS_DIR=.meteor-spk/deps METEOR_WAREHOUSE_DIR="${METEOR_WAREHOUSE_DIR:-$HOME/.meteor}" -if [ ! -e "$DEPS_DIR" ]; then - echo "Couldn't find $0's dependencies; expected in: $DEPS_DIR" >&2 - exit 1 -fi if [ ! -x "$METEOR_WAREHOUSE_DIR/meteor" ]; then echo "Couldn't find Meteor installation. Please install Meteor." >&2 exit 1 fi -METEOR_DEV_BUNDLE=$(dirname $(readlink -f "$METEOR_WAREHOUSE_DIR/meteor"))/dev_bundle +# +# The purpose is to use the EXACT same binaries that the specific meteor project +# uses to run in development mode. It may not be ideal, but it *does* run. +# + +METEOR_RELEASE=$(<.meteor/release) +TOOL_VERSION=$(meteor show --ejson $METEOR_RELEASE | grep '^ *"tool":' | + sed -re 's/^.*"(meteor-tool@[^"]*)".*$/\1/g') +TOOLDIR=$(echo $TOOL_VERSION | tr @ /) + +METEOR_DEV_BUNDLE=$(readlink -f "$HOME/.meteor/packages/$TOOLDIR/mt-os.linux.x86_64/dev_bundle") + + if [ ! -e "$METEOR_DEV_BUNDLE/bin/node" ]; then echo "Meteor installation is not laid out like I expected." >&2 echo "This tool requires Meteor version 0.9.0 or newer." >&2 @@ -58,10 +83,66 @@ fi COMMAND=$1 shift +copyDep() { + # Copies a file from the system into the chroot. + local FILE=$1 + local DST=.meteor-spk/deps"${FILE/#\/usr\/local/\/usr}" + + if [ -e "$DST" ]; then + # already copied + : + elif [[ "$FILE" == /etc/* ]]; then + # We'll want to copy configuration (e.g. for DNS) from the host at runtime. + if [ -f "$FILE" ]; then + echo "$FILE" >> tmp/etc.list + fi + # Symbolic link. + # We copy over the target, and recreate the link. + # Currently we denormalize the link because I'm not sure how to follow + # one link at a time in bash (since readlink without -f gives a relative + # path and I'm not sure how to interpret that against the link's path). + # I'm sure there's a way, but whatever... + mkdir -p $(dirname "$DST") + local LINK=$(readlink -f "$FILE") + ln -sf "${LINK/#\/usr\/local/\/usr}" "$DST" + copyDep "$LINK" + elif [ -d "$FILE" ]; then + # Directory. Make it, but don't copy contents; we'll do that later. + mkdir -p "$DST" + elif [ -f "$FILE" ]; then + # Regular file. Copy it over. + mkdir -p $(dirname "$DST") + cp "$FILE" "$DST" + fi +} + +copyDeps() { + # Reads filenames on stdin and copies them into the chroot. + + while read FILE; do + copyDep "$FILE" + done +} + makedotdir() { - mkdir -p .meteor-spk - ln -sfT "$DEPS_DIR" .meteor-spk/deps + rm -rf $DEPS_DIR + mkdir -p $DEPS_DIR + # copy over the sandstorm files + mkdir -p $DEPS_DIR/programs/server/node_modules + cp $SOURCE_DIR/start.js $DEPS_DIR/start.js + cp $SOURCE_DIR/package.json $DEPS_DIR/package.json + (cd $DEPS_DIR && $METEOR_DEV_BUNDLE/bin/npm install) + echo "After installing start" + cp /opt/sandstorm/latest/node_modules/{capnp.node,capnp.js} $DEPS_DIR/programs/server/node_modules + cp -r /opt/sandstorm/latest/usr/include/{capnp,sandstorm} $DEPS_DIR/programs/server/node_modules + # Copy over key binaries. + mkdir -p $DEPS_DIR/bin + echo "Copying $METEOR_DEV_BUNDLE/mongodb/bin/mongod to $DEPS_DIR/bin/" + cp $METEOR_DEV_BUNDLE/mongodb/bin/mongod $DEPS_DIR/bin/ + (cd $DEPS_DIR/bin && ln -s ./mongod niscud) + cp $METEOR_DEV_BUNDLE/bin/node $DEPS_DIR/bin + (ldd $DEPS_DIR/bin/* $(find $DEPS_DIR -name '*.node' || true) | grep -o '[[:space:]]/[^ ]*') | copyDeps } bundle() { @@ -71,12 +152,13 @@ bundle() { meteor npm install meteor build --directory .meteor-spk (cd .meteor-spk/bundle/programs/server && meteor npm install) + #cp -r $DEPS_DIR/* .meteor-spk/bundle } case "$COMMAND" in init ) makedotdir - spk init -p 4000 -I.meteor-spk/deps -I.meteor-spk/bundle -A "$@" -- node start.js + spk init -p 4000 -I$DEPS_DIR -I.meteor-spk/bundle -A "$@" -- node start.js if [ -e .git ]; then cat >> .gitignore << __EOF__ .meteor-spk @@ -93,6 +175,7 @@ __EOF__ ;; clean ) rm -rf .meteor-spk/bundle + rm -rf .meteor-spk/deps ;; help ) cat << __EOF__ @@ -108,4 +191,3 @@ __EOF__ spk "$COMMAND" "$@" ;; esac - diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..cedf3c5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,120 @@ +{ + "name": "meteor-spk-start", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha512-CUD62/uqeE0L+EJeypOKuFfM56CFaH4vo+++J76bff0NkeQ2bBmWVCTNxL2hj9HeCYPkof6Gqea0BSeK17gBzA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + }, + "dependencies": { + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g==" + } + } + }, + "mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "requires": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==" + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + } + } +} diff --git a/package.json b/package.json index d0c3f21..d730b6f 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,15 @@ { "name": "meteor-spk-start", - "repository": "https://github.com/sandstorm-io/meteor-spk", "version": "0.1.0", - "private": false, + "description": "## Introduction", + "main": "start.js", + "repository": { + "type": "git", + "url": "git+https://github.com/gischer/meteor-spk.git" + }, + "license": "ISC", "dependencies": { - "mongodb": "~2.0", - "es6-promise": "~3.0" + "es6-promise": "~3.0", + "mongodb": "^2.2.36" } } diff --git a/start.js b/start.js index a821a13..eff3845 100644 --- a/start.js +++ b/start.js @@ -80,7 +80,7 @@ function startMongo(continuation) { console.log("** Starting Mongo..."); var db = child_process.spawn("/bin/mongod", [ "--fork", "--port", mongoPort, "--dbpath", dbPath, - "--noauth", "--bind_ip", "127.0.0.1", "--nohttpinterface", + "--noauth", "--bind_ip", "127.0.0.1", "--storageEngine", "wiredTiger", "--wiredTigerEngineConfigString", "log=(prealloc=false,file_max=200KB)", @@ -196,4 +196,3 @@ if (fs.existsSync(dbPath) && !fs.existsSync(migrationDumpPath)) { }); } } - From 169c68df4df1e9dc85ce47fc1a1c376b8b29c75a Mon Sep 17 00:00:00 2001 From: gischer Date: Tue, 9 Apr 2024 15:40:20 -0700 Subject: [PATCH 2/4] Test for checkin --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index d01c586..89a26b2 100644 --- a/Makefile +++ b/Makefile @@ -42,3 +42,4 @@ reallyclean: clean cd niscu && scons -c .PHONY: dist clean reallyclean push +// This is a comment From ab5b8cc17b9120a54402665d9ee5b0a47ce1d71b Mon Sep 17 00:00:00 2001 From: gischer Date: Fri, 12 Apr 2024 09:55:56 -0700 Subject: [PATCH 3/4] Some cleanup for release. Updated README and removed dead code. --- .gitmodules | 8 --- README.md | 43 ++++++--------- gather-deps.sh | 147 ------------------------------------------------- 3 files changed, 17 insertions(+), 181 deletions(-) delete mode 100644 .gitmodules delete mode 100755 gather-deps.sh diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 303d52b..0000000 --- a/.gitmodules +++ /dev/null @@ -1,8 +0,0 @@ -[submodule "mongo"] - path = mongo - url = https://github.com/mongodb/mongo.git -[submodule "niscu"] - path = niscu - url = https://github.com/kentonv/mongo.git - branch = niscu - diff --git a/README.md b/README.md index 8dc78fa..739c4c7 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,17 @@ This package provides a tool, `meteor-spk`, which wraps Sandstorm's normal `spk` tool as well as Meteor's tools in order to easily package Meteor apps to run on Sandstorm. +This version of `meteor-spk` is heavily modified. Rather than +pack up a bunch of binaries to be part of the .spk file, it uses the binaries that meteor itself uses in development mode. +This includes `node`, `npm`, and most importantly `mongo`. + +Previous versions had employed a special built version of +`mongo`, known as `niscu`, which was built to be smaller, in keeping with the self-contained principle of Sandstorm grains. + +This is no longer possible. Many of the flags used to build niscu do not exist. So we use the binaries used to run a `meteor` development environment instead. + +We also binary encode a couple of support scripts so that `meteor-spk` can now be a single shell script, simplifying installation. + ## Installing the tool ### Prerequisites @@ -25,18 +36,11 @@ way to do that is: curl https://install.sandstorm.io | bash -### Installing `meteor-spk` from binaries - -1. Download and unpack - [the binary distribution](https://dl.sandstorm.io/meteor-spk-0.6.0.tar.xz), - e.g.: +### Installing `meteor-spk` - mkdir -p ~/projects/meteor-spk - cd ~/projects/meteor-spk - curl https://dl.sandstorm.io/meteor-spk-0.6.0.tar.xz | tar Jxf - - cd meteor-spk-0.6.0 +1. Clone this repo -2. Add the directory to your `$PATH`, or symlink the `meteor-spk` script into +2. Add the directory of your clone to your `$PATH`, or symlink the `meteor-spk` script into a directory in your `$PATH`, e.g.: ln -s $PWD/meteor-spk ~/bin @@ -45,6 +49,7 @@ way to do that is: To package your existing Meteor app, do the following: +0. You must have a working meteor application on your build machine. 1. Run `meteor-spk init` in your app's source tree. 2. Open the generated file `sandstorm-pkgdef.capnp` in a text editor. Read the comments and fill in as appropriate. In particular you will probably @@ -64,12 +69,6 @@ To package your existing Meteor app, do the following: ## Tips -* As of version 0.1.5, `meteor-spk` uses Mongo 3.0. Mongo 2.x does not work - well for Sandstorm apps as it pre-allocates far too much disk space - expecting a large database; Mongo 3.x mostly avoids preallocation. The - differences should be invisible to your app. Note that apps built with - previous versions of `meteor-spk` can upgrade safely -- old grains will - automatically be migrated to Mongo 3 format on their first run. * If your app uses accounts, add the package [`kenton:accounts-sandstorm`](https://github.com/sandstorm-io/meteor-accounts-sandstorm) to integrate with Sandstorm's login system. (See also @@ -92,13 +91,5 @@ To package your existing Meteor app, do the following: ### Installing `meteor-spk` from source -1. Check out this github repository. Note that you must use the `--recursive` - flag to ensure that submodules are cloned as well: - - git clone --recursive https://github.com/sandstorm-io/meteor-spk.git - -2. Run `make`. -3. Add the directory to your `$PATH`, or symlink the `meteor-spk` script into - a directory in your `$PATH`, e.g.: - - ln -s $PWD/meteor-spk ~/bin +1. Check out this github repository. You can modify the the shell script `meteor-spk` directly. There are two other important files - `start.js` and `package.json` If you need +to modify them, they will need to be b64 encoded and put into `meteor-spk` at the appropriate spot. \ No newline at end of file diff --git a/gather-deps.sh b/gather-deps.sh deleted file mode 100755 index 16d417b..0000000 --- a/gather-deps.sh +++ /dev/null @@ -1,147 +0,0 @@ -#! /bin/bash - -# Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors -# Licensed under the MIT License: -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# This script gathers all of the binaries and libraries needed to run Meteor, -# but which aren't part of a normal Meteor bundle. -# -# We pull Node.js from the Meteor tools installation. -# -# We build a custom MongoDB binary using a special fork of Mongo which creates -# much smaller databases. This is necessary because Mongo by default -# pre-allocates many megabytes of space, but Sandstorm app instances should be -# individual documents and therefore small. (It would be nice to replace Mongo -# entirely with an in-process database; maybe based on Meteor's own -# "minimongo"...) -# -# We pull any needed libraries straight from the local system. - -set -euo pipefail - -if [ $# != 1 ]; then - echo "usage: $0 METEOR_VERSION" >&2 - exit 1 -fi -METEOR_RELEASE="METEOR@$1" - -mkdir -p tmp - -copyDep() { - # Copies a file from the system into the chroot. - - local FILE=$1 - local DST=bundle"${FILE/#\/usr\/local/\/usr}" - - if [ -e "$DST" ]; then - # already copied - : - elif [[ "$FILE" == /etc/* ]]; then - # We'll want to copy configuration (e.g. for DNS) from the host at runtime. - if [ -f "$FILE" ]; then - echo "$FILE" >> tmp/etc.list - fi - elif [ -h "$FILE" ]; then - # Symbolic link. - # We copy over the target, and recreate the link. - # Currently we denormalize the link because I'm not sure how to follow - # one link at a time in bash (since readlink without -f gives a relative - # path and I'm not sure how to interpret that against the link's path). - # I'm sure there's a way, but whatever... - mkdir -p $(dirname "$DST") - local LINK=$(readlink -f "$FILE") - ln -sf "${LINK/#\/usr\/local/\/usr}" "$DST" - copyDep "$LINK" - elif [ -d "$FILE" ]; then - # Directory. Make it, but don't copy contents; we'll do that later. - mkdir -p "$DST" - elif [ -f "$FILE" ]; then - # Regular file. Copy it over. - mkdir -p $(dirname "$DST") - cp "$FILE" "$DST" - fi -} - -copyDeps() { - # Reads filenames on stdin and copies them into the chroot. - - while read FILE; do - copyDep "$FILE" - done -} - -rm -rf bundle -mkdir bundle -METEOR_WAREHOUSE_DIR="${METEOR_WAREHOUSE_DIR:-$HOME/.meteor}" -echo -n "Finding meteor-tool installation (can take a few seconds)..." >&2 -TOOL_VERSION=$(meteor show --ejson $METEOR_RELEASE | grep '^ *"tool":' | - sed -re 's/^.*"(meteor-tool@[^"]*)".*$/\1/g') -TOOLDIR=$(echo $TOOL_VERSION | tr @ /) -echo " $TOOL_VERSION" >&2 -METEOR_DEV_BUNDLE=$(readlink -f $METEOR_WAREHOUSE_DIR/packages/$TOOLDIR/mt-os.linux.x86_64/dev_bundle) - -cp start.js bundle/start.js - -$METEOR_DEV_BUNDLE/bin/npm install - -# Extract node-capnp build from installed Sandstorm and shove it into node_modules. This makes -# Npm.require('capnp') "just work" for Meteor Sandstorm apps, which is convenient since it can -# be tedious to build otherwise. We also copy in the standard .capnp imports that people will -# need on Sandstorm, so that you can do e.g. require("sandstorm/grain.capnp"). -# -# Note that capnp.node and capnp.js have to got into programs/server/node_modules as Meteor will -# not search up the tree as of: https://github.com/meteor/meteor/pull/9095 -mkdir -p bundle/programs/server/node_modules -cp /opt/sandstorm/latest/node_modules/{capnp.node,capnp.js} bundle/programs/server/node_modules -cp -r /opt/sandstorm/latest/usr/include/{capnp,sandstorm} bundle/programs/server/node_modules - -mv node_modules bundle/node_modules - -# Copy over key binaries. -mkdir -p bundle/bin -cp niscu/mongod bundle/bin/niscud -cp mongo/mongod bundle/bin/ -cp $METEOR_DEV_BUNDLE/bin/node bundle/bin - -# Binaries copied from Meteor aren't writable by default. -chmod u+w bundle/bin/* - -# Copy over all necessary shared libraries. -(ldd bundle/bin/* $(find bundle -name '*.node') || true) | grep -o '[[:space:]]/[^ ]*' | copyDeps - -# Mongo wants these localization files. -mkdir -p bundle/usr/lib -cp -r /usr/lib/locale bundle/usr/lib -mkdir -p bundle/usr/share/locale -cp /usr/share/locale/locale.alias bundle/usr/share/locale - -# Due to a bug in Node 12, /proc/meminfo must exist otherwise the process will die at startup. -# However, it can be an empty file. See: https://github.com/nodejs/help/issues/2099 -mkdir bundle/proc -touch bundle/proc/meminfo - -# Make bundle smaller by stripping stuff. -strip bundle/bin/* -find bundle -name '*.so' | xargs strip - -rm -rf meteor-spk.deps -mv bundle meteor-spk.deps - From 34081fd8e44e02b031aeeec0a1cdfe12cf33e8b0 Mon Sep 17 00:00:00 2001 From: gischer Date: Fri, 12 Apr 2024 10:37:11 -0700 Subject: [PATCH 4/4] The actual update to meteor-spk --- meteor-spk | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/meteor-spk b/meteor-spk index d4bc8b3..b0a3d84 100755 --- a/meteor-spk +++ b/meteor-spk @@ -81,6 +81,18 @@ if [ $# = 0 ]; then exit 1 fi + # We replace the normal meteor start.js with our own version, which allows us + # to support Sandstorm operations such as updating a live grain. Both start.js + # and packages.json to install it correctly are embedded in this shell script + # in order for it to be standalone. + + writeStartJs() { + base64 -d >$DEPS_DIR/start.js <<< Ly8gQ29weXJpZ2h0IChjKSAyMDE0IFNhbmRzdG9ybSBEZXZlbG9wbWVudCBHcm91cCwgSW5jLiBhbmQgY29udHJpYnV0b3JzCi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZToKLy8KLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weQovLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwgdG8gZGVhbAovLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzCi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwKLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6Ci8vCi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluCi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLgovLwovLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgovLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTgovLyBUSEUgU09GVFdBUkUuCgovLyBBcHBsaWNhdGlvbiBzdGFydCBzY3JpcHQuIFRoaXMgbGF1bmNoZXMgTW9uZ28sIHRoZW4gZGVsZWdhdGVzIHRvIG1haW4uanMuCi8vIG1ldGVvci1zcGsgd2lsbCBhdXRvbWF0aWNhbGx5IGluY2x1ZGUgdGhpcyBpbiB5b3VyIHBhY2thZ2U7IHlvdSBkb24ndCBuZWVkCi8vIHRvIHdvcnJ5IGFib3V0IGl0LgovLwovLyBUaGUgb3JpZ2luYWwgdmVyc2lvbiBvZiBtZXRlb3Itc3BrIHVzZWQgTmlzY3VbMV0sIGEgZm9yayBvZiBNb25nbyB0aGF0IGFkanVzdHMKLy8gc29tZSBjb21waWxlZC1pbiBjb25zdGFudHMgdG8gb3B0aW1pemUgZm9yIGEgc21hbGwgZGlzayBmb290cHJpbnQuIEFzIG9mIE1vbmdvIDMuMCwKLy8gd2Ugbm8gbG9uZ2VyIG5lZWQgTmlzY3UsIGJlY2F1c2UgdGhlIFdpcmVkVGlnZXIgc3RvcmFnZSBlbmdpbmUgY2FuIGJlIGNvbmZpZ3VyZWQKLy8gdG8gc3VpdCBvdXIgbmVlZHMuIFRoaXMgc2NyaXB0IHBlcmZvcm1zIHRoZSBtaWdyYXRpb24gZnJvbSBOaXNjdSB0byBNb25nbyAzLjAsCi8vIGlmIG5lY2Vzc2FyeS4KLy8KLy8gWzFdIGh0dHBzOi8vZ2l0aHViLmNvbS9rZW50b252L21vbmdvL3RyZWUvbmlzY3UKCnZhciBjaGlsZF9wcm9jZXNzID0gcmVxdWlyZSgiY2hpbGRfcHJvY2VzcyIpOwp2YXIgZnMgPSByZXF1aXJlKCJmcyIpOwp2YXIgUHJvbWlzZSA9IHJlcXVpcmUoImVzNi1wcm9taXNlIikuUHJvbWlzZTsKdmFyIE1vbmdvQ2xpZW50ID0gcmVxdWlyZSgnbW9uZ29kYicpLk1vbmdvQ2xpZW50OwoKdmFyIGFwcFBvcnQgPSAiNDAwMCI7CnZhciBtb25nb1BvcnQgPSAiNDAwMSI7CnZhciBuaXNjdVBvcnQgPSAiNDAwMiI7CmlmIChwcm9jZXNzLmFyZ3YubGVuZ3RoID4gMykgewogIC8vIFlvdSBjYW4gcGFzcyBpbiBhIHBvcnQgbnVtYmVyIGZvciB0aGUgYXBwIHRvIGxpc3RlbiBvbjoKICAvLyBgbm9kZSBzdGFydC5qcyAtcCA8cG9ydCBudW1iZXI+YAogIGlmIChwcm9jZXNzLmFyZ3ZbMl0gIT09ICItcCIpIHsKICAgIHRocm93IG5ldyBFcnJvcigiLXAgaXMgdGhlIG9ubHkgb3B0aW9uIGN1cnJlbnRseSBzdXBwb3J0ZWQiKTsKICB9CiAgdmFyIGFwcFBvcnROdW0gPSBwYXJzZUludChwcm9jZXNzLmFyZ3ZbM10pOwogIGlmIChpc05hTihhcHBQb3J0TnVtKSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJjb3VsZCBub3QgcGFyc2UgYSBwb3J0IG51bWJlciBmcm9tOiAiICsgcHJvY2Vzcy5hcmd2WzJdKTsKICB9CiAgYXBwUG9ydCA9IGFwcFBvcnROdW0udG9TdHJpbmcoKTsKICBtb25nb1BvcnQgPSAoYXBwUG9ydE51bSArIDEpLnRvU3RyaW5nKCk7CiAgbmlzY3VQb3J0ID0gKGFwcFBvcnROdW0gKyAyKS50b1N0cmluZygpOwp9Cgp2YXIgZGJQYXRoID0gIi92YXIvd2lyZWRUaWdlckRiIgoKZnVuY3Rpb24gcnVuQ2hpbGRQcm9jZXNzKGNoaWxkLCBuYW1lLCBjb250aW51YXRpb24pIHsKLy8gUnVucyB0aGUgcHJvY2VzcyB1bnRpbCBpdCBleGl0cyBzdWNjZXNzZnVsbHkuIFRoZW4gY2FsbHMgdGhlIGNvbnRpbnVhdGlvbi4KICBjaGlsZC5vbigiZXJyb3IiLCBmdW5jdGlvbiAoZXJyKSB7CiAgICBjb25zb2xlLmVycm9yKCJlcnJvciBpbiAiICsgbmFtZSArICI6ICIgICsgZXJyLnN0YWNrKTsKICAgIHByb2Nlc3MuZXhpdCgxKTsKICB9KTsKCiAgY2hpbGQub24oImV4aXQiLCBmdW5jdGlvbiAoY29kZSwgc2lnbmFsKSB7CiAgICBpZiAoc2lnbmFsKSB7CiAgICAgIGNvbnNvbGUuZXJyb3IobmFtZSArICIgZmFpbGVkIHdpdGggc2lnbmFsOiAiICsgc2lnbmFsKTsKICAgICAgcHJvY2Vzcy5leGl0KDEpOwogICAgfQogICAgaWYgKGNvZGUgIT09IDApIHsKICAgICAgY29uc29sZS5lcnJvcihuYW1lICsgIiBleGl0ZWQgd2l0aCBlcnJvciBjb2RlOiAiICsgY29kZSk7CiAgICAgIHByb2Nlc3MuZXhpdCgxKTsKICAgIH0KICAgIGNvbnRpbnVhdGlvbigpOwogIH0pOwp9CgpmdW5jdGlvbiBzdGFydE1vbmdvKGNvbnRpbnVhdGlvbikgewogIGNvbnNvbGUubG9nKCIqKiBTdGFydGluZyBNb25nby4uLiIpOwogIHZhciBkYiA9IGNoaWxkX3Byb2Nlc3Muc3Bhd24oIi9iaW4vbW9uZ29kIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsgIi0tZm9yayIsICItLXBvcnQiLCBtb25nb1BvcnQsICItLWRicGF0aCIsIGRiUGF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIi0tbm9hdXRoIiwgIi0tYmluZF9pcCIsICIxMjcuMC4wLjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLS1zdG9yYWdlRW5naW5lIiwgIndpcmVkVGlnZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLS13aXJlZFRpZ2VyRW5naW5lQ29uZmlnU3RyaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImxvZz0ocHJlYWxsb2M9ZmFsc2UsZmlsZV9tYXg9MjAwS0IpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIi0td2lyZWRUaWdlckNhY2hlU2l6ZUdCIiwgIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLS1sb2dwYXRoIiwgZGJQYXRoICsgIi9tb25nby5sb2ciIF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IHN0ZGlvOiAiaW5oZXJpdCIgfSk7CgogIHJ1bkNoaWxkUHJvY2VzcyhkYiwgIk1vbmdvIiwgY29udGludWF0aW9uKTsKfQoKZnVuY3Rpb24gcnVuQXBwKCkgewogIGNvbnNvbGUubG9nKCIqKiBTdGFydGluZyBNZXRlb3IuLi4iKTsKICBwcm9jZXNzLmVudi5NT05HT19VUkw9Im1vbmdvZGI6Ly8xMjcuMC4wLjE6IiArIG1vbmdvUG9ydCArICIvbWV0ZW9yIjsKICBwcm9jZXNzLmVudi5ST09UX1VSTD0iaHR0cDovLzEyNy4wLjAuMToiICsgYXBwUG9ydDsKICBwcm9jZXNzLmVudi5QT1JUPWFwcFBvcnQ7CiAgcmVxdWlyZSgiLi9tYWluLmpzIik7Cn0KCnZhciBtaWdyYXRpb25EdW1wUGF0aCA9ICIvdmFyL21pZ3JhdGlvbk1vbmdvRHVtcCI7Ci8vIEJhY2sgd2hlbiB3ZSB1c2VkIG1vbmdvZHVtcCBmb3IgbWlncmF0aW9uLCB0aGlzIHdhcyBhIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBkdW1wZWQgZGF0YS4KLy8gTm93IGl0J3MganVzdCBhbiBlbXB0eSBmaWxlLCB0aGUgZXhpc3RlbmNlIG9mIHdoaWNoIGltcGxpZXMgdGhhdCBhIG1pZ3JhdGlvbiBpcyBpbiBwcm9ncmVzcy4KCmlmIChmcy5leGlzdHNTeW5jKGRiUGF0aCkgJiYgIWZzLmV4aXN0c1N5bmMobWlncmF0aW9uRHVtcFBhdGgpKSB7CiAgc3RhcnRNb25nbyhydW5BcHApOwp9IGVsc2UgewogIC8vIFRoZSBvbGQgZGF0YWJhc2Ugd2FzIGluIC92YXIuCiAgaWYgKCFmcy5leGlzdHNTeW5jKCIvdmFyL2pvdXJuYWwiKSkgewogICAgLy8gTm8gbWlncmF0aW9uIHJlcXVpcmVkLgogICAgZnMubWtkaXJTeW5jKGRiUGF0aCk7CiAgICBzdGFydE1vbmdvKHJ1bkFwcCk7CiAgfSBlbHNlIHsKICAgIGNvbnNvbGUubG9nKCJTdGFydGluZyBtaWdyYXRpb24gdG8gV2lyZWRUaWdlciBzdG9yYWdlIGVuZ2luZS4uLiIpOwoKICAgIGlmIChmcy5leGlzdHNTeW5jKG1pZ3JhdGlvbkR1bXBQYXRoKSkgewogICAgICBjb25zb2xlLmxvZygiSXQgbG9va3MgbGlrZSBhIHByZXZpb3VzIGF0dGVtcHQgdG8gbWlncmF0ZSBmYWlsZWQuIENsZWFuaW5nIGl0IHVwLi4uIik7CiAgICAgIHZhciBub3cgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpOwogICAgICBpZiAoZnMuZXhpc3RzU3luYyhkYlBhdGgpKSB7CiAgICAgICAgZnMucmVuYW1lU3luYyhkYlBhdGgsICIvdmFyL2ZhaWxlZE1pZ3JhdGlvbiIgKyBub3cpOwogICAgICB9CiAgICAgIGZzLnJlbmFtZVN5bmMobWlncmF0aW9uRHVtcFBhdGgsICIvdmFyL2ZhaWxlZE1pZ3JhdGlvbkR1bXAiICsgbm93KTsKICAgICAgLy8gQ2FuJ3QganVzdCBjYWxsIHVubGlua1N5bmMoKSBiZWNhdXNlIGl0IG1pZ2h0IGJlIGEgZGlyZWN0b3J5IHdpdGggbW9uZ29kdW1wIGNvbnRlbnRzLgogICAgfQogICAgZnMud3JpdGVGaWxlU3luYyhtaWdyYXRpb25EdW1wUGF0aCwgIiIpOwoKICAgIGNvbnNvbGUubG9nKCJsYXVuY2hpbmcgbmlzY3VkIik7CiAgICB2YXIgb2xkRGJQcm9jZXNzID0gY2hpbGRfcHJvY2Vzcy5zcGF3bigiL2Jpbi9uaXNjdWQiLCBbICItLWZvcmsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLS1wb3J0IiwgbmlzY3VQb3J0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLS1kYnBhdGgiLCAiL3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICItLW5vYXV0aCIsICItLWJpbmRfaXAiLCAiMTI3LjAuMC4xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIi0tbm9odHRwaW50ZXJmYWNlIiwgIi0tbm9wcmVhbGxvYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICItLWxvZ3BhdGgiLCAiL3Zhci9tb25nby5sb2ciIF0sIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGRpbzogImluaGVyaXQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgZnMubWtkaXJTeW5jKGRiUGF0aCk7CiAgICBydW5DaGlsZFByb2Nlc3Mob2xkRGJQcm9jZXNzLCAibmlzdWNkIiwgZnVuY3Rpb24gKCkgewogICAgICBzdGFydE1vbmdvKGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgbmlzY3VVcmwgPSAibW9uZ29kYjovLzEyNy4wLjAuMToiICsgbmlzY3VQb3J0ICsgIi9tZXRlb3IiOwogICAgICAgIHZhciBtb25nb1VybCA9ICJtb25nb2RiOi8vMTI3LjAuMC4xOiIgKyBtb25nb1BvcnQgKyAiL21ldGVvciI7CgogICAgICAgIC8vIEFmdGVyIGBtb25nb2QgLS1mb3JrYCByZXR1cm5zLCB3ZSBzdGlsbCBuZWVkIHRvIHdhaXQgYSBiaXQgYmVmb3JlIG1vbmdvZCBpcyBsaXN0ZW5pbmcuIDooCiAgICAgICAgdmFyIHdhaXRGb3JMaXN0ZW4gPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyByZXNvbHZlKCk7IH0sIDEwMDApOwogICAgICAgIH0pOwogICAgICAgIHdhaXRGb3JMaXN0ZW4udGhlbihmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBNb25nb0NsaWVudC5jb25uZWN0KG5pc2N1VXJsLCB7fSkudGhlbihmdW5jdGlvbihvbGREYikgewogICAgICAgICAgICByZXR1cm4gTW9uZ29DbGllbnQuY29ubmVjdChtb25nb1VybCwge30pLnRoZW4oZnVuY3Rpb24obmV3RGIpIHsKICAgICAgICAgICAgICByZXR1cm4ge29sZERiOiBvbGREYiwgbmV3RGI6IG5ld0RifTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChkYnMpIHsKICAgICAgICAgIHJldHVybiBkYnMub2xkRGIuY29sbGVjdGlvbnMoKS50aGVuKGZ1bmN0aW9uIChvbGRDb2xsZWN0aW9ucykgewogICAgICAgICAgICB2YXIgY29sbGVjdGlvblByb21pc2VzID0gW107CiAgICAgICAgICAgIG9sZENvbGxlY3Rpb25zLmZvckVhY2goZnVuY3Rpb24ob2xkQ29sbGVjdGlvbikgewogICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJjb2xsZWN0aW9uOiAiICsgb2xkQ29sbGVjdGlvbi5jb2xsZWN0aW9uTmFtZSk7CiAgICAgICAgICAgICAgaWYgKG9sZENvbGxlY3Rpb24uY29sbGVjdGlvbk5hbWUuc2xpY2UoMCwgNykgID09PSAic3lzdGVtLiIpIHsKICAgICAgICAgICAgICAgIC8vIElnbm9yZSBzeXN0ZW0uaW5kZXhlcyBhbmQgb3RoZXIgc3BlY2lhbCBjb2xsZWN0aW9ucy4KICAgICAgICAgICAgICAgIC8vIElmIHRoZSBhcHAgdXNlcyBjcmVhdGVJbmRleCgpIG9yIGVuc3VyZUluZGV4KCkgc2Vuc2libHksIHRoZSBpbmRleGVzCiAgICAgICAgICAgICAgICAvLyBzaG91bGQgYmUgcmVnZW5lcmF0ZWQgb24gdGhlIG5leHQgc3RhcnQgb2YgdGhlIGFwcC4KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdmFyIHByb21pc2UgPSBkYnMubmV3RGIuY3JlYXRlQ29sbGVjdGlvbihvbGRDb2xsZWN0aW9uLmNvbGxlY3Rpb25OYW1lKQogICAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAobmV3Q29sbGVjdGlvbikgewogICAgICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0aW9uTG9vcChjdXJzb3IpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnNvci5oYXNOZXh0KCkudGhlbihmdW5jdGlvbiAoaGFzTmV4dCkgewogICAgICAgICAgICAgICAgICAgIGlmIChoYXNOZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3Vyc29yLm5leHQoKS50aGVuKGZ1bmN0aW9uIChkb2MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ld0NvbGxlY3Rpb24uaW5zZXJ0T25lKGRvYykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydGlvbkxvb3AoY3Vyc29yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydGlvbkxvb3Aob2xkQ29sbGVjdGlvbi5maW5kKCkpOwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGNvbGxlY3Rpb25Qcm9taXNlcy5wdXNoKHByb21pc2UpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKGNvbGxlY3Rpb25Qcm9taXNlcykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgZGJzLm9sZERiLmFkbWluKCkuY29tbWFuZCh7c2h1dGRvd246IDF9KTsKICAgICAgICAgICAgICAvLyBXZSBkb24ndCB3YWl0IGZvciBzdWNjZXNzIG9mIHRoaXMgY29tbWFuZCBiZWNhdXNlIHRoZSBzZXJ2ZXIga2lsbHMgaXRzZWxmCiAgICAgICAgICAgICAgLy8gYmVmb3JlIGl0IHNlbmRzIGEgY29uZmlybWF0aW9uLgoKICAgICAgICAgICAgICBmcy51bmxpbmtTeW5jKG1pZ3JhdGlvbkR1bXBQYXRoKTsKICAgICAgICAgICAgICAvLyBTdWNjZXNzIQoKICAgICAgICAgICAgICBydW5BcHAoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICB9KS5jYXRjaChmdW5jdGlvbihlKSB7CiAgICAgICAgICBjb25zb2xlLmxvZygiZXJyb3I6ICIgKyBlKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICB9Cn0K + } + + writePackageJson() { + base64 -d >$DEPS_DIR/package.json <<