feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

19
api.hyungi.net/node_modules/promptly/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2012 IndigoUnited
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.

178
api.hyungi.net/node_modules/promptly/README.md generated vendored Normal file
View File

@@ -0,0 +1,178 @@
# promptly
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]
[npm-url]:https://npmjs.org/package/promptly
[downloads-image]:http://img.shields.io/npm/dm/promptly.svg
[npm-image]:http://img.shields.io/npm/v/promptly.svg
[travis-url]:https://travis-ci.org/IndigoUnited/node-promptly
[travis-image]:http://img.shields.io/travis/IndigoUnited/node-promptly/master.svg
[david-dm-url]:https://david-dm.org/IndigoUnited/node-promptly
[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-promptly.svg
[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-promptly#info=devDependencies
[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-promptly.svg
Simple command line prompting utility.
## Installation
`$ npm install promptly`
## API
### .prompt(message, [opts], [fn])
Prompts for a value, printing the `message` and waiting for the input.
When done, calls `fn` with `error` and `value` or returns a `Promise` if no `fn` is provided.
Default options:
```js
{
// The default value. If not supplied, the input is mandatory
'default': null,
// Automatically trim the input
'trim': true,
// A validator or an array of validators.
'validator': null,
// Automatically retry if a validator fails
'retry': true,
// Do not print what the user types
'silent': false,
// Replace each character with the specified string when 'silent' is true
'replace': '',
// Input and output streams to read and write to
'input': process.stdin,
'output': process.stdout
}
```
The validators have two purposes:
```js
function (value) {
// Validation example, throwing an error when invalid
if (value.length !== 2) {
throw new Error('Length must be 2');
}
// Parse the value, modifying it
return value.replace('aa', 'bb');
}
```
Example usages
Ask for a name:
```js
promptly.prompt('Name: ', function (err, value) {
// err is always null in this case, because no validators are set
console.log(value);
});
```
Using Promise:
```js
promptly.prompt('Name: ')
.then(function (value) {
// no need for catch in this case, because no validators are set
console.log(value);
});
```
Ask for a name with a constraint (non-empty value and length > 2):
```js
var validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
}
return value;
};
promptly.prompt('Name: ', { validator: validator }, function (err, value) {
// Since retry is true by default, err is always null
// because promptly will be prompting for a name until it validates
// Between each prompt, the error message from the validator will be printed
console.log('Name is:', value);
});
```
Same as above but do not retry automatically:
```js
var validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
}
return value;
};
promptly.prompt('Name: ', { validator: validator, retry: false }, function (err, value) {
if (err) {
console.error('Invalid name:', err.message);
// Manually call retry
// The passed error has a retry method to easily prompt again.
return err.retry();
}
console.log('Name is:', value);
});
```
### .confirm(message, [opts], fn)
Ask the user to confirm something.
Calls `fn` with `error` and `value` (true or false).
Truthy values are: `y`, `yes` and `1`.
Falsy values are `n`, `no`, and `0`.
Comparison is made in a case insensitive way.
Example usage:
```js
promptly.confirm('Are you sure? ', function (err, value) {
console.log('Answer:', value);
});
```
### .choose(message, choices, [opts], fn)
Ask the user to choose between multiple `choices` (array of choices).
Calls `fn` with `error` and `value`.
Example usage:
```js
promptly.choose('Do you want an apple or an orange? ', ['apple', 'orange'], function (err, value) {
console.log('Answer:', value);
});
```
### .password(message, [opts], fn)
Prompts for a password, printing the `message` and waiting for the input.
When available, calls `fn` with `error` and `value`.
The available options are the same, except that `trim` and `silent` default to `false` and `default` is an empty string (to allow empty passwords).
Example usage:
```js
promptly.password('Type a password: ', { replace: '*' }, function (err, value) {
console.log('Password is:', value);
});
```
## License
Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).

197
api.hyungi.net/node_modules/promptly/index.js generated vendored Normal file
View File

@@ -0,0 +1,197 @@
'use strict';
var read = require('read');
var promptly = module.exports;
function prompt(message, opts, fn) {
// Setup read's options
var readOpts = {
prompt: message,
input: opts.input || process.stdin,
output: opts.output || process.stdout,
silent: opts.silent,
replace: opts.replace || ''
};
// Use readline question
read(readOpts, function (err, data) {
// Ignore the error attribute
// It is set on SIGINT or if timeout reached (we are not using timeout)
if (err) {
return;
}
// Trim?
if (opts.trim) {
data = data.trim();
}
// Mandatory?
if (opts['default'] == null && !data) {
return promptly.prompt(message, opts, fn);
} else {
data = data || opts['default'];
}
// Validator verification
if (opts.validator) {
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
var x;
var length = opts.validator.length;
for (x = 0; x < length; x += 1) {
try {
data = opts.validator[x](data);
} catch (e) {
// Retry automatically if the retry option is enabled
if (opts.retry) {
if (e.message) {
readOpts.output.write(e.message + '\n');
}
return promptly.prompt(message, opts, fn);
}
e.retry = promptly.prompt.bind(promptly, message, opts, fn);
return fn(e);
}
}
}
// Everything ok
fn(null, data);
});
}
promptly.prompt = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
if (opts.trim === undefined) {
opts.trim = true;
}
if (opts.retry === undefined) {
opts.retry = true;
}
if (fn) {
return prompt(message, opts, fn);
}
return new Promise(function (resolve, reject) {
prompt(message, opts, function (err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
});
};
promptly.password = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else {
opts = opts || {};
}
// Set default options
if (opts.silent === undefined) {
opts.silent = true;
}
if (opts.trim === undefined) {
opts.trim = false;
}
if (opts['default'] === undefined) {
opts['default'] = '';
}
// Use prompt()
return promptly.prompt(message, opts, fn);
};
promptly.confirm = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
opts.validator = opts.validator || [];
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
// Push the validator that will coerse boolean values
var validator = function (value) {
if (typeof value === 'string') {
value = value.toLowerCase();
}
switch (value) {
case 'y':
case 'yes':
case '1':
case true:
return true;
case 'n':
case 'no':
case '0':
case false:
return false;
}
throw new Error();
};
opts.validator.push(validator);
// Use choose() with true, false
return promptly.choose(message, [true, false], opts, fn);
};
promptly.choose = function (message, choices, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
opts.validator = opts.validator || [];
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
// Push the choice validator
var nrChoices = choices.length;
var validator = function (value) {
var x;
for (x = 0; x < nrChoices; x++) {
if (choices[x] == value) {
return choices[x];
}
}
throw new Error('Invalid choice: ' + value);
};
opts.validator.push(validator);
// Use prompt()
return promptly.prompt(message, opts, fn);
};

34
api.hyungi.net/node_modules/promptly/package.json generated vendored Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "promptly",
"version": "2.2.0",
"description": "Simple command line prompting utility",
"main": "index.js",
"dependencies": {
"read": "^1.0.4"
},
"devDependencies": {
"async": "^2.0.0",
"expect.js": "^0.3.1",
"mocha": "^3.0.2"
},
"scripts": {
"test": "mocha --bail"
},
"repository": {
"type": "git",
"url": "git://github.com/IndigoUnited/node-promptly"
},
"bugs": {
"url": "http://github.com/IndigoUnited/node-promptly/issues"
},
"keywords": [
"prompt",
"choose",
"choice",
"cli",
"command",
"line"
],
"author": "IndigoUnited <hello@indigounited.com> (http://indigounited.com)",
"license": "MIT"
}

