@saltcorn/data 0.6.2 → 0.6.3-beta.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/dist/base-plugin/index.d.ts +97 -92
- package/dist/base-plugin/index.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/edit.js +25 -2
- package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/feed.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/feed.js +11 -1
- package/dist/base-plugin/viewtemplates/feed.js.map +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts +1 -1
- package/dist/base-plugin/viewtemplates/list.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/list.js +23 -11
- package/dist/base-plugin/viewtemplates/list.js.map +1 -1
- package/dist/base-plugin/viewtemplates/show.d.ts +5 -0
- package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
- package/dist/base-plugin/viewtemplates/show.js +34 -4
- package/dist/base-plugin/viewtemplates/show.js.map +1 -1
- package/dist/common_types.d.ts +28 -0
- package/dist/common_types.d.ts.map +1 -0
- package/dist/common_types.js +16 -0
- package/dist/common_types.js.map +1 -0
- package/dist/models/backup.d.ts +6 -21
- package/dist/models/backup.d.ts.map +1 -1
- package/dist/models/backup.js +48 -44
- package/dist/models/backup.js.map +1 -1
- package/dist/models/eventlog.d.ts +39 -38
- package/dist/models/eventlog.d.ts.map +1 -1
- package/dist/models/eventlog.js +14 -29
- package/dist/models/eventlog.js.map +1 -1
- package/dist/models/expression.d.ts.map +1 -1
- package/dist/models/expression.js +14 -3
- package/dist/models/expression.js.map +1 -1
- package/dist/models/field.d.ts +123 -120
- package/dist/models/field.d.ts.map +1 -1
- package/dist/models/field.js +129 -147
- package/dist/models/field.js.map +1 -1
- package/dist/models/form.d.ts.map +1 -1
- package/dist/models/form.js +2 -0
- package/dist/models/form.js.map +1 -1
- package/dist/models/library.d.ts +29 -19
- package/dist/models/library.d.ts.map +1 -1
- package/dist/models/library.js +10 -8
- package/dist/models/library.js.map +1 -1
- package/dist/models/role.d.ts +13 -9
- package/dist/models/role.d.ts.map +1 -1
- package/dist/models/role.js +10 -7
- package/dist/models/role.js.map +1 -1
- package/dist/models/table.d.ts +85 -132
- package/dist/models/table.d.ts.map +1 -1
- package/dist/models/table.js +172 -177
- package/dist/models/table.js.map +1 -1
- package/dist/models/tenant.d.ts +6 -0
- package/dist/models/tenant.d.ts.map +1 -1
- package/dist/models/tenant.js +9 -0
- package/dist/models/tenant.js.map +1 -1
- package/dist/models/trigger.d.ts +62 -66
- package/dist/models/trigger.d.ts.map +1 -1
- package/dist/models/trigger.js +7 -33
- package/dist/models/trigger.js.map +1 -1
- package/dist/tests/calc.test.js +13 -0
- package/dist/tests/calc.test.js.map +1 -1
- package/dist/tests/exact_views.test.js +214 -0
- package/dist/tests/exact_views.test.js.map +1 -1
- package/dist/tests/table.test.js +7 -0
- package/dist/tests/table.test.js.map +1 -1
- package/dist/tsconfig.ref.tsbuildinfo +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +26 -0
- package/dist/utils.js.map +1 -1
- package/package.json +8 -5
package/dist/models/field.js
CHANGED
|
@@ -5,18 +5,22 @@
|
|
|
5
5
|
* @module models/field
|
|
6
6
|
* @subcategory models
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
const db_1 = __importDefault(require("../db"));
|
|
10
12
|
const { recalculate_for_stored, jsexprToWhere } = require("./expression");
|
|
11
|
-
const
|
|
13
|
+
const internal_1 = require("@saltcorn/db-common/internal");
|
|
12
14
|
const { InvalidAdminAction } = require("../utils");
|
|
13
|
-
const
|
|
15
|
+
const common_types_1 = require("../common_types");
|
|
14
16
|
const readKey = (v, field) => {
|
|
15
17
|
if (v === "")
|
|
16
18
|
return null;
|
|
17
19
|
if (typeof v === "string" && v.startsWith("Preset:"))
|
|
18
20
|
return v;
|
|
19
21
|
const { getState } = require("../db/state");
|
|
22
|
+
if (!field.reftype)
|
|
23
|
+
throw new Error("Unable to find the type, 'reftype' is undefined.");
|
|
20
24
|
const type = getState().types[field.reftype];
|
|
21
25
|
const parsed = type.read(v);
|
|
22
26
|
return parsed || (v ? { error: "Unable to read key" } : null);
|
|
@@ -31,10 +35,13 @@ class Field {
|
|
|
31
35
|
* @param o
|
|
32
36
|
*/
|
|
33
37
|
constructor(o) {
|
|
38
|
+
this.refname = "";
|
|
39
|
+
if (!o.name && !o.label)
|
|
40
|
+
throw new Error(`Field initialised with no name and no label`);
|
|
41
|
+
this.label = (o.label || o.name);
|
|
42
|
+
this.name = (o.name || Field.labelToName(this.label));
|
|
34
43
|
if (!o.type && !o.input_type)
|
|
35
44
|
throw new Error(`Field ${o.name} initialised with no type`);
|
|
36
|
-
this.label = o.label || o.name;
|
|
37
|
-
this.name = o.name || Field.labelToName(o.label);
|
|
38
45
|
this.fieldview = o.fieldview;
|
|
39
46
|
this.validator = o.validator || (() => true);
|
|
40
47
|
this.showIf = o.showIf;
|
|
@@ -48,7 +55,7 @@ class Field {
|
|
|
48
55
|
const { getState } = require("../db/state");
|
|
49
56
|
this.type = typeof o.type === "string" ? getState().types[o.type] : o.type;
|
|
50
57
|
if (!this.type)
|
|
51
|
-
this.typename = o.type;
|
|
58
|
+
this.typename = typeof o.type === "string" ? o.type : o.type?.name;
|
|
52
59
|
this.options = o.options;
|
|
53
60
|
this.required = o.required ? true : false;
|
|
54
61
|
this.is_unique = o.is_unique ? true : false;
|
|
@@ -74,10 +81,9 @@ class Field {
|
|
|
74
81
|
this.refname = "id";
|
|
75
82
|
}
|
|
76
83
|
else {
|
|
77
|
-
this.reftable_name =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
o.type.replace("Key to ", "");
|
|
84
|
+
this.reftable_name = o.reftable_name || (o.reftable && o.reftable.name);
|
|
85
|
+
if (!this.reftable_name && o.type && typeof o.type === "string")
|
|
86
|
+
this.reftable_name = o.type.replace("Key to ", "");
|
|
81
87
|
this.reftable = o.reftable;
|
|
82
88
|
this.type = "Key";
|
|
83
89
|
this.input_type =
|
|
@@ -96,7 +102,6 @@ class Field {
|
|
|
96
102
|
if (o.table.id && !o.table_id)
|
|
97
103
|
this.table_id = o.table.id;
|
|
98
104
|
}
|
|
99
|
-
contract.class(this);
|
|
100
105
|
}
|
|
101
106
|
/**
|
|
102
107
|
* To Json
|
|
@@ -114,7 +119,7 @@ class Field {
|
|
|
114
119
|
expression: this.expression,
|
|
115
120
|
sublabel: this.sublabel,
|
|
116
121
|
fieldview: this.fieldview,
|
|
117
|
-
type: typeof this.type === "string" ? this.type : this.type
|
|
122
|
+
type: typeof this.type === "string" ? this.type : this.type?.name,
|
|
118
123
|
reftable_name: this.reftable_name,
|
|
119
124
|
attributes: this.attributes,
|
|
120
125
|
required: this.required,
|
|
@@ -132,7 +137,7 @@ class Field {
|
|
|
132
137
|
// todo from internalization point of view better to separate label, name. sqlname
|
|
133
138
|
// because label can contain characters that cannot be used in PG for sql names
|
|
134
139
|
static labelToName(label) {
|
|
135
|
-
return sqlsanitize(label.toLowerCase().replace(" ", "_"));
|
|
140
|
+
return (0, internal_1.sqlsanitize)(label.toLowerCase().replace(" ", "_"));
|
|
136
141
|
}
|
|
137
142
|
/**
|
|
138
143
|
* ???
|
|
@@ -150,7 +155,7 @@ class Field {
|
|
|
150
155
|
* @param {object} where
|
|
151
156
|
* @returns {Promise<void>}
|
|
152
157
|
*/
|
|
153
|
-
async fill_fkey_options(force_allow_none = false, where0, extraCtx) {
|
|
158
|
+
async fill_fkey_options(force_allow_none = false, where0, extraCtx = {}) {
|
|
154
159
|
const where = where0 ||
|
|
155
160
|
(this.attributes.where
|
|
156
161
|
? jsexprToWhere(this.attributes.where, extraCtx)
|
|
@@ -159,7 +164,7 @@ class Field {
|
|
|
159
164
|
if (this.is_fkey &&
|
|
160
165
|
(this.type !== "File" ||
|
|
161
166
|
typeof this.attributes.select_file_where !== "undefined")) {
|
|
162
|
-
const rows = await
|
|
167
|
+
const rows = await db_1.default.select(this.reftable_name, this.type === "File" ? this.attributes.select_file_where : where);
|
|
163
168
|
const summary_field = this.attributes.summary_field ||
|
|
164
169
|
(this.type === "File" ? "filename" : "id");
|
|
165
170
|
const dbOpts = rows.map((r) => ({
|
|
@@ -179,7 +184,8 @@ class Field {
|
|
|
179
184
|
*/
|
|
180
185
|
async distinct_values(req, where) {
|
|
181
186
|
const __ = req && req.__ ? req.__ : (s) => s;
|
|
182
|
-
if (this.type
|
|
187
|
+
if ((0, common_types_1.instanceOfTypeObj)(this.type) &&
|
|
188
|
+
this.type.name === "String" &&
|
|
183
189
|
this.attributes &&
|
|
184
190
|
this.attributes.options) {
|
|
185
191
|
return [
|
|
@@ -193,7 +199,7 @@ class Field {
|
|
|
193
199
|
await this.fill_fkey_options(false, where);
|
|
194
200
|
return this.options || [];
|
|
195
201
|
}
|
|
196
|
-
if (this.type.name === "Bool") {
|
|
202
|
+
if ((0, common_types_1.instanceOfTypeObj)(this.type) && this.type.name === "Bool") {
|
|
197
203
|
return [
|
|
198
204
|
{ label: "", value: "" },
|
|
199
205
|
{ label: __("True"), value: "on", jsvalue: true },
|
|
@@ -204,11 +210,11 @@ class Field {
|
|
|
204
210
|
let whereS = "";
|
|
205
211
|
let values = [];
|
|
206
212
|
if (where) {
|
|
207
|
-
const whereValues = mkWhere(where);
|
|
213
|
+
const whereValues = db_1.default.mkWhere(where);
|
|
208
214
|
whereS = whereValues.where;
|
|
209
215
|
values = whereValues.values;
|
|
210
216
|
}
|
|
211
|
-
const { rows } = await
|
|
217
|
+
const { rows } = await db_1.default.query(`select distinct "${db_1.default.sqlsanitize(this.name)}" from ${this.table?.sql_name} ${whereS} order by "${db_1.default.sqlsanitize(this.name)}"`, values);
|
|
212
218
|
const dbOpts = rows.map((r) => ({
|
|
213
219
|
label: `${r[this.name]}`,
|
|
214
220
|
value: r[this.name],
|
|
@@ -220,13 +226,19 @@ class Field {
|
|
|
220
226
|
*/
|
|
221
227
|
get sql_type() {
|
|
222
228
|
if (this.is_fkey) {
|
|
223
|
-
|
|
229
|
+
if (!this.reftype || !this.reftable_name) {
|
|
230
|
+
throw new Error("'reftype' and 'reftable_name' must be set if 'is_fkey' is true.");
|
|
231
|
+
}
|
|
232
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
224
233
|
const { getState } = require("../db/state");
|
|
225
|
-
return `${getState().types[this.reftype].sql_name} references ${schema}"${sqlsanitize(this.reftable_name)}" ("${this.refname}")`;
|
|
234
|
+
return `${getState().types[this.reftype].sql_name} references ${schema}"${(0, internal_1.sqlsanitize)(this.reftable_name)}" ("${this.refname}")`;
|
|
226
235
|
}
|
|
227
|
-
else
|
|
236
|
+
else if (this.type &&
|
|
237
|
+
(0, common_types_1.instanceOfTypeObj)(this.type) &&
|
|
238
|
+
this.type.sql_name) {
|
|
228
239
|
return this.type.sql_name;
|
|
229
240
|
}
|
|
241
|
+
throw new Error("Unable to get the sql_type");
|
|
230
242
|
}
|
|
231
243
|
/**
|
|
232
244
|
* @type {string}
|
|
@@ -237,31 +249,37 @@ class Field {
|
|
|
237
249
|
if (this.is_fkey)
|
|
238
250
|
return `Key to ${this.reftable_name}`;
|
|
239
251
|
else
|
|
240
|
-
return this.type ? this.type.name : "?";
|
|
252
|
+
return this.type && (0, common_types_1.instanceOfTypeObj)(this.type) ? this.type.name : "?";
|
|
241
253
|
}
|
|
242
254
|
/**
|
|
243
255
|
* @type {string}
|
|
244
256
|
*/
|
|
245
257
|
get sql_bare_type() {
|
|
246
258
|
if (this.is_fkey) {
|
|
259
|
+
if (!this.reftype || !this.reftable_name) {
|
|
260
|
+
throw new Error("'reftype' and 'reftable_name' must be set if 'is_fkey' is true.");
|
|
261
|
+
}
|
|
247
262
|
const { getState } = require("../db/state");
|
|
248
263
|
return getState().types[this.reftype].sql_name;
|
|
249
264
|
}
|
|
250
|
-
else
|
|
265
|
+
else if (this.type &&
|
|
266
|
+
(0, common_types_1.instanceOfTypeObj)(this.type) &&
|
|
267
|
+
this.type.sql_name) {
|
|
251
268
|
return this.type.sql_name;
|
|
252
269
|
}
|
|
270
|
+
throw new Error("Unable to get the sql_type");
|
|
253
271
|
}
|
|
254
272
|
/**
|
|
255
273
|
* @returns {Promise<any>}
|
|
256
274
|
*/
|
|
257
275
|
async generate() {
|
|
258
276
|
if (this.is_fkey) {
|
|
259
|
-
const rows = await
|
|
277
|
+
const rows = await db_1.default.select(this.reftable_name, {}, { limit: 1, orderBy: "RANDOM()" });
|
|
260
278
|
if (rows.length === 1)
|
|
261
279
|
return rows[0].id;
|
|
262
280
|
}
|
|
263
281
|
else {
|
|
264
|
-
if (this.type && this.type.contract)
|
|
282
|
+
if ((0, common_types_1.instanceOfTypeObj)(this.type) && this.type.contract)
|
|
265
283
|
return this.type.contract(this.attributes).generate();
|
|
266
284
|
}
|
|
267
285
|
}
|
|
@@ -271,19 +289,25 @@ class Field {
|
|
|
271
289
|
*/
|
|
272
290
|
validate(whole_rec) {
|
|
273
291
|
const type = this.is_fkey ? { name: "Key" } : this.type;
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
292
|
+
let readval = null;
|
|
293
|
+
if (this.is_fkey) {
|
|
294
|
+
readval = readKey(whole_rec[this.form_name], this);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
let typeObj = this.type;
|
|
298
|
+
readval =
|
|
299
|
+
!type || !typeObj.read
|
|
300
|
+
? whole_rec[this.form_name]
|
|
301
|
+
: typeObj.readFromFormRecord
|
|
302
|
+
? typeObj.readFromFormRecord(whole_rec, this.form_name)
|
|
303
|
+
: typeObj.read(whole_rec[this.form_name], this.attributes);
|
|
304
|
+
}
|
|
281
305
|
if (typeof readval === "undefined" || readval === null)
|
|
282
306
|
if (this.required && this.type !== "File")
|
|
283
|
-
return { error: "Unable to read " + type
|
|
307
|
+
return { error: "Unable to read " + type?.name };
|
|
284
308
|
else
|
|
285
309
|
return { success: null };
|
|
286
|
-
const tyvalres = type && type.validate
|
|
310
|
+
const tyvalres = (0, common_types_1.instanceOfTypeObj)(type) && type.validate
|
|
287
311
|
? type.validate(this.attributes || {})(readval)
|
|
288
312
|
: readval;
|
|
289
313
|
if (tyvalres.error)
|
|
@@ -303,7 +327,7 @@ class Field {
|
|
|
303
327
|
* @returns {Field[]}
|
|
304
328
|
*/
|
|
305
329
|
static async find(where, selectopts = { orderBy: "name", nocase: true }) {
|
|
306
|
-
const db_flds = await
|
|
330
|
+
const db_flds = await db_1.default.select("_sc_fields", where, selectopts);
|
|
307
331
|
return db_flds.map((dbf) => new Field(dbf));
|
|
308
332
|
}
|
|
309
333
|
/**
|
|
@@ -311,7 +335,7 @@ class Field {
|
|
|
311
335
|
* @returns {Promise<Field>}
|
|
312
336
|
*/
|
|
313
337
|
static async findOne(where) {
|
|
314
|
-
const db_fld = await
|
|
338
|
+
const db_fld = await db_1.default.selectOne("_sc_fields", where);
|
|
315
339
|
return new Field(db_fld);
|
|
316
340
|
}
|
|
317
341
|
/**
|
|
@@ -319,14 +343,14 @@ class Field {
|
|
|
319
343
|
*/
|
|
320
344
|
async add_unique_constraint() {
|
|
321
345
|
await this.fill_table();
|
|
322
|
-
await
|
|
346
|
+
await db_1.default.add_unique_constraint(this.table?.name, [this.name]);
|
|
323
347
|
}
|
|
324
348
|
/**
|
|
325
349
|
* @returns {Promise<void>}
|
|
326
350
|
*/
|
|
327
351
|
async remove_unique_constraint() {
|
|
328
352
|
await this.fill_table();
|
|
329
|
-
await
|
|
353
|
+
await db_1.default.drop_unique_constraint(this.table?.name, [this.name]);
|
|
330
354
|
}
|
|
331
355
|
/**
|
|
332
356
|
*
|
|
@@ -334,9 +358,12 @@ class Field {
|
|
|
334
358
|
* @returns {Promise<void>}
|
|
335
359
|
*/
|
|
336
360
|
async toggle_not_null(not_null) {
|
|
337
|
-
|
|
361
|
+
if (!this.table) {
|
|
362
|
+
throw new Error("To toogle a not null constraint, 'table' must be set.");
|
|
363
|
+
}
|
|
364
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
338
365
|
await this.fill_table();
|
|
339
|
-
await
|
|
366
|
+
await db_1.default.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(this.table.name)}" alter column "${(0, internal_1.sqlsanitize)(this.name)}" ${not_null ? "set" : "drop"} not null;`);
|
|
340
367
|
await require("../db/state").getState().refresh_tables();
|
|
341
368
|
}
|
|
342
369
|
/**
|
|
@@ -344,22 +371,27 @@ class Field {
|
|
|
344
371
|
* @returns {Promise<void>}
|
|
345
372
|
*/
|
|
346
373
|
async alter_sql_type(new_field) {
|
|
374
|
+
if (!this.table) {
|
|
375
|
+
throw new Error(`To add the field '${new_field.name}', 'table' must be set.`);
|
|
376
|
+
}
|
|
347
377
|
let new_sql_type = new_field.sql_type;
|
|
348
378
|
let def = "";
|
|
349
|
-
let using = `USING ("${sqlsanitize(this.name)}"::${new_sql_type})`;
|
|
350
|
-
const schema =
|
|
379
|
+
let using = `USING ("${(0, internal_1.sqlsanitize)(this.name)}"::${new_sql_type})`;
|
|
380
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
351
381
|
await this.fill_table();
|
|
352
382
|
if (new_field.primary_key) {
|
|
353
|
-
await
|
|
354
|
-
if (new_field.type
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
383
|
+
await db_1.default.query(`ALTER TABLE ${schema}"${(0, internal_1.sqlsanitize)(this.table.name)}" drop column "${(0, internal_1.sqlsanitize)(this.name)}";`);
|
|
384
|
+
if ((0, common_types_1.instanceOfTypeObj)(new_field.type)) {
|
|
385
|
+
if (new_field.type.primaryKey.sql_type)
|
|
386
|
+
new_sql_type = new_field.type.primaryKey.sql_type;
|
|
387
|
+
if (new_field.type.primaryKey.default_sql) {
|
|
388
|
+
def = `default ${new_field.type.primaryKey.default_sql}`;
|
|
389
|
+
}
|
|
358
390
|
}
|
|
359
|
-
await
|
|
391
|
+
await db_1.default.query(`ALTER TABLE ${schema}"${(0, internal_1.sqlsanitize)(this.table.name)}" add column "${(0, internal_1.sqlsanitize)(this.name)}" ${new_sql_type} primary key ${def};`);
|
|
360
392
|
}
|
|
361
393
|
else
|
|
362
|
-
await
|
|
394
|
+
await db_1.default.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(this.table.name)}" alter column "${(0, internal_1.sqlsanitize)(this.name)}" TYPE ${new_sql_type} ${using} ${def};`);
|
|
363
395
|
await require("../db/state").getState().refresh_tables();
|
|
364
396
|
}
|
|
365
397
|
/**
|
|
@@ -376,25 +408,30 @@ class Field {
|
|
|
376
408
|
* @returns {Promise<void>}
|
|
377
409
|
*/
|
|
378
410
|
async update(v) {
|
|
411
|
+
const f = new Field({ ...this, ...v });
|
|
412
|
+
const rename = f.name !== this.name;
|
|
413
|
+
if (rename && !this.table?.name) {
|
|
414
|
+
throw new Error("");
|
|
415
|
+
}
|
|
379
416
|
if (typeof v.is_unique !== "undefined" &&
|
|
380
417
|
!!v.is_unique !== !!this.is_unique) {
|
|
381
418
|
if (v.is_unique && !this.is_unique)
|
|
382
419
|
await this.add_unique_constraint();
|
|
383
420
|
if (!v.is_unique && this.is_unique)
|
|
384
421
|
await this.remove_unique_constraint();
|
|
385
|
-
await
|
|
422
|
+
await db_1.default.update("_sc_fields", { is_unique: v.is_unique }, this.id);
|
|
386
423
|
}
|
|
387
424
|
if (typeof v.required !== "undefined" && !!v.required !== !!this.required)
|
|
388
425
|
await this.toggle_not_null(!!v.required);
|
|
389
|
-
const f = new Field({ ...this, ...v });
|
|
390
426
|
if (f.sql_type !== this.sql_type) {
|
|
391
427
|
await this.alter_sql_type(f);
|
|
392
428
|
}
|
|
393
|
-
if (
|
|
394
|
-
const schema =
|
|
395
|
-
await
|
|
429
|
+
if (rename) {
|
|
430
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
431
|
+
await db_1.default.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(this.table.name // ensured above
|
|
432
|
+
)}" rename column "${(0, internal_1.sqlsanitize)(this.name)}" TO ${f.name};`);
|
|
396
433
|
}
|
|
397
|
-
await
|
|
434
|
+
await db_1.default.update("_sc_fields", v, this.id);
|
|
398
435
|
Object.entries(v).forEach(([k, v]) => {
|
|
399
436
|
this[k] = v;
|
|
400
437
|
});
|
|
@@ -404,17 +441,18 @@ class Field {
|
|
|
404
441
|
* @type {string}
|
|
405
442
|
*/
|
|
406
443
|
get listKey() {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
444
|
+
if ((0, common_types_1.instanceOfTypeObj)(this.type))
|
|
445
|
+
if (this.type.listAs)
|
|
446
|
+
return (r) => this.type.listAs(r[this.name]);
|
|
447
|
+
else if (this.type.showAs)
|
|
448
|
+
return (r) => this.type.showAs(r[this.name]);
|
|
449
|
+
return this.name;
|
|
412
450
|
}
|
|
413
451
|
/**
|
|
414
452
|
* @type {object}
|
|
415
453
|
*/
|
|
416
454
|
get presets() {
|
|
417
|
-
if (this.type && this.type.presets)
|
|
455
|
+
if ((0, common_types_1.instanceOfTypeObj)(this.type) && this.type.presets)
|
|
418
456
|
return this.type.presets;
|
|
419
457
|
if (this.type === "Key" && this.reftable_name === "users")
|
|
420
458
|
return { LoggedIn: ({ user }) => user && user.id };
|
|
@@ -432,18 +470,18 @@ class Field {
|
|
|
432
470
|
if (table.ownership_field_id === this.id) {
|
|
433
471
|
throw new InvalidAdminAction(`Cannot delete field ${this.name} as it sets ownership for table ${table.name}`);
|
|
434
472
|
}
|
|
435
|
-
const schema =
|
|
436
|
-
const client =
|
|
473
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
474
|
+
const client = db_1.default.isSQLite ? db_1.default : await db_1.default.getClient();
|
|
437
475
|
await client.query("BEGIN");
|
|
438
|
-
await
|
|
439
|
-
if (!
|
|
440
|
-
await client.query(`alter table ${schema}"${sqlsanitize(table.name)}" drop column "${sqlsanitize(this.name)}"`);
|
|
476
|
+
await db_1.default.deleteWhere("_sc_fields", { id: this.id }, { client });
|
|
477
|
+
if (!db_1.default.isSQLite && (!this.calculated || this.stored)) {
|
|
478
|
+
await client.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}" drop column "${(0, internal_1.sqlsanitize)(this.name)}"`);
|
|
441
479
|
if (table.versioned) {
|
|
442
|
-
await client.query(`alter table ${schema}"${sqlsanitize(table.name)}__history" drop column "${sqlsanitize(this.name)}"`);
|
|
480
|
+
await client.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}__history" drop column "${(0, internal_1.sqlsanitize)(this.name)}"`);
|
|
443
481
|
}
|
|
444
482
|
}
|
|
445
483
|
await client.query("COMMIT");
|
|
446
|
-
if (!
|
|
484
|
+
if (!db_1.default.isSQLite)
|
|
447
485
|
await client.release(true);
|
|
448
486
|
await require("../db/state").getState().refresh_tables();
|
|
449
487
|
}
|
|
@@ -452,10 +490,13 @@ class Field {
|
|
|
452
490
|
* @returns {Promise<void>}
|
|
453
491
|
*/
|
|
454
492
|
async enable_fkey_constraint(table) {
|
|
455
|
-
if (this.is_fkey && !
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
493
|
+
if (this.is_fkey && !db_1.default.isSQLite) {
|
|
494
|
+
if (!this.reftable_name) {
|
|
495
|
+
throw new Error("To enable a foreign key constraint, the 'reftable_name' must be set.");
|
|
496
|
+
}
|
|
497
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
498
|
+
const q = `alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}" ADD CONSTRAINT "fkey_${(0, internal_1.sqlsanitize)(table.name)}_${(0, internal_1.sqlsanitize)(this.name)}" FOREIGN KEY ("${(0, internal_1.sqlsanitize)(this.name)}") references ${schema}"${(0, internal_1.sqlsanitize)(this.reftable_name)}" (id)`;
|
|
499
|
+
await db_1.default.query(q);
|
|
459
500
|
}
|
|
460
501
|
}
|
|
461
502
|
/**
|
|
@@ -465,9 +506,9 @@ class Field {
|
|
|
465
506
|
*/
|
|
466
507
|
static async create(fld, bare = false) {
|
|
467
508
|
const f = new Field(fld);
|
|
468
|
-
const schema =
|
|
509
|
+
const schema = db_1.default.getTenantSchemaPrefix();
|
|
469
510
|
const Table = require("./table");
|
|
470
|
-
const is_sqlite =
|
|
511
|
+
const is_sqlite = db_1.default.isSQLite;
|
|
471
512
|
//const tables = await Table.find();
|
|
472
513
|
//console.log({ tables, fld });
|
|
473
514
|
if (f.is_fkey) {
|
|
@@ -484,34 +525,34 @@ class Field {
|
|
|
484
525
|
const table = await Table.findOne({ id: f.table_id });
|
|
485
526
|
if (!f.calculated || f.stored) {
|
|
486
527
|
if (typeof f.attributes.default === "undefined") {
|
|
487
|
-
const q = `alter table ${schema}"${sqlsanitize(table.name)}" add column "${sqlsanitize(f.name)}" ${sql_type} ${f.required ? `not null ${is_sqlite ? 'default ""' : ""}` : ""}`;
|
|
488
|
-
await
|
|
528
|
+
const q = `alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}" add column "${(0, internal_1.sqlsanitize)(f.name)}" ${sql_type} ${f.required ? `not null ${is_sqlite ? 'default ""' : ""}` : ""}`;
|
|
529
|
+
await db_1.default.query(q);
|
|
489
530
|
}
|
|
490
531
|
else if (is_sqlite) {
|
|
491
532
|
//warning: not safe but sqlite so we don't care
|
|
492
|
-
const q = `alter table ${schema}"${sqlsanitize(table.name)}" add column "${sqlsanitize(f.name)}" ${sql_type} ${f.required
|
|
533
|
+
const q = `alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}" add column "${(0, internal_1.sqlsanitize)(f.name)}" ${sql_type} ${f.required
|
|
493
534
|
? `not null default ${JSON.stringify(f.attributes.default)}`
|
|
494
535
|
: ""}`;
|
|
495
|
-
await
|
|
536
|
+
await db_1.default.query(q);
|
|
496
537
|
}
|
|
497
538
|
else {
|
|
498
|
-
const q = `DROP FUNCTION IF EXISTS add_field_${sqlsanitize(f.name)};
|
|
499
|
-
CREATE FUNCTION add_field_${sqlsanitize(f.name)}(thedef ${f.sql_bare_type}) RETURNS void AS $$
|
|
539
|
+
const q = `DROP FUNCTION IF EXISTS add_field_${(0, internal_1.sqlsanitize)(f.name)};
|
|
540
|
+
CREATE FUNCTION add_field_${(0, internal_1.sqlsanitize)(f.name)}(thedef ${f.sql_bare_type}) RETURNS void AS $$
|
|
500
541
|
BEGIN
|
|
501
|
-
EXECUTE format('alter table ${schema}"${sqlsanitize(table.name)}" add column "${sqlsanitize(f.name)}" ${sql_type} ${f.required ? "not null" : ""} default %L', thedef);
|
|
542
|
+
EXECUTE format('alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}" add column "${(0, internal_1.sqlsanitize)(f.name)}" ${sql_type} ${f.required ? "not null" : ""} default %L', thedef);
|
|
502
543
|
END;
|
|
503
544
|
$$ LANGUAGE plpgsql;`;
|
|
504
|
-
await
|
|
505
|
-
await
|
|
545
|
+
await db_1.default.query(q);
|
|
546
|
+
await db_1.default.query(`SELECT add_field_${(0, internal_1.sqlsanitize)(f.name)}($1)`, [
|
|
506
547
|
f.attributes.default,
|
|
507
548
|
]);
|
|
508
549
|
}
|
|
509
550
|
}
|
|
510
|
-
f.id = await
|
|
551
|
+
f.id = await db_1.default.insert("_sc_fields", {
|
|
511
552
|
table_id: f.table_id,
|
|
512
553
|
name: f.name,
|
|
513
554
|
label: f.label,
|
|
514
|
-
type: f.is_fkey ? f.type : f.type
|
|
555
|
+
type: f.is_fkey ? f.type : f.type?.name,
|
|
515
556
|
reftable_name: f.is_fkey ? f.reftable_name : undefined,
|
|
516
557
|
reftype: f.is_fkey ? f.reftype : undefined,
|
|
517
558
|
refname: f.is_fkey ? f.refname : undefined,
|
|
@@ -524,7 +565,7 @@ class Field {
|
|
|
524
565
|
});
|
|
525
566
|
await require("../db/state").getState().refresh_tables();
|
|
526
567
|
if (table.versioned && !f.calculated) {
|
|
527
|
-
await
|
|
568
|
+
await db_1.default.query(`alter table ${schema}"${(0, internal_1.sqlsanitize)(table.name)}__history" add column "${(0, internal_1.sqlsanitize)(f.name)}" ${f.sql_bare_type}`);
|
|
528
569
|
}
|
|
529
570
|
if (f.is_unique && !f.calculated)
|
|
530
571
|
await f.add_unique_constraint();
|
|
@@ -556,64 +597,5 @@ class Field {
|
|
|
556
597
|
return typeattribs;
|
|
557
598
|
}
|
|
558
599
|
}
|
|
559
|
-
Field.contract = {
|
|
560
|
-
variables: {
|
|
561
|
-
name: is.str,
|
|
562
|
-
label: is.str,
|
|
563
|
-
class: is.str,
|
|
564
|
-
postText: is.maybe(is.str),
|
|
565
|
-
sublabel: is.maybe(is.str),
|
|
566
|
-
fieldview: is.maybe(is.str),
|
|
567
|
-
parent_field: is.maybe(is.str),
|
|
568
|
-
reftable_name: is.maybe(is.str),
|
|
569
|
-
validator: is.fun(is.any, is.bool),
|
|
570
|
-
type: is.maybe(is.or(is.eq("Key"), is.eq("File"), is.obj({ name: is.str }))),
|
|
571
|
-
input_type: is.maybe(is.one_of([
|
|
572
|
-
"hidden",
|
|
573
|
-
"file",
|
|
574
|
-
"select",
|
|
575
|
-
"fromtype",
|
|
576
|
-
"search",
|
|
577
|
-
"text",
|
|
578
|
-
"password",
|
|
579
|
-
"section_header",
|
|
580
|
-
"textarea",
|
|
581
|
-
"custom_html",
|
|
582
|
-
"code",
|
|
583
|
-
])),
|
|
584
|
-
is_fkey: is.bool,
|
|
585
|
-
is_unique: is.bool,
|
|
586
|
-
required: is.bool,
|
|
587
|
-
disabled: is.bool,
|
|
588
|
-
id: is.maybe(is.posint),
|
|
589
|
-
attributes: is.obj(),
|
|
590
|
-
table_id: is.maybe(is.posint),
|
|
591
|
-
},
|
|
592
|
-
instance_check: is.and(is.or(is.obj({ type: is.defined }), is.obj({ input_type: is.defined })), is.or(is.obj({ is_fkey: is.eq(false), reftable_name: is.eq(undefined) }), is.obj({ is_fkey: is.eq(true), reftable_name: is.str }))),
|
|
593
|
-
methods: {
|
|
594
|
-
validate: is.fun(is.obj(), is.or(is.obj({ errors: is.str }), is.obj({ success: is.any }))),
|
|
595
|
-
toJson: is.getter(is.obj({ type: is.str })),
|
|
596
|
-
sql_type: is.getter(is.str),
|
|
597
|
-
sql_bare_type: is.getter(is.str),
|
|
598
|
-
form_name: is.getter(is.str),
|
|
599
|
-
listKey: is.getter(is.any),
|
|
600
|
-
presets: is.getter(is.maybe(is.objVals(is.fun(is.obj(), is.any)))),
|
|
601
|
-
delete: is.fun([], is.promise(is.undefined)),
|
|
602
|
-
generate: is.fun([], is.promise(is.any)),
|
|
603
|
-
add_unique_constraint: is.fun([], is.promise(is.undefined)),
|
|
604
|
-
remove_unique_constraint: is.fun([], is.promise(is.undefined)),
|
|
605
|
-
toggle_not_null: is.fun(is.bool, is.promise(is.undefined)),
|
|
606
|
-
fill_table: is.fun([], is.promise(is.undefined)),
|
|
607
|
-
update: is.fun(is.obj(), is.promise(is.undefined)),
|
|
608
|
-
fill_fkey_options: is.fun(is.maybe(is.bool), is.promise()),
|
|
609
|
-
distinct_values: is.fun([], is.promise(is.array(is.obj({ label: is.any, value: is.any })))),
|
|
610
|
-
},
|
|
611
|
-
static_methods: {
|
|
612
|
-
find: is.fun([is.maybe(is.obj()), is.maybe(is.obj())], is.promise(is.array(is.class("Field")))),
|
|
613
|
-
findOne: is.fun(is.obj(), is.promise(is.class("Field"))),
|
|
614
|
-
create: is.fun(is.obj(), is.promise(is.class("Field"))),
|
|
615
|
-
labelToName: is.fun(is.str, is.str),
|
|
616
|
-
},
|
|
617
|
-
};
|
|
618
600
|
module.exports = Field;
|
|
619
601
|
//# sourceMappingURL=field.js.map
|