@via-profit/ability 3.3.0 → 3.4.0
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/CHANGELOG.md +2 -2
- package/CONTRIBUTING.md +14 -14
- package/LICENSE +21 -21
- package/README.md +1374 -1346
- package/SECURITY.md +33 -33
- package/dist/core/AbilityCondition.d.ts +4 -2
- package/dist/index.js +59 -10
- package/dist/parsers/dsl/AbilityDSLParser.d.ts +0 -1
- package/dist/parsers/dsl/AbilityDSLToken.d.ts +3 -1
- package/package.json +73 -73
package/SECURITY.md
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Reporting a Vulnerability
|
|
4
|
-
|
|
5
|
-
I take the security of `@via-profit/ability` seriously. If you discover a security vulnerability, please report it responsibly.
|
|
6
|
-
|
|
7
|
-
### How to Report a Vulnerability
|
|
8
|
-
|
|
9
|
-
**Please DO NOT create a public GitHub issue for security vulnerabilities.**
|
|
10
|
-
|
|
11
|
-
Instead, send the details directly to me:
|
|
12
|
-
|
|
13
|
-
- **Email**: [delhsmail@gmail.com](mailto:delhsmail@gmail.com)
|
|
14
|
-
- **Author**: Vasily Novosad
|
|
15
|
-
- **Timezone**: UTC+5 (for coordinating response time)
|
|
16
|
-
|
|
17
|
-
### What to Include
|
|
18
|
-
|
|
19
|
-
To help me address the issue quickly, please include:
|
|
20
|
-
|
|
21
|
-
- Description of the vulnerability
|
|
22
|
-
- Steps to reproduce (if applicable)
|
|
23
|
-
- Potential impact
|
|
24
|
-
- Suggestions for fixing (if any)
|
|
25
|
-
|
|
26
|
-
### Process
|
|
27
|
-
|
|
28
|
-
1. I will acknowledge your report within 48 hours
|
|
29
|
-
2. I will assess the vulnerability
|
|
30
|
-
3. Work on a fix will begin depending on severity
|
|
31
|
-
4. After the fix is released, I will notify you and acknowledge your contribution (if you agree)
|
|
32
|
-
|
|
33
|
-
Thank you for helping keep this project secure!
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
I take the security of `@via-profit/ability` seriously. If you discover a security vulnerability, please report it responsibly.
|
|
6
|
+
|
|
7
|
+
### How to Report a Vulnerability
|
|
8
|
+
|
|
9
|
+
**Please DO NOT create a public GitHub issue for security vulnerabilities.**
|
|
10
|
+
|
|
11
|
+
Instead, send the details directly to me:
|
|
12
|
+
|
|
13
|
+
- **Email**: [delhsmail@gmail.com](mailto:delhsmail@gmail.com)
|
|
14
|
+
- **Author**: Vasily Novosad
|
|
15
|
+
- **Timezone**: UTC+5 (for coordinating response time)
|
|
16
|
+
|
|
17
|
+
### What to Include
|
|
18
|
+
|
|
19
|
+
To help me address the issue quickly, please include:
|
|
20
|
+
|
|
21
|
+
- Description of the vulnerability
|
|
22
|
+
- Steps to reproduce (if applicable)
|
|
23
|
+
- Potential impact
|
|
24
|
+
- Suggestions for fixing (if any)
|
|
25
|
+
|
|
26
|
+
### Process
|
|
27
|
+
|
|
28
|
+
1. I will acknowledge your report within 48 hours
|
|
29
|
+
2. I will assess the vulnerability
|
|
30
|
+
3. Work on a fix will begin depending on severity
|
|
31
|
+
4. After the fix is released, I will notify you and acknowledge your contribution (if you agree)
|
|
32
|
+
|
|
33
|
+
Thank you for helping keep this project secure!
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AbilityCode from './AbilityCode';
|
|
2
|
-
export type AbilityConditionCodeType = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in' | 'contains' | 'not contains' | 'length greater than' | 'length less than' | 'length equals';
|
|
3
|
-
export type AbilityConditionLiteralType = 'equals' | 'not_equals' | 'contains' | 'no_contains' | 'in' | 'not_in' | 'greater_than' | 'less_than' | 'less_or_equal' | 'greater_or_equal' | 'length_greater_than' | 'length_less_than' | 'length_equals';
|
|
2
|
+
export type AbilityConditionCodeType = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in' | 'contains' | 'not contains' | 'length greater than' | 'length less than' | 'length equals' | 'always' | 'never';
|
|
3
|
+
export type AbilityConditionLiteralType = 'equals' | 'not_equals' | 'contains' | 'no_contains' | 'in' | 'not_in' | 'greater_than' | 'less_than' | 'less_or_equal' | 'greater_or_equal' | 'length_greater_than' | 'length_less_than' | 'length_equals' | 'always' | 'never';
|
|
4
4
|
export declare class AbilityCondition extends AbilityCode<AbilityConditionCodeType> {
|
|
5
5
|
static equals: AbilityCondition;
|
|
6
6
|
static not_equals: AbilityCondition;
|
|
@@ -15,6 +15,8 @@ export declare class AbilityCondition extends AbilityCode<AbilityConditionCodeTy
|
|
|
15
15
|
static length_greater_than: AbilityCondition;
|
|
16
16
|
static length_less_than: AbilityCondition;
|
|
17
17
|
static length_equals: AbilityCondition;
|
|
18
|
+
static always: AbilityCondition;
|
|
19
|
+
static never: AbilityCondition;
|
|
18
20
|
static fromLiteral(literal: AbilityConditionLiteralType): AbilityCondition;
|
|
19
21
|
get literal(): AbilityConditionLiteralType;
|
|
20
22
|
}
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,8 @@ class AbilityCondition extends AbilityCode {
|
|
|
46
46
|
static length_greater_than = new AbilityCondition('length greater than');
|
|
47
47
|
static length_less_than = new AbilityCondition('length less than');
|
|
48
48
|
static length_equals = new AbilityCondition('length equals');
|
|
49
|
+
static always = new AbilityCondition('always');
|
|
50
|
+
static never = new AbilityCondition('never');
|
|
49
51
|
static fromLiteral(literal) {
|
|
50
52
|
switch (literal) {
|
|
51
53
|
case 'equals':
|
|
@@ -72,6 +74,10 @@ class AbilityCondition extends AbilityCode {
|
|
|
72
74
|
return this.length_greater_than;
|
|
73
75
|
case 'length_equals':
|
|
74
76
|
return this.length_equals;
|
|
77
|
+
case 'always':
|
|
78
|
+
return this.always;
|
|
79
|
+
case 'never':
|
|
80
|
+
return this.never;
|
|
75
81
|
default:
|
|
76
82
|
throw new AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);
|
|
77
83
|
}
|
|
@@ -627,6 +633,10 @@ class AbilityRule {
|
|
|
627
633
|
let is = false;
|
|
628
634
|
const [subjectValue, resourceValue] = this.extractValues(resource, environment);
|
|
629
635
|
const isValue = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null;
|
|
636
|
+
// always
|
|
637
|
+
if (AbilityCondition.always.isEqual(this.condition)) {
|
|
638
|
+
is = true;
|
|
639
|
+
}
|
|
630
640
|
// equals
|
|
631
641
|
if (AbilityCondition.equals.isEqual(this.condition)) {
|
|
632
642
|
is = subjectValue === resourceValue;
|
|
@@ -1221,6 +1231,8 @@ class AbilityDSLToken extends AbilityCode {
|
|
|
1221
1231
|
static LEN_LT = 'LEN_LT';
|
|
1222
1232
|
static LEN_EQ = 'LEN_EQ';
|
|
1223
1233
|
static NOT_EQ = 'NOT_EQ';
|
|
1234
|
+
static ALWAYS = 'ALWAYS';
|
|
1235
|
+
static NEVER = 'NEVER';
|
|
1224
1236
|
static STRING = 'STRING';
|
|
1225
1237
|
static NUMBER = 'NUMBER';
|
|
1226
1238
|
static BOOLEAN = 'BOOLEAN';
|
|
@@ -1263,6 +1275,8 @@ class AbilityDSLLexer {
|
|
|
1263
1275
|
'is',
|
|
1264
1276
|
'or',
|
|
1265
1277
|
'than',
|
|
1278
|
+
'always',
|
|
1279
|
+
'never',
|
|
1266
1280
|
]);
|
|
1267
1281
|
constructor(input) {
|
|
1268
1282
|
this.input = input;
|
|
@@ -1408,6 +1422,12 @@ class AbilityDSLLexer {
|
|
|
1408
1422
|
}
|
|
1409
1423
|
}
|
|
1410
1424
|
const word = this.input.slice(start, this.pos);
|
|
1425
|
+
if (word === 'always') {
|
|
1426
|
+
return new AbilityDSLToken(AbilityDSLToken.ALWAYS, word, startLine, startColumn);
|
|
1427
|
+
}
|
|
1428
|
+
if (word === 'never') {
|
|
1429
|
+
return new AbilityDSLToken(AbilityDSLToken.NEVER, word, startLine, startColumn);
|
|
1430
|
+
}
|
|
1411
1431
|
// Если есть точка — это путь (identifier или permission)
|
|
1412
1432
|
if (word.includes('.')) {
|
|
1413
1433
|
const last = this.tokens[this.tokens.length - 1];
|
|
@@ -1670,7 +1690,9 @@ class AbilityDSLParser {
|
|
|
1670
1690
|
if (this.isStartOfGroup() || this.isStartOfPolicy()) {
|
|
1671
1691
|
break;
|
|
1672
1692
|
}
|
|
1673
|
-
if (this.check(AbilityDSLToken.IDENTIFIER)
|
|
1693
|
+
if (this.check(AbilityDSLToken.IDENTIFIER) ||
|
|
1694
|
+
this.check(AbilityDSLToken.ALWAYS) ||
|
|
1695
|
+
this.check(AbilityDSLToken.NEVER)) {
|
|
1674
1696
|
group.addRule(this.parseRule());
|
|
1675
1697
|
}
|
|
1676
1698
|
else {
|
|
@@ -1687,7 +1709,7 @@ class AbilityDSLParser {
|
|
|
1687
1709
|
parseGroup() {
|
|
1688
1710
|
this.consumeLeadingComments();
|
|
1689
1711
|
const meta = this.takeAnnotations();
|
|
1690
|
-
const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY], 'Expected "all" or "any"');
|
|
1712
|
+
const compareToken = this.consumeOneOf([AbilityDSLToken.ALL, AbilityDSLToken.ANY, AbilityDSLToken.ALWAYS, AbilityDSLToken.NEVER], 'Expected "all" or "any" or "always" or "never"');
|
|
1691
1713
|
const compareMethod = compareToken.code === AbilityDSLToken.ALL ? AbilityCompare.and : AbilityCompare.or;
|
|
1692
1714
|
if (this.check(AbilityDSLToken.OF)) {
|
|
1693
1715
|
this.advance();
|
|
@@ -1717,11 +1739,26 @@ class AbilityDSLParser {
|
|
|
1717
1739
|
parseRule() {
|
|
1718
1740
|
this.consumeLeadingComments();
|
|
1719
1741
|
const meta = this.takeAnnotations();
|
|
1720
|
-
if (
|
|
1721
|
-
|
|
1742
|
+
// if (this.check(AbilityDSLToken.ALWAYS) || this.check(AbilityDSLToken.NEVER)) {
|
|
1743
|
+
// // Checking that there are no extra tokens after the value
|
|
1744
|
+
// // (skip comments)
|
|
1745
|
+
// this.consumeLeadingComments();
|
|
1746
|
+
// const specOperator = this.consume();
|
|
1747
|
+
// // return new AbilityRule({
|
|
1748
|
+
// // subject: '',
|
|
1749
|
+
// // resource,
|
|
1750
|
+
// // condition,
|
|
1751
|
+
// // name: meta.name,
|
|
1752
|
+
// // });
|
|
1753
|
+
// }
|
|
1754
|
+
const isNeverAlways = this.check(AbilityDSLToken.ALWAYS) || this.check(AbilityDSLToken.NEVER);
|
|
1755
|
+
if (!isNeverAlways && !this.check(AbilityDSLToken.IDENTIFIER)) {
|
|
1756
|
+
this.syntaxError(`Expected identifier, but got ${this.peek().code}`, this.peek());
|
|
1722
1757
|
}
|
|
1723
1758
|
// Subject (e.g., "user.roles")
|
|
1724
|
-
const subject =
|
|
1759
|
+
const subject = isNeverAlways
|
|
1760
|
+
? ''
|
|
1761
|
+
: this.consume(AbilityDSLToken.IDENTIFIER, 'Expected field').value;
|
|
1725
1762
|
// Operator (e.g., "contains", "equals", "is not null")
|
|
1726
1763
|
const { condition, operator } = this.parseConditionOperator();
|
|
1727
1764
|
let resource;
|
|
@@ -1729,7 +1766,9 @@ class AbilityDSLParser {
|
|
|
1729
1766
|
// Special operators that don't consume a value token.
|
|
1730
1767
|
if (operator === AbilityDSLToken.EQ_NULL ||
|
|
1731
1768
|
operator === AbilityDSLToken.NOT_EQ_NULL ||
|
|
1732
|
-
operator === AbilityDSLToken.NULL
|
|
1769
|
+
operator === AbilityDSLToken.NULL ||
|
|
1770
|
+
operator === AbilityDSLToken.ALWAYS ||
|
|
1771
|
+
operator === AbilityDSLToken.NEVER) {
|
|
1733
1772
|
resource = null;
|
|
1734
1773
|
}
|
|
1735
1774
|
else {
|
|
@@ -1761,6 +1800,16 @@ class AbilityDSLParser {
|
|
|
1761
1800
|
*/
|
|
1762
1801
|
parseConditionOperator() {
|
|
1763
1802
|
const savedPos = this.pos;
|
|
1803
|
+
// "always"
|
|
1804
|
+
if (this.matchWord('always')) {
|
|
1805
|
+
return { condition: AbilityCondition.always, operator: AbilityDSLToken.ALWAYS };
|
|
1806
|
+
}
|
|
1807
|
+
this.pos = savedPos;
|
|
1808
|
+
// "never"
|
|
1809
|
+
if (this.matchWord('never')) {
|
|
1810
|
+
return { condition: AbilityCondition.never, operator: AbilityDSLToken.NEVER };
|
|
1811
|
+
}
|
|
1812
|
+
this.pos = savedPos;
|
|
1764
1813
|
// "length equals"
|
|
1765
1814
|
if (this.matchWord('length') && this.matchWord('equals')) {
|
|
1766
1815
|
return { condition: AbilityCondition.length_equals, operator: AbilityDSLToken.LEN_EQ };
|
|
@@ -1956,7 +2005,10 @@ class AbilityDSLParser {
|
|
|
1956
2005
|
return false;
|
|
1957
2006
|
}
|
|
1958
2007
|
const token = this.peek();
|
|
1959
|
-
if ((token.code === AbilityDSLToken.KEYWORD ||
|
|
2008
|
+
if ((token.code === AbilityDSLToken.KEYWORD ||
|
|
2009
|
+
token.code === AbilityDSLToken.IDENTIFIER ||
|
|
2010
|
+
token.code === AbilityDSLToken.ALWAYS ||
|
|
2011
|
+
token.code === AbilityDSLToken.NEVER) &&
|
|
1960
2012
|
token.value === word) {
|
|
1961
2013
|
this.advance();
|
|
1962
2014
|
return true;
|
|
@@ -2101,9 +2153,6 @@ class AbilityDSLParser {
|
|
|
2101
2153
|
}
|
|
2102
2154
|
throw new AbilityDSLSyntaxError(token.line, token.column, context + '\n', finalDetails);
|
|
2103
2155
|
}
|
|
2104
|
-
getLine(lineNumber) {
|
|
2105
|
-
return this.dsl.split(/\r?\n/)[lineNumber - 1] ?? '';
|
|
2106
|
-
}
|
|
2107
2156
|
suggest(actual, expectedTypes) {
|
|
2108
2157
|
const candidates = [];
|
|
2109
2158
|
for (const type of expectedTypes) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AbilityCode from '../../core/AbilityCode';
|
|
2
|
-
export type TokenType = 'EFFECT' | 'IF' | 'PERMISSION' | 'IDENTIFIER' | 'COLON' | 'COMMA' | 'DOT' | 'LBRACKET' | 'RBRACKET' | 'ALL' | 'ANY' | 'OF' | 'EOF' | 'COMMENT' | 'EQ' | 'CONTAINS' | 'IN' | 'NOT_IN' | 'NOT_CONTAINS' | 'GT' | 'GTE' | 'LT' | 'LTE' | 'NULL' | 'EQ_NULL' | 'NOT_EQ_NULL' | 'NOT_EQ' | 'LEN_GT' | 'LEN_LT' | 'LEN_EQ' | 'STRING' | 'NUMBER' | 'BOOLEAN' | 'SYMBOL' | 'KEYWORD' | 'UNKNOWN';
|
|
2
|
+
export type TokenType = 'EFFECT' | 'IF' | 'PERMISSION' | 'IDENTIFIER' | 'COLON' | 'COMMA' | 'DOT' | 'LBRACKET' | 'RBRACKET' | 'ALL' | 'ANY' | 'OF' | 'EOF' | 'COMMENT' | 'EQ' | 'CONTAINS' | 'IN' | 'NOT_IN' | 'NOT_CONTAINS' | 'GT' | 'GTE' | 'LT' | 'LTE' | 'NULL' | 'EQ_NULL' | 'NOT_EQ_NULL' | 'NOT_EQ' | 'LEN_GT' | 'LEN_LT' | 'LEN_EQ' | 'ALWAYS' | 'NEVER' | 'STRING' | 'NUMBER' | 'BOOLEAN' | 'SYMBOL' | 'KEYWORD' | 'UNKNOWN';
|
|
3
3
|
/**
|
|
4
4
|
* Represents a single token produced by the Ability DSL lexer.
|
|
5
5
|
* Each token carries a type (e.g., EFFECT, IDENTIFIER, STRING) and its raw string value.
|
|
@@ -47,6 +47,8 @@ export declare class AbilityDSLToken<Code extends TokenType = TokenType> extends
|
|
|
47
47
|
static readonly LEN_LT: TokenType;
|
|
48
48
|
static readonly LEN_EQ: TokenType;
|
|
49
49
|
static readonly NOT_EQ: TokenType;
|
|
50
|
+
static readonly ALWAYS: TokenType;
|
|
51
|
+
static readonly NEVER: TokenType;
|
|
50
52
|
static readonly STRING: TokenType;
|
|
51
53
|
static readonly NUMBER: TokenType;
|
|
52
54
|
static readonly BOOLEAN: TokenType;
|
package/package.json
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@via-profit/ability",
|
|
3
|
-
"support": "https://via-profit.ru",
|
|
4
|
-
"version": "3.
|
|
5
|
-
"description": "Via-Profit Ability service",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"ability",
|
|
8
|
-
"access",
|
|
9
|
-
"via-profit"
|
|
10
|
-
],
|
|
11
|
-
"main": "./dist/index.js",
|
|
12
|
-
"engines": {
|
|
13
|
-
"node": ">= 17.0.0",
|
|
14
|
-
"npm": ">= 8.19.3"
|
|
15
|
-
},
|
|
16
|
-
"files": [
|
|
17
|
-
"dist",
|
|
18
|
-
"README.md",
|
|
19
|
-
"LICENSE",
|
|
20
|
-
"CHANGELOG.md",
|
|
21
|
-
"CONTRIBUTING.md",
|
|
22
|
-
"SECURITY.md"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "rollup -c",
|
|
26
|
-
"build:dev": "cross-env NODE_ENV=development rollup -c -w",
|
|
27
|
-
"bench": "npm run build && node ./bench/benchmark.js",
|
|
28
|
-
"test": "jest",
|
|
29
|
-
"lint": "tsc --noEmit && eslint --fix .",
|
|
30
|
-
"pretty": "prettier --write ./src"
|
|
31
|
-
},
|
|
32
|
-
"repository": {
|
|
33
|
-
"type": "git",
|
|
34
|
-
"url": "https://github.com/via-profit/ability.git"
|
|
35
|
-
},
|
|
36
|
-
"author": {
|
|
37
|
-
"name": "Via Profit",
|
|
38
|
-
"url": "https://dev.via-profit.ru"
|
|
39
|
-
},
|
|
40
|
-
"contributors": [
|
|
41
|
-
"Vasily Novosad <delhsmail@gmail.com>",
|
|
42
|
-
"Pavel Natalin <trubonru@gmail.com>"
|
|
43
|
-
],
|
|
44
|
-
"license": "MIT",
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@eslint/js": "^9.13.0",
|
|
47
|
-
"@jagi/jest-transform-graphql": "^1.0.2",
|
|
48
|
-
"@jest/types": "^29.6.3",
|
|
49
|
-
"@rollup/plugin-alias": "^6.0.0",
|
|
50
|
-
"@rollup/plugin-commonjs": "^29.0.2",
|
|
51
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
52
|
-
"@rollup/plugin-typescript": "^12.3.0",
|
|
53
|
-
"@types/jest": "^29.5.13",
|
|
54
|
-
"@types/node": "^22.7.7",
|
|
55
|
-
"@types/nodemon": "^1.19.6",
|
|
56
|
-
"concurrently": "^9.0.1",
|
|
57
|
-
"cross-env": "^7.0.3",
|
|
58
|
-
"eslint": "^9.13.0",
|
|
59
|
-
"globals": "^15.11.0",
|
|
60
|
-
"jest": "^29.7.0",
|
|
61
|
-
"jest-transform-graphql": "^2.1.0",
|
|
62
|
-
"nodemon": "^3.1.7",
|
|
63
|
-
"prettier": "^3.3.3",
|
|
64
|
-
"rollup": "^4.60.0",
|
|
65
|
-
"rollup-plugin-copy": "^3.5.0",
|
|
66
|
-
"tinybench": "^6.0.0",
|
|
67
|
-
"ts-jest": "^29.2.5",
|
|
68
|
-
"ts-loader": "^9.5.1",
|
|
69
|
-
"ts-node": "^10.9.2",
|
|
70
|
-
"typescript": "^5.6.3",
|
|
71
|
-
"typescript-eslint": "^8.10.0"
|
|
72
|
-
}
|
|
73
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@via-profit/ability",
|
|
3
|
+
"support": "https://via-profit.ru",
|
|
4
|
+
"version": "3.4.0",
|
|
5
|
+
"description": "Via-Profit Ability service",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ability",
|
|
8
|
+
"access",
|
|
9
|
+
"via-profit"
|
|
10
|
+
],
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">= 17.0.0",
|
|
14
|
+
"npm": ">= 8.19.3"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"CHANGELOG.md",
|
|
21
|
+
"CONTRIBUTING.md",
|
|
22
|
+
"SECURITY.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rollup -c",
|
|
26
|
+
"build:dev": "cross-env NODE_ENV=development rollup -c -w",
|
|
27
|
+
"bench": "npm run build && node ./bench/benchmark.js",
|
|
28
|
+
"test": "jest",
|
|
29
|
+
"lint": "tsc --noEmit && eslint --fix .",
|
|
30
|
+
"pretty": "prettier --write ./src"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/via-profit/ability.git"
|
|
35
|
+
},
|
|
36
|
+
"author": {
|
|
37
|
+
"name": "Via Profit",
|
|
38
|
+
"url": "https://dev.via-profit.ru"
|
|
39
|
+
},
|
|
40
|
+
"contributors": [
|
|
41
|
+
"Vasily Novosad <delhsmail@gmail.com>",
|
|
42
|
+
"Pavel Natalin <trubonru@gmail.com>"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@eslint/js": "^9.13.0",
|
|
47
|
+
"@jagi/jest-transform-graphql": "^1.0.2",
|
|
48
|
+
"@jest/types": "^29.6.3",
|
|
49
|
+
"@rollup/plugin-alias": "^6.0.0",
|
|
50
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
51
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
52
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
53
|
+
"@types/jest": "^29.5.13",
|
|
54
|
+
"@types/node": "^22.7.7",
|
|
55
|
+
"@types/nodemon": "^1.19.6",
|
|
56
|
+
"concurrently": "^9.0.1",
|
|
57
|
+
"cross-env": "^7.0.3",
|
|
58
|
+
"eslint": "^9.13.0",
|
|
59
|
+
"globals": "^15.11.0",
|
|
60
|
+
"jest": "^29.7.0",
|
|
61
|
+
"jest-transform-graphql": "^2.1.0",
|
|
62
|
+
"nodemon": "^3.1.7",
|
|
63
|
+
"prettier": "^3.3.3",
|
|
64
|
+
"rollup": "^4.60.0",
|
|
65
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
66
|
+
"tinybench": "^6.0.0",
|
|
67
|
+
"ts-jest": "^29.2.5",
|
|
68
|
+
"ts-loader": "^9.5.1",
|
|
69
|
+
"ts-node": "^10.9.2",
|
|
70
|
+
"typescript": "^5.6.3",
|
|
71
|
+
"typescript-eslint": "^8.10.0"
|
|
72
|
+
}
|
|
73
|
+
}
|