@docstack/client 0.0.4 → 0.0.5
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/lib/core/attribute.js +406 -0
- package/lib/core/attribute.js.map +1 -0
- package/lib/core/class.d.ts +14 -15
- package/lib/core/class.js +761 -0
- package/lib/core/class.js.map +1 -0
- package/lib/core/crypto-engine/index.js +229 -0
- package/lib/core/crypto-engine/index.js.map +1 -0
- package/lib/core/crypto-engine/utils.js +88 -0
- package/lib/core/crypto-engine/utils.js.map +1 -0
- package/lib/core/datamodel/index.js +1308 -0
- package/lib/core/datamodel/index.js.map +1 -0
- package/lib/core/domain.d.ts +7 -8
- package/lib/core/domain.js +423 -0
- package/lib/core/domain.js.map +1 -0
- package/lib/core/index.js +520 -0
- package/lib/core/index.js.map +1 -0
- package/lib/core/job-engine/index.js +220 -0
- package/lib/core/job-engine/index.js.map +1 -0
- package/lib/core/policy-engine/index.js +232 -0
- package/lib/core/policy-engine/index.js.map +1 -0
- package/lib/core/query-engine/accumulators.js +258 -0
- package/lib/core/query-engine/accumulators.js.map +1 -0
- package/lib/core/query-engine/evaluator.js +179 -0
- package/lib/core/query-engine/evaluator.js.map +1 -0
- package/lib/core/query-engine/executor.js +405 -0
- package/lib/core/query-engine/executor.js.map +1 -0
- package/lib/core/query-engine/index.js +4 -0
- package/lib/core/query-engine/index.js.map +1 -0
- package/lib/core/query-engine/parser.js +515 -0
- package/lib/core/query-engine/parser.js.map +1 -0
- package/lib/core/query-engine/planner.js +330 -0
- package/lib/core/query-engine/planner.js.map +1 -0
- package/lib/core/stack.js +1817 -0
- package/lib/core/stack.js.map +1 -0
- package/lib/core/test-utils/docstack.js +222 -0
- package/lib/core/test-utils/docstack.js.map +1 -0
- package/lib/core/trigger/index.js +81 -0
- package/lib/core/trigger/index.js.map +1 -0
- package/lib/index.js +10 -4
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +10 -4
- package/lib/plugins/pouchdb.js +368 -0
- package/lib/plugins/pouchdb.js.map +1 -0
- package/lib/utils/crypto/index.js +34 -0
- package/lib/utils/crypto/index.js.map +1 -0
- package/lib/utils/index.js +58 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/logger/index.js +20 -0
- package/lib/utils/logger/index.js.map +1 -0
- package/lib/utils/logger/transport.js +28 -0
- package/lib/utils/logger/transport.js.map +1 -0
- package/lib/workers/dataModel.js +48 -0
- package/lib/workers/dataModel.js.map +1 -0
- package/package.json +2 -2
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","mappings":"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","sources":["webpack://@docstack/client/./src/core/query-engine/planner.ts","webpack://@docstack/client/../../node_modules/setimmediate/setImmediate.js","webpack://@docstack/client/webpack/bootstrap","webpack://@docstack/client/webpack/runtime/define property getters","webpack://@docstack/client/webpack/runtime/global","webpack://@docstack/client/webpack/runtime/hasOwnProperty shorthand","webpack://@docstack/client/./src/utils/logger/transport.ts","webpack://@docstack/client/./src/utils/logger/index.ts","webpack://@docstack/client/./src/core/attribute.ts","webpack://@docstack/client/./src/core/trigger/index.ts","webpack://@docstack/client/./src/core/class.ts","webpack://@docstack/client/./src/core/domain.ts","webpack://@docstack/client/./src/core/datamodel/index.ts","webpack://@docstack/client/./src/utils/index.ts","webpack://@docstack/client/./src/plugins/pouchdb.ts","webpack://@docstack/client/./src/core/query-engine/parser.ts","webpack://@docstack/client/./src/core/query-engine/evaluator.ts","webpack://@docstack/client/./src/core/query-engine/accumulators.ts","webpack://@docstack/client/./src/core/query-engine/executor.ts","webpack://@docstack/client/./src/core/job-engine/index.ts","webpack://@docstack/client/./src/core/policy-engine/index.ts","webpack://@docstack/client/./src/core/crypto-engine/utils.ts","webpack://@docstack/client/./src/core/crypto-engine/index.ts","webpack://@docstack/client/./src/core/stack.ts","webpack://@docstack/client/./src/core/index.ts","webpack://@docstack/client/./src/index.ts"],"sourcesContent":["// @ts-nocheck\n\n/**\n * Traverses an expression AST to find all referenced table aliases.\n * @param {object} expr The expression AST node.\n * @param {Set<string>} refs A set to accumulate the found table aliases.\n */\nfunction findExpressionRefs(expr, refs) {\n if (!expr) return;\n if (expr.type === 'column_ref' && expr.table) {\n refs.add(expr.table);\n }\n if (expr.left) findExpressionRefs(expr.left, refs);\n if (expr.right) findExpressionRefs(expr.right, refs);\n if (expr.expr) findExpressionRefs(expr.expr, refs);\n if (expr.args && expr.args.expr) findExpressionRefs(expr.args.expr, refs);\n if (Array.isArray(expr.exprs)) expr.exprs.forEach(e => findExpressionRefs(e, refs));\n}\n\n/**\n * Analyzes a subquery to find its correlation with the outer query.\n * @param {object} subqueryAst The AST of the subquery.\n * @param {Set<string>} outerTableAliases A set of table aliases available in the outer query scope.\n * @returns {object|null} Correlation details if found, otherwise null.\n */\nfunction findCorrelation(subqueryAst, outerTableAliases) {\n const correlations = [];\n const subqueryTableAliases = new Set([\n ...subqueryAst.from.map(f => f.as),\n ...subqueryAst.joins.map(j => j.as)\n ]);\n \n // Traverse the subquery's WHERE clause to find predicates linking inner and outer tables.\n function traverse(predicate) {\n if (!predicate) return;\n if (predicate.type === 'binary_expr') {\n const leftRefs = new Set();\n findExpressionRefs(predicate.left, leftRefs);\n const rightRefs = new Set();\n findExpressionRefs(predicate.right, rightRefs);\n\n const leftIsOuter = [...leftRefs].some(r => outerTableAliases.has(r));\n const leftIsInner = [...leftRefs].some(r => subqueryTableAliases.has(r));\n const rightIsOuter = [...rightRefs].some(r => outerTableAliases.has(r));\n const rightIsInner = [...rightRefs].some(r => subqueryTableAliases.has(r));\n \n // A correlation predicate connects one inner and one outer table.\n if ((leftIsInner && rightIsOuter) || (leftIsOuter && rightIsInner)) {\n correlations.push(predicate);\n return; // This predicate is a correlation, don't look deeper\n }\n }\n if (predicate.left) traverse(predicate.left);\n if (predicate.right) traverse(predicate.right);\n }\n \n traverse(subqueryAst.where);\n \n if (correlations.length > 0) {\n // Remove correlation predicates from the subquery's own WHERE clause.\n const originalWhere = subqueryAst.where;\n const correlationSet = new Set(correlations);\n \n function filterWhere(predicate) {\n if (!predicate || correlationSet.has(predicate)) return null;\n if (predicate.type === 'and') {\n const newLeft = filterWhere(predicate.left);\n const newRight = filterWhere(predicate.right);\n if (newLeft && newRight) return { ...predicate, left: newLeft, right: newRight };\n return newLeft || newRight;\n }\n return predicate;\n }\n \n subqueryAst.where = filterWhere(originalWhere);\n return { predicates: correlations };\n }\n return null;\n}\n\n/**\n * Pre-processes an AST to find and rewrite correlated subqueries into joins.\n * @param {object} ast The main query AST.\n * @returns {object} The transformed AST.\n */\nfunction decorrelateSubqueries(ast) {\n if (!ast.where) return ast;\n \n const outerTableAliases = new Set([\n ...ast.from.map(f => f.as),\n ...ast.joins.map(j => j.as)\n ]);\n \n // This function will be called recursively to traverse the WHERE clause tree.\n function transformPredicate(predicate) {\n if (!predicate) return null;\n\n if (predicate.type === 'exists_expr') {\n const correlation = findCorrelation(predicate.subquery, outerTableAliases);\n if (correlation) {\n // De-correlate! Rewrite the EXISTS subquery into a SEMI or ANTI join.\n if (correlation.predicates.length === 0) {\n throw new Error('Found correlated subquery but could not extract correlation predicate.');\n }\n \n // For simplicity, we assume the first correlation predicate is the join condition.\n // A real engine would handle multiple predicates.\n const joinCondition = correlation.predicates[0];\n \n ast.joins.push({\n type: predicate.not ? 'ANTI' : 'SEMI',\n // The \"table\" is the subquery itself. We'll flatten its FROM/JOINs.\n // This is a simplification; a real planner would create a sub-plan.\n table: predicate.subquery.from[0].table,\n as: predicate.subquery.from[0].as,\n on: joinCondition,\n // The subquery's own filters become part of the join operation.\n filters: predicate.subquery.where ? [predicate.subquery.where] : [],\n });\n // Since we've transformed this predicate into a join, we remove it from the WHERE clause.\n return null;\n }\n // If not correlated, it can be executed once. For now, we leave it as is.\n return predicate;\n }\n \n // Recurse for AND/OR conditions\n if (predicate.left) predicate.left = transformPredicate(predicate.left);\n if (predicate.right) predicate.right = transformPredicate(predicate.right);\n\n // Filter out parts that were transformed (returned null)\n if (predicate.type === 'and') {\n if (!predicate.left) return predicate.right;\n if (!predicate.right) return predicate.left;\n }\n\n return predicate;\n }\n\n ast.where = transformPredicate(ast.where);\n return ast;\n}\n\n\n/**\n * Analyzes an expression from the AST to determine which tables it references.\n * @param {object} expr The AST expression node.\n * @param {Array<object>} from The list of tables in the FROM clause.\n * @param {Array<object>} joins The list of tables in JOIN clauses.\n * @returns {Array<string>} A list of table names referenced in the expression.\n */\nfunction getReferencedTables(expr, from, joins) {\n const tables = new Set();\n if (!expr) return [];\n\n const allTables = [...from, ...joins.map(j => ({table: j.table, as: j.as}))];\n \n function traverse(node) {\n if (!node) return;\n if (node.type === 'column_ref' && node.table) {\n const tableInfo = allTables.find(t => t.as === node.table);\n if (tableInfo) {\n tables.add(tableInfo.table);\n }\n }\n if (node.left) traverse(node.left);\n if (node.right) traverse(node.right);\n if (node.expr) traverse(node.expr);\n }\n \n traverse(expr);\n return Array.from(tables);\n}\n\n/**\n * Checks if a predicate is a simple binary expression that can be converted\n * directly into a Mango selector by `buildSelector`.\n * @param {object} predicate The predicate AST node.\n * @returns {boolean} True if the predicate is simple enough for pushdown.\n */\nfunction isSimplePredicate(predicate) {\n if (predicate && predicate.type === 'binary_expr' &&\n predicate.left && predicate.left.type === 'column_ref' &&\n predicate.right && predicate.right.type === 'param') {\n // Check for operators supported by buildSelector\n const supportedOps = ['=', '>', '<', '>=', '<='];\n return supportedOps.includes(predicate.operator);\n }\n return false;\n}\n\nfunction createSingleSelectPlan(ast) {\n // Before creating the plan, run the de-correlation pass.\n ast = decorrelateSubqueries(ast);\n\n const plan = {\n type: 'select',\n distinct: ast.distinct,\n distinctOn: ast.distinctOn,\n fromTable: ast.from[0],\n joins: [],\n filters: {\n left: [],\n right: {},\n residual: []\n },\n projections: ast.columns,\n aggregation: null,\n orderBy: ast.orderBy,\n limit: ast.limit,\n };\n \n const fromTableName = ast.from[0].table;\n \n // Classify join predicates\n for (const join of ast.joins) {\n plan.joins.push({ ...join, filters: join.filters || [] });\n }\n \n // Unpack AND clauses into a flat list of predicates.\n const wherePredicates = [];\n function collectPredicates(p) {\n if (!p) return;\n if (p.type === 'and') {\n collectPredicates(p.left);\n collectPredicates(p.right);\n } else {\n wherePredicates.push(p);\n }\n }\n collectPredicates(ast.where);\n\n // Classify WHERE predicates\n for (const predicate of wherePredicates) {\n // Only simple predicates (e.g., col > literal) can be pushed down.\n // Complex predicates involving subqueries or functions become residual.\n const isSimple = isSimplePredicate(predicate);\n const referenced = getReferencedTables(predicate, ast.from, ast.joins);\n \n if (isSimple && referenced.length === 1 && referenced[0] === fromTableName) {\n plan.filters.left.push(predicate);\n } else if (isSimple && referenced.length === 1 && plan.joins.some(j => j.table === referenced[0])) {\n const join = plan.joins.find(j => j.table === referenced[0]);\n if(!plan.filters.right[join.table]) plan.filters.right[join.table] = [];\n plan.filters.right[join.table].push(predicate);\n } else {\n plan.filters.residual.push(predicate);\n }\n }\n \n // Setup aggregation\n const hasAggregates = ast.columns.some(c => c.expr.type === 'aggr_func');\n\n if (hasAggregates || ast.groupBy || ast.having) {\n // Semantic Validation for GROUP BY and aggregate functions\n if (ast.groupBy || hasAggregates) {\n const groupByCols = new Set(ast.groupBy ? ast.groupBy.columns.map(c => c.column) : []);\n for (const p of ast.columns) {\n if (p.expr.type !== 'aggr_func') {\n // This is a regular column projection\n const colName = p.as || p.expr.column;\n if (!ast.groupBy) {\n throw new Error(`Column '${colName}' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.`);\n }\n if (!groupByCols.has(p.expr.column)) {\n throw new Error(`Column '${colName}' must appear in the GROUP BY clause or be used in an aggregate function.`);\n }\n }\n }\n }\n \n plan.aggregation = {\n groupBy: ast.groupBy ? ast.groupBy.columns : [], // Empty array for scalar aggregation\n aggregates: ast.columns.filter(c => c.expr.type === 'aggr_func'),\n having: ast.having\n };\n }\n\n return plan;\n}\n\n/**\n * Creates a logical query plan from a list of Abstract Syntax Trees (ASTs) for a UNION query.\n * @param {Array<object>} astList The list of ASTs generated by the parser.\n * @returns {object} A query plan object for the executor.\n */\nexport function createPlan(astList) {\n if (!astList || astList.length === 0) return null;\n\n // Handle a single SELECT query (backwards compatibility)\n if (astList.length === 1 && astList[0].type === 'select') {\n const ast = astList[0];\n return createSingleSelectPlan(ast);\n }\n\n // It's a UNION query\n const plan = {\n type: 'union',\n selectPlans: [],\n unionOps: [],\n orderBy: null,\n limit: null,\n };\n \n // Create a map from the SelectAST object to its future index in selectPlans\n const selectAsts = astList.filter(ast => ast.type === 'select');\n const selectAstIndexMap = new Map();\n selectAsts.forEach((ast, index) => {\n selectAstIndexMap.set(ast, index);\n });\n\n plan.selectPlans = selectAsts.map(ast => createSingleSelectPlan(ast));\n\n const unionAsts = astList.filter(ast => ast.type === 'union');\n plan.unionOps = unionAsts.map(ast => {\n const topSelectAst = astList[ast.top];\n const bottomSelectAst = astList[ast.bottom];\n \n const topPlanIndex = selectAstIndexMap.get(topSelectAst);\n const bottomPlanIndex = selectAstIndexMap.get(bottomSelectAst);\n\n if (topPlanIndex === undefined || bottomPlanIndex === undefined) {\n throw new Error('Internal Planner Error: Could not map UNION AST to SELECT plans.');\n }\n\n return {\n distinct: ast.distinct,\n topPlanIndex,\n bottomPlanIndex,\n };\n });\n\n\n // According to SQL standard, ORDER BY and LIMIT in a UNION query apply to the entire result set\n // and can only appear at the very end.\n const lastSelectAst = astList[astList.length - 1];\n if (lastSelectAst.type === 'select') {\n plan.orderBy = lastSelectAst.orderBy;\n plan.limit = lastSelectAst.limit;\n \n // Remove from individual plan to avoid applying it early\n const lastSelectPlan = plan.selectPlans[plan.selectPlans.length - 1];\n if (lastSelectPlan) {\n lastSelectPlan.orderBy = null;\n lastSelectPlan.limit = null;\n }\n }\n\n return plan;\n}\n","(function (global, undefined) {\n \"use strict\";\n\n if (global.setImmediate) {\n return;\n }\n\n var nextHandle = 1; // Spec says greater than zero\n var tasksByHandle = {};\n var currentlyRunningATask = false;\n var doc = global.document;\n var registerImmediate;\n\n function setImmediate(callback) {\n // Callback can either be a function or a string\n if (typeof callback !== \"function\") {\n callback = new Function(\"\" + callback);\n }\n // Copy function arguments\n var args = new Array(arguments.length - 1);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i + 1];\n }\n // Store and register the task\n var task = { callback: callback, args: args };\n tasksByHandle[nextHandle] = task;\n registerImmediate(nextHandle);\n return nextHandle++;\n }\n\n function clearImmediate(handle) {\n delete tasksByHandle[handle];\n }\n\n function run(task) {\n var callback = task.callback;\n var args = task.args;\n switch (args.length) {\n case 0:\n callback();\n break;\n case 1:\n callback(args[0]);\n break;\n case 2:\n callback(args[0], args[1]);\n break;\n case 3:\n callback(args[0], args[1], args[2]);\n break;\n default:\n callback.apply(undefined, args);\n break;\n }\n }\n\n function runIfPresent(handle) {\n // From the spec: \"Wait until any invocations of this algorithm started before this one have completed.\"\n // So if we're currently running a task, we'll need to delay this invocation.\n if (currentlyRunningATask) {\n // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a\n // \"too much recursion\" error.\n setTimeout(runIfPresent, 0, handle);\n } else {\n var task = tasksByHandle[handle];\n if (task) {\n currentlyRunningATask = true;\n try {\n run(task);\n } finally {\n clearImmediate(handle);\n currentlyRunningATask = false;\n }\n }\n }\n }\n\n function installNextTickImplementation() {\n registerImmediate = function(handle) {\n process.nextTick(function () { runIfPresent(handle); });\n };\n }\n\n function canUsePostMessage() {\n // The test against `importScripts` prevents this implementation from being installed inside a web worker,\n // where `global.postMessage` means something completely different and can't be used for this purpose.\n if (global.postMessage && !global.importScripts) {\n var postMessageIsAsynchronous = true;\n var oldOnMessage = global.onmessage;\n global.onmessage = function() {\n postMessageIsAsynchronous = false;\n };\n global.postMessage(\"\", \"*\");\n global.onmessage = oldOnMessage;\n return postMessageIsAsynchronous;\n }\n }\n\n function installPostMessageImplementation() {\n // Installs an event handler on `global` for the `message` event: see\n // * https://developer.mozilla.org/en/DOM/window.postMessage\n // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages\n\n var messagePrefix = \"setImmediate$\" + Math.random() + \"$\";\n var onGlobalMessage = function(event) {\n if (event.source === global &&\n typeof event.data === \"string\" &&\n event.data.indexOf(messagePrefix) === 0) {\n runIfPresent(+event.data.slice(messagePrefix.length));\n }\n };\n\n if (global.addEventListener) {\n global.addEventListener(\"message\", onGlobalMessage, false);\n } else {\n global.attachEvent(\"onmessage\", onGlobalMessage);\n }\n\n registerImmediate = function(handle) {\n global.postMessage(messagePrefix + handle, \"*\");\n };\n }\n\n function installMessageChannelImplementation() {\n var channel = new MessageChannel();\n channel.port1.onmessage = function(event) {\n var handle = event.data;\n runIfPresent(handle);\n };\n\n registerImmediate = function(handle) {\n channel.port2.postMessage(handle);\n };\n }\n\n function installReadyStateChangeImplementation() {\n var html = doc.documentElement;\n registerImmediate = function(handle) {\n // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted\n // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.\n var script = doc.createElement(\"script\");\n script.onreadystatechange = function () {\n runIfPresent(handle);\n script.onreadystatechange = null;\n html.removeChild(script);\n script = null;\n };\n html.appendChild(script);\n };\n }\n\n function installSetTimeoutImplementation() {\n registerImmediate = function(handle) {\n setTimeout(runIfPresent, 0, handle);\n };\n }\n\n // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.\n var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);\n attachTo = attachTo && attachTo.setTimeout ? attachTo : global;\n\n // Don't get fooled by e.g. browserify environments.\n if ({}.toString.call(global.process) === \"[object process]\") {\n // For Node.js before 0.9\n installNextTickImplementation();\n\n } else if (canUsePostMessage()) {\n // For non-IE10 modern browsers\n installPostMessageImplementation();\n\n } else if (global.MessageChannel) {\n // For web workers, where supported\n installMessageChannelImplementation();\n\n } else if (doc && \"onreadystatechange\" in doc.createElement(\"script\")) {\n // For IE 6–8\n installReadyStateChangeImplementation();\n\n } else {\n // For older browsers\n installSetTimeoutImplementation();\n }\n\n attachTo.setImmediate = setImmediate;\n attachTo.clearImmediate = clearImmediate;\n}(typeof self === \"undefined\" ? typeof global === \"undefined\" ? this : global : self));\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Transport, { TransportStreamOptions } from \"winston-transport\";\nimport 'setimmediate';\nimport { Stack } from \"@docstack/shared\";\n//\n// Inherit from `winston-transport` so you can take advantage\n// of the base functionality and `.exceptions.handle()`.\n//\nclass PouchDBTransport extends Transport {\n stack: Stack;\n // fields for storing database connection information\n constructor(opts: {\n stack: Stack\n } & TransportStreamOptions) {\n super(opts);\n\n // Make sure that the database connection information is passed\n // and use that information to connect to the database\n this.stack = opts.stack;\n }\n\n async log(info: Object, callback: Function) {\n queueMicrotask(() => {\n this.emit('logged', info);\n });\n\n const response = await this.stack.db.post({\n log: info\n });\n // Perform the writing to the remote service\n callback();\n }\n};\n\nexport default PouchDBTransport","\nimport * as winston from \"winston\";\nimport { createLogger } from \"winston\";\nimport PouchDBTransport from \"./transport\";\nimport { Stack } from \"@docstack/shared\";\n\nconst clientLogger = (stack?: Stack | null) => {\n const transports: winston.transport[]= [];\n if (stack) {\n transports.push(new PouchDBTransport({ stack }));\n }\n\n // if (process.env.NODE_ENV !== \"test\") {\n const consoleTransport = new winston.transports.Console({\n level: \"warn\"\n });\n transports.push(consoleTransport);\n // }\n\n return createLogger({\n transports: transports\n });\n}\n\nexport default clientLogger;\n","import z, { ZodType, SafeParseReturnType } from \"zod\";\nimport Class from \"./class.js\";\nimport { Attribute as Attribute_, AttributeModel, AttributeType, ATTRIBUTE_TYPES, AttributeTypeConfig, AttributeTypeReference } from \"@docstack/shared\";\n\n/**\n * Represents a single attribute (field) within a Class schema.\n * \n * Attributes define the structure of documents, including their type,\n * validation rules (via Zod), and configuration options like mandatory,\n * default values, primary keys, and foreign key references.\n * \n * Use the static factory method {@link Attribute.create} to instantiate\n * attributes with proper validation and persistence.\n * \n * @example\n * ```typescript\n * // Create a string attribute\n * const titleAttr = await Attribute.create(taskClass, 'title', 'string', 'Task Title', {\n * mandatory: true,\n * maxLength: 200\n * });\n * \n * // Create a foreign key reference\n * const assigneeAttr = await Attribute.create(taskClass, 'assigneeId', 'foreign_key', 'Assigned User', {\n * targetClass: 'User'\n * });\n * ```\n * \n * @extends Attribute_\n */\nclass Attribute extends Attribute_ {\n /** The attribute name used as the document field key. */\n name: string;\n /** Optional description explaining the attribute's purpose. */\n description?: string;\n /** The underlying AttributeModel containing type and configuration. */\n model!: AttributeModel;\n /** Zod schema for runtime validation of this field. */\n field: any = z.any();\n /** Reference to the parent Class that owns this attribute. */\n class: Class | null;\n /** Default value to use when the field is not provided. */\n defaultValue?: any;\n\n /**\n * Creates a new Attribute instance.\n * For most use cases, prefer using {@link Attribute.create} which also persists the attribute.\n * \n * @param classObj - The parent Class for this attribute\n * @param name - The attribute name\n * @param type - The attribute type (e.g., 'string', 'integer', 'boolean', 'enum')\n * @param description - Optional description\n * @param config - Type-specific configuration options\n */\n constructor(classObj: Class | null = null, name: string, type: AttributeType[\"type\"], description?: string, config?: AttributeType[\"config\"]) {\n super(classObj, name, type, config);\n this.name = name;\n this.description = description;\n this.setModel({\n name: this.name,\n description: this.description,\n type: this.getType(type),\n config: this.getTypeConf(type, config) || {},\n });\n this.setField();\n this.class = classObj;\n }\n\n /**\n * Validates that reference-type attributes have proper domain configuration.\n * Called automatically during {@link Attribute.create}.\n * @throws Error if the reference configuration is invalid\n */\n ensureReferenceConfigIsValid = async () => {\n if (this.model.type !== \"reference\") {\n return;\n }\n if (!this.class) {\n throw new Error(`Attribute '${this.name}' must belong to a class to validate reference configuration.`);\n }\n const stack = this.class.getStack();\n if (!stack) {\n throw new Error(`Class '${this.class.getName()}' is not attached to a stack.`);\n }\n const config = this.model.config as AttributeTypeReference[\"config\"];\n const domainName = config.domain;\n if (typeof domainName !== \"string\" || domainName.length === 0) {\n throw new Error(`Attribute '${this.name}' of type 'reference' must declare a domain.`);\n }\n if (config.isArray) {\n throw new Error(`Attribute '${this.name}' of type 'reference' cannot be an array.`);\n }\n const domain = await stack.getDomain(domainName);\n if (!domain) {\n throw new Error(`Domain '${domainName}' was not found for attribute '${this.name}'.`);\n }\n const classId = this.class.id;\n switch (domain.relation) {\n case \"1:N\":\n if (classId !== domain.targetClass.id) {\n throw new Error(`Given classId '${classId}' Reference attributes for domain '${domainName}' can only be added to class '${domain.targetClass}'.`);\n }\n break;\n case \"N:1\":\n if (classId !== domain.sourceClass.id) {\n throw new Error(`Given classId '${classId}' Reference attributes for domain '${domainName}' can only be added to class '${domain.sourceClass}'.`);\n }\n break;\n case \"1:1\":\n if (classId !== domain.sourceClass.id && classId !== domain.targetClass.id) {\n throw new Error(`Class '${classId}' is not part of domain '${domainName}'.`);\n }\n break;\n case \"N:N\":\n throw new Error(`Domain '${domainName}' does not support reference attributes.`);\n default:\n throw new Error(`Unsupported relation '${domain.relation}' for domain '${domainName}'.`);\n }\n }\n\n /**\n * Builds the Zod validation schema based on attribute type and configuration.\n * Called automatically during construction.\n */\n public setField = () => {\n const { name, type, config } = this.model;\n let field: z.ZodType;\n\n switch (type) {\n // ... existing cases for 'string', 'number', 'boolean', 'date' ...\n case 'string':\n field = z.string();\n if (config.maxLength !== undefined) {\n field = (field as z.ZodString).max(config.maxLength);\n }\n break;\n\n case 'integer':\n field = z.number();\n if (typeof config.min === 'number') {\n field = (field as z.ZodNumber).min(config.min);\n }\n\n if (typeof config.max === 'number') {\n field = (field as z.ZodNumber).max(config.max);\n }\n break;\n\n // case 'date':\n // field = z.date();\n\n\n // break;\n\n case 'decimal':\n field = z.number();\n\n // min and max validation\n if (typeof config.min === 'number') {\n field = (field as z.ZodNumber).min(config.min);\n }\n if (typeof config.max === 'number') {\n field = (field as z.ZodNumber).max(config.max);\n }\n\n // decimal precision validation (with refinement)\n if (typeof config.precision === 'number' && config.precision >= 0) {\n const isPrecise = (value: any) => {\n if (typeof value !== 'number')\n return true;\n const valueAsString = value.toString();\n const decimalPart = valueAsString.split('.')[1];\n const decimalPlaces = decimalPart ? decimalPart.length : 0;\n return decimalPlaces <= config.precision;\n };\n\n field = field.refine(\n isPrecise,\n `Number cannot have more than ${config.precision} decimals.`\n );\n }\n break;\n\n case 'boolean':\n field = z.boolean();\n break;\n\n case \"object\":\n field = z.object({});\n break;\n\n case 'enum':\n if (!config.values || !Array.isArray(config.values) || config.values.length === 0) {\n throw new Error(\n `Attribute '${name}' of type 'enum' must have a non-empty 'values' array in its config.`\n );\n }\n const enumValues = config.values.map(v => v.value);\n field = z.enum(enumValues as [string, ...string[]]);\n break;\n\n case 'foreign_key':\n if (!config.targetClass) {\n throw new Error(\n `Attribute '${name}' of type 'foreign_key' is missing a 'targetClass' in its config.`\n );\n }\n\n const foreignClass = config.targetClass;\n const baseSchema = z.string();\n\n field = baseSchema.refine(\n async (documentIdOrIds: string | string[]) => {\n const idsToValidate = Array.isArray(documentIdOrIds) ? documentIdOrIds : [documentIdOrIds];\n if (idsToValidate.length === 0) {\n return true;\n }\n\n try {\n if (this.class) {\n const stack = this.class.getStack();\n if (stack) {\n const promises = idsToValidate.map(id => stack.db.get!(id));\n const fetchResult = await Promise.all(promises);\n return true;\n } else throw new Error(\"Missing stack connection\");\n } else throw new Error(\"Missing class parentship\");\n } catch (error: any) {\n if (error.status === 404) {\n console.error(`Foreign key validation failed: document not found in class '${foreignClass}'. ${this.class?.getName()}`, { error });\n return false;\n }\n throw error;\n }\n },\n {\n message: `One or more documents not found in class '${foreignClass}'.`,\n }\n );\n break;\n\n case 'reference':\n field = z.string().min(1);\n break;\n\n default:\n throw new Error(`Unsupported schema type: '${type}' for field '${name}'`);\n }\n\n // These rules are applied regardless of the type, and in the correct order\n if (config.defaultValue) {\n field = field.default(config.defaultValue);\n }\n if (config.mandatory !== true) {\n field = field.optional();\n }\n if (config.isArray === true) {\n field = z.array(field);\n }\n\n this.field = field;\n }\n\n /**\n * Creates a new Attribute and persists it to the parent Class.\n * This is the primary factory method for creating attributes.\n * \n * @param classObj - The parent Class to add the attribute to\n * @param name - The attribute name\n * @param type - The attribute type\n * @param description - Optional description\n * @param config - Type-specific configuration\n * @returns The created Attribute instance\n * \n * @example\n * ```typescript\n * const priceAttr = await Attribute.create(productClass, 'price', 'decimal', 'Product price', {\n * min: 0,\n * precision: 2,\n * mandatory: true\n * });\n * ```\n */\n public static async create(\n classObj: Class,\n name: string,\n type: AttributeType[\"type\"],\n description?: string,\n config?: AttributeType[\"config\"]\n ) {\n const attribute = new Attribute(classObj, name, type, description, config);\n await attribute.ensureReferenceConfigIsValid();\n await Attribute.build(attribute)\n return attribute;\n }\n\n /**\n * Checks if this attribute is marked as a primary key.\n * @returns `true` if this is a primary key attribute\n */\n isPrimaryKey = () => {\n let model = this.getModel();\n return !!model.config.primaryKey;\n }\n\n /**\n * Checks if this attribute is mandatory (required).\n * @returns `true` if the attribute is mandatory\n */\n isMandatory = () => {\n return !!this.model.config.mandatory;\n }\n\n /**\n * Returns the AttributeModel for this attribute.\n * @returns The underlying AttributeModel\n */\n getModel = () => {\n return this.model;\n }\n\n /**\n * Returns the parent Class for this attribute.\n * @returns The Class instance\n * @throws Error if the attribute has no parent class\n */\n getClass = () => {\n if (this.class) return this.class\n else throw Error(\"Missing class configuration for this attribute\");\n }\n\n /**\n * Validates a value against this attribute's Zod schema.\n * \n * @param data - The value to validate\n * @returns Zod safe parse result with success status and data/error\n * \n * @example\n * ```typescript\n * const result = await priceAttr.validate(19.99);\n * if (result.success) {\n * console.log('Valid:', result.data);\n * } else {\n * console.log('Invalid:', result.error);\n * }\n * ```\n */\n public validate = async (data: any): Promise<SafeParseReturnType<any, any>> => {\n return this.field.safeParseAsync(data);\n }\n\n /**\n * Adds an attribute to its parent class and persists to the database.\n * Used internally by {@link Attribute.create}.\n * \n * @param attributeObj - The Attribute instance to build\n * @returns The Attribute instance\n * @throws Error if the class has no stack connection\n */\n static build = async (attributeObj: Attribute) => {\n let classObj = attributeObj.getClass();\n let stack = classObj.getStack();\n if (stack) {\n await classObj.addAttribute(attributeObj);\n return attributeObj;\n } else {\n throw new Error(\"Missing db configuration\");\n }\n }\n\n setModel = (model: AttributeModel) => {\n let currentModel = this.getModel();\n model = Object.assign(currentModel || {}, model);\n this.model = model;\n this.defaultValue = model.config.defaultValue;\n }\n\n // TODO: Better define config\n getType = (type: AttributeType[\"type\"]) => {\n if (this.checkTypeValidity(type)) {\n return type\n } else throw Error(\"Invalid attribute type: \" + type)\n // return this?\n }\n\n /**\n * Returns an empty/default value for this attribute.\n * Uses the Zod schema's default value if configured.\n * @returns Object with attribute name as key and default/null value\n */\n getEmpty = () => {\n const partialDoc = {\n [this.name]: this.field.parse(undefined) || null\n }\n return partialDoc;\n }\n\n // getType()\n\n /**\n * Returns the attribute name.\n * @returns The attribute name string\n */\n getName = () => {\n return this.name;\n }\n\n checkTypeValidity = (type: string) => {\n let validity = false;\n if (ATTRIBUTE_TYPES.includes(type)) {\n validity = true;\n }\n return validity;\n }\n\n // TODO: change to imported const default configs for types\n // as of now it accepts only string\n // TODO: since config depends on attribute's type, \n // find a way to check if given configs are correct\n // find a way to add default configs base on type\n getTypeConf = (type: AttributeType[\"type\"], config: AttributeType[\"config\"] | undefined) => {\n switch (type) {\n // TODO: add missing cases and change values to imported const \n case \"decimal\":\n config = Object.assign({ max: null, min: null, precision: null, isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"integer\":\n config = Object.assign({ max: null, min: null, isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"string\":\n config = Object.assign({ isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"object\":\n config = Object.assign({ isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"date\":\n config = Object.assign({ format: \"iso\", max: null, min: null, isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"boolean\":\n config = Object.assign({ defaultValue: false, isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"foreign_key\":\n config = Object.assign({ targetClass: null, isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"enum\":\n config = Object.assign({ values: [], isArray: false }, config) as AttributeTypeConfig;\n break;\n case \"reference\":\n config = Object.assign({ isArray: false }, config) as AttributeTypeReference[\"config\"];\n break;\n default:\n throw new Error(\"Unexpected type: \" + type);\n // return \"^[a-zA-Z0-9_\\\\s]\".concat(\"{0,\"+config.maxLength+\"}$\");\n }\n return config\n }\n}\n\nexport default Attribute;","import { Class, Document, Trigger as Trigger_, TriggerModel, TriggerRunFunction} from \"@docstack/shared\";\n\n/**\n * The Trigger class dynamically hydrates a function from a string.\n * This allows for declarative, data-driven logic to be executed at runtime.\n */\nexport class Trigger extends Trigger_ {\n /** The declarative model for the trigger. */\n public readonly model: TriggerModel;\n public readonly name: TriggerModel[\"name\"];\n public readonly order: TriggerModel[\"order\"];\n\n /** A reference to the parent Class instance. */\n public readonly classObj: Class | undefined;\n\n /** The dynamically hydrated function that executes the trigger logic. */\n public readonly run: TriggerRunFunction;\n\n constructor(model: TriggerModel, classObj?: Class) {\n super();\n this.model = model;\n this.name = model.name;\n this.order = model.order;\n this.classObj = classObj;\n\n if (model.run !== undefined && typeof model.run !== \"string\") {\n throw new Error(\"Trigger model's 'run' field must be a string representation of a function.\");\n }\n\n if (!model.run && !model.jobId) {\n throw new Error(\"Trigger requires either a 'run' script or a 'jobId'.\");\n }\n\n if (model.jobId) {\n this.run = async (document, _classObj, stack) => {\n if (!stack || !stack.jobEngine) {\n throw new Error(`Stack does not expose a job engine for trigger '${model.name}'.`);\n }\n await (stack as any).jobEngine.executeJob(model.jobId as string, { document }, \"event\");\n return document;\n }\n } else if (model.run) {\n // Hydrate the run function from the string.\n try {\n // Use 'new Function()' for secure, sandboxed execution.\n // We pass dependencies as explicit arguments to the function's scope.\n // The `this` context is not used to prevent unwanted access.\n this.run = new Function('document', 'classObj', 'stack', `\n \"use strict\";\n // The developer's code is placed here.\n return (async () => {\n ${model.run}\n })();\n `) as TriggerRunFunction;\n } catch (error) {\n throw new Error(`Failed to hydrate trigger '${model.name}': ${error}`);\n }\n }\n }\n\n /**\n * Executes the hydrated run function with the necessary context.\n * The method is now asynchronous by default.\n * @param document The document to be processed by the trigger.\n * @returns The updated document returned by the trigger logic as a Promise.\n */\n public execute = async (document: Document): Promise<Document> => {\n const stack = this.classObj ? this.classObj.getStack() : undefined;\n \n // Call the dynamically created function with the required arguments.\n // It's crucial to pass the `document` argument and await the result.\n const result = await this.run(document, this.classObj, stack);\n\n if (result === undefined) {\n console.warn(`Trigger '${this.model.name}' did not return a document. Returning the original document.`);\n return document;\n }\n\n return result;\n }\n\n /**\n * Executes the hydrated run function without providing class or stack context.\n * This is useful for testing or previews where cross-document\n * behaviors are not desired.\n * @param document The document to be processed by the trigger.\n * @returns The updated document returned by the trigger logic as a Promise.\n */\n public executeLimited = async (document: Document): Promise<Document> => {\n // Call the dynamically created function, providing null for classObj and stack.\n const result = await this.run(document);\n\n if (result === undefined) {\n console.warn(`Trigger '${this.model.name}' did not return a document. Returning the original document.`);\n return document;\n }\n\n return result;\n }\n}\n","import { Class as Class_, DesignDocument, TriggerModel } from \"@docstack/shared\";\nimport createLogger from \"../utils/logger/index\";\n// import ReferenceAttribute from '../Reference';\nimport { Stack, ClassModel, AttributeModel, Document } from \"@docstack/shared\";\nimport Attribute from \"./attribute\";\nimport { Logger } from 'winston';\nimport { Trigger } from \"./trigger/index\";\nimport { z } from \"zod\";\nimport clientLogger from \"../utils/logger/index\";\n\n/**\n * Represents a data class (schema definition) in the DocStack database.\n * \n * A Class defines the structure of documents, including their attributes,\n * validation rules (via Zod), and triggers that execute during document operations.\n * \n * Use the static factory methods ({@link Class.create}, {@link Class.fetch}) to\n * instantiate classes - the constructor is private.\n * \n * @example\n * ```typescript\n * // Create a new class with schema\n * const taskClass = await Class.create(stack, 'Task', 'class', 'User Tasks');\n * \n * // Add attributes to define the schema\n * await Attribute.create(taskClass, 'title', 'string', 'Task Title', { mandatory: true });\n * await Attribute.create(taskClass, 'isComplete', 'boolean', 'Done?', { defaultValue: false });\n * \n * // Create documents (cards) of this class\n * const task = await taskClass.add({ title: 'My Task', isComplete: false });\n * ```\n * \n * @extends Class_\n */\nclass Class extends Class_ {\n /** Reference to the parent stack instance. */\n stack: Stack | undefined;\n /** The name of this class (e.g., 'Task', 'User'). */\n name!: string;\n /** The class type (e.g., 'class', '~self'). */\n type!: ClassModel[\"~class\"];\n /** Optional description of the class purpose. */\n description?: string;\n /** Map of attribute names to Attribute instances defining the schema. */\n attributes: { [name: string]: Attribute } = {};\n /** The raw schema definition from the ClassModel. */\n schema: ClassModel[\"schema\"] = {};\n /** Zod schema for runtime validation of document data. */\n schemaZOD: z.ZodObject<any, any, any> = z.object({});\n /** The unique identifier for this class (e.g., 'Task', 'Class-123'). */\n id?: string;\n /** The underlying ClassModel document. */\n model!: ClassModel;\n /** Current state indicating if the class is processing an operation. */\n state: \"busy\" | \"idle\" = \"idle\";\n static logger: Logger = createLogger().child({ module: \"class\" });\n logger!: Logger;\n /** Array of triggers that execute before/after document operations. */\n triggers: Trigger[] = [];\n\n private constructor() {\n super();\n // Private constructor to prevent direct instantiation\n /* Populated on async build */\n // this.id = null; \n }\n\n // TODO: Test\n /*\n inheritAttributes( parentClass: Class ) {\n let parentAttributes = parentClass.getAttributes();\n for ( let attribute of parentAttributes ) {\n this.addAttribute(attribute);\n }\n } */\n\n build = (): Promise<Class> => {\n return new Promise(async (resolve, reject) => {\n let stack = this.getStack();\n if (stack) {\n // if (parentClassName) this.setParentClass(parentClassName);\n let classModel = await stack.addClass(this);\n // Hydrate model\n if (classModel) {\n this.setModel(classModel)\n Class.logger.info(\"build - classModel\", { classModel: classModel })\n this.setId(classModel._id);\n resolve(this);\n } else {\n reject(\"unable to get classModel. Check logs\");\n }\n\n } else {\n reject(\"Missing stack assignment\");\n }\n })\n }\n\n init = (\n stack: Stack | null,\n id: string,\n name: string,\n type: ClassModel[\"~class\"],\n description?: string,\n schema: ClassModel[\"schema\"] = {}\n // parentClass: Class | null\n ) => {\n // this.parentClass = parentClass;\n if (stack) {\n this.stack = stack;\n }\n this.name = name;\n this.id = id;\n this.description = description;\n this.type = type;\n // this.attributes = [];\n // this.stack = null;\n // this.id = null;\n // if (schema) {\n // this.schema = schema;\n // }\n this.setModel({\n \"~class\": type, _id: id, active: true,\n name, description,\n schema, triggers: [],\n });\n\n this.logger = clientLogger(stack).child({ module: \"class\", className: this.name });\n // TODO: Waiting for test of method\n // if (parentClass) this.inheritAttributes(parentClass);\n }\n\n\n /**\n * Gets a Class instance without persisting it to the database.\n * Use this for working with existing class models or for testing.\n * Sets up a document change listener for real-time updates.\n * \n * @param stack - The parent stack instance\n * @param id - The class ID\n * @param name - The class name\n * @param type - The class type\n * @param description - Optional description\n * @param schema - Initial schema definition\n * @returns A new Class instance (not persisted)\n */\n public static get = (\n stack: Stack,\n id: string,\n name: string,\n type: ClassModel[\"~class\"],\n description?: string,\n schema: ClassModel[\"schema\"] = {},\n ) => {\n const class_ = new Class();\n Class.logger.info(\"Received schema\", { schema })\n class_.init(stack, id, name, type, description, schema);\n // Add listener for new documents of this class type\n class_.stack!.onClassDoc(name)\n .on(\"change\", (change) => {\n const evt = new CustomEvent(\"doc\", {\n detail: change\n })\n class_.dispatchEvent(evt);\n })\n return class_;\n }\n\n /**\n * Creates a new class and persists it to the database.\n * This is the primary factory method for creating new classes.\n * \n * @param stack - The parent stack instance\n * @param name - The name for the new class\n * @param type - The class type (typically 'class')\n * @param description - Optional description of the class\n * @param schema - Initial schema definition\n * @returns The persisted Class instance\n * \n * @example\n * ```typescript\n * const userClass = await Class.create(stack, 'User', 'class', 'Application users');\n * ```\n */\n public static create = async (\n stack: Stack,\n name: string,\n type: ClassModel[\"~class\"],\n description?: string,\n schema: ClassModel[\"schema\"] = {},\n ) => {\n const class_ = Class.get(stack, name, name, type, description, schema);\n await class_.build();\n return class_;\n }\n\n /**\n * Builds a Class instance from an existing ClassModel document.\n * Hydrates attributes and triggers from the model.\n * \n * @param stack - The parent stack instance\n * @param classModel - The ClassModel document from the database\n * @returns The hydrated Class instance\n */\n static buildFromModel = async (stack: Stack, classModel: ClassModel) => {\n Class.logger.info(\"buildFromModel - Instantiate from model\", { classModel });\n\n if (classModel._rev) {\n let classObj: Class = Class.get(\n stack, classModel._id, classModel.name,\n classModel[\"~class\"], classModel.description,\n classModel.schema\n )\n classObj.setModel(classModel);\n return classObj;\n } else {\n let classObj: Class = await Class.create(stack, classModel.name, classModel[\"~class\"], classModel[\"~class\"], classModel.schema);\n classObj.setModel(classModel);\n return classObj;\n }\n }\n\n /**\n * Fetches a class by its document ID.\n * \n * @param stack - The parent stack instance\n * @param classId - The class document ID\n * @returns The Class instance\n * @throws Error if the class is not found\n */\n static fetchById = async (stack: Stack, classId: string) => {\n try {\n let classModel = await stack.db.get<ClassModel>(classId);\n const classObj = await Class.buildFromModel(stack, classModel);\n return classObj;\n } catch (error) {\n throw new Error(`Class not found: ${classId}`);\n }\n }\n\n /**\n * Fetches a class by its name.\n * This is the most common way to retrieve an existing class.\n * \n * @param stack - The parent stack instance\n * @param className - The class name to fetch\n * @returns The Class instance, or `null` if not found\n * \n * @example\n * ```typescript\n * const taskClass = await Class.fetch(stack, 'Task');\n * if (taskClass) {\n * const tasks = await taskClass.getCards();\n * }\n * ```\n */\n static fetch = async (stack: Stack, className: string) => {\n let classModel = await stack.getClassModel(className);\n if (classModel) {\n return Class.buildFromModel(stack, classModel);\n } else {\n return null;\n }\n }\n\n uniqueCheck = async (doc: Document): Promise<boolean> => {\n const fnLogger = this.logger.child({ method: \"uniqueCheck\", args: { doc } });\n const duplicate = await this.getByPrimaryKeys(doc);\n if (duplicate == null || duplicate._id == doc._id) {\n fnLogger.info(\"No duplicate found for doc\");\n return true;\n } else {\n fnLogger.info(\"Duplicate found for doc\", { duplicate });\n return false;\n }\n };\n\n bulkUniqueCheck = async (pKs: string[]): Promise<boolean> => {\n const fnLogger = this.logger.child({ method: \"bulkUniqueCheck\", args: { pKs } });\n const ddocId = await this.stack?.addDesignDocumentPKs(this.name, pKs, true);\n fnLogger.info(`Created temporary design document '${ddocId}'`);\n if (this.stack && ddocId) {\n try {\n const result = await this.stack.db.query(`${ddocId}/by_pKeys`, {\n group: true,\n reduce: '_count'\n });\n\n const hasDuplicates = result.rows.some(row => row.value > 1);\n\n if (hasDuplicates) {\n // 3a. Rollback: new schema is invalid\n fnLogger.error('Schema change invalid: new duplicates found.');\n const finalTempDoc = await this.stack.db.get(ddocId);\n await this.stack.db.remove(finalTempDoc);\n return false; // Indicate failure\n } else {\n // 3b. Execute: new schema is valid. Replace the live document.\n fnLogger.info('Bulk unique check completed: no new duplicates found');\n const finalTempDoc = await this.stack.db.get(ddocId) as DesignDocument;\n\n // Clean up the temporary document\n await this.stack.db.remove(finalTempDoc);\n return true; // Indicate success\n }\n } catch (err) {\n console.error('Error during schema validation:', err);\n // Ensure the temporary document is removed on error\n try {\n const finalTempDoc = await this.stack.db.get(ddocId);\n await this.stack.db.remove(finalTempDoc);\n } catch (e: any) { /* ignore */ }\n return false;\n }\n } else {\n fnLogger.error(`Was unable to create temporary design document to group by`);\n return false;\n }\n\n }\n\n /**\n * Validates document data against the class schema using Zod.\n * \n * @param data - The document data to validate\n * @returns `true` if validation passes, `false` otherwise\n */\n validate = async (data: { [key: string]: any }): Promise<boolean> => {\n const fnLogger = this.logger.child({ method: \"validate\" });\n const result = await this.schemaZOD.safeParseAsync(data);\n fnLogger.debug(\"Got result\", { result });\n if (result.success) {\n return true\n } else {\n return false;\n }\n }\n\n // TODO Turn into method (after factory method instantiation refactory is done)\n setId = (id: string) => {\n this.id = id;\n }\n\n getName = () => {\n return this.name;\n }\n\n getStack = () => {\n return this.stack;\n }\n\n getDescription = () => {\n return this.description;\n }\n\n getType = () => {\n return this.type;\n }\n\n getId = () => {\n return this.id;\n }\n\n /**\n * Builds the schema object from the current attributes.\n * @returns The schema definition object\n */\n buildSchema = () => {\n let schema: ClassModel[\"schema\"] = {};\n Object.entries(this.attributes).forEach(t => {\n schema[t[0]] = t[1].model\n });\n return schema;\n }\n\n /**\n * Returns the current ClassModel representation of this class.\n * @returns The ClassModel document\n */\n getModel = () => {\n let triggers: ClassModel[\"triggers\"] = [];\n for (const trigger of this.triggers) {\n triggers.push(trigger.model);\n }\n let model: ClassModel = {\n _id: this.id!,\n name: this.getName(),\n description: this.getDescription(),\n \"~class\": this.getType(),\n schema: this.buildSchema(),\n triggers: triggers,\n active: true,\n _rev: this.model ? this.model._rev : \"\",\n \"~createTimestamp\": this.model ? this.model[\"~createTimestamp\"] : undefined,\n };\n return model;\n }\n\n // [TODO] Change into buildFromModel\n /**\n * It hydrates attributes and triggers from given model\n * @param model \n */\n setModel = (model?: ClassModel) => {\n Class.logger.info(\"setModel - got incoming model\", { model: model });\n // Retreive current class model\n let currentModel = this.getModel();\n // Set model arg to the overwrite of the current model with the given one \n model = Object.assign(currentModel, model);\n if (model.schema) {\n // model.schema = {...this.model.schema, ...model.schema};\n this.attributes = {};\n this.schemaZOD = z.object({});\n for (const [key, attrModel] of Object.entries(model.schema)) {\n let attribute = new Attribute(\n this, attrModel.name, attrModel.type, attrModel.description, attrModel.config\n );\n this.attributes[attrModel.name] = attribute;\n this.schemaZOD = this.schemaZOD.extend({\n [attrModel.name]: attribute.field\n });\n }\n }\n\n if (model.triggers) {\n this.triggers = [];\n for (const trigger of model.triggers) {\n let trigger_ = new Trigger(trigger, this);\n this.triggers.push(trigger_);\n }\n }\n\n this.name = model.name;\n this.description = model.description;\n this.type = model[\"~class\"];\n this.model = model;\n Class.logger.info(\"setModel - model after processing\", { model: model })\n }\n\n /**\n * Returns the primary key attribute names for this class.\n * @returns Array of attribute names marked as primary keys\n */\n getPrimaryKeys = () => {\n return Object.values(this.attributes).filter(attr => attr.isPrimaryKey())\n .map(attr => attr.getName());\n }\n\n getAttributes = (...names: string[]) => {\n let attributes: typeof this.attributes = {};\n for (const attribute of Object.values(this.attributes)) {\n if (names.length > 0) {\n // filter with given names\n for (let name of names) {\n // match?\n if (name != null && attribute.getName() == name) {\n attributes[attribute.name] = attribute;\n }\n }\n } else {\n // no filter provided add all\n attributes[attribute.name] = attribute;\n }\n }\n return attributes\n }\n\n hasAllAttributes = (...names: string[]) => {\n let result = false;\n let attributes = this.getAttributes(...names);\n for (let attribute of Object.values(attributes)) {\n result = names.includes(attribute.getName())\n if (!result) break;\n }\n return result;\n }\n\n hasAnyAttributes = (...names: string[]) => {\n let result = false;\n let attributes = this.getAttributes(...names);\n for (let attribute of Object.values(attributes)) {\n result = names.includes(attribute.getName())\n if (result) break;\n }\n return result;\n }\n\n getEncryptedAttributes = () => {\n return Object.values(this.attributes).filter((attribute) => {\n const config = attribute.model.config;\n return config?.encrypted === true && config?.primaryKey !== true;\n });\n }\n\n // interface of hasAnyAttributes\n hasAttribute = (name: string) => {\n return this.hasAnyAttributes(name)\n }\n\n\n /**\n * Adds a new attribute to the class schema.\n * Persists the change to the database.\n * \n * @param attribute - The Attribute instance or AttributeModel to add\n * @returns This Class instance for chaining\n * \n * @example\n * ```typescript\n * await taskClass.addAttribute(new Attribute(taskClass, 'dueDate', 'date', 'Due Date'));\n * // Or use Attribute.create() for a simpler API\n * ```\n */\n addAttribute = async (attribute: Attribute | AttributeModel): Promise<Class> => {\n const fnLogger = this.logger.child({ method: \"addAttribute\", args: { attribute: attribute.name } });\n const attribute_ = attribute instanceof Attribute\n ? attribute : new Attribute(\n this, attribute.name, attribute.type,\n attribute.description, attribute.config\n );\n try {\n let name = attribute_.getName();\n // console.log(\"Adding attribute\", {className: this.name, attribute: name})\n if (!this.hasAttribute(name)) {\n fnLogger.info(\"Adding attribute\", { name: name, type: attribute_.getModel() });\n this.attributes[name] = attribute_;\n let attributeModel = attribute_.getModel();\n fnLogger.info(\"Adding attribute to schema\", { attributeModel: attributeModel });\n const currentSchema = this.model.schema ?? {};\n this.model.schema = {\n ...currentSchema,\n [name]: attributeModel\n };\n this.schemaZOD = this.schemaZOD.extend({\n [name]: attribute_.field\n });\n // TODO:\n // this.schema[name] = attributeModel; // sometimes getting schema undefined\n // update class on db\n fnLogger.info(\"Checking for requirements before updating class on db\", { stack: (this.stack != null), id: this.id })\n if (this.stack && this.id) {\n // debugger;\n fnLogger.info(\"Updating class on db\")\n let res = await this.stack.updateClass(this);\n return this;\n // TODO: Check if this class has subclasses\n } else {\n fnLogger.error(\"Class not updated on db because of missing stack or id\")\n return this;\n }\n } else {\n fnLogger.error(\"Attribute with name \" + name + \" already exists within this Class\");\n return this;\n }\n } catch (e) {\n fnLogger.error(\"Falied adding attribute because: \", e)\n return this;\n }\n }\n\n /**\n * Modifies an existing attribute in the class schema.\n * \n * @param name - The name of the attribute to modify\n * @param attribute - The new Attribute or AttributeModel definition\n * @returns This Class instance for chaining\n */\n modifyAttribute = async (name: string, attribute: Attribute | AttributeModel): Promise<Class> => {\n const fnLogger = this.logger.child({ method: \"modifyAttribute\", args: { name } });\n const originSchema = { ...this.model.schema[name] },\n originAttr = this.attributes[name];\n const attribute_ = attribute instanceof Attribute\n ? attribute : new Attribute(\n this, attribute.name, attribute.type,\n attribute.description, attribute.config\n );\n try {\n fnLogger.info(`Attempting to change attribute definition.`);\n delete this.model.schema[name];\n delete this.attributes[name];\n this.schemaZOD = this.schemaZOD.omit({ [name]: true });\n return this.addAttribute(attribute_);\n } catch (e: any) {\n // Revert\n this.model.schema[name] = originSchema;\n this.attributes[name] = originAttr;\n fnLogger.error(`Failed at removing attribute from class.'`);\n }\n return this;\n }\n\n /**\n * Removes an attribute from the class schema.\n * \n * @param name - The name of the attribute to remove\n * @returns This Class instance for chaining\n */\n removeAttribute = async (name: string): Promise<Class> => {\n const fnLogger = this.logger.child({ method: \"removeAttribute\", args: { name } });\n const originSchema = { ...this.model.schema[name] },\n originAttr = this.attributes[name];\n try {\n fnLogger.info(`Attempting to remove attribute from class.`);\n delete this.model.schema[name];\n delete this.attributes[name];\n this.schemaZOD = this.schemaZOD.omit({ [name]: true });\n if (this.stack) {\n this.stack.updateClass(this);\n } else throw new Error(\"Missing stack, cannot perform updates.\");\n } catch (e: any) {\n // Revert\n this.model.schema[name] = originSchema;\n this.attributes[name] = originAttr;\n fnLogger.error(`Failed at removing attribute from class.'`);\n }\n return this;\n };\n\n /**\n * Creates a new document (card) of this class type.\n * \n * @param params - The document data\n * @returns The created document, or `null` if stack is not defined\n * \n * @example\n * ```typescript\n * const task = await taskClass.addCard({\n * title: 'My Task',\n * isComplete: false\n * });\n * ```\n */\n addCard = async (params: { [key: string]: any }) => {\n const fnLogger = this.logger.child({ method: \"addCard\", args: { params } });\n if (!this.stack) {\n fnLogger.error(\"Stack is not defined\");\n return null;\n }\n return await this.stack.createDoc(null, this.getName(), this, params);\n }\n\n /**\n * Creates multiple documents (cards) of this class type in a batch.\n * \n * @param paramsArray - Array of document data objects\n * @returns Array of created documents\n */\n addCards = async (paramsArray: { [key: string]: any }[]) => {\n const fnLogger = this.logger.child({ method: \"addCards\", args: { paramsArray } });\n if (!this.stack) {\n fnLogger.error(\"Stack is not defined\");\n return [];\n }\n let addedCards: Document[] = [];\n addedCards = await this.stack.createDocs(\n paramsArray.map(params => ({ docId: null, params })), this.getName(), this\n );\n return addedCards;\n }\n\n getByPrimaryKeys = async (params: { [key: string]: any }): Promise<Document | null> => {\n const fnLogger = this.logger.child({ method: \"getByPrimaryKeys\" });\n // attempt to retrieve card by primary key\n let filter: { [key: string]: any } = {}\n let primaryKeys = this.getPrimaryKeys();\n fnLogger.info(\"Got primary keys\", { primaryKeys });\n if (primaryKeys.length) {\n // executes a reducer function on each element of the primaryKeys array\n // that sets each primary key prop to the corresponding param value \n primaryKeys.reduce(\n (accumulator, currentValue) => accumulator[currentValue] = params[currentValue],\n filter,\n );\n fnLogger.info(\"Defined filter\", { filter });\n let cards = await this.getCards(filter, undefined, 0, 1);\n if (cards.length > 0) {\n return cards[0];\n } else {\n fnLogger.info(\"Did not find any documents with given primary key\", { filter });\n return null;\n }\n } else {\n fnLogger.info(\"Class has no field specified as primary key\");\n return null;\n }\n }\n\n /**\n * Creates one or more documents of this class type.\n * Convenience method that handles both single and batch creation.\n * \n * @param params - Document data (single object for one doc, or multiple for batch)\n * @returns Single document when one param passed, array when multiple\n * \n * @example\n * ```typescript\n * // Single document\n * const task = await taskClass.add({ title: 'Task 1' });\n * \n * // Multiple documents\n * const tasks = await taskClass.add(\n * { title: 'Task 1' },\n * { title: 'Task 2' }\n * );\n * ```\n */\n async add(params: { [key: string]: any }): Promise<Document | null>;\n async add(...paramsArray: { [key: string]: any }[]): Promise<Document[]>;\n async add(...paramsArray: { [key: string]: any }[]): Promise<Document | Document[] | null> {\n const fnLogger = this.logger.child({ method: \"add\", args: { paramsArray } });\n const addedCards = await this.addCards(paramsArray);\n fnLogger.info(\"Added cards\", { addedCards });\n if (paramsArray.length === 1) return addedCards[0] || null;\n return addedCards;\n }\n\n addOrUpdateCard = async (params: { [key: string]: any }, cardId?: string) => {\n const fnLogger = this.logger.child({ method: \"addOrUpdateCard\", args: { params, cardId } });\n return new Promise<Document | null>(async (resolve, reject) => {\n if (cardId) {\n fnLogger.info(\"Provided document's id, performing an update\");\n const res = await this.updateCard(cardId, params);\n resolve(res);\n } else {\n fnLogger.info(\"No document id provided, checking for PKs\");\n const card = await this.getByPrimaryKeys(params);\n if (card == null) {\n const res = await this.addCard(params);\n resolve(res);\n } else {\n fnLogger.error(\"Duplicate card by keys\");\n reject(\"Duplicate card by keys\");\n }\n }\n });\n\n }\n\n /**\n * Updates an existing document (card) of this class.\n * \n * @param cardId - The document ID to update\n * @param params - The updated document data\n * @returns The updated document, or `null` if stack is not defined\n */\n updateCard = async (cardId: string, params: { [key: string]: any }) => {\n return new Promise<Document | null>(async (resolve, reject) => {\n if (this.stack) {\n const res = await this.stack.createDoc(cardId, this.getName(), this, params);\n resolve(res)\n } else {\n Class.logger.info(\"no stack defined\");\n resolve(null);\n }\n })\n }\n\n /**\n * Soft-deletes a document by setting its `active` flag to `false`.\n * \n * @param cardId - The document ID to delete\n * @returns `true` if successful, `false` otherwise\n */\n deleteCard = async (cardId: string) => {\n const fnLogger = this.logger.child({ method: \"deleteCard\", args: { cardId } });\n if (this.stack) {\n const res = await this.stack.deleteDocument(cardId);\n return res;\n } else {\n fnLogger.error(\"Stack is not defined\");\n return false;\n }\n }\n\n /**\n * Retrieves documents (cards) of this class type.\n * \n * @param selector - Optional PouchDB/Mango selector for filtering\n * @param fields - Optional list of fields to return\n * @param skip - Number of documents to skip\n * @param limit - Maximum number of documents to return\n * @returns Array of matching documents\n * \n * @example\n * ```typescript\n * // Get all tasks\n * const allTasks = await taskClass.getCards();\n * \n * // Get incomplete tasks\n * const incomplete = await taskClass.getCards({ isComplete: { $eq: false } });\n * ```\n */\n getCards = async (selector?: { [key: string]: any }, fields?: string[], skip?: number, limit?: number) => {\n const _selector = { ...(selector || {}), \"~class\": { $eq: this.name } };\n this.logger.info(\"getCards - selector\", { selector: _selector, fields, skip, limit })\n let docs = (await this.stack!.findDocuments<Document>(_selector, fields, skip, limit)).docs\n return docs;\n }\n\n /**\n * Retrieves one or more documents by their IDs.\n * \n * @param cardId - Single ID or multiple IDs to fetch\n * @returns Single document (or null) when one ID passed, array when multiple\n * \n * @example\n * ```typescript\n * // Get single document\n * const task = await taskClass.get('Task-123');\n * \n * // Get multiple documents\n * const tasks = await taskClass.get('Task-1', 'Task-2', 'Task-3');\n * ```\n */\n async get(cardId: string): Promise<Document | null>;\n async get(...cardId: string[]): Promise<Document[]>;\n async get(...cardId: string[]): Promise<Document | Document[] | null> {\n const fnLogger = this.logger.child({ method: \"get\", args: { cardId } });\n if (typeof cardId === \"string\") {\n let docs = await this.getCards(\n { _id: { $eq: cardId } },\n );\n return docs[0] || null;\n } else {\n let docs = await this.getCards(\n { _id: { $in: cardId } },\n );\n fnLogger.info(\"Fetched documents\", { docs });\n return docs;\n }\n }\n\n /**\n * Adds a trigger to this class.\n * Triggers execute before or after document operations.\n * \n * @param name - The trigger name\n * @param model - The trigger model containing the execution logic\n * @returns This Class instance for chaining\n * \n * @example\n * ```typescript\n * await taskClass.addTrigger('generate-slug', {\n * name: 'generate-slug',\n * order: 'before',\n * run: `document.slug = document.title.toLowerCase().replace(/\\\\s+/g, '-'); return document;`\n * });\n * ```\n */\n addTrigger = async (name: string, model: TriggerModel) => {\n const fnLogger = this.logger.child({ method: \"addTrigger\" });\n try {\n const trigger = new Trigger(model, this);\n this.triggers.push(trigger);\n if (this.stack) {\n this.setModel();\n let res = await this.stack.updateClass(this);\n } else {\n throw new Error(`Stack is not defined. Can't update class`);\n }\n } catch (e) {\n fnLogger.error(e);\n }\n return this;\n }\n\n /**\n * Removes a trigger from this class by name.\n * \n * @param name - The name of the trigger to remove\n * @returns This Class instance for chaining\n */\n removeTrigger = async (name: string) => {\n this.triggers = this.triggers.filter(t => t.name != name)\n return this;\n }\n}\n\nexport default Class;","import { Document, Domain as Domain_, DomainModel, Stack, DomainRelationValidation, DomainRelationParams, Class, RelationDocument } from \"@docstack/shared\";\nimport clientLogger from \"../utils/logger/index\";\nimport winston, { createLogger, Logger } from \"winston\";\n\n/**\n * Represents a relationship definition between two Classes in the DocStack database.\n * \n * A Domain defines how documents of different classes relate to each other,\n * supporting cardinality constraints (1:1, 1:N, N:1, N:N). Relation documents\n * are created to track the links between source and target documents.\n * \n * Use the static factory methods ({@link Domain.create}, {@link Domain.fetch}) to\n * instantiate domains - the constructor is private.\n * \n * @example\n * ```typescript\n * // Define a 1:N relationship between Projects and Tasks\n * const projectTaskDomain = await Domain.create(\n * stack,\n * null,\n * 'ProjectTasks',\n * 'domain',\n * '1:N',\n * projectClass,\n * taskClass\n * );\n * \n * // Create a relation between a project and a task\n * await projectTaskDomain.addRelation(taskDoc, 'Project-1');\n * ```\n * \n * @extends Domain_\n */\nclass Domain extends Domain_ {\n /** Reference to the parent stack instance. */\n stack: Stack | undefined;\n /** The name of this domain (e.g., 'ProjectTasks'). */\n name!: string;\n /** The domain type (typically 'domain'). */\n type!: DomainModel[\"~class\"];\n /** Optional description of the domain purpose. */\n description: string | undefined;\n /** The unique identifier for this domain. */\n id!: string;\n /** The cardinality of the relationship: '1:1', '1:N', 'N:1', or 'N:N'. */\n relation!: DomainModel[\"relation\"];\n /** The source class in the relationship. */\n sourceClass!: Class;\n /** The target class in the relationship. */\n targetClass!: Class;\n /** The underlying DomainModel document. */\n model!: DomainModel;\n /** Current state indicating if the domain is processing an operation. */\n state: \"busy\" | \"idle\" = \"idle\";\n static logger: Logger = clientLogger().child({ module: \"domain\" });\n logger!: Logger;\n\n private constructor() {\n super();\n }\n\n getStack = () => {\n return this.stack;\n }\n\n getName = () => {\n return this.name;\n }\n\n setId = (id: string) => {\n this.id = id;\n }\n\n setModel = (model?: DomainModel) => {\n Domain.logger.info(\"setModel - got incoming model\", { model: model });\n // Retreive current class model\n let currentModel = this.getModel();\n // Set model arg to the overwrite of the current model with the given one \n model = Object.assign(currentModel, model);\n\n this.id = model._id;\n this.name = model.name;\n this.description = model.description;\n this.relation = model.relation;\n this.type = model[\"~class\"];\n this.model = model;\n Domain.logger.info(\"setModel - model after processing\", { model: model })\n }\n\n build = (): Promise<Domain> => {\n return new Promise(async (resolve, reject) => {\n let stack = this.getStack();\n if (stack) {\n let domainModel = await stack.addDomain(this);\n if (domainModel) {\n // Hydrate model\n this.setModel(domainModel);\n Domain.logger.info(\"build - domainModel\", { domainModel });\n this.setId(domainModel._id);\n resolve(this)\n } else {\n reject(\"Unable to get create domainModel. Check logs.\");\n }\n } else {\n reject(\"Missing stack assignment\");\n }\n })\n }\n\n init = (\n stack: Stack | null,\n id: string | null,\n name: string,\n type: DomainModel[\"~class\"],\n relation: typeof this.relation,\n sourceClass: Class,\n targetClass: Class,\n description?: string,\n\n // schema: DomainModel[\"schema\"] = {}\n ) => {\n if (stack) {\n this.stack = stack;\n }\n this.name = name;\n this.id = id!;\n\n this.description = description;\n this.type = type;\n this.relation = relation;\n this.sourceClass = sourceClass;\n this.targetClass = targetClass;\n this.setModel({\n \"~class\": type, _id: id!, active: true,\n name, relation, sourceClass: sourceClass.id!,\n targetClass: targetClass.id!, description,\n })\n this.logger = clientLogger(this.stack).child({ module: \"domain\", domainName: this.name });\n }\n\n /**\n * Gets a Domain instance without persisting it to the database.\n * Use this for working with existing domain models or for testing.\n * Sets up a document change listener for real-time updates.\n * \n * @param stack - The parent stack instance\n * @param id - The domain ID (or null for new domains)\n * @param name - The domain name\n * @param type - The domain type (typically 'domain')\n * @param relation - The cardinality constraint\n * @param sourceClass - The source Class in the relationship\n * @param targetClass - The target Class in the relationship\n * @param description - Optional description\n * @param schema - Optional schema definition\n * @returns A new Domain instance (not persisted)\n */\n public static get = (\n stack: Stack,\n id: string | null,\n name: string,\n type: DomainModel[\"~class\"],\n relation: \"1:1\" | \"1:N\" | \"N:1\" | \"N:N\",\n sourceClass: Class,\n targetClass: Class,\n description?: string,\n schema: DomainModel[\"schema\"] = {},\n ) => {\n const domain_ = new Domain();\n Domain.logger.info(\"Received schema\", { schema })\n domain_.init(\n stack, id, name, type, relation, sourceClass, targetClass, description);\n // Add listener for new documents of this class type\n domain_.stack!.onClassDoc(name)\n .on(\"change\", (change) => {\n const evt = new CustomEvent(\"doc\", {\n detail: change\n })\n domain_.dispatchEvent(evt);\n })\n return domain_;\n }\n\n /**\n * Creates a new domain and persists it to the database.\n * This is the primary factory method for creating new domains.\n * \n * @param stack - The parent stack instance\n * @param id - The domain ID (typically null for auto-generation)\n * @param name - The name for the new domain\n * @param type - The domain type (typically 'domain')\n * @param relation - The cardinality constraint: '1:1', '1:N', 'N:1', or 'N:N'\n * @param sourceClass - The source Class in the relationship\n * @param targetClass - The target Class in the relationship\n * @param description - Optional description of the domain\n * @param schema - Optional schema definition\n * @returns The persisted Domain instance\n * \n * @example\n * ```typescript\n * const domain = await Domain.create(\n * stack, null, 'UserProjects', 'domain', '1:N',\n * userClass, projectClass, 'Users can have many projects'\n * );\n * ```\n */\n public static create = async (\n stack: Stack,\n id: string | null,\n name: string,\n type: DomainModel[\"~class\"],\n relation: \"1:1\" | \"1:N\" | \"N:1\" | \"N:N\",\n sourceClass: Class,\n targetClass: Class,\n description?: string,\n schema: DomainModel[\"schema\"] = {},\n ) => {\n const domain_ = Domain.get(\n stack, null, name, type,\n relation, sourceClass, targetClass,\n description, schema\n );\n await domain_.build();\n return domain_;\n }\n\n /**\n * Builds a Domain instance from an existing DomainModel document.\n * Fetches the source and target classes and hydrates the domain.\n * \n * @param stack - The parent stack instance\n * @param domainModel - The DomainModel document from the database\n * @returns The hydrated Domain instance\n * @throws Error if source or target class is not found\n */\n static buildFromModel = async (stack: Stack, domainModel: DomainModel) => {\n Domain.logger.info(\"buildFromModel - Instantiate from model\", { domainModel });\n const sourceClass = await stack.getClass(domainModel.sourceClass);\n const targetClass = await stack.getClass(domainModel.targetClass);\n if (!sourceClass || !targetClass) {\n throw new Error(\"Source or target class not found for domain \" + domainModel.name);\n }\n if (domainModel._rev) {\n let classObj: Domain = Domain.get(\n stack, domainModel._id, domainModel.name,\n domainModel[\"~class\"], domainModel.relation,\n sourceClass, targetClass,\n domainModel.description, domainModel.schema\n )\n return classObj;\n } else {\n let classObj: Domain = await Domain.create(\n stack, domainModel._id, domainModel.name, domainModel[\"~class\"],\n domainModel.relation, sourceClass,\n targetClass, domainModel.description,\n domainModel.schema\n );\n return classObj;\n }\n }\n\n /**\n * Fetches a domain by its name.\n * This is the most common way to retrieve an existing domain.\n * \n * @param stack - The parent stack instance\n * @param domainName - The domain name to fetch\n * @returns The Domain instance, or `null` if not found\n * \n * @example\n * ```typescript\n * const domain = await Domain.fetch(stack, 'ProjectTasks');\n * if (domain) {\n * const relations = await domain.getRelations();\n * }\n * ```\n */\n static fetch = async (stack: Stack, domainName: string) => {\n let domainModel = await stack.getDomainModel(domainName);\n if (domainModel) {\n return Domain.buildFromModel(stack, domainModel);\n } else {\n return null;\n }\n }\n\n /**\n * Returns the current DomainModel representation of this domain.\n * @returns The DomainModel document\n */\n getModel = () => {\n let model: DomainModel = {\n _id: this.id,\n name: this.name,\n description: this.description,\n \"~class\": this.type,\n relation: this.relation,\n sourceClass: this.sourceClass.id!,\n targetClass: this.targetClass.id!,\n active: true,\n _rev: this.model ? this.model._rev : \"\",\n \"~createTimestamp\": this.model ? this.model[\"~createTimestamp\"] : undefined,\n };\n return model;\n }\n\n requireStack = (): Stack => {\n if (!this.stack) {\n throw new Error(`Stack is not defined for Domain ${this.name}`);\n }\n return this.stack;\n }\n\n getDocumentRole = (doc: Document): \"source\" | \"target\" => {\n if (doc[\"~class\"] === this.sourceClass.getName()) {\n return \"source\";\n }\n if (doc[\"~class\"] === this.targetClass.getName()) {\n return \"target\";\n }\n throw new Error(`Document of type '${doc[\"~class\"]}' is not part of domain '${this.name}'.`);\n }\n\n assertReferenceAllowed = (role: \"source\" | \"target\") => {\n switch (this.relation) {\n case \"1:N\":\n if (role !== \"target\") {\n throw new Error(`Documents of class '${this.sourceClass}' cannot hold reference attributes for domain '${this.name}'.`);\n }\n break;\n case \"N:1\":\n if (role !== \"source\") {\n throw new Error(`Documents of class '${this.targetClass}' cannot hold reference attributes for domain '${this.name}'.`);\n }\n break;\n case \"1:1\":\n break;\n case \"N:N\":\n throw new Error(`Domain '${this.name}' does not support reference attributes.`);\n default:\n throw new Error(`Unsupported relation type ${this.relation}`);\n }\n }\n\n buildRelationParams = (doc: Document, referenceId: string, role: \"source\" | \"target\"): DomainRelationParams => {\n if (!doc._id) {\n throw new Error(\"Document is missing identifier.\");\n }\n if (typeof referenceId !== \"string\" || referenceId.length === 0) {\n throw new Error(`Invalid reference value provided for domain '${this.name}'.`);\n }\n if (role === \"source\") {\n return {\n sourceClass: this.sourceClass.id!,\n targetClass: this.targetClass.id!,\n sourceId: doc._id,\n targetId: referenceId\n };\n }\n return {\n sourceClass: this.sourceClass.id!,\n targetClass: this.targetClass.id!,\n sourceId: referenceId,\n targetId: doc._id\n };\n }\n\n fetchReferenceDocument = async (referenceId: string, expectedType: string) => {\n const stack = this.requireStack();\n const referenceDoc = await stack.db.get<Document>(referenceId).catch(() => null);\n if (!referenceDoc || referenceDoc[\"~class\"] !== expectedType || referenceDoc.active === false) {\n throw new Error(`Reference '${referenceId}' does not exist for class '${expectedType}'.`);\n }\n return referenceDoc as Document;\n }\n\n findRelationDoc = async (selector: { [key: string]: any }): Promise<RelationDocument | null> => {\n const stack = this.requireStack();\n const searchSelector = {\n \"~domain\": { $eq: this.name },\n ...selector,\n };\n const { docs } = await stack.findDocuments<RelationDocument>(searchSelector, undefined, 0, 1);\n return docs[0] || null;\n }\n\n throwIfRelationExists = async (filter: { [key: string]: any }, params: DomainRelationParams) => {\n const relation = await this.findRelationDoc(filter);\n if (relation) {\n if (relation.sourceId === params.sourceId && relation.targetId === params.targetId) {\n return relation;\n }\n throw new Error(`Domain '${this.name}' already contains a relation that violates cardinality constraints.`);\n }\n return null;\n }\n\n ensureCardinalityConstraints = async (params: DomainRelationParams) => {\n switch (this.relation) {\n case \"1:1\":\n await this.throwIfRelationExists({ sourceId: { $eq: params.sourceId } }, params);\n await this.throwIfRelationExists({ targetId: { $eq: params.targetId } }, params);\n break;\n case \"1:N\":\n await this.throwIfRelationExists({ targetId: { $eq: params.targetId } }, params);\n break;\n case \"N:1\":\n await this.throwIfRelationExists({ sourceId: { $eq: params.sourceId } }, params);\n break;\n }\n }\n\n validateRelation = async (doc: Document, referenceId: string): Promise<DomainRelationValidation> => {\n const fnLogger = this.logger.child({ method: \"validateRelation\", args: { docId: doc._id, referenceId } });\n const role = this.getDocumentRole(doc);\n this.assertReferenceAllowed(role);\n const expectedType = role === \"source\" ? this.targetClass.getName() : this.sourceClass.getName();\n await this.fetchReferenceDocument(referenceId, expectedType);\n const params = this.buildRelationParams(doc, referenceId, role);\n const existing = await this.findRelationDoc({\n sourceId: { $eq: params.sourceId },\n targetId: { $eq: params.targetId },\n });\n if (existing) {\n fnLogger.info(\"validateRelation - relation already exists\");\n return { params, exists: true, relation: existing };\n }\n await this.ensureCardinalityConstraints(params);\n return { params, exists: false };\n }\n\n /**\n * Retrieves relation documents for this domain.\n * \n * @param selector - Optional PouchDB/Mango selector for filtering\n * @param fields - Optional list of fields to return\n * @param skip - Number of documents to skip\n * @param limit - Maximum number of documents to return\n * @returns Array of matching relation documents\n * \n * @example\n * ```typescript\n * // Get all relations\n * const allRelations = await domain.getRelations();\n * \n * // Get relations for a specific source\n * const projectRelations = await domain.getRelations({ sourceId: { $eq: 'Project-1' } });\n * ```\n */\n getRelations = async (selector?: { [key: string]: any }, fields?: string[], skip?: number, limit?: number) => {\n const stack = this.requireStack();\n const _selector = { ...(selector || {}), \"~domain\": { $eq: this.name } };\n Domain.logger.info(\"getRelations - selector\", { selector: _selector, fields, skip, limit })\n const docs = (await stack.findDocuments<RelationDocument>(_selector, fields, skip, limit)).docs\n return docs;\n }\n\n /**\n * Creates a relation between documents.\n * Validates cardinality constraints before creating the relation.\n * \n * @param document - The document to link (source or target based on role)\n * @param referenceId - The ID of the document to link to\n * @returns The created relation document, or existing relation if already exists\n * \n * @example\n * ```typescript\n * // Link a task to a project (assuming 1:N from Project to Task)\n * const relation = await projectTaskDomain.addRelation(taskDoc, 'Project-1');\n * ```\n */\n addRelation = async (document: Document, referenceId: string) => {\n const fnLogger = this.logger.child({ method: \"addRelation\", args: { document, referenceId } });\n const stack = this.requireStack();\n const validation = await this.validateRelation(document, referenceId);\n if (validation.exists) {\n fnLogger.info(\"addRelation - relation already in place\");\n return validation.relation || null;\n }\n fnLogger.info(\"addRelation - relation validated\");\n const relationDoc = await stack.createRelationDoc(null, this.name, this, validation.params);\n fnLogger.info(\"addRelation - relationDoc created\", { relationDoc });\n return relationDoc;\n }\n\n /**\n * Deletes a relation between two documents by their IDs.\n * \n * @param sourceId - The source document ID\n * @param targetId - The target document ID\n * @returns `true` if deleted, `false` if relation not found\n */\n deleteRelation = async (sourceId: string, targetId: string) => {\n const relation = await this.findRelationDoc({\n sourceId: { $eq: sourceId },\n targetId: { $eq: targetId },\n });\n if (!relation || !relation._id) {\n return false;\n }\n return this.requireStack().deleteDocument(relation._id);\n }\n\n /**\n * Deletes a relation document by its ID.\n * \n * @param relationDocId - The relation document ID to delete\n * @returns `true` if deleted successfully\n */\n deleteRelationDoc = async (relationDocId: string) => {\n return this.requireStack().deleteDocument(relationDocId);\n }\n\n}\n\nexport default Domain;","import { Patch } from \"@docstack/shared\";\nimport semver from \"semver\";\n\nconst syspatches: Patch[] = [];\nconst hashContent = async (content: string) => {\n const data = new TextEncoder().encode(content);\n const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');\n};\n\n// TODO: implement _rev auto handler:\n// If patches include updates to existing documents, \n// we need to ensure that the _rev field is handled correctly to avoid conflicts.\n\nconst sys_001: Patch = {\n \"_id\": \"~sys-0.0.1\",\n \"~class\": \"patch\",\n \"version\": \"0.0.1\",\n \"target\": \"system\",\n \"changelog\": \"### Initial patch with originators: Class and Domain\",\n \"docs\": [\n {\n \"_id\": \"class\",\n \"active\": true,\n \"name\": \"class\",\n \"description\": \"A class document representing a data model class\",\n \"~class\": \"~self\",\n \"schema\": {\n \"name\": {\n \"name\": \"name\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"mandatory\": true,\n \"isArray\": false,\n \"maxLength\": 100\n }\n },\n \"description\": {\n \"name\": \"description\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": false,\n \"isArray\": false,\n \"maxLength\": 500\n }\n },\n \"~class\": {\n \"name\": \"~class\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"isArray\": false,\n \"maxLength\": 50,\n \"defaultValue\": \"class\"\n }\n },\n \"schema\": { \"name\": \"schema\", \"type\": \"object\", \"config\": { \"maxLength\": 1000, \"isArray\": false } },\n }\n },\n {\n \"_id\": \"domain\",\n \"active\": true,\n \"name\": \"domain\",\n \"description\": \"A domain document representing a data model domain\",\n \"~class\": \"~self\",\n \"schema\": {\n \"~class\": { name: \"~class\", type: \"string\", config: { defaultValue: \"domain\" } },\n \"relation\": {\n name: \"relation\", type: \"enum\", config: {\n isArray: false, values: [\n { value: \"1:1\" }, { value: \"1:N\" }, { value: \"N:1\" }, { value: \"N:N\" }\n ]\n }\n },\n \"sourceClass\": {\n name: \"sourceClass\",\n type: \"foreign_key\",\n config: {\n targetClass: \"class\",\n isArray: false\n }\n },\n \"targetClass\": {\n name: \"targetClass\",\n type: \"foreign_key\",\n config: {\n targetClass: \"class\",\n isArray: false\n }\n },\n }\n }\n ]\n}\n\n// const sys_002: Patch = {\n// \"_id\": \"~sys-0.0.2\",\n// \"~class\": \"patch\",\n// \"version\": \"0.0.2\",\n// \"target\": \"system\",\n// \"changelog\": \"### Initial patch with system classes and domains\",\n// \"docs\": [\n// {\n// \"_id\": \"log\",\n// \"active\": true,\n// \"name\": \"log\",\n// \"description\": \"Contains the system logs\",\n// \"~class\": \"class\",\n// \"schema\": {\n// \"log\": {\n// \"name\": \"log\",\n// \"type\": \"object\",\n// \"config\": {\n// \"isArray\": false\n// }\n// }\n// }\n// }\n// ]\n// }\n\nconst sys_003: Patch = {\n \"_id\": \"~sys-0.0.3\",\n \"~class\": \"patch\",\n \"version\": \"0.0.3\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.3\\\\\\n#### New Classes: ~User, ~UserSession\",\n \"docs\": [\n {\n \"_id\": \"~User\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n }\n }\n },\n {\n \"_id\": \"~UserSession\",\n \"name\": \"UserSession\",\n \"active\": true,\n \"description\": \"Tracks user sessions\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false,\n \"primaryKey\": true,\n \"mandatory\": true\n }\n },\n \"sessionId\": {\n \"name\": \"sessionId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"primaryKey\": true,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStart\": {\n \"name\": \"sessionStart\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStatus\": {\n \"name\": \"sessionStatus\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionEnd\": {\n \"name\": \"sessionEnd\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": false\n }\n }\n }\n }\n ]\n};\n\nconst classicAuthJobContent = `\nconst toHex = (buffer) => Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n\nasync function deriveKeyMaterial(password, salt, iterations = 120000, length = 32) {\n if (!globalThis.crypto || !globalThis.crypto.subtle) {\n throw new Error(\"WebCrypto unavailable for key derivation\");\n }\n\n const encoder = new TextEncoder();\n const keyMaterial = await globalThis.crypto.subtle.importKey(\n \"raw\",\n encoder.encode(String(password)),\n { name: \"PBKDF2\" },\n false,\n [\"deriveBits\"]\n );\n\n const derived = await globalThis.crypto.subtle.deriveBits(\n {\n name: \"PBKDF2\",\n salt: encoder.encode(String(salt)),\n iterations,\n hash: \"SHA-256\",\n },\n keyMaterial,\n length * 8\n );\n\n return toHex(derived);\n}\n\nasync function execute(_stack, params) {\n const password = params?.password ?? \"\";\n const salt = params?.salt ?? params?.keyDerivationSalt ?? \"\";\n\n if (!password) {\n throw new Error(\"Password is required for key derivation\");\n }\n if (!salt) {\n throw new Error(\"Salt is required for key derivation\");\n }\n\n const derivedKey = await deriveKeyMaterial(password, salt);\n const metadata = { derivedKey, derivedAt: Date.now() };\n return { metadata };\n}\n`;\n\nconst sys_004: Patch = {\n \"_id\": \"~sys-0.0.4\",\n \"~class\": \"patch\",\n \"version\": \"0.0.4\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.4\\\\n#### New Classes: ~Job, ~JobRun, ~Policy, ~AuthModule\\\\n#### Updates: ~User authentication fields\",\n \"docs\": [\n {\n \"_id\": \"~User\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"authMethod\": {\n \"name\": \"authMethod\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"maxLength\": 100,\n \"isArray\": false\n }\n },\n \"externalId\": {\n \"name\": \"externalId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"keyDerivationSalt\": {\n \"name\": \"keyDerivationSalt\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"maxLength\": 200,\n \"isArray\": false\n }\n }\n }\n },\n {\n \"_id\": \"~Job\",\n \"active\": true,\n \"name\": \"Job\",\n \"description\": \"A long running or scheduled job\",\n \"~class\": \"class\",\n \"schema\": {\n \"_id\": { \"name\": \"_id\", \"type\": \"string\", \"config\": { \"primaryKey\": true, \"mandatory\": true } },\n \"name\": { \"name\": \"name\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"description\": { \"name\": \"description\", \"type\": \"string\", \"config\": { \"isArray\": false } },\n \"type\": { \"name\": \"type\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"workerPlatform\": { \"name\": \"workerPlatform\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"content\": { \"name\": \"content\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"hash\": { \"name\": \"hash\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"schedule\": { \"name\": \"schedule\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"isSingleton\": { \"name\": \"isSingleton\", \"type\": \"boolean\", \"config\": { \"defaultValue\": false } },\n \"isEnabled\": { \"name\": \"isEnabled\", \"type\": \"boolean\", \"config\": { \"mandatory\": true, \"defaultValue\": true } },\n \"nextRunTimestamp\": { \"name\": \"nextRunTimestamp\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"defaultParams\": { \"name\": \"defaultParams\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"metadata\": { \"name\": \"metadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } }\n }\n },\n {\n \"_id\": \"~JobRun\",\n \"active\": true,\n \"name\": \"JobRun\",\n \"description\": \"Execution history for jobs\",\n \"~class\": \"class\",\n \"schema\": {\n \"_id\": { \"name\": \"_id\", \"type\": \"string\", \"config\": { \"primaryKey\": true, \"mandatory\": true } },\n \"~class\": { \"name\": \"~class\", \"type\": \"string\", \"config\": { \"mandatory\": true, \"defaultValue\": \"~JobRun\" } },\n \"jobId\": { \"name\": \"jobId\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"status\": { \"name\": \"status\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"triggerType\": { \"name\": \"triggerType\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"startTime\": { \"name\": \"startTime\", \"type\": \"integer\", \"config\": { \"mandatory\": true } },\n \"endTime\": { \"name\": \"endTime\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"durationMs\": { \"name\": \"durationMs\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"runtimeArgs\": { \"name\": \"runtimeArgs\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"initialMetadata\": { \"name\": \"initialMetadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"finalMetadata\": { \"name\": \"finalMetadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"errorMessage\": { \"name\": \"errorMessage\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"errorStack\": { \"name\": \"errorStack\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"logs\": { \"name\": \"logs\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"workerId\": { \"name\": \"workerId\", \"type\": \"string\", \"config\": { \"mandatory\": false } }\n }\n },\n {\n \"_id\": \"~Policy\",\n \"active\": true,\n \"name\": \"Policy\",\n \"description\": \"Access policies for classes and documents\",\n \"~class\": \"class\",\n \"schema\": {\n \"userId\": { \"name\": \"userId\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"rule\": { \"name\": \"rule\", \"type\": \"string\", \"config\": { \"mandatory\": true, \"maxLength\": 2000 } },\n \"description\": { \"name\": \"description\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"targetClass\": { \"name\": \"targetClass\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": true, \"isArray\": true, \"targetClass\": \"class\" } }\n }\n },\n {\n \"_id\": \"~AuthModule\",\n \"active\": true,\n \"name\": \"AuthModule\",\n \"description\": \"Authentication module descriptor\",\n \"~class\": \"class\",\n \"schema\": {\n \"name\": { \"name\": \"name\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"config\": { \"name\": \"config\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"jobId\": { \"name\": \"jobId\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": true, \"targetClass\": \"~Job\" } }\n }\n },\n ]\n};\n\nconst sys_005: Patch = {\n \"_id\": \"~sys-0.0.5\",\n \"~class\": \"patch\",\n \"version\": \"0.0.5\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.5\\\\n#### New Documents: Job-Auth-Classic, AuthMod-Classic, Policy-System-Classes\",\n \"docs\": [\n {\n \"_id\": \"Job-Auth-Classic\",\n \"~class\": \"~Job\",\n \"active\": true,\n \"name\": \"Classic authentication\",\n \"description\": \"Derive key material from password and salt\",\n \"type\": \"user\",\n \"workerPlatform\": \"client\",\n \"content\": classicAuthJobContent,\n \"hash\": \"e63887145113429477843420c388d35116e255403148163f4c4a436f0b8338b1\", // Pre-calculated hash\n \"isEnabled\": true,\n \"isSingleton\": true,\n \"defaultParams\": {},\n \"metadata\": {}\n },\n ]\n};\n\nconst sys_006: Patch = {\n \"_id\": \"~sys-00.6\",\n \"~class\": \"patch\",\n \"version\": \"0.0.6\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.6\\\\n#### New Documents: AuthMod-Classic, Policy-System-Classes\",\n \"docs\": [\n {\n \"_id\": \"AuthMod-Classic\",\n \"~class\": \"~AuthModule\",\n \"active\": true,\n \"name\": \"Classic Email/Password\",\n \"config\": { \"mode\": \"password\" },\n \"jobId\": \"Job-Auth-Classic\"\n },\n {\n \"_id\": \"Policy-System-Classes\",\n \"~class\": \"~Policy\",\n \"active\": true,\n \"userId\": \"system\",\n \"rule\": \"return true;\",\n \"description\": \"Default system policy\",\n \"targetClass\": [\"class\", \"~User\", \"~UserSession\", \"~Policy\", \"~Job\", \"~JobRun\", \"~AuthModule\"]\n }\n ]\n};\n\nconst sys_007: Patch = {\n \"_id\": \"~sys-0.0.7\",\n \"~class\": \"patch\",\n \"version\": \"0.0.7\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.7\\\\n#### Updates: enforce enum/foreign key definitions for job, policy, and user auth fields\",\n \"docs\": [\n {\n \"_id\": \"~User\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"authMethod\": {\n \"name\": \"authMethod\",\n \"type\": \"foreign_key\",\n \"config\": { \"mandatory\": true, \"targetClass\": \"~AuthModule\" }\n },\n \"externalId\": {\n \"name\": \"externalId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"keyDerivationSalt\": {\n \"name\": \"keyDerivationSalt\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"maxLength\": 200,\n \"isArray\": false\n }\n }\n }\n },\n {\n \"_id\": \"~Job\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"Job\",\n \"description\": \"A long running or scheduled job\",\n \"~class\": \"class\",\n \"schema\": {\n \"_id\": { \"name\": \"_id\", \"type\": \"string\", \"config\": { \"primaryKey\": true, \"mandatory\": true } },\n \"name\": { \"name\": \"name\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"description\": { \"name\": \"description\", \"type\": \"string\", \"config\": { \"isArray\": false } },\n \"type\": {\n \"name\": \"type\",\n \"type\": \"enum\",\n \"config\": { \"mandatory\": true, \"values\": [{ value: \"system\" }, { value: \"user\" }] }\n },\n \"workerPlatform\": {\n \"name\": \"workerPlatform\",\n \"type\": \"enum\",\n \"config\": { \"mandatory\": true, \"values\": [{ value: \"client\" }, { value: \"server\" }, { value: \"hybrid\" }] }\n },\n \"content\": { \"name\": \"content\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"hash\": { \"name\": \"hash\", \"type\": \"string\", \"config\": { \"mandatory\": true } },\n \"schedule\": { \"name\": \"schedule\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"isSingleton\": { \"name\": \"isSingleton\", \"type\": \"boolean\", \"config\": { \"defaultValue\": false } },\n \"isEnabled\": { \"name\": \"isEnabled\", \"type\": \"boolean\", \"config\": { \"mandatory\": true, \"defaultValue\": true } },\n \"nextRunTimestamp\": { \"name\": \"nextRunTimestamp\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"defaultParams\": { \"name\": \"defaultParams\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"metadata\": { \"name\": \"metadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } }\n }\n },\n {\n \"_id\": \"~JobRun\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"JobRun\",\n \"description\": \"Execution history for jobs\",\n \"~class\": \"class\",\n \"schema\": {\n \"_id\": { \"name\": \"_id\", \"type\": \"string\", \"config\": { \"primaryKey\": true, \"mandatory\": true } },\n \"~class\": { \"name\": \"~class\", \"type\": \"string\", \"config\": { \"mandatory\": true, \"defaultValue\": \"~JobRun\" } },\n \"jobId\": { \"name\": \"jobId\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": true, \"targetClass\": \"~Job\" } },\n \"status\": {\n \"name\": \"status\",\n \"type\": \"enum\",\n \"config\": {\n \"mandatory\": true,\n \"values\": [\n { value: \"PENDING\" },\n { value: \"RUNNING\" },\n { value: \"SUCCESS\" },\n { value: \"FAILURE\" },\n { value: \"CANCELED\" },\n { value: \"SKIPPED\" }\n ]\n }\n },\n \"triggerType\": {\n \"name\": \"triggerType\",\n \"type\": \"enum\",\n \"config\": { \"mandatory\": true, \"values\": [{ value: \"manual\" }, { value: \"scheduled\" }, { value: \"event\" }] }\n },\n \"startTime\": { \"name\": \"startTime\", \"type\": \"integer\", \"config\": { \"mandatory\": true } },\n \"endTime\": { \"name\": \"endTime\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"durationMs\": { \"name\": \"durationMs\", \"type\": \"integer\", \"config\": { \"mandatory\": false } },\n \"runtimeArgs\": { \"name\": \"runtimeArgs\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"initialMetadata\": { \"name\": \"initialMetadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"finalMetadata\": { \"name\": \"finalMetadata\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"errorMessage\": { \"name\": \"errorMessage\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"errorStack\": { \"name\": \"errorStack\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"logs\": { \"name\": \"logs\", \"type\": \"object\", \"config\": { \"mandatory\": false } },\n \"workerId\": { \"name\": \"workerId\", \"type\": \"string\", \"config\": { \"mandatory\": false } }\n }\n },\n {\n \"_id\": \"~Policy\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"Policy\",\n \"description\": \"Access policies for classes and documents\",\n \"~class\": \"class\",\n \"schema\": {\n \"userId\": { \"name\": \"userId\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": false, \"targetClass\": \"~User\" } },\n \"rule\": { \"name\": \"rule\", \"type\": \"string\", \"config\": { \"mandatory\": true, \"maxLength\": 2000 } },\n \"description\": { \"name\": \"description\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"targetClass\": { \"name\": \"targetClass\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": true, \"isArray\": true, \"targetClass\": \"class\" } }\n }\n },\n {\n \"_id\": \"system\",\n \"~class\": \"~User\",\n \"active\": true,\n \"username\": \"system\",\n \"password\": \"system\",\n \"email\": \"\",\n \"firstName\": \"System\",\n \"lastName\": \"User\",\n \"authMethod\": \"AuthMod-Classic\",\n \"externalId\": \"\",\n \"keyDerivationSalt\": \"system-salt\"\n }\n ]\n};\n\nconst sys_008: Patch = {\n \"_id\": \"~sys-0.0.8\",\n \"~class\": \"patch\",\n \"version\": \"0.0.8\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.8\\\\n#### Updates: support wrapped document keys and encrypted user secrets\",\n \"docs\": [\n {\n \"_id\": \"~User\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false,\n \"encrypted\": true\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"authMethod\": {\n \"name\": \"authMethod\",\n \"type\": \"foreign_key\",\n \"config\": { \"mandatory\": true, \"targetClass\": \"~AuthModule\" }\n },\n \"externalId\": {\n \"name\": \"externalId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"keyDerivationSalt\": {\n \"name\": \"keyDerivationSalt\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"wrappedDocumentKey\": {\n \"name\": \"wrappedDocumentKey\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": false,\n \"maxLength\": 4096,\n \"isArray\": false,\n \"encrypted\": false\n }\n }\n }\n },\n {\n \"_id\": \"system\",\n \"_rev\": \"auto\",\n \"~class\": \"~User\",\n \"active\": true,\n \"username\": \"system\",\n \"password\": \"system\",\n \"email\": \"\",\n \"firstName\": \"System\",\n \"lastName\": \"User\",\n \"authMethod\": \"AuthMod-Classic\",\n \"externalId\": \"\",\n \"keyDerivationSalt\": \"system-salt\",\n \"wrappedDocumentKey\": \"\"\n }\n ]\n};\n\nconst sys_009: Patch = {\n \"_id\": \"~sys-0.0.9\",\n \"~class\": \"patch\",\n\n \"version\": \"0.0.9\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.9\\\\n#### Updates: restrict ~User access to the owner and system user\",\n \"docs\": [\n {\n \"_id\": \"Policy-System-Classes\",\n \"_rev\": \"auto\",\n \"~class\": \"~Policy\",\n \"active\": true,\n \"userId\": \"system\",\n \"rule\": \"return true;\",\n \"description\": \"Default system policy\",\n \"targetClass\": [\"class\", \"~UserSession\", \"~Policy\", \"~Job\", \"~JobRun\", \"~AuthModule\"]\n },\n {\n \"_id\": \"Policy-User-SelfAccess\",\n \"~class\": \"~Policy\",\n \"active\": true,\n \"rule\": \"if (!session || session.sessionStatus !== 'active') return false; if (session.username === 'system') return true; const targetUsername = document?.username || document?._id; return targetUsername === session.username;\",\n \"description\": \"Allow users to access only their own user document or the system user\",\n \"targetClass\": [\"~User\"]\n }\n ]\n};\n\nconst sys_010: Patch = {\n \"_id\": \"~sys-0.0.10\",\n \"~class\": \"patch\",\n \"version\": \"0.0.10\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.10\\\\n#### Updates: enforce ~UserSession references an existing ~User via userId\",\n \"docs\": [\n {\n \"_id\": \"~UserSession\",\n \"_rev\": \"auto\",\n \"name\": \"UserSession\",\n \"active\": true,\n \"description\": \"Tracks user sessions\",\n \"~class\": \"class\",\n \"schema\": {\n \"userId\": {\n \"name\": \"userId\",\n \"type\": \"foreign_key\",\n \"config\": {\n \"mandatory\": true,\n \"targetClass\": \"~User\",\n \"isArray\": false\n }\n },\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false,\n \"primaryKey\": true,\n \"mandatory\": true\n }\n },\n \"sessionId\": {\n \"name\": \"sessionId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"primaryKey\": true,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStart\": {\n \"name\": \"sessionStart\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStatus\": {\n \"name\": \"sessionStatus\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionEnd\": {\n \"name\": \"sessionEnd\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": false\n }\n }\n }\n }\n ]\n};\n\nsyspatches.push(sys_001, /* sys_002 ,*/ sys_003, sys_004, sys_005, sys_006, sys_007, sys_008, sys_009, sys_010);\n\nconst sys_011: Patch = {\n \"_id\": \"~sys-0.0.11\",\n \"~class\": \"patch\",\n \"version\": \"0.0.11\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.11\\\\n#### New Class: ~Group\",\n \"docs\": [\n {\n \"_id\": \"~Group\",\n \"active\": true,\n \"name\": \"Group\",\n \"description\": \"Represents a user group\",\n \"~class\": \"class\",\n \"schema\": {\n \"name\": { \"name\": \"name\", \"type\": \"string\", \"config\": { \"primaryKey\": true, \"mandatory\": true, \"maxLength\": 100, \"isArray\": false } }\n }\n }\n ]\n};\n\nconst sys_012: Patch = {\n \"_id\": \"~sys-0.0.12\",\n \"~class\": \"patch\",\n \"version\": \"0.0.12\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.12\\\\n#### Updates: introduce groups, optional policy principals, and group-aware sessions\",\n \"docs\": [\n {\n \"_id\": \"~User\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false,\n \"encrypted\": true\n }\n },\n \"groupId\": {\n \"name\": \"groupId\",\n \"type\": \"foreign_key\",\n \"config\": {\n \"mandatory\": true,\n \"isArray\": true,\n \"targetClass\": \"~Group\"\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"authMethod\": {\n \"name\": \"authMethod\",\n \"type\": \"foreign_key\",\n \"config\": { \"mandatory\": true, \"targetClass\": \"~AuthModule\" }\n },\n \"externalId\": {\n \"name\": \"externalId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"keyDerivationSalt\": {\n \"name\": \"keyDerivationSalt\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": true,\n \"maxLength\": 200,\n \"isArray\": false\n }\n },\n \"wrappedDocumentKey\": {\n \"name\": \"wrappedDocumentKey\",\n \"type\": \"string\",\n \"config\": {\n \"mandatory\": false,\n \"maxLength\": 4096,\n \"isArray\": false,\n \"encrypted\": false\n }\n }\n }\n },\n {\n \"_id\": \"~UserSession\",\n \"_rev\": \"auto\",\n \"name\": \"UserSession\",\n \"active\": true,\n \"description\": \"Tracks user sessions\",\n \"~class\": \"class\",\n \"schema\": {\n \"userId\": {\n \"name\": \"userId\",\n \"type\": \"foreign_key\",\n \"config\": {\n \"mandatory\": true,\n \"targetClass\": \"~User\",\n \"isArray\": false\n }\n },\n \"groupId\": {\n \"name\": \"groupId\",\n \"type\": \"foreign_key\",\n \"config\": {\n \"mandatory\": true,\n \"targetClass\": \"~Group\",\n \"isArray\": true\n }\n },\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false,\n \"primaryKey\": true,\n \"mandatory\": true\n }\n },\n \"sessionId\": {\n \"name\": \"sessionId\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 200,\n \"primaryKey\": true,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStart\": {\n \"name\": \"sessionStart\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionStatus\": {\n \"name\": \"sessionStatus\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": true\n }\n },\n \"sessionEnd\": {\n \"name\": \"sessionEnd\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 100,\n \"isArray\": false,\n \"mandatory\": false\n }\n }\n }\n },\n {\n \"_id\": \"~Policy\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"Policy\",\n \"description\": \"Access policies for classes and documents\",\n \"~class\": \"class\",\n \"schema\": {\n \"userId\": { \"name\": \"userId\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": false, \"targetClass\": \"~User\" } },\n \"groupId\": { \"name\": \"groupId\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": false, \"targetClass\": \"~Group\" } },\n \"rule\": { \"name\": \"rule\", \"type\": \"string\", \"config\": { \"mandatory\": true, \"maxLength\": 2000 } },\n \"description\": { \"name\": \"description\", \"type\": \"string\", \"config\": { \"mandatory\": false } },\n \"targetClass\": { \"name\": \"targetClass\", \"type\": \"foreign_key\", \"config\": { \"mandatory\": true, \"isArray\": true, \"targetClass\": \"class\" } }\n }\n }\n ]\n};\n\nconst sys_013: Patch = {\n \"_id\": \"~sys-0.0.13\",\n \"~class\": \"patch\",\n \"version\": \"0.0.13\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.13\\\\n#### New Documents: Group-Admin, Group-Default\\\\n#### Updates: ~User with after trigger for wrappedDocumentKey\",\n \"docs\": [\n {\n \"_id\": \"Group-Admin\",\n \"~class\": \"~Group\",\n \"active\": true,\n \"name\": \"Admin\"\n },\n {\n \"_id\": \"Group-Default\",\n \"~class\": \"~Group\",\n \"active\": true,\n \"name\": \"Default\"\n }\n ,\n {\n \"_id\": \"~User\",\n \"_rev\": \"auto\",\n \"active\": true,\n \"name\": \"User\",\n \"description\": \"A user class for secure login\",\n \"~class\": \"class\",\n \"triggers\": [\n {\n \"name\": \"ensure-salt\",\n \"order\": \"before\",\n \"run\": `if (!document.keyDerivationSalt) {\n const salt = stack.cryptoEngine.generateRandomString(32);\n document.keyDerivationSalt = salt;\n }\n return document;`\n },\n {\n \"name\": \"auto-wrap-document-key\",\n \"order\": \"before\",\n \"run\": `if (document.password && document.keyDerivationSalt && stack.cryptoEngine.getDocumentKey()) {\n let shouldRecalculate = true;\n if (document._id) {\n try {\n const currentDoc = await stack.db.get(document._id);\n if (currentDoc && currentDoc.password === document.password && currentDoc.keyDerivationSalt === document.keyDerivationSalt && currentDoc.wrappedDocumentKey) {\n shouldRecalculate = false;\n if (!document.wrappedDocumentKey) {\n document.wrappedDocumentKey = currentDoc.wrappedDocumentKey;\n }\n }\n } catch (e) { }\n }\n if (shouldRecalculate) {\n const authModuleId = document.authMethod || \"AuthMod-Classic\";\n const authModule = await stack.db.get(authModuleId);\n const jobId = authModule.jobId;\n const run = await stack.jobEngine.executeJob(jobId, {\n password: document.password,\n salt: document.keyDerivationSalt,\n keyDerivationSalt: document.keyDerivationSalt,\n });\n const derivedKey = (run.finalMetadata)?.derivedKey ?? (run.initialMetadata)?.derivedKey;\n const wrappedKey = await stack.cryptoEngine.wrapDocumentKey(stack.cryptoEngine.getDocumentKey(), derivedKey);\n document.wrappedDocumentKey = wrappedKey;\n }\n }\n return document;`\n }\n ],\n \"schema\": {\n \"username\": {\n \"name\": \"username\",\n \"type\": \"string\",\n \"config\": {\n \"primaryKey\": true,\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false\n }\n },\n \"password\": {\n \"name\": \"password\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"mandatory\": true,\n \"isArray\": false,\n \"encrypted\": true\n }\n },\n \"groupId\": {\n \"name\": \"groupId\",\n \"type\": \"foreign_key\",\n \"config\": {\n \"mandatory\": true,\n \"isArray\": true,\n \"targetClass\": \"~Group\"\n }\n },\n \"email\": {\n \"name\": \"email\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"firstName\": {\n \"name\": \"firstName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"lastName\": {\n \"name\": \"lastName\",\n \"type\": \"string\",\n \"config\": {\n \"maxLength\": 50,\n \"isArray\": false\n }\n },\n \"authMethod\": {\n \"name\": \"authMethod\",\n \"type\": \"foreign_key\",\n \"config\": { \"mandatory\": true, \"targetClass\": \"~AuthModule\" }\n },\n \"externalId\": {\n \"name\": \"externalId\",\n \"type\": \"string\",\n \"config\": { \"maxLength\": 200, \"isArray\": false }\n },\n \"keyDerivationSalt\": {\n \"name\": \"keyDerivationSalt\",\n \"type\": \"string\",\n \"config\": { \"mandatory\": true, \"maxLength\": 200, \"isArray\": false }\n },\n \"wrappedDocumentKey\": {\n \"name\": \"wrappedDocumentKey\",\n \"type\": \"string\",\n \"config\": { \"mandatory\": false, \"maxLength\": 4096, \"isArray\": false, \"encrypted\": false }\n }\n }\n }\n ]\n};\n\nconst sys_014: Patch = {\n \"_id\": \"~sys-0.0.14\",\n \"~class\": \"patch\",\n \"version\": \"0.0.14\",\n \"target\": \"system\",\n \"changelog\": \"### Schema Patch: v0.0.14\\\\n#### New Documents: Policy-Admin, Policy-User-SelfAccess\\\\n#### Updates: system user with groupId\",\n \"docs\": [\n {\n \"_id\": \"system\",\n \"_rev\": \"auto\",\n \"~class\": \"~User\",\n \"active\": true,\n \"username\": \"system\",\n \"password\": \"system\",\n \"groupId\": [\"Group-Admin\"],\n \"email\": \"\",\n \"firstName\": \"System\",\n \"lastName\": \"User\",\n \"authMethod\": \"AuthMod-Classic\",\n \"externalId\": \"\",\n },\n {\n \"_id\": \"Policy-Admin\",\n \"~class\": \"~Policy\",\n \"active\": true,\n \"groupId\": \"Group-Admin\",\n \"rule\": \"return true;\",\n \"description\": \"Default admin policy\",\n \"targetClass\": [\"class\", \"~UserSession\", \"~Policy\", \"~Job\", \"~JobRun\", \"~AuthModule\", \"~Group\"]\n },\n {\n \"_id\": \"Policy-User-SelfAccess\",\n \"_rev\": \"auto\",\n \"~class\": \"~Policy\",\n \"active\": true,\n \"rule\": \"if (!session || session.sessionStatus !== 'active') return false; if (session.username === 'system') return true; const targetUsername = document?.username || document?._id; return targetUsername === session.username;\",\n \"description\": \"Allow users to access only their own user document or the system user\",\n \"targetClass\": [\"~User\"]\n }\n ]\n};\n\nsyspatches.push(sys_011, sys_012, sys_013, sys_014);\n\nexport async function getSystemPatches(currentVersion: string) {\n const classicAuthJobHash = await hashContent(classicAuthJobContent);\n const jobAuthClassic = sys_005.docs.find(d => d._id === 'Job-Auth-Classic');\n if (jobAuthClassic) {\n (jobAuthClassic as any).hash = classicAuthJobHash;\n }\n\n return syspatches\n .sort((a, b) => semver.compare(a.version, b.version))\n .filter((patch) => semver.gt(patch.version, currentVersion))\n}\n\nexport async function getAllSystemPatches() {\n const classicAuthJobHash = await hashContent(classicAuthJobContent);\n const jobAuthClassic = sys_005.docs.find(d => d._id === 'Job-Auth-Classic');\n if (jobAuthClassic) { (jobAuthClassic as any).hash = classicAuthJobHash; }\n return syspatches.sort((a, b) => semver.compare(a.version, b.version));\n}","import { AttributeModel, Document } from \"@docstack/shared\";\nimport Attribute from \"../core/attribute\";\nimport Class from \"../core/class\";\nimport * as jsondiff from 'jsondiffpatch';\nimport createLogger from \"./logger/index\";\n\nconst attributeEffect = async (\n operation: \"delete\" | \"add\" | \"change\",\n model: AttributeModel,\n classObj: Class,\n doc: Document\n) => {\n const attribute = new Attribute(\n null, model.name, model.type, \n model.description, model.config\n );\n if (operation === \"add\") {\n doc = {...doc, ...attribute.getEmpty()};\n }\n\n if (operation === \"delete\") {\n delete doc[attribute.name];\n } else { // when addition or change also perform validation\n const res = await attribute.validate(doc[attribute.name]);\n if (!res) throw new Error(`Attribute '${classObj.name}.${attribute.name}' ${operation} fails for current document because of its validation`);\n }\n\n \n if (attribute.isPrimaryKey()) {\n const result = classObj.bulkUniqueCheck(classObj.getPrimaryKeys());\n if (!result) {\n throw new Error(`With attribute '${attribute.name}' ${operation} of class '${classObj.name}', docs fail primary keys check.`);\n }\n }\n if (operation !== \"delete\" && attribute.isMandatory() && doc[attribute.name] == undefined) {\n throw new Error(`Attribute '${classObj.name}.${attribute.name}' is mandatory but has no value.`);\n } \n return doc;\n}\n\nexport const applySchemaDelta = async (\n doc: Document, \n schemaDelta: jsondiff.AddedDelta | jsondiff.ModifiedDelta | jsondiff.DeletedDelta | jsondiff.ObjectDelta | jsondiff.ArrayDelta | jsondiff.MovedDelta | jsondiff.TextDiffDelta, \n classObj: Class): Promise<Document> => {\n const fnLogger = createLogger().child({method: \"applySchemaDelta\"});\n let updatedDoc = {...doc};\n\n const t = Object.entries(schemaDelta);\n for (const e of t) {\n fnLogger.debug(`Delta of attribute '${e[0]}'`);\n if (Array.isArray(e[1])) {\n // e[1] can represent an addition, a deletion or an edit\n // it's an addition when the array has only one element\n if (e[1].length === 1) {\n const attrModel = e[1][0] as AttributeModel;\n updatedDoc = await attributeEffect(\"add\", attrModel, classObj, updatedDoc);\n }\n // it's an edit when it has 2 elements\n if (e[1].length === 1) {\n const attrModel = e[1][0] as AttributeModel;\n updatedDoc = await attributeEffect(\"change\", attrModel, classObj, updatedDoc);\n }\n\n // it's a removal when it has 3 elements\n if (e[1].length === 3) {\n const attrModel = e[1][0] as AttributeModel;\n updatedDoc = await attributeEffect(\"delete\", attrModel, classObj, updatedDoc);\n }\n return updatedDoc;\n } else {\n // TODO: The change is nested within the attribute model\n }\n }\n\n return updatedDoc;\n}","import { isClassModel, isDocument, isRelation, isPatch, Domain } from \"@docstack/shared\";\nimport type { AttributeTypeReference, ClassModel, Document, DomainRelationParams, StackPluginType } from \"@docstack/shared\";\n// import Stack from \"../utils/stack\";\nimport Stack from \"../core/stack\"\nimport PouchDB from \"pouchdb-browser\";\nimport { Trigger } from \"../core/trigger/index\";\nimport createLogger from \"../utils/logger/index\";\nimport {diff} from 'jsondiffpatch';\nimport { applySchemaDelta } from \"../utils/index\";\nimport Class from \"../core/class\";\n\nconst logger = createLogger().child({ module: \"pouchdb\" });\n/**\n * Plugin Factory method that returns a PouchDB plugin object\n * which performs on documents (before) triggers and validation against\n * their class schema \n * @param stack \n * @returns \n */\nexport const StackPlugin: StackPluginType = (pouch: PouchDB.Static, stack: Stack) => {\n const pouchBulkDocs = PouchDB.prototype.bulkDocs;\n const pouchGet = PouchDB.prototype.get;\n const pouchPut = PouchDB.prototype.put;\n return {\n bulkDocs: async function (docs, options: PouchDB.Core.BulkDocsOptions & {\n isPostOp?: boolean\n } | null, callback) {\n const fnLogger = logger.child({ method: \"bulkDocs\" });\n if (typeof options == 'function') {\n callback = options\n options = {}\n }\n\n\n let documentsToProcess: typeof docs;\n if (Array.isArray(docs)) {\n documentsToProcess = docs;\n } else {\n documentsToProcess = (docs as any).docs;\n }\n\n const relationQueue: { domain: Domain; params: DomainRelationParams; }[] = [];\n\n const flushRelationQueue = async () => {\n if (!relationQueue.length) return;\n const grouped = new Map<string, { domain: Domain; drafts: { docId: string | null; params: DomainRelationParams; }[] }>();\n while (relationQueue.length) {\n const entry = relationQueue.shift();\n if (!entry) continue;\n const key = entry.domain.name;\n if (!grouped.has(key)) {\n grouped.set(key, { domain: entry.domain, drafts: [] });\n }\n grouped.get(key)!.drafts.push({ docId: null, params: entry.params });\n }\n for (const { domain, drafts } of grouped.values()) {\n await stack.createRelationDocs(drafts, domain.name, domain);\n }\n };\n\n const triggerQueue: Record<string, Trigger[]> = Object.create(null);\n const classCache = new Map<string, Class>();\n\n const postOperations = async (\n error: PouchDB.Core.Error | null,\n result: (PouchDB.Core.Error | PouchDB.Core.Response)[] | null\n ) => {\n if (error) {\n return { error, result }\n } else if (result) {\n const docs: Document[] = []\n for (const docRes of result) {\n if (docRes.id) {\n // const doc = await stack.db.get(docRes.id, { rev: (docRes as any).rev }) as Document;\n const doc = documentsToProcess.find(d => d._id === docRes.id) as unknown as Document | undefined;\n if (doc) {\n const updatedRev = (docRes as any).rev;\n if (updatedRev) {\n doc._rev = updatedRev;\n }\n const afterTriggers = triggerQueue[docRes.id]\n if (afterTriggers && afterTriggers.length) {\n for (const afterTrigger of afterTriggers) {\n const updatedDoc = await afterTrigger.execute(doc);\n Object.assign(doc, updatedDoc);\n }\n docs.push(doc);\n }\n }\n }\n }\n if (docs.length) {\n const recurse: Promise<{\n error: PouchDB.Core.Error | null,\n result: (PouchDB.Core.Error | PouchDB.Core.Response)[] | null\n }> = new Promise((resolve, reject) => {\n (this.bulkDocs as any).apply(this, [docs, {\n isPostOp: true\n }, (rErr: typeof error, rRes: typeof result) => resolve({\n error: rErr,\n result: rRes\n })])\n })\n const { error: rErr, result: rRes } = await recurse;\n await flushRelationQueue();\n return { error: rErr, result: rRes }\n }\n }\n await flushRelationQueue();\n return { error, result }\n }\n\n const postExec = async (error, result) => {\n if (!options?.isPostOp) {\n const { error: err, result: res } = await postOperations(error, result);\n if (callback) callback(err, res);\n } else if (callback) {\n callback(error, result);\n }\n }\n\n // TODO: use promise.all for concurrency\n for (const doc of documentsToProcess) {\n if (isClassModel(doc)) {\n // Validate against parent class\n if (doc[\"~class\"] !== \"~self\") {\n const parentClass = await stack.getClass(doc[\"~class\"]);\n if (parentClass) {\n fnLogger.info(\"Validating class model against parent class\", { doc, parentClass: parentClass.name });\n const validationResult = await parentClass.validate(doc);\n if (!validationResult) {\n fnLogger.error(\"Class model is not valid for its parent class\", { doc, parentClass: parentClass.name });\n throw new Error(`Discarded class model because model not valid for its parent class '${parentClass.name}' schema`);\n }\n } else {\n fnLogger.error(\"Parent class not found\", { doc });\n throw new Error(`Parent class '${doc[\"~class\"]}' not found for class model '${doc._id}'`);\n }\n } else {\n // TODO: Consider validating against self after registering the class?\n console.log(\"Class model is of type '~self', skipping parent class validation\", { doc });\n }\n\n fnLogger.info(\"Document is class model, following update propagation procedure.\");\n // When a class document is updated, its change must have an effect on its children\n const classDocId = doc._id;\n const className = typeof doc.name === \"string\" ? doc.name : classDocId;\n try {\n // Get the previous version of the class model\n const docWithRevs = await stack.db.get(classDocId, { revs: true });\n const revisionIDList = docWithRevs._revisions!.ids;\n if (revisionIDList.length == 1) {\n fnLogger.info(`Class '${className}' (doc '${classDocId}') was just created. Nothing to do.`);\n continue;\n return pouchBulkDocs.call(this, docs, options, postExec);\n }\n } catch (e: any) {\n if (e.name === 'not_found') {\n fnLogger.info(`Class '${className}' (doc '${classDocId}') was just created. Nothing to do.`);\n continue;\n return pouchBulkDocs.call(this, docs, options, postExec);\n }\n }\n // Fetch the current (next old) version of the class document.\n const previousClassDoc = await stack.db.get<ClassModel>(classDocId);\n const classObj = await Class.buildFromModel(stack, previousClassDoc);\n // const classObj = await stack.getClass(className, true);\n // if (classObj == null) {\n // throw new Error(`Unexpected, can't retrieve class '${className}' (doc '${classDocId}')`);\n // }\n // const previousClassDoc = classObj.model;\n fnLogger.info(\"Retrieved documents\", { doc, previousClassDoc });\n const schemaDelta = diff(previousClassDoc.schema, doc.schema);\n\n if (!schemaDelta) {\n fnLogger.info(`Class '${className}' has no changes on schema.`);\n continue;\n return pouchBulkDocs.call(this, docs, options, postExec);\n }\n\n const documents = await classObj.getCards();\n\n if (documents.length === 0) {\n fnLogger.info(`No documents found for class '${className}' after its update.`);\n continue;\n return pouchBulkDocs.call(this, docs, options, postExec);\n }\n\n const updates = await Promise.all(documents.map(async doc => {\n const updatedDoc = await applySchemaDelta(doc, schemaDelta, classObj);\n return updatedDoc;\n }));\n\n const result = await stack.db.bulkDocs(updates);\n fnLogger.info('Propagated updates');\n } else if (isRelation(doc)) {\n const domain = await stack.getDomain(doc[\"~domain\"]);\n if (!domain) {\n throw new Error(`Domain not found: ${doc[\"~domain\"]}`);\n }\n if (doc.sourceClass !== domain.sourceClass.id || doc.targetClass !== domain.targetClass.id) {\n throw new Error(`Relation document classes do not match domain '${domain.name}'.`);\n }\n\n const [sourceDoc, targetDoc] = await Promise.all([\n stack.db.get<Document>(doc.sourceId).catch(() => null),\n stack.db.get<Document>(doc.targetId).catch(() => null),\n ]);\n\n if (!sourceDoc) {\n throw new Error(`Source document '${doc.sourceId}' does not exist for domain '${domain.name}'.`);\n }\n\n if (!targetDoc) {\n throw new Error(`Target document '${doc.targetId}' does not exist for domain '${domain.name}'.`);\n }\n\n continue;\n } else if (isPatch(doc)) {\n // Patches are not validated or processed, just stored\n continue;\n } else if (isDocument(doc)) {\n const className = doc[\"~class\"];\n\n try {\n let classObj: Class | null;\n try {\n classObj = classCache.get(className) || await stack.getClass(className, true);\n } catch (error) {\n throw new Error(`Class '${className}' not found for document '${doc._id}'.`);\n }\n\n if (!classObj) {\n throw new Error(`Class '${className}' not found for document '${doc._id}'.`);\n }\n\n classCache.set(className, classObj);\n const encryptableAttributes = classObj.getEncryptedAttributes();\n if (stack.cryptoEngine.isEnabled() && encryptableAttributes.length) {\n await stack.cryptoEngine.decryptDocument(doc as Document, classObj);\n }\n\n const relationalAttrs = Object.values(classObj.getAttributes()).filter(a => {\n if (classObj.getName().startsWith(\"Account-\")) {\n // console.log(\"Checking attribute for relation\", { class: classObj.getName(), attr: a.name, type: a.model.type })\n }\n return a.model.type === \"reference\"\n });\n for (const attr of relationalAttrs) {\n const relationValue = doc[attr.name];\n if (!relationValue) continue;\n const domainId = (attr.model.config as AttributeTypeReference[\"config\"]).domain;\n const domain = await stack.getDomain(domainId);\n if (!domain) throw new Error(`Domain not found: ${domainId}`);\n\n // Validate relation constraint\n const validation = await domain.validateRelation(doc, relationValue);\n if (!validation.exists) {\n // console.log(\"Queuing relation creation for doc\", {docId: doc._id, domain: domain.name, params: validation.params})\n relationQueue.push({\n domain,\n params: validation.params,\n });\n }\n }\n // TODO: skip execution of before triggers if option.isPostOp\n const beforeTriggers = classObj.triggers.filter(t => t.order === \"before\");\n const afterTriggers = classObj.triggers.filter(t => t.order === \"after\");\n\n for (const trigger of beforeTriggers) {\n const updatedDoc = await trigger.execute(doc);\n Object.assign(doc, updatedDoc); // Merge changes back.\n }\n\n triggerQueue[doc._id] = [\n ...(triggerQueue[doc._id] || []),\n ...afterTriggers\n ];\n\n // Perform validation using the schema.\n const validationResult = await classObj.validate(doc);\n if (!validationResult) {\n fnLogger.error(\"Validation failed for document\", { id: doc._id, className, doc });\n throw new Error(`Discarded document ${JSON.stringify(doc)} because object not valid for its Class schema: ${JSON.stringify(classObj.buildSchema())}`);\n }\n } catch (error) {\n return Promise.reject(error);\n }\n }\n }\n\n if (!stack.cryptoEngine.isEnabled()) {\n console.log(\"Crypto engine not enabled, skipping encryption.\");\n return await new Promise<(PouchDB.Core.Error | PouchDB.Core.Response)[]>((resolve, reject) => {\n pouchBulkDocs.call(this, payload as any, options, async (err, res) => {\n if (err) {\n reject(err);\n } else {\n await postExec(null, res).then(() => {\n resolve(res);\n }).catch(reject);\n }\n })\n });\n } else {\n console.log(\"Crypto engine enabled, processing encryption.\");\n }\n\n const originalDocs = Array.isArray(docs) ? documentsToProcess : (docs as any).docs;\n const encryptedDocs = await Promise.all((originalDocs || []).map(async (doc) => {\n if (isDocument(doc)) {\n const className = doc[\"~class\"];\n const classObj = classCache.get(className) || await stack.getClass(className, true);\n if (classObj) {\n const encryptableAttributes = classObj.getEncryptedAttributes();\n if (!stack.cryptoEngine.isEnabled() || !encryptableAttributes.length) {\n return doc;\n }\n classCache.set(className, classObj);\n const clone = { ...doc } as Document;\n await stack.cryptoEngine.encryptDocument(clone, classObj);\n return clone;\n }\n }\n return doc;\n }));\n\n const payload = Array.isArray(docs)\n ? encryptedDocs\n : { ...(docs as any), docs: encryptedDocs };\n\n return await new Promise<(PouchDB.Core.Error | PouchDB.Core.Response)[]>((resolve, reject) => {\n pouchBulkDocs.call(this, payload as any, options, async (err, res) => {\n if (err) {\n reject(err);\n } else {\n await postExec(null, res).then(() => {\n resolve(res);\n }).catch(reject);\n }\n })\n });\n },\n\n get: async function (docId, options?: PouchDB.Core.GetOptions | null, callback?) {\n if (typeof options === \"function\") {\n callback = options;\n options = undefined;\n }\n\n const exec = async () => {\n const result = await pouchGet.call(this, docId, options ?? {});\n if (result && isDocument(result) && stack.cryptoEngine.isEnabled()) {\n const classObj = await stack.getClass(result[\"~class\"], true).catch(() => null);\n if (classObj && classObj.getEncryptedAttributes().length) {\n await stack.cryptoEngine.decryptDocument(result as Document, classObj);\n }\n }\n return result;\n };\n\n if (callback) {\n exec().then((res) => callback(null, res)).catch((err) => callback(err, undefined));\n return;\n }\n return exec();\n },\n /*\n put: async function (doc, options?: PouchDB.Core.PutOptions | null, callback?) {\n if (typeof options === \"function\") {\n callback = options;\n options = undefined;\n }\n const exec = async () => {\n let payload = doc as any;\n if (isDocument(doc) && stack.cryptoEngine.isEnabled()) {\n const classObj = await stack.getClass(doc[\"~class\"], true).catch(() => null);\n if (classObj && classObj.getEncryptedAttributes().length) {\n payload = { ...doc } as Document;\n await stack.cryptoEngine.encryptDocument(payload as Document, classObj);\n }\n }\n return pouchPut.call(this, payload, options ?? {});\n };\n\n if (callback) {\n exec().then((res) => callback(null, res)).catch((err) => callback(err));\n return;\n }\n return exec();\n },\n */\n\n };\n};","\n// @ts-nocheck\n// A SQL parser built with a scanner and a registry of pluggable clause handlers.\n// This approach is more robust and extensible than regex-based string splitting.\n\n// ---------- Core AST types ----------\n// These types match the existing AST structure expected by the planner.\nimport { SelectAST, UnionAST } from \"@docstack/shared\";\n\n// ---------- Scanner (cursor) ----------\nclass Scanner {\n constructor(public text: string, public pos = 0) {}\n eof() { return this.pos >= this.text.length; }\n rest() { return this.text.slice(this.pos); }\n\n skipWSAndComments(): void {\n while (!this.eof()) {\n const char = this.peekChar();\n if (/\\s/.test(char)) {\n this.pos++;\n continue;\n }\n if (char === '-' && this.peekChar(1) === '-') {\n while (!this.eof() && this.peekChar() !== '\\n') this.pos++;\n continue;\n }\n break;\n }\n }\n\n peekChar(offset = 0): string {\n const i = this.pos + offset;\n return i < this.text.length ? this.text[i] : '';\n }\n\n peekKW(kw: string): boolean {\n this.skipWSAndComments();\n const len = kw.length;\n if (this.text.substr(this.pos, len).toUpperCase() !== kw.toUpperCase()) return false;\n const next = this.text[this.pos + len] || '';\n // Keyword boundary rule: next char must not be part of an identifier\n if (/[A-Za-z0-9_]/.test(next)) return false;\n return true;\n }\n\n tryKW(kw: string): boolean {\n if (!this.peekKW(kw)) return false;\n this.pos += kw.length;\n return true;\n }\n\n expectKW(kw: string, msg = `Expected '${kw}'`): void {\n if (!this.tryKW(kw)) throw new Error(msg + ` at position ${this.pos}`);\n }\n\n matchRe(re: RegExp): RegExpMatchArray | null {\n this.skipWSAndComments();\n const m = this.rest().match(re);\n if (!m || m.index !== 0) return null;\n return m;\n }\n\n consumeRe(re: RegExp, msg: string): RegExpMatchArray {\n const m = this.matchRe(re);\n if (!m) throw new Error(msg + ` at position ${this.pos}`);\n this.pos += m[0].length;\n return m;\n }\n}\n\n// ---------- Helper parsers ----------\n\nfunction parseIdentifier(scan: Scanner): string {\n scan.skipWSAndComments();\n\n if (scan.peekChar() === '\"') {\n scan.pos++;\n let value = '';\n while (!scan.eof()) {\n const char = scan.peekChar();\n scan.pos++;\n\n if (char === '\"') {\n // Support escaped double quotes by doubling them: \"\".\n if (scan.peekChar() === '\"') {\n value += '\"';\n scan.pos++;\n continue;\n }\n return value;\n }\n\n value += char;\n }\n\n throw new Error('Unterminated quoted identifier');\n }\n\n const match = scan.consumeRe(/^[a-zA-Z_][a-zA-Z0-9_]*/, 'Expected identifier');\n return match[0];\n}\n\nfunction parseColumnExpr(scan: Scanner) {\n scan.skipWSAndComments();\n const char = scan.peekChar();\n if (char === '*') {\n scan.pos++;\n return { type: 'star' };\n }\n if (char === '1') { // Hack for `SELECT 1` in EXISTS\n scan.pos++;\n return { type: 'literal', value: 1 };\n }\n\n const part1 = parseIdentifier(scan);\n scan.skipWSAndComments();\n if (scan.peekChar() === '.') {\n scan.pos++;\n const part2 = parseIdentifier(scan);\n return { type: 'column_ref', table: part1, column: part2 };\n }\n return { type: 'column_ref', table: null, column: part1 };\n}\n\nfunction parseExpression(scan: Scanner): any {\n scan.skipWSAndComments();\n const startPos = scan.pos;\n\n // Check for scalar subquery `(SELECT ...)`\n if (scan.peekChar() === '(') {\n const tempScan = new Scanner(scan.text, scan.pos + 1);\n if (tempScan.peekKW('SELECT')) {\n scan.consumeRe(/^\\s*\\(/, 'Expected (');\n const subqueryAst = parseSingleSelect(scan);\n scan.consumeRe(/^\\s*\\)/, 'Expected )');\n return { type: 'scalar_subquery', ast: subqueryAst };\n }\n }\n\n const identMatch = scan.matchRe(/^[a-zA-Z_][a-zA-Z0-9_]*/);\n if (identMatch) {\n const afterIdentPos = scan.pos + identMatch[0].length;\n const tempScanner = new Scanner(scan.text, afterIdentPos);\n tempScanner.skipWSAndComments();\n if (tempScanner.peekChar() === '(') {\n // Confirmed function call\n const name = identMatch[0].toUpperCase();\n scan.pos = afterIdentPos;\n scan.consumeRe(/^\\s*\\(/, 'Expected (');\n const distinct = scan.tryKW('DISTINCT');\n const argExpr = parseColumnExpr(scan);\n scan.consumeRe(/^\\s*\\)/, 'Expected )');\n return {\n type: 'aggr_func',\n name,\n args: { expr: argExpr, distinct }\n };\n }\n }\n \n scan.pos = startPos;\n return parseColumnExpr(scan);\n}\n\nfunction parsePredicate(scan: Scanner): any {\n scan.skipWSAndComments();\n\n let not = false;\n if (scan.tryKW('NOT')) {\n not = true;\n }\n\n if (scan.tryKW('EXISTS')) {\n scan.consumeRe(/^\\s*\\(/, 'Expected (');\n const subqueryAst = parseSingleSelect(scan);\n scan.consumeRe(/^\\s*\\)/, 'Expected )');\n return { type: 'exists_expr', subquery: subqueryAst, not };\n }\n \n if (not) {\n // \"NOT\" was consumed but it wasn't \"NOT EXISTS\". This could be \"NOT IN\" or a syntax error.\n // We put it back and let the binary expression parser handle it.\n scan.pos -= 3;\n }\n\n const left = parseExpression(scan);\n scan.skipWSAndComments();\n const opMatch = scan.matchRe(/^(>=|<=|>|<|=|IN|NOT\\s+IN)/i);\n if (!opMatch) throw new Error(`Expected binary operator at position ${scan.pos}`);\n \n const operator = opMatch[0].trim().toUpperCase();\n scan.pos += opMatch[0].length;\n\n scan.skipWSAndComments();\n let right;\n if (operator === 'IN' || operator === 'NOT IN') {\n if (scan.peekChar() === '(') {\n scan.consumeRe(/^\\s*\\(/, 'Expected (');\n scan.skipWSAndComments();\n if(scan.peekKW('SELECT')) {\n right = { type: 'subquery', ast: parseSingleSelect(scan) };\n } else {\n throw new Error('Value lists for IN are not supported. Use subquery or array column ref.');\n }\n scan.consumeRe(/^\\s*\\)/, 'Expected )');\n } else {\n // This handles the `a._id IN m.actors` case where actors is a column ref to an array\n right = parseColumnExpr(scan);\n }\n } else {\n const valMatch = scan.matchRe(/^[0-9]+(\\.[0-9]+)?/);\n if (valMatch) {\n scan.pos += valMatch[0].length;\n right = { type: 'param', value: valMatch[0] };\n } else {\n // Handle right side being a column expression\n right = parseExpression(scan);\n }\n }\n\n // A real parser would build a proper expression tree for multiple AND/ORs.\n // For now, we assume a single predicate or predicates joined by AND, which we'll handle by pushing to a list.\n const predicate = { type: 'binary_expr', operator, left, right };\n \n if (scan.tryKW('AND')) {\n return { type: 'and', left: predicate, right: parsePredicate(scan) };\n }\n\n return predicate;\n}\n\nfunction parseSelectItem(scan: Scanner) {\n const expr = parseExpression(scan);\n let alias = null;\n if (scan.tryKW('AS')) {\n alias = parseIdentifier(scan);\n }\n return { expr, as: alias };\n}\n\nfunction parseSingleFrom(scan: Scanner) {\n const table = parseIdentifier(scan);\n scan.skipWSAndComments();\n let alias = null;\n\n if (scan.tryKW('AS')) {\n alias = parseIdentifier(scan);\n } else if (scan.peekChar() === '\"') {\n alias = parseIdentifier(scan);\n } else {\n const aliasMatch = scan.matchRe(/^[a-zA-Z_][a-zA-Z0-9_]*/);\n if (aliasMatch) {\n const tempScanner = new Scanner(scan.text, scan.pos + aliasMatch[0].length);\n const isReservedWord = ['JOIN', 'WHERE', 'GROUP', 'ORDER', 'LIMIT', 'HAVING', 'ON', 'AS'].some(kw => tempScanner.peekKW(kw));\n if (!isReservedWord) {\n scan.pos += aliasMatch[0].length;\n alias = aliasMatch[0];\n }\n }\n }\n return { table, as: alias || table };\n}\n\nfunction parseSingleSelect(scan: Scanner): SelectAST {\n const ast: SelectAST = {\n type: 'select', distinct: false, columns: [], from: [], joins: [],\n where: null, groupBy: null, having: null, orderBy: null, limit: null\n };\n\n const ctx = { scan, ast };\n \n if (!SelectHandler.canStart(ctx)) throw new Error('Expected SELECT in subquery');\n SelectHandler.parse(ctx);\n \n if (FromHandler.canStart(ctx)) FromHandler.parse(ctx);\n else throw new Error('Subquery must have a FROM clause.');\n\n while (JoinHandler.canStart(ctx)) JoinHandler.parse(ctx);\n if (WhereHandler.canStart(ctx)) WhereHandler.parse(ctx);\n if (GroupByHandler.canStart(ctx)) GroupByHandler.parse(ctx);\n if (HavingHandler.canStart(ctx)) HavingHandler.parse(ctx);\n if (OrderByHandler.canStart(ctx)) OrderByHandler.parse(ctx);\n if (LimitHandler.canStart(ctx)) LimitHandler.parse(ctx);\n\n return ast;\n}\n\n\n// ---------- Clause handler interface ----------\ntype ClauseCtx = { \n scan: Scanner;\n ast: SelectAST;\n setAST?: (ast: SelectAST) => void;\n astList?: (SelectAST | UnionAST)[]\n};\ninterface ClauseHandler {\n id: string;\n repeatable?: boolean;\n canStart(ctx: ClauseCtx): boolean;\n parse(ctx: ClauseCtx): void;\n}\n\n// ---------- Registry ----------\nclass ClauseRegistry {\n private handlers: ClauseHandler[] = [];\n register(h: ClauseHandler) { this.handlers.push(h); }\n get(id: string) { return this.handlers.find(h => h.id === id)!; }\n}\n\n// ---------- Concrete handlers ----------\nconst SelectHandler: ClauseHandler = {\n id: 'SELECT',\n canStart: ({ scan }) => scan.peekKW('SELECT'),\n parse: ({ scan, ast }) => {\n scan.expectKW('SELECT');\n if (scan.tryKW('DISTINCT')) {\n ast.distinct = true;\n if (scan.tryKW('ON')) {\n scan.consumeRe(/^\\s*\\(/, 'Expected ( after DISTINCT ON');\n const distinctExprs: any[] = [];\n while (!scan.eof()) {\n distinctExprs.push(parseColumnExpr(scan));\n if (!scan.tryKW(',')) break;\n }\n scan.consumeRe(/^\\s*\\)/, 'Expected ) after DISTINCT ON expressions');\n ast.distinctOn = distinctExprs;\n }\n }\n const cols: any[] = [];\n while (!scan.eof()) {\n scan.skipWSAndComments();\n if (scan.peekKW('FROM')) break;\n cols.push(parseSelectItem(scan));\n if (!scan.tryKW(',')) break;\n }\n ast.columns = cols;\n }\n};\n\nconst FromHandler: ClauseHandler = {\n id: 'FROM',\n canStart: ({ scan }) => scan.peekKW('FROM'),\n parse: ({ scan, ast }) => {\n scan.expectKW('FROM');\n ast.from = [parseSingleFrom(scan)];\n }\n};\n\nconst JoinHandler: ClauseHandler = {\n id: 'JOIN',\n repeatable: true,\n canStart: ({ scan }) => {\n const save = scan.pos;\n scan.skipWSAndComments();\n scan.tryKW('LEFT') || scan.tryKW('RIGHT') || scan.tryKW('INNER');\n const ok = scan.peekKW('JOIN');\n scan.pos = save;\n return ok;\n },\n parse: ({ scan, ast }) => {\n let joinType: 'LEFT' | 'INNER' | 'RIGHT' = 'INNER';\n if (scan.tryKW('LEFT')) joinType = 'LEFT';\n else if (scan.tryKW('RIGHT')) joinType = 'RIGHT';\n else scan.tryKW('INNER');\n scan.expectKW('JOIN');\n const fromPart = parseSingleFrom(scan);\n scan.expectKW('ON');\n const onCondition = parsePredicate(scan);\n ast.joins.push({ type: joinType, table: fromPart.table, as: fromPart.as, on: onCondition });\n }\n};\n\nconst WhereHandler: ClauseHandler = {\n id: 'WHERE',\n canStart: ({ scan }) => scan.peekKW('WHERE'),\n parse: ({ scan, ast }) => {\n scan.expectKW('WHERE');\n ast.where = parsePredicate(scan);\n }\n};\n\nconst GroupByHandler: ClauseHandler = {\n id: 'GROUP BY',\n canStart: ({ scan }) => scan.peekKW('GROUP'),\n parse: ({ scan, ast }) => {\n scan.expectKW('GROUP'); scan.expectKW('BY');\n const cols: any[] = [];\n while (true) {\n cols.push(parseColumnExpr(scan));\n if (!scan.tryKW(',')) break;\n }\n ast.groupBy = { type: 'group_by', columns: cols };\n }\n};\n\nconst HavingHandler: ClauseHandler = {\n id: 'HAVING',\n canStart: ({ scan }) => scan.peekKW('HAVING'),\n parse: ({ scan, ast }) => {\n scan.expectKW('HAVING');\n ast.having = parsePredicate(scan);\n }\n};\n\nconst OrderByHandler: ClauseHandler = {\n id: 'ORDER BY',\n canStart: ({ scan }) => scan.peekKW('ORDER'),\n parse: ({ scan, ast }) => {\n scan.expectKW('ORDER'); scan.expectKW('BY');\n const items: Array<{ expr: any; order: 'ASC' | 'DESC' }> = [];\n while (true) {\n const expr = parseColumnExpr(scan);\n let order: 'ASC' | 'DESC' = 'ASC';\n if (scan.tryKW('DESC')) order = 'DESC';\n else scan.tryKW('ASC');\n items.push({ expr, order });\n if (!scan.tryKW(',')) break;\n }\n ast.orderBy = items;\n }\n};\n\nconst LimitHandler: ClauseHandler = {\n id: 'LIMIT',\n canStart: ({ scan }) => scan.peekKW('LIMIT'),\n parse: ({ scan, ast }) => {\n scan.expectKW('LIMIT');\n const m = scan.consumeRe(/^\\s*\\d+/, 'Expected integer after LIMIT');\n ast.limit = parseInt(m[0], 10);\n }\n};\n\nconst UnionHandler: ClauseHandler = {\n id: 'UNION',\n canStart: ({ scan }) => scan.peekKW('UNION'),\n parse: ({ scan, astList, setAST }) => {\n scan.expectKW('UNION');\n const isAll = scan.tryKW('ALL');\n\n const topIndex = astList.length - 1;\n // The union AST will be at astList.length.\n // The next select AST will be at astList.length + 1.\n const bottomIndex = astList.length + 1;\n\n astList.push({\n type: 'union',\n distinct: !isAll,\n top: topIndex,\n bottom: bottomIndex,\n });\n \n // As requested, reset the main AST object to prepare for the next SELECT statement.\n setAST({\n type: 'select', distinct: false, columns: [], from: [], joins: [],\n where: null, groupBy: null, having: null, orderBy: null, limit: null\n });\n }\n};\n\n// ---------- Driver ----------\nconst registry = new ClauseRegistry();\nregistry.register(SelectHandler);\nregistry.register(FromHandler);\nregistry.register(JoinHandler);\nregistry.register(WhereHandler);\nregistry.register(GroupByHandler);\nregistry.register(HavingHandler);\nregistry.register(OrderByHandler);\nregistry.register(LimitHandler);\nregistry.register(UnionHandler); // Register the union handler\n\nconst SEQUENCE = [\n 'SELECT', 'FROM', 'JOIN*', \n 'WHERE', 'GROUP BY', 'HAVING', 'ORDER BY',\n 'LIMIT',\n] as const;\n\n/**\n * Parses a SQL SELECT statement into an Abstract Syntax Tree (AST).\n * This parser uses a scanner and a sequence of clause handlers to build the AST\n * in a structured and extensible way. It supports UNION and UNION ALL.\n * @param {string} sql The SQL query string to parse.\n * @returns {(SelectAST | UnionAST)[]} List of ASTs representing the query.\n * @throws {Error} If the SQL syntax is invalid or contains unexpected tokens.\n */\nexport function parse(sql: string) {\n let text = sql.replace(/[\\r\\n]+/g, ' ').replace(/\\s+/g, ' ').trim();\n if (text.endsWith(';')) text = text.slice(0, -1);\n const astList: (SelectAST | UnionAST)[] = [];\n const scan = new Scanner(text);\n\n let ast: SelectAST = {\n type: 'select', distinct: false, columns: [], from: [], joins: [],\n where: null, groupBy: null, having: null, orderBy: null, limit: null\n };\n\n const ctx: ClauseCtx = {\n scan,\n get ast() { return ast; },\n setAST: (newAst) => { ast = newAst; },\n astList\n };\n \n // The main driver loop. It repeatedly parses a full SELECT statement\n // and then checks for a UNION operator to continue.\n while (!scan.eof()) {\n scan.skipWSAndComments();\n if (scan.eof()) break;\n\n // Parse one full SELECT statement using the defined sequence of handlers.\n for (const step of SEQUENCE) {\n const repeatable = step.endsWith('*');\n const id = repeatable ? step.slice(0, -1) : step;\n const handler = registry.get(id);\n\n if (repeatable) {\n while (handler.canStart(ctx)) handler.parse(ctx);\n } else {\n if (handler.canStart(ctx)) handler.parse(ctx);\n }\n }\n\n // Validate and store the parsed SELECT AST.\n if (ast.columns.length === 0) {\n if (astList.length > 0) { // After a UNION, a SELECT is mandatory.\n throw new Error('Expected SELECT statement after UNION.');\n }\n // If it's the first statement and it's empty, it might be an empty query string.\n break;\n }\n if (ast.from.length === 0) throw new Error('Invalid SQL: Missing FROM clause.');\n astList.push(ast);\n\n // After a full SELECT statement, check if a UNION follows.\n scan.skipWSAndComments();\n const unionHandler = registry.get('UNION');\n if (unionHandler.canStart(ctx)) {\n // The handler adds the UnionAST and resets the `ast` variable via `setAST`.\n unionHandler.parse(ctx);\n } else {\n // No UNION operator, so the query should be complete.\n break;\n }\n }\n\n scan.skipWSAndComments();\n if (!scan.eof()) {\n throw new Error(`Unexpected token near: \"${scan.rest().slice(0, 40)}\"`);\n }\n\n return astList;\n}","// @ts-nocheck\n\n/**\n * Creates a function that evaluates a predicate AST node against a row.\n * This is useful for filtering operations (e.g., in WHERE or JOIN ON clauses).\n * The returned function is async to handle subqueries.\n * @param {object} astNode The predicate AST node.\n * @param {object} stack The ClientStack instance.\n * @param {function} executePlan The main query execution function.\n * @param {object} outerRow The row from the parent query context.\n * @param {object} outerAliases The aliases from the parent query context.\n * @returns {function(object): Promise<boolean>} An async function that takes a row and returns true if it matches the predicate.\n */\nexport function createRowEvaluator(astNode, stack, executePlan, outerRow, outerAliases) {\n return async (row) => {\n // Determine aliases from the current row context\n const fromAlias = Object.keys(row).find(k => row[k] !== null) || Object.keys(row)[0];\n const joinAliases = Object.keys(row).reduce((acc, key) => {\n if (key !== fromAlias) acc[key] = key; // simplified alias mapping\n return acc;\n }, {});\n // The row being evaluated is the inner context, and we pass the captured outer context.\n return await evalExpression(row, astNode, fromAlias, joinAliases, stack, executePlan, outerRow, outerAliases);\n };\n}\n\n/**\n * Evaluates an AST expression node against a data row. This function is async\n * to handle scalar subqueries which require executing a separate query plan.\n * @param {object} row The data row to evaluate against.\n * @param {object} expr The AST expression node.\n * @param {string} fromAlias The alias for the main FROM table.\n * @param {object} joinAliases A map of aliases for joined tables.\n * @param {object} stack The ClientStack instance for data access.\n * @param {function} executePlan The function to execute sub-plans.\n * @param {object} outerRow The row from the parent query context (for correlation).\n * @param {object} outerAliases The aliases from the parent query context.\n * @returns {Promise<*>} The result of the expression evaluation.\n */\nexport async function evalExpression(row, expr, fromAlias, joinAliases, stack, executePlan, outerRow, outerAliases) {\n if (!expr) return null;\n \n switch (expr.type) {\n case 'scalar_subquery': {\n // Dynamically import planner to avoid circular dependency\n const { createPlan } = await import('./planner');\n const subqueryPlan = createPlan([expr.ast]);\n // Execute the subquery, passing the current row as the outer context for correlation\n const result = await executePlan(stack, subqueryPlan, [], row, null); // Pass outer row, but no aliases\n if (result.length > 0 && result[0] != null) {\n const firstRow = result[0];\n const firstColName = Object.keys(firstRow)[0];\n return firstRow[firstColName];\n }\n return null; // SQL standard: scalar subquery with no rows evaluates to NULL\n }\n\n case 'column_ref': {\n const tableAlias = expr.table || fromAlias;\n const tableData = row[tableAlias];\n\n // 1. Check current row's data for the specified alias\n if (tableData && typeof tableData === 'object' && tableData !== null && tableData.hasOwnProperty(expr.column)) {\n return tableData[expr.column];\n }\n \n // 2. Fallback for simplified structures (e.g., aggregated rows)\n if (row.hasOwnProperty(expr.column)) {\n return row[expr.column];\n }\n\n // 3. Check outer context for correlated subqueries\n if (outerRow) {\n for (const alias in outerRow) {\n const outerTableData = outerRow[alias];\n if (outerTableData && typeof outerTableData === 'object' && outerTableData.hasOwnProperty(expr.column)) {\n // If an explicit table is specified in the expression (e.g., m.actors),\n // it must match the alias in the outer row.\n if (expr.table && expr.table !== alias) {\n continue;\n }\n return outerTableData[expr.column];\n }\n }\n }\n return null;\n }\n \n case 'binary_expr': {\n const left = await evalExpression(row, expr.left, fromAlias, joinAliases, stack, executePlan, outerRow, outerAliases);\n let right;\n if (expr.right.type === 'param') {\n right = expr.right.value;\n if (!isNaN(parseFloat(right))) right = parseFloat(right);\n } else {\n right = await evalExpression(row, expr.right, fromAlias, joinAliases, stack, executePlan, outerRow, outerAliases);\n }\n\n switch (expr.operator) {\n case '=': return left == right;\n case '>': return left > right;\n case '<': return left < right;\n case '>=': return left >= right;\n case '<=': return left <= right;\n case 'IN': // This is handled specially during join execution\n return Array.isArray(right) && right.includes(left);\n default:\n throw new Error(`Unsupported operator ${expr.operator}`);\n }\n }\n \n case 'aggr_func':\n // This should be handled by accumulators, but can be evaluated post-aggregation\n if(row.hasOwnProperty(expr.name)) return row[expr.name];\n return null;\n \n case 'param':\n let value = expr.value;\n if (!isNaN(parseFloat(value))) value = parseFloat(value);\n return value;\n \n case 'star':\n return row; // Represents the whole row for COUNT(*)\n\n default:\n throw new Error(`Unsupported expression type: ${expr.type}`);\n }\n}\n\n/**\n * Evaluates an expression against a row that has already been aggregated.\n * This is specifically used for the HAVING clause, where expressions can\n * contain aggregate functions or GROUP BY columns.\n * @param {object} row The aggregated data row.\n * @param {object} expr The AST expression node from the HAVING clause.\n * @param {Map<string, string>} aggregateAliasMap A map to resolve aggregate function expressions to their aliases in the row.\n * @returns {*} The result of the expression evaluation.\n * @throws {Error} If the expression is invalid for a HAVING clause.\n */\nexport function evalAggregatedRowExpression(row, expr, aggregateAliasMap) {\n if (!expr) return null;\n\n switch (expr.type) {\n case 'aggr_func':\n const key = JSON.stringify(expr);\n const alias = aggregateAliasMap.get(key);\n if (alias && row.hasOwnProperty(alias)) {\n return row[alias];\n }\n throw new Error(`Aggregate function ${expr.name} used in HAVING clause was not found in the SELECT list.`);\n\n case 'column_ref':\n // In an aggregated row, column refs point to GROUP BY keys.\n const colName = expr.as || expr.column;\n if (row.hasOwnProperty(colName)) {\n return row[colName];\n }\n throw new Error(`Column '${colName}' not found in aggregated row. It must be part of the GROUP BY clause.`);\n\n case 'binary_expr':\n const left = evalAggregatedRowExpression(row, expr.left, aggregateAliasMap);\n let right;\n if (expr.right.type === 'param') {\n right = expr.right.value;\n if (!isNaN(parseFloat(right))) right = parseFloat(right);\n } else {\n right = evalAggregatedRowExpression(row, expr.right, aggregateAliasMap);\n }\n\n switch (expr.operator) {\n case '=': return left == right;\n case '>': return left > right;\n case '<': return left < right;\n case '>=': return left >= right;\n case '<=': return left <= right;\n default:\n throw new Error(`Unsupported operator in HAVING clause: ${expr.operator}`);\n }\n\n case 'param':\n let value = expr.value;\n if (!isNaN(parseFloat(value))) value = parseFloat(value);\n return value;\n\n default:\n throw new Error(`Unsupported expression type in HAVING clause: ${expr.type}`);\n }\n}","// @ts-nocheck\nimport { evalExpression } from './evaluator';\n\n/**\n * Accumulator for the SUM() aggregate function.\n */\nclass Sum {\n /**\n * @param {string} alias The result alias for this aggregate.\n * @param {object} expr The expression to be summed.\n * @param {string} fromAlias The alias of the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n */\n constructor(alias, expr, fromAlias, joinAliases) {\n this.alias = alias;\n this.expr = expr;\n this.fromAlias = fromAlias;\n this.joinAliases = joinAliases;\n this.sum = 0;\n this.seen = false;\n }\n /**\n * Adds a row's value to the sum.\n * @param {object} row The row to process.\n */\n async add(row) {\n const val = await evalExpression(row, this.expr, this.fromAlias, this.joinAliases);\n if (val != null && typeof val === 'number') {\n this.sum += val;\n this.seen = true;\n }\n }\n /**\n * Returns the final sum.\n * @returns {number|null} The total sum, or null if no values were added.\n */\n result() { return this.seen ? this.sum : null; }\n}\n\n/**\n * Accumulator for the COUNT() aggregate function.\n */\nclass Count {\n /**\n * @param {string} alias The result alias for this aggregate.\n * @param {object} expr The expression to be counted.\n * @param {string} fromAlias The alias of the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n */\n constructor(alias, expr, fromAlias, joinAliases) {\n this.alias = alias;\n this.expr = expr;\n this.fromAlias = fromAlias;\n this.joinAliases = joinAliases;\n this.count = 0;\n }\n /**\n * Increments the count for a row. For COUNT(column), it only counts non-null values.\n * For COUNT(*), it counts all rows.\n * @param {object} row The row to process.\n */\n async add(row) {\n if (this.expr.type === 'star') {\n this.count++;\n } else {\n const val = await evalExpression(row, this.expr, this.fromAlias, this.joinAliases);\n if (val != null) {\n this.count++;\n }\n }\n }\n /**\n * Returns the final count.\n * @returns {number} The total count.\n */\n result() { return this.count; }\n}\n\n/**\n * Accumulator for the AVG() aggregate function.\n */\nclass Avg {\n /**\n * @param {string} alias The result alias for this aggregate.\n * @param {object} expr The expression to be averaged.\n * @param {string} fromAlias The alias of the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n */\n constructor(alias, expr, fromAlias, joinAliases) {\n this.alias = alias;\n this.expr = expr;\n this.fromAlias = fromAlias;\n this.joinAliases = joinAliases;\n this.sum = 0;\n this.count = 0;\n }\n /**\n * Adds a row's value to the running sum and increments the count.\n * @param {object} row The row to process.\n */\n async add(row) {\n const val = await evalExpression(row, this.expr, this.fromAlias, this.joinAliases);\n if (val != null && typeof val === 'number') {\n this.sum += val;\n this.count++;\n }\n }\n /**\n * Returns the final average.\n * @returns {number|null} The average, or null if no values were added.\n */\n result() { return this.count > 0 ? this.sum / this.count : null; }\n}\n\n/**\n * Accumulator for the MIN() aggregate function.\n */\nclass Min {\n /**\n * @param {string} alias The result alias for this aggregate.\n * @param {object} expr The expression to find the minimum of.\n * @param {string} fromAlias The alias of the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n */\n constructor(alias, expr, fromAlias, joinAliases) {\n this.alias = alias;\n this.expr = expr;\n this.fromAlias = fromAlias;\n this.joinAliases = joinAliases;\n this.min = null;\n }\n /**\n * Updates the minimum value based on the current row.\n * @param {object} row The row to process.\n */\n async add(row) {\n const val = await evalExpression(row, this.expr, this.fromAlias, this.joinAliases);\n if (val != null) {\n if (this.min === null || val < this.min) {\n this.min = val;\n }\n }\n }\n /**\n * Returns the final minimum value.\n * @returns {*} The minimum value, or null if no values were processed.\n */\n result() { return this.min; }\n}\n\n/**\n * Accumulator for the MAX() aggregate function.\n */\nclass Max {\n /**\n * @param {string} alias The result alias for this aggregate.\n * @param {object} expr The expression to find the maximum of.\n * @param {string} fromAlias The alias of the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n */\n constructor(alias, expr, fromAlias, joinAliases) {\n this.alias = alias;\n this.expr = expr;\n this.fromAlias = fromAlias;\n this.joinAliases = joinAliases;\n this.max = null;\n }\n /**\n * Updates the maximum value based on the current row.\n * @param {object} row The row to process.\n */\n async add(row) {\n const val = await evalExpression(row, this.expr, this.fromAlias, this.joinAliases);\n if (val != null) {\n if (this.max === null || val > this.max) {\n this.max = val;\n }\n }\n }\n /**\n * Returns the final maximum value.\n * @returns {*} The maximum value, or null if no values were processed.\n */\n result() { return this.max; }\n}\n\n/**\n * A wrapper class that adds DISTINCT functionality to another accumulator.\n * It ensures that the inner accumulator only processes unique values.\n */\nclass DistinctWrapper {\n /**\n * @param {object} innerAccumulator The accumulator to wrap (e.g., Count, Sum).\n */\n constructor(innerAccumulator) {\n this.inner = innerAccumulator;\n this.seen = new Set();\n this.alias = this.inner.alias;\n }\n\n /**\n * Adds a row's value to the inner accumulator only if it hasn't been seen before.\n * @param {object} row The row to process.\n */\n async add(row) {\n const val = await evalExpression(row, this.inner.expr, this.inner.fromAlias, this.inner.joinAliases);\n const key = JSON.stringify(val); // Use JSON to handle objects/arrays as keys\n\n if (!this.seen.has(key)) {\n this.seen.add(key);\n // Delegate to the inner accumulator, which will re-evaluate, but only for unique values\n await this.inner.add(row);\n }\n }\n\n /**\n * Returns the result from the inner accumulator.\n * @returns {*} The final aggregated result.\n */\n result() {\n return this.inner.result();\n }\n}\n\n\n/**\n * Creates an array of accumulator instances based on the aggregate functions in the query plan.\n * @param {Array<object>} aggregates A list of aggregate function definitions from the plan.\n * @param {string} fromAlias The alias for the FROM table.\n * @param {object} joinAliases A map of join aliases.\n * @returns {Array<object>} An array of initialized accumulator instances.\n * @throws {Error} If an unsupported aggregate function is specified.\n */\nexport function createAccumulators(aggregates, fromAlias, joinAliases) {\n return aggregates.map(agg => {\n const alias = agg.as || agg.expr.name;\n const expr = agg.expr.args.expr;\n const isDistinct = agg.expr.args.distinct;\n\n let accumulator;\n\n switch(agg.expr.name) {\n case 'COUNT':\n accumulator = new Count(alias, expr, fromAlias, joinAliases);\n break;\n case 'SUM':\n accumulator = new Sum(alias, expr, fromAlias, joinAliases);\n break;\n case 'AVG':\n accumulator = new Avg(alias, expr, fromAlias, joinAliases);\n break;\n case 'MIN':\n accumulator = new Min(alias, expr, fromAlias, joinAliases);\n break;\n case 'MAX':\n accumulator = new Max(alias, expr, fromAlias, joinAliases);\n break;\n default:\n throw new Error(`Unsupported aggregate function: ${agg.expr.name}`);\n }\n\n if (isDistinct) {\n // COUNT(*) should not be distinct\n if (expr.type === 'star') return accumulator;\n return new DistinctWrapper(accumulator);\n }\n \n return accumulator;\n });\n}","// @ts-nocheck\nimport { evalExpression, createRowEvaluator, evalAggregatedRowExpression } from './evaluator';\nimport { createAccumulators } from './accumulators';\nimport ClientStack from '../stack';\n\n/**\n * An async version of Array.prototype.filter.\n * @param {Array<any>} arr The array to filter.\n * @param {function(any): Promise<boolean>} predicate An async function that returns a boolean.\n * @returns {Promise<Array<any>>} The filtered array.\n */\nasync function asyncFilter(arr, predicate) {\n const results = await Promise.all(arr.map(predicate));\n return arr.filter((_v, index) => results[index]);\n}\n\n\n/**\n * Converts an array of AST predicate nodes into a PouchDB/Mango selector object.\n * This is a simplified implementation for basic equality and comparison operators.\n * @param {Array<object>} predicates An array of predicate nodes from the query plan.\n * @returns {object} A Mango selector object for filtering documents.\n */\nfunction buildSelector(predicates) {\n if (!predicates || predicates.length === 0) return {};\n const selector = {};\n for (const pred of predicates) {\n // This is a simplified conversion from AST to Mango selector\n if (pred.type === 'binary_expr' && pred.left.type === 'column_ref') {\n const key = pred.left.column;\n const op = {\n '=': '$eq',\n '>': '$gt',\n '<': '$lt',\n '>=': '$gte',\n '<=': '$lte',\n }[pred.operator];\n if (op && pred.right.type === 'param') {\n // For demo, we are assuming numeric/string literals.\n let value = pred.right.value;\n if(!isNaN(parseFloat(value))) value = parseFloat(value);\n selector[key] = { [op]: value };\n }\n }\n }\n return selector;\n}\n\n/**\n * Transforms a set of rows by applying the projections from the SELECT clause.\n * Each row is reshaped to include only the specified columns, with aliasing.\n * @param {Array<object>} rows The input rows to process.\n * @param {Array<object>} projections The projection definitions from the query plan.\n * @param {string} fromAlias The alias for the FROM table.\n * @param {object} joinAliases A map of join table aliases.\n * @returns {Promise<Array<object>>} The transformed rows.\n */\nasync function applyProjections(rows, projections, fromAlias, joinAliases, stack, executePlan) {\n return Promise.all(rows.map(async (row) => {\n const newRow = {};\n for (const p of projections) {\n const alias = p.as || (p.expr.type === 'column_ref' ? p.expr.column : (p.expr.name || 'expr'));\n newRow[alias] = await evalExpression(row, p.expr, fromAlias, joinAliases, stack, executePlan, row);\n }\n return newRow;\n }));\n}\n\n/**\n * Removes duplicate rows from a result set, implementing SELECT DISTINCT.\n * @param {Array<object>} rows The rows to de-duplicate.\n * @returns {Array<object>} The de-duplicated rows.\n */\nfunction applyDistinct(rows, columns = null) {\n if (!rows || rows.length === 0) return [];\n\n const seen = new Set();\n const result = [];\n\n for (const row of rows) {\n // Create a stable key based on the row's values.\n // Sorting keys ensures that {a:1, b:2} and {b:2, a:1} are treated as the same.\n const key = JSON.stringify(\n columns && columns.length > 0\n ? columns.map(col => row[col])\n : Object.keys(row).sort().map(k => row[k])\n );\n if (!seen.has(key)) {\n seen.add(key);\n result.push(row);\n }\n }\n return result;\n}\n\n/**\n * Sorts a set of rows based on the ORDER BY clause.\n * @param {Array<object>} rows The rows to sort.\n * @param {Array<object>} orderBy The sorting criteria from the query plan.\n * @returns {Array<object>} The sorted rows.\n */\nfunction applyOrderBy(rows, orderBy) {\n if (!orderBy) return rows;\n \n return [...rows].sort((a, b) => {\n for (const order of orderBy) {\n // We assume aliases from projection are now keys in the row object.\n const key = order.expr.column;\n const valA = a[key];\n const valB = b[key];\n \n let comparison = 0;\n if (valA < valB) comparison = -1;\n if (valA > valB) comparison = 1;\n \n if (comparison !== 0) {\n return order.order === 'DESC' ? -comparison : comparison;\n }\n }\n return 0;\n });\n}\n\n/**\n * Performs grouping and aggregation on a set of rows.\n * Implements GROUP BY, aggregate functions (COUNT, SUM, etc.), and HAVING.\n * @param {Array<object>} rows The input rows.\n * @param {object} aggregation The aggregation plan, including group by keys and aggregates.\n * @param {string} fromAlias Alias of the FROM table.\n * @param {object} joinAliases Map of join table aliases.\n * @returns {Promise<Array<object>>} The aggregated result rows.\n */\nasync function applyAggregation(rows, aggregation, fromAlias, joinAliases, stack, executePlan) {\n const { groupBy, aggregates, having } = aggregation;\n\n // Handle scalar aggregation on an empty result set (e.g., SELECT COUNT(*) FROM empty_table).\n // SQL expects one row with initial values (COUNT=0, SUM=NULL, etc.).\n if (rows.length === 0 && groupBy.length === 0) {\n const accumulators = createAccumulators(aggregates, fromAlias, joinAliases);\n const initialRow = {};\n await Promise.all(accumulators.map(async acc => {\n initialRow[acc.alias] = await acc.result();\n }));\n \n // If there's a HAVING clause, it must be evaluated against this initial row.\n if (having) {\n const aggregateAliasMap = new Map();\n (aggregates || []).forEach(agg => {\n const key = JSON.stringify(agg.expr);\n const alias = agg.as || agg.expr.name;\n aggregateAliasMap.set(key, alias);\n });\n \n if (evalAggregatedRowExpression(initialRow, having, aggregateAliasMap)) {\n return [initialRow];\n }\n return []; // The initial row did not satisfy the HAVING condition.\n }\n \n return [initialRow];\n }\n \n const groups = new Map();\n for (const row of rows) {\n const keyParts = await Promise.all(groupBy.map(gb => evalExpression(row, gb, fromAlias, joinAliases, stack, executePlan, row)));\n const key = JSON.stringify(keyParts);\n\n if (!groups.has(key)) {\n groups.set(key, {\n accumulators: createAccumulators(aggregates, fromAlias, joinAliases),\n keyValues: keyParts,\n });\n }\n const group = groups.get(key);\n for(const acc of group.accumulators) {\n await acc.add(row);\n }\n }\n\n let resultRows = [];\n \n // Create a map from aggregate function AST to its final alias for HAVING clause evaluation.\n const aggregateAliasMap = new Map();\n (aggregates || []).forEach(agg => {\n const key = JSON.stringify(agg.expr);\n const alias = agg.as || agg.expr.name;\n aggregateAliasMap.set(key, alias);\n });\n\n for (const group of groups.values()) {\n const resultRow = {};\n // Add group by keys to result\n groupBy.forEach((gb, i) => {\n const alias = gb.as || gb.column;\n resultRow[alias] = group.keyValues[i];\n });\n // Add aggregate results\n await Promise.all(group.accumulators.map(async acc => {\n resultRow[acc.alias] = await acc.result();\n }));\n resultRows.push(resultRow);\n }\n \n // Apply HAVING clause filter\n if (having) {\n resultRows = resultRows.filter(row => {\n // Use the new, specialized evaluator for aggregated rows.\n return evalAggregatedRowExpression(row, having, aggregateAliasMap);\n });\n }\n\n return resultRows;\n}\n\n\nasync function executeSingleSelectPlan(stack: ClientStack, plan, params, outerRow, outerAliases) {\n // 1. Fetch from table\n const fromClass = await stack.getClass(plan.fromTable.table);\n if (!fromClass) throw new Error(`Table not found: ${plan.fromTable.table}`);\n\n const leftSelector = buildSelector(plan.filters.left);\n let leftRows = (await fromClass.getCards(leftSelector)).map(row => ({ [plan.fromTable.as || plan.fromTable.table]: row }));\n\n // 2. Execute Joins\n let currentResultRows = leftRows;\n for (const join of plan.joins) {\n const rightClass = await stack.getClass(join.table);\n if (!rightClass) throw new Error(`Table not found: ${join.table}`);\n \n const joinAlias = join.as || join.table;\n const fromAlias = plan.fromTable.as || plan.fromTable.table;\n\n // Combine base table filters with filters from the subquery's WHERE clause\n const rightBaseSelector = buildSelector(plan.filters.right[join.table] || []);\n const subqueryFilterSelector = buildSelector(join.filters || []);\n const finalRightSelector = {...rightBaseSelector, ...subqueryFilterSelector};\n\n const allRightRows = await rightClass.getCards(finalRightSelector);\n \n if (join.type === 'SEMI' || join.type === 'ANTI') {\n let resultRows;\n \n if (join.on.operator === 'IN') {\n // This logic handles correlated `IN` where an inner table column\n // is checked against an outer table column that is an array.\n // e.g., WHERE EXISTS (SELECT 1 FROM Actor a WHERE a._id IN m.actors AND ...)\n const rightRowIds = new Set(allRightRows.map(r => r._id));\n\n resultRows = await asyncFilter(currentResultRows, async (leftRow) => {\n // right side of IN is the outer table array, e.g., m.actors\n const outerArray = await evalExpression(leftRow, join.on.right, fromAlias, {}, stack, executePlan, leftRow);\n if (!Array.isArray(outerArray)) {\n return join.type === 'ANTI'; // No match if not an array\n }\n\n const matchFound = outerArray.some(id => rightRowIds.has(id));\n\n return (join.type === 'SEMI') ? matchFound : !matchFound;\n });\n } else { // Handle standard equi-join correlations like `a.name = m.title`\n const rightRowMap = new Map();\n const rightJoinKeyExpr = join.on.right;\n \n // 1. Build a map from the right-side rows, keyed by their join attribute.\n await Promise.all(allRightRows.map(async rightRow => {\n const key = await evalExpression({ [joinAlias]: rightRow }, rightJoinKeyExpr, fromAlias, { [joinAlias]: join.table }, stack, executePlan, { [joinAlias]: rightRow });\n rightRowMap.set(key, true);\n }));\n \n // 2. Filter the left-side rows by probing the map.\n resultRows = await asyncFilter(currentResultRows, async (leftRow) => {\n // Evaluate the join key expression (e.g., a.name) on the left row.\n const key = await evalExpression(leftRow, join.on.left, fromAlias, {}, stack, executePlan, leftRow);\n const matchFound = rightRowMap.has(key);\n \n return (join.type === 'SEMI') ? matchFound : !matchFound;\n });\n }\n \n currentResultRows = resultRows;\n continue; // Skip to next join\n }\n\n\n const rightRowMap = new Map(allRightRows.map(r => [r._id, r]));\n let newResultRows = [];\n const matchedRightIds = new Set();\n\n for(const leftRow of currentResultRows) {\n let matchFoundForLeftRow = false;\n \n // This logic is specific to the `ON a._id IN m.actors` pattern\n const fk_list = await evalExpression(leftRow, join.on.right, fromAlias, {}, stack, executePlan, leftRow);\n if (join.on.operator === 'IN' && Array.isArray(fk_list)) {\n for(const fk of fk_list) {\n if (rightRowMap.has(fk)) {\n newResultRows.push({...leftRow, [joinAlias]: rightRowMap.get(fk)});\n matchFoundForLeftRow = true;\n if (join.type === 'RIGHT') {\n matchedRightIds.add(fk);\n }\n }\n }\n }\n \n if (!matchFoundForLeftRow && join.type === 'LEFT') {\n const nullRightRow = { [joinAlias]: null };\n newResultRows.push({ ...leftRow, ...nullRightRow });\n }\n }\n \n if (join.type === 'RIGHT') {\n for (const rightRow of allRightRows) {\n if (!matchedRightIds.has(rightRow._id)) {\n // Create a row with nulls for all fields that have been accumulated so far.\n const nullLeftRow = {};\n const leftSchemaAliases = [plan.fromTable.as || plan.fromTable.table];\n const previousJoins = plan.joins.slice(0, plan.joins.indexOf(join));\n previousJoins.forEach(pj => leftSchemaAliases.push(pj.as || pj.table));\n \n leftSchemaAliases.forEach(alias => {\n nullLeftRow[alias] = null;\n });\n\n newResultRows.push({ ...nullLeftRow, [joinAlias]: rightRow });\n }\n }\n }\n \n currentResultRows = newResultRows;\n }\n let joinedRows = currentResultRows;\n \n // 3. Apply residual filters\n let filteredRows = joinedRows;\n if (plan.filters.residual.length > 0) {\n const evaluators = plan.filters.residual.map(predicate => createRowEvaluator(predicate, stack, executePlan, outerRow, null));\n filteredRows = await asyncFilter(joinedRows, async (row) => {\n for (const evaluator of evaluators) {\n if (!(await evaluator(row))) {\n return false;\n }\n }\n return true;\n });\n }\n\n let finalRows = filteredRows;\n\n // 4. Aggregation\n if (plan.aggregation) {\n const fromAlias = plan.fromTable.as || plan.fromTable.table;\n const joinAliases = plan.joins.reduce((acc, j) => ({ ...acc, [j.as || j.table]: j.table }), {});\n finalRows = await applyAggregation(filteredRows, plan.aggregation, fromAlias, joinAliases, stack, executePlan);\n }\n \n // 5. Projections\n let projectedRows;\n if (plan.aggregation) {\n // Projection is handled inside aggregation for aliasing group keys and agg results.\n // Here we just re-alias if needed.\n projectedRows = await Promise.all(finalRows.map(async row => {\n const newRow = {};\n for(const p of plan.projections) {\n const colName = p.expr.column || p.expr.name;\n const alias = p.as || colName;\n if(row.hasOwnProperty(colName)) {\n newRow[alias] = row[colName];\n } else if(row.hasOwnProperty(alias)) {\n newRow[alias] = row[alias];\n }\n }\n return newRow;\n }));\n\n } else {\n const fromAlias = plan.fromTable.as || plan.fromTable.table;\n const joinAliases = plan.joins.reduce((acc, j) => ({ ...acc, [j.as || j.table]: j.table }), {});\n projectedRows = await applyProjections(finalRows, plan.projections, fromAlias, joinAliases, stack, executePlan);\n }\n \n // 5.5 Apply DISTINCT/DISTINCT ON to final result set if specified\n let orderedRows = projectedRows;\n if (plan.distinct && plan.distinctOn) {\n const distinctColumns = plan.distinctOn.map(expr => expr.column);\n orderedRows = applyOrderBy(orderedRows, plan.orderBy);\n orderedRows = applyDistinct(orderedRows, distinctColumns);\n } else {\n let distinctRows = projectedRows;\n if (plan.distinct) {\n distinctRows = applyDistinct(projectedRows);\n }\n orderedRows = applyOrderBy(distinctRows, plan.orderBy);\n }\n\n // 7. Limit\n if (plan.limit !== null && plan.limit !== undefined) {\n return orderedRows.slice(0, plan.limit);\n }\n \n return orderedRows;\n}\n\nasync function executeUnionPlan(stack, plan, params) {\n if (plan.selectPlans.length === 0) return [];\n\n // Step 1: Execute all SELECT sub-queries to get their result sets.\n // This can be done in parallel for efficiency.\n const allSelectResults = await Promise.all(\n plan.selectPlans.map(p => executeSingleSelectPlan(stack, p, params))\n );\n\n // Step 2: Combine the results sequentially based on the UNION operations.\n // UNION is left-associative, e.g., (A UNION B) UNION C.\n // We start with the results of the very first SELECT statement, which corresponds to the\n // first `top` plan in the chain.\n let combinedRows = allSelectResults[plan.unionOps[0].topPlanIndex];\n\n // The unionOps are ordered. Each one connects the result of the previous operation\n // with the next SELECT statement's results.\n for (const unionOp of plan.unionOps) {\n // The `bottomPlanIndex` tells us which result set to merge next.\n const nextRows = allSelectResults[unionOp.bottomPlanIndex];\n \n combinedRows.push(...nextRows);\n \n if (unionOp.distinct) {\n combinedRows = applyDistinct(combinedRows);\n }\n }\n\n // Step 3: Apply final ORDER BY and LIMIT to the fully combined result set.\n let orderedRows = applyOrderBy(combinedRows, plan.orderBy);\n if (plan.limit !== null && plan.limit !== undefined) {\n return orderedRows.slice(0, plan.limit);\n }\n return orderedRows;\n}\n\n\n/**\n * Executes a query plan against the in-memory database.\n * This function orchestrates fetching data, joining, filtering, aggregating,\n * projecting, sorting, and limiting the results.\n * @param {object} stack The ClientStack instance providing data access.\n * @param {object} plan The query plan generated by the planner.\n * @param {Array<any>} params A list of parameters for prepared statements (not used in this version).\n * @param {object | null} outerRow The data row from an outer query for correlated subqueries.\n * @param {object | null} outerAliases The aliases from an outer query.\n * @returns {Promise<Array<object>>} A promise that resolves to the final query results.\n * @throws {Error} If a table specified in the query is not found.\n */\nexport async function executePlan(stack: ClientStack, plan, params, outerRow = null, outerAliases = null) {\n if (!plan) return [];\n \n if (plan.type === 'union') {\n return executeUnionPlan(stack, plan, params);\n }\n \n // Default to existing logic for single select plan\n return executeSingleSelectPlan(stack, plan, params, outerRow, outerAliases);\n}","import type ClientStack from \"../stack.js\";\nimport type { JobModel, JobRunModel, JobStatus, JobTriggerType } from \"@docstack/shared\";\n\n/**\n * Calculates a SHA-256 hash of the given content.\n * Used to verify job content integrity.\n * @param content - The string content to hash\n * @returns The hex-encoded hash string\n */\nconst calculateHash = async (content: string): Promise<string> => {\n const getCrypto = () => globalThis.crypto;\n const crypto = getCrypto();\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const buffer = await crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(buffer)).map(b => b.toString(16).padStart(2, '0')).join('');\n};\n\nconst now = () => Date.now();\n\n/**\n * Represents an executable job that can perform background tasks.\n * \n * Jobs are stored as documents with executable content that is verified\n * via hash before execution. They support singleton mode (only one instance\n * can run at a time), metadata persistence, and run history tracking.\n * \n * @example\n * ```typescript\n * // Jobs are typically executed via JobEngine\n * const run = await stack.jobEngine.executeJob('Job-auth', {\n * password: 'user-password',\n * salt: 'user-salt'\n * });\n * console.log('Job result:', run.finalMetadata);\n * ```\n */\nexport class Job {\n /** The JobModel document containing job configuration and content. */\n public readonly model: JobModel;\n /** Reference to the parent stack for database operations. */\n private readonly stack: ClientStack;\n\n private constructor(model: JobModel, stack: ClientStack) {\n this.model = model;\n this.stack = stack;\n }\n\n /**\n * Creates a validated Job instance from a JobModel document.\n * Verifies the content hash to ensure integrity.\n * \n * @param model - The JobModel document from the database\n * @param stack - The parent ClientStack instance\n * @returns A validated Job instance\n * @throws Error if the content hash doesn't match\n */\n public static async create(model: JobModel, stack: ClientStack): Promise<Job> {\n const computed = await calculateHash(model.content);\n if (computed !== model.hash) {\n throw new Error(`Job content hash mismatch for ${model._id}`);\n }\n return new Job(model, stack);\n }\n\n /**\n * Hydrates the job content into an executable function.\n * The job content must define an `execute(stack, params, job)` function.\n */\n private hydrate() {\n return new Function(\"stack\", \"params\", \"job\", `\"use strict\"; ${this.model.content}; return execute(stack, params, job);`);\n }\n\n private async hasRunningInstance() {\n if (!this.model.isSingleton) return false;\n const existingRuns = await (this.stack.db as any).find({\n selector: {\n \"~class\": \"~JobRun\",\n jobId: this.model._id,\n status: \"RUNNING\",\n },\n limit: 1,\n });\n return Boolean(existingRuns?.docs?.length);\n }\n\n private buildRun(triggerType: JobTriggerType, runtimeArgs?: Record<string, any>): JobRunModel {\n const getCrypto = () => globalThis.crypto;\n const crypto = getCrypto();\n const id = `JobRun-${crypto.randomUUID ? crypto.randomUUID() :\n Array.from(crypto.getRandomValues(new Uint8Array(16))).map(b => b.toString(16).padStart(2, '0')).join('')\n }`;\n const base: JobRunModel = {\n _id: id,\n \"~class\": \"~JobRun\",\n jobId: this.model._id,\n status: \"PENDING\" as JobStatus,\n triggerType,\n startTime: now(),\n runtimeArgs,\n initialMetadata: this.model.metadata ? { ...this.model.metadata } : undefined,\n };\n return base;\n }\n\n private async persistRun(run: JobRunModel) {\n const existing = await this.stack.db.get<JobRunModel>(run._id).catch(() => null);\n const doc = existing ? { ...run, _rev: existing._rev } : run;\n await this.stack.db.bulkDocs([doc as any]);\n return (doc as JobRunModel);\n }\n\n private async persistJobMetadata(metadata?: Record<string, any>) {\n if (!metadata) return;\n const current = await this.stack.db.get<JobModel>(this.model._id).catch(() => null);\n const nextDoc: JobModel = {\n ...this.model,\n _rev: current?._rev,\n metadata,\n } as JobModel;\n await this.stack.db.bulkDocs([nextDoc as any]);\n }\n\n /**\n * Executes the job with optional runtime arguments.\n * \n * Creates a JobRun document to track execution, handles singleton logic,\n * and persists any metadata updates from the job execution.\n * \n * @param runtimeArgs - Optional parameters to pass to the job\n * @param triggerType - How the job was triggered ('manual', 'scheduled', etc.)\n * @returns The completed JobRunModel with status and results\n * @throws Error if the job is disabled or a singleton instance is already running\n * \n * @example\n * ```typescript\n * const run = await job.execute({ userId: 'user-123' }, 'manual');\n * if (run.status === 'SUCCESS') {\n * console.log('Result:', run.finalMetadata);\n * }\n * ```\n */\n public async execute(runtimeArgs?: Record<string, any>, triggerType: JobTriggerType = \"manual\") {\n let run = this.buildRun(triggerType, runtimeArgs);\n run = await this.persistRun(run);\n\n if (!this.model.isEnabled) {\n run.status = \"SKIPPED\";\n run.errorMessage = `Job ${this.model._id} is disabled`;\n run.endTime = now();\n run.durationMs = run.endTime - run.startTime;\n await this.persistRun(run);\n throw new Error(run.errorMessage);\n }\n\n if (await this.hasRunningInstance()) {\n run.status = \"SKIPPED\";\n run.errorMessage = `Job ${this.model._id} already has a running instance`;\n run.endTime = now();\n run.durationMs = run.endTime - run.startTime;\n await this.persistRun(run);\n throw new Error(run.errorMessage);\n }\n\n try {\n run.status = \"RUNNING\";\n run.startTime = now();\n run = await this.persistRun(run);\n\n const executor = this.hydrate();\n const params = { ...(this.model.defaultParams || {}), ...(runtimeArgs || {}) };\n const result = await executor(this.stack, params, this.model);\n const finalMetadata = (result && result.metadata) || this.model.metadata;\n\n if (finalMetadata) {\n run.finalMetadata = finalMetadata;\n this.model.metadata = finalMetadata;\n await this.persistJobMetadata(finalMetadata);\n }\n\n run.status = \"SUCCESS\";\n run.endTime = now();\n run.durationMs = run.endTime - run.startTime;\n return await this.persistRun(run);\n } catch (error: any) {\n run.status = \"FAILURE\";\n run.errorMessage = error?.message || String(error);\n run.errorStack = error?.stack;\n run.endTime = now();\n run.durationMs = run.endTime - run.startTime;\n return await this.persistRun(run);\n }\n }\n}\n\n/**\n * Engine for executing background jobs in the DocStack system.\n * \n * The JobEngine provides a simple interface to execute jobs by their ID.\n * Jobs are fetched from the database, validated, and executed with\n * full run tracking and metadata persistence.\n * \n * @example\n * ```typescript\n * // Execute a job\n * const run = await stack.jobEngine.executeJob('Job-process-data', {\n * batchSize: 100\n * });\n * \n * console.log('Status:', run.status);\n * console.log('Duration:', run.durationMs, 'ms');\n * ```\n */\nexport class JobEngine {\n /** Reference to the parent stack for database operations. */\n private readonly stack: ClientStack;\n\n /**\n * Creates a new JobEngine instance.\n * @param stack - The parent ClientStack instance\n */\n constructor(stack: ClientStack) {\n this.stack = stack;\n }\n\n /**\n * Executes a job by its document ID.\n * \n * @param jobId - The job document ID (e.g., 'Job-auth')\n * @param runtimeArgs - Optional parameters to pass to the job\n * @param triggerType - How the job was triggered (default: 'manual')\n * @returns The completed JobRunModel with execution results\n * \n * @example\n * ```typescript\n * const authRun = await jobEngine.executeJob('Job-auth', {\n * password: 'secret',\n * salt: 'user-salt'\n * });\n * const derivedKey = authRun.finalMetadata?.derivedKey;\n * ```\n */\n public async executeJob(jobId: string, runtimeArgs?: Record<string, any>, triggerType: JobTriggerType = \"manual\") {\n const jobDoc = await this.stack.db.get<JobModel>(jobId);\n const job = await Job.create(jobDoc, this.stack);\n return job.execute(runtimeArgs, triggerType);\n }\n}\n","import type ClientStack from \"../stack.js\";\nimport type { AuthSessionProof, Document, PolicyModel } from \"@docstack/shared\";\n\n/**\n * Set of system classes that bypass policy evaluation.\n * These classes are internal to DocStack and always accessible.\n */\nconst SYSTEM_CLASSES = new Set([\n \"~Policy\",\n \"~Job\",\n \"~JobRun\",\n \"~AuthModule\",\n \"~UserSession\",\n \"class\",\n \"domain\"\n]);\n\n/** The type of operation being authorized: read or write. */\nexport type PolicyOperation = \"read\" | \"write\";\n\n/**\n * Engine for evaluating access control policies on documents.\n * \n * PolicyEngine implements role-based access control (RBAC) by evaluating\n * policy rules against documents and user sessions. Policies can be:\n * - Class-level (apply to all documents of a class)\n * - User-specific (apply only to a specific user)\n * - Group-specific (apply only to users in a specific group)\n * \n * Policy rules are JavaScript expressions that receive the document,\n * session, and groupId as context and return a boolean.\n * \n * @example\n * ```typescript\n * // Policy engine is used automatically during document operations\n * // Policies are defined as documents:\n * await stack.createDoc(null, '~Policy', null, {\n * name: 'user-read-own',\n * targetClass: ['User'],\n * rule: 'return document.userId === session.userId;'\n * });\n * ```\n */\nexport class PolicyEngine {\n /** Reference to the parent stack for database and session access. */\n private readonly stack: ClientStack;\n\n /**\n * Creates a new PolicyEngine instance.\n * @param stack - The parent ClientStack instance\n */\n constructor(stack: ClientStack) {\n this.stack = stack;\n }\n\n /**\n * Gets the current authentication session proof.\n * @returns The session proof, or undefined if not authenticated\n */\n private getSessionProof(): AuthSessionProof | undefined {\n return this.stack.authSession;\n }\n\n /**\n * Checks if a class should bypass policy evaluation.\n * System classes (prefixed with ~) are always allowed.\n * \n * @param targetClass - The class name to check\n * @returns `true` if the class should bypass policies\n */\n private shouldBypass(targetClass: string) {\n if (SYSTEM_CLASSES.has(targetClass)) return true;\n const normalized = targetClass.startsWith(\"~\") ? targetClass.slice(1) : `~${targetClass}`;\n return SYSTEM_CLASSES.has(normalized);\n }\n\n private async loadPolicies(targetClass: string, aliases: string[] = []): Promise<PolicyModel[]> {\n const identifiers = new Set([targetClass, ...aliases]);\n const result = await this.stack.findDocuments<PolicyModel>(\n { \"~class\": \"~Policy\" }\n );\n return result.docs.filter((doc) => {\n if (!Array.isArray(doc.targetClass)) return false;\n return doc.targetClass.some((entry) => identifiers.has(entry));\n });\n }\n\n private getTargetIdentifiers(targetId: string, targetName: string) {\n const identifiers = new Set<string>();\n const variants = [targetId, targetName];\n for (const value of variants) {\n identifiers.add(value);\n if (value.startsWith(\"~\")) {\n identifiers.add(value.slice(1));\n } else {\n identifiers.add(`~${value}`);\n }\n }\n return Array.from(identifiers);\n }\n\n private async resolveClassTarget(targetClass: string) {\n const classModel = await this.stack.getClassModel(targetClass).catch(() => null);\n return {\n id: classModel?._id ?? targetClass,\n name: classModel?.name ?? targetClass,\n };\n }\n\n /**\n * Evaluates a policy rule against a document and session.\n * The rule is a JavaScript expression that returns a boolean.\n * \n * @param policy - The policy containing the rule\n * @param document - The document being accessed\n * @param session - The current auth session\n * @returns Whether the rule permits access\n */\n private async evaluateRule(policy: PolicyModel, document: Document | null, session: AuthSessionProof): Promise<boolean> {\n const executor = new Function(\n \"document\",\n \"session\",\n \"groupId\",\n `\"use strict\"; ${policy.rule}`\n ) as (doc: Document | object, sess: AuthSessionProof[\"session\"], groupId: string | string[]) => any;\n\n const result = executor(document || {}, session.session, session.session.groupId);\n if (result instanceof Promise) {\n return Boolean(await result);\n }\n\n return Boolean(result);\n }\n\n private filterPoliciesForSession(policies: PolicyModel[], session: AuthSessionProof) {\n const sessionUserId = session.session.userId || session.session.username;\n const sessionGroups = Array.isArray((session.session as any).groupId)\n ? (session.session as any).groupId\n : (session.session as any).groupId\n ? [(session.session as any).groupId]\n : [];\n\n return policies.filter((policy) => {\n const matchesUser = !policy.userId || policy.userId === sessionUserId || policy.userId === session.session.username;\n const matchesGroup = !policy.groupId || sessionGroups.includes(policy.groupId);\n return matchesUser && matchesGroup;\n });\n }\n\n private async authorize(targetClass: string, operation: PolicyOperation, document: Document | null): Promise<boolean> {\n const { id: targetId, name: targetName } = await this.resolveClassTarget(targetClass);\n const identifiers = this.getTargetIdentifiers(targetId, targetName);\n\n if (this.shouldBypass(targetName)) {\n return true;\n }\n\n const policies = await this.loadPolicies(targetId, identifiers);\n if (policies.length === 0) {\n return true;\n }\n\n const session = this.getSessionProof();\n if (!session) {\n throw new Error(\"Stack is not authenticated for policy evaluation\");\n }\n\n const targetedPolicies = policies.filter((policy) => policy.userId || policy.groupId);\n const basePolicies = policies.filter((policy) => !policy.userId && !policy.groupId);\n const matchingPolicies = targetedPolicies.length > 0\n ? this.filterPoliciesForSession(targetedPolicies, session)\n : this.filterPoliciesForSession(basePolicies, session);\n\n if (targetedPolicies.length > 0 && matchingPolicies.length === 0) {\n throw new Error(`No matching policy allowed ${operation} on class '${targetClass}'`);\n }\n\n let allowed = false;\n for (const policy of matchingPolicies) {\n const result = await this.evaluateRule(policy, document, session);\n if (result === false) {\n throw new Error(`Policy '${policy._id}' denied ${operation} on class '${targetClass}'`);\n }\n if (result === true) {\n allowed = true;\n }\n }\n\n return allowed;\n }\n\n /**\n * Ensures write access is allowed for a document of the given class.\n * Throws an error if no policy permits the write operation.\n * \n * @param targetClass - The class of the document being written\n * @param document - The document to write\n * @throws Error if write is not permitted\n * \n * @example\n * ```typescript\n * // Called automatically during createDoc/updateCard operations\n * await policyEngine.ensureWriteAllowed('Task', taskDocument);\n * ```\n */\n public async ensureWriteAllowed(targetClass: string, document: Document | null) {\n const allowed = await this.authorize(targetClass, \"write\", document);\n if (!allowed) {\n throw new Error(`No matching policy allowed write on class '${targetClass}'`);\n }\n }\n\n /**\n * Checks if a document is readable by the current user.\n * Used to filter query results based on read policies.\n * \n * @param document - The document to check\n * @returns `true` if the document can be read\n * @throws Error if the stack is not authenticated\n * \n * @example\n * ```typescript\n * // Used internally during findDocuments\n * const readable = await policyEngine.isReadableDocument(doc);\n * if (readable) {\n * results.push(doc);\n * }\n * ```\n */\n public async isReadableDocument(document: Document): Promise<boolean> {\n const targetClass = (document as any)?.[\"~class\"] as string;\n const { id: targetId, name: targetName } = await this.resolveClassTarget(targetClass);\n if (!targetClass || this.shouldBypass(targetName)) {\n return true;\n }\n\n const policies = await this.loadPolicies(targetId, this.getTargetIdentifiers(targetId, targetName));\n if (policies.length === 0) {\n return true;\n }\n\n const session = this.getSessionProof();\n if (!session) {\n throw new Error(\"Stack is not authenticated for policy evaluation\");\n }\n\n const targetedPolicies = policies.filter((policy) => policy.userId || policy.groupId);\n const basePolicies = policies.filter((policy) => !policy.userId && !policy.groupId);\n const matchingPolicies = targetedPolicies.length > 0\n ? this.filterPoliciesForSession(targetedPolicies, session)\n : this.filterPoliciesForSession(basePolicies, session);\n\n if (targetedPolicies.length > 0 && matchingPolicies.length === 0) {\n return false;\n }\n\n let permitted = false;\n for (const policy of matchingPolicies) {\n const result = await this.evaluateRule(policy, document, session);\n if (result === false) {\n return false;\n }\n if (result === true) {\n permitted = true;\n }\n }\n\n return permitted;\n }\n}\n","\n\nexport type EncryptedPayload = {\n __enc: true;\n iv: string;\n data: string;\n alg: \"AES-GCM\";\n};\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nconst getCrypto = () => globalThis.crypto;\n\nexport const hexToBytes = (hex: string): Uint8Array => {\n if (hex.length % 2 !== 0) {\n throw new Error(\"Hex value must have an even length\");\n }\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);\n }\n return bytes;\n};\n\nconst toUint8Array = (data: ArrayBuffer | Uint8Array) => data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n\nexport const toBase64 = (data: ArrayBuffer | Uint8Array): string => {\n const bytes = toUint8Array(data); \n let binary = \"\";\n bytes.forEach((byte) => {\n binary += String.fromCharCode(byte);\n });\n return btoa(binary);\n};\n\nexport const fromBase64 = (value: string): Uint8Array => { \n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n};\n\nexport const importAesKeyFromHex = async (hexKey: string, usages: KeyUsage[] = [\"encrypt\", \"decrypt\"]): Promise<CryptoKey> => {\n const cryptoObj = getCrypto();\n return cryptoObj.subtle.importKey(\n \"raw\",\n hexToBytes(hexKey) as BufferSource,\n { name: \"AES-GCM\" } as any,\n false,\n usages,\n );\n};\n\nexport const isEncryptedPayload = (value: unknown): value is EncryptedPayload => {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as Record<string, unknown>;\n return candidate.__enc === true && typeof candidate.iv === \"string\" && typeof candidate.data === \"string\";\n};\n\nexport const encryptWithAesGcm = async (plaintext: string, key: CryptoKey): Promise<EncryptedPayload> => {\n const cryptoObj = getCrypto();\n const iv = new Uint8Array(12);\n (cryptoObj as any).getRandomValues(iv);\n const ivBuffer = iv.buffer.slice(iv.byteOffset, iv.byteOffset + iv.byteLength);\n const ciphertext = await cryptoObj.subtle.encrypt({ name: \"AES-GCM\", iv: ivBuffer } as any, key, encoder.encode(plaintext));\n return {\n __enc: true,\n iv: toBase64(iv),\n data: toBase64(ciphertext),\n alg: \"AES-GCM\",\n };\n};\n\nexport const decryptWithAesGcm = async (payload: EncryptedPayload, key: CryptoKey): Promise<string> => {\n const cryptoObj = getCrypto();\n const ivBytes = fromBase64(payload.iv);\n const dataBytes = fromBase64(payload.data);\n const ivBuffer = ivBytes.buffer.slice(ivBytes.byteOffset, ivBytes.byteOffset + ivBytes.byteLength);\n const dataBuffer = dataBytes.buffer.slice(dataBytes.byteOffset, dataBytes.byteOffset + dataBytes.byteLength);\n const decrypted = await cryptoObj.subtle.decrypt(\n { name: \"AES-GCM\", iv: ivBuffer } as any,\n key,\n dataBuffer as BufferSource,\n );\n return decoder.decode(decrypted);\n};\n\nexport const wrapDocumentKey = async (documentKey: string, derivedKeyHex: string): Promise<string> => {\n const key = await importAesKeyFromHex(derivedKeyHex);\n const payload = await encryptWithAesGcm(documentKey, key);\n return JSON.stringify(payload);\n};\n\nexport const unwrapDocumentKey = async (wrappedDocumentKey: string, cryptoKey: CryptoKey, derivedKeyHex: string): Promise<string> => {\n const parsed: unknown = JSON.parse(wrappedDocumentKey);\n if (!isEncryptedPayload(parsed)) {\n throw new Error(\"Wrapped document key payload is malformed: \"+wrappedDocumentKey);\n }\n const key = await importAesKeyFromHex(derivedKeyHex, [\"decrypt\"]);\n const firstLayer = await decryptWithAesGcm(parsed, key);\n return firstLayer;\n // return await decryptWithAesGcm((JSON.parse(firstLayer) as EncryptedPayload), key);\n};\n\n/**\n * Generate random string of given length in bytes, returned as hex string\n *\n**/\nexport const generateRandomString = (length: number = 16): string => {\n const cryptoObj = getCrypto();\n const array = new Uint8Array(length);\n (cryptoObj as any).getRandomValues(array);\n return Array.from(array).map(b => ('00' + b.toString(16)).slice(-2)).join('');\n}\n","import { AttributeModel, Document } from \"@docstack/shared\";\nimport createLogger from \"../../utils/logger/index\";\nimport Class from \"../class\";\nimport type ClientStack from \"../stack\";\nimport { wrapDocumentKey, generateRandomString } from \"./utils\";\nimport {\n EncryptedPayload,\n decryptWithAesGcm,\n encryptWithAesGcm,\n importAesKeyFromHex,\n isEncryptedPayload,\n unwrapDocumentKey,\n} from \"./utils\";\n\n/**\n * Engine for handling document-level encryption and decryption.\n * \n * CryptoEngine manages AES-GCM encryption for sensitive document fields.\n * It uses a document key (derived from user credentials) to encrypt/decrypt\n * fields marked with `encrypted: true` in their attribute configuration.\n * \n * The engine can be disabled via stack options for scenarios where\n * encryption is not required.\n * \n * @example\n * ```typescript\n * // Encryption is handled automatically during document operations\n * // when attributes are configured with `encrypted: true`\n * await Attribute.create(userClass, 'ssn', 'string', 'Social Security Number', {\n * encrypted: true\n * });\n * \n * // After authentication, the document key is available\n * await stack.authenticate({ username: 'user', password: 'pass' });\n * // Now encrypted fields will be automatically encrypted/decrypted\n * ```\n */\nexport class CryptoEngine {\n /** The hex-encoded document encryption key. */\n private documentKey?: string;\n /** The imported CryptoKey for Web Crypto API operations. */\n private cryptoKey?: CryptoKey;\n private readonly logger = createLogger().child({ module: \"crypto-engine\" });\n /** Reference to the parent stack. */\n private readonly stack: ClientStack;\n /** Whether the crypto engine is enabled. */\n private readonly enabled: boolean;\n\n /**\n * Creates a new CryptoEngine instance.\n * @param stack - The parent ClientStack instance\n */\n constructor(stack: ClientStack) {\n this.stack = stack;\n this.enabled = !stack.isCryptoEngineDisabled();\n }\n\n /**\n * Sets the document encryption key.\n * Called automatically during authentication to provide the key\n * derived from user credentials.\n * \n * @param documentKey - The hex-encoded document key, or null to clear\n */\n public async setDocumentKey(documentKey?: string | null) {\n if (!this.enabled) return;\n this.documentKey = documentKey || undefined;\n this.cryptoKey = undefined;\n }\n\n /**\n * Returns the current document key.\n * @returns The hex-encoded document key, or undefined if not set\n */\n public getDocumentKey() {\n return this.enabled ? this.documentKey : undefined;\n }\n\n /**\n * Generates a cryptographically secure random string.\n * Useful for generating salts or nonces.\n * \n * @param length - The length of the string to generate (default: 16)\n * @returns A random hex string\n */\n public generateRandomString(length: number = 16): string {\n return generateRandomString(length);\n }\n\n public async encryptValueForMarker(value: unknown) {\n if (!this.enabled) return null;\n const key = await this.getCryptoKey();\n if (!key) return null;\n return await this.encryptValue(value, key) as EncryptedPayload;\n }\n\n /**\n * Checks if the crypto engine is enabled.\n * @returns `true` if encryption is enabled\n */\n public isEnabled() {\n return this.enabled;\n }\n\n /**\n * Wraps a document key using the user's derived key.\n * Used during user registration to store the encrypted document key.\n * \n * @param documentKey - The document key to wrap\n * @param derivedKeyHex - The user's derived key (from password)\n * @returns The wrapped (encrypted) document key\n */\n public async wrapDocumentKey(documentKey: string, derivedKeyHex: string): Promise<string> {\n return wrapDocumentKey(documentKey, derivedKeyHex);\n }\n\n /**\n * Unwraps and stores the document key using the user's derived key.\n * Called during authentication to recover the document key.\n * \n * @param wrappedDocumentKey - The wrapped document key from the user record\n * @param derivedKey - The user's derived key (from password)\n * @returns The unwrapped document key\n * @throws Error if the crypto engine is disabled or keys are missing\n */\n public async unwrapAndStoreDocumentKey(wrappedDocumentKey?: string | null, derivedKey?: string | null) {\n if (!this.enabled) throw new Error(\"Crypto engine is disabled\");\n if (!wrappedDocumentKey) throw new Error(\"Missing wrapped document key\");\n if (!derivedKey) throw new Error(\"Missing derived key\");\n\n const key = await unwrapDocumentKey(wrappedDocumentKey, await this.getCryptoKey(), derivedKey);\n await this.setDocumentKey(key);\n return key;\n }\n\n private async getCryptoKey() {\n if (!this.enabled) return null;\n if (!this.documentKey) return null;\n if (this.cryptoKey) return this.cryptoKey;\n\n this.cryptoKey = await importAesKeyFromHex(this.documentKey, [\"encrypt\", \"decrypt\"]);\n return this.cryptoKey;\n }\n\n private async encryptValue(value: unknown, key: CryptoKey | null): Promise<EncryptedPayload | unknown> {\n if (!this.enabled) return value;\n if (!key) return value;\n if (value === undefined || value === null) return value;\n if (isEncryptedPayload(value)) return value;\n const serialized = JSON.stringify(value);\n return encryptWithAesGcm(serialized, key);\n }\n\n private async decryptValue(value: unknown, key: CryptoKey | null): Promise<unknown> {\n if (!this.enabled) return value;\n if (!key) return value;\n if (!isEncryptedPayload(value)) return value;\n try {\n const decrypted = await decryptWithAesGcm(value, key);\n return JSON.parse(decrypted);\n } catch (error: any) {\n this.logger.error(\"Failed to decrypt value\", { error: error?.message || error });\n return value;\n }\n }\n\n /**\n * Identifies which document keys contain encrypted data.\n * Combines schema-defined encrypted attributes with runtime detection.\n * \n * @param document - The document to analyze\n * @param classObj - Optional class for schema-based detection\n * @returns Array of field names that are/should be encrypted\n */\n public identifyEncryptedKeys(document: Document, classObj?: Class): string[] {\n if (!this.enabled) return [];\n const encryptedFromSchema = classObj?.getEncryptedAttributes().map((attribute) => attribute.getName()) ?? [];\n const encryptedFromPayload = Object.keys(document).filter((key) => isEncryptedPayload((document as any)[key]));\n\n if (!encryptedFromSchema.length) {\n return encryptedFromPayload;\n }\n\n const merged = new Set<string>(encryptedFromSchema);\n for (const key of encryptedFromPayload) {\n merged.add(key);\n }\n return Array.from(merged);\n }\n\n /**\n * Encrypts sensitive fields in a document before storage.\n * Only encrypts fields marked with `encrypted: true` in the schema.\n * Modifies the document in place.\n * \n * @param document - The document to encrypt\n * @param classObj - The class defining which fields to encrypt\n */\n public async encryptDocument(document: Document, classObj: Class) {\n if (!this.enabled) return;\n const encryptableAttributes = classObj.getEncryptedAttributes();\n if (!encryptableAttributes.length) return;\n\n const key = await this.getCryptoKey();\n if (!key) {\n this.logger.warn(\"Document key is not available; skipping encryption\", { className: classObj.getName?.() ?? classObj.model?.name });\n return;\n }\n\n for (const attribute of encryptableAttributes) {\n const name = attribute.getName();\n if (!(name in document)) continue;\n const encrypted = await this.encryptValue((document as any)[name], key);\n (document as any)[name] = encrypted;\n }\n }\n\n /**\n * Decrypts encrypted fields in a document after retrieval.\n * Modifies the document in place.\n * \n * @param document - The document to decrypt\n * @param classObj - Optional class for schema-based detection\n * @param encryptedKeys - Optional pre-computed list of encrypted field names\n */\n public async decryptDocument(document: Document, classObj?: Class, encryptedKeys?: string[]) {\n if (!this.enabled) return;\n const encryptedAttributes = encryptedKeys ?? this.identifyEncryptedKeys(document, classObj);\n if (!encryptedAttributes.length) return;\n\n const key = await this.getCryptoKey();\n if (!key) {\n this.logger.warn(\"Document key is not available; returning encrypted payload\", { className: classObj?.getName?.() ?? classObj?.model?.name });\n return;\n }\n\n for (const name of encryptedAttributes) {\n const decrypted = await this.decryptValue((document as any)[name], key);\n (document as any)[name] = decrypted;\n }\n }\n}\n\nexport type { EncryptedPayload } from \"./utils\";\nexport { wrapDocumentKey, unwrapDocumentKey } from \"./utils\";\n","import PouchDB from \"pouchdb-browser\";\nimport createLogger from \"../utils/logger\";\nimport Class from \"./class\";\nimport Domain from \"./domain\";\nimport PouchDBFind from 'pouchdb-find';\n\nimport { getAllSystemPatches, getSystemPatches } from \"./datamodel\";\nimport {\n Stack,\n StackOptions,\n AuthSessionProof,\n ClientCredentials,\n CachedClass,\n ClassModelPropagationStart,\n ClassModelPropagationComplete,\n isClassModel,\n CachedDomain,\n DomainModel,\n UserModel,\n UserSessionModel,\n AuthModuleModel,\n PolicyModel,\n} from \"@docstack/shared\";\n\nimport { SystemDoc, Patch, ClassModel, Document, RelationDocument } from \"@docstack/shared\";\nimport { StackPlugin } from \"../plugins/pouchdb\";\n\nimport { parse, createPlan, executePlan } from \"./query-engine\";\nimport type { SelectAST, UnionAST } from \"./query-engine\";\nimport { JobEngine } from \"./job-engine\";\nimport { PolicyEngine } from \"./policy-engine\";\nimport { CryptoEngine } from \"./crypto-engine\";\nimport { isEncryptedPayload } from \"./crypto-engine/utils\";\n\nconst logger = createLogger().child({ module: \"stack\" });\n\nexport const BASE_SCHEMA: ClassModel[\"schema\"] = {\n \"_id\": { name: \"_id\", type: \"string\", config: { maxLength: 100, primaryKey: true } },\n \"~class\": { name: \"~class\", type: \"string\", config: { maxLength: 100 } },\n \"~createTimestamp\": { name: \"~createTimestamp\", type: \"integer\", config: { min: 0 } },\n \"~updateTimestamp\": { name: \"~updateTimestamp\", type: \"integer\", config: { min: 0 } },\n \"description\": { name: \"description\", type: \"string\", config: { maxLength: 1000 } },\n \"active\": { name: \"active\", type: \"boolean\", config: { defaultValue: true, primaryKey: true } }\n}\nexport const CLASS_SCHEMA: ClassModel[\"schema\"] = {\n ...BASE_SCHEMA,\n \"~class\": { name: \"~class\", type: \"string\", config: { defaultValue: \"class\" } },\n \"schema\": { name: \"schema\", type: \"object\", config: { maxLength: 1000, isArray: false } },\n \"parentClass\": { name: \"parentClass\", type: \"foreign_key\", config: { isArray: false } },\n}\nconst DOMAIN_SCHEMA: ClassModel[\"schema\"] = {\n ...BASE_SCHEMA,\n \"~class\": { name: \"~class\", type: \"string\", config: { defaultValue: \"domain\" } },\n \"schema\": {\n name: \"schema\", type: \"object\", config: {\n isArray: true,\n defaultValue: {\n \"source\": {\n name: \"source\",\n type: \"foreign_key\",\n config: {\n isArray: false\n }\n },\n \"target\": {\n name: \"target\",\n type: \"foreign_key\",\n config: {\n isArray: false\n }\n }\n }\n }\n },\n // \"parentDomain\": { name: \"parentDomain\", type: \"foreign_key\", config: { isArray: false } },\n \"relation\": {\n name: \"relation\", type: \"enum\", config: {\n isArray: false, values: [\n { value: \"1:1\" }, { value: \"1:N\" }, { value: \"N:1\" }, { value: \"N:N\" }\n ]\n }\n },\n \"sourceClass\": { name: \"sourceClass\", type: \"foreign_key\", config: { isArray: false } },\n \"targetClass\": { name: \"targetClass\", type: \"foreign_key\", config: { isArray: false } },\n};\n/**\n * The core database engine for DocStack client applications.\n * \n * ClientStack provides a complete offline-first datastore built on PouchDB with:\n * - Schema validation and class-based document modeling\n * - SQL-like querying capabilities\n * - Field-level encryption via {@link CryptoEngine}\n * - Access control via {@link PolicyEngine}\n * - Background job execution via {@link JobEngine}\n * \n * @example\n * ```typescript\n * // Create a new stack instance\n * const stack = await ClientStack.create('my-app-db');\n * \n * // Authenticate a user\n * const session = await stack.authenticate({ username: 'admin', password: 'secret' });\n * \n * // Query documents using SQL\n * const { rows } = await stack.query('SELECT * FROM Task WHERE isComplete = false');\n * ```\n * \n * @extends Stack\n */\nclass ClientStack extends Stack {\n private static readonly CRYPTO_CONFIG_DOC_ID = \"~crypto-engine-config\";\n /**\n * The underlying PouchDB database instance.\n * Initialized asynchronously during stack creation.\n * \n * @example\n * ```typescript\n * // Access the raw PouchDB API for advanced operations\n * const allDocs = await stack.db.allDocs({ include_docs: true });\n * ```\n */\n db!: PouchDB.Database<{}>;\n /** The unique name identifier for this stack instance, derived from the connection string. */\n name!: string;\n /* Retrieved asynchronously */\n lastDocId!: number;\n /** The connection string used to create this stack. */\n connection!: string;\n /** Configuration options provided during stack creation. */\n options?: StackOptions;\n /** The current application version string. */\n appVersion: string = \"0.0.1\";\n /**\n * In-memory cache for Class and Domain objects.\n * Items are cached with a 15-minute TTL to improve performance.\n */\n cache: {\n [className: string]: CachedClass | CachedDomain\n }\n patchCount!: number;\n\n listeners: PouchDB.Core.Changes<{}>[] = [];\n\n modelWorker: Worker | null = null;\n /**\n * Engine for executing background jobs and scheduled tasks.\n * Jobs are defined as documents and run in a sandboxed environment.\n * \n * @example\n * ```typescript\n * const run = await stack.jobEngine.executeJob('Job-CleanupOldData');\n * console.log('Job completed:', run.status);\n * ```\n */\n jobEngine!: JobEngine;\n\n /**\n * Engine for enforcing read/write access control policies.\n * Policies are evaluated based on user session and document content.\n */\n policyEngine!: PolicyEngine;\n\n /**\n * Engine for field-level encryption and decryption.\n * Handles key derivation (PBKDF2) and AES-GCM encryption.\n */\n cryptoEngine!: CryptoEngine;\n schemaVersion: string | undefined;\n /**\n * The current authenticated user session, if any.\n * Contains session details, derived key, and document encryption key.\n */\n authSession?: AuthSessionProof;\n private cryptoEngineDisabled!: boolean;\n\n private constructor() {\n super();\n // Private constructor to prevent direct instantiation\n this.cache = {}\n }\n\n private async initialize(conn: string, options?: StackOptions) {\n // Store the connection string and options\n this.connection = conn;\n this.options = options;\n this.cryptoEngineDisabled = Boolean(options?.disableCryptoEngine);\n if (options?.name) {\n this.name = options?.name\n }\n const connRegExp = /(?<=db-).*/\n const match = conn.match(connRegExp);\n if (match) {\n this.name = match[0];\n } else {\n this.name = conn;\n }\n\n // PouchDB.plugin((await import('pouchdb-adapter-node-websql')).default);\n // PouchDB.plugin((await import('pouchdb-adapter-websql')).default);\n\n // Load default plugins\n PouchDB.plugin(PouchDBFind);\n PouchDB.plugin(StackPlugin(PouchDB, this, conn));\n // Validation plugin\n if (options?.plugins) {\n for (let plugin of options.plugins) {\n PouchDB.plugin(plugin);\n }\n }\n this.db = new PouchDB(\n conn,\n );\n this.cache = {\n // empty at init\n }\n this.jobEngine = new JobEngine(this);\n this.policyEngine = new PolicyEngine(this);\n this.cryptoEngine = new CryptoEngine(this);\n }\n\n /**\n * Returns the underlying PouchDB database instance.\n * @returns The PouchDB database\n */\n public getDb() {\n return this.db\n }\n\n /**\n * Retrieves information about the database including document count and update sequence.\n * @returns Database information object\n */\n public async getDbInfo() {\n return this.db.info();\n }\n\n /**\n * Returns the name of the underlying PouchDB database.\n * @returns The database name string\n */\n public getDbName() {\n return this.db.name;\n }\n\n /**\n * Checks if the crypto engine was disabled during stack initialization.\n * @returns `true` if encryption is disabled, `false` otherwise\n */\n public isCryptoEngineDisabled() {\n return this.cryptoEngineDisabled;\n }\n\n /**\n * Sets the current authentication session.\n * Called automatically by {@link authenticate}, but can be set manually for custom auth flows.\n * @param proof - The authentication session proof containing session and encryption keys\n */\n public setAuthSession(proof: AuthSessionProof) {\n this.authSession = proof;\n }\n\n /**\n * Clears the current authentication session and removes the document encryption key.\n * Call this when a user logs out.\n */\n public clearAuthSession() {\n this.authSession = undefined;\n this.cryptoEngine.setDocumentKey(null);\n }\n\n /**\n * Exports all documents from the database.\n * Useful for debugging or creating backups.\n * @returns All documents including their content\n */\n public dump = async () => {\n const all = await this.db.allDocs({ include_docs: true });\n return all;\n }\n\n private async ensureDefaultPolicyForClass(targetClass: ClassModel) {\n const fnLogger = logger.child({ method: \"ensureDefaultPolicyForClass\", targetClass: targetClass._id });\n const existingPolicy = await this.findDocument<PolicyModel>({\n \"~class\": { $eq: \"~Policy\" },\n targetClass: { $elemMatch: { $eq: targetClass._id } }\n });\n if (existingPolicy) {\n return;\n }\n\n const policyDoc: PolicyModel = {\n _id: `Policy-${targetClass._id}`,\n \"~class\": \"~Policy\",\n rule: \"return session && session.sessionStatus === 'active';\",\n description: `Default policy for ${targetClass.name || targetClass._id}`,\n targetClass: [targetClass._id],\n };\n\n fnLogger.info(\"Creating default policy\", { policyDoc });\n try {\n await this.db.bulkDocs([policyDoc as any]);\n } catch (error: any) {\n throw new Error(`Failed to create default policy for ${targetClass._id}: ${error?.message || error}`);\n }\n }\n\n /**\n * Creates and initializes a new ClientStack instance.\n * This is the primary way to instantiate a stack - the constructor is private.\n * \n * @param conn - The connection string or database name\n * @param options - Optional configuration including plugins, patches, and credentials\n * @returns A fully initialized ClientStack instance\n * \n * @example\n * ```typescript\n * // Basic initialization\n * const stack = await ClientStack.create('my-app-db');\n * \n * // With authentication\n * const stack = await ClientStack.create('my-app-db', {\n * credentials: { username: 'admin', password: 'secret' }\n * });\n * \n * // With custom patches\n * const stack = await ClientStack.create('my-app-db', {\n * patches: [myCustomPatch]\n * });\n * ```\n */\n public static async create(conn: string, options?: StackOptions): Promise<ClientStack> {\n const stack = new ClientStack();\n await stack.initialize(conn, options);\n await stack.initdb()\n if (options?.patches && options.patches.length) {\n const patches = await stack.findDocuments<Patch>({\n \"~class\": { $eq: \"patch\" }\n })\n for (const patch of options.patches.filter(\n p => !patches.docs.find(\n existing => existing.version === p.version\n && existing.target === p.target\n )\n )) {\n await stack.applyPatch(patch);\n }\n }\n if (options?.credentials) {\n await stack.authenticate(options.credentials);\n }\n return stack;\n }\n\n /**\n * Authenticates a user and establishes a session.\n * \n * This method:\n * 1. Looks up the user by username\n * 2. Executes the configured authentication job (e.g., password verification)\n * 3. Creates a new session document\n * 4. Sets up encryption keys for the session\n * \n * @param credentials - The user's login credentials containing username and password\n * @returns The authentication session proof containing session info and encryption keys\n * @throws Error if the user is not found or authentication fails\n * \n * @example\n * ```typescript\n * const proof = await stack.authenticate({\n * username: 'john.doe',\n * password: 'securePassword123'\n * });\n * console.log('Logged in as:', proof.session.username);\n * ```\n */\n public async authenticate(credentials: ClientCredentials) {\n const { username, password } = credentials;\n const userQuery = await this.db.find({\n selector: {\n \"~class\": { $eq: \"~User\" },\n username: { $eq: username },\n active: { $eq: true }\n }\n });\n const user = userQuery.docs.length ? userQuery.docs[0] as unknown as UserModel : null;\n\n if (!user) {\n throw new Error(`User '${username}' not found`);\n }\n\n const authModuleId = user.authMethod || \"AuthMod-Classic\";\n const authModule = await this.db.get<AuthModuleModel>(authModuleId);\n const jobId = authModule.jobId;\n const run = await this.jobEngine.executeJob(jobId, {\n password,\n salt: user.keyDerivationSalt,\n keyDerivationSalt: user.keyDerivationSalt,\n });\n\n const derivedKey = (run.finalMetadata as any)?.derivedKey ?? (run.initialMetadata as any)?.derivedKey;\n const userGroups = Array.isArray((user as any).groupId)\n ? (user as any).groupId\n : (user as any).groupId\n ? [(user as any).groupId]\n : [\"Group-Default\"];\n const randomBytes = new Uint8Array(8);\n globalThis.crypto.getRandomValues(randomBytes);\n const hexId = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');\n const sessionId = `session-${globalThis.crypto.randomUUID ? globalThis.crypto.randomUUID() : hexId}`;\n const sessionDoc: UserSessionModel = {\n _id: sessionId,\n \"~class\": \"~UserSession\",\n userId: user._id || user.username,\n groupId: userGroups,\n username: user.username,\n sessionId,\n sessionStart: new Date().toISOString(),\n sessionStatus: \"active\",\n };\n\n const sessionClassModel = (await this.getClassModel(\"~UserSession\")) || (await this.getClassModel(\"UserSession\"));\n const sessionSchema = sessionClassModel?.schema || {};\n await this.createDoc(sessionDoc._id, sessionDoc[\"~class\"], sessionSchema, sessionDoc);\n // TODO: Initially the wrappedDocumentKey is missing for the system user,\n // perhaps the documentKey hasn't been set yet? \n const documentKey = await this.cryptoEngine.unwrapAndStoreDocumentKey(user.wrappedDocumentKey, derivedKey);\n\n const proof: AuthSessionProof = { session: sessionDoc, derivedKey, documentKey: documentKey ?? undefined };\n this.setAuthSession(proof);\n await this.ensureCryptoMarkerEncryption();\n return proof;\n }\n\n async getLastDocId() {\n let lastDocId = 0;\n try {\n let doc: { value: number, [key: string]: string | number } = await this.db.get(\"lastDocId\");\n lastDocId = doc.value;\n } catch (e: any) {\n if (e.name === 'not_found') {\n logger.info(\"getLastDocId - not found. Must be first initialization.\")\n return lastDocId\n }\n logger.error(\"checkdb - something went wrong\", { \"error\": e });\n }\n return lastDocId;\n }\n\n async getSystem() {\n try {\n let doc = await this.db.get(\"~system\") as SystemDoc;\n return doc;\n } catch (e: any) {\n if (e.name === 'not_found') {\n logger.info(\"get System - not found\", e)\n return null;\n }\n logger.error(\"getSystem - something went wrong\", { \"error\": e });\n throw new Error(e);\n }\n }\n\n private async loadPatches(schemaVersion: string | undefined): Promise<Patch[]> {\n const fnLogger = logger.child({ method: \"loadPatches\" });\n try {\n fnLogger.info(\"loadPatches - loading patches\");\n const patches = await getSystemPatches(schemaVersion || \"0.0.0\");\n fnLogger.warn(`loadPatches - loaded ${patches.length} patches`);\n return patches;\n } catch (e: any) {\n fnLogger.error(\"loadPatches - something went wrong\", e)\n throw new Error(e);\n }\n }\n\n applyPatch = async (patch: Patch): Promise<string> => {\n const fnLogger = logger.child({ method: \"applyPatch\", args: { patch } });\n return new Promise<string>(async (resolve, reject) => {\n try {\n fnLogger.info(\"Attempting to apply patch\", { patch })\n fnLogger.info(\"applyPatch - starting to hydrate patch docs\", { docCount: patch.docs.length });\n const hydratedDocs = await Promise.all(patch.docs.map(async doc => {\n if (doc._rev === \"auto\") {\n delete doc._rev;\n const existingDoc = await this.db.get(doc._id);\n if (existingDoc) {\n doc = { ...existingDoc, ...doc };\n }\n }\n return doc;\n }));\n fnLogger.info(\"applyPatch - hydration complete, calling bulkDocs\", { docCount: hydratedDocs.length });\n await this.db.bulkDocs(hydratedDocs, { isPatch: true } as PouchDB.Core.BulkDocsOptions).then((result) => {\n fnLogger.warn(\"applyPatch - bulkDocs completed with result\", { result });\n fnLogger.warn(\"Successfully processed patch\", { version: patch.version });\n }).catch((error) => {\n fnLogger.error(\"applyPatch - bulkDocs error\", { error });\n reject(error);\n });\n // Store patch itself\n await this.db.post({createTimestamp: (new Date()).valueOf(), ...patch});\n fnLogger.info(\"Successfully stored patch\", { version: patch.version, target: patch.target });\n resolve(patch.version);\n } catch (e: any) {\n fnLogger.error(\"Failed to apply patch\", e)\n reject(new Error(e));\n }\n });\n }\n\n private async applyPatches(schemaVersion: string | undefined): Promise<string> {\n const fnLogger = logger.child({ method: \"applyPatches\", args: { schemaVersion } });\n let _schemaVersion = schemaVersion;\n try {\n const patches = await this.loadPatches(_schemaVersion);\n for (let patch of patches) {\n _schemaVersion = await this.applyPatch(patch);\n }\n if (_schemaVersion) {\n fnLogger.warn(\"Successfully applied patches till version\", { version: _schemaVersion });\n this.schemaVersion = _schemaVersion;\n return _schemaVersion!;\n } else {\n fnLogger.info(\"No patches were provided or applied\");\n throw new Error(\"applyPatches - No patches were provided or applied\");\n }\n } catch (e: any) {\n fnLogger.error(\"Something went wrong\", e);\n throw new Error(e);\n }\n }\n\n // Method that verifies wether the system information are updated\n // applies patches too\n // TODO: Test if works corrrectly with multiple patch files\n async checkSystem() {\n let systemDoc = await this.getSystem();\n let _systemDoc: SystemDoc;\n const dbInfo = await this.getDbInfo();\n logger.info(\"checkSystem - current system doc\", { system: systemDoc })\n if (!systemDoc) {\n _systemDoc = {\n _id: \"~system\",\n appVersion: this.appVersion,\n dbInfo: dbInfo,\n schemaVersion: undefined,\n startupTime: (new Date()).valueOf()\n }\n // schemaVersion will be added after applying patches\n let schemaVersion = await this.applyPatches(_systemDoc.schemaVersion);\n console.log(\"Applied patches, new schema version:\", schemaVersion);\n _systemDoc.schemaVersion = schemaVersion;\n } else {\n logger.info(\"checkSystem - system doc already exists. Checking for updates\", systemDoc)\n // apply patches if needed\n let schemaVersion = await this.applyPatches(systemDoc.schemaVersion);\n _systemDoc = {\n ...systemDoc,\n appVersion: this.appVersion,\n dbInfo: dbInfo,\n schemaVersion: schemaVersion,\n startupTime: (new Date()).valueOf()\n }\n }\n // Update systemDoc\n try {\n await this.db.put(_systemDoc);\n\n } catch (e: any) {\n logger.error(\"checkSystem - There was a problem while updating system\", { error: e })\n throw new Error(e)\n }\n logger.info(\"checkSystem - updated system\", { system: _systemDoc })\n }\n\n setListeners = () => {\n const fnLogger = logger.child({ method: \"setListeners\" });\n\n // Listening for class model propagation\n this.addEventListener('class-model-propagation-pending', this.onClassModelPropagationStart as EventListener);\n this.addEventListener('class-model-propagation-complete', this.onClassModelPropagationComplete as EventListener);\n\n // fnLogger.info(\"Setting up class model worker\");\n // this.modelWorker = new Worker(require(\"../workers/dataModel\"), {type: \"module\"});\n\n fnLogger.info(\"Setting up class model changes listener\");\n const classModelChanges = this.onClassModelChanges();\n\n /*\n this.modelWorker.onmessage = (event) => {\n const { status, className, message } = event.data;\n \n this.dispatchEvent(new CustomEvent('class-model-propagation-complete', {\n detail: { className: className, success: status === 'success', message }\n }));\n\n if (status === 'error') {\n fnLogger.error(`Model worker error for class '${className}': ${message}`);\n }\n };\n */\n\n // Store listener for later\n this.listeners.push(classModelChanges);\n }\n\n /**\n * @description Clears all listeners from the Stack\n */\n removeAllListeners = () => {\n this.removeEventListener('class-model-propagation-pending', this.onClassModelPropagationStart as EventListener);\n this.removeEventListener('class-model-propagation-complete', this.onClassModelPropagationComplete as EventListener);\n\n if (this.listeners.length > 0) {\n for (const listener of this.listeners) {\n if (listener && typeof listener.cancel === 'function') {\n try {\n listener.cancel();\n } catch (error) {\n logger.warn('Error while cancelling listener', { error });\n }\n }\n }\n this.listeners = [];\n }\n }\n\n /**\n * @description When a class model propagation starts write the ~lock document to the database.\n * It prevents any further modifications on the class data model\n * @param event\n */\n onClassModelPropagationStart = (event: CustomEvent<ClassModelPropagationStart>) => {\n const className = event.detail.className;\n const fnLogger = logger.child({ method: \"onClassModelPropagationStart\", className });\n this.addClassLock(className).then(() => {\n fnLogger.info(`Lock created successfully for class: '${className}'`);\n }).catch(error => {\n fnLogger.error(`Error creating lock for '${className}': ${error}`);\n });\n }\n\n /**\n * @description When a class model propagation comes to completion remove the corresponding \n * ~lock from the database\n * @param event \n */\n onClassModelPropagationComplete = (event: CustomEvent<ClassModelPropagationComplete>) => {\n const fnLogger = logger.child({ method: \"onClassModelPropagationComplete\", args: { event } });\n const className = event.detail.className;\n this.clearClassLock(className).then(() => {\n fnLogger.info(`Lock removed successfully for class: '${className}'`);\n }).catch(error => {\n fnLogger.error(`Error removing lock for '${className}': ${error}`);\n });;\n }\n\n /**\n * @returns PouchDB.Core.Changes<{}>\n */\n onClassModelChanges = () => {\n const fnLogger = logger.child({ listener: \"classModelChanges\" });\n\n const classModelChanges = this.db.changes({\n since: 'now',\n live: true,\n include_docs: true,\n filter: (doc) => {\n return doc[\"~class\"] == \"class\";\n }\n }).on(\"change\", async (change) => {\n const doc = change.doc;\n if (doc && isClassModel(doc) && doc.active) {\n const className = doc.name;\n // Invalidate cached version if present\n fnLogger.info(`Class model was updated. Clearing '${className}' from cache.`);\n delete this.cache[className];\n fnLogger.info(`Successfully cleared '${className}' from cache.`);\n } else if (doc && isClassModel(doc) && !doc.active) {\n const className = doc.name;\n fnLogger.info(`Class was deleted. Removing from '${className} from cache.'`);\n } // else\n });\n\n return classModelChanges;\n }\n\n onClassLock = (className: string) => {\n const classLockListener = this.db.changes({\n since: 'now',\n live: true,\n include_docs: true,\n filter: (doc) => {\n return doc[\"~class\"] == \"~lock\" && doc._id == `~lock-propagation-${className}`;\n }\n });\n this.listeners.push(classLockListener);\n return classLockListener;\n }\n\n addClassLock = async (className: string) => {\n const fnLogger = logger.child({ method: \"addClassLock\", args: { className } });\n try {\n const existing = await this.db.get(`~lock-propagation-${className}`);\n let _rev: string | undefined = undefined;\n if (existing) {\n _rev = existing._rev;\n }\n const response = await this.db.put({\n _id: `~lock-propagation-${className}`,\n \"~class\": `~Lock`,\n _rev\n });\n fnLogger.info(`Adding class lock response`, { response });\n return response.ok;\n } catch (e: any) {\n fnLogger.error(`Error while adding class lock: ${e}`);\n return false;\n }\n }\n\n clearClassLock = async (className: string) => {\n const fnLogger = logger.child({ method: \"clearClassLock\", args: { className } });\n try {\n const doc = await this.db.get(`~lock-propagation-${className}`);\n fnLogger.info(`Fetched class lock`, { document: doc });\n const response = await this.db.remove(doc);\n fnLogger.info(`Removing class lock response`, { response });\n return response.ok;\n } catch (e: any) {\n fnLogger.error(`Error while adding class lock: ${e}`);\n return false;\n }\n }\n\n onClassDoc = (className: string) => {\n const onClassDocListener = this.db.changes({\n since: 'now',\n live: true,\n include_docs: true,\n filter: (doc) => {\n return doc[\"~class\"] == className;\n }\n });\n this.listeners.push(onClassDocListener);\n return onClassDocListener;\n }\n\n // Database initialization should be about making sure that all the documents\n // representing the base data model for this framework are present\n // perform tasks like applying patches, creating indexes, etc.\n async initdb() {\n logger.warn(\"initdb - starting initialization\", { \"stackName\": this.name });\n await this.ensureCryptoConfigDocument();\n logger.warn(\"initdb - crypto config ensured\", { \"stackName\": this.name });\n await this.initIndex();\n logger.warn(\"initdb - index initialized\", { \"stackName\": this.name });\n await this.checkSystem();\n logger.warn(\"initdb - system checked\", { \"stackName\": this.name });\n this.setListeners();\n logger.warn(\"initdb - listeners set, initialization complete\", { \"stackName\": this.name });\n return this;\n }\n\n private async ensureCryptoConfigDocument() {\n const markerId = ClientStack.CRYPTO_CONFIG_DOC_ID;\n const existing = await this.db.get<{ cryptoEngineDisabled?: boolean; encryptedMarker?: unknown }>(markerId).catch((error: any) => {\n if (error?.name === \"not_found\" || error?.status === 404) return null;\n throw error;\n });\n\n if (!this.cryptoEngineDisabled && !this.cryptoEngine.getDocumentKey()) {\n const randomBytes = new Uint8Array(32);\n globalThis.crypto.getRandomValues(randomBytes);\n const documentKey = Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join('');\n await this.cryptoEngine.setDocumentKey(documentKey);\n logger.info(\"Initialized new document key\");\n }\n\n if (existing) {\n this.validateCryptoConfig(existing);\n return existing;\n }\n\n const markerDoc: PouchDB.Core.PutDocument<Record<string, unknown>> = {\n _id: markerId,\n cryptoEngineDisabled: this.cryptoEngineDisabled,\n createdAt: new Date().toISOString(),\n };\n\n if (!this.cryptoEngineDisabled) {\n const randomBytes = new Uint8Array(12);\n globalThis.crypto.getRandomValues(randomBytes);\n const encryptedMarker = await this.cryptoEngine.encryptValueForMarker({\n nonce: Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join(''),\n });\n if (encryptedMarker) {\n (markerDoc as any).encryptedMarker = encryptedMarker;\n }\n }\n\n try {\n await this.db.put(markerDoc as any);\n return markerDoc;\n } catch (error: any) {\n if (error?.status === 409 || error?.name === \"conflict\") {\n const current = await this.db.get<{ cryptoEngineDisabled?: boolean; encryptedMarker?: unknown }>(markerId);\n this.validateCryptoConfig(current);\n return current;\n }\n throw error;\n }\n }\n\n private async ensureCryptoMarkerEncryption() {\n if (this.cryptoEngineDisabled || !this.cryptoEngine.isEnabled()) return;\n\n const markerId = ClientStack.CRYPTO_CONFIG_DOC_ID;\n const markerDoc = await this.db.get<{ encryptedMarker?: unknown }>(markerId).catch((error: any) => {\n if (error?.name === \"not_found\" || error?.status === 404) return null;\n throw error;\n });\n\n if (!markerDoc || isEncryptedPayload((markerDoc as any).encryptedMarker)) return;\n\n const randomBytes = new Uint8Array(12);\n globalThis.crypto.getRandomValues(randomBytes);\n const encryptedMarker = await this.cryptoEngine.encryptValueForMarker({\n nonce: Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join(''),\n });\n\n if (!encryptedMarker) return;\n\n (markerDoc as any).encryptedMarker = encryptedMarker;\n await this.db.put(markerDoc as any);\n }\n\n private validateCryptoConfig(existing: { cryptoEngineDisabled?: boolean; encryptedMarker?: unknown }) {\n const storedDisabled = Boolean(existing.cryptoEngineDisabled);\n if (storedDisabled !== this.cryptoEngineDisabled) {\n throw new Error(\n storedDisabled\n ? \"Stack was initialized with crypto engine disabled; re-open it with disableCryptoEngine set to true.\"\n : \"Stack requires the crypto engine; remove disableCryptoEngine to continue.\"\n );\n }\n\n if (!storedDisabled && isEncryptedPayload((existing as any).encryptedMarker) && !this.cryptoEngine.isEnabled()) {\n throw new Error(\"Crypto engine must be enabled to access this stack because it contains encrypted data.\");\n }\n }\n\n /**\n * Closes the stack and cleans up all resources.\n * Removes event listeners and terminates background workers.\n */\n close = () => {\n this.removeAllListeners();\n if (this.modelWorker) this.modelWorker.terminate();\n }\n\n /**\n * Retrieves a Class instance by name.\n * Results are cached for 15 minutes to improve performance.\n * \n * @param className - The name or ID of the class to retrieve\n * @param fresh - If `true`, bypasses the cache and fetches from database\n * @returns The Class instance, or `null` if not found\n * \n * @example\n * ```typescript\n * const taskClass = await stack.getClass('Task');\n * if (taskClass) {\n * const tasks = await taskClass.getCards();\n * }\n * ```\n */\n getClass = async (className: string, fresh = false): Promise<Class | null> => {\n const fnLogger = logger.child({ method: \"getClass\", args: { className, fresh } });\n if (!fresh) {\n // Check if class is in cache and not expired\n if (this.cache[className] && this.cache[className] instanceof Class && Date.now() < this.cache[className].ttl) {\n fnLogger.info(\"Retrieving class from cache\", { ttl: this.cache[className].ttl })\n return this.cache[className] as Class;\n }\n }\n\n const classObj = await Class.fetch(this, className);\n if (classObj) {\n (classObj as unknown as CachedClass).ttl = Date.now() + 60000 * 15; // 15 minutes expiration\n this.cache[className] = classObj as unknown as CachedClass;\n }\n return classObj;\n }\n\n /**\n * Retrieves a Domain instance by name.\n * Results are cached for 15 minutes to improve performance.\n * \n * @param domainName - The name or ID of the domain to retrieve\n * @param fresh - If `true`, bypasses the cache and fetches from database\n * @returns The Domain instance, or `null` if not found\n */\n getDomain = async (domainName: string, fresh = false): Promise<Domain | null> => {\n const fnLogger = logger.child({ method: \"getDomain\", args: { domainName, fresh } });\n if (!fresh) {\n if (this.cache[domainName] && Date.now() < this.cache[domainName].ttl) {\n fnLogger.info(\"Retrieving domain from cache\", { ttl: this.cache[domainName].ttl });\n return this.cache[domainName] as Domain;\n }\n }\n\n const domainObj = await Domain.fetch(this, domainName);\n if (domainObj) {\n (domainObj as CachedDomain).ttl = Date.now() + 60000 * 15; // 15 minutes expiration\n this.cache[domainName] = domainObj as CachedDomain;\n }\n return domainObj;\n }\n\n async initIndex() {\n try {\n let lastDocId: number = await this.getLastDocId();\n // logger.info(\"initdb - res\", res)\n if (!lastDocId) {\n lastDocId = Number(lastDocId);\n // logger.info(\"initdb - initializing db\")\n try {\n let response = await this.db.put({\n _id: \"lastDocId\",\n value: ++lastDocId\n });\n if (response.ok) this.lastDocId = lastDocId;\n else throw new Error(\"Got problem while putting doc\" + response);\n } catch (error: any) {\n if (error?.status === 409 || error?.name === \"conflict\") {\n const existing = await this.db.get<{ value: number }>(\"lastDocId\");\n this.lastDocId = Number(existing.value);\n return;\n }\n throw error;\n }\n } else {\n logger.info(\"initdb - db already initialized, consider purge\")\n }\n this.lastDocId = Number(lastDocId);\n } catch (e: any) {\n logger.error(\"initdb - something went wrong\", e)\n throw new Error(e);\n }\n }\n\n // static async build( that: ClientStack ) {\n // let result = await that.initdb();\n // return result;\n // }\n\n /**\n * Retrieves a single document by its ID.\n * \n * @typeParam T - The expected document type\n * @param docId - The document ID to retrieve\n * @returns The document, or `null` if not found\n * \n * @example\n * ```typescript\n * const task = await stack.getDocument<TaskDocument>('Task-123');\n * if (task) {\n * console.log(task.title);\n * }\n * ```\n */\n async getDocument<T extends Document>(docId: string) {\n let doc: PouchDB.Core.ExistingDocument<T> | undefined = undefined;\n try {\n doc = await this.db.get<T>(docId);\n } catch (e: any) {\n if (e.name === 'not_found') {\n logger.info(\"getDocument - not found\", e)\n return null;\n }\n logger.info(\"getDocument - error\", e)\n throw new Error(e);\n }\n return doc;\n }\n\n async getDocRevision(docId: string) {\n let _rev: string | null = null;\n try {\n let doc = await this.getDocument(docId);\n if (doc) _rev = doc._rev;\n } catch (e: any) {\n logger.info(\"getDocRevision - error\", e)\n throw new Error(e);\n }\n return _rev;\n }\n\n /**\n * Finds multiple documents matching a PouchDB/Mango-style selector.\n * Automatically filters to only active documents and applies access policies.\n * \n * @typeParam T - The expected document type\n * @param selector - A PouchDB/Mango query selector\n * @param fields - Optional list of fields to return\n * @param skip - Number of documents to skip (for pagination)\n * @param limit - Maximum number of documents to return\n * @returns Object containing matching documents array\n * \n * @example\n * ```typescript\n * const result = await stack.findDocuments({\n * '~class': { $eq: 'Task' },\n * isComplete: { $eq: false }\n * });\n * console.log('Found tasks:', result.docs.length);\n * ```\n */\n findDocuments = async <T extends Document | RelationDocument = Document>(selector: { [key: string]: any }, fields?: string[], skip?: number, limit?: number) => {\n const fnLogger = logger.child({ method: \"findDocuments\", args: { selector, fields, skip, limit } });\n\n // By default request for only active documents\n if (!selector.hasOwnProperty(\"active\")) {\n selector[\"active\"] = true;\n }\n\n let indexFields = Object.keys(selector);\n fnLogger.info(\"Produced index fields from selector\", { indexFields });\n\n let result: {\n docs: T[],\n [key: string]: any\n } = {\n docs: []\n }\n\n try {\n // [TODO] This breaks find method and even db!!\n // let indexResult = await this.db.createIndex({\n // index: { fields: indexFields }\n // });\n // fnLogger.info(\"Index result\", indexResult);\n\n let foundResult = await this.db.find({\n selector: selector,\n fields: fields,\n skip: skip,\n limit: limit\n });\n if (selector.hasOwnProperty(\"username\")) {\n console.log(\"Found result\", { result: foundResult, selector })\n }\n\n fnLogger.info(\"Found\", {\n result: foundResult,\n selector: selector,\n });\n const readableDocs: T[] = [];\n for (const doc of foundResult.docs as unknown as Document[]) {\n const canRead = await this.policyEngine.isReadableDocument(doc);\n if (!canRead) {\n fnLogger.info(\"Based on policies, document is not readable\", { docId: doc._id, docClass: doc[\"~class\"] });\n console.log(\"Based on policies, document is not readable\", { docId: doc._id, docClass: doc[\"~class\"] });\n continue;\n }\n\n const encryptedKeys = this.cryptoEngine.identifyEncryptedKeys(doc as Document);\n const classObj = encryptedKeys.length || (fields && fields.length)\n ? (await this.getClass(doc[\"~class\"], true)) ?? undefined\n : undefined;\n\n const processedDoc = await this.processReadableDocument(doc as Document, classObj, fields, encryptedKeys);\n if (processedDoc) {\n readableDocs.push(processedDoc as unknown as T);\n }\n }\n\n result = { docs: readableDocs, selector, skip, limit };\n return result;\n } catch (e: any) {\n fnLogger.error(\"findDocument - error\", e);\n throw e;\n }\n }\n\n private async processReadableDocument(doc: Document, classObj?: Class, fields?: string[], precomputedEncryptedKeys?: string[]) {\n if (!this.cryptoEngine.isEnabled()) {\n return doc;\n }\n\n const encryptedKeys = precomputedEncryptedKeys ?? this.cryptoEngine.identifyEncryptedKeys(doc, classObj);\n if (!encryptedKeys.length && (!fields || !fields.length)) {\n return doc;\n }\n\n const clone: Document = { ...doc } as Document;\n const hasDocumentKey = Boolean(this.cryptoEngine.getDocumentKey());\n\n if (hasDocumentKey && encryptedKeys.length) {\n await this.cryptoEngine.decryptDocument(clone, classObj, encryptedKeys);\n } else if (encryptedKeys.length) {\n for (const key of encryptedKeys) {\n if ((clone as any)[key] !== undefined) {\n (clone as any)[key] = null;\n }\n }\n }\n\n const encryptedKeySet = new Set(encryptedKeys);\n const visibleKeys = Object.keys(clone).filter((key) => {\n if (key === \"_id\" || key === \"_rev\" || key === \"~rev\" || key === \"~class\" || key === \"active\" || key === \"~createTimestamp\" || key === \"~updateTimestamp\" || key === \"description\") {\n return false;\n }\n if (fields && fields.length) {\n return fields.includes(key) && (clone as any)[key] !== undefined;\n }\n return (clone as any)[key] !== undefined;\n });\n\n if (!hasDocumentKey && encryptedKeySet.size) {\n const nonEncryptedVisible = visibleKeys.filter((key) => !encryptedKeySet.has(key));\n if (!nonEncryptedVisible.length) {\n return null;\n }\n }\n\n if (!visibleKeys.length) {\n return null;\n }\n\n return clone;\n }\n\n /**\n * Finds a single document matching a selector.\n * Convenience wrapper around {@link findDocuments} that returns the first match.\n * \n * @typeParam T - The expected document type\n * @param selector - A PouchDB/Mango query selector\n * @param fields - Optional list of fields to return\n * @param skip - Number of documents to skip\n * @param limit - Maximum number of documents to check\n * @returns The first matching document, or `null` if none found\n */\n async findDocument<T extends Document | RelationDocument = Document>(selector: any, fields = undefined, skip = undefined, limit = undefined) {\n let result = await this.findDocuments<T>(selector, fields, skip, limit);\n return result.docs.length > 0 ? result.docs[0] : null;\n }\n\n getClassModel = async (className: string) => {\n // TODO: understand whether to use name of _id field\n let selector = {\n $or: [\n { name: { $eq: className } },\n { _id: { $eq: className } }\n ],\n // _id: { $eq: className },\n \"~class\": { $in: [\"class\", \"~self\"] }\n };\n\n try {\n let response = await this.db.find({ selector });\n if (response == null) return null;\n let result: ClassModel = response.docs[0] as unknown as ClassModel\n logger.info(\"getClassModel - result\", { result: result })\n return result;\n } catch (e: any) {\n logger.info(\"getClassModel - error\", e)\n throw new Error(e)\n }\n }\n\n getDomainModel = async (domainName: string) => {\n let selector = {\n \"~class\": { $eq: \"domain\" },\n name: { $eq: domainName }\n };\n\n try {\n let response = await this.findDocument(selector);\n if (response == null) return null;\n let result: DomainModel = response as DomainModel\n logger.info(\"getDomainModel - result\", { result: result })\n return result;\n } catch (e: any) {\n logger.info(\"getDomainModel - error\", e)\n throw new Error(e)\n }\n }\n\n // TODO: move listener to stack field, for easier un-registering\n // TODO: Change into getClass(\"Class\").getCards()\n getClassModels = async (conf: { listen?: boolean, filter?: string[], search?: string } = {}) => {\n const { listen, filter, search } = conf;\n const selector: { [field: string]: object } = { \"~class\": { $eq: \"class\" } };\n if (Array.isArray(filter) && filter.length > 0) {\n // TODO: Consider checking against name field instead of _id\n selector._id = { $in: filter };\n }\n\n // Case 2: A search query (partial match)\n else if (search && typeof search === 'string') {\n // Mango doesn’t have full regex support, so we use $regex via the pouchdb-find plugin.\n selector.$or = [\n { _id: { $regex: RegExp(search, \"i\") } },\n { name: { $regex: RegExp(search, \"i\") } },\n { description: { $regex: RegExp(search, \"i\") } }\n ];\n }\n const fields = ['_id', 'name', 'description', 'schema', '~class', '_rev'];\n\n const response = await this.findDocuments(selector, fields);\n const result: ClassModel[] = response.docs as ClassModel[];\n\n if (!conf.listen) {\n return { list: result };\n }\n\n // Create a live listener via PouchDB changes feed\n const listener = this.db.changes({\n since: 'now',\n live: true,\n include_docs: true,\n selector\n });\n\n this.listeners.push(listener);\n\n return {\n list: result,\n listener\n };\n }\n\n getClasses = async (conf: { filter?: string[], search?: string }) => {\n const classNames = conf.filter;\n const searchFilter = conf.search;\n const fnLogger = logger.child({ method: \"getClasses\" });\n fnLogger.info(\"Requesting\");\n\n const { list: classModels, listener } = await this.getClassModels({\n listen: true, filter: classNames, search: searchFilter\n });\n fnLogger.info(\"Received class models\", { classModels });\n\n const classList: Class[] = [];\n\n // Get current class list\n for (const classModel of classModels) {\n fnLogger.info(`Building class \"${classModel.name}\"`);\n const classObj = await Class.buildFromModel(this, classModel);\n classList.push(classObj);\n }\n\n // Queue for occasional addition/deletion\n if (listener) {\n listener.on(\"change\", async (change) => {\n if (!change.deleted) {\n const className = change.id;\n fnLogger.info(`Received class model change with \"${className}\"`);\n const existingIndex = classList.findIndex(c => c.model._id === className);\n const classObj = await Class.buildFromModel(this, change.doc as ClassModel);\n if (existingIndex === -1) {\n classList.push(classObj);\n } else {\n classList[existingIndex] = classObj;\n }\n const evt = new CustomEvent(\"classListChange\", { detail: classList });\n this.dispatchEvent(evt);\n } else {\n // remove from classList without altering the array reference\n const idx = classList.findIndex(c => c.model._id === change.id);\n if (idx !== -1) {\n classList.splice(idx, 1);\n const evt = new CustomEvent(\"classListChange\", { detail: classList });\n this.dispatchEvent(evt);\n }\n }\n })\n }\n\n fnLogger.info(\"Completed inital classes build\");\n\n return classList;\n };\n\n getDomainModels = async (conf: { listen?: boolean, filter?: string[], search?: string } = {}) => {\n const { listen, filter, search } = conf;\n const selector: { [field: string]: object } = { \"~class\": { $eq: \"domain\" } };\n if (Array.isArray(filter) && filter.length > 0) {\n // TODO: Consider checking against name field instead of _id\n selector._id = { $in: filter };\n }\n\n // Case 2: A search query (partial match)\n else if (search && typeof search === 'string') {\n // Mango doesn’t have full regex support, so we use $regex via the pouchdb-find plugin.\n selector.$or = [\n { _id: { $regex: RegExp(search, \"i\") } },\n { name: { $regex: RegExp(search, \"i\") } },\n { description: { $regex: RegExp(search, \"i\") } }\n ];\n }\n const fields = ['_id', 'name', 'description', 'schema', '~class', '_rev'];\n\n const response = await this.findDocuments(selector, fields);\n const result: DomainModel[] = response.docs as DomainModel[];\n\n if (!conf.listen) {\n return { list: result };\n }\n\n // Create a live listener via PouchDB changes feed\n const listener = this.db.changes({\n since: 'now',\n live: true,\n include_docs: true,\n selector\n });\n\n return {\n list: result,\n listener\n };\n }\n\n getDomains = async (conf: { filter?: string[], search?: string }) => {\n const classNames = conf.filter;\n const searchFilter = conf.search;\n const fnLogger = logger.child({ method: \"getDomains\" });\n fnLogger.info(\"Requesting\");\n\n const { list: domainModels, listener } = await this.getDomainModels({\n listen: true, filter: classNames, search: searchFilter\n });\n fnLogger.info(\"Received class models\", { domainModels });\n\n const domainList: Domain[] = [];\n\n // Get current class list\n for (const domainModel of domainModels) {\n fnLogger.info(`Building class \"${domainModel.name}\"`);\n const domain = await Domain.buildFromModel(this, domainModel);\n domainList.push(domain);\n }\n\n // Queue for occasional addition/deletion\n if (listener) {\n listener.on(\"change\", async (change) => {\n if (!change.deleted) {\n const domainName = change.id;\n fnLogger.info(`Received class model change with \"${domainName}\"`);\n const existingIndex = domainList.findIndex(c => c.model._id === domainName);\n const domain = await Domain.buildFromModel(this, change.doc as DomainModel);\n if (existingIndex === -1) {\n domainList.push(domain);\n } else {\n domainList[existingIndex] = domain;\n }\n const evt = new CustomEvent(\"domainListChange\", { detail: domainList });\n this.dispatchEvent(evt);\n } else {\n // remove from classList without altering the array reference\n const idx = domainList.findIndex(c => c.model._id === change.id);\n if (idx !== -1) {\n domainList.splice(idx, 1);\n const evt = new CustomEvent(\"domainListChange\", { detail: domainList });\n this.dispatchEvent(evt);\n }\n }\n })\n }\n\n fnLogger.info(\"Completed inital domains build\");\n\n return domainList;\n };\n\n async incrementLastDocId() {\n let docId = \"lastDocId\",\n _rev = await this.getDocRevision(docId);\n\n if (_rev) {\n await this.db.put({\n _id: \"lastDocId\",\n _rev: _rev,\n value: ++this.lastDocId\n });\n return this.lastDocId;\n }\n // throw new Error\n\n }\n\n // The idea of this method is to be called from within the server (like CLI command)\n // \n async reset() {\n await this.destroyDb();\n // wait a few seconds\n await new Promise((resolve) => setTimeout(resolve, 2000));\n await this.initialize(\n this.connection, this.options\n );\n await this.initdb()\n return this;\n }\n\n async destroyDb() {\n const fnLogger = logger.child({ method: \"destroyDb\" });\n try {\n this.db.destroy(null, () => {\n fnLogger.info(\"Destroyed db\");\n return true;\n });\n } catch (e: any) {\n fnLogger.error(`Error while destroying db: ${e}`);\n return false;\n }\n }\n\n // This method is similar to destroyDb, but intended to be called from the client (not to destroy the main db)\n // TODO: Right now this allows to clear any db\n // there should be more restrictions\n static async clear(conn: string) {\n return new Promise((resolve, reject) => {\n try {\n let db = new PouchDB(conn)\n db.destroy(null, () => {\n logger.info(\"clear - Destroyed db\");\n resolve(true);\n });\n } catch (e: any) {\n logger.error(\"clear - Error while destroying db\" + e)\n reject(false)\n }\n })\n }\n\n addClass = async (classObj: Class) => {\n const fnLogger = logger.child({ method: \"addClass\", args: { class: classObj.name } });\n const classOrigin = await this.getClass(classObj.type);\n if (classOrigin == null) {\n fnLogger.error(\"Class originator not found\", { classType: classObj.type });\n throw new Error(`Class originator ${classObj.type} not found in stack`);\n }\n let classModel = classObj.getModel();\n fnLogger.info(\"Got class model\", { classModel })\n try {\n const result = await classOrigin.addCard(classModel) as ClassModel;\n fnLogger.info(\"Added class card\", { result });\n await this.ensureDefaultPolicyForClass(result);\n return result;\n } catch (e) {\n fnLogger.error(\"Error adding class card\", { error: e })\n const message = (e as Error)?.message || \"Failed to add class card\";\n throw new Error(message)\n }\n // let existingDoc = await this.getClassModel(classModel.name);\n // if ( existingDoc == null ) {\n // let resultDoc = await this.createDoc(classModel.name, 'class', CLASS_SCHEMA, classModel);\n // fnLogger.info(\"Result\", {result: resultDoc});\n // // TODO: Consider creating a design doc for easier filtering\n // return resultDoc as ClassModel;\n // } else {\n // return existingDoc;\n // } \n }\n\n addDomain = async (domainObj: Domain) => {\n const fnLogger = logger.child({ method: \"addDomain\", args: { domain: domainObj.name } });\n let domainModel = domainObj.getModel();\n fnLogger.info(\"Got domain model\", { domainModel })\n let existingDoc = await this.getDomainModel(domainModel.name);\n if (existingDoc == null) {\n let resultDoc = await this.createDoc(domainModel.name, 'domain', DOMAIN_SCHEMA, domainModel);\n fnLogger.info(\"Result\", { result: resultDoc });\n // TODO: Consider creating a design doc for easier filtering\n return resultDoc as DomainModel;\n } else {\n return existingDoc;\n }\n }\n\n updateClass = async (classObj: Class) => {\n const fnLogger = logger.child({ method: \"updateClass\", args: { class: classObj.name } });\n let result = await this.createDoc(classObj.getId()!, 'class', classObj, classObj.getModel());\n fnLogger.info(\"Result\", result)\n return result\n }\n\n addDesignDocumentPKs = async (className: string, pKs: string[], temp = false) => {\n const fnLogger = logger.child({ method: 'addDesignDocumentPKs', args: { className, pKs } });\n // Construct the compound key string dynamically\n const keyString = pKs.map(key => `doc.${key}`).join(', ');\n\n // The 'map' function as a string\n const mapCode = `function (doc) {\n const hasAllKeys = ${pKs.map(key => `doc.${key}`).join(' && ')};\n if (hasAllKeys && doc[\"~class\"] === '${className}') {\n emit([${keyString}], doc._id);\n }\n }`;\n fnLogger.info(\"Generated map code\", { code: mapCode });\n\n let designDocId = `_design/${className}-group`;\n if (temp) designDocId = `_design/${className}-group-temp`;\n const ddoc: {\n _id: string;\n views: {};\n _rev: undefined | string;\n } = {\n _id: designDocId,\n views: {\n 'by_pKeys': {\n map: mapCode\n }\n },\n _rev: undefined,\n };\n fnLogger.info(\"Prepared design document\", { ddoc });\n\n try {\n // Use 'get' to check if the design doc already exists\n const existingDoc = await this.db.get(designDocId);\n ddoc._rev = existingDoc._rev; // Add _rev to update the existing doc\n await this.db.put(ddoc);\n fnLogger.info('Design document updated successfully.');\n } catch (err: any) {\n if (err.name === 'not_found') {\n // Doc doesn't exist, create it\n await this.db.put(ddoc);\n fnLogger.info('Design document created successfully.');\n } else {\n fnLogger.error('Error saving design document:', err);\n throw err;\n }\n }\n return designDocId;\n }\n\n // TODO: consider refactoring to use ~class (before, create) triggers\n // and (before, update) triggers\n prepareDoc(\n _id: string,\n type: string,\n params: { [key: string]: string | number | boolean },\n metaKey: \"~class\"\n ): Document;\n prepareDoc(\n _id: string,\n type: string,\n params: { [key: string]: string | number | boolean },\n metaKey: \"~domain\"\n ): RelationDocument;\n prepareDoc(\n _id: string,\n type: string,\n params: { [key: string]: string | number | boolean },\n metaKey: \"~class\" | \"~domain\" = \"~class\"\n ): Document | RelationDocument {\n logger.info(\"prepareDoc - given args\", { _id: _id, type: type, params: params });\n params[\"_id\"] = _id;\n params[metaKey] = type;\n params[\"~createTimestamp\"] = new Date().getTime();\n params[\"active\"] = true;\n logger.info(\"prepareDoc - after elaborations\", { params });\n return params as unknown as Document | RelationDocument;\n }\n\n /**\n * Creates or updates a single document in the database.\n * \n * If `docId` is provided and the document exists, it will be updated.\n * If `docId` is `null`, a new ID will be auto-generated in the format `{type}-{incrementalId}`.\n * Access policies are enforced before writing.\n * \n * @param docId - The document ID, or `null` to auto-generate\n * @param type - The class name (e.g., 'Task', 'User')\n * @param classObj - The Class instance or schema definition for validation\n * @param params - The document data to save\n * @returns The created or updated document\n * @throws Error if policy check fails or document type conflicts\n * \n * @example\n * ```typescript\n * // Create with auto-generated ID\n * const task = await stack.createDoc(null, 'Task', taskClass, {\n * title: 'New Task',\n * isComplete: false\n * });\n * \n * // Update existing document\n * await stack.createDoc('Task-123', 'Task', taskClass, {\n * title: 'Updated Title'\n * });\n * ```\n */\n createDoc = async (docId: string | null, type: string, classObj: Class | ClassModel[\"schema\"], params: {}) => {\n const fnLogger = logger.child({ method: \"createDoc\", args: { docId, type, params } });\n fnLogger.info(\"Creating document\");\n let schema: ClassModel[\"schema\"] = {};\n if (classObj instanceof Class) {\n schema = classObj.buildSchema();\n } else {\n schema = classObj;\n }\n let db = this.db,\n doc: Document | null = null,\n isNewDoc = false,\n newDocId = \"\";\n try {\n if (docId) {\n const existingDoc = await this.getDocument(docId) as unknown as Document;\n fnLogger.info(\"Retrieved doc\", { existingDoc })\n // console.log(\"Existing doc\", {existingDoc, params})\n if (existingDoc && existingDoc[\"~class\"] === type) {\n fnLogger.info(\"Assigning existing doc\", { doc: existingDoc });\n doc = { ...existingDoc };\n } else if (existingDoc && existingDoc[\"~class\"] !== type) {\n fnLogger.error(\"Existing document type differs\");\n throw new Error(\"createDoc - Existing document type differs\");\n } else {\n isNewDoc = true;\n newDocId = docId;\n doc = this.prepareDoc(newDocId, type, params, \"~class\") as Document;\n }\n } else {\n isNewDoc = true;\n newDocId = `${type}-${(this.lastDocId + 1)}`;\n doc = this.prepareDoc(newDocId, type, params, \"~class\") as Document;\n fnLogger.info(\"Generated docId\", { newDocId });\n }\n fnLogger.info(\"Doc BEFORE elaboration (i.e. merge)\", { doc, params });\n let doc_ = { ...doc, ...params, _rev: doc._rev, \"~updateTimestamp\": new Date().getTime() };\n if (type === \"~User\" || type === \"User\") {\n const groups = (doc_ as any).groupId;\n if (!groups || (Array.isArray(groups) && groups.length === 0)) {\n (doc_ as any).groupId = [\"Group-Default\"];\n }\n }\n if (type === \"~UserSession\" || type === \"UserSession\") {\n let sessionGroups = (doc_ as any).groupId;\n if (!sessionGroups || (Array.isArray(sessionGroups) && sessionGroups.length === 0)) {\n const sessionUserId = (doc_ as any).userId;\n if (sessionUserId) {\n const relatedUser = await this.getDocument(sessionUserId).catch(() => null) as any;\n if (relatedUser?.groupId) {\n sessionGroups = relatedUser.groupId;\n }\n }\n if (!sessionGroups || (Array.isArray(sessionGroups) && sessionGroups.length === 0)) {\n sessionGroups = [\"Group-Default\"];\n }\n (doc_ as any).groupId = sessionGroups;\n }\n }\n if (doc_[\"~class\"]?.startsWith(\"Account-\")) {\n // console.log(\"Doc after merge\", { doc_ })\n }\n fnLogger.info(\"Doc AFTER elaboration (i.e. merge)\", { doc_ });\n await this.policyEngine.ensureWriteAllowed(type, doc_ as Document);\n let response = await db.put(doc_);\n // Find me\n fnLogger.info(\"Response after put\", { \"response\": response });\n if (response.ok && isNewDoc) {\n await this.incrementLastDocId();\n docId = response.id;\n }\n else if (response.ok) {\n docId = response.id;\n }\n else {\n fnLogger.error(\"Error, check logs\", { \"response\": response });\n throw new Error(\"createDoc - Error, check logs\");\n }\n } catch (e: any) {\n if (e.name === 'conflict') {\n fnLogger.info(\"Conflict! Ignoring..\");\n // TODO: Handle conflict!\n } else {\n fnLogger.info(\"Problem while putting doc\", {\n \"error\": e,\n \"document\": doc\n })\n throw new Error(\"createDoc - Problem while putting doc\" + e);\n }\n }\n return doc;\n }\n\n /**\n * Creates or updates multiple documents in a single batch operation.\n * More efficient than calling {@link createDoc} multiple times.\n * \n * @param docs - Array of document specifications with optional docId and params\n * @param type - The class name for all documents\n * @param classObj - The Class instance or schema definition for validation\n * @returns Array of created or updated documents\n * @throws Error if policy check fails for any document\n * \n * @example\n * ```typescript\n * const tasks = await stack.createDocs([\n * { docId: null, params: { title: 'Task 1' } },\n * { docId: null, params: { title: 'Task 2' } },\n * { docId: 'Task-existing', params: { title: 'Updated' } }\n * ], 'Task', taskClass);\n * ```\n */\n createDocs = async (docs: { docId: string | null, params: {} }[], type: string, classObj: Class | ClassModel[\"schema\"]) => {\n const fnLogger = logger.child({ method: \"createDocs\", args: { docs } });\n\n let schema: ClassModel[\"schema\"] = {};\n if (classObj instanceof Class) {\n schema = classObj.buildSchema();\n } else {\n schema = classObj;\n }\n fnLogger.info(\"Determined schema\", { schema });\n\n let db = this.db;\n const documents: Document[] = [];\n let newDocsIds: string[] = [];\n\n for (const draft of docs) {\n let { docId, params } = draft;\n let doc: Document | null = null;\n let isNewDoc = false;\n try {\n if (docId) {\n const existingDoc = await this.getDocument(docId) as unknown as Document;\n fnLogger.info(\"retrieved doc\", { existingDoc })\n if (existingDoc && existingDoc[\"~class\"] === type) {\n fnLogger.info(\"createDocs - assigning existing doc\", { doc: existingDoc });\n doc = { ...existingDoc };\n } else if (existingDoc && existingDoc[\"~class\"] !== type) {\n throw new Error(\"createDocs - Existing document type differs\");\n } else {\n isNewDoc = true;\n doc = this.prepareDoc(docId, type, params, \"~class\") as Document;\n }\n } else {\n docId = `${type}-${(this.lastDocId + 1)}`;\n doc = this.prepareDoc(docId, type, params, \"~class\") as Document;\n isNewDoc = true;\n fnLogger.info(\"Generated docId\", docId);\n }\n fnLogger.info(\"Doc BEFORE elaboration (i.e. merge)\", { doc, params });\n const doc_ = { ...doc, ...params, _id: docId, _rev: doc._rev, \"~updateTimestamp\": new Date().getTime() };\n fnLogger.info(\"Doc AFTER elaboration (i.e. merge)\", { doc_ });\n await this.policyEngine.ensureWriteAllowed(type, doc_ as Document);\n documents.push(doc_);\n if (isNewDoc) newDocsIds.push(docId);\n } catch (e: any) {\n fnLogger.error(\"createDocs - Problem while preparing doc\", {\n \"error\": e,\n \"document\": doc\n });\n throw new Error(\"createDocs - Problem while preparing doc\" + e);\n }\n }\n try {\n const response = await db.bulkDocs(documents);\n fnLogger.info(\"Response after bulkDocs\", { \"response\": response });\n // Increment lastDocId based on number of new docs created\n const newDocsCount = response.filter(res => res.id != null && newDocsIds.includes(res.id)).length;\n fnLogger.info(`Successfully created ${newDocsCount} new documents.`);\n for (let i = 0; i < newDocsCount; i++) {\n await this.incrementLastDocId();\n }\n } catch (e: any) {\n fnLogger.error(\"createDocs - Problem while putting docs\", {\n \"error\": e,\n \"documents\": documents\n });\n throw new Error(\"createDocs - Problem while putting docs\" + e);\n }\n return documents;\n }\n\n /**\n * Creates a relation document linking two entities via a Domain.\n * Relation documents represent relationships between documents (e.g., 1:N, N:N).\n * \n * @param docId - The relation document ID, or `null` to auto-generate\n * @param relationName - A descriptive name for this relation instance\n * @param domainObj - The Domain defining the relationship type\n * @param params - The relation parameters including source and target references\n * @returns The created relation document, or `null` on error\n * \n * @example\n * ```typescript\n * const relation = await stack.createRelationDoc(\n * null,\n * 'ProjectTask',\n * projectTaskDomain,\n * {\n * sourceClass: 'Project',\n * targetClass: 'Task',\n * sourceId: 'Project-1',\n * targetId: 'Task-42'\n * }\n * );\n * ```\n */\n createRelationDoc = async (\n docId: string | null,\n relationName: string,\n domainObj: Domain,\n params: {\n sourceClass: string,\n targetClass: string,\n sourceId: string,\n targetId: string\n }): Promise<RelationDocument | null> => {\n const fnLogger = logger.child({ method: \"createRelationDoc\", args: { docId, relationName, params } });\n fnLogger.info(\"Creating relation document\");\n let db = this.db,\n doc: RelationDocument | null = null,\n isNewDoc = false;\n try {\n if (docId) {\n const existingDoc = await this.db.get(docId) as RelationDocument;\n fnLogger.info(\"retrieved doc\", { existingDoc })\n if (existingDoc && existingDoc[\"~domain\"] === domainObj.name) {\n fnLogger.info(\"Assigning existing doc\", { doc: existingDoc });\n doc = { ...existingDoc };\n } else if (existingDoc && existingDoc[\"~domain\"] !== domainObj.name) {\n fnLogger.error(\"Existing document type differs\");\n throw new Error(\"createDoc - Existing document type differs\");\n } else {\n fnLogger.warn(\"No relation document\");\n isNewDoc = true;\n doc = this.prepareDoc(docId, domainObj.name, params, \"~domain\");\n }\n } else {\n docId = `${domainObj.name}-${(this.lastDocId + 1)}`;\n doc = this.prepareDoc(docId, domainObj.name, params, \"~domain\");\n isNewDoc = true;\n fnLogger.info(\"Generated docId\", docId);\n }\n fnLogger.info(\"Doc BEFORE elaboration (i.e. merge)\", { doc, params });\n const doc_ = { ...doc, ...params, _id: docId, _rev: doc._rev, \"~updateTimestamp\": new Date().getTime() };\n fnLogger.info(\"Doc AFTER elaboration (i.e. merge)\", { doc_ });\n let response = await db.put(doc_);\n fnLogger.info(\"Response after put\", { \"response\": response });\n if (response.ok && isNewDoc) {\n await this.incrementLastDocId();\n docId = response.id;\n }\n else if (response.ok) {\n docId = response.id;\n }\n else {\n fnLogger.error(\"Error, check logs\", { \"response\": response });\n throw new Error(\"createDoc - Error, check logs\");\n }\n } catch (e) {\n fnLogger.error(\"Error while creating relation document\", { error: e });\n }\n return doc;\n }\n\n /**\n * Creates multiple relation documents in a single batch operation.\n * More efficient than calling {@link createRelationDoc} multiple times.\n * \n * @param docs - Array of relation specifications\n * @param relationName - A descriptive name for these relations\n * @param domainObj - The Domain defining the relationship type\n * @returns Array of created relation documents\n * \n * @example\n * ```typescript\n * const relations = await stack.createRelationDocs([\n * { docId: null, params: { sourceClass: 'Project', targetClass: 'Task', sourceId: 'Project-1', targetId: 'Task-1' } },\n * { docId: null, params: { sourceClass: 'Project', targetClass: 'Task', sourceId: 'Project-1', targetId: 'Task-2' } }\n * ], 'ProjectTasks', projectTaskDomain);\n * ```\n */\n createRelationDocs = async (docs: {\n docId: string | null; params: {\n sourceClass: string;\n targetClass: string;\n sourceId: string;\n targetId: string;\n };\n }[], relationName: string, domainObj: Domain): Promise<RelationDocument[]> => {\n const fnLogger = logger.child({ method: \"createRelationDocs\", args: { docs, relationName } });\n\n let db = this.db;\n const documents: RelationDocument[] = [];\n let newDocsIds: string[] = [];\n\n for (const draft of docs) {\n let { docId, params } = draft;\n let doc: RelationDocument | null = null;\n let isNewDoc = false;\n try {\n if (docId) {\n const existingDoc = await db.get(docId) as RelationDocument;\n fnLogger.info(\"retrieved doc\", { existingDoc })\n if (existingDoc && existingDoc[\"~domain\"] === domainObj.name) {\n fnLogger.info(\"createRelationDocs - assigning existing doc\", { doc: existingDoc });\n doc = { ...existingDoc };\n } else if (existingDoc && existingDoc[\"~domain\"] !== domainObj.name) {\n throw new Error(\"createRelationDocs - Existing document type differs\");\n } else {\n isNewDoc = true;\n doc = this.prepareDoc(docId, domainObj.name, params, \"~domain\");\n }\n } else {\n docId = `${domainObj.name}-${(this.lastDocId + 1)}`;\n doc = this.prepareDoc(docId, domainObj.name, params, \"~domain\");\n isNewDoc = true;\n fnLogger.info(\"Generated docId\", docId);\n }\n fnLogger.info(\"Doc BEFORE elaboration (i.e. merge)\", { doc, params });\n const doc_ = {\n ...doc,\n ...params,\n _id: docId,\n _rev: doc._rev,\n \"~updateTimestamp\": new Date().getTime()\n };\n fnLogger.info(\"Doc AFTER elaboration (i.e. merge)\", { doc_ });\n documents.push(doc_);\n if (isNewDoc) newDocsIds.push(docId);\n } catch (e: any) {\n fnLogger.error(\"createRelationDocs - Problem while preparing doc\", {\n \"error\": e,\n \"document\": doc\n });\n throw new Error(\"createRelationDocs - Problem while preparing doc\" + e);\n }\n }\n try {\n // console.log(\"Documents to be created\", {documents});\n const response = await db.bulkDocs(documents);\n fnLogger.info(\"Response after bulkDocs\", { \"response\": response });\n // Increment lastDocId based on number of new docs created\n const newDocsCount = response.filter(res => res.id != null && newDocsIds.includes(res.id)).length;\n fnLogger.info(`Successfully created ${newDocsCount} new documents.`);\n for (let i = 0; i < newDocsCount; i++) {\n await this.incrementLastDocId();\n }\n } catch (e: any) {\n fnLogger.error(\"createRelationDocs - Problem while putting docs\", {\n \"error\": e,\n \"documents\": documents\n });\n throw new Error(\"createRelationDocs - Problem while putting docs\" + e);\n }\n return documents;\n }\n\n /**\n * Sets the active param of a document to false\n * @param _id \n * @returns Promise<boolean>\n */\n deleteDocument = async (_id: string): Promise<boolean> => {\n const fnLogger = logger.child({ method: \"deleteDocument\", args: { _id } });\n const doc = await this.db.get<Document>(_id);\n if (doc) {\n try {\n const targetClass = (doc as any)[\"~class\"] as string;\n await this.policyEngine.ensureWriteAllowed(targetClass, doc);\n await this.db.put({ ...doc, active: false });\n return true;\n } catch (e: any) {\n fnLogger.error(`Error while deleting document: ${e}`, { document: doc });\n return false;\n }\n } else {\n fnLogger.error(\"Found no document with given id\");\n return false;\n }\n }\n\n /**\n * Executes a SQL query against the local database.\n * Supports SELECT, JOIN, WHERE, ORDER BY, GROUP BY, and UNION operations.\n * \n * @param sql - The SQL query string\n * @param params - Optional query parameters for prepared statements\n * @returns Object containing result rows and the parsed AST\n * \n * @example\n * ```typescript\n * // Simple select\n * const { rows } = await stack.query('SELECT * FROM Task WHERE isComplete = false');\n * \n * // Join with ordering\n * const { rows } = await stack.query(`\n * SELECT t.title, u.username AS assignee\n * FROM Task AS t\n * JOIN User AS u ON u._id = t.assigneeId\n * ORDER BY t.createdAt DESC\n * `);\n * \n * // With parameters\n * const { rows } = await stack.query('SELECT * FROM Task WHERE priority = ?', 'high');\n * ```\n */\n query = async (sql: string, ...params: any[]) => {\n const fnLogger = logger.child({ method: \"query\", args: { sql, params } });\n fnLogger.info(\"Executing query\");\n let astList: (SelectAST | UnionAST)[] = [];\n try {\n astList = parse(sql);\n fnLogger.info(\"Produced AST\", { astList });\n } catch (error: any) {\n error.ast = astList.length > 0 ? astList[0] : null;\n throw error;\n }\n\n // A UNION query is treated as a single execution, not a loop over ASTs.\n if (astList.length > 0) {\n try {\n const plan = createPlan(astList);\n const rows = await executePlan(this, plan, params);\n // The AST for the whole query (including unions) is the list\n fnLogger.info(\"Query executed successfully\", { rows, astList });\n return { rows, ast: astList };\n } catch (error: any) {\n error.ast = astList; // Attach full AST list to error for debugging\n throw error;\n }\n }\n\n // Handle case where query is empty or only comments\n return { rows: [], ast: null };\n }\n}\n\n\n\nexport default ClientStack","// import express, {Express} from 'express'\n// import { static as exStatic } from 'express';\n// import * as dotenv from \"dotenv\";\n// import cors from \"cors\";\n// dotenv.config({ path: './.env' })\nimport createlogger from \"../utils/logger/index\"\n// import test from '../../../server/src//utils/dbManager/test';\n// import { generateJwtKeys, generatePswKeys } from '../../../server/src/utils/crypto';\nimport ClientStack from './stack';\n// import { login, JWTAuthPayload, setupAdminUser } from '../../../server/src//utils/auth';\n// import memoryAdapter from \"pouchdb-adapter-memory\"\n// import cookieParser from 'cookie-parser';\n// import jwt from 'jsonwebtoken';\nimport Class from \"./class\";\nimport Domain from './domain';\nimport { Trigger } from \"./trigger/index\";\nimport { JobEngine } from \"./job-engine/index\";\n// import AbstractClass from '../../shared/src//utils/stack/class';\nimport Attribute from './attribute';\nimport { AttributeType, ClientCredentials, DocstackReady, StackConfig, StackOptions } from \"@docstack/shared\";\nimport { createLogger, Logger } from \"winston\";\n// import { EventTarget } from 'node:events';\n\n// let envPath = process.env.ENVFILE || \"./.env\";\n// envPath = resolve(process.cwd(), envPath);\n// dotenv.config({ path: envPath });\n\n\n// [TODO] Implement DocStack.type in \"remote\" | \"local\"\n// When is remote, open a websocket (socket.io) connection to given remote\n// implement cases in each of stack methods (queries and doc creation)\n// to actually send and receive messages\n// [TODO][HARD] Think about authentication mechanism\n// Probably support same rest authentication (jwtToken)\n// but also api tokens\n// Remote connection that require auth can be opened but\n// cannot send or receive messages until authentication\n/**\n * The main entry point for the DocStack client library.\n * \n * DocStack manages multiple {@link ClientStack} instances and provides\n * a unified interface for database operations, authentication, and\n * class/attribute creation.\n * \n * The client emits a `ready` event when all stacks are initialized.\n * \n * @example\n * ```typescript\n * // Initialize DocStack with a single database\n * const docstack = new DocStack({ name: 'my-app' });\n * \n * // Wait for ready\n * docstack.addEventListener('ready', async () => {\n * const stack = docstack.getStack('my-app');\n * const taskClass = await stack.getClass('Task');\n * });\n * \n * // Initialize with credentials for automatic authentication\n * const docstack = new DocStack({\n * name: 'my-app',\n * credentials: { username: 'admin', password: 'secret' }\n * });\n * ```\n * \n * @extends EventTarget\n */\nclass DocStack extends EventTarget {\n /** Array of stack configurations used for initialization. */\n private config: StackConfig[] = [];\n /** Whether all stacks have been initialized and ready for use. */\n private readyState: boolean;\n /** The primary/default stack (first in the list). */\n private store!: ClientStack;\n /** Array of all initialized ClientStack instances. */\n stacks: ClientStack[] = [];\n private logger: Logger = createlogger().child({ module: \"client\" });\n\n private async addStack(config: StackConfig) {\n let stack: ClientStack | undefined;\n if (typeof config == \"object\" && config.name) {\n stack = await ClientStack.create(`db-${config.name}`, {\n // defaults to leveldb\n // adapter: 'memory',\n plugins: [\n // https://www.npmjs.com/package/pouchdb-adapter-memory\n // memoryAdapter\n ],\n patches: config.patches,\n credentials: (config as any).credentials,\n disableCryptoEngine: (config as StackOptions).disableCryptoEngine,\n });\n } else if (typeof config === \"string\") {\n stack = await ClientStack.create(`db-${config}`, {\n // defaults to leveldb\n // adapter: 'memory',\n plugins: [\n // https://www.npmjs.com/package/pouchdb-adapter-memory\n // memoryAdapter\n ]\n });\n }\n if (stack) {\n this.stacks.push(stack);\n // let window_ = window as Window & typeof globalThis & {\n // stacks: ClientStack[]\n // }\n // if (window_.stacks) {\n // window_.stacks.push(stack)\n // } \n return stack;\n }\n // await setupAdminUser();\n }\n\n private initStacks = async (configs: StackConfig[]) => {\n // TODO: Consider changing to Promise.all for concurrency\n for (const config of configs) {\n const stack = await this.addStack(config);\n }\n\n this.readyState = true;\n this.dispatchEvent(new CustomEvent(\"ready\", {\n detail: {\n stacks: this.stacks\n }\n }))\n }\n\n async resetAll() {\n try {\n for (const stack of this.stacks) {\n await stack.reset();\n }\n } catch (e: any) {\n throw new Error(e);\n }\n }\n\n /**\n * Returns all initialized stacks.\n * @returns Array of ClientStack instances\n */\n public getStacks() {\n return this.stacks;\n }\n\n /**\n * Gets a stack by its name or connection string.\n * \n * @param name - The stack name or connection identifier\n * @returns The matching ClientStack, or `undefined` if not found\n * \n * @example\n * ```typescript\n * const stack = docstack.getStack('my-app');\n * if (stack) {\n * const users = await stack.query('SELECT * FROM User');\n * }\n * ```\n */\n public getStack = (name: string) => {\n return this.stacks.find(s => s.name == name || s.connection == name);\n }\n\n /**\n * Authenticates a user on a specific stack.\n * \n * @param name - The stack name to authenticate against\n * @param credentials - The user's login credentials\n * @returns The authentication session proof\n * @throws Error if the stack is not found\n * \n * @example\n * ```typescript\n * const proof = await docstack.authenticateStack('my-app', {\n * username: 'user@example.com',\n * password: 'password123'\n * });\n * ```\n */\n public async authenticateStack(name: string, credentials: ClientCredentials) {\n const stack = this.getStack(name);\n if (!stack) {\n throw new Error(`Stack '${name}' not found`);\n }\n return stack.authenticate(credentials);\n }\n\n /**\n * Returns whether all stacks have been initialized.\n * @returns `true` if ready, `false` otherwise\n */\n public getReadyState() {\n return this.readyState;\n }\n /**\n * Resets all stacks and re-initializes them.\n * Useful for testing or clearing all data.\n */\n async reset() {\n try {\n await this.resetAll();\n await this.initStacks(this.config);\n } catch (e: any) {\n throw new Error(e);\n }\n }\n\n public clearConnection = async (conn: string) => {\n const fnLogger = this.logger.child({ method: 'clearConnection' });\n try {\n // const conn = req.params.conn;\n if (!conn) {\n throw new Error(\"Connection name not provided\");\n }\n await ClientStack.clear(conn);\n fnLogger.info('Internal database cleared');\n // return res.status(200).json({ success: true, message: 'Internal database cleared' });\n } catch (e: any) {\n throw new Error(e);\n // return res.status(500).json({ success: false, error: 'An error occurred' });\n }\n }\n\n /**\n * Exports all documents from a stack.\n * \n * @param stackName - The name of the stack to export\n * @returns All documents from the stack\n * @throws Error if the stack is not found\n */\n public export = async (stackName: string) => {\n const stack = this.getStack(stackName);\n if (stack) {\n const dump = await stack.dump();\n return dump;\n } else {\n throw new Error(`Did not find any stack for name '${stackName}'`);\n }\n }\n\n /**\n * Creates a new Class in the specified stack.\n * \n * @param stackName - The name of the stack to create the class in\n * @param name - The class name\n * @param config - Configuration with type and description\n * @throws Error if the stack is not found\n * \n * @example\n * ```typescript\n * await docstack.createClass('my-app', 'Product', {\n * type: 'class',\n * description: 'Product catalog items'\n * });\n * ```\n */\n public createClass = async (stackName: string, name: string, config: {\n type: string,\n description: string\n }) => {\n const fnLogger = this.logger.child({ method: 'createClass' });\n const stack = this.getStack(stackName);\n if (!stack) {\n throw new Error(`Stack '${stackName}' not found`);\n }\n const { type, description } = config;\n fnLogger.info(\"Args\", {\n stackName, name, config\n })\n\n try {\n const newClass = await Class.create(\n stack, name, \"class\", description as string,\n {}\n );\n fnLogger.info(`class '${name}' created successfully.`,\n { classModel: newClass.getModel() }\n )\n } catch (e: any) {\n throw new Error(`Error during class '${name}' creation. ${e}`);\n }\n\n fnLogger.info('Class created successfully');\n }\n\n /**\n * Creates a new Attribute on a Class in the specified stack.\n * \n * @param stackName - The name of the stack containing the class\n * @param className - The class to add the attribute to\n * @param params - Attribute configuration\n * @throws Error if the stack or class is not found\n * \n * @example\n * ```typescript\n * await docstack.createAttribute('my-app', 'Product', {\n * name: 'price',\n * type: 'number',\n * description: 'Product price in cents'\n * });\n * ```\n */\n public createAttribute = async (stackName: string, className: string, params: {\n name: string, type: AttributeType[\"type\"], description?: string, config?: {}\n }) => {\n const fnLogger = this.logger.child({ method: 'createAttribute' });\n const stack = this.getStack(stackName);\n if (!stack) {\n throw new Error(`Stack '${stackName}' not found`);\n }\n const { name, type, description, config } = params;\n fnLogger.info(`Creating attribute for class '${className}' in stack '${stackName}'`, {\n name, type, config\n });\n\n try {\n // Loads the class object\n let classObj = await stack.getClass(className);\n if (classObj) {\n let newAttribute = await Attribute.create(classObj, name, type, description, config);\n fnLogger.info(`Attribute '${name}' added to class '${className}'`,\n { attributeModel: newAttribute.getModel() }\n );\n } else {\n throw new Error(`Failed to retrieve Class '${className}'`);\n }\n\n } catch (e: any) {\n fnLogger.error(`Error during attribute '${name}' creation: ${e}`);\n throw new Error(`Error during attribute '${name}' creation: ${e}`);\n }\n }\n\n /**\n * Creates a new DocStack client instance.\n * Initializes all configured stacks asynchronously.\n * Listen for the `ready` event to know when initialization is complete.\n * \n * @param config - One or more stack configurations\n * \n * @example\n * ```typescript\n * const docstack = new DocStack(\n * { name: 'primary-db' },\n * { name: 'backup-db' }\n * );\n * \n * docstack.addEventListener('ready', () => {\n * console.log('All stacks ready!');\n * });\n * ```\n */\n constructor(...config: StackConfig[]) {\n super();\n this.readyState = false;\n const fnLogger = this.logger.child({ method: \"constructor\" });\n\n /*\n this.app.use(logRequest)\n // Enable CORS for all routes\n if (process.env.NODE_ENV === 'development') {\n logger.info(\"Development environment. Enabling CORS for :8080\");\n this.app.use(cors({\n origin: 'http://localhost:8080',\n // Replace with the origin of webpack dev server\n methods: ['GET', 'POST'], \n credentials: true,\n }));\n }\n */\n /*\n // Use built-in middleware for parsing JSON and URL-encoded data\n this.app.use(express.json());\n this.app.use(express.urlencoded({ extended: true }));\n this.app.use(cookieParser());\n this.app.use((req, res, next) => {\n if (!this.readyState) {\n return res.status(503); // Service Unavailable.\n }\n // Server is ready to receive requests\n next()\n })\n */\n /*\n this.app.use('/api/private', (req, res, next) => {\n const token = req.cookies.jwtToken\n if (!token) {\n logger.error(\"No token provided\")\n return res.status(403).json({\n success: false,\n message: 'No token provided',\n });\n }\n const secretKey = process.env.JWT_PUBLIC_KEY;\n if (!secretKey || secretKey === '') {\n logger.error(\"No secret key found\")\n return res.status(500).json({\n success: false,\n message: 'No secret key found',\n });\n }\n jwt.verify(token, secretKey, async (err, payload: JWTAuthPayload) => {\n if (err) {\n logger.error(\"Invalid token\", err)\n return res.status(403).json({\n success: false,\n message: 'Invalid token',\n });\n } else {\n // Check whether the session is still valid\n const { sessionId } = payload;\n const UserSessionClass = await this.store.getClass(\"UserSession\");\n const sessionCards = await UserSessionClass.getCards({\n sessionId: { $eq: sessionId },\n sessionStatus: { $eq: \"active\" }\n }, null, 0, 1);\n if (sessionCards.length === 0) {\n return res.status(403).json({\n success: false,\n message: 'Session expired',\n });\n }\n // TODO: Consider passing the session card to the next middleware\n next();\n }\n });\n })\n */\n // TODO: Serve the dashboard to a specific route, i.e.: admin \n // this.app.use(exStatic('./dist'));\n\n // TODO: Serve the static files from the build folder\n // of the UI application\n // this.app.get('*', (req, res) => {\n // const templatePath = resolve(__dirname, './dist', 'index.html');\n // res.sendFile(templatePath);\n // });\n\n /*\n this.app.post('/login', async (req, res) => {\n try {\n const { username, password } = req.body;\n const { responseCode, body, token } = await login(username, password);\n // Append also the token to the response\n let cookieOptions = {}\n if (process.env.NODE_ENV === 'development') {\n cookieOptions = { sameSite: 'None', secure: true, maxAge: 1000 * 60 * 15 };\n logger.warn(\"Development mode: setting cookie options to SameSite=None; Secure=true for JWT token\");\n } else cookieOptions = { sameSite: 'Strict', httpOnly: true, maxAge: 1000 * 60 * 15 };\n\n res.cookie('jwtToken', token, cookieOptions);\n return res.status(responseCode).json(body);\n } catch (error) {\n console.error(\"Error during login\", error);\n return res.status(500).json({ success: false, error: 'An error occurred' });\n }\n });\n */\n\n /* \n this.app.get('/api/private/reset', async (req, res) => {\n try {\n await this.reset();\n return res.status(200).json({ success: true, message: 'Internal database reset' });\n } catch (e) {\n return res.status(500).json({ success: false, error: 'An error occurred' });\n }\n });\n */\n /*\n this.app.get('/api/private/clear:conn', async (req, res) => {\n try {\n const conn = req.params.conn;\n if (!conn) {\n throw new Error(\"Connection name not provided\");\n }\n await ClientStack.clear(conn);\n return res.status(200).json({ success: true, message: 'Internal database cleared' });\n } catch (e) {\n logger.error(\"Error during database clear\", e);\n return res.status(500).json({ success: false, error: 'An error occurred' });\n }\n });\n */\n /*\n this.app.get('/api/private/test', (req, res) => {\n return res.status(200).json({ message: 'Hello from the server! This is a private route' });\n });\n */\n /*\n this.app.post('/api/private/create-class/:name', async (req, res) => {\n const { name } = req.params;\n const { type, description } = req.query;\n logger.info(\"create-class - received request\", {\n params: req.params,\n query: req.query\n })\n\n try {\n const newClass = await Class.create(\n this.store, name, type as string, description as string\n );\n logger.info(\"create-class\", `class '${name}' created successfully.`,\n {classModel: newClass.getModel()}\n )\n } catch (e) {\n logger.error(`Error during class '${name} creation: ${e}`);\n return res.status(500).json({ success: false, error: 'An error occurred' });\n }\n \n return res.status(200).json({ success: true, message: 'Class created successfully' });\n })\n */\n /*\n this.app.put('/api/private/create-attribute/:name', async (req, res) => {\n const className = req.params.name;\n const { name, type, config } = req.body;\n logger.info(`create-attribute - for class '${className}'`, {\n name, type, config\n });\n\n try {\n // Loads the class object\n let classObj = await this.store.getClass(className);\n let newAttribute = await Attribute.create(classObj, name, type, config);\n logger.info(`create-attribute - Attribute '${name}' added to class '${className}'`, \n {attributeModel: newAttribute.getModel()}\n );\n } catch (e) {\n logger.error(`Error during attribute '${name}' creation: ${e}`)\n }\n })\n */\n // const port = process.env.SERVER_PORT || 5000;\n\n // const server = this.app.listen(port, () => logger.info(`Listening on port ${port}`));\n\n // Procedure that should run once only\n // can be considered \"setup procedures\"\n //generatePswKeys()\n // generateJwtKeys()\n\n // Server \"startup procedures\"\n // setTimeout(test, 1000)\n this.initStacks(config);\n this.addEventListener(\"ready\", () => fnLogger.info(\"DocStack client successfully initialized\"));\n }\n\n // public getApp() {\n // return this.app;\n // }\n}\n\n/**\n * Core exports from the DocStack client library.\n * \n * @module @docstack/client\n */\nexport { ClientStack, Trigger, Class, Attribute, Domain, JobEngine };\nexport { DocStack };\n","import { DocStack } from \"./core/\";\n\nexport { ClientStack, Class, Domain, Attribute, Trigger, DocStack } from \"./core/\";\nexport type { AttributeType, DocstackReady, StackConfig, StackOptions } from \"@docstack/shared\";\nexport default DocStack;"],"names":["findExpressionRefs","expr","refs","type","table","add","left","right","args","Array","isArray","exprs","forEach","e","decorrelateSubqueries","ast","where","outerTableAliases","Set","from","map","f","as","joins","j","transformPredicate","predicate","correlation","subqueryAst","correlations","subqueryTableAliases","traverse","leftRefs","rightRefs","leftIsOuter","some","r","has","leftIsInner","rightIsOuter","rightIsInner","push","length","originalWhere","correlationSet","filterWhere","newLeft","newRight","predicates","findCorrelation","subquery","Error","joinCondition","not","on","filters","getReferencedTables","tables","allTables","node","tableInfo","find","t","isSimplePredicate","includes","operator","createSingleSelectPlan","plan","distinct","distinctOn","fromTable","residual","projections","columns","aggregation","orderBy","limit","fromTableName","join","wherePredicates","collectPredicates","p","isSimple","referenced","hasAggregates","c","groupBy","having","groupByCols","column","colName","aggregates","filter","createPlan","astList","selectPlans","unionOps","selectAsts","selectAstIndexMap","Map","index","set","unionAsts","topSelectAst","top","bottomSelectAst","bottom","topPlanIndex","get","bottomPlanIndex","undefined","lastSelectAst","lastSelectPlan","global","setImmediate","registerImmediate","html","channel","messagePrefix","onGlobalMessage","nextHandle","tasksByHandle","currentlyRunningATask","doc","document","attachTo","Object","getPrototypeOf","setTimeout","toString","call","process","handle","nextTick","runIfPresent","postMessage","importScripts","postMessageIsAsynchronous","oldOnMessage","onmessage","canUsePostMessage","Math","random","event","source","data","indexOf","slice","addEventListener","attachEvent","MessageChannel","port1","port2","createElement","documentElement","script","onreadystatechange","removeChild","appendChild","callback","Function","arguments","i","task","clearImmediate","apply","run","self","g","this","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","d","definition","key","o","defineProperty","enumerable","globalThis","window","obj","prop","prototype","hasOwnProperty","constructor","opts","super","stack","log","info","queueMicrotask","emit","db","post","transports","consoleTransport","Console","level","Attribute","classObj","name","description","config","field","ensureReferenceConfigIsValid","async","model","class","getStack","getName","domainName","domain","getDomain","classId","id","relation","targetClass","sourceClass","setField","maxLength","max","min","precision","isPrecise","value","decimalPart","split","refine","values","enumValues","v","foreignClass","documentIdOrIds","idsToValidate","promises","Promise","all","error","status","console","message","defaultValue","default","mandatory","optional","isPrimaryKey","getModel","primaryKey","isMandatory","getClass","validate","safeParseAsync","setModel","currentModel","assign","getType","checkTypeValidity","getEmpty","parse","validity","getTypeConf","format","create","attribute","build","attributeObj","addAttribute","Trigger","execute","result","warn","executeLimited","order","jobId","_classObj","jobEngine","executeJob","Class","attributes","schema","schemaZOD","object","state","triggers","resolve","reject","classModel","addClass","logger","setId","_id","init","active","child","className","uniqueCheck","fnLogger","method","duplicate","getByPrimaryKeys","bulkUniqueCheck","pKs","ddocId","addDesignDocumentPKs","query","group","reduce","rows","row","finalTempDoc","remove","err","debug","success","getDescription","getId","buildSchema","entries","trigger","_rev","attrModel","extend","trigger_","getPrimaryKeys","attr","getAttributes","names","hasAllAttributes","hasAnyAttributes","getEncryptedAttributes","encrypted","hasAttribute","attribute_","attributeModel","currentSchema","updateClass","modifyAttribute","originSchema","originAttr","omit","removeAttribute","addCard","params","createDoc","addCards","paramsArray","addedCards","createDocs","docId","primaryKeys","accumulator","currentValue","cards","getCards","addOrUpdateCard","cardId","updateCard","deleteCard","deleteDocument","selector","fields","skip","_selector","$eq","findDocuments","docs","addTrigger","removeTrigger","$in","class_","onClassDoc","change","evt","CustomEvent","detail","dispatchEvent","buildFromModel","fetchById","fetch","getClassModel","Domain","domainModel","addDomain","requireStack","getDocumentRole","assertReferenceAllowed","role","buildRelationParams","referenceId","sourceId","targetId","fetchReferenceDocument","expectedType","referenceDoc","catch","findRelationDoc","searchSelector","throwIfRelationExists","ensureCardinalityConstraints","validateRelation","existing","exists","getRelations","addRelation","validation","relationDoc","createRelationDoc","deleteRelation","deleteRelationDoc","relationDocId","domain_","getDomainModel","syspatches","classicAuthJobContent","sys_005","attributeEffect","operation","applySchemaDelta","schemaDelta","updatedDoc","StackPlugin","pouch","pouchBulkDocs","bulkDocs","pouchGet","put","options","documentsToProcess","relationQueue","flushRelationQueue","grouped","entry","shift","drafts","createRelationDocs","triggerQueue","classCache","postOperations","docRes","updatedRev","rev","afterTriggers","afterTrigger","recurse","isPostOp","rErr","rRes","postExec","res","parentClass","classDocId","revs","_revisions","ids","previousClassDoc","documents","updates","sourceDoc","targetDoc","encryptableAttributes","cryptoEngine","isEnabled","decryptDocument","relationalAttrs","a","startsWith","relationValue","domainId","beforeTriggers","JSON","stringify","payload","then","originalDocs","encryptedDocs","clone","encryptDocument","exec","Scanner","text","pos","eof","rest","skipWSAndComments","char","peekChar","test","offset","peekKW","kw","len","substr","toUpperCase","next","tryKW","expectKW","msg","matchRe","re","m","match","consumeRe","parseIdentifier","scan","parseColumnExpr","part1","parseExpression","startPos","parseSingleSelect","identMatch","afterIdentPos","tempScanner","argExpr","parsePredicate","opMatch","trim","valMatch","parseSelectItem","alias","parseSingleFrom","aliasMatch","ctx","SelectHandler","canStart","FromHandler","JoinHandler","WhereHandler","GroupByHandler","HavingHandler","OrderByHandler","LimitHandler","distinctExprs","cols","repeatable","save","ok","joinType","fromPart","onCondition","items","parseInt","registry","handlers","register","h","setAST","isAll","topIndex","bottomIndex","SEQUENCE","evalExpression","fromAlias","joinAliases","executePlan","outerRow","outerAliases","subqueryPlan","firstRow","keys","tableData","outerTableData","isNaN","parseFloat","evalAggregatedRowExpression","aggregateAliasMap","Sum","sum","seen","val","Count","count","Avg","Min","Max","DistinctWrapper","innerAccumulator","inner","createAccumulators","agg","isDistinct","asyncFilter","arr","results","_v","buildSelector","pred","op","applyDistinct","col","sort","k","applyOrderBy","b","valA","valB","comparison","executeSingleSelectPlan","fromClass","leftSelector","currentResultRows","rightClass","joinAlias","rightBaseSelector","subqueryFilterSelector","finalRightSelector","allRightRows","resultRows","rightRowIds","leftRow","outerArray","matchFound","rightRowMap","rightJoinKeyExpr","rightRow","newResultRows","matchedRightIds","matchFoundForLeftRow","fk_list","fk","nullRightRow","nullLeftRow","leftSchemaAliases","pj","joinedRows","filteredRows","evaluators","astNode","acc","createRowEvaluator","evaluator","projectedRows","finalRows","accumulators","initialRow","groups","keyParts","gb","keyValues","resultRow","applyAggregation","newRow","applyProjections","orderedRows","distinctColumns","distinctRows","allSelectResults","combinedRows","unionOp","nextRows","executeUnionPlan","now","Date","Job","content","crypto","TextEncoder","encode","buffer","subtle","digest","Uint8Array","padStart","calculateHash","hash","hydrate","hasRunningInstance","isSingleton","existingRuns","Boolean","buildRun","triggerType","runtimeArgs","randomUUID","getRandomValues","startTime","initialMetadata","metadata","persistRun","persistJobMetadata","current","nextDoc","errorMessage","endTime","durationMs","executor","defaultParams","finalMetadata","String","errorStack","JobEngine","jobDoc","SYSTEM_CLASSES","PolicyEngine","getSessionProof","authSession","shouldBypass","normalized","loadPolicies","aliases","identifiers","getTargetIdentifiers","targetName","variants","resolveClassTarget","evaluateRule","policy","session","rule","groupId","filterPoliciesForSession","policies","sessionUserId","userId","username","sessionGroups","matchesUser","matchesGroup","authorize","targetedPolicies","basePolicies","matchingPolicies","allowed","ensureWriteAllowed","isReadableDocument","permitted","encoder","decoder","TextDecoder","getCrypto","toBase64","bytes","ArrayBuffer","toUint8Array","binary","byte","fromCharCode","btoa","fromBase64","atob","charCodeAt","importAesKeyFromHex","hexKey","usages","importKey","hex","hexToBytes","isEncryptedPayload","candidate","__enc","iv","encryptWithAesGcm","plaintext","cryptoObj","ivBuffer","byteOffset","byteLength","ciphertext","encrypt","alg","decryptWithAesGcm","ivBytes","dataBytes","dataBuffer","decrypted","decrypt","decode","CryptoEngine","enabled","isCryptoEngineDisabled","setDocumentKey","documentKey","cryptoKey","getDocumentKey","generateRandomString","array","encryptValueForMarker","getCryptoKey","encryptValue","wrapDocumentKey","derivedKeyHex","unwrapAndStoreDocumentKey","wrappedDocumentKey","derivedKey","parsed","unwrapDocumentKey","serialized","decryptValue","identifyEncryptedKeys","encryptedFromSchema","encryptedFromPayload","merged","encryptedKeys","encryptedAttributes","BASE_SCHEMA","DOMAIN_SCHEMA","ClientStack","appVersion","listeners","modelWorker","dump","allDocs","include_docs","applyPatch","patch","docCount","hydratedDocs","existingDoc","isPatch","version","createTimestamp","valueOf","target","setListeners","onClassModelPropagationStart","onClassModelPropagationComplete","classModelChanges","onClassModelChanges","removeAllListeners","removeEventListener","listener","cancel","addClassLock","clearClassLock","changes","since","live","cache","onClassLock","classLockListener","response","onClassDocListener","close","terminate","fresh","ttl","domainObj","indexFields","foundResult","readableDocs","policyEngine","docClass","processedDoc","processReadableDocument","$or","findDocument","getClassModels","conf","listen","search","$regex","RegExp","list","getClasses","classNames","searchFilter","classModels","classList","deleted","idx","findIndex","splice","existingIndex","getDomainModels","getDomains","domainModels","domainList","classOrigin","classType","ensureDefaultPolicyForClass","resultDoc","temp","keyString","mapCode","code","designDocId","ddoc","views","isNewDoc","newDocId","getDocument","prepareDoc","lastDocId","doc_","getTime","relatedUser","incrementLastDocId","newDocsIds","draft","newDocsCount","relationName","sql","replace","endsWith","newAst","step","handler","unionHandler","initialize","conn","connection","cryptoEngineDisabled","disableCryptoEngine","plugins","plugin","getDb","getDbInfo","getDbName","setAuthSession","proof","clearAuthSession","$elemMatch","policyDoc","initdb","patches","credentials","authenticate","password","userQuery","user","authModuleId","authMethod","salt","keyDerivationSalt","userGroups","randomBytes","hexId","sessionId","sessionDoc","sessionStart","toISOString","sessionStatus","sessionClassModel","sessionSchema","ensureCryptoMarkerEncryption","getLastDocId","getSystem","loadPatches","schemaVersion","currentVersion","classicAuthJobHash","hashBuffer","hashContent","jobAuthClassic","getSystemPatches","applyPatches","_schemaVersion","checkSystem","_systemDoc","systemDoc","dbInfo","system","startupTime","ensureCryptoConfigDocument","initIndex","markerId","CRYPTO_CONFIG_DOC_ID","validateCryptoConfig","markerDoc","createdAt","encryptedMarker","nonce","storedDisabled","Number","getDocRevision","precomputedEncryptedKeys","hasDocumentKey","encryptedKeySet","visibleKeys","size","reset","destroyDb","destroy","clear","metaKey","DocStack","EventTarget","addStack","stacks","resetAll","getStacks","authenticateStack","getReadyState","readyState","initStacks","configs","s","clearConnection","export","stackName","createClass","newClass","createAttribute","newAttribute"],"ignoreList":[],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnF,eAAe,QAAQ,CAAC"}
|