Skip to content

Commit f8ab8fa

Browse files
author
Piotr Oleś
committed
Initial implementation
1 parent 3299f42 commit f8ab8fa

19 files changed

+3841
-109
lines changed

.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Coverage directory used by tools like istanbul
7+
coverage
8+
9+
# Dependency directories
10+
node_modules
11+
jspm_packages
12+
13+
# Optional npm cache directory
14+
.npm
15+
16+
# Optional REPL history
17+
.node_repl_history
18+
19+
# IDEA directory
20+
.idea

.npmignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/coverage
2+
/examples
3+
/test
4+
yarn.lock
5+
.idea
6+
.travis.yml
7+
.nvmrc
8+
karma.conf.js

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
6.9.4

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: node_js
2+
after_success: npm run coveralls
3+
deploy:
4+
provider: npm
5+
6+
api_key:
7+
secure: qp9hx3Xm6avFvDjwhjhyAwJ0jv360ga7jfip3gb8WjDn0pc0IfhLQl5MCsNBRY7/4yAU53WzbpnvZRWxMf6U2mYWxqEVlphkk+2UN/k1kJhVPEhH04pLhcsQ/kIpt+660VVEfUjQuDPpJh0KuMy5uJFhGihK77moDDe8Op3XNRGnjqnV/84eNeNJmiu0Z25/5wfhaErBYGtGXkHY5Pfs4OBMG910t+p/4gBJjhYwwPWLdIYX/kQSfO5sA0IDxAY7ttX+IdEsE3lzMT/AI+y3vySgTjiuJ7pxhh+mzfL6pfWLBeUwiaeQdpsqvGWq2bzzdHHqtajCPQOzGMhJcf/nWUVUp0ZOUvFweEMG3J61vAbvbYNJ8/z8fPfYPW5VplFdzyCmPWPJIGRyrdDEqQ7KyHz01naNsVhuJC+eLOS2EjDcZpscPuVY7nR6PHoezMvugMl24nMhixbJF7XO/2h+oC8IS1ni8nlnnpzFxc2nJbyXfDNiLDI0ZCyntmTel5NfJ90sPuU1JAIL7CvRblJab487tPIVGGXQIapPdRguhs0G6Y9498axSOvmhdaeuDnDprX0niirnPXPd7lt6tvZHcBrCEhUCpDYJOBQHqLvz1G7sIheNLIDmPCT1IxW14wVIbKV/HIFzJ/ef3t1ASYdSQnFVRAKzG+qLha0ip4TD7M=
8+
on:
9+
tags: true
10+
branch: master

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Piotr Oleś
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.

README.md

