@objectstack/driver-memory 1.0.5 → 1.0.7
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +15 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/memory-driver.ts +1 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/driver-memory@1.0.
|
|
2
|
+
> @objectstack/driver-memory@1.0.7 build /home/runner/work/spec/spec/packages/plugins/driver-memory
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m16.61 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m35.16 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 58ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m17.64 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m35.21 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 59ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 6683ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.24 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.24 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @objectstack/driver-memory
|
|
2
2
|
|
|
3
|
+
## 1.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @objectstack/spec@1.0.7
|
|
8
|
+
- @objectstack/core@1.0.7
|
|
9
|
+
|
|
10
|
+
## 1.0.6
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [a7f7b9d]
|
|
15
|
+
- @objectstack/spec@1.0.6
|
|
16
|
+
- @objectstack/core@1.0.6
|
|
17
|
+
|
|
3
18
|
## 1.0.5
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -138,6 +138,7 @@ function checkCondition(value, condition) {
|
|
|
138
138
|
var InMemoryDriver = class {
|
|
139
139
|
constructor(config) {
|
|
140
140
|
this.name = "in-memory-driver";
|
|
141
|
+
this.type = "driver";
|
|
141
142
|
this.version = "0.0.1";
|
|
142
143
|
this.supports = {
|
|
143
144
|
// Transaction & Connection Management
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/memory-driver.ts","../src/memory-matcher.ts"],"sourcesContent":["import { InMemoryDriver } from './memory-driver.js';\n\nexport { InMemoryDriver }; // Export class for direct usage\n\n// Note: In a real environment, you would import these from @objectstack/spec\n// But distinct PluginDefinition interface might not be strictly defined in schema yet, \n// usually it mimics the Manifest structure + runtime hooks.\n\n// For this example, we define a basic shape if not available, or use \"any\" to bypass strictness for the demo.\n// In plugin-bi it imported: import { PluginDefinition, PluginContextData } from '@objectstack/spec';\n\n// Let's rely on the environment being set up like plugin-bi.\n// If types are missing, this is just an example file.\n\nexport default {\n id: 'com.objectstack.driver.memory',\n version: '1.0.0',\n\n onEnable: async (context: any) => {\n const { logger, config, drivers } = context;\n logger.info('[Memory Driver] Initializing...');\n\n // Simulate driver registration\n // This assumes the runtime exposes a 'drivers' registry\n if (drivers) {\n const driver = new InMemoryDriver(config); // Pass config to driver\n drivers.register(driver);\n logger.info(`[Memory Driver] Registered driver: ${driver.name}`);\n } else {\n logger.warn('[Memory Driver] No driver registry found in context.');\n }\n }\n};\n","import { QueryAST, QueryInput } from '@objectstack/spec/data';\nimport { DriverOptions } from '@objectstack/spec/data';\nimport { DriverInterface, Logger, createLogger } from '@objectstack/core';\nimport { match, getValueByPath } from './memory-matcher.js';\n\n/**\n * Example: In-Memory Driver\n * \n * A minimal reference implementation of the ObjectStack Driver Protocol.\n * This driver stores data in a simple JavaScript object (Heap).\n */\nexport class InMemoryDriver implements DriverInterface {\n name = 'in-memory-driver';\n version = '0.0.1';\n private config: any;\n private logger: Logger;\n\n constructor(config?: any) {\n this.config = config || {};\n this.logger = config?.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.debug('InMemory driver instance created', { config: this.config });\n }\n\n // Duck-typed RuntimePlugin hook\n install(ctx: any) {\n this.logger.debug('Installing InMemory driver via plugin hook');\n if (ctx.engine && ctx.engine.ql && typeof ctx.engine.ql.registerDriver === 'function') {\n ctx.engine.ql.registerDriver(this);\n this.logger.info('InMemory driver registered with ObjectQL engine');\n } else {\n this.logger.warn('Could not register driver - ObjectQL engine not found in context');\n }\n }\n \n supports = {\n // Transaction & Connection Management\n transactions: false, \n \n // Query Operations\n queryFilters: true, // Implemented via memory-matcher\n queryAggregations: true, // Implemented\n querySorting: true, // Implemented via JS sort\n queryPagination: true, // Implemented\n queryWindowFunctions: false, // TODO: Not implemented\n querySubqueries: false, // TODO: Not implemented\n joins: false, // TODO: Not implemented\n \n // Advanced Features\n fullTextSearch: false, // TODO: Not implemented\n vectorSearch: false, // TODO: Not implemented\n geoSpatial: false, // TODO: Not implemented\n jsonFields: true, // Native JS object support\n arrayFields: true, // Native JS array support\n };\n\n /**\n * The \"Database\": A map of TableName -> Array of Records\n */\n private db: Record<string, any[]> = {};\n\n // ===================================\n // Lifecycle\n // ===================================\n\n async connect() {\n this.logger.info('InMemory Database Connected (Virtual)');\n }\n\n async disconnect() {\n const tableCount = Object.keys(this.db).length;\n const recordCount = Object.values(this.db).reduce((sum, table) => sum + table.length, 0);\n \n this.db = {};\n this.logger.info('InMemory Database Disconnected & Cleared', { \n tableCount, \n recordCount \n });\n }\n\n async checkHealth() {\n this.logger.debug('Health check performed', { \n tableCount: Object.keys(this.db).length,\n status: 'healthy' \n });\n return true; \n }\n\n // ===================================\n // Execution\n // ===================================\n\n async execute(command: any, params?: any[]) {\n this.logger.warn('Raw execution not supported in InMemory driver', { command });\n return null;\n }\n\n // ===================================\n // CRUD\n // ===================================\n\n async find(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('Find operation', { object, query });\n \n const table = this.getTable(object);\n let results = table;\n\n // 1. Filter\n if (query.where) {\n results = results.filter(record => match(record, query.where));\n }\n\n // 1.5 Aggregation & Grouping\n if (query.groupBy || (query.aggregations && query.aggregations.length > 0)) {\n results = this.performAggregation(results, query);\n }\n\n // 2. Sort\n if (query.orderBy) {\n // Normalize sort to array\n const sortFields = Array.isArray(query.orderBy) ? query.orderBy : [query.orderBy];\n \n results.sort((a, b) => {\n for (const { field, order } of sortFields) {\n const valA = getValueByPath(a, field);\n const valB = getValueByPath(b, field);\n \n if (valA === valB) continue;\n \n const comparison = valA > valB ? 1 : -1;\n return order === 'desc' ? -comparison : comparison;\n }\n return 0;\n });\n }\n\n // 3. Pagination (Offset)\n if (query.offset) {\n results = results.slice(query.offset);\n }\n\n // 4. Pagination (Limit)\n if (query.limit) {\n results = results.slice(0, query.limit);\n }\n\n this.logger.debug('Find completed', { object, resultCount: results.length });\n return results;\n }\n\n async *findStream(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindStream operation', { object });\n \n const results = await this.find(object, query, options);\n for (const record of results) {\n yield record;\n }\n }\n\n async findOne(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindOne operation', { object, query });\n \n const results = await this.find(object, { ...query, limit: 1 }, options);\n const result = results[0] || null;\n \n this.logger.debug('FindOne completed', { object, found: !!result });\n return result;\n }\n\n async create(object: string, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Create operation', { object, hasData: !!data });\n \n const table = this.getTable(object);\n \n // COMPATIBILITY: Driver must return 'id' as string\n const newRecord = {\n id: data.id || this.generateId(),\n ...data,\n created_at: data.created_at || new Date(),\n updated_at: data.updated_at || new Date(),\n };\n\n table.push(newRecord);\n this.logger.debug('Record created', { object, id: newRecord.id, tableSize: table.length });\n return newRecord;\n }\n\n async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Update operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for update', { object, id });\n throw new Error(`Record with ID ${id} not found in ${object}`);\n }\n\n const updatedRecord = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n \n table[index] = updatedRecord;\n this.logger.debug('Record updated', { object, id });\n return updatedRecord;\n }\n\n async upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions) {\n this.logger.debug('Upsert operation', { object, conflictKeys });\n \n const table = this.getTable(object);\n let existingRecord: any = null;\n\n if (data.id) {\n existingRecord = table.find(r => r.id === data.id);\n } else if (conflictKeys && conflictKeys.length > 0) {\n existingRecord = table.find(r => conflictKeys.every(key => r[key] === data[key]));\n }\n\n if (existingRecord) {\n this.logger.debug('Record exists, updating', { object, id: existingRecord.id });\n return this.update(object, existingRecord.id, data, options);\n } else {\n this.logger.debug('Record does not exist, creating', { object });\n return this.create(object, data, options);\n }\n }\n\n async delete(object: string, id: string | number, options?: DriverOptions) {\n this.logger.debug('Delete operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for deletion', { object, id });\n return false;\n }\n\n table.splice(index, 1);\n this.logger.debug('Record deleted', { object, id, tableSize: table.length });\n return true;\n }\n\n async count(object: string, query?: QueryInput, options?: DriverOptions) {\n let results = this.getTable(object);\n if (query?.where) {\n results = results.filter(record => match(record, query.where));\n }\n const count = results.length;\n this.logger.debug('Count operation', { object, count });\n return count;\n }\n\n // ===================================\n // Bulk Operations\n // ===================================\n\n async bulkCreate(object: string, dataArray: Record<string, any>[], options?: DriverOptions) {\n this.logger.debug('BulkCreate operation', { object, count: dataArray.length });\n const results = await Promise.all(dataArray.map(data => this.create(object, data, options)));\n this.logger.debug('BulkCreate completed', { object, count: results.length });\n return results;\n }\n \n async updateMany(object: string, query: QueryInput, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('UpdateMany operation', { object, query });\n \n const table = this.getTable(object);\n let targetRecords = table;\n \n if (query && query.where) {\n targetRecords = targetRecords.filter(r => match(r, query.where));\n }\n \n const count = targetRecords.length;\n \n // Update each record\n for (const record of targetRecords) {\n // Find index in original table\n const index = table.findIndex(r => r.id === record.id);\n if (index !== -1) {\n const updated = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n table[index] = updated;\n }\n }\n \n this.logger.debug('UpdateMany completed', { object, count });\n return { count };\n }\n\n async deleteMany(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('DeleteMany operation', { object, query });\n \n const table = this.getTable(object);\n const initialLength = table.length;\n \n // Filter IN PLACE or create new array?\n // Creating new array is safer for now.\n \n const remaining = table.filter(r => {\n if (!query || !query.where) return false; // Delete all? No, standard safety implies explicit empty filter for delete all.\n // Wait, normally deleteMany({}) deletes all.\n // Let's assume if query passed, use it.\n const matches = match(r, query.where);\n return !matches; // Keep if it DOES NOT match\n });\n \n this.db[object] = remaining;\n const count = initialLength - remaining.length;\n \n this.logger.debug('DeleteMany completed', { object, count });\n return { count };\n }\n\n // Compatibility aliases\n async bulkUpdate(object: string, updates: { id: string | number, data: Record<string, any> }[], options?: DriverOptions) {\n this.logger.debug('BulkUpdate operation', { object, count: updates.length });\n const results = await Promise.all(updates.map(u => this.update(object, u.id, u.data, options)));\n this.logger.debug('BulkUpdate completed', { object, count: results.length });\n return results;\n }\n\n async bulkDelete(object: string, ids: (string | number)[], options?: DriverOptions) {\n this.logger.debug('BulkDelete operation', { object, count: ids.length });\n await Promise.all(ids.map(id => this.delete(object, id, options)));\n this.logger.debug('BulkDelete completed', { object, count: ids.length });\n }\n\n // ===================================\n // Schema & Transactions\n // ===================================\n\n async syncSchema(object: string, schema: any, options?: DriverOptions) {\n if (!this.db[object]) {\n this.db[object] = [];\n this.logger.info('Created in-memory table', { object });\n }\n }\n\n async dropTable(object: string, options?: DriverOptions) {\n if (this.db[object]) {\n const recordCount = this.db[object].length;\n delete this.db[object];\n this.logger.info('Dropped in-memory table', { object, recordCount });\n }\n }\n\n async beginTransaction() {\n throw new Error('Transactions not supported in InMemoryDriver');\n }\n\n async commit() { /* No-op */ }\n async rollback() { /* No-op */ }\n\n // ===================================\n // Aggregation Logic\n // ===================================\n\n private performAggregation(records: any[], query: QueryInput): any[] {\n const { groupBy, aggregations } = query;\n const groups: Map<string, any[]> = new Map();\n\n // 1. Group records\n if (groupBy && groupBy.length > 0) {\n for (const record of records) {\n // Create a composite key from group values\n const keyParts = groupBy.map(field => {\n const val = getValueByPath(record, field);\n return val === undefined || val === null ? 'null' : String(val);\n });\n const key = JSON.stringify(keyParts);\n \n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n } else {\n // No grouping -> Single group containing all records\n // If aggregation is requested without group by, it runs on whole set (even if empty)\n if (aggregations && aggregations.length > 0) {\n groups.set('all', records);\n } else {\n // Should not be here if performAggregation called correctly\n groups.set('all', records);\n }\n }\n\n // 2. Compute aggregates for each group\n const resultRows: any[] = [];\n \n for (const [key, groupRecords] of groups.entries()) {\n const row: any = {};\n \n // A. Add Group fields to row (if groupBy exists)\n if (groupBy && groupBy.length > 0) {\n if (groupRecords.length > 0) {\n const firstRecord = groupRecords[0];\n for (const field of groupBy) {\n this.setValueByPath(row, field, getValueByPath(firstRecord, field));\n }\n }\n }\n \n // B. Compute Aggregations\n if (aggregations) {\n for (const agg of aggregations) {\n const value = this.computeAggregate(groupRecords, agg);\n row[agg.alias] = value;\n }\n }\n \n resultRows.push(row);\n }\n \n return resultRows;\n }\n \n private computeAggregate(records: any[], agg: any): any {\n const { function: func, field } = agg;\n \n const values = field ? records.map(r => getValueByPath(r, field)) : [];\n \n switch (func) {\n case 'count':\n if (!field || field === '*') return records.length;\n return values.filter(v => v !== null && v !== undefined).length;\n \n case 'sum':\n case 'avg': {\n const nums = values.filter(v => typeof v === 'number');\n const sum = nums.reduce((a, b) => a + b, 0);\n if (func === 'sum') return sum;\n return nums.length > 0 ? sum / nums.length : null;\n }\n \n case 'min': {\n // Handle comparable values\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n // Works for numbers and strings\n return valid.reduce((min, v) => (v < min ? v : min), valid[0]);\n }\n\n case 'max': {\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n return valid.reduce((max, v) => (v > max ? v : max), valid[0]);\n }\n\n default:\n return null;\n }\n }\n\n private setValueByPath(obj: any, path: string, value: any) {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) current[part] = {};\n current = current[part];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n // ===================================\n // Helpers\n // ===================================\n\n private getTable(name: string) {\n if (!this.db[name]) {\n this.db[name] = [];\n }\n return this.db[name];\n }\n\n private generateId() {\n return Math.random().toString(36).substring(2, 15);\n }\n}\n","\n/**\n * Simple In-Memory Query Matcher\n * \n * Implements a subset of the ObjectStack Filter Protocol (MongoDB-compatible)\n * for evaluating conditions against in-memory JavaScript objects.\n */\n\ntype RecordType = Record<string, any>;\n\n/**\n * matches - Check if a record matches a filter criteria\n * @param record The data record to check\n * @param filter The filter condition (where clause)\n */\nexport function match(record: RecordType, filter: any): boolean {\n if (!filter || Object.keys(filter).length === 0) return true;\n \n // 1. Handle Top-Level Logical Operators ($and, $or, $not)\n // These usually appear at the root or nested.\n \n // $and: [ { ... }, { ... } ]\n if (Array.isArray(filter.$and)) {\n if (!filter.$and.every((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $or: [ { ... }, { ... } ]\n if (Array.isArray(filter.$or)) {\n if (!filter.$or.some((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $not: { ... }\n if (filter.$not) {\n if (match(record, filter.$not)) {\n return false;\n }\n }\n \n // 2. Iterate over field constraints\n for (const key of Object.keys(filter)) {\n // Skip logical operators we already handled (or future ones)\n if (key.startsWith('$')) continue;\n \n const condition = filter[key];\n const value = getValueByPath(record, key);\n \n if (!checkCondition(value, condition)) {\n return false;\n }\n }\n \n return true;\n}\n\n/**\n * Access nested properties via dot-notation (e.g. \"user.name\")\n */\nexport function getValueByPath(obj: any, path: string): any {\n if (!path.includes('.')) return obj[path];\n return path.split('.').reduce((o, i) => (o ? o[i] : undefined), obj);\n}\n\n/**\n * Evaluate a specific condition against a value\n */\nfunction checkCondition(value: any, condition: any): boolean {\n // Case A: Implicit Equality (e.g. status: 'active')\n // If condition is a primitive or Date/Array (exact match), treat as equality.\n if (\n typeof condition !== 'object' || \n condition === null || \n condition instanceof Date ||\n Array.isArray(condition)\n ) {\n // Loose equality to handle undefined/null mismatch or string/number coercion if desired.\n // But stick to == for JS loose equality which is often convenient in weakly typed queries.\n return value == condition;\n }\n \n // Case B: Operator Object (e.g. { $gt: 10, $lt: 20 })\n const keys = Object.keys(condition);\n const isOperatorObject = keys.some(k => k.startsWith('$'));\n \n if (!isOperatorObject) {\n // It's just a nested object comparison or implicit equality against an object\n // Simplistic check:\n return JSON.stringify(value) === JSON.stringify(condition);\n }\n\n // Iterate operators\n for (const op of keys) {\n const target = condition[op];\n \n // Handle undefined values\n if (value === undefined && op !== '$exists' && op !== '$ne') {\n return false; \n }\n\n switch (op) {\n case '$eq': \n if (value != target) return false; \n break;\n case '$ne': \n if (value == target) return false; \n break;\n \n // Numeric / Date\n case '$gt': \n if (!(value > target)) return false; \n break;\n case '$gte': \n if (!(value >= target)) return false; \n break;\n case '$lt': \n if (!(value < target)) return false; \n break;\n case '$lte': \n if (!(value <= target)) return false; \n break;\n case '$between':\n // target should be [min, max]\n if (Array.isArray(target) && (value < target[0] || value > target[1])) return false;\n break;\n\n // Sets\n case '$in': \n if (!Array.isArray(target) || !target.includes(value)) return false; \n break;\n case '$nin': \n if (Array.isArray(target) && target.includes(value)) return false; \n break;\n \n // Existence\n case '$exists':\n const exists = value !== undefined && value !== null;\n if (exists !== !!target) return false;\n break;\n\n // Strings\n case '$contains': \n if (typeof value !== 'string' || !value.includes(target)) return false; \n break;\n case '$startsWith': \n if (typeof value !== 'string' || !value.startsWith(target)) return false; \n break;\n case '$endsWith': \n if (typeof value !== 'string' || !value.endsWith(target)) return false; \n break;\n case '$regex':\n try {\n const re = new RegExp(target, condition.$options || '');\n if (!re.test(String(value))) return false;\n } catch (e) { return false; }\n break;\n\n default: \n // Unknown operator, ignore or fail. Ignoring safe for optional features.\n break;\n }\n }\n \n return true;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/memory-driver.ts","../src/memory-matcher.ts"],"sourcesContent":["import { InMemoryDriver } from './memory-driver.js';\n\nexport { InMemoryDriver }; // Export class for direct usage\n\n// Note: In a real environment, you would import these from @objectstack/spec\n// But distinct PluginDefinition interface might not be strictly defined in schema yet, \n// usually it mimics the Manifest structure + runtime hooks.\n\n// For this example, we define a basic shape if not available, or use \"any\" to bypass strictness for the demo.\n// In plugin-bi it imported: import { PluginDefinition, PluginContextData } from '@objectstack/spec';\n\n// Let's rely on the environment being set up like plugin-bi.\n// If types are missing, this is just an example file.\n\nexport default {\n id: 'com.objectstack.driver.memory',\n version: '1.0.0',\n\n onEnable: async (context: any) => {\n const { logger, config, drivers } = context;\n logger.info('[Memory Driver] Initializing...');\n\n // Simulate driver registration\n // This assumes the runtime exposes a 'drivers' registry\n if (drivers) {\n const driver = new InMemoryDriver(config); // Pass config to driver\n drivers.register(driver);\n logger.info(`[Memory Driver] Registered driver: ${driver.name}`);\n } else {\n logger.warn('[Memory Driver] No driver registry found in context.');\n }\n }\n};\n","import { QueryAST, QueryInput } from '@objectstack/spec/data';\nimport { DriverOptions } from '@objectstack/spec/data';\nimport { DriverInterface, Logger, createLogger } from '@objectstack/core';\nimport { match, getValueByPath } from './memory-matcher.js';\n\n/**\n * Example: In-Memory Driver\n * \n * A minimal reference implementation of the ObjectStack Driver Protocol.\n * This driver stores data in a simple JavaScript object (Heap).\n */\nexport class InMemoryDriver implements DriverInterface {\n name = 'in-memory-driver';\n type = 'driver';\n version = '0.0.1';\n private config: any;\n private logger: Logger;\n\n constructor(config?: any) {\n this.config = config || {};\n this.logger = config?.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.debug('InMemory driver instance created', { config: this.config });\n }\n\n // Duck-typed RuntimePlugin hook\n install(ctx: any) {\n this.logger.debug('Installing InMemory driver via plugin hook');\n if (ctx.engine && ctx.engine.ql && typeof ctx.engine.ql.registerDriver === 'function') {\n ctx.engine.ql.registerDriver(this);\n this.logger.info('InMemory driver registered with ObjectQL engine');\n } else {\n this.logger.warn('Could not register driver - ObjectQL engine not found in context');\n }\n }\n \n supports = {\n // Transaction & Connection Management\n transactions: false, \n \n // Query Operations\n queryFilters: true, // Implemented via memory-matcher\n queryAggregations: true, // Implemented\n querySorting: true, // Implemented via JS sort\n queryPagination: true, // Implemented\n queryWindowFunctions: false, // TODO: Not implemented\n querySubqueries: false, // TODO: Not implemented\n joins: false, // TODO: Not implemented\n \n // Advanced Features\n fullTextSearch: false, // TODO: Not implemented\n vectorSearch: false, // TODO: Not implemented\n geoSpatial: false, // TODO: Not implemented\n jsonFields: true, // Native JS object support\n arrayFields: true, // Native JS array support\n };\n\n /**\n * The \"Database\": A map of TableName -> Array of Records\n */\n private db: Record<string, any[]> = {};\n\n // ===================================\n // Lifecycle\n // ===================================\n\n async connect() {\n this.logger.info('InMemory Database Connected (Virtual)');\n }\n\n async disconnect() {\n const tableCount = Object.keys(this.db).length;\n const recordCount = Object.values(this.db).reduce((sum, table) => sum + table.length, 0);\n \n this.db = {};\n this.logger.info('InMemory Database Disconnected & Cleared', { \n tableCount, \n recordCount \n });\n }\n\n async checkHealth() {\n this.logger.debug('Health check performed', { \n tableCount: Object.keys(this.db).length,\n status: 'healthy' \n });\n return true; \n }\n\n // ===================================\n // Execution\n // ===================================\n\n async execute(command: any, params?: any[]) {\n this.logger.warn('Raw execution not supported in InMemory driver', { command });\n return null;\n }\n\n // ===================================\n // CRUD\n // ===================================\n\n async find(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('Find operation', { object, query });\n \n const table = this.getTable(object);\n let results = table;\n\n // 1. Filter\n if (query.where) {\n results = results.filter(record => match(record, query.where));\n }\n\n // 1.5 Aggregation & Grouping\n if (query.groupBy || (query.aggregations && query.aggregations.length > 0)) {\n results = this.performAggregation(results, query);\n }\n\n // 2. Sort\n if (query.orderBy) {\n // Normalize sort to array\n const sortFields = Array.isArray(query.orderBy) ? query.orderBy : [query.orderBy];\n \n results.sort((a, b) => {\n for (const { field, order } of sortFields) {\n const valA = getValueByPath(a, field);\n const valB = getValueByPath(b, field);\n \n if (valA === valB) continue;\n \n const comparison = valA > valB ? 1 : -1;\n return order === 'desc' ? -comparison : comparison;\n }\n return 0;\n });\n }\n\n // 3. Pagination (Offset)\n if (query.offset) {\n results = results.slice(query.offset);\n }\n\n // 4. Pagination (Limit)\n if (query.limit) {\n results = results.slice(0, query.limit);\n }\n\n this.logger.debug('Find completed', { object, resultCount: results.length });\n return results;\n }\n\n async *findStream(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindStream operation', { object });\n \n const results = await this.find(object, query, options);\n for (const record of results) {\n yield record;\n }\n }\n\n async findOne(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindOne operation', { object, query });\n \n const results = await this.find(object, { ...query, limit: 1 }, options);\n const result = results[0] || null;\n \n this.logger.debug('FindOne completed', { object, found: !!result });\n return result;\n }\n\n async create(object: string, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Create operation', { object, hasData: !!data });\n \n const table = this.getTable(object);\n \n // COMPATIBILITY: Driver must return 'id' as string\n const newRecord = {\n id: data.id || this.generateId(),\n ...data,\n created_at: data.created_at || new Date(),\n updated_at: data.updated_at || new Date(),\n };\n\n table.push(newRecord);\n this.logger.debug('Record created', { object, id: newRecord.id, tableSize: table.length });\n return newRecord;\n }\n\n async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Update operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for update', { object, id });\n throw new Error(`Record with ID ${id} not found in ${object}`);\n }\n\n const updatedRecord = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n \n table[index] = updatedRecord;\n this.logger.debug('Record updated', { object, id });\n return updatedRecord;\n }\n\n async upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions) {\n this.logger.debug('Upsert operation', { object, conflictKeys });\n \n const table = this.getTable(object);\n let existingRecord: any = null;\n\n if (data.id) {\n existingRecord = table.find(r => r.id === data.id);\n } else if (conflictKeys && conflictKeys.length > 0) {\n existingRecord = table.find(r => conflictKeys.every(key => r[key] === data[key]));\n }\n\n if (existingRecord) {\n this.logger.debug('Record exists, updating', { object, id: existingRecord.id });\n return this.update(object, existingRecord.id, data, options);\n } else {\n this.logger.debug('Record does not exist, creating', { object });\n return this.create(object, data, options);\n }\n }\n\n async delete(object: string, id: string | number, options?: DriverOptions) {\n this.logger.debug('Delete operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for deletion', { object, id });\n return false;\n }\n\n table.splice(index, 1);\n this.logger.debug('Record deleted', { object, id, tableSize: table.length });\n return true;\n }\n\n async count(object: string, query?: QueryInput, options?: DriverOptions) {\n let results = this.getTable(object);\n if (query?.where) {\n results = results.filter(record => match(record, query.where));\n }\n const count = results.length;\n this.logger.debug('Count operation', { object, count });\n return count;\n }\n\n // ===================================\n // Bulk Operations\n // ===================================\n\n async bulkCreate(object: string, dataArray: Record<string, any>[], options?: DriverOptions) {\n this.logger.debug('BulkCreate operation', { object, count: dataArray.length });\n const results = await Promise.all(dataArray.map(data => this.create(object, data, options)));\n this.logger.debug('BulkCreate completed', { object, count: results.length });\n return results;\n }\n \n async updateMany(object: string, query: QueryInput, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('UpdateMany operation', { object, query });\n \n const table = this.getTable(object);\n let targetRecords = table;\n \n if (query && query.where) {\n targetRecords = targetRecords.filter(r => match(r, query.where));\n }\n \n const count = targetRecords.length;\n \n // Update each record\n for (const record of targetRecords) {\n // Find index in original table\n const index = table.findIndex(r => r.id === record.id);\n if (index !== -1) {\n const updated = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n table[index] = updated;\n }\n }\n \n this.logger.debug('UpdateMany completed', { object, count });\n return { count };\n }\n\n async deleteMany(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('DeleteMany operation', { object, query });\n \n const table = this.getTable(object);\n const initialLength = table.length;\n \n // Filter IN PLACE or create new array?\n // Creating new array is safer for now.\n \n const remaining = table.filter(r => {\n if (!query || !query.where) return false; // Delete all? No, standard safety implies explicit empty filter for delete all.\n // Wait, normally deleteMany({}) deletes all.\n // Let's assume if query passed, use it.\n const matches = match(r, query.where);\n return !matches; // Keep if it DOES NOT match\n });\n \n this.db[object] = remaining;\n const count = initialLength - remaining.length;\n \n this.logger.debug('DeleteMany completed', { object, count });\n return { count };\n }\n\n // Compatibility aliases\n async bulkUpdate(object: string, updates: { id: string | number, data: Record<string, any> }[], options?: DriverOptions) {\n this.logger.debug('BulkUpdate operation', { object, count: updates.length });\n const results = await Promise.all(updates.map(u => this.update(object, u.id, u.data, options)));\n this.logger.debug('BulkUpdate completed', { object, count: results.length });\n return results;\n }\n\n async bulkDelete(object: string, ids: (string | number)[], options?: DriverOptions) {\n this.logger.debug('BulkDelete operation', { object, count: ids.length });\n await Promise.all(ids.map(id => this.delete(object, id, options)));\n this.logger.debug('BulkDelete completed', { object, count: ids.length });\n }\n\n // ===================================\n // Schema & Transactions\n // ===================================\n\n async syncSchema(object: string, schema: any, options?: DriverOptions) {\n if (!this.db[object]) {\n this.db[object] = [];\n this.logger.info('Created in-memory table', { object });\n }\n }\n\n async dropTable(object: string, options?: DriverOptions) {\n if (this.db[object]) {\n const recordCount = this.db[object].length;\n delete this.db[object];\n this.logger.info('Dropped in-memory table', { object, recordCount });\n }\n }\n\n async beginTransaction() {\n throw new Error('Transactions not supported in InMemoryDriver');\n }\n\n async commit() { /* No-op */ }\n async rollback() { /* No-op */ }\n\n // ===================================\n // Aggregation Logic\n // ===================================\n\n private performAggregation(records: any[], query: QueryInput): any[] {\n const { groupBy, aggregations } = query;\n const groups: Map<string, any[]> = new Map();\n\n // 1. Group records\n if (groupBy && groupBy.length > 0) {\n for (const record of records) {\n // Create a composite key from group values\n const keyParts = groupBy.map(field => {\n const val = getValueByPath(record, field);\n return val === undefined || val === null ? 'null' : String(val);\n });\n const key = JSON.stringify(keyParts);\n \n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n } else {\n // No grouping -> Single group containing all records\n // If aggregation is requested without group by, it runs on whole set (even if empty)\n if (aggregations && aggregations.length > 0) {\n groups.set('all', records);\n } else {\n // Should not be here if performAggregation called correctly\n groups.set('all', records);\n }\n }\n\n // 2. Compute aggregates for each group\n const resultRows: any[] = [];\n \n for (const [key, groupRecords] of groups.entries()) {\n const row: any = {};\n \n // A. Add Group fields to row (if groupBy exists)\n if (groupBy && groupBy.length > 0) {\n if (groupRecords.length > 0) {\n const firstRecord = groupRecords[0];\n for (const field of groupBy) {\n this.setValueByPath(row, field, getValueByPath(firstRecord, field));\n }\n }\n }\n \n // B. Compute Aggregations\n if (aggregations) {\n for (const agg of aggregations) {\n const value = this.computeAggregate(groupRecords, agg);\n row[agg.alias] = value;\n }\n }\n \n resultRows.push(row);\n }\n \n return resultRows;\n }\n \n private computeAggregate(records: any[], agg: any): any {\n const { function: func, field } = agg;\n \n const values = field ? records.map(r => getValueByPath(r, field)) : [];\n \n switch (func) {\n case 'count':\n if (!field || field === '*') return records.length;\n return values.filter(v => v !== null && v !== undefined).length;\n \n case 'sum':\n case 'avg': {\n const nums = values.filter(v => typeof v === 'number');\n const sum = nums.reduce((a, b) => a + b, 0);\n if (func === 'sum') return sum;\n return nums.length > 0 ? sum / nums.length : null;\n }\n \n case 'min': {\n // Handle comparable values\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n // Works for numbers and strings\n return valid.reduce((min, v) => (v < min ? v : min), valid[0]);\n }\n\n case 'max': {\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n return valid.reduce((max, v) => (v > max ? v : max), valid[0]);\n }\n\n default:\n return null;\n }\n }\n\n private setValueByPath(obj: any, path: string, value: any) {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) current[part] = {};\n current = current[part];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n // ===================================\n // Helpers\n // ===================================\n\n private getTable(name: string) {\n if (!this.db[name]) {\n this.db[name] = [];\n }\n return this.db[name];\n }\n\n private generateId() {\n return Math.random().toString(36).substring(2, 15);\n }\n}\n","\n/**\n * Simple In-Memory Query Matcher\n * \n * Implements a subset of the ObjectStack Filter Protocol (MongoDB-compatible)\n * for evaluating conditions against in-memory JavaScript objects.\n */\n\ntype RecordType = Record<string, any>;\n\n/**\n * matches - Check if a record matches a filter criteria\n * @param record The data record to check\n * @param filter The filter condition (where clause)\n */\nexport function match(record: RecordType, filter: any): boolean {\n if (!filter || Object.keys(filter).length === 0) return true;\n \n // 1. Handle Top-Level Logical Operators ($and, $or, $not)\n // These usually appear at the root or nested.\n \n // $and: [ { ... }, { ... } ]\n if (Array.isArray(filter.$and)) {\n if (!filter.$and.every((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $or: [ { ... }, { ... } ]\n if (Array.isArray(filter.$or)) {\n if (!filter.$or.some((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $not: { ... }\n if (filter.$not) {\n if (match(record, filter.$not)) {\n return false;\n }\n }\n \n // 2. Iterate over field constraints\n for (const key of Object.keys(filter)) {\n // Skip logical operators we already handled (or future ones)\n if (key.startsWith('$')) continue;\n \n const condition = filter[key];\n const value = getValueByPath(record, key);\n \n if (!checkCondition(value, condition)) {\n return false;\n }\n }\n \n return true;\n}\n\n/**\n * Access nested properties via dot-notation (e.g. \"user.name\")\n */\nexport function getValueByPath(obj: any, path: string): any {\n if (!path.includes('.')) return obj[path];\n return path.split('.').reduce((o, i) => (o ? o[i] : undefined), obj);\n}\n\n/**\n * Evaluate a specific condition against a value\n */\nfunction checkCondition(value: any, condition: any): boolean {\n // Case A: Implicit Equality (e.g. status: 'active')\n // If condition is a primitive or Date/Array (exact match), treat as equality.\n if (\n typeof condition !== 'object' || \n condition === null || \n condition instanceof Date ||\n Array.isArray(condition)\n ) {\n // Loose equality to handle undefined/null mismatch or string/number coercion if desired.\n // But stick to == for JS loose equality which is often convenient in weakly typed queries.\n return value == condition;\n }\n \n // Case B: Operator Object (e.g. { $gt: 10, $lt: 20 })\n const keys = Object.keys(condition);\n const isOperatorObject = keys.some(k => k.startsWith('$'));\n \n if (!isOperatorObject) {\n // It's just a nested object comparison or implicit equality against an object\n // Simplistic check:\n return JSON.stringify(value) === JSON.stringify(condition);\n }\n\n // Iterate operators\n for (const op of keys) {\n const target = condition[op];\n \n // Handle undefined values\n if (value === undefined && op !== '$exists' && op !== '$ne') {\n return false; \n }\n\n switch (op) {\n case '$eq': \n if (value != target) return false; \n break;\n case '$ne': \n if (value == target) return false; \n break;\n \n // Numeric / Date\n case '$gt': \n if (!(value > target)) return false; \n break;\n case '$gte': \n if (!(value >= target)) return false; \n break;\n case '$lt': \n if (!(value < target)) return false; \n break;\n case '$lte': \n if (!(value <= target)) return false; \n break;\n case '$between':\n // target should be [min, max]\n if (Array.isArray(target) && (value < target[0] || value > target[1])) return false;\n break;\n\n // Sets\n case '$in': \n if (!Array.isArray(target) || !target.includes(value)) return false; \n break;\n case '$nin': \n if (Array.isArray(target) && target.includes(value)) return false; \n break;\n \n // Existence\n case '$exists':\n const exists = value !== undefined && value !== null;\n if (exists !== !!target) return false;\n break;\n\n // Strings\n case '$contains': \n if (typeof value !== 'string' || !value.includes(target)) return false; \n break;\n case '$startsWith': \n if (typeof value !== 'string' || !value.startsWith(target)) return false; \n break;\n case '$endsWith': \n if (typeof value !== 'string' || !value.endsWith(target)) return false; \n break;\n case '$regex':\n try {\n const re = new RegExp(target, condition.$options || '');\n if (!re.test(String(value))) return false;\n } catch (e) { return false; }\n break;\n\n default: \n // Unknown operator, ignore or fail. Ignoring safe for optional features.\n break;\n }\n }\n \n return true;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -111,6 +111,7 @@ function checkCondition(value, condition) {
|
|
|
111
111
|
var InMemoryDriver = class {
|
|
112
112
|
constructor(config) {
|
|
113
113
|
this.name = "in-memory-driver";
|
|
114
|
+
this.type = "driver";
|
|
114
115
|
this.version = "0.0.1";
|
|
115
116
|
this.supports = {
|
|
116
117
|
// Transaction & Connection Management
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/memory-driver.ts","../src/memory-matcher.ts","../src/index.ts"],"sourcesContent":["import { QueryAST, QueryInput } from '@objectstack/spec/data';\nimport { DriverOptions } from '@objectstack/spec/data';\nimport { DriverInterface, Logger, createLogger } from '@objectstack/core';\nimport { match, getValueByPath } from './memory-matcher.js';\n\n/**\n * Example: In-Memory Driver\n * \n * A minimal reference implementation of the ObjectStack Driver Protocol.\n * This driver stores data in a simple JavaScript object (Heap).\n */\nexport class InMemoryDriver implements DriverInterface {\n name = 'in-memory-driver';\n version = '0.0.1';\n private config: any;\n private logger: Logger;\n\n constructor(config?: any) {\n this.config = config || {};\n this.logger = config?.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.debug('InMemory driver instance created', { config: this.config });\n }\n\n // Duck-typed RuntimePlugin hook\n install(ctx: any) {\n this.logger.debug('Installing InMemory driver via plugin hook');\n if (ctx.engine && ctx.engine.ql && typeof ctx.engine.ql.registerDriver === 'function') {\n ctx.engine.ql.registerDriver(this);\n this.logger.info('InMemory driver registered with ObjectQL engine');\n } else {\n this.logger.warn('Could not register driver - ObjectQL engine not found in context');\n }\n }\n \n supports = {\n // Transaction & Connection Management\n transactions: false, \n \n // Query Operations\n queryFilters: true, // Implemented via memory-matcher\n queryAggregations: true, // Implemented\n querySorting: true, // Implemented via JS sort\n queryPagination: true, // Implemented\n queryWindowFunctions: false, // TODO: Not implemented\n querySubqueries: false, // TODO: Not implemented\n joins: false, // TODO: Not implemented\n \n // Advanced Features\n fullTextSearch: false, // TODO: Not implemented\n vectorSearch: false, // TODO: Not implemented\n geoSpatial: false, // TODO: Not implemented\n jsonFields: true, // Native JS object support\n arrayFields: true, // Native JS array support\n };\n\n /**\n * The \"Database\": A map of TableName -> Array of Records\n */\n private db: Record<string, any[]> = {};\n\n // ===================================\n // Lifecycle\n // ===================================\n\n async connect() {\n this.logger.info('InMemory Database Connected (Virtual)');\n }\n\n async disconnect() {\n const tableCount = Object.keys(this.db).length;\n const recordCount = Object.values(this.db).reduce((sum, table) => sum + table.length, 0);\n \n this.db = {};\n this.logger.info('InMemory Database Disconnected & Cleared', { \n tableCount, \n recordCount \n });\n }\n\n async checkHealth() {\n this.logger.debug('Health check performed', { \n tableCount: Object.keys(this.db).length,\n status: 'healthy' \n });\n return true; \n }\n\n // ===================================\n // Execution\n // ===================================\n\n async execute(command: any, params?: any[]) {\n this.logger.warn('Raw execution not supported in InMemory driver', { command });\n return null;\n }\n\n // ===================================\n // CRUD\n // ===================================\n\n async find(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('Find operation', { object, query });\n \n const table = this.getTable(object);\n let results = table;\n\n // 1. Filter\n if (query.where) {\n results = results.filter(record => match(record, query.where));\n }\n\n // 1.5 Aggregation & Grouping\n if (query.groupBy || (query.aggregations && query.aggregations.length > 0)) {\n results = this.performAggregation(results, query);\n }\n\n // 2. Sort\n if (query.orderBy) {\n // Normalize sort to array\n const sortFields = Array.isArray(query.orderBy) ? query.orderBy : [query.orderBy];\n \n results.sort((a, b) => {\n for (const { field, order } of sortFields) {\n const valA = getValueByPath(a, field);\n const valB = getValueByPath(b, field);\n \n if (valA === valB) continue;\n \n const comparison = valA > valB ? 1 : -1;\n return order === 'desc' ? -comparison : comparison;\n }\n return 0;\n });\n }\n\n // 3. Pagination (Offset)\n if (query.offset) {\n results = results.slice(query.offset);\n }\n\n // 4. Pagination (Limit)\n if (query.limit) {\n results = results.slice(0, query.limit);\n }\n\n this.logger.debug('Find completed', { object, resultCount: results.length });\n return results;\n }\n\n async *findStream(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindStream operation', { object });\n \n const results = await this.find(object, query, options);\n for (const record of results) {\n yield record;\n }\n }\n\n async findOne(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindOne operation', { object, query });\n \n const results = await this.find(object, { ...query, limit: 1 }, options);\n const result = results[0] || null;\n \n this.logger.debug('FindOne completed', { object, found: !!result });\n return result;\n }\n\n async create(object: string, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Create operation', { object, hasData: !!data });\n \n const table = this.getTable(object);\n \n // COMPATIBILITY: Driver must return 'id' as string\n const newRecord = {\n id: data.id || this.generateId(),\n ...data,\n created_at: data.created_at || new Date(),\n updated_at: data.updated_at || new Date(),\n };\n\n table.push(newRecord);\n this.logger.debug('Record created', { object, id: newRecord.id, tableSize: table.length });\n return newRecord;\n }\n\n async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Update operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for update', { object, id });\n throw new Error(`Record with ID ${id} not found in ${object}`);\n }\n\n const updatedRecord = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n \n table[index] = updatedRecord;\n this.logger.debug('Record updated', { object, id });\n return updatedRecord;\n }\n\n async upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions) {\n this.logger.debug('Upsert operation', { object, conflictKeys });\n \n const table = this.getTable(object);\n let existingRecord: any = null;\n\n if (data.id) {\n existingRecord = table.find(r => r.id === data.id);\n } else if (conflictKeys && conflictKeys.length > 0) {\n existingRecord = table.find(r => conflictKeys.every(key => r[key] === data[key]));\n }\n\n if (existingRecord) {\n this.logger.debug('Record exists, updating', { object, id: existingRecord.id });\n return this.update(object, existingRecord.id, data, options);\n } else {\n this.logger.debug('Record does not exist, creating', { object });\n return this.create(object, data, options);\n }\n }\n\n async delete(object: string, id: string | number, options?: DriverOptions) {\n this.logger.debug('Delete operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for deletion', { object, id });\n return false;\n }\n\n table.splice(index, 1);\n this.logger.debug('Record deleted', { object, id, tableSize: table.length });\n return true;\n }\n\n async count(object: string, query?: QueryInput, options?: DriverOptions) {\n let results = this.getTable(object);\n if (query?.where) {\n results = results.filter(record => match(record, query.where));\n }\n const count = results.length;\n this.logger.debug('Count operation', { object, count });\n return count;\n }\n\n // ===================================\n // Bulk Operations\n // ===================================\n\n async bulkCreate(object: string, dataArray: Record<string, any>[], options?: DriverOptions) {\n this.logger.debug('BulkCreate operation', { object, count: dataArray.length });\n const results = await Promise.all(dataArray.map(data => this.create(object, data, options)));\n this.logger.debug('BulkCreate completed', { object, count: results.length });\n return results;\n }\n \n async updateMany(object: string, query: QueryInput, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('UpdateMany operation', { object, query });\n \n const table = this.getTable(object);\n let targetRecords = table;\n \n if (query && query.where) {\n targetRecords = targetRecords.filter(r => match(r, query.where));\n }\n \n const count = targetRecords.length;\n \n // Update each record\n for (const record of targetRecords) {\n // Find index in original table\n const index = table.findIndex(r => r.id === record.id);\n if (index !== -1) {\n const updated = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n table[index] = updated;\n }\n }\n \n this.logger.debug('UpdateMany completed', { object, count });\n return { count };\n }\n\n async deleteMany(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('DeleteMany operation', { object, query });\n \n const table = this.getTable(object);\n const initialLength = table.length;\n \n // Filter IN PLACE or create new array?\n // Creating new array is safer for now.\n \n const remaining = table.filter(r => {\n if (!query || !query.where) return false; // Delete all? No, standard safety implies explicit empty filter for delete all.\n // Wait, normally deleteMany({}) deletes all.\n // Let's assume if query passed, use it.\n const matches = match(r, query.where);\n return !matches; // Keep if it DOES NOT match\n });\n \n this.db[object] = remaining;\n const count = initialLength - remaining.length;\n \n this.logger.debug('DeleteMany completed', { object, count });\n return { count };\n }\n\n // Compatibility aliases\n async bulkUpdate(object: string, updates: { id: string | number, data: Record<string, any> }[], options?: DriverOptions) {\n this.logger.debug('BulkUpdate operation', { object, count: updates.length });\n const results = await Promise.all(updates.map(u => this.update(object, u.id, u.data, options)));\n this.logger.debug('BulkUpdate completed', { object, count: results.length });\n return results;\n }\n\n async bulkDelete(object: string, ids: (string | number)[], options?: DriverOptions) {\n this.logger.debug('BulkDelete operation', { object, count: ids.length });\n await Promise.all(ids.map(id => this.delete(object, id, options)));\n this.logger.debug('BulkDelete completed', { object, count: ids.length });\n }\n\n // ===================================\n // Schema & Transactions\n // ===================================\n\n async syncSchema(object: string, schema: any, options?: DriverOptions) {\n if (!this.db[object]) {\n this.db[object] = [];\n this.logger.info('Created in-memory table', { object });\n }\n }\n\n async dropTable(object: string, options?: DriverOptions) {\n if (this.db[object]) {\n const recordCount = this.db[object].length;\n delete this.db[object];\n this.logger.info('Dropped in-memory table', { object, recordCount });\n }\n }\n\n async beginTransaction() {\n throw new Error('Transactions not supported in InMemoryDriver');\n }\n\n async commit() { /* No-op */ }\n async rollback() { /* No-op */ }\n\n // ===================================\n // Aggregation Logic\n // ===================================\n\n private performAggregation(records: any[], query: QueryInput): any[] {\n const { groupBy, aggregations } = query;\n const groups: Map<string, any[]> = new Map();\n\n // 1. Group records\n if (groupBy && groupBy.length > 0) {\n for (const record of records) {\n // Create a composite key from group values\n const keyParts = groupBy.map(field => {\n const val = getValueByPath(record, field);\n return val === undefined || val === null ? 'null' : String(val);\n });\n const key = JSON.stringify(keyParts);\n \n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n } else {\n // No grouping -> Single group containing all records\n // If aggregation is requested without group by, it runs on whole set (even if empty)\n if (aggregations && aggregations.length > 0) {\n groups.set('all', records);\n } else {\n // Should not be here if performAggregation called correctly\n groups.set('all', records);\n }\n }\n\n // 2. Compute aggregates for each group\n const resultRows: any[] = [];\n \n for (const [key, groupRecords] of groups.entries()) {\n const row: any = {};\n \n // A. Add Group fields to row (if groupBy exists)\n if (groupBy && groupBy.length > 0) {\n if (groupRecords.length > 0) {\n const firstRecord = groupRecords[0];\n for (const field of groupBy) {\n this.setValueByPath(row, field, getValueByPath(firstRecord, field));\n }\n }\n }\n \n // B. Compute Aggregations\n if (aggregations) {\n for (const agg of aggregations) {\n const value = this.computeAggregate(groupRecords, agg);\n row[agg.alias] = value;\n }\n }\n \n resultRows.push(row);\n }\n \n return resultRows;\n }\n \n private computeAggregate(records: any[], agg: any): any {\n const { function: func, field } = agg;\n \n const values = field ? records.map(r => getValueByPath(r, field)) : [];\n \n switch (func) {\n case 'count':\n if (!field || field === '*') return records.length;\n return values.filter(v => v !== null && v !== undefined).length;\n \n case 'sum':\n case 'avg': {\n const nums = values.filter(v => typeof v === 'number');\n const sum = nums.reduce((a, b) => a + b, 0);\n if (func === 'sum') return sum;\n return nums.length > 0 ? sum / nums.length : null;\n }\n \n case 'min': {\n // Handle comparable values\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n // Works for numbers and strings\n return valid.reduce((min, v) => (v < min ? v : min), valid[0]);\n }\n\n case 'max': {\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n return valid.reduce((max, v) => (v > max ? v : max), valid[0]);\n }\n\n default:\n return null;\n }\n }\n\n private setValueByPath(obj: any, path: string, value: any) {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) current[part] = {};\n current = current[part];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n // ===================================\n // Helpers\n // ===================================\n\n private getTable(name: string) {\n if (!this.db[name]) {\n this.db[name] = [];\n }\n return this.db[name];\n }\n\n private generateId() {\n return Math.random().toString(36).substring(2, 15);\n }\n}\n","\n/**\n * Simple In-Memory Query Matcher\n * \n * Implements a subset of the ObjectStack Filter Protocol (MongoDB-compatible)\n * for evaluating conditions against in-memory JavaScript objects.\n */\n\ntype RecordType = Record<string, any>;\n\n/**\n * matches - Check if a record matches a filter criteria\n * @param record The data record to check\n * @param filter The filter condition (where clause)\n */\nexport function match(record: RecordType, filter: any): boolean {\n if (!filter || Object.keys(filter).length === 0) return true;\n \n // 1. Handle Top-Level Logical Operators ($and, $or, $not)\n // These usually appear at the root or nested.\n \n // $and: [ { ... }, { ... } ]\n if (Array.isArray(filter.$and)) {\n if (!filter.$and.every((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $or: [ { ... }, { ... } ]\n if (Array.isArray(filter.$or)) {\n if (!filter.$or.some((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $not: { ... }\n if (filter.$not) {\n if (match(record, filter.$not)) {\n return false;\n }\n }\n \n // 2. Iterate over field constraints\n for (const key of Object.keys(filter)) {\n // Skip logical operators we already handled (or future ones)\n if (key.startsWith('$')) continue;\n \n const condition = filter[key];\n const value = getValueByPath(record, key);\n \n if (!checkCondition(value, condition)) {\n return false;\n }\n }\n \n return true;\n}\n\n/**\n * Access nested properties via dot-notation (e.g. \"user.name\")\n */\nexport function getValueByPath(obj: any, path: string): any {\n if (!path.includes('.')) return obj[path];\n return path.split('.').reduce((o, i) => (o ? o[i] : undefined), obj);\n}\n\n/**\n * Evaluate a specific condition against a value\n */\nfunction checkCondition(value: any, condition: any): boolean {\n // Case A: Implicit Equality (e.g. status: 'active')\n // If condition is a primitive or Date/Array (exact match), treat as equality.\n if (\n typeof condition !== 'object' || \n condition === null || \n condition instanceof Date ||\n Array.isArray(condition)\n ) {\n // Loose equality to handle undefined/null mismatch or string/number coercion if desired.\n // But stick to == for JS loose equality which is often convenient in weakly typed queries.\n return value == condition;\n }\n \n // Case B: Operator Object (e.g. { $gt: 10, $lt: 20 })\n const keys = Object.keys(condition);\n const isOperatorObject = keys.some(k => k.startsWith('$'));\n \n if (!isOperatorObject) {\n // It's just a nested object comparison or implicit equality against an object\n // Simplistic check:\n return JSON.stringify(value) === JSON.stringify(condition);\n }\n\n // Iterate operators\n for (const op of keys) {\n const target = condition[op];\n \n // Handle undefined values\n if (value === undefined && op !== '$exists' && op !== '$ne') {\n return false; \n }\n\n switch (op) {\n case '$eq': \n if (value != target) return false; \n break;\n case '$ne': \n if (value == target) return false; \n break;\n \n // Numeric / Date\n case '$gt': \n if (!(value > target)) return false; \n break;\n case '$gte': \n if (!(value >= target)) return false; \n break;\n case '$lt': \n if (!(value < target)) return false; \n break;\n case '$lte': \n if (!(value <= target)) return false; \n break;\n case '$between':\n // target should be [min, max]\n if (Array.isArray(target) && (value < target[0] || value > target[1])) return false;\n break;\n\n // Sets\n case '$in': \n if (!Array.isArray(target) || !target.includes(value)) return false; \n break;\n case '$nin': \n if (Array.isArray(target) && target.includes(value)) return false; \n break;\n \n // Existence\n case '$exists':\n const exists = value !== undefined && value !== null;\n if (exists !== !!target) return false;\n break;\n\n // Strings\n case '$contains': \n if (typeof value !== 'string' || !value.includes(target)) return false; \n break;\n case '$startsWith': \n if (typeof value !== 'string' || !value.startsWith(target)) return false; \n break;\n case '$endsWith': \n if (typeof value !== 'string' || !value.endsWith(target)) return false; \n break;\n case '$regex':\n try {\n const re = new RegExp(target, condition.$options || '');\n if (!re.test(String(value))) return false;\n } catch (e) { return false; }\n break;\n\n default: \n // Unknown operator, ignore or fail. Ignoring safe for optional features.\n break;\n }\n }\n \n return true;\n}\n","import { InMemoryDriver } from './memory-driver.js';\n\nexport { InMemoryDriver }; // Export class for direct usage\n\n// Note: In a real environment, you would import these from @objectstack/spec\n// But distinct PluginDefinition interface might not be strictly defined in schema yet, \n// usually it mimics the Manifest structure + runtime hooks.\n\n// For this example, we define a basic shape if not available, or use \"any\" to bypass strictness for the demo.\n// In plugin-bi it imported: import { PluginDefinition, PluginContextData } from '@objectstack/spec';\n\n// Let's rely on the environment being set up like plugin-bi.\n// If types are missing, this is just an example file.\n\nexport default {\n id: 'com.objectstack.driver.memory',\n version: '1.0.0',\n\n onEnable: async (context: any) => {\n const { logger, config, drivers } = context;\n logger.info('[Memory Driver] Initializing...');\n\n // Simulate driver registration\n // This assumes the runtime exposes a 'drivers' registry\n if (drivers) {\n const driver = new InMemoryDriver(config); // Pass config to driver\n drivers.register(driver);\n logger.info(`[Memory Driver] Registered driver: ${driver.name}`);\n } else {\n logger.warn('[Memory Driver] No driver registry found in context.');\n }\n }\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/memory-driver.ts","../src/memory-matcher.ts","../src/index.ts"],"sourcesContent":["import { QueryAST, QueryInput } from '@objectstack/spec/data';\nimport { DriverOptions } from '@objectstack/spec/data';\nimport { DriverInterface, Logger, createLogger } from '@objectstack/core';\nimport { match, getValueByPath } from './memory-matcher.js';\n\n/**\n * Example: In-Memory Driver\n * \n * A minimal reference implementation of the ObjectStack Driver Protocol.\n * This driver stores data in a simple JavaScript object (Heap).\n */\nexport class InMemoryDriver implements DriverInterface {\n name = 'in-memory-driver';\n type = 'driver';\n version = '0.0.1';\n private config: any;\n private logger: Logger;\n\n constructor(config?: any) {\n this.config = config || {};\n this.logger = config?.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.debug('InMemory driver instance created', { config: this.config });\n }\n\n // Duck-typed RuntimePlugin hook\n install(ctx: any) {\n this.logger.debug('Installing InMemory driver via plugin hook');\n if (ctx.engine && ctx.engine.ql && typeof ctx.engine.ql.registerDriver === 'function') {\n ctx.engine.ql.registerDriver(this);\n this.logger.info('InMemory driver registered with ObjectQL engine');\n } else {\n this.logger.warn('Could not register driver - ObjectQL engine not found in context');\n }\n }\n \n supports = {\n // Transaction & Connection Management\n transactions: false, \n \n // Query Operations\n queryFilters: true, // Implemented via memory-matcher\n queryAggregations: true, // Implemented\n querySorting: true, // Implemented via JS sort\n queryPagination: true, // Implemented\n queryWindowFunctions: false, // TODO: Not implemented\n querySubqueries: false, // TODO: Not implemented\n joins: false, // TODO: Not implemented\n \n // Advanced Features\n fullTextSearch: false, // TODO: Not implemented\n vectorSearch: false, // TODO: Not implemented\n geoSpatial: false, // TODO: Not implemented\n jsonFields: true, // Native JS object support\n arrayFields: true, // Native JS array support\n };\n\n /**\n * The \"Database\": A map of TableName -> Array of Records\n */\n private db: Record<string, any[]> = {};\n\n // ===================================\n // Lifecycle\n // ===================================\n\n async connect() {\n this.logger.info('InMemory Database Connected (Virtual)');\n }\n\n async disconnect() {\n const tableCount = Object.keys(this.db).length;\n const recordCount = Object.values(this.db).reduce((sum, table) => sum + table.length, 0);\n \n this.db = {};\n this.logger.info('InMemory Database Disconnected & Cleared', { \n tableCount, \n recordCount \n });\n }\n\n async checkHealth() {\n this.logger.debug('Health check performed', { \n tableCount: Object.keys(this.db).length,\n status: 'healthy' \n });\n return true; \n }\n\n // ===================================\n // Execution\n // ===================================\n\n async execute(command: any, params?: any[]) {\n this.logger.warn('Raw execution not supported in InMemory driver', { command });\n return null;\n }\n\n // ===================================\n // CRUD\n // ===================================\n\n async find(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('Find operation', { object, query });\n \n const table = this.getTable(object);\n let results = table;\n\n // 1. Filter\n if (query.where) {\n results = results.filter(record => match(record, query.where));\n }\n\n // 1.5 Aggregation & Grouping\n if (query.groupBy || (query.aggregations && query.aggregations.length > 0)) {\n results = this.performAggregation(results, query);\n }\n\n // 2. Sort\n if (query.orderBy) {\n // Normalize sort to array\n const sortFields = Array.isArray(query.orderBy) ? query.orderBy : [query.orderBy];\n \n results.sort((a, b) => {\n for (const { field, order } of sortFields) {\n const valA = getValueByPath(a, field);\n const valB = getValueByPath(b, field);\n \n if (valA === valB) continue;\n \n const comparison = valA > valB ? 1 : -1;\n return order === 'desc' ? -comparison : comparison;\n }\n return 0;\n });\n }\n\n // 3. Pagination (Offset)\n if (query.offset) {\n results = results.slice(query.offset);\n }\n\n // 4. Pagination (Limit)\n if (query.limit) {\n results = results.slice(0, query.limit);\n }\n\n this.logger.debug('Find completed', { object, resultCount: results.length });\n return results;\n }\n\n async *findStream(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindStream operation', { object });\n \n const results = await this.find(object, query, options);\n for (const record of results) {\n yield record;\n }\n }\n\n async findOne(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('FindOne operation', { object, query });\n \n const results = await this.find(object, { ...query, limit: 1 }, options);\n const result = results[0] || null;\n \n this.logger.debug('FindOne completed', { object, found: !!result });\n return result;\n }\n\n async create(object: string, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Create operation', { object, hasData: !!data });\n \n const table = this.getTable(object);\n \n // COMPATIBILITY: Driver must return 'id' as string\n const newRecord = {\n id: data.id || this.generateId(),\n ...data,\n created_at: data.created_at || new Date(),\n updated_at: data.updated_at || new Date(),\n };\n\n table.push(newRecord);\n this.logger.debug('Record created', { object, id: newRecord.id, tableSize: table.length });\n return newRecord;\n }\n\n async update(object: string, id: string | number, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('Update operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for update', { object, id });\n throw new Error(`Record with ID ${id} not found in ${object}`);\n }\n\n const updatedRecord = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n \n table[index] = updatedRecord;\n this.logger.debug('Record updated', { object, id });\n return updatedRecord;\n }\n\n async upsert(object: string, data: Record<string, any>, conflictKeys?: string[], options?: DriverOptions) {\n this.logger.debug('Upsert operation', { object, conflictKeys });\n \n const table = this.getTable(object);\n let existingRecord: any = null;\n\n if (data.id) {\n existingRecord = table.find(r => r.id === data.id);\n } else if (conflictKeys && conflictKeys.length > 0) {\n existingRecord = table.find(r => conflictKeys.every(key => r[key] === data[key]));\n }\n\n if (existingRecord) {\n this.logger.debug('Record exists, updating', { object, id: existingRecord.id });\n return this.update(object, existingRecord.id, data, options);\n } else {\n this.logger.debug('Record does not exist, creating', { object });\n return this.create(object, data, options);\n }\n }\n\n async delete(object: string, id: string | number, options?: DriverOptions) {\n this.logger.debug('Delete operation', { object, id });\n \n const table = this.getTable(object);\n const index = table.findIndex(r => r.id == id);\n \n if (index === -1) {\n this.logger.warn('Record not found for deletion', { object, id });\n return false;\n }\n\n table.splice(index, 1);\n this.logger.debug('Record deleted', { object, id, tableSize: table.length });\n return true;\n }\n\n async count(object: string, query?: QueryInput, options?: DriverOptions) {\n let results = this.getTable(object);\n if (query?.where) {\n results = results.filter(record => match(record, query.where));\n }\n const count = results.length;\n this.logger.debug('Count operation', { object, count });\n return count;\n }\n\n // ===================================\n // Bulk Operations\n // ===================================\n\n async bulkCreate(object: string, dataArray: Record<string, any>[], options?: DriverOptions) {\n this.logger.debug('BulkCreate operation', { object, count: dataArray.length });\n const results = await Promise.all(dataArray.map(data => this.create(object, data, options)));\n this.logger.debug('BulkCreate completed', { object, count: results.length });\n return results;\n }\n \n async updateMany(object: string, query: QueryInput, data: Record<string, any>, options?: DriverOptions) {\n this.logger.debug('UpdateMany operation', { object, query });\n \n const table = this.getTable(object);\n let targetRecords = table;\n \n if (query && query.where) {\n targetRecords = targetRecords.filter(r => match(r, query.where));\n }\n \n const count = targetRecords.length;\n \n // Update each record\n for (const record of targetRecords) {\n // Find index in original table\n const index = table.findIndex(r => r.id === record.id);\n if (index !== -1) {\n const updated = {\n ...table[index],\n ...data,\n updated_at: new Date()\n };\n table[index] = updated;\n }\n }\n \n this.logger.debug('UpdateMany completed', { object, count });\n return { count };\n }\n\n async deleteMany(object: string, query: QueryInput, options?: DriverOptions) {\n this.logger.debug('DeleteMany operation', { object, query });\n \n const table = this.getTable(object);\n const initialLength = table.length;\n \n // Filter IN PLACE or create new array?\n // Creating new array is safer for now.\n \n const remaining = table.filter(r => {\n if (!query || !query.where) return false; // Delete all? No, standard safety implies explicit empty filter for delete all.\n // Wait, normally deleteMany({}) deletes all.\n // Let's assume if query passed, use it.\n const matches = match(r, query.where);\n return !matches; // Keep if it DOES NOT match\n });\n \n this.db[object] = remaining;\n const count = initialLength - remaining.length;\n \n this.logger.debug('DeleteMany completed', { object, count });\n return { count };\n }\n\n // Compatibility aliases\n async bulkUpdate(object: string, updates: { id: string | number, data: Record<string, any> }[], options?: DriverOptions) {\n this.logger.debug('BulkUpdate operation', { object, count: updates.length });\n const results = await Promise.all(updates.map(u => this.update(object, u.id, u.data, options)));\n this.logger.debug('BulkUpdate completed', { object, count: results.length });\n return results;\n }\n\n async bulkDelete(object: string, ids: (string | number)[], options?: DriverOptions) {\n this.logger.debug('BulkDelete operation', { object, count: ids.length });\n await Promise.all(ids.map(id => this.delete(object, id, options)));\n this.logger.debug('BulkDelete completed', { object, count: ids.length });\n }\n\n // ===================================\n // Schema & Transactions\n // ===================================\n\n async syncSchema(object: string, schema: any, options?: DriverOptions) {\n if (!this.db[object]) {\n this.db[object] = [];\n this.logger.info('Created in-memory table', { object });\n }\n }\n\n async dropTable(object: string, options?: DriverOptions) {\n if (this.db[object]) {\n const recordCount = this.db[object].length;\n delete this.db[object];\n this.logger.info('Dropped in-memory table', { object, recordCount });\n }\n }\n\n async beginTransaction() {\n throw new Error('Transactions not supported in InMemoryDriver');\n }\n\n async commit() { /* No-op */ }\n async rollback() { /* No-op */ }\n\n // ===================================\n // Aggregation Logic\n // ===================================\n\n private performAggregation(records: any[], query: QueryInput): any[] {\n const { groupBy, aggregations } = query;\n const groups: Map<string, any[]> = new Map();\n\n // 1. Group records\n if (groupBy && groupBy.length > 0) {\n for (const record of records) {\n // Create a composite key from group values\n const keyParts = groupBy.map(field => {\n const val = getValueByPath(record, field);\n return val === undefined || val === null ? 'null' : String(val);\n });\n const key = JSON.stringify(keyParts);\n \n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n } else {\n // No grouping -> Single group containing all records\n // If aggregation is requested without group by, it runs on whole set (even if empty)\n if (aggregations && aggregations.length > 0) {\n groups.set('all', records);\n } else {\n // Should not be here if performAggregation called correctly\n groups.set('all', records);\n }\n }\n\n // 2. Compute aggregates for each group\n const resultRows: any[] = [];\n \n for (const [key, groupRecords] of groups.entries()) {\n const row: any = {};\n \n // A. Add Group fields to row (if groupBy exists)\n if (groupBy && groupBy.length > 0) {\n if (groupRecords.length > 0) {\n const firstRecord = groupRecords[0];\n for (const field of groupBy) {\n this.setValueByPath(row, field, getValueByPath(firstRecord, field));\n }\n }\n }\n \n // B. Compute Aggregations\n if (aggregations) {\n for (const agg of aggregations) {\n const value = this.computeAggregate(groupRecords, agg);\n row[agg.alias] = value;\n }\n }\n \n resultRows.push(row);\n }\n \n return resultRows;\n }\n \n private computeAggregate(records: any[], agg: any): any {\n const { function: func, field } = agg;\n \n const values = field ? records.map(r => getValueByPath(r, field)) : [];\n \n switch (func) {\n case 'count':\n if (!field || field === '*') return records.length;\n return values.filter(v => v !== null && v !== undefined).length;\n \n case 'sum':\n case 'avg': {\n const nums = values.filter(v => typeof v === 'number');\n const sum = nums.reduce((a, b) => a + b, 0);\n if (func === 'sum') return sum;\n return nums.length > 0 ? sum / nums.length : null;\n }\n \n case 'min': {\n // Handle comparable values\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n // Works for numbers and strings\n return valid.reduce((min, v) => (v < min ? v : min), valid[0]);\n }\n\n case 'max': {\n const valid = values.filter(v => v !== null && v !== undefined);\n if (valid.length === 0) return null;\n return valid.reduce((max, v) => (v > max ? v : max), valid[0]);\n }\n\n default:\n return null;\n }\n }\n\n private setValueByPath(obj: any, path: string, value: any) {\n const parts = path.split('.');\n let current = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!current[part]) current[part] = {};\n current = current[part];\n }\n current[parts[parts.length - 1]] = value;\n }\n\n // ===================================\n // Helpers\n // ===================================\n\n private getTable(name: string) {\n if (!this.db[name]) {\n this.db[name] = [];\n }\n return this.db[name];\n }\n\n private generateId() {\n return Math.random().toString(36).substring(2, 15);\n }\n}\n","\n/**\n * Simple In-Memory Query Matcher\n * \n * Implements a subset of the ObjectStack Filter Protocol (MongoDB-compatible)\n * for evaluating conditions against in-memory JavaScript objects.\n */\n\ntype RecordType = Record<string, any>;\n\n/**\n * matches - Check if a record matches a filter criteria\n * @param record The data record to check\n * @param filter The filter condition (where clause)\n */\nexport function match(record: RecordType, filter: any): boolean {\n if (!filter || Object.keys(filter).length === 0) return true;\n \n // 1. Handle Top-Level Logical Operators ($and, $or, $not)\n // These usually appear at the root or nested.\n \n // $and: [ { ... }, { ... } ]\n if (Array.isArray(filter.$and)) {\n if (!filter.$and.every((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $or: [ { ... }, { ... } ]\n if (Array.isArray(filter.$or)) {\n if (!filter.$or.some((f: any) => match(record, f))) {\n return false;\n }\n }\n \n // $not: { ... }\n if (filter.$not) {\n if (match(record, filter.$not)) {\n return false;\n }\n }\n \n // 2. Iterate over field constraints\n for (const key of Object.keys(filter)) {\n // Skip logical operators we already handled (or future ones)\n if (key.startsWith('$')) continue;\n \n const condition = filter[key];\n const value = getValueByPath(record, key);\n \n if (!checkCondition(value, condition)) {\n return false;\n }\n }\n \n return true;\n}\n\n/**\n * Access nested properties via dot-notation (e.g. \"user.name\")\n */\nexport function getValueByPath(obj: any, path: string): any {\n if (!path.includes('.')) return obj[path];\n return path.split('.').reduce((o, i) => (o ? o[i] : undefined), obj);\n}\n\n/**\n * Evaluate a specific condition against a value\n */\nfunction checkCondition(value: any, condition: any): boolean {\n // Case A: Implicit Equality (e.g. status: 'active')\n // If condition is a primitive or Date/Array (exact match), treat as equality.\n if (\n typeof condition !== 'object' || \n condition === null || \n condition instanceof Date ||\n Array.isArray(condition)\n ) {\n // Loose equality to handle undefined/null mismatch or string/number coercion if desired.\n // But stick to == for JS loose equality which is often convenient in weakly typed queries.\n return value == condition;\n }\n \n // Case B: Operator Object (e.g. { $gt: 10, $lt: 20 })\n const keys = Object.keys(condition);\n const isOperatorObject = keys.some(k => k.startsWith('$'));\n \n if (!isOperatorObject) {\n // It's just a nested object comparison or implicit equality against an object\n // Simplistic check:\n return JSON.stringify(value) === JSON.stringify(condition);\n }\n\n // Iterate operators\n for (const op of keys) {\n const target = condition[op];\n \n // Handle undefined values\n if (value === undefined && op !== '$exists' && op !== '$ne') {\n return false; \n }\n\n switch (op) {\n case '$eq': \n if (value != target) return false; \n break;\n case '$ne': \n if (value == target) return false; \n break;\n \n // Numeric / Date\n case '$gt': \n if (!(value > target)) return false; \n break;\n case '$gte': \n if (!(value >= target)) return false; \n break;\n case '$lt': \n if (!(value < target)) return false; \n break;\n case '$lte': \n if (!(value <= target)) return false; \n break;\n case '$between':\n // target should be [min, max]\n if (Array.isArray(target) && (value < target[0] || value > target[1])) return false;\n break;\n\n // Sets\n case '$in': \n if (!Array.isArray(target) || !target.includes(value)) return false; \n break;\n case '$nin': \n if (Array.isArray(target) && target.includes(value)) return false; \n break;\n \n // Existence\n case '$exists':\n const exists = value !== undefined && value !== null;\n if (exists !== !!target) return false;\n break;\n\n // Strings\n case '$contains': \n if (typeof value !== 'string' || !value.includes(target)) return false; \n break;\n case '$startsWith': \n if (typeof value !== 'string' || !value.startsWith(target)) return false; \n break;\n case '$endsWith': \n if (typeof value !== 'string' || !value.endsWith(target)) return false; \n break;\n case '$regex':\n try {\n const re = new RegExp(target, condition.$options || '');\n if (!re.test(String(value))) return false;\n } catch (e) { return false; }\n break;\n\n default: \n // Unknown operator, ignore or fail. Ignoring safe for optional features.\n break;\n }\n }\n \n return true;\n}\n","import { InMemoryDriver } from './memory-driver.js';\n\nexport { InMemoryDriver }; // Export class for direct usage\n\n// Note: In a real environment, you would import these from @objectstack/spec\n// But distinct PluginDefinition interface might not be strictly defined in schema yet, \n// usually it mimics the Manifest structure + runtime hooks.\n\n// For this example, we define a basic shape if not available, or use \"any\" to bypass strictness for the demo.\n// In plugin-bi it imported: import { PluginDefinition, PluginContextData } from '@objectstack/spec';\n\n// Let's rely on the environment being set up like plugin-bi.\n// If types are missing, this is just an example file.\n\nexport default {\n id: 'com.objectstack.driver.memory',\n version: '1.0.0',\n\n onEnable: async (context: any) => {\n const { logger, config, drivers } = context;\n logger.info('[Memory Driver] Initializing...');\n\n // Simulate driver registration\n // This assumes the runtime exposes a 'drivers' registry\n if (drivers) {\n const driver = new InMemoryDriver(config); // Pass config to driver\n drivers.register(driver);\n logger.info(`[Memory Driver] Registered driver: ${driver.name}`);\n } else {\n logger.warn('[Memory Driver] No driver registry found in context.');\n }\n }\n};\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/driver-memory",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "In-Memory Driver for ObjectStack (Reference Implementation)",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@objectstack/core": "1.0.
|
|
10
|
-
"@objectstack/spec": "1.0.
|
|
9
|
+
"@objectstack/core": "1.0.7",
|
|
10
|
+
"@objectstack/spec": "1.0.7"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"typescript": "^5.0.0",
|
package/src/memory-driver.ts
CHANGED