@reldens/storage 0.79.0 → 0.81.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/lib/entities-generator.js +1 -1
- package/lib/entity-templates/objection-js-model.template +1 -1
- package/lib/generators/models-generation.js +26 -1
- package/lib/prisma/prisma-data-server.js +1 -1
- package/lib/prisma/prisma-driver.js +187 -490
- package/lib/prisma/prisma-metadata-loader.js +126 -0
- package/lib/prisma/prisma-relation-resolver.js +267 -0
- package/lib/prisma/prisma-schema-generator.js +182 -182
- package/lib/prisma/prisma-type-caster.js +231 -0
- package/package.json +1 -1
|
@@ -1,182 +1,182 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Reldens - PrismaSchemaGenerator
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const { execSync } = require('child_process');
|
|
8
|
-
const { FileHandler } = require('@reldens/server-utils');
|
|
9
|
-
const { Logger, sc } = require('@reldens/utils');
|
|
10
|
-
|
|
11
|
-
class PrismaSchemaGenerator
|
|
12
|
-
{
|
|
13
|
-
|
|
14
|
-
constructor(props)
|
|
15
|
-
{
|
|
16
|
-
this.config = sc.get(props, 'config', {});
|
|
17
|
-
this.client = sc.get(props, 'client', 'mysql');
|
|
18
|
-
this.debug = sc.get(props, 'debug', false);
|
|
19
|
-
this.dataProxy = sc.get(props, 'dataProxy', false);
|
|
20
|
-
this.checkInterval = sc.get(props, 'checkInterval', 1000);
|
|
21
|
-
this.maxWaitTime = sc.get(props, 'maxWaitTime', 30000);
|
|
22
|
-
this.prismaSchemaPath = sc.get(props, 'prismaSchemaPath', FileHandler.joinPaths(process.cwd(), 'prisma'));
|
|
23
|
-
this.schemaFilePath = FileHandler.joinPaths(this.prismaSchemaPath, 'schema.prisma');
|
|
24
|
-
this.clientOutputPath = sc.get(props, 'clientOutputPath', '');
|
|
25
|
-
this.generateBinaryTargets = sc.get(props, 'generateBinaryTargets', ['native', 'debian-openssl-1.1.x']);
|
|
26
|
-
this.dbParams = sc.get(props, 'dbParams', process.env.RELDENS_DB_PARAMS || '');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async generate()
|
|
30
|
-
{
|
|
31
|
-
FileHandler.createFolder(this.prismaSchemaPath);
|
|
32
|
-
this.generateSchemaFile();
|
|
33
|
-
Logger.info('Running prisma introspect "npx prisma db pull"...');
|
|
34
|
-
try {
|
|
35
|
-
execSync('npx prisma db pull', { stdio: 'inherit' });
|
|
36
|
-
} catch(error) {
|
|
37
|
-
Logger.critical('Failed to pull database schema: ' + error.message);
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
let generateCommand = 'npx prisma generate';
|
|
41
|
-
if(this.dataProxy){
|
|
42
|
-
generateCommand += ' --data-proxy';
|
|
43
|
-
}
|
|
44
|
-
Logger.info('Running prisma generate "'+generateCommand+'"...');
|
|
45
|
-
try {
|
|
46
|
-
execSync(generateCommand, { stdio: 'inherit' });
|
|
47
|
-
} catch(error) {
|
|
48
|
-
let errorString = error.toString();
|
|
49
|
-
if(errorString.includes('EPERM') && errorString.includes('query_engine-windows.dll.node')){
|
|
50
|
-
Logger.warning('Windows permission error detected with query engine file.');
|
|
51
|
-
Logger.warning('This is a known Prisma issue on Windows.');
|
|
52
|
-
Logger.warning('Please manually run: ' + generateCommand);
|
|
53
|
-
Logger.warning('You may need to close any processes using the Prisma client first.');
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
Logger.critical('Generate command failed: ' + error.message);
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
await this.waitForSchemaGeneration();
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async waitForSchemaGeneration()
|
|
64
|
-
{
|
|
65
|
-
let clientPath = this.clientOutputPath || 'node_modules/.prisma/client';
|
|
66
|
-
let generatedClientPath = this.resolveClientPath(clientPath);
|
|
67
|
-
let clientIndexPath = FileHandler.joinPaths(generatedClientPath, 'index.js');
|
|
68
|
-
let startTime = Date.now();
|
|
69
|
-
return new Promise((resolve) => {
|
|
70
|
-
let interval = setInterval(() => {
|
|
71
|
-
let awaitTime = Date.now() - startTime;
|
|
72
|
-
Logger.info('Awaiting on schema generation: ' + clientIndexPath, (awaitTime/1000).toFixed(0));
|
|
73
|
-
if(FileHandler.exists(clientIndexPath)){
|
|
74
|
-
clearInterval(interval);
|
|
75
|
-
resolve();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if(awaitTime > this.maxWaitTime){
|
|
79
|
-
clearInterval(interval);
|
|
80
|
-
Logger.warning('Schema generation wait timeout reached.');
|
|
81
|
-
resolve();
|
|
82
|
-
}
|
|
83
|
-
}, this.checkInterval);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
resolveClientPath(clientPath)
|
|
88
|
-
{
|
|
89
|
-
if(clientPath.match(/^[a-zA-Z]:/) || clientPath.startsWith('/')){
|
|
90
|
-
return clientPath;
|
|
91
|
-
}
|
|
92
|
-
if(clientPath.startsWith('node_modules')){
|
|
93
|
-
return FileHandler.joinPaths(process.cwd(), clientPath);
|
|
94
|
-
}
|
|
95
|
-
return FileHandler.joinPaths(this.prismaSchemaPath, clientPath);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
generateSchemaFile()
|
|
99
|
-
{
|
|
100
|
-
let datasourceProvider = this.getDatasourceProvider();
|
|
101
|
-
let schemaContent = this.buildSchemaContent(
|
|
102
|
-
datasourceProvider,
|
|
103
|
-
this.buildConnectionString(datasourceProvider),
|
|
104
|
-
this.buildDirectConnectionString(datasourceProvider)
|
|
105
|
-
);
|
|
106
|
-
FileHandler.writeFile(this.schemaFilePath, schemaContent);
|
|
107
|
-
Logger.info('Generated Prisma schema file at: '+this.schemaFilePath);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
getDatasourceProvider()
|
|
111
|
-
{
|
|
112
|
-
if('postgresql' === this.client || 'postgres' === this.client){
|
|
113
|
-
return 'postgresql';
|
|
114
|
-
}
|
|
115
|
-
if('mongodb' === this.client){
|
|
116
|
-
return 'mongodb';
|
|
117
|
-
}
|
|
118
|
-
return 'mysql';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
buildConnectionString(datasourceProvider)
|
|
122
|
-
{
|
|
123
|
-
if(this.dataProxy){
|
|
124
|
-
datasourceProvider = 'prisma';
|
|
125
|
-
}
|
|
126
|
-
return datasourceProvider + this.buildConnectionDataString();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
buildDirectConnectionString(datasourceProvider)
|
|
130
|
-
{
|
|
131
|
-
if(!this.dataProxy){
|
|
132
|
-
return '';
|
|
133
|
-
}
|
|
134
|
-
return datasourceProvider + this.buildConnectionDataString();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
buildConnectionDataString()
|
|
138
|
-
{
|
|
139
|
-
return '://' + this.config.user + ':' + this.config.password
|
|
140
|
-
+ '@' + this.config.host+':' + this.config.port
|
|
141
|
-
+ '/' + this.config.database
|
|
142
|
-
+ (this.dbParams ? '?' + this.dbParams : '');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
buildSchemaContent(datasourceProvider, connectionString, directConnectionString)
|
|
146
|
-
{
|
|
147
|
-
return this.buildGeneratorBlock() + '\n\n'
|
|
148
|
-
+ this.buildDatasourceBlock(datasourceProvider, connectionString, directConnectionString) + '\n';
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
buildGeneratorBlock()
|
|
152
|
-
{
|
|
153
|
-
let generatorContent = 'generator client {\n';
|
|
154
|
-
generatorContent += ' provider = "prisma-client-js"\n';
|
|
155
|
-
if(this.clientOutputPath){
|
|
156
|
-
let normalizedPath = this.clientOutputPath.replace(/\\/g, '/');
|
|
157
|
-
generatorContent += ' output = "' + normalizedPath + '"\n';
|
|
158
|
-
}
|
|
159
|
-
if(0 < this.generateBinaryTargets.length){
|
|
160
|
-
generatorContent += ' binaryTargets = [' +
|
|
161
|
-
this.generateBinaryTargets.map(target => '"' + target + '"').join(', ')
|
|
162
|
-
+ ']\n';
|
|
163
|
-
}
|
|
164
|
-
generatorContent += '}';
|
|
165
|
-
return generatorContent;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
buildDatasourceBlock(datasourceProvider, connectionString, directConnectionString)
|
|
169
|
-
{
|
|
170
|
-
let datasourceContent = 'datasource db {\n';
|
|
171
|
-
datasourceContent += ' provider = "' + datasourceProvider + '"\n';
|
|
172
|
-
datasourceContent += ' url = "' + connectionString + '"\n';
|
|
173
|
-
if('' !== directConnectionString){
|
|
174
|
-
datasourceContent += ' directUrl = "' + directConnectionString + '"\n';
|
|
175
|
-
}
|
|
176
|
-
datasourceContent += '}';
|
|
177
|
-
return datasourceContent;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
module.exports.PrismaSchemaGenerator = PrismaSchemaGenerator;
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - PrismaSchemaGenerator
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
const { FileHandler } = require('@reldens/server-utils');
|
|
9
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
10
|
+
|
|
11
|
+
class PrismaSchemaGenerator
|
|
12
|
+
{
|
|
13
|
+
|
|
14
|
+
constructor(props)
|
|
15
|
+
{
|
|
16
|
+
this.config = sc.get(props, 'config', {});
|
|
17
|
+
this.client = sc.get(props, 'client', 'mysql');
|
|
18
|
+
this.debug = sc.get(props, 'debug', false);
|
|
19
|
+
this.dataProxy = sc.get(props, 'dataProxy', false);
|
|
20
|
+
this.checkInterval = sc.get(props, 'checkInterval', 1000);
|
|
21
|
+
this.maxWaitTime = sc.get(props, 'maxWaitTime', 30000);
|
|
22
|
+
this.prismaSchemaPath = sc.get(props, 'prismaSchemaPath', FileHandler.joinPaths(process.cwd(), 'prisma'));
|
|
23
|
+
this.schemaFilePath = FileHandler.joinPaths(this.prismaSchemaPath, 'schema.prisma');
|
|
24
|
+
this.clientOutputPath = sc.get(props, 'clientOutputPath', '');
|
|
25
|
+
this.generateBinaryTargets = sc.get(props, 'generateBinaryTargets', ['native', 'debian-openssl-1.1.x']);
|
|
26
|
+
this.dbParams = sc.get(props, 'dbParams', process.env.RELDENS_DB_PARAMS || '');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async generate()
|
|
30
|
+
{
|
|
31
|
+
FileHandler.createFolder(this.prismaSchemaPath);
|
|
32
|
+
this.generateSchemaFile();
|
|
33
|
+
Logger.info('Running prisma introspect "npx prisma db pull"...');
|
|
34
|
+
try {
|
|
35
|
+
execSync('npx prisma db pull', { stdio: 'inherit' });
|
|
36
|
+
} catch(error) {
|
|
37
|
+
Logger.critical('Failed to pull database schema: ' + error.message);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
let generateCommand = 'npx prisma generate';
|
|
41
|
+
if(this.dataProxy){
|
|
42
|
+
generateCommand += ' --data-proxy';
|
|
43
|
+
}
|
|
44
|
+
Logger.info('Running prisma generate "'+generateCommand+'"...');
|
|
45
|
+
try {
|
|
46
|
+
execSync(generateCommand, { stdio: 'inherit' });
|
|
47
|
+
} catch(error) {
|
|
48
|
+
let errorString = error.toString();
|
|
49
|
+
if(errorString.includes('EPERM') && errorString.includes('query_engine-windows.dll.node')){
|
|
50
|
+
Logger.warning('Windows permission error detected with query engine file.');
|
|
51
|
+
Logger.warning('This is a known Prisma issue on Windows.');
|
|
52
|
+
Logger.warning('Please manually run: ' + generateCommand);
|
|
53
|
+
Logger.warning('You may need to close any processes using the Prisma client first.');
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
Logger.critical('Generate command failed: ' + error.message);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
await this.waitForSchemaGeneration();
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async waitForSchemaGeneration()
|
|
64
|
+
{
|
|
65
|
+
let clientPath = this.clientOutputPath || 'node_modules/.prisma/client';
|
|
66
|
+
let generatedClientPath = this.resolveClientPath(clientPath);
|
|
67
|
+
let clientIndexPath = FileHandler.joinPaths(generatedClientPath, 'index.js');
|
|
68
|
+
let startTime = Date.now();
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
let interval = setInterval(() => {
|
|
71
|
+
let awaitTime = Date.now() - startTime;
|
|
72
|
+
Logger.info('Awaiting on schema generation: ' + clientIndexPath, (awaitTime/1000).toFixed(0));
|
|
73
|
+
if(FileHandler.exists(clientIndexPath)){
|
|
74
|
+
clearInterval(interval);
|
|
75
|
+
resolve();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if(awaitTime > this.maxWaitTime){
|
|
79
|
+
clearInterval(interval);
|
|
80
|
+
Logger.warning('Schema generation wait timeout reached.');
|
|
81
|
+
resolve();
|
|
82
|
+
}
|
|
83
|
+
}, this.checkInterval);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
resolveClientPath(clientPath)
|
|
88
|
+
{
|
|
89
|
+
if(clientPath.match(/^[a-zA-Z]:/) || clientPath.startsWith('/')){
|
|
90
|
+
return clientPath;
|
|
91
|
+
}
|
|
92
|
+
if(clientPath.startsWith('node_modules')){
|
|
93
|
+
return FileHandler.joinPaths(process.cwd(), clientPath);
|
|
94
|
+
}
|
|
95
|
+
return FileHandler.joinPaths(this.prismaSchemaPath, clientPath);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
generateSchemaFile()
|
|
99
|
+
{
|
|
100
|
+
let datasourceProvider = this.getDatasourceProvider();
|
|
101
|
+
let schemaContent = this.buildSchemaContent(
|
|
102
|
+
datasourceProvider,
|
|
103
|
+
this.buildConnectionString(datasourceProvider),
|
|
104
|
+
this.buildDirectConnectionString(datasourceProvider)
|
|
105
|
+
);
|
|
106
|
+
FileHandler.writeFile(this.schemaFilePath, schemaContent);
|
|
107
|
+
Logger.info('Generated Prisma schema file at: '+this.schemaFilePath);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getDatasourceProvider()
|
|
111
|
+
{
|
|
112
|
+
if('postgresql' === this.client || 'postgres' === this.client){
|
|
113
|
+
return 'postgresql';
|
|
114
|
+
}
|
|
115
|
+
if('mongodb' === this.client){
|
|
116
|
+
return 'mongodb';
|
|
117
|
+
}
|
|
118
|
+
return 'mysql';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
buildConnectionString(datasourceProvider)
|
|
122
|
+
{
|
|
123
|
+
if(this.dataProxy){
|
|
124
|
+
datasourceProvider = 'prisma';
|
|
125
|
+
}
|
|
126
|
+
return datasourceProvider + this.buildConnectionDataString();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
buildDirectConnectionString(datasourceProvider)
|
|
130
|
+
{
|
|
131
|
+
if(!this.dataProxy){
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
return datasourceProvider + this.buildConnectionDataString();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
buildConnectionDataString()
|
|
138
|
+
{
|
|
139
|
+
return '://' + this.config.user + ':' + this.config.password
|
|
140
|
+
+ '@' + this.config.host+':' + this.config.port
|
|
141
|
+
+ '/' + this.config.database
|
|
142
|
+
+ (this.dbParams ? '?' + this.dbParams : '');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
buildSchemaContent(datasourceProvider, connectionString, directConnectionString)
|
|
146
|
+
{
|
|
147
|
+
return this.buildGeneratorBlock() + '\n\n'
|
|
148
|
+
+ this.buildDatasourceBlock(datasourceProvider, connectionString, directConnectionString) + '\n';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
buildGeneratorBlock()
|
|
152
|
+
{
|
|
153
|
+
let generatorContent = 'generator client {\n';
|
|
154
|
+
generatorContent += ' provider = "prisma-client-js"\n';
|
|
155
|
+
if(this.clientOutputPath){
|
|
156
|
+
let normalizedPath = this.clientOutputPath.replace(/\\/g, '/');
|
|
157
|
+
generatorContent += ' output = "' + normalizedPath + '"\n';
|
|
158
|
+
}
|
|
159
|
+
if(0 < this.generateBinaryTargets.length){
|
|
160
|
+
generatorContent += ' binaryTargets = [' +
|
|
161
|
+
this.generateBinaryTargets.map(target => '"' + target + '"').join(', ')
|
|
162
|
+
+ ']\n';
|
|
163
|
+
}
|
|
164
|
+
generatorContent += '}';
|
|
165
|
+
return generatorContent;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
buildDatasourceBlock(datasourceProvider, connectionString, directConnectionString)
|
|
169
|
+
{
|
|
170
|
+
let datasourceContent = 'datasource db {\n';
|
|
171
|
+
datasourceContent += ' provider = "' + datasourceProvider + '"\n';
|
|
172
|
+
datasourceContent += ' url = "' + connectionString + '"\n';
|
|
173
|
+
if('' !== directConnectionString){
|
|
174
|
+
datasourceContent += ' directUrl = "' + directConnectionString + '"\n';
|
|
175
|
+
}
|
|
176
|
+
datasourceContent += '}';
|
|
177
|
+
return datasourceContent;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports.PrismaSchemaGenerator = PrismaSchemaGenerator;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - PrismaTypeCaster
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
const { Prisma } = require('@prisma/client');
|
|
9
|
+
|
|
10
|
+
class PrismaTypeCaster
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
constructor(props)
|
|
14
|
+
{
|
|
15
|
+
this.idFieldType = sc.get(props, 'idFieldType', 'String');
|
|
16
|
+
this.jsonFields = sc.get(props, 'jsonFields', new Set());
|
|
17
|
+
this.fieldTypes = sc.get(props, 'fieldTypes', {});
|
|
18
|
+
this.fieldDefaults = sc.get(props, 'fieldDefaults', {});
|
|
19
|
+
this.requiredFields = sc.get(props, 'requiredFields', []);
|
|
20
|
+
this.optionalFields = sc.get(props, 'optionalFields', []);
|
|
21
|
+
this.rawModel = sc.get(props, 'rawModel', false);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
updateMetadata(metadata)
|
|
25
|
+
{
|
|
26
|
+
this.idFieldType = sc.get(metadata, 'idFieldType', this.idFieldType);
|
|
27
|
+
this.jsonFields = sc.get(metadata, 'jsonFields', this.jsonFields);
|
|
28
|
+
this.fieldTypes = sc.get(metadata, 'fieldTypes', this.fieldTypes);
|
|
29
|
+
this.fieldDefaults = sc.get(metadata, 'fieldDefaults', this.fieldDefaults);
|
|
30
|
+
this.requiredFields = sc.get(metadata, 'requiredFields', this.requiredFields);
|
|
31
|
+
this.optionalFields = sc.get(metadata, 'optionalFields', this.optionalFields);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
isNumericFieldType(fieldType)
|
|
35
|
+
{
|
|
36
|
+
return ('Int' === fieldType || 'BigInt' === fieldType || 'Float' === fieldType || 'Decimal' === fieldType);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
isBooleanFieldType(fieldType)
|
|
40
|
+
{
|
|
41
|
+
return 'Boolean' === fieldType;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
isDateTimeFieldType(fieldType)
|
|
45
|
+
{
|
|
46
|
+
return 'DateTime' === fieldType || 'Date' === fieldType;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
isJsonFieldType(fieldType)
|
|
50
|
+
{
|
|
51
|
+
return 'Json' === fieldType;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
isJsonFieldByName(fieldName)
|
|
55
|
+
{
|
|
56
|
+
if(this.jsonFields.has(fieldName)){
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if(!this.rawModel || !this.rawModel.properties){
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return 'json' === sc.get(this.rawModel.properties[fieldName], 'dbType', '');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
isStringFieldType(fieldType)
|
|
66
|
+
{
|
|
67
|
+
return 'String' === fieldType;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isNullOrEmpty(value)
|
|
71
|
+
{
|
|
72
|
+
return null === value || undefined === value || '' === value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
castValue(value, fieldType, fieldName = null)
|
|
76
|
+
{
|
|
77
|
+
if('id' === fieldName){
|
|
78
|
+
return this.castToIdType(value);
|
|
79
|
+
}
|
|
80
|
+
if(this.isNullOrEmpty(value)){
|
|
81
|
+
if(sc.hasOwn(this.fieldDefaults, fieldName)){
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
if(-1 !== this.optionalFields.indexOf(fieldName)){
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if(-1 !== this.requiredFields.indexOf(fieldName)){
|
|
88
|
+
Logger.warning('Required field '+fieldName+' cannot be null or empty');
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
if(this.isJsonFieldByName(fieldName)){
|
|
94
|
+
return this.castToJsonType(value);
|
|
95
|
+
}
|
|
96
|
+
if(this.isNumericFieldType(fieldType)){
|
|
97
|
+
return this.castToNumericType(value, fieldType);
|
|
98
|
+
}
|
|
99
|
+
if(this.isBooleanFieldType(fieldType)){
|
|
100
|
+
return this.castToBooleanType(value);
|
|
101
|
+
}
|
|
102
|
+
if(this.isDateTimeFieldType(fieldType)){
|
|
103
|
+
return this.castToDateType(value);
|
|
104
|
+
}
|
|
105
|
+
if(this.isStringFieldType(fieldType)){
|
|
106
|
+
return this.castToStringType(value);
|
|
107
|
+
}
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
castToIdType(value)
|
|
112
|
+
{
|
|
113
|
+
if(this.isNullOrEmpty(value)){
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
if(this.isNumericFieldType(this.idFieldType)){
|
|
117
|
+
let numeric = Number(value);
|
|
118
|
+
if(!isNaN(numeric)){
|
|
119
|
+
return ('Int' === this.idFieldType || 'BigInt' === this.idFieldType) ? Math.floor(numeric) : numeric;
|
|
120
|
+
}
|
|
121
|
+
Logger.warning('Cannot cast non-numeric value "'+value+'" to ID type '+this.idFieldType);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return String(value);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
castToNumericType(value, fieldType)
|
|
128
|
+
{
|
|
129
|
+
if(this.isNullOrEmpty(value)){
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
let numericValue = Number(value);
|
|
133
|
+
if(isNaN(numericValue)){
|
|
134
|
+
Logger.warning('Cannot convert value to numeric: '+value);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if('Int' === fieldType || 'BigInt' === fieldType){
|
|
138
|
+
return Math.floor(numericValue);
|
|
139
|
+
}
|
|
140
|
+
return numericValue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
castToBooleanType(value)
|
|
144
|
+
{
|
|
145
|
+
if(this.isNullOrEmpty(value)){
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
if('boolean' === typeof value){
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
if('number' === typeof value){
|
|
152
|
+
return 0 !== value;
|
|
153
|
+
}
|
|
154
|
+
if('string' === typeof value){
|
|
155
|
+
let lowerValue = value.toLowerCase();
|
|
156
|
+
if('true' === lowerValue || '1' === lowerValue || 'yes' === lowerValue){
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
if('false' === lowerValue || '0' === lowerValue || 'no' === lowerValue){
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return Boolean(value);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
castToDateType(dateValue)
|
|
167
|
+
{
|
|
168
|
+
if(dateValue instanceof Date){
|
|
169
|
+
return dateValue;
|
|
170
|
+
}
|
|
171
|
+
if(this.isNullOrEmpty(dateValue)){
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
let dateString = String(dateValue);
|
|
175
|
+
if(dateString.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/)){
|
|
176
|
+
return new Date(dateString.replace(' ', 'T')+'Z');
|
|
177
|
+
}
|
|
178
|
+
if(dateString.match(/^\d{4}-\d{2}-\d{2}$/)){
|
|
179
|
+
return new Date(dateString+'T00:00:00Z');
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
let parsedDate = new Date(dateString);
|
|
183
|
+
if(isNaN(parsedDate.getTime())){
|
|
184
|
+
Logger.warning('Invalid date value: '+dateString);
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return parsedDate;
|
|
188
|
+
} catch(error) {
|
|
189
|
+
Logger.warning('Failed to convert date value: '+dateString);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
castToJsonType(value)
|
|
195
|
+
{
|
|
196
|
+
if(this.isNullOrEmpty(value)){
|
|
197
|
+
return Prisma.DbNull;
|
|
198
|
+
}
|
|
199
|
+
if('object' === typeof value){
|
|
200
|
+
return value;
|
|
201
|
+
}
|
|
202
|
+
if('string' === typeof value){
|
|
203
|
+
if(value.startsWith('%') && value.endsWith('%')){
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
return JSON.parse(value);
|
|
208
|
+
} catch(error) {
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
castToStringType(value)
|
|
216
|
+
{
|
|
217
|
+
if(null === value || undefined === value){
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
if('string' === typeof value){
|
|
221
|
+
if('null' === value){
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
return value;
|
|
225
|
+
}
|
|
226
|
+
return String(value);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
module.exports.PrismaTypeCaster = PrismaTypeCaster;
|