Skip to content
This repository was archived by the owner on May 16, 2021. It is now read-only.

Commit abb4c45

Browse files
committed
Revert "Remove Duplicate Unnecessary Files"
This reverts commit feafc5c.
1 parent 9489b19 commit abb4c45

File tree

2 files changed

+364
-0
lines changed

2 files changed

+364
-0
lines changed

bin/README.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Kamanda - A Firebase CLI Companion Tool
2+
3+
[![npm](https://img.shields.io/npm/v/kamanda)](https://www.npmjs.com/package/kamanda)
4+
[![](https://img.shields.io/github/release/mainawycliffe/kamanda.svg)](https://github.com/mainawycliffe/kamanda/releases/latest)
5+
[![](https://github.com/mainawycliffe/kamanda/workflows/Go%20Tests/badge.svg)](https://github.com/mainawycliffe/kamanda/actions?query=workflow%3A%22Go+Tests%22)
6+
[![](https://github.com/mainawycliffe/kamanda/workflows/Go%20Linting/badge.svg)](https://github.com/mainawycliffe/kamanda/actions?query=workflow%3A%22Go+Linting%22)
7+
[![](https://github.com/mainawycliffe/kamanda/workflows/Go%20Release/badge.svg)](https://github.com/mainawycliffe/kamanda/actions?query=workflow%3A%22Go+Release%22)
8+
[![](https://github.com/mainawycliffe/kamanda/workflows/npm%20publish/badge.svg)](https://github.com/mainawycliffe/kamanda/actions?query=workflow%3A%22npm+publish%22)
9+
10+
Kamanda is an open source tool is meant to provide additional functionality not provided by Firebase
11+
CLI such as Managing Users of your Projects, Exporting and Importing of Cloud
12+
Firestore Data.
13+
14+
> This is not meant to replace Firebase CLI but to compliment it.
15+
16+
## Table of Content <!-- omit in toc -->
17+
18+
- [Why?](#why)
19+
- [Installation](#installation)
20+
- [Using npm (Node Package Manager)](#using-npm-node-package-manager)
21+
- [Executable Binaries](#executable-binaries)
22+
- [Usage](#usage)
23+
- [Documentation](#documentation)
24+
- [CI Environment](#ci-environment)
25+
- [Multiple Project Support](#multiple-project-support)
26+
- [Features](#features)
27+
- [Work in Progress](#work-in-progress)
28+
- [Contributors](#contributors)
29+
- [Roadmap](#roadmap)
30+
31+
## Why?
32+
33+
Kamanda is meant to make your work as developer easier by providing with well
34+
built tools to help you manage your Firebase project quickly.
35+
36+
For instance you want to create a new admin user for your Firebase App, you can
37+
use Kamanda to quickly add the user and attach the necessary custom claims. You
38+
can also attach or remove a users custom claims, view list of users among other
39+
functionality currently available for Firebase Auth.
40+
41+
In future as Kamanda gains support for Firestore, it will give you can easy way
42+
to explore, export, import and manipulate your Firestore documents, right from
43+
the cloud without writing extra code.
44+
45+
## Installation
46+
47+
> This is still an early version, feedback on improvements is much needed.
48+
49+
### Using npm (Node Package Manager)
50+
51+
You can use npm to install Kamanda:
52+
53+
```sh
54+
npm -g install kamanda
55+
```
56+
57+
> NB: At the moment, it doesn't work with yarn, I am working on a solution for this.
58+
59+
To check if installation was completed successfully, run the following
60+
command:
61+
62+
```sh
63+
kamanda version
64+
```
65+
66+
You can view all supported commands [here](./docs/kamanda.md) or by running `kamanda help`
67+
68+
```sh
69+
kamanda help
70+
```
71+
72+
### Executable Binaries
73+
74+
You can find the latest binaries for your operating system in the
75+
[releases](https://github.com/mainawycliffe/kamanda/releases).
76+
77+
## Usage
78+
79+
There are a few things to keep in minds, Kamanda works inside a Firebase Project
80+
and not outside and is meant to provide extra functionality and not replace
81+
Firebase CLI.
82+
83+
First you will need to login just like Firebase CLI, this provides Kamanda with
84+
the credentials it requires in order to perform most of the tasks.
85+
86+
You can login by running the following command:
87+
88+
```sh
89+
kamanda login
90+
```
91+
92+
> Kamanda mimics Firebase in this regard, so all authentication commands work
93+
similar to Firebase CLI Authentication commands.
94+
95+
Login to your Google Account and Give Kamanda the permission it requires. As of
96+
now, you might get a warning from Google, I am working to have the app verified
97+
as soon as possible.
98+
99+
![Unsafe App Screen](docs/images/unsafe_app.png)
100+
101+
> Kamanda is a fully open source project, no information is corrected at any time.
102+
103+
### Documentation
104+
105+
Documentation for this project can be found [here](https://kamanda.dev).
106+
107+
### CI Environment
108+
109+
If you are in CI environment, you can use the `--token` flag to pass the
110+
firebase refresh token without login in. You can acquire the refresh token by
111+
running `kamanda login:ci`.
112+
113+
### Multiple Project Support
114+
115+
Kamanda also support multiple Firebase project within the same workspace just
116+
like `firebase cli`. You can use the `--project` flag to pass either the project
117+
name or project alias you wish to execute the command on. If the flag is not
118+
specified, Kamanda uses the `default` project with the workspace. This is
119+
usually specified inside the `.firebaserc` file at the root of you workspace.
120+
Please note, Kamanda cannot be used to setup multiple projects, this can only be
121+
done using Firebase CLI.
122+
123+
## Features
124+
125+
- Firebase Auth Users:
126+
- Add Single Users - Ideal for adding a user quickly
127+
- Edit, Delete a User Account By ID
128+
- Get a user by UID or Email Address
129+
- Add Custom Claims to a User Account
130+
- Add User by Bulk using a JSON/Yaml File
131+
- List Users
132+
133+
## Work in Progress
134+
135+
Its still a work in progress, I hope to wrap the first few features in
136+
the coming weeks (mid april at the latest).
137+
138+
## Contributors
139+
140+
Contributions are always welcome.
141+
142+
## Roadmap
143+
144+
This is currently our roadmap, please feel free to request additions/changes.
145+
146+
| Feature | Progress |
147+
| ---------------- | -------- |
148+
| Firebase Auth | ✔✔ |
149+
| Cloud Firestore | 🔜 |
150+
| Firebase Storage | 🔜 |

bin/index.js

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
#!/usr/bin/env node
2+
3+
4+
"use strict";
5+
6+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
7+
8+
var request = require("request"),
9+
path = require("path"),
10+
unzipper = require("unzipper"),
11+
mkdirp = require("mkdirp"),
12+
fs = require("fs"),
13+
exec = require("child_process").exec;
14+
15+
// Mapping from Node's `process.arch` to Golang's `$GOARCH`
16+
var ARCH_MAPPING = {
17+
ia32: "386",
18+
x64: "amd64",
19+
arm: "arm"
20+
};
21+
22+
// Mapping between Node's `process.platform` to Golang's
23+
var PLATFORM_MAPPING = {
24+
darwin: "darwin",
25+
linux: "linux",
26+
win32: "windows",
27+
freebsd: "freebsd"
28+
};
29+
30+
function getInstallationPath(callback) {
31+
// `$npm_execpath bin` will output the path where binary files should be installed
32+
// using whichever package manager is current
33+
var execPath = process.env.npm_execpath;
34+
var packageManager = execPath && execPath.includes("yarn") ? "yarn global" : "npm";
35+
exec(packageManager + " bin", function (err, stdout, stderr) {
36+
var dir = null;
37+
if (err || stderr && !stderr.includes("No license field") || !stdout || stdout.length === 0) {
38+
// We couldn't infer path from `npm bin`. Let's try to get it from
39+
// Environment variables set by NPM when it runs.
40+
// npm_config_prefix points to NPM's installation directory where `bin` folder is available
41+
// Ex: /Users/foo/.nvm/versions/node/v4.3.0
42+
var env = process.env;
43+
if (env && env.npm_config_prefix) {
44+
dir = path.join(env.npm_config_prefix, "bin");
45+
}
46+
} else {
47+
dir = stdout.trim();
48+
}
49+
50+
mkdirp.sync(dir);
51+
52+
callback(null, dir);
53+
});
54+
}
55+
56+
function verifyAndPlaceBinary(binName, binPath, callback) {
57+
if (!fs.existsSync(path.join(binPath, binName))) return callback("Downloaded binary does not contain the binary specified in configuration - " + binName);
58+
59+
getInstallationPath(function (err, installationPath) {
60+
if (err) return callback("Error getting binary installation path from `npm bin`");
61+
62+
// Move the binary file
63+
fs.renameSync(path.join(binPath, binName), path.join(installationPath, binName));
64+
65+
callback(null);
66+
});
67+
}
68+
69+
function validateConfiguration(packageJson) {
70+
if (!packageJson.version) {
71+
return "'version' property must be specified";
72+
}
73+
74+
if (!packageJson.goBinary || _typeof(packageJson.goBinary) !== "object") {
75+
return "'goBinary' property must be defined and be an object";
76+
}
77+
78+
if (!packageJson.goBinary.name) {
79+
return "'name' property is necessary";
80+
}
81+
82+
if (!packageJson.goBinary.path) {
83+
return "'path' property is necessary";
84+
}
85+
86+
if (!packageJson.goBinary.url) {
87+
return "'url' property is required";
88+
}
89+
90+
// if (!packageJson.bin || typeof(packageJson.bin) !== "object") {
91+
// return "'bin' property of package.json must be defined and be an object";
92+
// }
93+
}
94+
95+
function parsePackageJson() {
96+
if (!(process.arch in ARCH_MAPPING)) {
97+
console.error("Installation is not supported for this architecture: " + process.arch);
98+
return;
99+
}
100+
101+
if (!(process.platform in PLATFORM_MAPPING)) {
102+
console.error("Installation is not supported for this platform: " + process.platform);
103+
return;
104+
}
105+
106+
var packageJsonPath = path.join(".", "package.json");
107+
if (!fs.existsSync(packageJsonPath)) {
108+
console.error("Unable to find package.json. " + "Please run this script at root of the package you want to be installed");
109+
return;
110+
}
111+
112+
var packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
113+
var error = validateConfiguration(packageJson);
114+
if (error && error.length > 0) {
115+
console.error("Invalid package.json: " + error);
116+
return;
117+
}
118+
119+
// We have validated the config. It exists in all its glory
120+
var binName = packageJson.goBinary.name;
121+
var binPath = packageJson.goBinary.path;
122+
var url = packageJson.goBinary.url;
123+
var version = packageJson.version;
124+
if (version[0] === "v") version = version.substr(1); // strip the 'v' if necessary v0.0.1 => 0.0.1
125+
126+
// Binary name on Windows has .exe suffix
127+
if (process.platform === "win32") {
128+
binName += ".exe";
129+
}
130+
131+
// Interpolate variables in URL, if necessary
132+
url = url.replace(/{{arch}}/g, ARCH_MAPPING[process.arch]);
133+
url = url.replace(/{{platform}}/g, PLATFORM_MAPPING[process.platform]);
134+
url = url.replace(/{{version}}/g, version);
135+
url = url.replace(/{{bin_name}}/g, binName);
136+
137+
return {
138+
binName: binName,
139+
binPath: binPath,
140+
url: url,
141+
version: version
142+
};
143+
}
144+
145+
/**
146+
* Reads the configuration from application's package.json,
147+
* validates properties, downloads the binary, untars, and stores at
148+
* ./bin in the package's root. NPM already has support to install binary files
149+
* specific locations when invoked with "npm install -g"
150+
*
151+
* See: https://docs.npmjs.com/files/package.json#bin
152+
*/
153+
function install(callback) {
154+
var opts = parsePackageJson();
155+
if (!opts) {
156+
return callback("Invalid inputs");
157+
}
158+
mkdirp.sync(opts.binPath);
159+
console.log("Downloading from URL: " + opts.url);
160+
var req = request({ uri: opts.url });
161+
req.on("error", callback.bind(null, "Error downloading from URL: " + opts.url));
162+
req.on("response", function (res) {
163+
if (res.statusCode !== 200) {
164+
return callback("Error downloading binary. HTTP Status Code: " + res.statusCode);
165+
}
166+
req.pipe(unzipper.Extract({ path: opts.binPath })).on("error", callback)
167+
// First we will Un-GZip, then we will untar. So once untar is completed,
168+
// binary is downloaded into `binPath`. Verify the binary and call it good
169+
.on("close", verifyAndPlaceBinary.bind(null, opts.binName, opts.binPath, callback));
170+
});
171+
}
172+
173+
function uninstall(callback) {
174+
var opts = parsePackageJson();
175+
getInstallationPath(function (err, installationPath) {
176+
if (err) callback("Error finding Kamanda installation directory");
177+
178+
try {
179+
fs.unlinkSync(path.join(installationPath, opts.binName));
180+
} catch (ex) {
181+
// Ignore errors when deleting the file.
182+
}
183+
184+
return callback(null);
185+
});
186+
}
187+
188+
// Parse command line arguments and call the right method
189+
var actions = {
190+
install: install,
191+
uninstall: uninstall
192+
};
193+
194+
var argv = process.argv;
195+
if (argv && argv.length > 2) {
196+
var cmd = process.argv[2];
197+
if (!actions[cmd]) {
198+
console.log("Invalid command to go-npm. `install` and `uninstall` are the only supported commands");
199+
process.exit(1);
200+
}
201+
202+
actions[cmd](function (err) {
203+
if (err) {
204+
console.error(err);
205+
process.exit(1);
206+
} else {
207+
process.exit(0);
208+
}
209+
});
210+
}
211+
212+
// this code is thanks to:
213+
// https://github.com/jumoel/go-npm/blob/feat/yarn-support/src/index.js and
214+
// https://github.com/sanathkr/go-npm

0 commit comments

Comments
 (0)