initial commit

This commit is contained in:
Pooya Parsa
2021-07-06 11:39:15 +02:00
commit a5b6b7fddb
11 changed files with 4186 additions and 0 deletions

5
.eslintrc Normal file
View File

@@ -0,0 +1,5 @@
{
"extends": [
"@nuxtjs/eslint-config-typescript"
]
}

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
*.log*
dist

77
README.md Normal file
View File

@@ -0,0 +1,77 @@
# 🥭 mongoz
> Ad hoc MongoDB server for Node.js
## Why?
[MongoDB](https://www.mongodb.com) is fantastic but setup for small projects can be lots of trouble.
This little package does everything necessary to download and start a fresh mongo server!
## Usage
**Note:** You need to have [Node.js](https://nodejs.org/en/) and [npm](https://docs.npmjs.com/cli/v7/commands/npm) already installed!
**Note:** Make sure there is not already a local mongodb server listening on default port (`2701`). If you do, either stop it or use `PORT` environment variable to change the port.
### Standalone Server
Let's start a fresh mongoz shall we?
```sh
npx mongoz
```
It will take few seconds on first time of usage to install and extract mongo server.
### Programmatic Usage
Do you need a MongoDB server? No problems!
```js
// CommonJS
const { startMongo } = require('mongoz')
// ESM
import { startMongo } from 'mongoz'
// Install and start listening MongoDB on 127.0.0.1:27017 in background
await startMongo()
```
When closing server, mongo will also gracefully shutdown with [node-graceful-shutdown](https://www.npmjs.com/package/node-graceful-shutdown).
### In parallel with server
You can also use [concurrently](https://www.npmjs.com/package/concurrently) to start mongo alongside with server:
`package.json`:
```json
{
"scripts": {
"start": "concurrently 'npx mongoz' 'node ./server.mjs'"
}
}
```
Or directly with `npx`:
```sh
npx concurrently 'npx mongoz' 'node ./server.mjs'
```
## Supported platforms
Windows, Linux and Darwin (Mac) are supported. Check [formula](./src/formula) for details.
## Changing data dir
By default, we use a temporary directory to store data and logs. You can customize it with `MONGO_DIR` environment variable.
## License
MIT.
See [MongoDB Licensing](https://www.mongodb.com/community/licensing) for underlying server license.

3
bin/mongoz Executable file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../dist/cli')

10
build.config.ts Normal file
View File

@@ -0,0 +1,10 @@
import { defineBuildConfig } from 'unbuild'
export default defineBuildConfig({
declaration: true,
entries: [
'./src/cli',
'./src/index'
],
inlineDependencies: true
})

39
package.json Normal file
View File

@@ -0,0 +1,39 @@
{
"name": "mongoz",
"version": "0.0.0",
"repository": "unjs/mongoz",
"license": "MIT",
"main": "./dist/index.js",
"exports": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"bin": "./bin/mongoz",
"files": [
"dist",
"bin"
],
"scripts": {
"lint": "eslint --ext .ts,.js",
"prepack": "unbuild",
"dev": "jiti ./src/cli.ts",
"start": "npx concurrently 'yarn dev' 'node server.mjs'",
"release": "yarn test && standard-version && git push --follow-tags && npm publish",
"test": "yarn lint"
},
"dependencies": {
"download": "^8.0.0",
"ora": "^5.4.1",
"decompress": "^4.2.1",
"consola": "^2.15.3",
"fs-extra": "^10.0.0",
"node-graceful-shutdown": "^1.1.0"
},
"devDependencies": {
"@nuxtjs/eslint-config-typescript": "^6.0.1",
"eslint": "^7.30.0",
"execa": "^5.1.1",
"jiti": "^1.10.1",
"standard-version": "^9.3.0",
"typescript": "^4.3.5",
"unbuild": "^0.3.1"
}
}

11
src/cli.ts Normal file
View File

@@ -0,0 +1,11 @@
import { startMongo } from './index'
async function main() {
const args = process.argv.splice(2)
const mongoserver = await startMongo({ args })
}
main().catch(err => {
console.error(err)
process.exit(1)
})

21
src/formula.ts Normal file
View File

@@ -0,0 +1,21 @@
export const mongoFormula = {
name: 'mongo',
version: '4.4.2',
port: 27017,
exec: 'bin/mongod',
execArgs: '--port {port} --dbpath {data}',
platforms: [
{
name: 'linux',
source: 'https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-4.4.2.tgz'
},
{
name: 'win32',
source: 'https://fastdl.mongodb.org/windows/mongodb-windows-x86_64-4.4.2.zip'
},
{
name: 'darwin',
source: 'https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.4.2.tgz'
}
]
}

84
src/index.ts Normal file
View File

@@ -0,0 +1,84 @@
import path from 'path'
import os from 'os'
import fsExtra from 'fs-extra'
import download from 'download'
import consola from 'consola'
import decompress from 'decompress'
import execa from 'execa'
import ora from 'ora'
import { onShutdown } from 'node-graceful-shutdown'
import { mongoFormula as formula } from './formula'
export async function startMongo (opts = { args: null }) {
const platformName = process.platform
let platform = formula.platforms.find(p => p.name === platformName)
if (!platform) {
throw new Error(`Platform '${platformName}' is not available for '${formula.name}'`)
}
const instanceName = 'default'
const appDir = process.env.MONGO_DIR || path.resolve(os.tmpdir(), formula.name)
// Resolve paths
const dataDir = path.resolve(appDir, 'data', instanceName, formula.name)
const logsDir = path.resolve(appDir, 'logs', instanceName, formula.name)
const logFile = path.resolve(logsDir, 'logs.txt')
const sourceDir = path.resolve(appDir, 'source', formula.name, formula.version, platform.name)
const sourceFileName = `${formula.name}-${formula.version}-${platform.name}` + path.extname(platform.source)
const sourceFile = path.resolve(sourceDir, sourceFileName)
const extractDir = path.resolve(sourceDir, 'unpacked')
const execFile = path.resolve(extractDir, formula.exec)
// Ensure data dir exists
await fsExtra.mkdirp(dataDir)
// Show a spinner
const spinner = ora()
// Ensure package is installed
if (!fsExtra.existsSync(extractDir) || !fsExtra.existsSync(execFile)) {
if (!fsExtra.existsSync(sourceFile)) {
const dlMessage = `Downloading ${sourceFileName}`
spinner.start(dlMessage + '...')
const res = download(platform.source, sourceDir, { filename: sourceFileName })
res.on('downloadProgress', (e) => {
spinner.text = `${dlMessage} | ${Math.round(e.percent * 100)}%`
})
await res
}
spinner.start(`Decompressing ${sourceFileName}...`)
await decompress(sourceFile, extractDir, { strip: 1 })
spinner.stop()
}
await fsExtra.mkdirp(logsDir)
await fsExtra.remove(logFile)
// Open logs file
let stdout, stderr
const logsFile = await fsExtra.open(logFile, 'w+')
stdout = stderr = logsFile
consola.info(`Writing logs to: ${logFile}`)
// Port and args
const port = process.env.PORT || formula.port
const execArgs = formula.execArgs.replace('{port}', port + '').replace('{data}', dataDir).split(' ')
if (Array.isArray(opts.args)) {
execArgs.push(...opts.args)
}
// Start app
spinner.info(`Starting ${formula.name} at port ${port}`)
const server = execa(execFile, execArgs, {
stdout,
stderr
})
const close = () => Promise.resolve(server.cancel())
onShutdown(() => close())
return {
server,
close
}
}

6
tsconfig.json Normal file
View File

@@ -0,0 +1,6 @@
{
"compilerOptions": {
"moduleResolution": "Node",
"esModuleInterop": true
},
}

3927
yarn.lock Normal file

File diff suppressed because it is too large Load Diff