Lines changed: 50 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,64 @@
1-
# Redux Detector
2-
[![Npm version](https://img.shields.io/npm/v/redux-detector.svg?style=flat-square)](https://www.npmjs.com/package/redux-detector)
3-
[![Build Status](https://travis-ci.org/piotr-oles/redux-detector.svg?branch=master)](https://travis-ci.org/piotr-oles/redux-detector)
4-
[![Coverage Status](https://coveralls.io/repos/github/piotr-oles/redux-detector/badge.svg?branch=master)](https://coveralls.io/github/piotr-oles/redux-detector?branch=master)
1+
# Fork TS Checker Webpack Plugin
2+
[![Npm version](https://img.shields.io/npm/v/@realytics/fork-ts-checker-webpack-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@realytics/fork-ts-checker-webpack-plugin)
3+
[![Build Status](https://travis-ci.org/realytics/fork-ts-checker-webpack-plugin.svg?branch=master)](https://travis-ci.org/realytics/fork-ts-checker-webpack-plugin)
4+
[![Coverage Status](https://coveralls.io/repos/github/realytics/fork-ts-checker-webpack-plugin/badge.svg?branch=master)](https://coveralls.io/github/realytics/fork-ts-checker-webpack-plugin?branch=master)
55

6-
Redux [enhancer](http://redux.js.org/docs/api/createStore.html) for pure detection of state changes.
6+
Webpack plugin that runs typescript type checker (and eventually linter) on separate process.
77

88
**Warning: API is not stable yet, will be from version 1.0**
99

1010
## Installation ##
11-
Redux Detector requires **Redux 3.1.0 or later.**
11+
This plugin is compatible with **Webpack 2**, **TypeScript 2.1** and **tslint 5.0**
1212
```sh
13-
npm install --save redux-detector
13+
npm install --save fork-ts-checker-webpack-plugin
1414
```
15-
This assumes that you’re using [npm](http://npmjs.com/) package manager with a module bundler like
16-
[Webpack](http://webpack.github.io/) or [Browserify](http://browserify.org/) to consume
17-
[CommonJS modules](http://webpack.github.io/docs/commonjs.html).
18-
19-
To enable Redux Detector, use `createDetectableStore`:
20-
```js
21-
import { createDetectableStore } from 'redux-detector';
22-
import rootReducer from './reducers/index';
23-
import rootDetector from './detectors/index';
24-
25-
const store = createDetectableStore(
26-
rootReducer,
27-
rootDetector
28-
);
29-
```
30-
31-
or if you have more complicated store creation, use `createStore` with `createDetectorEnhancer`:
15+
Basic webpack config (with [ts-loader](https://github.com/TypeStrong/ts-loader))
3216
```js
33-
import { createStore } from 'redux';
34-
import { createDetectorEnhancer } from 'redux-detector';
35-
import rootReducer from './reducers/index';
36-
import rootDetector from './detectors/index';
37-
38-
const store = createStore(
39-
rootReducer,
40-
createDetectorEnhancer(rootDetector)
41-
);
17+
var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
18+
19+
var webpackConfig = {
20+
context: __dirname, // to automatically find tsconfig.json
21+
entry: './src/index.ts',
22+
output: {
23+
path: 'dist',
24+
filename: 'index.js'
25+
},
26+
module: {
27+
rules: [
28+
{
29+
test: /\.tsx?$/,
30+
include: './src',
31+
loader: 'ts-loader',
32+
options: {
33+
// disable type checker - we will use it in fork plugin
34+
transpileOnly: true
35+
}
36+
}
37+
]
38+
},
39+
plugins: [
40+
new ForkTsCheckerWebpackPlugin({
41+
watch: './src' // optional but improves performance (less stat calls)
42+
})
43+
]
44+
};
4245
```
4346

4447
## Motivation ##
45-
Redux Detector [enhancer](http://redux.js.org/docs/api/createStore.html) allows you to use state changes detectors with redux.
46-
Detector is a simple and pure function which compares two states and returns action or list of actions for some states configurations.
47-
It can be used for reacting on particular state transitions.
48-
```typescript
49-
type Detector<S> = (prevState: S | undefined, nextState: S) => ActionLike | ActionLike[] | void;
50-
```
51-
52-
For example detector that checks if number of rows exceed 100 looks like this:
53-
```js
54-
function rowsLimitExceededDetector(prevState, nextState) {
55-
if (prevState.rows.length <= 100 && nextState.rows.length > 100) {
56-
return { type: ROWS_LIMIT_EXCEEDED };
57-
}
58-
}
59-
```
60-
You can also return array of actions or nothing (undefined).
61-
Thanks to detectors purity they are predictable and easy to test. There is no problem with features like time-travel, etc.
62-
63-
## Composition ##
64-
Redux store can handle only one detector (and one reducer). But don't worry - you can combine and reduce them. To do this, use
65-
`combineDetectors` and `reduceDetectors` functions.
66-
```js
67-
// ./detectors/rootDetector.js
68-
import { combineDetectors, reduceDetectors } from 'redux-detector';
69-
import { fooDetector } from './fooDetector';
70-
import { barDetector } from './barDetector';
71-
import { anotherDetector } from './anotherDetector';
72-
73-
// our state has shape:
74-
// {
75-
// foo: [],
76-
// bar: 1
77-
// }
78-
//
79-
// We want to bind `fooDetector` and `anotherDetector` to `state.foo` branch (they should run in sequence)
80-
// and also `barDetector` to `state.bar` branch.
81-
82-
export default combineDetectors({
83-
foo: reduceDetectors(
84-
fooDetector,
85-
anotherDetector
86-
),
87-
bar: barDetector
88-
});
89-
```
90-
91-
Another way to re-use local state detectors is to mount them with `mountDetector` function. Combine detectors works only on objects level -
92-
if you want to use detectors on more nested data, you should mount them. With factory pattern it becomes very elastic.
93-
```js
94-
// ./detectors/limitExceedDetector.js
95-
export function createLimitExceedDetector(limit, action) {
96-
return function limitExceedDetector(prevState, nextState) {
97-
if (prevState <= limit && nextState > limit) {
98-
return action;
99-
}
100-
}
101-
}
102-
103-
// ./detectors/rowsLimitExceedDetector.js
104-
import { mountDetector } from 'redux-detector';
105-
import { createLimitExceeedDetector } from './limitExceedDetector';
106-
107-
export const rowsLimitExceedDetector = mountDetector(
108-
state => state.rows.length,
109-
createLimitExceedDetector(100, ROWS_LIMIT_EXCEEDED)
110-
);
111-
```
112-
Of course examples above are very trivial, but you can use it to solve more common problems
113-
(you can for example schedule resource fetch on parameters change).
114-
115-
## Code Splitting ##
116-
Redux Detector provides `replaceDetector` method on `DetectableStore` interface (store created by Redux Detector). It's similar to
117-
`replaceReducer` - it changes detector and dispatches `{ type: '@@detector/INIT' }`.
118-
119-
## Typings ##
120-
If you are using [TypeScript](https://www.typescriptlang.org/), you don't have to install typings - they are provided in npm package.
48+
TODO
49+
50+
## Options ##
51+
| option | type | description |
52+
|--------|------|-------------|
53+
|**tsconfig**| `string` | Path to tsconfig.json file. If not set, plugin will use `path.resolve(compiler.context, './tsconfig.json')`. |
54+
|**tslint**| `string` or `false` | Path to tslint.json file. If not set, plugin will use `path.resolve(compiler.context, './tslint.json')`. If `false`, disables tslint.|
55+
|**watch**| `string` or `string[]` | Files or directories to watch be service. Not necessary but improves performance (reduces number of `fs.stat` calls). |
56+
|**blockEmit**| `boolean` | If `true`, plugin will block emit until check will be done. It's good setting for ci/production build because webpack will return code != 0 if there are type/lint errors. Default: `false`. |
57+
|**ignoreDiagnostics**| `number[]` | List of typescript diagnostic codes to ignore. |
58+
|**ignoreLints**| `string[]` | List of tslint rule names to ignore. |
59+
|**colors**| `boolean` | If `false`, disables colors for logger. Default: `true`. |
60+
|**logger**| `LoggerInterface` | Logger instance. It should be object that implements method: `error`, `warn`, `info`. Default: `console`.|
61+
|**silent**| `boolean` | If `true`, logger will not be used. Default: `false`.|
12162

12263
## License ##
12364
MIT

karma.conf.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var webpack = require('webpack');
2+
var path = require('path');
3+
var process = require('process');
4+
5+
module.exports = function (config) {
6+
config.set({
7+
browsers: ['PhantomJS'],
8+
singleRun: true,
9+
colors: true,
10+
frameworks: ['mocha', 'chai'],
11+
files: [
12+
'lib/**/*.js',
13+
'test/**/*.spec.js'
14+
],
15+
reporters: ['dots'],
16+
karmaTypescriptConfig: {
17+
reports: {
18+
'lcovonly': {
19+
'directory': 'coverage',
20+
'subdirectory': 'lcov',
21+
'filename': 'lcov.info'
22+
},
23+
'html': {
24+
'directory': 'coverage',
25+
'subdirectory': 'html',
26+
'filename': '.'
27+
},
28+
'text': ''
29+
}
30+
}
31+
});
32+
};

lib/CancellationToken.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
var ts = require('typescript');
2+
var fs = require('fs');
3+
var os = require('os');
4+
var path = require('path');
5+
var crypto = require('crypto');
6+
7+
function CancellationToken(cancellationFileName, isCancelled) {
8+
this.isCancelled = !!isCancelled;
9+
this.cancellationFileName = cancellationFileName || crypto.randomBytes(64).toString('hex');
10+
this.lastCancellationCheckTime = 0;
11+
}
12+
module.exports = CancellationToken;
13+
14+
CancellationToken.createFromJSON = function(json) {
15+
return new CancellationToken(
16+
json.cancellationFileName,
17+
json.isCancelled
18+
);
19+
};
20+
21+
CancellationToken.prototype.toJSON = function() {
22+
return {
23+
cancellationFileName: this.cancellationFileName,
24+
isCancelled: this.isCancelled
25+
};
26+
};
27+
28+
CancellationToken.prototype.isCancellationRequested = function() {
29+
if (this.isCancelled) {
30+
return true;
31+
}
32+
33+
var time = Date.now();
34+
var duration = Math.abs(time - this.lastCancellationCheckTime);
35+
36+
if (duration > 10) {
37+
// check no more than once every 10ms
38+
this.lastCancellationCheckTime = time;
39+
this.isCancelled = fs.existsSync(getCancellationFilePath(this.cancellationFileName));
40+
}
41+
42+
return this.isCancelled;
43+
};
44+
45+
CancellationToken.prototype.throwIfCancellationRequested = function() {
46+
if (this.isCancellationRequested()) {
47+
throw new ts.OperationCanceledException();
48+
}
49+
};
50+
51+
CancellationToken.prototype.requestCancellation = function() {
52+
fs.writeFileSync(getCancellationFilePath(this.cancellationFileName), '');
53+
};
54+
55+
CancellationToken.prototype.cleanupCancellation = function () {
56+
if (this.isCancelled) {
57+
fs.unlink(getCancellationFilePath(this.cancellationFileName));
58+
}
59+
};
60+
61+
function getCancellationFilePath(cancellationFileName) {
62+
return path.join(os.tmpdir(), cancellationFileName);
63+
}

0 commit comments

Comments
 (0)