390
api.hyungi.net/node_modules/promptly/test/test.js generated vendored Normal file
View File

@@ -0,0 +1,390 @@
'use strict';
var expect = require('expect.js');
var promptly = require('../index');
var async = require('async');
// Mock stdout
var stdout = '';
var oldWrite = process.stdout.write;
process.stdout.write = function (data) {
stdout += data;
return oldWrite.apply(process.stdout, arguments);
};
// Function to send a line to stdin
function sendLine(line) {
setImmediate(function () {
process.stdin.emit('data', line + '\n');
});
}
beforeEach(function () {
stdout = '';
});
describe('prompt()', function () {
it('should prompt the user', function (next) {
promptly.prompt('something: ', function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
next();
});
sendLine('yeaa');
});
it('should keep asking if no value is passed and no default was defined', function (next) {
promptly.prompt('something: ', function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout.indexOf('something')).to.not.be(stdout.lastIndexOf('something'));
next();
});
sendLine('');
sendLine('yeaa');
});
it('should assume default value if nothing is passed', function (next) {
promptly.prompt('something: ', { 'default': 'myValue' }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be('myValue');
expect(stdout).to.contain('something: ');
next();
});
sendLine('');
});
it('should trim the user input if trim is enabled', function (next) {
promptly.prompt('something: ', { trim: true }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
next();
});
sendLine(' yeaa ');
});
it('should call validator after trimming', function (next) {
function validator(value) {
if (value !== 'yeaa') {
throw new Error('bla');
}
return value;
}
promptly.prompt('something: ', { validator: validator, retry: false }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
next();
});
sendLine(' yeaa ');
});
it('should assume values from the validator', function (next) {
function validator() { return 'bla'; }
promptly.prompt('something: ', { validator: validator }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be('bla');
expect(stdout).to.contain('something: ');
next();
});
sendLine(' yeaa ');
});
it('should automatically retry if a validator fails by default', function (next) {
function validator(value) {
if (value !== 'yeaa') {
throw new Error('bla');
}
return value;
}
promptly.prompt('something: ', { validator: validator, retry: true }, function (err, value) {
expect(stdout).to.contain('something: ');
expect(stdout.indexOf('something')).to.not.be(stdout.lastIndexOf('something'));
expect(stdout).to.contain('bla');
expect(value).to.equal('yeaa');
next();
});
sendLine('wtf');
sendLine('yeaa');
});
it('should give error if the validator fails and retry is false', function (next) {
function validator() { throw new Error('bla'); }
promptly.prompt('something: ', { validator: validator, retry: false }, function (err) {
expect(err).to.be.an(Error);
expect(err.message).to.be('bla');
expect(stdout).to.contain('something: ');
next();
});
sendLine(' yeaa ');
});
it('should give retry ability on error', function (next) {
var times = 0;
function validator(value) {
if (value !== 'yeaa') {
throw new Error('bla');
}
return value;
}
promptly.prompt('something: ', { validator: validator, retry: false }, function (err, value) {
times++;
if (times === 1) {
expect(err).to.be.an(Error);
err.retry();
return sendLine('yeaa');
}
expect(value).to.equal('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout.indexOf('something')).to.not.be(stdout.lastIndexOf('something'));
next();
});
sendLine('wtf');
});
it('should write input to stdout by default', function (next) {
promptly.prompt('something: ', function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout).to.contain(value);
next();
});
sendLine('yeaa');
});
it('should write input to stdout if silent is false', function (next) {
promptly.prompt('something: ', { silent: true }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout).to.not.contain(value);
next();
});
sendLine('yeaa');
});
it('should prompt the user (using promise)', function (next) {
promptly.prompt('something: ')
.then(function (value) {
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
next();
})
.catch(function () {
expect().fail();
next();
});
sendLine('yeaa');
});
});
describe('choose()', function () {
it('should keep asking on invalid choice', function (next) {
promptly.choose('apple or orange? ', ['apple', 'orange'], function (err, value) {
expect(err).to.be(null);
expect(value).to.be('orange');
expect(stdout).to.contain('apple or orange? ');
expect(stdout.indexOf('apple or orange')).to.not.be(stdout.lastIndexOf('apple or orange'));
expect(stdout).to.contain('Invalid choice');
next();
});
sendLine('bleh');
sendLine('orange');
});
it('should error on invalid choice if retry is disabled', function (next) {
promptly.choose('apple or orange? ', ['apple', 'orange'], { retry: false }, function (err) {
expect(err).to.be.an(Error);
expect(err.message).to.contain('choice');
expect(stdout).to.contain('apple or orange? ');
next();
});
sendLine('bleh');
});
it('should be ok on valid choice', function (next) {
promptly.choose('apple or orange? ', ['apple', 'orange'], function (err, value) {
expect(err).to.be(null);
expect(value).to.be('apple');
expect(stdout).to.contain('apple or orange? ');
next();
});
sendLine('apple');
});
it('should not use strict comparison when matching against valid choices', function (next) {
promptly.choose('choices: ', [1, 2, 3], function (err, value) {
expect(err).to.be(null);
expect(typeof value).to.equal('number');
expect(value).to.be(1);
expect(stdout).to.contain('choices: ');
next();
});
sendLine('1');
});
it('should work using promise', function (next) {
promptly.choose('apple or orange? ', ['apple', 'orange'])
.then(function (value) {
expect(value).to.be('orange');
expect(stdout).to.contain('apple or orange? ');
next();
})
.catch(function () {
expect().fail();
next();
});
sendLine('orange');
});
});
describe('confirm()', function () {
it('should be ok on valid choice and coerce to boolean values', function (next) {
async.forEachSeries(['yes', 'Y', 'y', '1'], function (truthy, next) {
promptly.confirm('test yes? ', { retry: false }, function (err, value) {
expect(err).to.be(null);
expect(value).to.be(true);
expect(stdout).to.contain('test yes? ');
next();
});
sendLine(truthy);
}, function () {
async.forEachSeries(['no', 'N', 'n', '0'], function (truthy, next) {
promptly.confirm('test no? ', function (err, value) {
expect(err).to.be(null);
expect(value).to.be(false);
expect(stdout).to.contain('test no? ');
next();
});
sendLine(truthy);
}, next);
});
});
it('should keep asking on invalid choice', function (next) {
promptly.confirm('yes or no? ', function (err, value) {
expect(err).to.be(null);
expect(value).to.be(true);
expect(stdout).to.contain('yes or no? ');
expect(stdout.indexOf('yes or no')).to.not.be(stdout.lastIndexOf('yes or no'));
next();
});
sendLine('bleh');
sendLine('y');
});
it('should error on invalid choice if retry is disabled', function (next) {
promptly.confirm('yes or no? ', { retry: false }, function (err) {
expect(err).to.be.an(Error);
expect(err.message).to.not.contain('Invalid choice');
expect(stdout).to.contain('yes or no? ');
next();
});
sendLine('bleh');
});
it('should work using promise', function (next) {
promptly.confirm('yes or no? ')
.then(function (value) {
expect(stdout).to.contain('yes or no? ');
expect(value).to.be(true);
next();
})
.catch(function () {
expect().fail();
next();
});
sendLine('y');
});
});
describe('password()', function () {
it('should prompt the user silently', function (next) {
promptly.password('something: ', function (err, value) {
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout).to.not.contain('yeaa');
next();
});
sendLine('yeaa');
});
it('should not trim by default', function (next) {
promptly.password('something: ', function (err, value) {
expect(value).to.be(' yeaa ');
expect(stdout).to.contain('something: ');
expect(stdout).to.not.contain(' yeaa ');
next();
});
sendLine(' yeaa ');
});
it('show allow empty passwords by default', function (next) {
promptly.password('something: ', function (err, value) {
expect(value).to.be('');
expect(stdout).to.contain('something: ');
next();
});
sendLine('');
});
it('should prompt the user silently using promise', function (next) {
promptly.password('something: ')
.then(function (value) {
expect(value).to.be('yeaa');
expect(stdout).to.contain('something: ');
expect(stdout).to.not.contain('yeaa');
next();
})
.catch(function () {
expect().fail();
next();
});
sendLine('yeaa');
});
});