Fixed failing tests, tested parser more
This commit is contained in:
@@ -40,8 +40,6 @@ export async function resolveCalculationNode(calculation, parseNode, scope, give
|
|||||||
const fn = calculation._parseLevel;
|
const fn = calculation._parseLevel;
|
||||||
const calculationScope = { ...calculation._localScope, ...scope };
|
const calculationScope = { ...calculation._localScope, ...scope };
|
||||||
const { result: resultNode, context } = await resolve(fn, parseNode, calculationScope, givenContext);
|
const { result: resultNode, context } = await resolve(fn, parseNode, calculationScope, givenContext);
|
||||||
if (calculation.hash === 1318417319946211 && calculation._key === 'attackRoll') console.log({ calculation, resultNode, parseNode, ers: context.errors })
|
|
||||||
|
|
||||||
calculation.errors = context.errors;
|
calculation.errors = context.errors;
|
||||||
calculation.valueNode = resultNode;
|
calculation.valueNode = resultNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ var testProperties = [
|
|||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
uses: {
|
uses: {
|
||||||
calculation: 'nonExistantProperty + 7',
|
calculation: 'nonExistentProperty + 7',
|
||||||
},
|
},
|
||||||
usesUsed: 5,
|
usesUsed: 5,
|
||||||
left: 1,
|
left: 1,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ export default async function () {
|
|||||||
await computeCreatureComputation(computation);
|
await computeCreatureComputation(computation);
|
||||||
const prop = id => computation.propsById[id];
|
const prop = id => computation.propsById[id];
|
||||||
// Tag targeted effects make complicated parse trees
|
// Tag targeted effects make complicated parse trees
|
||||||
console.log(prop('attackAction2'));
|
|
||||||
assert.equal(prop('attackAction2').attackRoll.value, 'min(3 + d4, d100)', 'Tag targeted effects change the attack roll correctly');
|
assert.equal(prop('attackAction2').attackRoll.value, 'min(3 + d4, d100)', 'Tag targeted effects change the attack roll correctly');
|
||||||
// Tags target effects on attributes
|
// Tags target effects on attributes
|
||||||
assert.equal(prop('taggedCon').value, 26, 'Tagged targeted effects affect attribute values');
|
assert.equal(prop('taggedCon').value, 26, 'Tagged targeted effects affect attribute values');
|
||||||
|
|||||||
@@ -235,6 +235,7 @@ const ComputedOnlyActionSchema = createPropertySchema({
|
|||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
uses: {
|
uses: {
|
||||||
|
parseLevel: 'reduce',
|
||||||
type: 'computedOnlyField',
|
type: 'computedOnlyField',
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ const parserFunctions: { [name: string]: ParserFunction } = {
|
|||||||
],
|
],
|
||||||
arguments: ['parseNode'],
|
arguments: ['parseNode'],
|
||||||
resultType: 'parseNode',
|
resultType: 'parseNode',
|
||||||
fn: function resolveFn(node) {
|
fn: async function resolveFn(node) {
|
||||||
const { result } = resolve('reduce', node, this.scope, this.context);
|
const { result } = await resolve('reduce', node, this.scope, this.context);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -268,7 +268,7 @@ const parserFunctions: { [name: string]: ParserFunction } = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function anyNumberOf(type) {
|
function anyNumberOf(type) {
|
||||||
const argumentArray = [type];
|
const argumentArray: any = [type];
|
||||||
argumentArray.anyLength = true;
|
argumentArray.anyLength = true;
|
||||||
return argumentArray;
|
return argumentArray;
|
||||||
}
|
}
|
||||||
|
|||||||
139
app/imports/parser/parseTree/accessor.test.ts
Normal file
139
app/imports/parser/parseTree/accessor.test.ts
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import inputProviderForTests from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
||||||
|
import { parse } from '/imports/parser/parser';
|
||||||
|
import resolve from '/imports/parser/resolve';
|
||||||
|
import toString from '/imports/parser/toString';
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
describe('Accessor Node', function () {
|
||||||
|
it('compiles', async function () {
|
||||||
|
const callNode = parse('unknownVariable + knownVariable + 1');
|
||||||
|
const scope = {
|
||||||
|
knownVariable: { value: 7 },
|
||||||
|
};
|
||||||
|
const { result, context } = await resolve(
|
||||||
|
'compile', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(context.errors);
|
||||||
|
assert.equal(
|
||||||
|
toString(result),
|
||||||
|
'unknownVariable + 8',
|
||||||
|
'Only known variables should be substituted during compilation step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('reduces', async function () {
|
||||||
|
const callNode = parse('unknownVariable + knownVariable + 1');
|
||||||
|
const scope = {
|
||||||
|
knownVariable: { value: 7 },
|
||||||
|
};
|
||||||
|
const { result, context } = await resolve(
|
||||||
|
'reduce', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(context.errors);
|
||||||
|
assert.equal(
|
||||||
|
toString(result),
|
||||||
|
'8',
|
||||||
|
'All variables should be substituted during reduce step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('marks undefined variables', async function () {
|
||||||
|
const callNode = parse('unknownVariable');
|
||||||
|
|
||||||
|
// At compile step
|
||||||
|
const { result: compileResult, context: compileContext } = await resolve(
|
||||||
|
'compile', callNode, undefined, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(compileContext.errors, 'compiling unknown variables should not have errors');
|
||||||
|
assert.deepEqual(
|
||||||
|
compileResult, { parseType: 'accessor', name: 'unknownVariable', isUndefined: true },
|
||||||
|
'Unknown variables should be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
|
||||||
|
// At reduce step
|
||||||
|
const { result: reduceResult, context: reduceContext } = await resolve(
|
||||||
|
'reduce', callNode, undefined, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(reduceContext.errors, 'reducing unknown variables should not have errors');
|
||||||
|
assert.deepEqual(
|
||||||
|
reduceResult, { parseType: 'constant', value: 0, valueType: 'number', isUndefined: true },
|
||||||
|
'Unknown variables should be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Does not mark isUndefined on known variables', async function () {
|
||||||
|
const callNode = parse('knownVariable');
|
||||||
|
const scope = {
|
||||||
|
knownVariable: { value: 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// At compile step
|
||||||
|
const { result: compileResult, context: compileContext } = await resolve(
|
||||||
|
'compile', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(compileContext.errors, 'compiling known variables should not have errors');
|
||||||
|
assert.deepEqual(
|
||||||
|
compileResult, { parseType: 'constant', value: 0, valueType: 'number' },
|
||||||
|
'Known variables should not be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
|
||||||
|
// At reduce step
|
||||||
|
const { result: reduceResult, context: reduceContext } = await resolve(
|
||||||
|
'reduce', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(reduceContext.errors, 'reducing known variables should not have errors');
|
||||||
|
assert.deepEqual(
|
||||||
|
reduceResult, { parseType: 'constant', value: 0, valueType: 'number' },
|
||||||
|
'Known variables should not be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('handles .isUndefined on unknown variables', async function () {
|
||||||
|
const callNode = parse('unknownVariable.isUndefined');
|
||||||
|
const scope = {
|
||||||
|
knownVariable: { value: 7 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// At compile step
|
||||||
|
const { result: compileResult, context: compileContext } = await resolve(
|
||||||
|
'compile', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(compileContext.errors, 'compiling unknown variables should not have errors');
|
||||||
|
assert.equal(
|
||||||
|
toString(compileResult), 'true',
|
||||||
|
'Unknown variables should be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
|
||||||
|
// At reduce step
|
||||||
|
const { result: reduceResult, context: reduceContext } = await resolve(
|
||||||
|
'reduce', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(reduceContext.errors, 'reducing unknown variables should not have errors');
|
||||||
|
assert.equal(
|
||||||
|
toString(reduceResult), 'true',
|
||||||
|
'Unknown variables should be marked as inUndefined in reduce step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('handles .isUndefined on known variables', async function () {
|
||||||
|
const callNode = parse('knownVariable.isUndefined');
|
||||||
|
const scope = {
|
||||||
|
knownVariable: { value: 7 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// At compile step
|
||||||
|
const { result: compileResult, context: compileContext } = await resolve(
|
||||||
|
'compile', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(compileContext.errors, 'compiling unknown variables should not have errors');
|
||||||
|
assert.equal(
|
||||||
|
toString(compileResult), 'false',
|
||||||
|
'Unknown variables should not be marked as inUndefined in compile step'
|
||||||
|
);
|
||||||
|
|
||||||
|
// At reduce step
|
||||||
|
const { result: reduceResult, context: reduceContext } = await resolve(
|
||||||
|
'reduce', callNode, scope, undefined, inputProviderForTests
|
||||||
|
);
|
||||||
|
assert.isEmpty(reduceContext.errors, 'reducing unknown variables should not have errors');
|
||||||
|
assert.equal(
|
||||||
|
toString(reduceResult), 'false',
|
||||||
|
'Known variables should not be marked as inUndefined in reduce step'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,6 +8,7 @@ export type AccessorNode = {
|
|||||||
parseType: 'accessor' | 'symbol';
|
parseType: 'accessor' | 'symbol';
|
||||||
path?: string[];
|
path?: string[];
|
||||||
name: string;
|
name: string;
|
||||||
|
isUndefined?: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccessorFactory = {
|
type AccessorFactory = {
|
||||||
@@ -18,18 +19,29 @@ type AccessorFactory = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const accessor: AccessorFactory = {
|
const accessor: AccessorFactory = {
|
||||||
create({ name, path }: { name: string, path?: string[] }): AccessorNode {
|
create({
|
||||||
|
name, path, isUndefined
|
||||||
|
}: {
|
||||||
|
name: string, path?: string[], isUndefined?: true
|
||||||
|
}): AccessorNode {
|
||||||
return {
|
return {
|
||||||
parseType: 'accessor',
|
parseType: 'accessor',
|
||||||
path,
|
|
||||||
name,
|
name,
|
||||||
|
...path && { path },
|
||||||
|
...isUndefined && { isUndefined: true },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async compile(node, scope, context) {
|
async compile(node, scope, context) {
|
||||||
let value = getFromScope(node.name, scope);
|
let value = getFromScope(node.name, scope);
|
||||||
// Get the value from the given path
|
// Get the value from the given path
|
||||||
node.path?.forEach(name => {
|
node.path?.forEach(name => {
|
||||||
if (value === undefined) return;
|
if (name === 'isUndefined') {
|
||||||
|
value = value === undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
value = value[name];
|
value = value[name];
|
||||||
});
|
});
|
||||||
let valueType = getType(value);
|
let valueType = getType(value);
|
||||||
@@ -75,14 +87,17 @@ const accessor: AccessorFactory = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (valueType === 'undefined') {
|
if (valueType === 'undefined') {
|
||||||
// Undefined defaults to zero
|
// We are only at compile, if it isn't defined in the scope, return a copy of the accessor
|
||||||
return {
|
return {
|
||||||
result: constant.create({
|
result: accessor.create({
|
||||||
value: 0,
|
name: node.name,
|
||||||
|
path: node.path,
|
||||||
|
isUndefined: true,
|
||||||
}),
|
}),
|
||||||
context
|
context,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// The type being accessed isn't supported above, make an error and return a copy of the node
|
||||||
context.error(`Accessing ${accessor.toString(node)} is not supported yet`);
|
context.error(`Accessing ${accessor.toString(node)} is not supported yet`);
|
||||||
return {
|
return {
|
||||||
result: accessor.create({
|
result: accessor.create({
|
||||||
@@ -93,18 +108,19 @@ const accessor: AccessorFactory = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
async reduce(node, scope, context, inputProvider, resolveOthers): Promise<ResolvedResult> {
|
async reduce(node, scope, context, inputProvider, resolveOthers): Promise<ResolvedResult> {
|
||||||
let { result } = await accessor.compile(node, scope, context, inputProvider, resolveOthers);
|
// First compile the accessor
|
||||||
({ result } = await resolveOthers('reduce', result, scope, context, inputProvider));
|
const { result } = await accessor.compile(node, scope, context, inputProvider, resolveOthers);
|
||||||
if (result.parseType === 'accessor') {
|
// If compilation didn't find a suitable replacement, return 0
|
||||||
|
if (result.parseType === 'accessor' && result.isUndefined) {
|
||||||
return {
|
return {
|
||||||
result: constant.create({
|
result: constant.create({
|
||||||
value: 0,
|
value: 0,
|
||||||
|
isUndefined: true,
|
||||||
}),
|
}),
|
||||||
context
|
context
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
return { result, context };
|
|
||||||
}
|
}
|
||||||
|
return { result, context };
|
||||||
},
|
},
|
||||||
toString(node) {
|
toString(node) {
|
||||||
if (!node.path?.length) return `${node.name}`;
|
if (!node.path?.length) return `${node.name}`;
|
||||||
|
|||||||
14
app/imports/parser/parseTree/call.test.ts
Normal file
14
app/imports/parser/parseTree/call.test.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import inputProviderForTests from '/imports/api/engine/action/functions/inputProviderForTests.testFn';
|
||||||
|
import { parse } from '/imports/parser/parser';
|
||||||
|
import resolve from '/imports/parser/resolve';
|
||||||
|
import toString from '/imports/parser/toString';
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
describe('Call Node', function () {
|
||||||
|
it('compiles', async function () {
|
||||||
|
const callNode = parse('min( unknownVariable, 1 + 2, 3d30 )');
|
||||||
|
const { result, context } = await resolve('compile', callNode, undefined, undefined, inputProviderForTests);
|
||||||
|
assert.isEmpty(context.errors)
|
||||||
|
assert.equal(toString(result), 'min(unknownVariable, 3, 3d30)');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -108,7 +108,7 @@ const call: CallFactory = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Run the function
|
// Run the function
|
||||||
const value = func.fn.apply({
|
const value = await func.fn.apply({
|
||||||
scope,
|
scope,
|
||||||
context,
|
context,
|
||||||
}, mappedArgs);
|
}, mappedArgs);
|
||||||
@@ -166,20 +166,22 @@ const call: CallFactory = {
|
|||||||
let failed = false;
|
let failed = false;
|
||||||
// Check that each argument is of the correct type
|
// Check that each argument is of the correct type
|
||||||
resolvedArgs.forEach((node, index) => {
|
resolvedArgs.forEach((node, index) => {
|
||||||
let type;
|
let expectedType;
|
||||||
if (argumentsExpected.anyLength) {
|
if (argumentsExpected.anyLength) {
|
||||||
type = argumentsExpected[0];
|
expectedType = argumentsExpected[0];
|
||||||
} else {
|
} else {
|
||||||
type = argumentsExpected[index];
|
expectedType = argumentsExpected[index];
|
||||||
}
|
}
|
||||||
if (type === 'parseNode') return;
|
if (expectedType === 'parseNode') return;
|
||||||
if (
|
if (
|
||||||
node.parseType !== type
|
node.parseType !== expectedType
|
||||||
&& node.parseType === 'constant'
|
|| (
|
||||||
&& node.valueType !== type
|
node.parseType === 'constant'
|
||||||
|
&& node.valueType !== expectedType
|
||||||
|
)
|
||||||
) failed = true;
|
) failed = true;
|
||||||
if (failed && fn === 'reduce') {
|
if (failed && fn === 'reduce') {
|
||||||
const typeName = typeof type === 'string' ? type : type.constructor.name;
|
const typeName = typeof expectedType === 'string' ? expectedType : expectedType.constructor.name;
|
||||||
const nodeName = node.parseType;
|
const nodeName = node.parseType;
|
||||||
context.error(`Incorrect arguments to ${callNode.functionName} function` +
|
context.error(`Incorrect arguments to ${callNode.functionName} function` +
|
||||||
`expected ${typeName} got ${nodeName}`);
|
`expected ${typeName} got ${nodeName}`);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
import ParseNode from '/imports/parser/parseTree/ParseNode';
|
||||||
import ResolveLevelFunction from '/imports/parser/types/ResolveLevelFunction';
|
import ResolveLevelFunction from '/imports/parser/types/ResolveLevelFunction';
|
||||||
|
|
||||||
export type ConstantValueType = number | string | boolean | undefined
|
export type ConstantValueType = number | string | boolean
|
||||||
|
|
||||||
export type ConstantNode = {
|
export type ConstantNode = {
|
||||||
parseType: 'constant';
|
parseType: 'constant';
|
||||||
value: ConstantValueType;
|
value: ConstantValueType;
|
||||||
// TODO replace all `constantNode.valueType` with `typeof constantNode.value`
|
// TODO replace all `constantNode.valueType` with `typeof constantNode.value`
|
||||||
valueType: 'number' | 'string' | 'boolean' | 'undefined';
|
valueType: 'number' | 'string' | 'boolean';
|
||||||
|
isUndefined?: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FiniteNumberConstantNode = {
|
export type FiniteNumberConstantNode = {
|
||||||
@@ -18,17 +19,18 @@ export type FiniteNumberConstantNode = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ConstantFactory = {
|
type ConstantFactory = {
|
||||||
create({ value }: { value: ConstantValueType }): ConstantNode;
|
create({ value, isUndefined }: { value: ConstantValueType, isUndefined?: true }): ConstantNode;
|
||||||
compile: ResolveLevelFunction<ConstantNode>;
|
compile: ResolveLevelFunction<ConstantNode>;
|
||||||
toString(node: ConstantNode): string;
|
toString(node: ConstantNode): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const constant: ConstantFactory = {
|
const constant: ConstantFactory = {
|
||||||
create({ value }): ConstantNode {
|
create({ value, isUndefined }): ConstantNode {
|
||||||
return {
|
return {
|
||||||
parseType: 'constant',
|
parseType: 'constant',
|
||||||
valueType: typeof value as 'number' | 'string' | 'boolean' | 'undefined',
|
valueType: typeof value as 'number' | 'string' | 'boolean',
|
||||||
value,
|
value,
|
||||||
|
...isUndefined && { isUndefined: true }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async compile(node, scope, context) {
|
async compile(node, scope, context) {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
console.log('index.ts imports')
|
|
||||||
|
|
||||||
import accessor from '/imports/parser/parseTree/accessor';
|
import accessor from '/imports/parser/parseTree/accessor';
|
||||||
import array from '/imports/parser/parseTree/array';
|
import array from '/imports/parser/parseTree/array';
|
||||||
import call from '/imports/parser/parseTree/call';
|
import call from '/imports/parser/parseTree/call';
|
||||||
@@ -14,8 +12,6 @@ import roll from '/imports/parser/parseTree/roll';
|
|||||||
import rollArray from '/imports/parser/parseTree/rollArray';
|
import rollArray from '/imports/parser/parseTree/rollArray';
|
||||||
import unaryOperator from '/imports/parser/parseTree/unaryOperator';
|
import unaryOperator from '/imports/parser/parseTree/unaryOperator';
|
||||||
|
|
||||||
console.log('index.ts')
|
|
||||||
|
|
||||||
const factories = {
|
const factories = {
|
||||||
accessor,
|
accessor,
|
||||||
array,
|
array,
|
||||||
@@ -34,12 +30,4 @@ const factories = {
|
|||||||
unaryOperator,
|
unaryOperator,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('---------------------');
|
|
||||||
console.log('---------------------');
|
|
||||||
console.log('---------------------');
|
|
||||||
console.log(factories.array);
|
|
||||||
console.log('---------------------');
|
|
||||||
console.log('---------------------');
|
|
||||||
console.log('---------------------');
|
|
||||||
|
|
||||||
export default factories;
|
export default factories;
|
||||||
|
|||||||
6
app/package-lock.json
generated
6
app/package-lock.json
generated
@@ -1422,6 +1422,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@tozd/vue-observer-utils/-/vue-observer-utils-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tozd/vue-observer-utils/-/vue-observer-utils-0.5.0.tgz",
|
||||||
"integrity": "sha512-HeRxWFJB7FXcQigH2LvauiR0l7hA4qqBC6hK9rBeKf076Ew08C4lx3eo7/YmvADt3b8ZP1j+TN0pGCEhKYOhEA=="
|
"integrity": "sha512-HeRxWFJB7FXcQigH2LvauiR0l7hA4qqBC6hK9rBeKf076Ew08C4lx3eo7/YmvADt3b8ZP1j+TN0pGCEhKYOhEA=="
|
||||||
},
|
},
|
||||||
|
"@types/chai": {
|
||||||
|
"version": "4.3.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz",
|
||||||
|
"integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/connect": {
|
"@types/connect": {
|
||||||
"version": "3.4.38",
|
"version": "3.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||||
|
|||||||
@@ -66,6 +66,7 @@
|
|||||||
"vuex": "^3.1.3"
|
"vuex": "^3.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/chai": "^4.3.11",
|
||||||
"@types/mocha": "^10.0.6",
|
"@types/mocha": "^10.0.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user