rman 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 sqbjs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,101 @@
1
+ ## postgresql-client
2
+
3
+ [![NPM Version][npm-image]][npm-url]
4
+ [![NPM Downloads][downloads-image]][downloads-url]
5
+ [![Build Status][travis-image]][travis-url]
6
+ [![Test Coverage][coveralls-image]][coveralls-url]
7
+
8
+
9
+ Professional PostgreSQL client written in TypeScript.
10
+
11
+ ## Features
12
+
13
+ - Pure JavaScript library completely written in TypeScript
14
+ - Supports both single connection and pooling
15
+ - Named Prepared Statements
16
+ - Extended cursor support with fast double-link cache
17
+ - Extensible data-types and type mapping
18
+ - Extended bind parameters
19
+ - Multidimensional arrays with fast binary encoding/decoding
20
+ - Low memory utilization and boosted performance with Shared Buffers
21
+ - Full binary and text wire protocol support for all data types
22
+ - Supports Clear text, MD5 and SASL password algorithms
23
+ - Can return both array and object rows
24
+ - Asynchronous Promise based api
25
+ - Strictly typed
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ $ npm install postgresql-client --save
31
+ ```
32
+
33
+ ## Documentation
34
+ Documentation for detailed usage is [here](DOCUMENTATION.md)
35
+
36
+ ```ts
37
+ import {Connection} from 'postgresql-client';
38
+
39
+ const connection = new Connection('postgres://localhost');
40
+ await connection.connect();
41
+ const result = await connection.query(
42
+ 'select * from cities where name like $1',
43
+ {params: ['%york%']});
44
+ const rows = result.rows;
45
+ await connection.close(); // Disconnect
46
+ ```
47
+
48
+ ```ts
49
+ import {Pool} from 'postgresql-client';
50
+
51
+ const db = new Pool({
52
+ host: 'postgres://localhost',
53
+ pool: {
54
+ min: 1,
55
+ max: 10,
56
+ idleTimeoutMillis: 5000
57
+ }
58
+ });
59
+
60
+ const result = await db.query(
61
+ 'select * from cities where name like $1',
62
+ {params: ['%york%'], cursor: true});
63
+ const cursor = result.cursor;
64
+ let row;
65
+ while ((row = cursor.next())) {
66
+ console.log(row);
67
+ }
68
+
69
+ await db.close(); // Disconnect all connections and shutdown pool
70
+ ```
71
+
72
+
73
+ ## Support
74
+ You can report bugs and discuss features on the [GitHub issues](https://github.com/panates/postgresql-client/issues) page
75
+ When you open an issue please provide version of NodeJS and PostgreSQL server.
76
+
77
+
78
+ ## Node Compatibility
79
+
80
+ - node >= 10.x
81
+
82
+
83
+ ### License
84
+ postgresql-client is available under [MIT](LICENSE) license.
85
+
86
+ [npm-image]: https://img.shields.io/npm/v/postgresql-client.svg
87
+ [npm-url]: https://npmjs.org/package/postgresql-client
88
+ [travis-image]: https://img.shields.io/travis/panates/postgresql-client/master.svg
89
+ [travis-url]: https://travis-ci.com/panates/postgresql-client
90
+ [coveralls-image]: https://img.shields.io/coveralls/panates/postgresql-client/master.svg
91
+ [coveralls-url]: https://coveralls.io/r/panates/postgresql-client
92
+ [downloads-image]: https://img.shields.io/npm/dm/postgresql-client.svg
93
+ [downloads-url]: https://npmjs.org/package/postgresql-client
94
+ [gitter-image]: https://badges.gitter.im/panates/postgresql-client.svg
95
+ [gitter-url]: https://gitter.im/panates/postgresql-client?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
96
+ [dependencies-image]: https://david-dm.org/panates/postgresql-client/status.svg
97
+ [dependencies-url]:https://david-dm.org/panates/postgresql-client
98
+ [devdependencies-image]: https://david-dm.org/panates/postgresql-client/dev-status.svg
99
+ [devdependencies-url]:https://david-dm.org/panates/postgresql-client?type=dev
100
+ [quality-image]: http://npm.packagequality.com/shield/postgresql-client.png
101
+ [quality-url]: http://packagequality.com/#?package=postgresql-client
package/bin/debug.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import {run} from '../src/cli.js';
3
+
4
+ run().catch(e => console.error(e));
package/bin/rman.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import {run} from '../dist/cli.js';
3
+
4
+ // eslint-disable-next-line
5
+ run().catch(e => console.error(e));
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function run(argv?: string[]): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,51 @@
1
+ import fs from 'fs/promises';
2
+ import { URL } from 'url';
3
+ import chalk from 'chalk';
4
+ import { program } from "commander";
5
+ import { Workspace } from './workspace/workspace.js';
6
+ export async function run(argv = process.argv) {
7
+ const pkgJson = JSON.parse(await fs.readFile(new URL('../package.json', import.meta.url), 'utf-8'));
8
+ program.version(pkgJson.version || '');
9
+ program
10
+ .command('run <script>')
11
+ .description('Executes given script for every package in repository')
12
+ .action(async (script) => runScript(script))
13
+ .allowUnknownOption();
14
+ program
15
+ .command('build')
16
+ .description('Executes "build" script for every package in repository')
17
+ .action(async () => runScript('build'))
18
+ .allowUnknownOption();
19
+ program
20
+ .command('lint')
21
+ .description('Executes "lint" script for every package in repository')
22
+ .action(async () => runScript('lint'))
23
+ .allowUnknownOption();
24
+ program
25
+ .command('test')
26
+ .description('Executes "test" script for every package in repository')
27
+ .action(async () => runScript('lint'))
28
+ .allowUnknownOption();
29
+ program.parse(argv);
30
+ }
31
+ async function runScript(script) {
32
+ const workspace = await Workspace.resolve();
33
+ const result = await workspace.runScript(script, {
34
+ gauge: true
35
+ });
36
+ if (result.errorCount) {
37
+ console.error('\n' + chalk.yellow(result.errorCount) + chalk.white(' error(s)'));
38
+ let s = '';
39
+ for (let i = 0; i < result.commands.length; i++) {
40
+ const cmd = result.commands[i];
41
+ if (cmd.error) {
42
+ s += '\n' + (i + 1) + ') ' +
43
+ chalk.cyanBright(cmd.package) + '\n' +
44
+ chalk.white(cmd.command) + '\n' +
45
+ chalk.red('Error: ' + cmd.error.message) + '\n' +
46
+ chalk.red(cmd.stderr) + '\n';
47
+ }
48
+ }
49
+ console.error(s);
50
+ }
51
+ }
@@ -0,0 +1 @@
1
+ export * from './workspace/workspace';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './workspace/workspace';
@@ -0,0 +1,23 @@
1
+ /// <reference types="node" />
2
+ import { ChildProcess } from 'child_process';
3
+ export interface IExecutorOptions {
4
+ stdio?: 'inherit' | 'pipe';
5
+ cwd?: string;
6
+ argv?: string[];
7
+ env?: Record<string, string | undefined>;
8
+ shell?: boolean;
9
+ color?: boolean;
10
+ onSpawn?: (childProcess: ChildProcess) => void;
11
+ onLine?: (line: string, stdio: 'stderr' | 'stdout') => void;
12
+ onData?: (data: string, stdio: 'stderr' | 'stdout') => void;
13
+ }
14
+ export interface IRunScriptOptions {
15
+ gauge?: boolean;
16
+ }
17
+ export interface ExecuteCommandResult {
18
+ code?: number;
19
+ error?: any;
20
+ stderr: string;
21
+ stdout: string;
22
+ }
23
+ export declare function executeCommand(command: string, options?: IExecutorOptions): Promise<ExecuteCommandResult>;
@@ -0,0 +1,107 @@
1
+ import { spawn } from 'child_process';
2
+ import npmRubPath from 'npm-run-path';
3
+ import chalk from 'chalk';
4
+ import { onProcessExit } from './utils.js';
5
+ const runningChildren = new Map();
6
+ export async function executeCommand(command, options) {
7
+ const opts = {
8
+ ...options
9
+ };
10
+ opts.env = {
11
+ ...npmRubPath.env({ cwd: options?.cwd }),
12
+ // FORCE_COLOR: `${chalk.level}`,
13
+ ...opts.env
14
+ };
15
+ opts.cwd = opts.cwd || process.cwd();
16
+ opts.color = opts.color == null ? true : opts.color;
17
+ const spawnOptions = {
18
+ stdio: opts.stdio || 'pipe',
19
+ env: opts.env,
20
+ cwd: opts.cwd,
21
+ shell: options?.shell,
22
+ windowsHide: true
23
+ };
24
+ const result = {
25
+ code: undefined,
26
+ stderr: '',
27
+ stdout: ''
28
+ };
29
+ const buffer = {
30
+ stdout: '',
31
+ stderr: ''
32
+ };
33
+ const processData = (data, stdio) => {
34
+ buffer[stdio] += data;
35
+ result[stdio] += data;
36
+ if (opts.onData)
37
+ opts.onData(data, stdio);
38
+ };
39
+ const processLines = (stdio, flush) => {
40
+ let chunk = buffer[stdio];
41
+ let i;
42
+ if (flush && !chunk.endsWith('\n'))
43
+ chunk += '\n';
44
+ while ((i = chunk.indexOf('\n')) >= 0) {
45
+ const line = chunk.substring(0, i);
46
+ chunk = chunk.substring(i + 1);
47
+ if (opts.onLine)
48
+ opts.onLine(line, stdio);
49
+ }
50
+ buffer[stdio] = chunk;
51
+ };
52
+ const child = spawn(command, opts.argv || [], spawnOptions);
53
+ if (child.pid) {
54
+ runningChildren.set(child.pid, child);
55
+ if (opts.onSpawn)
56
+ opts.onSpawn(child);
57
+ }
58
+ child.stdout?.on('data', (data) => {
59
+ processData(data, 'stdout');
60
+ processLines('stdout');
61
+ });
62
+ child.stderr?.on('data', (data) => {
63
+ processData(data, 'stderr');
64
+ processLines('stderr');
65
+ });
66
+ return new Promise(resolve => {
67
+ let resolved;
68
+ child.on('error', (err) => {
69
+ if (child.pid)
70
+ runningChildren.delete(child.pid);
71
+ processLines('stdout', true);
72
+ processLines('stderr', true);
73
+ if (resolved)
74
+ return;
75
+ result.code = err.code || 1;
76
+ result.error = err;
77
+ if (!result.error) {
78
+ const text = `Command failed (${result.code})`;
79
+ result.error =
80
+ new Error((opts.color ? chalk.red(text) : text) + '\n ' +
81
+ opts.color ? chalk.white(err.message) : err.message);
82
+ }
83
+ resolved = true;
84
+ resolve(result);
85
+ });
86
+ child.on('close', (code) => {
87
+ if (child.pid)
88
+ runningChildren.delete(child.pid);
89
+ processLines('stdout', true);
90
+ processLines('stderr', true);
91
+ if (resolved)
92
+ return;
93
+ result.code = code;
94
+ resolved = true;
95
+ if (code) {
96
+ const text = `Command failed (${result.code})`;
97
+ result.error = new Error((opts.color ? chalk.red(text) : text));
98
+ }
99
+ return resolve(result);
100
+ });
101
+ });
102
+ }
103
+ onProcessExit(() => {
104
+ runningChildren.forEach((child) => {
105
+ child.kill();
106
+ });
107
+ });
@@ -0,0 +1,27 @@
1
+ export interface RunScriptResult {
2
+ script: string;
3
+ code?: number;
4
+ errorCount: number;
5
+ commands: CommandResult[];
6
+ }
7
+ export interface ScriptCommand {
8
+ name: string;
9
+ command: string;
10
+ step: string;
11
+ }
12
+ export interface CommandResult {
13
+ package: string;
14
+ command: string;
15
+ code: number;
16
+ error: any;
17
+ stdout: string;
18
+ stderr: string;
19
+ }
20
+ export declare class Package {
21
+ readonly dirname: string;
22
+ readonly def: any;
23
+ dependencies: string[];
24
+ constructor(dirname: string, def: any);
25
+ get name(): string;
26
+ getScriptCommands(script: string): ScriptCommand[];
27
+ }
@@ -0,0 +1,36 @@
1
+ import parseNpmScript from '@netlify/parse-npm-script';
2
+ export class Package {
3
+ constructor(dirname, def) {
4
+ this.dirname = dirname;
5
+ this.dependencies = [];
6
+ Object.defineProperty(this, 'def', {
7
+ enumerable: false,
8
+ value: def,
9
+ });
10
+ }
11
+ get name() {
12
+ return this.def.name;
13
+ }
14
+ getScriptCommands(script) {
15
+ const result = [];
16
+ let scriptInfo;
17
+ try {
18
+ scriptInfo = parseNpmScript(this.def, 'npm run ' + script);
19
+ }
20
+ catch {
21
+ return result;
22
+ }
23
+ if (scriptInfo && scriptInfo.raw)
24
+ for (const step of scriptInfo.steps) {
25
+ const parsed = Array.isArray(step.parsed) ? step.parsed : [step.parsed];
26
+ for (const cmd of parsed) {
27
+ result.push({
28
+ name: cmd.split(' ')[0],
29
+ command: cmd,
30
+ step: step.name
31
+ });
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ }
@@ -0,0 +1,4 @@
1
+ import { IParsedWorkspaceInfo, IWorkspaceProvider } from '../types';
2
+ export declare class NpmProvider implements IWorkspaceProvider {
3
+ parse(root: string): Promise<IParsedWorkspaceInfo | undefined>;
4
+ }
@@ -0,0 +1,12 @@
1
+ import { getPackageJson } from '../utils.js';
2
+ export class NpmProvider {
3
+ async parse(root) {
4
+ const pkg = getPackageJson(root);
5
+ if (pkg && typeof pkg.workspaces === 'object') {
6
+ if (Array.isArray(pkg.workspaces))
7
+ return { root, packages: pkg.workspaces };
8
+ if (Array.isArray(pkg.workspaces.packages))
9
+ return { root, packages: pkg.workspaces.packages };
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,11 @@
1
+ export interface IWorkspaceOptions {
2
+ packageOrder?: string[];
3
+ scripts?: Record<string, {}>;
4
+ }
5
+ export interface IWorkspaceProvider {
6
+ parse: (root: string) => Promise<IParsedWorkspaceInfo | undefined>;
7
+ }
8
+ export interface IParsedWorkspaceInfo {
9
+ root: string;
10
+ packages: string[];
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" />
2
+ declare type ExitListener = (signal: NodeJS.Signals | "exit") => void;
3
+ export declare function getPackageJson(dirname: string): any;
4
+ export declare function onProcessExit(listener: ExitListener, forceExit?: boolean): void;
5
+ export declare function setFind<T>(set: Set<T>, cb: (item: T) => boolean): T | undefined;
6
+ export {};
@@ -0,0 +1,22 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ export function getPackageJson(dirname) {
4
+ const f = path.resolve(dirname, 'package.json');
5
+ if (!fs.existsSync(f))
6
+ return;
7
+ return JSON.parse(fs.readFileSync(f, 'utf-8'));
8
+ }
9
+ export function onProcessExit(listener, forceExit = true) {
10
+ ["SIGTERM", "SIGINT"].forEach((event) => process.once(event, (signal) => {
11
+ listener(signal);
12
+ if (forceExit)
13
+ process.exit(1);
14
+ }));
15
+ process.once("exit", () => listener("exit"));
16
+ }
17
+ export function setFind(set, cb) {
18
+ for (const e of set) {
19
+ if (cb(e))
20
+ return e;
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ import { IRunScriptOptions } from './executor.js';
2
+ import { Package, RunScriptResult } from './package.js';
3
+ import { IWorkspaceOptions } from './types.js';
4
+ export declare class Workspace {
5
+ readonly root: string;
6
+ readonly packages: Package[];
7
+ private _options;
8
+ constructor(root: string, packages: Package[], options?: IWorkspaceOptions);
9
+ getPackage(name: string): Package | undefined;
10
+ runScript(script: string, options?: IRunScriptOptions): Promise<RunScriptResult>;
11
+ private _determineDependencies;
12
+ private _getSortedPackages;
13
+ static resolve(root?: string, options?: {
14
+ deep?: number;
15
+ }): Promise<Workspace>;
16
+ }
@@ -0,0 +1,227 @@
1
+ import fs from 'fs';
2
+ import glob from 'fast-glob';
3
+ import path from 'path';
4
+ import chalk from 'chalk';
5
+ import { MultiBar, Presets } from 'cli-progress';
6
+ import { getPackageJson, setFind } from './utils.js';
7
+ import { executeCommand } from './executor.js';
8
+ import { Package } from './package.js';
9
+ import { NpmProvider } from './providers/npm-provider.js';
10
+ const providers = [
11
+ new NpmProvider()
12
+ ];
13
+ export class Workspace {
14
+ constructor(root, packages, options) {
15
+ this.root = root;
16
+ this.packages = packages;
17
+ this._options = { ...options };
18
+ this._determineDependencies();
19
+ }
20
+ getPackage(name) {
21
+ return this.packages.find(p => p.name === name);
22
+ }
23
+ async runScript(script, options = {}) {
24
+ const packages = {};
25
+ const result = {
26
+ script,
27
+ errorCount: 0,
28
+ commands: []
29
+ };
30
+ options.gauge = options.gauge == null ? true : options.gauge;
31
+ const progressBars = options.gauge && new MultiBar({
32
+ format: '[' + chalk.cyan('{bar}') + '] {percentage}% | {value}/{total} | ' +
33
+ chalk.yellowBright('{package}') + ' | ' + chalk.yellow('{command}'),
34
+ barsize: 30,
35
+ hideCursor: true
36
+ }, Presets.rect);
37
+ const overallProgress = progressBars && progressBars.create(0, 0);
38
+ let totalCommands = 0;
39
+ for (const p of this._getSortedPackages()) {
40
+ const commands = p.getScriptCommands(script);
41
+ const progress = progressBars && progressBars.create(commands.length, 0);
42
+ packages[p.name] = {
43
+ package: p,
44
+ commands: [...commands],
45
+ progress
46
+ };
47
+ totalCommands += commands.length;
48
+ if (progress)
49
+ progress.start(commands.length, 0, {
50
+ package: p.name,
51
+ command: 'Waiting'
52
+ });
53
+ }
54
+ if (overallProgress) {
55
+ overallProgress.start(totalCommands, 0, { package: 'Overall', command: '' });
56
+ }
57
+ const t = Date.now();
58
+ return new Promise((resolve) => {
59
+ const remaining = new Set(Object.keys(packages));
60
+ const runScripts = () => {
61
+ for (const pkgName of remaining) {
62
+ const pkgInfo = packages[pkgName];
63
+ const pkg = pkgInfo.package;
64
+ const progress = pkgInfo.progress;
65
+ for (let k = 0; k < pkgInfo.commands.length; k++) {
66
+ const cmd = pkgInfo.commands[k];
67
+ if (cmd.status === 'running')
68
+ break;
69
+ if (!cmd.status) {
70
+ const concurrent = cmd.step.startsWith('pre');
71
+ if (!concurrent &&
72
+ pkg.dependencies.find(dep => setFind(remaining, p => p === dep))) {
73
+ cmd.status = '';
74
+ if (progress)
75
+ progress.update({ command: chalk.bgYellow.white('Waiting dependencies') });
76
+ break;
77
+ }
78
+ cmd.status = 'running';
79
+ if (progress)
80
+ progress.update({ command: cmd.name });
81
+ else
82
+ console.log('[' + chalk.whiteBright(pkg.name) + '] ' +
83
+ chalk.yellow(cmd.command), (chalk.cyanBright(' +' + (Date.now() - t))));
84
+ void executeCommand(cmd.command, {
85
+ ...options,
86
+ cwd: pkg.dirname,
87
+ shell: true
88
+ }).then(r => {
89
+ if (overallProgress)
90
+ overallProgress.increment(1);
91
+ if (progress)
92
+ progress.increment(1);
93
+ const cr = {
94
+ package: pkg.name,
95
+ command: cmd,
96
+ code: r.code || 1,
97
+ error: r.error,
98
+ stdout: r.stdout,
99
+ stderr: r.stderr
100
+ };
101
+ result.code = result.code || r.code;
102
+ if (r.error)
103
+ result.errorCount++;
104
+ result.commands.push(cr);
105
+ cmd.status = 'done';
106
+ if (r.error || k === pkgInfo.commands.length - 1) {
107
+ if (progress) {
108
+ if (r.error)
109
+ progress.update({ command: chalk.yellow(cmd.name) + chalk.red(' Filed!') });
110
+ else
111
+ progress.update({ command: chalk.green(' Completed!') });
112
+ }
113
+ remaining.delete(pkg.name);
114
+ }
115
+ if (!remaining.size) {
116
+ if (progressBars)
117
+ progressBars.stop();
118
+ return resolve(result);
119
+ }
120
+ if (!result.errorCount)
121
+ setTimeout(runScripts, 1);
122
+ });
123
+ if (!concurrent)
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ };
129
+ runScripts();
130
+ });
131
+ }
132
+ _determineDependencies() {
133
+ const deps = {};
134
+ for (const pkg of this.packages) {
135
+ const o = {
136
+ ...pkg.def.dependencies,
137
+ ...pkg.def.devDependencies,
138
+ ...pkg.def.peerDependencies,
139
+ ...pkg.def.optionalDependencies
140
+ };
141
+ const dependencies = [];
142
+ for (const k of Object.keys(o)) {
143
+ const p = this.getPackage(k);
144
+ if (p)
145
+ dependencies.push(k);
146
+ }
147
+ deps[pkg.name] = dependencies;
148
+ pkg.dependencies = dependencies;
149
+ }
150
+ let circularCheck;
151
+ const deepFindDependencies = (pkg, target) => {
152
+ if (circularCheck.includes(pkg.name))
153
+ return;
154
+ circularCheck.push(pkg.name);
155
+ for (const s of pkg.dependencies) {
156
+ if (!target.includes(s)) {
157
+ target.push(s);
158
+ const p = this.getPackage(s);
159
+ if (p) {
160
+ deepFindDependencies(p, target);
161
+ }
162
+ }
163
+ }
164
+ };
165
+ for (const pkg of this.packages) {
166
+ circularCheck = [];
167
+ deepFindDependencies(pkg, pkg.dependencies);
168
+ }
169
+ }
170
+ _getSortedPackages() {
171
+ const packages = [...this.packages];
172
+ const packageOrder = this._options.packageOrder;
173
+ packages.sort((a, b) => {
174
+ if (packageOrder) {
175
+ const a1 = packageOrder.indexOf(a.name);
176
+ const b1 = packageOrder.indexOf(b.name);
177
+ const i = (a1 >= 0 ? a1 : Number.MAX_SAFE_INTEGER) - (b1 >= 0 ? b1 : Number.MAX_SAFE_INTEGER);
178
+ if (i !== 0)
179
+ return i;
180
+ }
181
+ if (b.dependencies.includes(a.name))
182
+ return -1;
183
+ if (a.dependencies.includes(b.name))
184
+ return 1;
185
+ return 0;
186
+ });
187
+ return packages;
188
+ }
189
+ static async resolve(root, options) {
190
+ root = root || process.cwd();
191
+ let deep = options?.deep || 0;
192
+ while (deep-- >= 0 && fs.existsSync(root)) {
193
+ for (let i = providers.length - 1; i >= 0; i--) {
194
+ const provider = providers[i];
195
+ const inf = await provider.parse(root);
196
+ if (!inf)
197
+ continue;
198
+ const pkgJson = getPackageJson(inf.root);
199
+ if (!pkgJson)
200
+ continue;
201
+ const packages = [];
202
+ for (const pattern of inf.packages) {
203
+ const dirs = await glob(pattern, {
204
+ cwd: inf.root,
205
+ absolute: true,
206
+ deep: 0,
207
+ onlyDirectories: true
208
+ });
209
+ for (const dir of dirs) {
210
+ const p = await detectPackage(dir);
211
+ if (p && !packages.find(x => x.name === p.name))
212
+ packages.push(p);
213
+ }
214
+ }
215
+ return new Workspace(inf.root, packages, pkgJson.rman);
216
+ }
217
+ root = path.resolve(root, '..');
218
+ }
219
+ throw new Error('No project workspace detected');
220
+ }
221
+ }
222
+ async function detectPackage(dirname) {
223
+ const pkgJson = getPackageJson(dirname);
224
+ if (pkgJson && pkgJson.name) {
225
+ return new Package(dirname, pkgJson);
226
+ }
227
+ }
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "rman",
3
+ "description": "Monorepo repository manager",
4
+ "version": "0.0.1",
5
+ "author": "Panates",
6
+ "license": "MIT",
7
+ "contributors": [
8
+ "Eray Hanoglu <e.hanoglu@panates.com>"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/panates/rman.git"
13
+ },
14
+ "keywords": [
15
+ "javascript",
16
+ "typescript",
17
+ "monorepo",
18
+ "repository",
19
+ "build",
20
+ "lerna"
21
+ ],
22
+ "bin": {
23
+ "rman": "bin/rman.js"
24
+ },
25
+ "type": "module",
26
+ "module": "dist/index.js",
27
+ "types": "dist/index.d.ts",
28
+ "dependencies": {
29
+ "chalk": "^4.1.2",
30
+ "commander": "^8.3.0",
31
+ "fast-glob": "^3.2.7",
32
+ "npm-run-path": "^4.0.1",
33
+ "@netlify/parse-npm-script": "^0.1.2",
34
+ "cli-progress": "^3.9.1"
35
+ },
36
+ "devDependencies": {
37
+ "@types/mocha": "^9.0.0",
38
+ "@types/node": "^16.4.8",
39
+ "@types/cli-progress": "^3.9.2",
40
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
41
+ "@typescript-eslint/parser": "^5.0.0",
42
+ "@babel/eslint-parser": "^7.16.3",
43
+ "eslint": "^8.0.0",
44
+ "eslint-config-google": "^0.14.0",
45
+ "mocha": "^9.0.1",
46
+ "nyc": "^15.1.0",
47
+ "ts-cleanup": "^0.2.2",
48
+ "ts-loader": "^9.0.0",
49
+ "ts-node": "^10.0.0",
50
+ "tsconfig-paths": "^3.9.0",
51
+ "typescript": "^4.5.2"
52
+ },
53
+ "engines": {
54
+ "node": ">= 14.0"
55
+ },
56
+ "files": [
57
+ "dist/",
58
+ "bin/",
59
+ "LICENSE",
60
+ "README.md"
61
+ ],
62
+ "scripts": {
63
+ "test": "TS_NODE_PROJECT='./test/tsconfig.json' mocha -r ts-node/register --reporter spec test/**/*.spec.ts",
64
+ "cover": "nyc --reporter=cobertura --reporter html --reporter text npm run test",
65
+ "clean": "npm run clean:src && npm run clean:dist",
66
+ "clean:dist": "ts-cleanup -d dist --remove-dirs --all",
67
+ "clean:src": "ts-cleanup -s src --all | ts-cleanup -s test",
68
+ "prebuild": "npm run clean && npm run lint",
69
+ "build": "tsc -b tsconfig.build.json",
70
+ "compile": "tsc -b tsconfig.json",
71
+ "lint": "eslint src/** --no-error-on-unmatched-pattern",
72
+ "travis-cover": "nyc --reporter lcovonly npm run test"
73
+ },
74
+ "nyc": {
75
+ "temp-dir": "./coverage/.nyc_output"
76
+ }
77
+ }