Skip to content

Commit

Permalink
Merge pull request #119 from lamartire/develop
Browse files Browse the repository at this point in the history
v2.2.0
  • Loading branch information
Konstantin Epishev authored May 26, 2020
2 parents 9a4e523 + 13fa5c8 commit f8436c7
Show file tree
Hide file tree
Showing 122 changed files with 889 additions and 361 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# v2.2.0

This release includes new step types - processors. These steps transforms data
passed through them. It is better solution for any configuration post-procession,
like meta injecting or formatting.

Features:

- `writeMeta` now is pure step
- Inserting EOL wrap to each file (now it is not configurable)
- Add `--include-cache` option for storing configuration cache outside of `node_modules`

# v2.1.2

Chore:
Expand Down
19 changes: 19 additions & 0 deletions packages/sharec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ Example:
}
```

**`--include-cache, -c`** - saves configuration cache in target project directory. It is very usefull,
if you want always have ability to change configuration version in project without any problems.

With this option, cache would be saved in `<project_path>/.sharec/.cache`, instead `node_modules`.

Especially this feature can be usefull if you are using package manager which do not make `node_modules`.

Be sure, if you use this option, that `.sharec` directory is not ignored by git!

Example:

```
{
"scripts": {
"postinstall": "sharec --include-cache"
}
}
```

## Ignoring configuration

If you want to force upcoming `sharec` configs – just add `ignore` flat to your projects's `sharec` field:
Expand Down
48 changes: 40 additions & 8 deletions packages/sharec/src/cli/logger.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
const { bold } = require('chalk')

/**
* @typedef {Object} Logger
*/

/**
* Creates logger for debug puporses
* Can be created with custom prefix for next problem scope determining
* @param {Object} params
* @param {String} [params.prefix] Prefix which would append to each logger message
* @param {Boolean} params.silent If silent is truthy - logger will not print any message
* @returns {Logger}
*/
const createLogger = ({ prefix = '', silent }) => {
const logPrefixParts = ['sharec', ':']

Expand All @@ -10,17 +22,37 @@ const createLogger = ({ prefix = '', silent }) => {
const logPrefix = bold(logPrefixParts.join(''))

const logger = {
wrap: (fn, fnId = '') => (...params) => {
if (silent) return fn(...params)
if (params.length === 0) return fn(...params)
/**
* Wraps function with logger by special ID
* Usefull in cases when we need to see all input and output parameters from function
* @memberof Logger
* @param {Function} fn Any function
* @param {String} [fnId] Function name for anonymous functions logging
* @returns {Function}
*/
wrap: (fn, fnId = '') =>
/**
* @memberof Logger
* @param {Array<*>} params Any arguments for logging
* @returns {*} Result of given function execution
*/
(...params) => {
if (silent) return fn(...params)
if (params.length === 0) return fn(...params)

params.forEach((param, i) => {
console.dir(logPrefix, bold(`${fn.name || fnId}(arg[${i}]): \n`), param)
})
params.forEach((param, i) => {
console.dir(logPrefix, bold(`${fn.name || fnId}(arg[${i}]): \n`), param)
})

return fn(...params)
},
return fn(...params)
},

/**
* Uses for logging like common console.log, but from special logger
* @memberof Logger
* @param {Array<*>} entries Any parameters which would be logged
* @returns {void}
*/
log: (...entries) => {
if (silent) return

Expand Down
10 changes: 8 additions & 2 deletions packages/sharec/src/cli/spinner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ const ora = require('ora')
*/

/**
* Creates wrapper below ora spinner
* Can be silenced by parameters
* @param {Object} params
* @param {String} params.text
* @param {Boolean} [params.silent]
* @param {String} params.text Spinner's initial text
* @param {Boolean} [params.silent] Ignores all spinner messages and frames
* @returns {Spinner}
*/
const createSpinner = ({ text, silent }) => {
Expand All @@ -20,6 +22,7 @@ const createSpinner = ({ text, silent }) => {

return {
/**
* Starts created spinner
* @memberof Spinner
* @returns {Spinner}
*/
Expand All @@ -34,6 +37,7 @@ const createSpinner = ({ text, silent }) => {
},

/**
* Checks spinner's current frame as succeed and returns spinner
* @memberof Spinner
* @param {String} text
* @returns {Spinner}
Expand All @@ -49,6 +53,7 @@ const createSpinner = ({ text, silent }) => {
},

/**
* Checks spinner's current frame as failed and returns spinner
* @memberof Spinner
* @param {String} text
* @returns {Spinner}
Expand All @@ -64,6 +69,7 @@ const createSpinner = ({ text, silent }) => {
},

/**
* Just changes spinner's current text
* @memberof Spinner
* @param {String} text
* @returns {Spinner}
Expand Down
26 changes: 20 additions & 6 deletions packages/sharec/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,24 @@ const { composeSteps, steps } = require('./steps')
const { CAUSES, InternalError } = require('./errors')

/**
* @param {NodeJS.Process} targetProcess
* Main sharec entrance, accepts node process all files and configuration
* On any error will notify user and exit with status 1
* In other cases will exit with status 0, and notify user with informative
* message
* In the future, should be moved to sharec-core package, all CLI things
* should be isolated in sharec-cli package or just sharec
* @param {NodeJS.Process} targetProcess Node process
* @returns {Promise<void>}
*/
async function sharec(targetProcess) {
// Input options
// input options
const { env } = targetProcess
const { _, ...options } = minimist(targetProcess.argv.slice(2))
const debugMode = env.DEBUG
const silentMode = options.s || options.silent
const disappearMode = options.d || options.disappear
const overwriteMode = options.o || options.overwrite
const includeCacheMode = options.c || options['include-cache']

// CLI utilities
const spinner = createSpinner({
Expand All @@ -27,17 +34,21 @@ async function sharec(targetProcess) {
silent: !debugMode,
})

// Steps preparation and definition
// steps preparation and definition
const targetPath = targetProcess.env.INIT_CWD
const configPath = pwd().stdout
const input = {
targetPath,
configPath,
configs: {},
mergedConfigs: {},
cache: {},
options: {
silent: silentMode,
overwrite: overwriteMode,
disappear: disappearMode,
debug: debugMode,
includeCache: includeCacheMode,
},
}

Expand All @@ -52,17 +63,18 @@ async function sharec(targetProcess) {
logger.wrap(steps.isIgnoresSharecConfigs(spinner), 'isIgnoresSharecConfigs'),
logger.wrap(steps.readConfigs(spinner), 'readConfigs'),
logger.wrap(steps.readCache(spinner), 'readCache'),
logger.wrap(steps.writeConfigs(spinner, 'writeConfigs')),
logger.wrap(steps.mergeConfigs(spinner), 'mergeConfigs'),
logger.wrap(steps.insertMeta(spinner), 'insertMeta'),
logger.wrap(steps.insertEOL(spinner), 'insertEOL'),
logger.wrap(steps.writeCache(spinner), 'writeCache'),
logger.wrap(steps.writeMeta(spinner), 'writeMeta'),
logger.wrap(steps.writeConfigs(spinner, 'writeConfigs')),
)

try {
const finalInput = await commonFlow(input)

logger.log('final input\n', finalInput)
spinner.succeed('configuration was installed')

targetProcess.exit(0)
} catch (err) {
if (!(err instanceof InternalError)) {
Expand All @@ -71,6 +83,7 @@ async function sharec(targetProcess) {
targetProcess.exit(1)
}

// errors which can be handled
switch (err.cause) {
case CAUSES.IS_DEPENDANT_OF_SHAREC.symbol:
case CAUSES.IS_IGNORES_SHAREC.symbol:
Expand All @@ -79,6 +92,7 @@ async function sharec(targetProcess) {
spinner.succeed(err.message)
break
default:
// unhadled internal errors
spinner.fail(err.message)
targetProcess.exit(1)
}
Expand Down
11 changes: 11 additions & 0 deletions packages/sharec/src/parsers/json/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
const json8 = require('json8')

/**
* Creates map from JSON string with order saving
* @param {String} str Raw JSON string
* @returns {Map}
*/
const fromJSON = (str) => json8.parse(str, { map: true })

/**
* Transforms given map to JSON string with order saving
* @param {Map} map Any map
* @param {Number} [space] Indent spaces count
* @returns {String}
*/
const toJSON = (map, space = 2) => json8.serialize(map, { space })

module.exports = {
Expand Down
4 changes: 3 additions & 1 deletion packages/sharec/src/parsers/json/test/base.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ describe('parsers > json', () => {

describe('toJSON', () => {
it('should create JSON string from Map', () => {
expect(toJSON(defaultFxtMap)).toWraplessEqual(defaultFxt.current)
expect(toJSON(defaultFxtMap)).toWraplessEqual(defaultFxt.current, {
eol: false,
})
})
})
})
10 changes: 10 additions & 0 deletions packages/sharec/src/parsers/yaml/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
const { safeLoad, safeDump } = require('js-yaml')

/**
* Creates JSON string from YAML string with order saving
* @param {String} str Raw YAML string
* @returns {String}
*/
const fromYAML = (str) => JSON.stringify(safeLoad(str), null, 2)

/**
* Transforms given JSON string to YAML string with order saving
* @param {String} str JSON string
* @returns {String}
*/
const toYAML = (str) => safeDump(JSON.parse(str))

module.exports = {
Expand Down
8 changes: 6 additions & 2 deletions packages/sharec/src/parsers/yaml/test/base.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ describe('parsers > yaml', () => {

describe('fromYAML', () => {
it('should create Map from given YAML', () => {
expect(fromYAML(defaultFxtYAML.current)).toWraplessEqual(defaultFxt.current)
expect(fromYAML(defaultFxtYAML.current)).toWraplessEqual(defaultFxt.current, {
eol: false,
})
})
})

describe('toYAML', () => {
it('should create YAML string from Map', () => {
expect(toYAML(defaultFxt.current)).toWraplessEqual(defaultFxtYAML.current)
expect(toYAML(defaultFxt.current)).toWraplessEqual(defaultFxtYAML.current, {
eol: false,
})
})
})
})
46 changes: 37 additions & 9 deletions packages/sharec/src/steps/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,61 @@ const readConfigs = require('./readConfigs')
const readTargetPackage = require('./readTargetPackage')
const readUpcomingPackage = require('./readUpcomingPackage')
const readCache = require('./readCache')
// Processing
const mergeConfigs = require('./mergeConfigs')
const insertEOL = require('./insertEOL')
// Output
const writeConfigs = require('./writeConfigs')
const writeMeta = require('./writeMeta')
const insertMeta = require('./insertMeta')
const writeCache = require('./writeCache')

const composeSteps = (...steps) => async (input) => {
let lastInput = input
/**
* @typedef {Object} Input
* @property {String} targetPath Target project path
* @property {String} configPath Upcoming configuration path
* @property {Object} options Different options from CLI
* @property {Boolean} options.silent Disables all messages from sharec
* @property {Boolean} options.overwrite Forcily replaces all configs by new ones
* @property {Boolean} options.disappeara Do not write cache and sharec meta to target project
* @property {Boolean} options.debug Enables debug messages
*/

for (const step of steps) {
lastInput = await step(lastInput)
}
/**
* Composes steps in one function
* Executes each step and pass result to the next one
* @param {Array<Function>} steps Steps functions
* @returns {Function}
*/
const composeSteps = (...steps) =>
/**
* @param {Input} input
* @returns {Input}
*/
async (input) => {
let lastInput = input

return lastInput
}
for (const step of steps) {
lastInput = await step(lastInput)
}

return lastInput
}

const steps = {
isAlreadyInstalled,
isDependantOfSharec,
isIgnoresSharecConfigs,

mergeConfigs,
insertEOL,
insertMeta,

readConfigs,
readTargetPackage,
readUpcomingPackage,
readCache,

writeConfigs,
writeMeta,
writeCache,
}

Expand Down
19 changes: 19 additions & 0 deletions packages/sharec/src/steps/insertEOL.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const insertEOL = (spinner) => async (input) => {
const { mergedConfigs } = input

spinner.frame('inserting EOL')

for (const config in mergedConfigs) {
const withEOL = /^\s*$/gm.test(mergedConfigs[config])

if (withEOL) continue

input.mergedConfigs[config] = mergedConfigs[config] + '\n'
}

spinner.frame('EOL was inserted')

return input
}

module.exports = insertEOL
Loading

0 comments on commit f8436c7

Please sign in to comment.