@friggframework/core 2.0.0--canary.531.14108ff.0 → 2.0.0--canary.517.aeeef23.0
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/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-process-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-process-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
- package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
- package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/admin-script-commands.js +344 -0
- package/database/use-cases/check-database-state-use-case.js +2 -2
- package/database/use-cases/trigger-database-migration-use-case.js +1 -1
- package/generated/prisma-mongodb/edge.js +47 -4
- package/generated/prisma-mongodb/index-browser.js +37 -1
- package/generated/prisma-mongodb/index.d.ts +2775 -52
- package/generated/prisma-mongodb/index.js +47 -4
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +69 -0
- package/generated/prisma-mongodb/wasm.js +47 -4
- package/generated/prisma-postgresql/edge.js +46 -4
- package/generated/prisma-postgresql/index-browser.js +36 -1
- package/generated/prisma-postgresql/index.d.ts +3414 -83
- package/generated/prisma-postgresql/index.js +46 -4
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +68 -0
- package/generated/prisma-postgresql/wasm.js +46 -4
- package/handlers/middleware/admin-auth.js +53 -0
- package/handlers/routers/db-migration.handler.js +1 -1
- package/handlers/routers/db-migration.js +18 -33
- package/modules/requester/oauth-2.js +7 -2
- package/package.json +5 -5
- package/prisma-mongodb/schema.prisma +69 -0
- package/prisma-postgresql/schema.prisma +68 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Scripts Module
|
|
3
|
+
*
|
|
4
|
+
* Exports repository interfaces and factories for admin script management.
|
|
5
|
+
* Concrete implementations support MongoDB, PostgreSQL, and DocumentDB.
|
|
6
|
+
*
|
|
7
|
+
* Repository interfaces follow the Port pattern in Hexagonal Architecture:
|
|
8
|
+
* - Define contracts for data access
|
|
9
|
+
* - Enable dependency injection
|
|
10
|
+
* - Allow testing with mocks
|
|
11
|
+
* - Support multiple database implementations
|
|
12
|
+
*
|
|
13
|
+
* Authentication:
|
|
14
|
+
* - Uses ENV-based ADMIN_API_KEY (see handlers/middleware/admin-auth.js)
|
|
15
|
+
* - No database-backed API keys (simplified from original design)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Repository Interfaces
|
|
19
|
+
const { AdminProcessRepositoryInterface } = require('./repositories/admin-process-repository-interface');
|
|
20
|
+
const { ScriptScheduleRepositoryInterface } = require('./repositories/script-schedule-repository-interface');
|
|
21
|
+
|
|
22
|
+
// Repository Factories
|
|
23
|
+
const {
|
|
24
|
+
createAdminProcessRepository,
|
|
25
|
+
AdminProcessRepositoryMongo,
|
|
26
|
+
AdminProcessRepositoryPostgres,
|
|
27
|
+
AdminProcessRepositoryDocumentDB,
|
|
28
|
+
} = require('./repositories/admin-process-repository-factory');
|
|
29
|
+
const {
|
|
30
|
+
createScriptScheduleRepository,
|
|
31
|
+
ScriptScheduleRepositoryMongo,
|
|
32
|
+
ScriptScheduleRepositoryPostgres,
|
|
33
|
+
ScriptScheduleRepositoryDocumentDB,
|
|
34
|
+
} = require('./repositories/script-schedule-repository-factory');
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
// Repository Interfaces
|
|
38
|
+
AdminProcessRepositoryInterface,
|
|
39
|
+
ScriptScheduleRepositoryInterface,
|
|
40
|
+
|
|
41
|
+
// Repository Factories (primary exports for use cases)
|
|
42
|
+
createAdminProcessRepository,
|
|
43
|
+
createScriptScheduleRepository,
|
|
44
|
+
|
|
45
|
+
// Concrete Implementations (for testing)
|
|
46
|
+
AdminProcessRepositoryMongo,
|
|
47
|
+
AdminProcessRepositoryPostgres,
|
|
48
|
+
AdminProcessRepositoryDocumentDB,
|
|
49
|
+
ScriptScheduleRepositoryMongo,
|
|
50
|
+
ScriptScheduleRepositoryPostgres,
|
|
51
|
+
ScriptScheduleRepositoryDocumentDB,
|
|
52
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const {
|
|
2
|
+
AdminProcessRepositoryMongo,
|
|
3
|
+
} = require('./admin-process-repository-mongo');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DocumentDB Admin Process Repository Adapter
|
|
7
|
+
* Extends MongoDB implementation since DocumentDB uses the same Prisma client
|
|
8
|
+
*
|
|
9
|
+
* DocumentDB-specific characteristics:
|
|
10
|
+
* - Uses MongoDB-compatible API
|
|
11
|
+
* - Prisma client handles the connection
|
|
12
|
+
* - IDs are strings with ObjectId format
|
|
13
|
+
* - All operations identical to MongoDB implementation
|
|
14
|
+
*/
|
|
15
|
+
class AdminProcessRepositoryDocumentDB extends AdminProcessRepositoryMongo {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = { AdminProcessRepositoryDocumentDB };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { AdminProcessRepositoryMongo } = require('./admin-process-repository-mongo');
|
|
2
|
+
const { AdminProcessRepositoryPostgres } = require('./admin-process-repository-postgres');
|
|
3
|
+
const {
|
|
4
|
+
AdminProcessRepositoryDocumentDB,
|
|
5
|
+
} = require('./admin-process-repository-documentdb');
|
|
6
|
+
const config = require('../../database/config');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Admin Process Repository Factory
|
|
10
|
+
* Creates the appropriate repository adapter based on database type
|
|
11
|
+
*
|
|
12
|
+
* This implements the Factory pattern for Hexagonal Architecture:
|
|
13
|
+
* - Reads database type from app definition (backend/index.js)
|
|
14
|
+
* - Returns correct adapter (MongoDB, DocumentDB, or PostgreSQL)
|
|
15
|
+
* - Provides clear error for unsupported databases
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```javascript
|
|
19
|
+
* const repository = createAdminProcessRepository();
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @returns {AdminProcessRepositoryInterface} Configured repository adapter
|
|
23
|
+
* @throws {Error} If database type is not supported
|
|
24
|
+
*/
|
|
25
|
+
function createAdminProcessRepository() {
|
|
26
|
+
const dbType = config.DB_TYPE;
|
|
27
|
+
|
|
28
|
+
switch (dbType) {
|
|
29
|
+
case 'mongodb':
|
|
30
|
+
return new AdminProcessRepositoryMongo();
|
|
31
|
+
|
|
32
|
+
case 'postgresql':
|
|
33
|
+
return new AdminProcessRepositoryPostgres();
|
|
34
|
+
|
|
35
|
+
case 'documentdb':
|
|
36
|
+
return new AdminProcessRepositoryDocumentDB();
|
|
37
|
+
|
|
38
|
+
default:
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Unsupported database type: ${dbType}. Supported values: 'mongodb', 'documentdb', 'postgresql'`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = {
|
|
46
|
+
createAdminProcessRepository,
|
|
47
|
+
// Export adapters for direct testing
|
|
48
|
+
AdminProcessRepositoryMongo,
|
|
49
|
+
AdminProcessRepositoryPostgres,
|
|
50
|
+
AdminProcessRepositoryDocumentDB,
|
|
51
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Process Repository Interface
|
|
3
|
+
* Abstract base class defining the contract for admin process persistence adapters
|
|
4
|
+
*
|
|
5
|
+
* This follows the Port in Hexagonal Architecture:
|
|
6
|
+
* - Domain layer depends on this abstraction
|
|
7
|
+
* - Concrete adapters implement this interface
|
|
8
|
+
* - Use cases receive repositories via dependency injection
|
|
9
|
+
*
|
|
10
|
+
* Admin processes track administrative operations including:
|
|
11
|
+
* - Admin script executions
|
|
12
|
+
* - Database migrations
|
|
13
|
+
* - Scheduled maintenance tasks
|
|
14
|
+
*
|
|
15
|
+
* The AdminProcess model uses a flexible JSON storage pattern:
|
|
16
|
+
* - context: Input parameters, trigger info, audit data, script version
|
|
17
|
+
* - results: Output data, logs, metrics, error details
|
|
18
|
+
*
|
|
19
|
+
* @abstract
|
|
20
|
+
*/
|
|
21
|
+
class AdminProcessRepositoryInterface {
|
|
22
|
+
/**
|
|
23
|
+
* Create a new admin process record
|
|
24
|
+
*
|
|
25
|
+
* @param {Object} params - Process creation parameters
|
|
26
|
+
* @param {string} params.name - Name of the process (e.g., script name, migration name)
|
|
27
|
+
* @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
|
|
28
|
+
* @param {Object} [params.context] - Context data (input, trigger, audit, script version)
|
|
29
|
+
* @param {string} [params.context.scriptVersion] - Version of the script
|
|
30
|
+
* @param {string} [params.context.trigger] - Trigger type ('MANUAL', 'SCHEDULED', 'QUEUE', 'WEBHOOK')
|
|
31
|
+
* @param {string} [params.context.mode] - Execution mode ('sync' or 'async')
|
|
32
|
+
* @param {Object} [params.context.input] - Input parameters
|
|
33
|
+
* @param {Object} [params.context.audit] - Audit information
|
|
34
|
+
* @param {string} [params.context.audit.apiKeyName] - Name of API key used
|
|
35
|
+
* @param {string} [params.context.audit.apiKeyLast4] - Last 4 chars of API key
|
|
36
|
+
* @param {string} [params.context.audit.ipAddress] - IP address of requester
|
|
37
|
+
* @returns {Promise<Object>} The created process record
|
|
38
|
+
* @abstract
|
|
39
|
+
*/
|
|
40
|
+
async createProcess({ name, type, context }) {
|
|
41
|
+
throw new Error('Method createProcess must be implemented by subclass');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Find a process by its ID
|
|
46
|
+
*
|
|
47
|
+
* @param {string|number} id - The process ID
|
|
48
|
+
* @returns {Promise<Object|null>} The process record or null if not found
|
|
49
|
+
* @abstract
|
|
50
|
+
*/
|
|
51
|
+
async findProcessById(id) {
|
|
52
|
+
throw new Error('Method findProcessById must be implemented by subclass');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Find all processes with a specific name
|
|
57
|
+
*
|
|
58
|
+
* @param {string} name - The process name to filter by
|
|
59
|
+
* @param {Object} [options] - Query options
|
|
60
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
61
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
62
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
63
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
64
|
+
* @returns {Promise<Array>} Array of process records
|
|
65
|
+
* @abstract
|
|
66
|
+
*/
|
|
67
|
+
async findProcessesByName(name, options = {}) {
|
|
68
|
+
throw new Error('Method findProcessesByName must be implemented by subclass');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Find all processes with a specific state
|
|
73
|
+
*
|
|
74
|
+
* @param {string} state - State to filter by ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
|
|
75
|
+
* @param {Object} [options] - Query options
|
|
76
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
77
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
78
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
79
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
80
|
+
* @returns {Promise<Array>} Array of process records
|
|
81
|
+
* @abstract
|
|
82
|
+
*/
|
|
83
|
+
async findProcessesByState(state, options = {}) {
|
|
84
|
+
throw new Error('Method findProcessesByState must be implemented by subclass');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Update the state of a process
|
|
89
|
+
*
|
|
90
|
+
* @param {string|number} id - The process ID
|
|
91
|
+
* @param {string} state - New state value ('PENDING', 'RUNNING', 'COMPLETED', 'FAILED')
|
|
92
|
+
* @returns {Promise<Object>} Updated process record
|
|
93
|
+
* @abstract
|
|
94
|
+
*/
|
|
95
|
+
async updateProcessState(id, state) {
|
|
96
|
+
throw new Error('Method updateProcessState must be implemented by subclass');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Update the results of a process
|
|
101
|
+
* Merges new results with existing results in the results JSON field
|
|
102
|
+
*
|
|
103
|
+
* @param {string|number} id - The process ID
|
|
104
|
+
* @param {Object} results - Results data to merge
|
|
105
|
+
* @param {Object} [results.output] - Output data from the process
|
|
106
|
+
* @param {Object} [results.error] - Error information
|
|
107
|
+
* @param {string} [results.error.name] - Error name/type
|
|
108
|
+
* @param {string} [results.error.message] - Error message
|
|
109
|
+
* @param {string} [results.error.stack] - Error stack trace
|
|
110
|
+
* @param {Object} [results.metrics] - Performance metrics
|
|
111
|
+
* @param {Date} [results.metrics.startTime] - Process start time
|
|
112
|
+
* @param {Date} [results.metrics.endTime] - Process end time
|
|
113
|
+
* @param {number} [results.metrics.durationMs] - Duration in milliseconds
|
|
114
|
+
* @returns {Promise<Object>} Updated process record
|
|
115
|
+
* @abstract
|
|
116
|
+
*/
|
|
117
|
+
async updateProcessResults(id, results) {
|
|
118
|
+
throw new Error('Method updateProcessResults must be implemented by subclass');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Append a log entry to a process's log array in results
|
|
123
|
+
*
|
|
124
|
+
* @param {string|number} id - The process ID
|
|
125
|
+
* @param {Object} logEntry - Log entry to append
|
|
126
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
127
|
+
* @param {string} logEntry.message - Log message
|
|
128
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
129
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
130
|
+
* @returns {Promise<Object>} Updated process record
|
|
131
|
+
* @abstract
|
|
132
|
+
*/
|
|
133
|
+
async appendProcessLog(id, logEntry) {
|
|
134
|
+
throw new Error('Method appendProcessLog must be implemented by subclass');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Delete all processes older than a specific date
|
|
139
|
+
* Used for cleanup and retention policies
|
|
140
|
+
*
|
|
141
|
+
* @param {Date} date - Delete processes older than this date
|
|
142
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
143
|
+
* @abstract
|
|
144
|
+
*/
|
|
145
|
+
async deleteProcessesOlderThan(date) {
|
|
146
|
+
throw new Error('Method deleteProcessesOlderThan must be implemented by subclass');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { AdminProcessRepositoryInterface };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const { prisma } = require('../../database/prisma');
|
|
2
|
+
const {
|
|
3
|
+
AdminProcessRepositoryInterface,
|
|
4
|
+
} = require('./admin-process-repository-interface');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MongoDB Admin Process Repository Adapter
|
|
8
|
+
* Handles admin process persistence using Prisma with MongoDB
|
|
9
|
+
*
|
|
10
|
+
* MongoDB-specific characteristics:
|
|
11
|
+
* - IDs are strings with @db.ObjectId
|
|
12
|
+
* - context and results are Json objects
|
|
13
|
+
* - Stores logs in results.logs array
|
|
14
|
+
*/
|
|
15
|
+
class AdminProcessRepositoryMongo extends AdminProcessRepositoryInterface {
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.prisma = prisma;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new admin process record
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} params - Process creation parameters
|
|
25
|
+
* @param {string} params.name - Name of the process
|
|
26
|
+
* @param {string} params.type - Type of process (e.g., 'ADMIN_SCRIPT', 'DB_MIGRATION')
|
|
27
|
+
* @param {Object} [params.context] - Context data
|
|
28
|
+
* @returns {Promise<Object>} The created process record
|
|
29
|
+
*/
|
|
30
|
+
async createProcess({ name, type, context = {} }) {
|
|
31
|
+
const data = {
|
|
32
|
+
name,
|
|
33
|
+
type,
|
|
34
|
+
context,
|
|
35
|
+
results: { logs: [] },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const process = await this.prisma.adminProcess.create({
|
|
39
|
+
data,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return process;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Find a process by its ID
|
|
47
|
+
*
|
|
48
|
+
* @param {string} id - The process ID
|
|
49
|
+
* @returns {Promise<Object|null>} The process record or null if not found
|
|
50
|
+
*/
|
|
51
|
+
async findProcessById(id) {
|
|
52
|
+
const process = await this.prisma.adminProcess.findUnique({
|
|
53
|
+
where: { id },
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return process;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Find all processes with a specific name
|
|
61
|
+
*
|
|
62
|
+
* @param {string} name - The process name to filter by
|
|
63
|
+
* @param {Object} [options] - Query options
|
|
64
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
65
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
66
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
67
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
68
|
+
* @returns {Promise<Array>} Array of process records
|
|
69
|
+
*/
|
|
70
|
+
async findProcessesByName(name, options = {}) {
|
|
71
|
+
const { limit, offset, sortBy = 'createdAt', sortOrder = 'desc' } = options;
|
|
72
|
+
|
|
73
|
+
const processes = await this.prisma.adminProcess.findMany({
|
|
74
|
+
where: { name },
|
|
75
|
+
orderBy: { [sortBy]: sortOrder },
|
|
76
|
+
take: limit,
|
|
77
|
+
skip: offset,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return processes;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Find all processes with a specific state
|
|
85
|
+
*
|
|
86
|
+
* @param {string} state - State to filter by
|
|
87
|
+
* @param {Object} [options] - Query options
|
|
88
|
+
* @param {number} [options.limit] - Maximum number of results
|
|
89
|
+
* @param {number} [options.offset] - Number of results to skip
|
|
90
|
+
* @param {string} [options.sortBy] - Field to sort by
|
|
91
|
+
* @param {string} [options.sortOrder] - Sort order ('asc' or 'desc')
|
|
92
|
+
* @returns {Promise<Array>} Array of process records
|
|
93
|
+
*/
|
|
94
|
+
async findProcessesByState(state, options = {}) {
|
|
95
|
+
const { limit, offset, sortBy = 'createdAt', sortOrder = 'desc' } = options;
|
|
96
|
+
|
|
97
|
+
const processes = await this.prisma.adminProcess.findMany({
|
|
98
|
+
where: { state },
|
|
99
|
+
orderBy: { [sortBy]: sortOrder },
|
|
100
|
+
take: limit,
|
|
101
|
+
skip: offset,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return processes;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Update the state of a process
|
|
109
|
+
*
|
|
110
|
+
* @param {string} id - The process ID
|
|
111
|
+
* @param {string} state - New state value
|
|
112
|
+
* @returns {Promise<Object>} Updated process record
|
|
113
|
+
*/
|
|
114
|
+
async updateProcessState(id, state) {
|
|
115
|
+
const process = await this.prisma.adminProcess.update({
|
|
116
|
+
where: { id },
|
|
117
|
+
data: { state },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return process;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Update the results of a process
|
|
125
|
+
* Merges new results with existing results
|
|
126
|
+
*
|
|
127
|
+
* @param {string} id - The process ID
|
|
128
|
+
* @param {Object} results - Results data to merge
|
|
129
|
+
* @returns {Promise<Object>} Updated process record
|
|
130
|
+
*/
|
|
131
|
+
async updateProcessResults(id, results) {
|
|
132
|
+
// Get current process to merge results
|
|
133
|
+
const currentProcess = await this.prisma.adminProcess.findUnique({
|
|
134
|
+
where: { id },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!currentProcess) {
|
|
138
|
+
throw new Error(`AdminProcess ${id} not found`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Merge new results with existing results
|
|
142
|
+
const mergedResults = {
|
|
143
|
+
...(currentProcess.results || {}),
|
|
144
|
+
...results,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const process = await this.prisma.adminProcess.update({
|
|
148
|
+
where: { id },
|
|
149
|
+
data: { results: mergedResults },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return process;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Append a log entry to a process's log array in results
|
|
157
|
+
*
|
|
158
|
+
* @param {string} id - The process ID
|
|
159
|
+
* @param {Object} logEntry - Log entry to append
|
|
160
|
+
* @param {string} logEntry.level - Log level ('debug', 'info', 'warn', 'error')
|
|
161
|
+
* @param {string} logEntry.message - Log message
|
|
162
|
+
* @param {Object} [logEntry.data] - Additional log data
|
|
163
|
+
* @param {string} logEntry.timestamp - ISO timestamp
|
|
164
|
+
* @returns {Promise<Object>} Updated process record
|
|
165
|
+
*/
|
|
166
|
+
async appendProcessLog(id, logEntry) {
|
|
167
|
+
// Get current process
|
|
168
|
+
const process = await this.prisma.adminProcess.findUnique({
|
|
169
|
+
where: { id },
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
if (!process) {
|
|
173
|
+
throw new Error(`AdminProcess ${id} not found`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Get current results and logs
|
|
177
|
+
const results = process.results || {};
|
|
178
|
+
const logs = Array.isArray(results.logs) ? [...results.logs] : [];
|
|
179
|
+
logs.push(logEntry);
|
|
180
|
+
|
|
181
|
+
// Update with new logs array in results
|
|
182
|
+
const updated = await this.prisma.adminProcess.update({
|
|
183
|
+
where: { id },
|
|
184
|
+
data: { results: { ...results, logs } },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return updated;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Delete all processes older than a specific date
|
|
192
|
+
* Used for cleanup and retention policies
|
|
193
|
+
*
|
|
194
|
+
* @param {Date} date - Delete processes older than this date
|
|
195
|
+
* @returns {Promise<Object>} Deletion result with count
|
|
196
|
+
*/
|
|
197
|
+
async deleteProcessesOlderThan(date) {
|
|
198
|
+
const result = await this.prisma.adminProcess.deleteMany({
|
|
199
|
+
where: {
|
|
200
|
+
createdAt: {
|
|
201
|
+
lt: date,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
acknowledged: true,
|
|
208
|
+
deletedCount: result.count,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
module.exports = { AdminProcessRepositoryMongo };
|