diff --git a/CHANGELOG.md b/CHANGELOG.md index f293655..1191e69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +# 0.1.1 (2025-02-01) +chore: Fixed typing in configParser + # 0.1.0 (2025-01-31) Initial release! \ No newline at end of file diff --git a/manifest.json b/manifest.json index efa1e90..cc72462 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "sqlseal-charts", "name": "SQLSeal Charts", - "version": "0.1.0", + "version": "0.1.1", "minAppVersion": "0.15.0", "isDesktopOnly": false, "description": "Charts extension for SQLSeal plugin. Generate pie charts, bar charts, line charts and more using data stored in your vault!", diff --git a/package.json b/package.json index 80e4308..dfa971b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sqlseal-charts", - "version": "0.1.0", + "version": "0.1.1", "description": "Chart extension for SQLSeal Obsidian plugin", "main": "main.js", "scripts": { diff --git a/src/utils/configParser.ts b/src/utils/configParser.ts index 126c12c..9a3bd7c 100644 --- a/src/utils/configParser.ts +++ b/src/utils/configParser.ts @@ -1,29 +1,33 @@ import * as acorn from 'acorn'; -import { Node, ObjectExpression, Property, CallExpression, Identifier, Literal, - ArrayExpression, MemberExpression, ArrowFunctionExpression, BlockStatement, - TemplateLiteral } from 'estree'; +import type { + Node, ObjectExpression, Property, CallExpression, Identifier, + Literal, ArrayExpression, MemberExpression, ArrowFunctionExpression, + BlockStatement, TemplateLiteral, ExpressionStatement, TemplateElement +} from 'acorn'; -type AllowedFunctions = Record any>; -type AllowedVariables = Record; +// Define more specific types for function parameters and returns +type AllowedFunction = (...args: unknown[]) => unknown; +type AllowedFunctions = Record; +type AllowedVariables = Record; // Extended to include function scope interface EvaluationContext { allowedFunctions: AllowedFunctions; allowedVariables: AllowedVariables; - scope: Record; + scope: Record; } export function parseCode( code: string, allowedFunctions: AllowedFunctions = {}, allowedVariables: AllowedVariables = {} -) { +): unknown { const wrappedCode = `(${code})`; const ast = acorn.parse(wrappedCode, { ecmaVersion: 2020, sourceType: 'module' - }) as any; + }) const context: EvaluationContext = { allowedFunctions, @@ -31,7 +35,7 @@ export function parseCode( scope: {} }; - function evaluateNode(node: Node, context: EvaluationContext): any { + function evaluateNode(node: Node, context: EvaluationContext): unknown { if (!node) { throw new Error('Null node encountered'); } @@ -54,23 +58,21 @@ export function parseCode( case 'BlockStatement': return evaluateBlockStatement(node as BlockStatement, context); case 'TemplateLiteral': - return evaluateTemplateLiteral(node as any, context); + return evaluateTemplateLiteral(node as TemplateLiteral, context); case 'TemplateElement': - return (node as any).value.cooked; + return (node as TemplateElement).value.cooked; default: throw new Error(`Unsupported node type: ${node.type}`); } } function evaluateArrowFunction(node: ArrowFunctionExpression, context: EvaluationContext): Function { - return (...args: any[]) => { - // Create a new scope for the function execution + return (...args: unknown[]) => { const functionContext: EvaluationContext = { ...context, scope: { ...context.scope } }; - // Bind parameters to arguments node.params.forEach((param, index) => { if (param.type === 'Identifier') { functionContext.scope[param.name] = args[index]; @@ -79,7 +81,6 @@ export function parseCode( } }); - // Handle both expression and block body if (node.body.type === 'BlockStatement') { return evaluateBlockStatement(node.body, functionContext); } else { @@ -88,26 +89,22 @@ export function parseCode( }; } - function evaluateBlockStatement(node: BlockStatement, context: EvaluationContext): any { - let result: any; + function evaluateBlockStatement(node: BlockStatement, context: EvaluationContext) { + let result: unknown; for (const statement of node.body) { result = evaluateNode(statement, context); } - return result; // Returns the value of the last statement + return result; } function evaluateTemplateLiteral(node: TemplateLiteral, context: EvaluationContext): string { let result = ''; - const expressions = node.expressions; - const quasis = node.quasis; - for (let i = 0; i < quasis.length; i++) { - // Add the template string part - result += evaluateNode(quasis[i], context); + for (let i = 0; i < node.quasis.length; i++) { + result += evaluateNode(node.quasis[i], context) as string; - // Add the expression value if there is one - if (i < expressions.length) { - const value = evaluateNode(expressions[i], context); + if (i < node.expressions.length) { + const value = evaluateNode(node.expressions[i], context); result += value != null ? String(value) : ''; } } @@ -115,20 +112,19 @@ export function parseCode( return result; } - function evaluateIdentifier(node: Identifier, context: EvaluationContext): any { + function evaluateIdentifier(node: Identifier, context: EvaluationContext) { const varName = node.name; - // Check scope first, then allowed variables - if (context.scope.hasOwnProperty(varName)) { + + if (Object.prototype.hasOwnProperty.call(context.scope, varName)) { return context.scope[varName]; } - if (context.allowedVariables.hasOwnProperty(varName)) { + if (Object.prototype.hasOwnProperty.call(context.allowedVariables, varName)) { return context.allowedVariables[varName]; } throw new Error(`Variable "${varName}" is not allowed`); } - function evaluateMemberExpression(node: MemberExpression, context: EvaluationContext): any { - // Evaluate the object part of the member expression + function evaluateMemberExpression(node: MemberExpression, context: EvaluationContext): unknown { const object = node.object.type === 'MemberExpression' ? evaluateMemberExpression(node.object, context) : node.object.type === 'Identifier' @@ -139,45 +135,49 @@ export function parseCode( throw new Error('Cannot access properties of null or undefined'); } - // Handle computed (bracket notation) access if (node.computed) { const propertyValue = evaluateNode(node.property, context); if (typeof propertyValue !== 'number' && typeof propertyValue !== 'string') { throw new Error('Property access must use number or string'); } - return object[propertyValue]; + return (object as Record)[propertyValue]; } - // Handle dot notation access if (node.property.type === 'Identifier') { - return object[node.property.name]; + return (object as Record)[node.property.name]; } throw new Error('Invalid property access'); } - function evaluateObject(node: ObjectExpression, context: EvaluationContext): Record { - const result: Record = {}; + function evaluateObject(node: acorn.ObjectExpression, context: EvaluationContext): Record { + const result: Record = {}; for (const prop of node.properties) { const property = prop as Property; - const key = property.key.type === 'Identifier' ? - property.key.name : - (property.key as Literal).value; + const key = property.key.type === 'Identifier' + ? property.key.name + : (property.key as Literal).value; - result[key as string] = evaluateNode(property.value, context); + if (typeof key === 'string') { + result[key] = evaluateNode(property.value, context); + } } return result; } - function evaluateArray(node: ArrayExpression, context: EvaluationContext): any[] { + function evaluateArray(node: ArrayExpression, context: EvaluationContext): unknown[] { return node.elements.map(element => element ? evaluateNode(element, context) : null ); } - function evaluateCall(node: CallExpression, context: EvaluationContext): any { + const isExpressionStatement = (x:(acorn.Statement | acorn.ModuleDeclaration)): x is ExpressionStatement => { + return !!x && x.type === 'ExpressionStatement' + } + + function evaluateCall(node: CallExpression, context: EvaluationContext): unknown { let func: Function; if (node.callee.type === 'Identifier') { @@ -187,7 +187,7 @@ export function parseCode( } func = context.allowedFunctions[callee]; } else if (node.callee.type === 'ArrowFunctionExpression') { - func = evaluateArrowFunction(node.callee as ArrowFunctionExpression, context); + func = evaluateArrowFunction(node.callee, context); } else { throw new Error('Unsupported function call type'); } @@ -196,8 +196,8 @@ export function parseCode( return func(...args); } - const expressionStatement = ast.body[0]; - if (!expressionStatement || expressionStatement.type !== 'ExpressionStatement') { + const expressionStatement = ast.body[0] + if (!isExpressionStatement(expressionStatement)) { throw new Error('Invalid input structure'); } diff --git a/versions.json b/versions.json index 37d5abe..397499d 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,4 @@ { - "0.1.0": "0.15.0" + "0.1.0": "0.15.0", + "0.1.1": "0.15.0" } \ No newline at end of file