{"id":3422,"date":"2025-09-17T07:03:44","date_gmt":"2025-09-17T07:03:44","guid":{"rendered":"https:\/\/structr.com\/?p=3422"},"modified":"2025-09-18T11:10:31","modified_gmt":"2025-09-18T11:10:31","slug":"graalvm-meets-structr-low-code-a-polyglot-revolution-in-graph-based-development","status":"publish","type":"post","link":"https:\/\/structr.com\/en\/blog\/graalvm-meets-structr-low-code-a-polyglot-revolution-in-graph-based-development\/","title":{"rendered":"GraalVM meets Structr Low-Code &#8211; A Polyglot Revolution in Graph-Based Development"},"content":{"rendered":"<div class=\"wpb-content-wrapper\"><p>[vc_row][vc_column][vc_column_text]The landscape of low-code development platforms has been rapidly evolving, and Structr has consistently remained at the forefront of innovation in graph-based application development. Today, we want to explore one of the most significant architectural advances in Structr&#8217;s evolution: the integration of <a href=\"https:\/\/www.graalvm.org\/\" target=\"_blank\" rel=\"noopener\">GraalVM&#8217;s<\/a> polyglot engine, which was first introduced with Structr 4.0 and transforms how developers interact with Structr&#8217;s powerful graph database integration capabilities.<\/p>\n<p>With the launch of the upcoming Structr Version 6.0, we want to spotlight this robust integration and demonstrate its powerful capabilities alongside several significant enhancements. Key improvements include an upgrade to GraalVM 25 and comprehensive ECMA-Script module support, enabling developers to, for example, build and organize JavaScript libraries within Structr&#8217;s integrated filesystem, incorporate existing codebases, and utilize standard ES6 import statements seamlessly throughout the polyglot environment. This filesystem-based module approach extends beyond JavaScript to other supported GraalVM languages as well.<\/p>\n<p>These advancements enable developers to better organize and reuse code across Structr projects, creating modular libraries that can be shared between different applications and components within the platform while maintaining the rapid development benefits that make low-code development so effective.[\/vc_column_text][vc_single_image image=&#8221;3424&#8243; img_size=&#8221;medium&#8221;]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >From Legacy JavaScript Engines to Modern Polyglot Runtime<\/h2><\/div><\/div>[vc_column_text]For years, Structr relied on JavaScript engines like Nashorn and Rhino to power its scripting capabilities. While these engines served the platform well in its early days, they eventually became limiting factors as they reached deprecated status, offered outdated JavaScript support, and suffered from performance constraints that hindered modern development workflows.<\/p>\n<p>The integration of GraalVM&#8217;s polyglot engine represents a fundamental shift from single-language scripting to a truly modern, multi-language development environment. Where developers once were constrained by the limitations of legacy JavaScript engines, they can now choose from multiple programming languages\u2014JavaScript with modern ES6+ support, Python, and many others\u2014all within a unified runtime environment that maintains seamless interoperability.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Structr's Built-in Function Library: 200+ Functions at Your Fingertips<\/h2><\/div><\/div>[vc_column_text]At the heart of this integration lies Structr&#8217;s comprehensive library of over 200 built-in functions, accessible through the familiar <code>$<\/code> or <code>Structr<\/code> objects. These functions span everything from complex Neo4j Cypher queries and HTTP API integrations to PDF generation and MongoDB operations. With GraalVM&#8217;s polyglot engine, this entire function ecosystem becomes available across multiple programming languages, creating unprecedented flexibility in how developers approach application logic.<\/p>\n<p>The function categories include:<\/p>\n<ul>\n<li>Database Operations: Direct Neo4j integration with <code>$.cypher()<\/code> and advanced search with <code>$.find()<\/code><\/li>\n<li>External API Integration: HTTP functions for seamless service communication<\/li>\n<li>Document Generation: File creation (PDF, CSV, Excel, XML etc.) and file manipulation capabilities<\/li>\n<li>Database Connectivity: Neo4j, MongoDB, JDBC integration and external database access<\/li>\n<li>Transaction Management: Advanced transaction handling with <code>$.doInNewTransaction()<\/code> or <code>$.schedule()<\/code><\/li>\n<\/ul>\n<pre>{\r\n       \/\/ Simple example: Finding users with predicates\r\n       $.find('User', $.predicate.equals('isAdmin', true));\r\n}\r\n<\/pre>\n<p>For a complete reference of all available functions, see the <a href=\"https:\/\/docs.structr.com\/docs\/built-in-functions\" target=\"_blank\" rel=\"noopener\">Structr Built-in Functions Documentation<\/a>.<\/p>\n<p>For comprehensive examples of all function categories, see the Detailed Function Examples section below.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Graph Navigation: From Complex Queries to Intuitive Object Access<\/h2><\/div><\/div>[vc_column_text]One of the most powerful aspects of Structr&#8217;s GraalVM integration is how it transforms complex Neo4j graph relationships into intuitive object navigation. Instead of writing complex Cypher queries for every relationship traversal, developers can navigate the graph using simple property access patterns that feel natural in any programming language.[\/vc_column_text][vc_single_image image=&#8221;3431&#8243; img_size=&#8221;full&#8221;][vc_column_text]Consider a typical project management data model with Projects, ProjectTasks, and Users. With traditional approaches, you&#8217;d write complex Cypher queries. With Structr&#8217;s graph navigation, relationships become as simple as accessing object properties:<\/p>\n<pre>{\r\n\t\/\/ Navigate graph relationships intuitively\r\n\tlet user = $.me; \/\/ me as the keyword for the authenticated user\r\n\tlet userTasks = user.tasks; \/\/ Automatic relationship traversal\r\n\tuserTasks.map(task =&gt; task.project);\r\n}<\/pre>\n<p>This approach allows developers to combine the best of both worlds\u2014using Cypher for complex pattern matching and filtering, then leveraging JavaScript for data processing and business logic. See <a href=\"https:\/\/structr.com\/en\/graalvm-meets-structr-low-code-a-polyglot-revolution-in-graph-based-development#example\">Advanced Graph Navigation Examples<\/a> for multi-hop traversal and complex patterns.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Schema Methods: Embedding Polyglot Logic in Data Types<\/h2><\/div><\/div>[vc_column_text]GraalVM&#8217;s polyglot engine extends beyond scripting into Structr&#8217;s schema definition itself. Developers can define custom methods directly on data types, creating reusable business logic that travels with the data model. These methods can be written in any supported polyglot language and have access to the full Structr function library.<\/p>\n<p>Schema methods come in three distinct types, each serving different purposes within Structr&#8217;s data model:<\/p>\n<ul>\n<li>Lifecycle Methods: Automatically triggered by Structr during node lifecycle events such as <code>onCreate<\/code>, <code>onSave<\/code>, <code>onDelete<\/code>, and others. These methods are called on node instances with access to <code>$.this<\/code> when the corresponding event occurs, enabling automatic data validation, relationship management, or side effects.<\/li>\n<li>Instance Methods: Explicitly called on specific node instances with access to the current node context through <code>$.this<\/code>. These methods encapsulate business logic that operates on individual nodes and can utilize the full power of Structr&#8217;s built-in functions.<\/li>\n<li>Static Methods: Called directly on data types without requiring a specific node instance. These utility methods are ideal for type-level operations such as finding nodes with specific criteria or performing aggregate operations across all instances of a type.<\/li>\n<\/ul>\n<pre>\/\/ Simple schema method example\r\n{ \/\/ Instance method on Project type\r\n  $.this.tasks.push($.create(\"ProjectTask\", {name: \"New Task\"}));\r\n}<\/pre>\n<p>This enables developers to encapsulate business logic directly in their data model, making applications more maintainable and logic more reusable. For comprehensive schema method examples including Python implementations, see <a href=\"https:\/\/structr.com\/en\/graalvm-meets-structr-low-code-a-polyglot-revolution-in-graph-based-development#example\">Schema Method Examples<\/a>.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Frontend Integration: Polyglot Power in Templates<\/h2><\/div><\/div>[vc_column_text]The same polyglot capabilities extend seamlessly throughout Structr&#8217;s entire stack, including frontend template rendering. Developers can use graph navigation and built-in functions directly in templates, creating dynamic, data-driven interfaces.<\/p>\n<pre>&lt;div class=\"user-dashboard\"&gt;\r\n  &lt;h2&gt;My Projects&lt;\/h2&gt;\r\n  &lt;div class=\"projects-container\"&gt;\r\n    ${{ \r\n      let userProjects = $.mergeUnique($.me.tasks.map(task =&gt; task.project));\r\n      $.include(\"project-list-template\", userProjects, \"project\");\r\n    }}\r\n  &lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n<p>This demonstrates the global integration of GraalVM&#8217;s polyglot engine\u2014whether you&#8217;re in backend logic, frontend rendering, or schema methods, the same navigation patterns and functions work consistently across all contexts.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Multi-Language Support: Beyond JavaScript<\/h2><\/div><\/div>[vc_column_text]While JavaScript remains the primary scripting language in Structr, GraalVM&#8217;s polyglot engine opens doors to additional programming languages for specialized use cases. Python brings powerful data processing capabilities and other languages can be integrated as needed.<\/p>\n<pre>python{ \r\ndef getUserNames(): \r\n\tusers = list(map(lambda u: u.name, Structr.find(\"User\"))) \r\n\treturn users \r\n\r\ngetUserNames() \r\n}<\/pre>\n<p>The beauty of this approach is that regardless of the language chosen, developers maintain access to Structr&#8217;s comprehensive built-in function library through consistent APIs like <code>Structr.call()<\/code> for Python contexts.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Conclusion: A New Era of Low-Code Development<\/h2><\/div><\/div>[vc_column_text]GraalVM&#8217;s integration with Structr represents more than just a technical upgrade\u2014it&#8217;s a paradigm shift that brings modern, polyglot capabilities to graph-based low-code development. By combining the intuitive power of object navigation, the flexibility of multiple programming languages, and the comprehensive functionality of Structr&#8217;s built-in library, developers can build sophisticated applications with unprecedented ease and flexibility.<\/p>\n<p>This transformation ensures that Structr remains at the cutting edge of low-code platforms, providing developers with the tools they need to tackle complex challenges while maintaining the rapid development capabilities that make low-code platforms so powerful.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \"  id=\"examples\" >Detailed Function Examples<\/h2><\/div><\/div><div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Database Operations with JavaScript<\/h3><\/div><\/div>[vc_column_text]One of Structr&#8217;s most powerful features is its direct integration with Neo4j through built-in functions like <code>$.cypher()<\/code> and <code>$.find()<\/code>. These database operations provide intuitive access to complex graph queries and data manipulation.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >Complex User Query<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Find admin users with advanced predicates\r\n\t\/\/ In this example only find Users with names \"jeff\" or \"joe\"\r\n\tlet adminUsers = $.find('User', $.predicate.and(\r\n\t    $.predicate.equals('isAdmin', true),\r\n\t    $.predicate.or([\r\n\t        $.predicate.equals('name', 'jeff'),\r\n\t        $.predicate.equals('name', 'joe')\r\n\t    ])\r\n\t));\r\n\t\r\n\t\/\/ Execute raw Cypher with parameters\r\n\tlet query = \"MATCH (user:User) WHERE user.name = $userName RETURN user\";\r\n\tlet users = $.cypher(query, {userName: 'admin'});\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Advanced Transaction Management<\/h3><\/div><\/div>[vc_column_text]Structr&#8217;s <code>$.doInNewTransaction()<\/code> function demonstrates how complex database operations can be managed with proper transaction boundaries:[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >Batch Processing<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\tlet pageSize = 10;\r\n\tlet pageNo = 1;\r\n\t\r\n\t$.doInNewTransaction(function() {\r\n\t    let nodes = $.find('User', $.predicate.page(pageNo, pageSize));\r\n\t    \r\n\t    nodes.forEach(user =&gt; {\r\n\t        $.set(user, {lastProcessed: new Date()});\r\n\t    });\r\n\t    \r\n\t    pageNo++;\r\n\t    return (nodes.length &gt; 0);\r\n\t}, function(error) {\r\n\t    $.log('Error occurred:', error.getMessage());\r\n\t    return false;\r\n\t});\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >External API Integration<\/h3><\/div><\/div>[vc_column_text]Structr&#8217;s HTTP functions showcase how external service integration works seamlessly.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >RESTful API Calls<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Configure headers and make requests\r\n\t$.addHeader('Authorization', 'Bearer ' + token);\r\n\t$.addHeader('Content-Type', 'application\/json');\r\n\t\r\n\t\/\/ Simple GET request example\r\n\tlet response = $.GET('https:\/\/api.example.com\/users');\r\n\t\r\n\t\/\/ POST request example\r\n\tlet postData = JSON.stringify({\r\n\t    name: 'New User',\r\n\t    email: 'user@example.com'\r\n\t});\r\n\t\r\n\tlet createResponse = $.POST('https:\/\/api.example.com\/users', postData);\r\n\t\r\n\tif (createResponse.status === 201) {\r\n\t    let newUser = createResponse.body;\r\n\t    $.log('Created user:', newUser.id);\r\n\t}\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >MongoDB Integration<\/h3><\/div><\/div>[vc_column_text]The <code>$.mongodb()<\/code> function demonstrates how external database connections work seamlessly.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >MongoDB Operations<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\tlet collection = $.mongodb('mongodb:\/\/localhost', 'testDatabase', 'testCollection');\r\n\t\r\n\t\/\/ Insert with BSON helper\r\n\tcollection.insertOne($.bson({\r\n\t    name: 'Test User',\r\n\t    email: 'test@example.com',\r\n\t    created: new Date()\r\n\t}));\r\n\t\r\n\t\/\/ Complex queries\r\n\tlet activeAdmins = collection.find($.bson({\r\n\t    $and: [\r\n\t        { active: true },\r\n\t        { role: 'admin' },\r\n\t        { lastLogin: { $gte: new Date(2023, 0, 1) } }\r\n\t    ]\r\n\t}));\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Document Generation and File Operations<\/h3><\/div><\/div>[vc_column_text]Structr&#8217;s document generation capabilities, like PDF creation, provide powerful content creation tools.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >PDF Generation<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\t$.setResponseHeader('Content-Disposition', 'attachment; filename=\"report.pdf\"');\r\n\t$.setResponseHeader('Cache-Control', 'no-cache');\r\n\t\r\n\tlet mainPage = 'pdf-export-main-page\/';\r\n\tlet header = '--header-html ' + $.get('base_url') + '\/pdf-export-header-page\/';\r\n\tlet footer = '--footer-html ' + $.get('base_url') + '\/pdf-export-footer-page\/';\r\n\tlet wkhtmlArgs = header + ' ' + footer + ' --disable-smart-shrinking';\r\n\t\r\n\t\/\/ transform html pages to a pdf\r\n\tlet pdf = $.pdf(mainPage, wkhtmlArgs);\r\n\t\r\n\t\/\/ save the pdf content in a new file\r\n\tlet newPDFFile = $.create(\"File\", {\r\n\t\tname: 'new-file.pdf'\r\n\t})\r\n\t$.setContent(newPDFFile, pdf, \"ISO-8859-1\");\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Advanced Graph Navigation Examples<\/h2><\/div><\/div><div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >JavaScript Graph Navigation<\/h3><\/div><\/div>[vc_column_text]With Structr&#8217;s polyglot engine, navigating relationships becomes as simple as accessing object properties:[\/vc_column_text][vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Get the current authenticated user\r\n\tlet user = $.me;\r\n\t\r\n\t\/\/ Navigate directly to all tasks assigned to this user\r\n\t\/\/ This automatically traverses the WORKS_ON relationship\r\n\tlet allUserTasks = user.tasks;\r\n\t\r\n\t\/\/ From tasks, navigate to their parent projects\r\n\t\/\/ Using reduce to collect unique projects from all tasks\r\n\tlet allProjectsOfUser = $.mergeUnique(user.tasks.map(task =&gt; task.project));\r\n\t\r\n\t\/\/ Get task counts per project for the current user\r\n\tlet projectTaskCounts = allProjectsOfUser.map(project =&gt; ({\r\n\t    project: project,\r\n\t    taskCount: project.tasks.filter(task =&gt; user.tasks.includes(task)).length,\r\n\t    completedTasks: project.tasks.filter(task =&gt; \r\n\t        user.tasks.includes(task) &amp;&amp; task.completed\r\n\t    ).length\r\n\t}));\r\n\t\r\n\t\/\/ Find projects where user is the primary contributor\r\n\tlet primaryProjects = allProjectsOfUser.filter(project =&gt; {\r\n\t    let projectTasks = project.tasks;\r\n\t    let userTasksInProject = projectTasks.filter(task =&gt; user.tasks.includes(task));\r\n\t    return userTasksInProject.length &gt; projectTasks.length * 0.5; \/\/ &gt;50% of tasks\r\n\t});\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Multi-Hop Navigation<\/h3><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Navigate through multiple relationship levels\r\n\tlet user = $.me;\r\n\t\r\n\t\/\/ Get all team members working on the same projects\r\n\tlet userProjects = user.tasks.map(task =&gt; task.project);\r\n\tlet colleagues = [];\r\n\t\r\n\tfor (let project of userProjects) {\r\n\t    let projectUsers = project.tasks\r\n\t        .flatMap(task =&gt; task.users)\r\n\t        .filter(colleague =&gt; colleague.id !== user.id);\r\n\t    \r\n\t    \/\/ Add unique colleagues\r\n\t    for (let colleague of projectUsers) {\r\n\t        if (!colleagues.find(c =&gt; c.id === colleague.id)) {\r\n\t            colleagues.push(colleague);\r\n\t        }\r\n\t    }\r\n\t}\r\n\t\r\n\t\/\/ Find project dependencies through shared resources\r\n\tlet projectDependencies = userProjects.map(project =&gt; {\r\n\t    let dependencies = [];\r\n\t    \r\n\t    \/\/ Get all users working on this project\r\n\t    let projectUsers = project.tasks.reduce((users, task) =&gt; {\r\n\t        task.users.forEach(user =&gt; {\r\n\t            if (!users.find(u =&gt; u.id === user.id)) {\r\n\t                users.push(user);\r\n\t            }\r\n\t        });\r\n\t        return users;\r\n\t    }, []);\r\n\t    \r\n\t    \/\/ Find other projects these users work on\r\n\t    for (let projectUser of projectUsers) {\r\n\t        let otherProjects = projectUser.tasks\r\n\t            .map(task =&gt; task.project)\r\n\t            .filter(p =&gt; p.id !== project.id);\r\n\t            \r\n\t        for (let otherProject of otherProjects) {\r\n\t            if (!dependencies.find(p =&gt; p.id === otherProject.id)) {\r\n\t                dependencies.push(otherProject);\r\n\t            }\r\n\t        }\r\n\t    }\r\n\t    \r\n\t    return {\r\n\t        project: project,\r\n\t        dependencies: dependencies\r\n\t    };\r\n\t});\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Mixing Graph Navigation with Cypher<\/h3><\/div><\/div>[vc_column_text]<\/p>\n<pre>{\r\n\tlet user = $.me;\r\n\t\r\n\t\/\/ Use graph navigation for simple relationship traversal\r\n\tlet projectTimeline = user.tasks.map(task =&gt; ({\r\n\t    project: task.project.name,\r\n\t    task: task.name,\r\n\t    startDate: task.startDate,\r\n\t    endDate: task.endDate,\r\n\t    status: task.status,\r\n\t    teamSize: task.users.length\r\n\t}));\r\n\t\r\n\t\/\/ Sort by start date\r\n\tprojectTimeline.sort((a, b) =&gt; a.startDate - b.startDate);\r\n\t\r\n\t\/\/ Use Cypher for complex filtering and pattern matching\r\n\tlet qualityQuery = `\r\n\t    MATCH (u:User {id: $userId})-[:WORKS_ON]-&gt;(task:ProjectTask)&lt;-[:HAS]-(project:Project)\r\n\t    WHERE project.status = 'active' \r\n\t      AND task.priority IN ['high', 'critical']\r\n\t      AND task.dueDate &gt; timestamp()\r\n\t    RETURN DISTINCT project\r\n\t`;\r\n\t\r\n\tlet activeHighPriorityProjects = $.cypher(qualityQuery, {userId: user.id});\r\n\t\r\n\t\/\/ Now use Structr's JavaScript functions for quality analysis\r\n\tlet qualityAnalysis = activeHighPriorityProjects.map(project =&gt; {\r\n\t    \/\/ Get all tasks in this project using graph navigation\r\n\t    let allProjectTasks = project.tasks;\r\n\t    let userTasks = user.tasks.filter(task =&gt; task.project.id === project.id);\r\n\t    \r\n\t    \/\/ Calculate quality metrics using JavaScript\r\n\t    let overdueTasks = allProjectTasks.filter(task =&gt; \r\n\t        task.dueDate &amp;&amp; task.dueDate &lt; Date.now() &amp;&amp; task.status !== 'completed'\r\n\t    ).length;\r\n\t    \r\n\t    let completionRate = allProjectTasks.length &gt; 0 \r\n\t        ? (allProjectTasks.filter(task =&gt; task.status === 'completed').length \/ allProjectTasks.length * 100).toFixed(1)\r\n\t        : 0;\r\n\t    \r\n\t    \/\/ Find critical path tasks using graph navigation\r\n\t    let criticalTasks = allProjectTasks.filter(task =&gt; \r\n\t        task.priority === 'critical' &amp;&amp; task.status !== 'completed'\r\n\t    );\r\n\t    \r\n\t    \/\/ Calculate team velocity\r\n\t    let recentlyCompleted = allProjectTasks.filter(task =&gt; \r\n\t        task.status === 'completed' &amp;&amp; \r\n\t        task.completedDate &amp;&amp; \r\n\t        task.completedDate &gt; Date.now() - (7 * 24 * 60 * 60 * 1000) \/\/ Last 7 days\r\n\t    ).length;\r\n\t    \r\n\t    return {\r\n\t        projectName: project.name,\r\n\t        projectDeadline: project.deadline,\r\n\t        totalTasks: allProjectTasks.length,\r\n\t        userTasks: userTasks.length,\r\n\t        overdueTasks: overdueTasks,\r\n\t        completionRate: completionRate,\r\n\t        criticalTasksRemaining: criticalTasks.length,\r\n\t        weeklyVelocity: recentlyCompleted,\r\n\t        riskLevel: overdueTasks &gt; 3 || criticalTasks.length &gt; 1 ? 'high' : 'low'\r\n\t    };\r\n\t});\r\n}\r\n<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h2 \"><h2 class=\"heading   \" >Schema Method Examples<\/h2><\/div><\/div><div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Instance Methods on Data Types<\/h3><\/div><\/div>[vc_column_text]Schema methods can be defined on any data type and called directly on node instances retrieved through functions like <code>$.cypher()<\/code> or <code>$.find()<\/code>. These methods have access to the current node context through <code>$.this<\/code> and can utilize the full power of Structr&#8217;s built-in functions.[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >Example \u2013 Project Type with addNewTask Method<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>\/\/ Method defined on Project schema type\r\n{\r\n    \/\/ Adds a new ProjectTask and connects it with the project node\r\n    $.this.tasks.push($.create(\"ProjectTask\", {\r\n        name: $.methodsParameters.name ?? \"New Task\", \r\n        dueDate: new Date(2026, 01, 01)\r\n    }));\r\n}<\/pre>\n<p>[\/vc_column_text][vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Find a project and call the custom method\r\n\tlet project = $.find('Project', {name: 'Website Redesign'})[0];\r\n\tproject.addNewTask({name: `New Task for ${project.name}`}); \/\/ Calls the schema method\r\n\t\r\n\t\/\/ Or use with Cypher results\r\n\tlet urgentProjects = $.cypher('MATCH (p:Project) WHERE p.priority = \"urgent\" RETURN p');\r\n\turgentProjects.forEach(project =&gt; {\r\n\t    project.addNewTask({name: `New Task for ${project.id}`}); \/\/ Each project gets a new task\r\n\t});\r\n}\r\n<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Advanced Schema Method Examples<\/h3><\/div><\/div><div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >Project Type \u2013 Calculate Project Health<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>\/\/ Schema method: calculateHealth()\r\n{\r\n    let totalTasks = $.this.tasks.length;\r\n    let completedTasks = $.this.tasks.filter(task =&gt; task.status === 'completed').length;\r\n    let overdueTasks = $.this.tasks.filter(task =&gt; \r\n        task.dueDate &amp;&amp; task.dueDate &lt; Date.now() &amp;&amp; task.status !== 'completed'\r\n    ).length;\r\n    \r\n    let completionRate = totalTasks &gt; 0 ? (completedTasks \/ totalTasks) : 0;\r\n    let healthScore = Math.max(0, completionRate * 100 - (overdueTasks * 10));\r\n    \r\n    return {\r\n        healthScore: healthScore.toFixed(1),\r\n        status: healthScore &gt; 80 ? 'excellent' : healthScore &gt; 60 ? 'good' : 'needs attention',\r\n        totalTasks: totalTasks,\r\n        completedTasks: completedTasks,\r\n        overdueTasks: overdueTasks\r\n    };\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >User Type \u2013 Get User Workload<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>\/\/ Schema method: getWorkloadSummary()\r\n{\r\n    let activeTasks = $.this.tasks.filter(task =&gt; task.status !== 'completed');\r\n    let projectMap = {};\r\n    \r\n    activeTasks.forEach(task =&gt; {\r\n        let projectName = task.project.name;\r\n        if (!projectMap[projectName]) {\r\n            projectMap[projectName] = {\r\n                project: task.project,\r\n                taskCount: 0,\r\n                highPriorityCount: 0\r\n            };\r\n        }\r\n        projectMap[projectName].taskCount++;\r\n        if (task.priority === 'high' || task.priority === 'critical') {\r\n            projectMap[projectName].highPriorityCount++;\r\n        }\r\n    });\r\n    \r\n    return {\r\n        totalActiveTasks: activeTasks.length,\r\n        projectCount: Object.keys(projectMap).length,\r\n        projectBreakdown: Object.values(projectMap)\r\n    };\r\n}<\/pre>\n<p>[\/vc_column_text]<div class=\"wpb_content_element\" ><div class=\"heading heading--h3 \"><h3 class=\"heading   \" >Static Methods on Data Types<\/h3><\/div><\/div><div class=\"wpb_content_element\" ><div class=\"heading heading--h4 \"><h4 class=\"heading   \" >Project Type \u2013 Static Method to Find Overdue Projects<\/h4><\/div><\/div>[vc_column_text]<\/p>\n<pre>\/\/ Static schema method: Project.findOverdueProjects()\r\n{\r\n    let currentDate = Date.now();\r\n    return $.find('Project', {\r\n        deadline: $.predicate.lt(currentDate),\r\n        status: $.predicate.not('completed')\r\n    });\r\n}<\/pre>\n<p>[\/vc_column_text][vc_column_text]<\/p>\n<pre>{\r\n\t\/\/ Call static method directly on the type\r\n\tlet overdueProjects = $.Project.findOverdueProjects();\r\n\t\r\n\t\/\/ Process results with additional logic\r\n\toverdueProjects.forEach(project =&gt; {\r\n\t    let health = project.calculateHealth(); \/\/ Instance method\r\n\t    if (health.healthScore &lt; 50) {\r\n\t        \/\/ Send notification or take action\r\n\t        $.log(`Project ${project.name} needs immediate attention`);\r\n\t    }\r\n\t});\r\n}<\/pre>\n<p>[\/vc_column_text][\/vc_column][\/vc_row]<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>[vc_row][vc_column][vc_column_text]The landscape of low-code development platforms has been rapidly evolving, and Structr has consistently remained at the forefront of innovation \u2026<\/p>\n","protected":false},"author":5,"featured_media":1202,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[24,26,29,40,32],"tags":[],"class_list":["post-3422","post","type-post","status-publish","format-standard","hentry","category-structr","category-cypher","category-example","category-low-code","category-programming"],"acf":[],"_links":{"self":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/3422","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/comments?post=3422"}],"version-history":[{"count":22,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/3422\/revisions"}],"predecessor-version":[{"id":3520,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/posts\/3422\/revisions\/3520"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/media\/1202"}],"wp:attachment":[{"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/media?parent=3422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/categories?post=3422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/structr.com\/en\/wp-json\/wp\/v2\/tags?post=3422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}