@opengis/fastify-table 2.5.44 → 2.5.46
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/functions.d.ts +1 -0
- package/dist/functions.d.ts.map +1 -1
- package/dist/functions.js +122 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/server/migrations/dictionaries.sql +79 -0
- package/dist/server/plugins/crud/funcs/dataDelete.d.ts +2 -1
- package/dist/server/plugins/crud/funcs/dataDelete.d.ts.map +1 -1
- package/dist/server/plugins/crud/funcs/dataDelete.js +2 -2
- package/dist/server/routes/crud/controllers/insert.d.ts +1 -2
- package/dist/server/routes/crud/controllers/insert.d.ts.map +1 -1
- package/dist/server/routes/crud/controllers/insert.js +1 -1
- package/dist/server/routes/crud/controllers/update.js +1 -1
- package/dist/server/routes/dictionaries/dictionaries.route.d.ts +2 -0
- package/dist/server/routes/dictionaries/dictionaries.route.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/dictionaries.route.js +134 -0
- package/dist/server/routes/dictionaries/dictionaries.schema.d.ts +190 -0
- package/dist/server/routes/dictionaries/dictionaries.schema.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/dictionaries.schema.js +86 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.d.ts +10 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.item.d.ts +13 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.item.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.item.js +57 -0
- package/dist/server/routes/dictionaries/functions/create.dictionary.js +76 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.d.ts +9 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.item.d.ts +11 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.item.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.item.js +32 -0
- package/dist/server/routes/dictionaries/functions/delete.dictionary.js +28 -0
- package/dist/server/routes/dictionaries/functions/read.dictionaries.d.ts +5 -0
- package/dist/server/routes/dictionaries/functions/read.dictionaries.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/read.dictionaries.js +27 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.d.ts +10 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.item.d.ts +13 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.item.d.ts.map +1 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.item.js +48 -0
- package/dist/server/routes/dictionaries/functions/update.dictionary.js +51 -0
- package/package.json +1 -1
package/dist/functions.d.ts
CHANGED
package/dist/functions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../functions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../functions.ts"],"names":[],"mappings":"AAoCA,wBAAsB,SAAS,kBAkH9B;AAED,wBAAsB,SAAS,kBAiJ9B;AAED,wBAAsB,SAAS,kBAkM9B;AAED,wBAAsB,WAAW,CAAC,EAChC,IAAI,EACJ,IAAI,EACJ,IAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B;;eAqBA;AAED,wBAAsB,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,gBASxE;AAED,wBAAsB,UAAU,CAAC,EAC/B,KAAK,EACL,GAAQ,EACR,OAAO,EAAE,IAAS,EAClB,IAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,iBA+FA;AAED,wBAAsB,aAAa,CAAC,EAClC,IAAI,EACJ,IAAI,EACJ,OAAO,EAAE,IAAS,EAClB,IAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B,6BAiEA;AAED,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,IAAS,EACT,OAAO,EAAE,GAAQ,EACjB,IAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,gBA6CA;AAED,wBAAsB,WAAW,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,OAAO,EAAE,GAAQ,EACjB,IAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,gBA2CA;AAED,wBAAsB,OAAO,kBAmC5B"}
|
package/dist/functions.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, mkdirSync, writeFileSync, } from "node:fs";
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
3
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import config from "./config.js";
|
|
6
6
|
import getTemplatePath from "./server/plugins/table/funcs/getTemplatePath.js";
|
|
@@ -12,11 +12,14 @@ import getMenu from "./server/routes/menu/controllers/getMenu.js";
|
|
|
12
12
|
import getSelectVal from "./server/plugins/table/funcs/metaFormat/getSelectVal.js";
|
|
13
13
|
import locales from "./server/routes/table/controllers/utils/locales.js";
|
|
14
14
|
import pgClients from "./server/plugins/pg/pgClients.js";
|
|
15
|
+
import { readdir } from "node:fs/promises";
|
|
16
|
+
import { readFile } from "node:fs/promises";
|
|
15
17
|
const { client } = pgClients;
|
|
16
18
|
const rclient = getRedis();
|
|
17
19
|
// core templates && cls
|
|
18
20
|
const filename = fileURLToPath(import.meta.url);
|
|
19
21
|
const cwd = path.dirname(filename);
|
|
22
|
+
const shortId = () => randomUUID().split("-").pop() || "";
|
|
20
23
|
export async function onListen1() {
|
|
21
24
|
const json = await getMenu({ user: { uid: "1" }, pg: client }, null).catch(); // prevent "too many clients already" from crashing the application
|
|
22
25
|
// insert interface list to db (user access management)
|
|
@@ -178,6 +181,124 @@ export async function onListen2() {
|
|
|
178
181
|
console.trace(err);
|
|
179
182
|
}
|
|
180
183
|
}
|
|
184
|
+
export async function onListen3() {
|
|
185
|
+
const clsQuery = [];
|
|
186
|
+
if (client && !client?.pk && client?.init) {
|
|
187
|
+
await client.init();
|
|
188
|
+
}
|
|
189
|
+
if (!client?.pk?.["admin.dictionaries"])
|
|
190
|
+
return;
|
|
191
|
+
try {
|
|
192
|
+
const dictionaries = existsSync("dictionaries")
|
|
193
|
+
? (await readdir("dictionaries", { withFileTypes: true }))
|
|
194
|
+
.filter((el) => el.isFile() && path.extname(el.name) === ".json")
|
|
195
|
+
.map((el) => el.name)
|
|
196
|
+
: [];
|
|
197
|
+
if (!dictionaries?.length)
|
|
198
|
+
return;
|
|
199
|
+
const uniqueDictionaries = dictionaries.filter((el, idx, arr) => arr.indexOf(el) === idx);
|
|
200
|
+
const hashes = await rclient
|
|
201
|
+
.hgetall("dictionaries-insert-hashes")
|
|
202
|
+
.then((obj) => Object.keys(obj));
|
|
203
|
+
const dbdata = await client
|
|
204
|
+
.query(`select json_object_agg(code, hash) from admin.dictionaries where system is true`)
|
|
205
|
+
.then((el) => el.rows?.[0]?.json_object_agg || {});
|
|
206
|
+
const codes = Object.keys(dbdata);
|
|
207
|
+
console.log("admin/hook dictionaries promise start");
|
|
208
|
+
const qHashes = await Promise.all(uniqueDictionaries.map(async (dictFileName) => {
|
|
209
|
+
const { code, name, module: moduleName, editable, values: arr, } = JSON.parse(await readFile(`dictionaries/${dictFileName}`, "utf-8"));
|
|
210
|
+
const hash = createHash("md5")
|
|
211
|
+
.update(JSON.stringify(arr || ""))
|
|
212
|
+
.digest("hex");
|
|
213
|
+
const dbhash = dbdata[code];
|
|
214
|
+
// check for changes by redis hash / dropped from db / changed at git project
|
|
215
|
+
const update = code &&
|
|
216
|
+
(!hashes.includes(hash) || !codes.includes(code) || hash !== dbhash);
|
|
217
|
+
if (update) {
|
|
218
|
+
const id = shortId();
|
|
219
|
+
const mainArgs = [
|
|
220
|
+
id,
|
|
221
|
+
code,
|
|
222
|
+
name,
|
|
223
|
+
moduleName,
|
|
224
|
+
"git",
|
|
225
|
+
editable || false,
|
|
226
|
+
true,
|
|
227
|
+
hash,
|
|
228
|
+
];
|
|
229
|
+
const mainQuery = `insert into admin.dictionaries(id,code,name,module,source,editable,system,hash) values($1::text,$2,$3,$4,$5,$6,$7,$8)`;
|
|
230
|
+
const itemsArgs = [];
|
|
231
|
+
const itemArgsLength = 8;
|
|
232
|
+
const itemsQuery = `insert into admin.dictionary_items(dictionary_id,code,name,icon,color,parent_id,system,sort_order) values ${arr.map((_, idx) => `(${Array.from({ length: itemArgsLength }, (_, i) => `$${itemsArgs.length + i + 1 + idx * itemArgsLength}${i <= 5 ? "::text" : ""}`).join(",")})`)}`;
|
|
233
|
+
arr.forEach((el) => {
|
|
234
|
+
itemsArgs.push(id);
|
|
235
|
+
itemsArgs.push(el.code);
|
|
236
|
+
itemsArgs.push(el.name);
|
|
237
|
+
itemsArgs.push(el.icon);
|
|
238
|
+
itemsArgs.push(el.color);
|
|
239
|
+
itemsArgs.push(el.parent_id);
|
|
240
|
+
itemsArgs.push(true);
|
|
241
|
+
itemsArgs.push(el.sort || 0);
|
|
242
|
+
});
|
|
243
|
+
if (config.trace) {
|
|
244
|
+
console.log(code, "insert fresh dictionary");
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
code,
|
|
248
|
+
update,
|
|
249
|
+
hash,
|
|
250
|
+
mainQuery,
|
|
251
|
+
mainArgs,
|
|
252
|
+
itemsQuery,
|
|
253
|
+
itemsArgs,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
if (config.trace) {
|
|
258
|
+
console.log(code, codes.includes(code)
|
|
259
|
+
? "skip equal hash dictionary"
|
|
260
|
+
: "insert missing dictionary");
|
|
261
|
+
}
|
|
262
|
+
return { code, update, hash, equalHash: hashes.includes(hash) };
|
|
263
|
+
}
|
|
264
|
+
}));
|
|
265
|
+
// debug
|
|
266
|
+
const logDir = path.join(cwd, "log/migration");
|
|
267
|
+
mkdirSync(logDir, { recursive: true });
|
|
268
|
+
writeFileSync(path.join(logDir, `${path.basename(cwd)}-${client.options?.database}-dictionaries.sql`), clsQuery.filter(Boolean).join(";"));
|
|
269
|
+
writeFileSync(path.join(logDir, `${path.basename(cwd)}-${client.options?.database}-dictionaries.json`), JSON.stringify(dictionaries));
|
|
270
|
+
const updateIds = qHashes
|
|
271
|
+
.filter((el) => el.mainQuery)
|
|
272
|
+
.map((el) => el.code);
|
|
273
|
+
const rowCountItems = await client
|
|
274
|
+
.query("delete from admin.dictionary_items where dictionary_id in (select id from admin.dictionaries where system is true and code=any($1::text[]))", [updateIds])
|
|
275
|
+
.then((r) => r.rowCount || 0);
|
|
276
|
+
const rowCount = await client
|
|
277
|
+
.query("delete from admin.dictionaries where system is true and code=any($1::text[])", [updateIds])
|
|
278
|
+
.then((r) => r.rowCount || 0);
|
|
279
|
+
console.log("fastify-table/hook old dictionaries deleted", rowCount, rowCountItems);
|
|
280
|
+
if (qHashes.find((el) => el && el.mainQuery)) {
|
|
281
|
+
await Promise.all(qHashes
|
|
282
|
+
.filter((el) => el && el.mainQuery)
|
|
283
|
+
.map(async ({ hash, mainQuery, mainArgs, itemsQuery, itemsArgs, }) => {
|
|
284
|
+
await client.query(mainQuery, mainArgs);
|
|
285
|
+
await client.query(itemsQuery, itemsArgs);
|
|
286
|
+
rclient.hset("dictionaries-insert-hashes", hash, 1);
|
|
287
|
+
}));
|
|
288
|
+
logger.file("migration/hash", {
|
|
289
|
+
list: qHashes.filter(Boolean),
|
|
290
|
+
dictionaries: true,
|
|
291
|
+
});
|
|
292
|
+
console.log("fastify-table/hook dictionaries sql finish");
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
console.log("fastify-table/hook dictionaries sql insert skipped");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
console.error("fastify-table/hook dictionaries sql error", err.toString());
|
|
300
|
+
}
|
|
301
|
+
}
|
|
181
302
|
export async function preTemplate({ name, type, user = {}, }) {
|
|
182
303
|
if (!name || !type)
|
|
183
304
|
return;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAgGA,iBAAe,MAAM,CAAC,OAAO,EAAE,GAAG,iBAsPjC;;AACD,wBAEG"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const cwd = path.dirname(filename);
|
|
|
9
9
|
config.templates?.forEach((el) => addTemplateDir(el));
|
|
10
10
|
addTemplateDir(path.join(cwd, "module/core"));
|
|
11
11
|
import config from "./config.js";
|
|
12
|
-
import { preForm, afterInsert, afterTable, afterTemplate, afterUpdate, preTemplate, onReady, onListen1, onListen2, } from "./functions.js";
|
|
12
|
+
import { preForm, afterInsert, afterTable, afterTemplate, afterUpdate, preTemplate, onReady, onListen1, onListen2, onListen3, } from "./functions.js";
|
|
13
13
|
import addHook from "./server/plugins/hook/addHook.js";
|
|
14
14
|
const { maxFileSize = 512 } = config;
|
|
15
15
|
const { name: execName } = path.parse(process.argv0);
|
|
@@ -56,6 +56,7 @@ import uploadChunkRoutes from "./server/routes/upload/index.js";
|
|
|
56
56
|
import grpcRoutes from "./server/routes/grpc/index.js";
|
|
57
57
|
import notificationsRoutes from "./server/routes/notifications/index.js";
|
|
58
58
|
import userClsRoutes from "./server/routes/usercls/index.js";
|
|
59
|
+
import dictionariesRoutes from "./server/routes/dictionaries/dictionaries.route.js";
|
|
59
60
|
import apiListService from "./server/routes/util/controllers/api.list.js";
|
|
60
61
|
addHook("preForm", preForm);
|
|
61
62
|
addHook("afterTable", afterTable);
|
|
@@ -138,6 +139,7 @@ async function plugin(fastify) {
|
|
|
138
139
|
});
|
|
139
140
|
fastify.addHook("onListen", onListen1);
|
|
140
141
|
fastify.addHook("onListen", onListen2);
|
|
142
|
+
fastify.addHook("onListen", onListen3);
|
|
141
143
|
fastify.addHook("onReady", onReady);
|
|
142
144
|
// core migrations (second argument for core only)
|
|
143
145
|
execMigrations(path.join(cwd, "server/migrations"), pgClients.client, true).catch((err) => console.warn(err.toString()));
|
|
@@ -226,6 +228,7 @@ async function plugin(fastify) {
|
|
|
226
228
|
// from admin
|
|
227
229
|
fastify.register(notificationsRoutes, opt);
|
|
228
230
|
fastify.register(userClsRoutes, opt);
|
|
231
|
+
fastify.register(dictionariesRoutes, opt);
|
|
229
232
|
config.proxy?.forEach?.((el) => {
|
|
230
233
|
if (execName === "bun") {
|
|
231
234
|
fastify.all(`${el.source}/*`, async (req, reply) => {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
create schema if not exists admin;
|
|
2
|
+
|
|
3
|
+
DO $$
|
|
4
|
+
BEGIN
|
|
5
|
+
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'dictionary_source_enum') THEN
|
|
6
|
+
CREATE TYPE admin.dictionary_source_enum AS ENUM (
|
|
7
|
+
'git',
|
|
8
|
+
'custom'
|
|
9
|
+
);
|
|
10
|
+
END IF;
|
|
11
|
+
END $$;
|
|
12
|
+
|
|
13
|
+
CREATE TABLE if not exists admin.dictionaries (
|
|
14
|
+
id text PRIMARY KEY DEFAULT public.next_id(),
|
|
15
|
+
|
|
16
|
+
code VARCHAR(100) NOT NULL UNIQUE,
|
|
17
|
+
name VARCHAR(255) NOT NULL,
|
|
18
|
+
module VARCHAR(50),
|
|
19
|
+
description TEXT,
|
|
20
|
+
|
|
21
|
+
source admin.dictionary_source_enum NOT NULL DEFAULT 'custom',
|
|
22
|
+
editable BOOLEAN NOT NULL DEFAULT true,
|
|
23
|
+
system BOOLEAN NOT NULL DEFAULT false,
|
|
24
|
+
|
|
25
|
+
hash text,
|
|
26
|
+
|
|
27
|
+
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
|
28
|
+
updated_at TIMESTAMP NOT NULL DEFAULT now()
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE if not exists admin.dictionary_items (
|
|
32
|
+
id text PRIMARY KEY DEFAULT public.next_id(),
|
|
33
|
+
|
|
34
|
+
dictionary_id text NOT NULL REFERENCES admin.dictionaries(id) ON DELETE CASCADE,
|
|
35
|
+
|
|
36
|
+
code VARCHAR(100) NOT NULL,
|
|
37
|
+
name VARCHAR(255) NOT NULL,
|
|
38
|
+
description TEXT,
|
|
39
|
+
|
|
40
|
+
color VARCHAR(20),
|
|
41
|
+
icon VARCHAR(50),
|
|
42
|
+
|
|
43
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
44
|
+
|
|
45
|
+
parent_id text,
|
|
46
|
+
|
|
47
|
+
active BOOLEAN NOT NULL DEFAULT true,
|
|
48
|
+
system BOOLEAN NOT NULL DEFAULT false,
|
|
49
|
+
|
|
50
|
+
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
51
|
+
|
|
52
|
+
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
|
53
|
+
updated_at TIMESTAMP NOT NULL DEFAULT now(),
|
|
54
|
+
|
|
55
|
+
CONSTRAINT admin_dictionary_items_dictionary_code_unique
|
|
56
|
+
UNIQUE (code, dictionary_id)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
ALTER TABLE admin.dictionary_items
|
|
60
|
+
DROP CONSTRAINT if exists admin_dictionary_items_dictionary_code_unique cascade;
|
|
61
|
+
|
|
62
|
+
ALTER TABLE admin.dictionary_items
|
|
63
|
+
ADD CONSTRAINT admin_dictionary_items_dictionary_code_unique UNIQUE (code, dictionary_id);
|
|
64
|
+
|
|
65
|
+
ALTER TABLE admin.dictionary_items
|
|
66
|
+
DROP CONSTRAINT if exists admin_dictionary_items_parent_same_dictionary_fk;
|
|
67
|
+
|
|
68
|
+
ALTER TABLE admin.dictionary_items
|
|
69
|
+
ADD CONSTRAINT admin_dictionary_items_parent_same_dictionary_fk FOREIGN KEY (parent_id, dictionary_id)
|
|
70
|
+
REFERENCES admin.dictionary_items (code, dictionary_id)
|
|
71
|
+
ON DELETE SET NULL;
|
|
72
|
+
|
|
73
|
+
CREATE INDEX if not exists admin_dictionary_items_dictionary_id_idx ON admin.dictionary_items (dictionary_id);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX if not exists admin_dictionary_items_parent_id_idx ON admin.dictionary_items (parent_id);
|
|
76
|
+
|
|
77
|
+
CREATE INDEX if not exists admin_dictionary_items_sort_order_idx ON admin.dictionary_items (dictionary_id, sort_order);
|
|
78
|
+
|
|
79
|
+
CREATE INDEX if not exists admin_dictionary_items_active_idx ON admin.dictionary_items (dictionary_id, active);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtendedPG } from "../../../types/core.js";
|
|
2
|
-
export default function dataDelete({ table: table1, tokenData, referer, id, pg: pg1, uid, query, }: {
|
|
2
|
+
export default function dataDelete({ table: table1, tokenData, referer, id, pg: pg1, uid, query, args, }: {
|
|
3
3
|
table: string;
|
|
4
4
|
tokenData?: Record<string, any>;
|
|
5
5
|
referer?: string;
|
|
@@ -7,5 +7,6 @@ export default function dataDelete({ table: table1, tokenData, referer, id, pg:
|
|
|
7
7
|
pg?: ExtendedPG;
|
|
8
8
|
uid: string | number;
|
|
9
9
|
query?: string;
|
|
10
|
+
args?: any[];
|
|
10
11
|
}): Promise<any>;
|
|
11
12
|
//# sourceMappingURL=dataDelete.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataDelete.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAezD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,EAAE,EAAE,GAAG,EACP,GAAG,EACH,KAAK,
|
|
1
|
+
{"version":3,"file":"dataDelete.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAezD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,EAAE,EAAE,GAAG,EACP,GAAG,EACH,KAAK,EACL,IAAI,GACL,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;CACd,gBA+FA"}
|
|
@@ -7,7 +7,7 @@ import extraData from "../../extra/extraData.js";
|
|
|
7
7
|
import logChanges from "./utils/logChanges.js";
|
|
8
8
|
import logger from "../../logger/getLogger.js";
|
|
9
9
|
const rclient = getRedis();
|
|
10
|
-
export default async function dataDelete({ table: table1, tokenData, referer, id, pg: pg1, uid, query, }) {
|
|
10
|
+
export default async function dataDelete({ table: table1, tokenData, referer, id, pg: pg1, uid, query, args, }) {
|
|
11
11
|
const pg = pg1 || getPG({ name: "client" });
|
|
12
12
|
if (!pg)
|
|
13
13
|
return null;
|
|
@@ -47,7 +47,7 @@ export default async function dataDelete({ table: table1, tokenData, referer, id
|
|
|
47
47
|
row,
|
|
48
48
|
}, client);
|
|
49
49
|
const res = await client
|
|
50
|
-
.query(delQuery, [id])
|
|
50
|
+
.query(delQuery, [id].concat(args || []))
|
|
51
51
|
.then((el) => (el.rows?.[0] ? { rowCount: 1, ...el.rows[0] } : {}));
|
|
52
52
|
await logChanges({
|
|
53
53
|
pg: client,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../../../server/routes/crud/controllers/insert.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"insert.d.ts","sourceRoot":"","sources":["../../../../../server/routes/crud/controllers/insert.ts"],"names":[],"mappings":"AAqBA,wBAA8B,MAAM,CAAC,GAAG,EAAE,GAAG,gBAgM5C"}
|
|
@@ -10,7 +10,7 @@ import getToken from "../../../plugins/crud/funcs/getToken.js";
|
|
|
10
10
|
import getTemplate from "../../../plugins/table/funcs/getTemplate.js";
|
|
11
11
|
import { resources } from "../../../plugins/access/funcs/getResources.js";
|
|
12
12
|
import { BadRequestError, ConflictError, ForbiddenError, NotFoundError, } from "../../../../errors.js";
|
|
13
|
-
export default async function insert(req
|
|
13
|
+
export default async function insert(req) {
|
|
14
14
|
const { pg = pgClients.client, user = {}, params = {}, body = {}, headers = {}, method, } = req || {};
|
|
15
15
|
if (!user) {
|
|
16
16
|
throw ForbiddenError("access restricted");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaries.route.d.ts","sourceRoot":"","sources":["../../../../server/routes/dictionaries/dictionaries.route.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,GAAG,EAAE,GAAG,QAmJrC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import readDictionaries from "./functions/read.dictionaries.js";
|
|
2
|
+
import createDictionary from "./functions/create.dictionary.js";
|
|
3
|
+
import updateDictionary from "./functions/update.dictionary.js";
|
|
4
|
+
import deleteDictionary from "./functions/delete.dictionary.js";
|
|
5
|
+
import createDictionaryItem from "./functions/create.dictionary.item.js";
|
|
6
|
+
import updateDictionaryItem from "./functions/update.dictionary.item.js";
|
|
7
|
+
import deleteDictionaryItem from "./functions/delete.dictionary.item.js";
|
|
8
|
+
import { dictionaryParamsSchema, createDictionaryBodySchema, createDictionaryItemBodySchema, updateDictionaryBodySchema, updateDictionaryItemBodySchema, } from "./dictionaries.schema.js";
|
|
9
|
+
const tags = ["core", "dictionaries"];
|
|
10
|
+
const packageName = "fastify-table";
|
|
11
|
+
export default function route(app) {
|
|
12
|
+
app.route({
|
|
13
|
+
method: "GET",
|
|
14
|
+
url: "/dictionaries/:code?",
|
|
15
|
+
config: { tags, package: packageName, policy: "L0" },
|
|
16
|
+
schema: { params: dictionaryParamsSchema },
|
|
17
|
+
handler: async ({ params, pg }) => {
|
|
18
|
+
const result = await readDictionaries({
|
|
19
|
+
code: params.code,
|
|
20
|
+
}, pg);
|
|
21
|
+
return result;
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
app.route({
|
|
25
|
+
method: "GET",
|
|
26
|
+
url: "/dictionaries/:code/values",
|
|
27
|
+
config: { tags, package: packageName, policy: "L0" },
|
|
28
|
+
schema: { params: dictionaryParamsSchema },
|
|
29
|
+
handler: async ({ params, pg }) => {
|
|
30
|
+
const result = await readDictionaries({
|
|
31
|
+
code: params.code,
|
|
32
|
+
values: true,
|
|
33
|
+
}, pg);
|
|
34
|
+
return result;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
app.route({
|
|
38
|
+
method: "POST",
|
|
39
|
+
url: "/dictionaries/:id?",
|
|
40
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
41
|
+
schema: {
|
|
42
|
+
params: dictionaryParamsSchema,
|
|
43
|
+
body: createDictionaryBodySchema,
|
|
44
|
+
},
|
|
45
|
+
handler: async ({ params, body, user, pg }) => {
|
|
46
|
+
const result = await createDictionary({
|
|
47
|
+
id: params.id,
|
|
48
|
+
body,
|
|
49
|
+
uid: user?.uid,
|
|
50
|
+
}, pg);
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
app.route({
|
|
55
|
+
method: "PUT",
|
|
56
|
+
url: "/dictionaries/:id",
|
|
57
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
58
|
+
schema: {
|
|
59
|
+
params: dictionaryParamsSchema,
|
|
60
|
+
body: updateDictionaryBodySchema,
|
|
61
|
+
},
|
|
62
|
+
handler: async ({ params, user, body, pg }) => {
|
|
63
|
+
const result = await updateDictionary({
|
|
64
|
+
id: params.id,
|
|
65
|
+
body,
|
|
66
|
+
uid: user?.uid,
|
|
67
|
+
}, pg);
|
|
68
|
+
return result;
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
app.route({
|
|
72
|
+
method: "DELETE",
|
|
73
|
+
url: "/dictionaries/:id",
|
|
74
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
75
|
+
schema: { params: dictionaryParamsSchema },
|
|
76
|
+
handler: async ({ params, user, pg }) => {
|
|
77
|
+
const result = await deleteDictionary({
|
|
78
|
+
id: params.id,
|
|
79
|
+
uid: user?.uid,
|
|
80
|
+
}, pg);
|
|
81
|
+
return result;
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
app.route({
|
|
85
|
+
method: "POST",
|
|
86
|
+
url: "/dictionaries/:code/values/:id?",
|
|
87
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
88
|
+
schema: {
|
|
89
|
+
params: dictionaryParamsSchema,
|
|
90
|
+
body: createDictionaryItemBodySchema,
|
|
91
|
+
},
|
|
92
|
+
handler: async ({ params, body, user, pg }) => {
|
|
93
|
+
const result = await createDictionaryItem({
|
|
94
|
+
id: params.id,
|
|
95
|
+
code: params.code,
|
|
96
|
+
body,
|
|
97
|
+
uid: user?.uid,
|
|
98
|
+
}, pg);
|
|
99
|
+
return result;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
app.route({
|
|
103
|
+
method: "PUT",
|
|
104
|
+
url: "/dictionaries/:code/values/:id",
|
|
105
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
106
|
+
schema: {
|
|
107
|
+
params: dictionaryParamsSchema,
|
|
108
|
+
body: updateDictionaryItemBodySchema,
|
|
109
|
+
},
|
|
110
|
+
handler: async ({ params, body, user, pg }) => {
|
|
111
|
+
const result = await updateDictionaryItem({
|
|
112
|
+
id: params.id,
|
|
113
|
+
code: params.code,
|
|
114
|
+
body,
|
|
115
|
+
uid: user?.uid,
|
|
116
|
+
}, pg);
|
|
117
|
+
return result;
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
app.route({
|
|
121
|
+
method: "DELETE",
|
|
122
|
+
url: "/dictionaries/:code/values/:id",
|
|
123
|
+
config: { tags, package: packageName, policy: "L1" },
|
|
124
|
+
schema: { params: dictionaryParamsSchema },
|
|
125
|
+
handler: async ({ params, user, pg }) => {
|
|
126
|
+
const result = await deleteDictionaryItem({
|
|
127
|
+
id: params.id,
|
|
128
|
+
code: params.code,
|
|
129
|
+
uid: user?.uid,
|
|
130
|
+
}, pg);
|
|
131
|
+
return result;
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
declare const _default: null;
|
|
2
|
+
export default _default;
|
|
3
|
+
export declare const dictionaryParamsSchema: {
|
|
4
|
+
type: string;
|
|
5
|
+
properties: {
|
|
6
|
+
code: {
|
|
7
|
+
type: string;
|
|
8
|
+
pattern: string;
|
|
9
|
+
};
|
|
10
|
+
id: {
|
|
11
|
+
type: string;
|
|
12
|
+
pattern: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare const createDictionaryBodySchema: {
|
|
17
|
+
type: string;
|
|
18
|
+
additionalProperties: boolean;
|
|
19
|
+
required: string[];
|
|
20
|
+
properties: {
|
|
21
|
+
code: {
|
|
22
|
+
type: string;
|
|
23
|
+
pattern: string;
|
|
24
|
+
};
|
|
25
|
+
name: {
|
|
26
|
+
type: string;
|
|
27
|
+
pattern: string;
|
|
28
|
+
};
|
|
29
|
+
module: {
|
|
30
|
+
type: string;
|
|
31
|
+
pattern: string;
|
|
32
|
+
};
|
|
33
|
+
description: {
|
|
34
|
+
type: string;
|
|
35
|
+
pattern: string;
|
|
36
|
+
};
|
|
37
|
+
editable: {
|
|
38
|
+
type: string;
|
|
39
|
+
};
|
|
40
|
+
values: {
|
|
41
|
+
type: string;
|
|
42
|
+
minItems: number;
|
|
43
|
+
maxItems: number;
|
|
44
|
+
items: {
|
|
45
|
+
required: string[];
|
|
46
|
+
additionalProperties: boolean;
|
|
47
|
+
properties: {
|
|
48
|
+
code: {
|
|
49
|
+
type: string;
|
|
50
|
+
pattern: string;
|
|
51
|
+
};
|
|
52
|
+
name: {
|
|
53
|
+
type: string;
|
|
54
|
+
pattern: string;
|
|
55
|
+
};
|
|
56
|
+
color: {
|
|
57
|
+
type: string;
|
|
58
|
+
};
|
|
59
|
+
icon: {
|
|
60
|
+
type: string;
|
|
61
|
+
};
|
|
62
|
+
sort: {
|
|
63
|
+
type: string;
|
|
64
|
+
minimum: number;
|
|
65
|
+
default: number;
|
|
66
|
+
};
|
|
67
|
+
metadata: {
|
|
68
|
+
type: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
export declare const updateDictionaryBodySchema: {
|
|
76
|
+
type: string;
|
|
77
|
+
additionalProperties: boolean;
|
|
78
|
+
properties: {
|
|
79
|
+
code: {
|
|
80
|
+
type: string;
|
|
81
|
+
pattern: string;
|
|
82
|
+
};
|
|
83
|
+
name: {
|
|
84
|
+
type: string;
|
|
85
|
+
pattern: string;
|
|
86
|
+
};
|
|
87
|
+
module: {
|
|
88
|
+
type: string;
|
|
89
|
+
pattern: string;
|
|
90
|
+
};
|
|
91
|
+
description: {
|
|
92
|
+
type: string;
|
|
93
|
+
pattern: string;
|
|
94
|
+
};
|
|
95
|
+
editable: {
|
|
96
|
+
type: string;
|
|
97
|
+
};
|
|
98
|
+
values: {
|
|
99
|
+
type: string;
|
|
100
|
+
minItems: number;
|
|
101
|
+
maxItems: number;
|
|
102
|
+
items: {
|
|
103
|
+
required: string[];
|
|
104
|
+
additionalProperties: boolean;
|
|
105
|
+
properties: {
|
|
106
|
+
code: {
|
|
107
|
+
type: string;
|
|
108
|
+
pattern: string;
|
|
109
|
+
};
|
|
110
|
+
name: {
|
|
111
|
+
type: string;
|
|
112
|
+
pattern: string;
|
|
113
|
+
};
|
|
114
|
+
color: {
|
|
115
|
+
type: string;
|
|
116
|
+
};
|
|
117
|
+
icon: {
|
|
118
|
+
type: string;
|
|
119
|
+
};
|
|
120
|
+
sort: {
|
|
121
|
+
type: string;
|
|
122
|
+
minimum: number;
|
|
123
|
+
default: number;
|
|
124
|
+
};
|
|
125
|
+
metadata: {
|
|
126
|
+
type: string;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
system: {
|
|
132
|
+
type: string;
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
export declare const createDictionaryItemBodySchema: {
|
|
137
|
+
type: string;
|
|
138
|
+
properties: {
|
|
139
|
+
code: {
|
|
140
|
+
type: string;
|
|
141
|
+
pattern: string;
|
|
142
|
+
};
|
|
143
|
+
name: {
|
|
144
|
+
type: string;
|
|
145
|
+
pattern: string;
|
|
146
|
+
};
|
|
147
|
+
color: {
|
|
148
|
+
type: string;
|
|
149
|
+
};
|
|
150
|
+
icon: {
|
|
151
|
+
type: string;
|
|
152
|
+
};
|
|
153
|
+
sort: {
|
|
154
|
+
type: string;
|
|
155
|
+
minimum: number;
|
|
156
|
+
default: number;
|
|
157
|
+
};
|
|
158
|
+
metadata: {
|
|
159
|
+
type: string;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
export declare const updateDictionaryItemBodySchema: {
|
|
164
|
+
type: string;
|
|
165
|
+
properties: {
|
|
166
|
+
code: {
|
|
167
|
+
type: string;
|
|
168
|
+
pattern: string;
|
|
169
|
+
};
|
|
170
|
+
name: {
|
|
171
|
+
type: string;
|
|
172
|
+
pattern: string;
|
|
173
|
+
};
|
|
174
|
+
color: {
|
|
175
|
+
type: string;
|
|
176
|
+
};
|
|
177
|
+
icon: {
|
|
178
|
+
type: string;
|
|
179
|
+
};
|
|
180
|
+
sort: {
|
|
181
|
+
type: string;
|
|
182
|
+
minimum: number;
|
|
183
|
+
default: number;
|
|
184
|
+
};
|
|
185
|
+
metadata: {
|
|
186
|
+
type: string;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
//# sourceMappingURL=dictionaries.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dictionaries.schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/dictionaries/dictionaries.schema.ts"],"names":[],"mappings":";AAAA,wBAAoB;AA2CpB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;CAMlC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CActC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBtC,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;CAG1C,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;CAG1C,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export default null;
|
|
2
|
+
const idSchema = {
|
|
3
|
+
type: "string",
|
|
4
|
+
pattern: "^([\\d\\w_.-]+)$",
|
|
5
|
+
};
|
|
6
|
+
const codeSchema = {
|
|
7
|
+
type: "string",
|
|
8
|
+
pattern: "^([\\d\\w_.-]+)$",
|
|
9
|
+
};
|
|
10
|
+
const nameSchema = {
|
|
11
|
+
type: "string",
|
|
12
|
+
pattern: "^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$",
|
|
13
|
+
};
|
|
14
|
+
const moduleSchema = {
|
|
15
|
+
type: "string",
|
|
16
|
+
pattern: "^([\\d\\w_.-]+)$",
|
|
17
|
+
};
|
|
18
|
+
const descriptionSchema = {
|
|
19
|
+
type: "string",
|
|
20
|
+
pattern: "^([А-Яа-яҐґЄєІіЇї\\d\\w\\s_.-]+)$",
|
|
21
|
+
};
|
|
22
|
+
const itemSchema = {
|
|
23
|
+
code: codeSchema,
|
|
24
|
+
name: nameSchema,
|
|
25
|
+
color: { type: "string" },
|
|
26
|
+
icon: { type: "string" },
|
|
27
|
+
sort: { type: "integer", minimum: 0, default: 0 },
|
|
28
|
+
metadata: { type: "object" },
|
|
29
|
+
};
|
|
30
|
+
const valuesSchema = {
|
|
31
|
+
type: "array",
|
|
32
|
+
minItems: 2,
|
|
33
|
+
maxItems: 100,
|
|
34
|
+
items: {
|
|
35
|
+
required: ["code", "name", "sort"],
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
properties: itemSchema,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export const dictionaryParamsSchema = {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
code: codeSchema,
|
|
44
|
+
id: idSchema,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
export const createDictionaryBodySchema = {
|
|
48
|
+
type: "object",
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
required: ["code", "name"],
|
|
51
|
+
properties: {
|
|
52
|
+
code: codeSchema,
|
|
53
|
+
name: nameSchema,
|
|
54
|
+
module: moduleSchema,
|
|
55
|
+
description: descriptionSchema,
|
|
56
|
+
editable: {
|
|
57
|
+
type: "boolean",
|
|
58
|
+
},
|
|
59
|
+
values: valuesSchema,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
export const updateDictionaryBodySchema = {
|
|
63
|
+
type: "object",
|
|
64
|
+
additionalProperties: false,
|
|
65
|
+
properties: {
|
|
66
|
+
code: codeSchema,
|
|
67
|
+
name: nameSchema,
|
|
68
|
+
module: moduleSchema,
|
|
69
|
+
description: descriptionSchema,
|
|
70
|
+
editable: {
|
|
71
|
+
type: "boolean",
|
|
72
|
+
},
|
|
73
|
+
values: valuesSchema,
|
|
74
|
+
system: {
|
|
75
|
+
type: "boolean",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
export const createDictionaryItemBodySchema = {
|
|
80
|
+
type: "object",
|
|
81
|
+
properties: itemSchema,
|
|
82
|
+
};
|
|
83
|
+
export const updateDictionaryItemBodySchema = {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: itemSchema,
|
|
86
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {String} id Dictionary ID, optional
|
|
4
|
+
*/
|
|
5
|
+
export default function createDictionary({ id, body, uid, }: {
|
|
6
|
+
id: string;
|
|
7
|
+
body: Record<string, any>;
|
|
8
|
+
uid: string;
|
|
9
|
+
}, pg?: any): Promise<any>;
|
|
10
|
+
//# sourceMappingURL=create.dictionary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.dictionary.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/create.dictionary.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH,wBAA8B,gBAAgB,CAC5C,EACE,EAAE,EACF,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBA8EtB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {String} id Item ID, optional
|
|
4
|
+
* @param {String} code Dictionary code (filename)
|
|
5
|
+
* @param {String} body.code Item code
|
|
6
|
+
*/
|
|
7
|
+
export default function createDictionaryItem({ id, code, body, uid, }: {
|
|
8
|
+
id: string;
|
|
9
|
+
code: string;
|
|
10
|
+
body: Record<string, any>;
|
|
11
|
+
uid: string;
|
|
12
|
+
}, pg?: any): Promise<any>;
|
|
13
|
+
//# sourceMappingURL=create.dictionary.item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.dictionary.item.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/create.dictionary.item.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AAEH,wBAA8B,oBAAoB,CAChD,EACE,EAAE,EACF,IAAI,EACJ,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBA2DtB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataInsert from "../../../plugins/crud/funcs/dataInsert.js";
|
|
3
|
+
import { BadRequestError, NotFoundError } from "../../../../errors.js";
|
|
4
|
+
import updateDictionary from "./update.dictionary.js";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {String} id Item ID, optional
|
|
8
|
+
* @param {String} code Dictionary code (filename)
|
|
9
|
+
* @param {String} body.code Item code
|
|
10
|
+
*/
|
|
11
|
+
export default async function createDictionaryItem({ id, code, body, uid, }, pg = pgClients.client) {
|
|
12
|
+
if (!pg) {
|
|
13
|
+
throw new Error("empty pg");
|
|
14
|
+
}
|
|
15
|
+
if (!code) {
|
|
16
|
+
throw BadRequestError("not enough params: code");
|
|
17
|
+
}
|
|
18
|
+
if (!body) {
|
|
19
|
+
throw BadRequestError("not enough params: body");
|
|
20
|
+
}
|
|
21
|
+
if (!body.code) {
|
|
22
|
+
throw BadRequestError("not enough body params: code");
|
|
23
|
+
}
|
|
24
|
+
if (!body.name) {
|
|
25
|
+
throw BadRequestError("not enough body params: name");
|
|
26
|
+
}
|
|
27
|
+
const { system, id: dictionaryId } = await pg
|
|
28
|
+
.query("select id from admin.dictionaries where code=$1", [code])
|
|
29
|
+
.then((r) => ({ system: r.rows?.[0]?.system, id: r.rows?.[0]?.id }));
|
|
30
|
+
if (!dictionaryId) {
|
|
31
|
+
throw NotFoundError("dictionary not found");
|
|
32
|
+
}
|
|
33
|
+
// make custom
|
|
34
|
+
if (system) {
|
|
35
|
+
await updateDictionary({ id: dictionaryId, body: { system: false }, uid }, pg);
|
|
36
|
+
}
|
|
37
|
+
const { data } = await dataInsert({
|
|
38
|
+
id,
|
|
39
|
+
table: "admin.dictionary_items",
|
|
40
|
+
data: {
|
|
41
|
+
code: body.code,
|
|
42
|
+
dictionary_id: dictionaryId,
|
|
43
|
+
name: body.name,
|
|
44
|
+
description: body.description,
|
|
45
|
+
color: body.color,
|
|
46
|
+
icon: body.icon,
|
|
47
|
+
parent_id: body.parent_id,
|
|
48
|
+
sort_order: body.sort,
|
|
49
|
+
metadata: body.metadata,
|
|
50
|
+
system: false,
|
|
51
|
+
active: body.active === false ? false : true,
|
|
52
|
+
},
|
|
53
|
+
pg,
|
|
54
|
+
uid,
|
|
55
|
+
});
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataInsert from "../../../plugins/crud/funcs/dataInsert.js";
|
|
3
|
+
import deleteDictionary from "./delete.dictionary.js";
|
|
4
|
+
import { BadRequestError } from "../../../../errors.js";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {String} id Dictionary ID, optional
|
|
8
|
+
*/
|
|
9
|
+
export default async function createDictionary({ id, body, uid, }, pg = pgClients.client) {
|
|
10
|
+
if (!pg) {
|
|
11
|
+
throw new Error("empty pg");
|
|
12
|
+
}
|
|
13
|
+
if (!body) {
|
|
14
|
+
throw BadRequestError("not enough params: body");
|
|
15
|
+
}
|
|
16
|
+
if (!body?.values?.length) {
|
|
17
|
+
// throw BadRequestError("not enough body params: values");
|
|
18
|
+
}
|
|
19
|
+
const client = await pg.connect();
|
|
20
|
+
try {
|
|
21
|
+
const systemDictionaryId = await pg
|
|
22
|
+
.query("select id from admin.dictionaries where system and id = $1", [id])
|
|
23
|
+
.then((r) => r.rows?.[0]?.id);
|
|
24
|
+
await client.query("begin");
|
|
25
|
+
if (systemDictionaryId) {
|
|
26
|
+
await deleteDictionary({ id: systemDictionaryId, uid }, client);
|
|
27
|
+
}
|
|
28
|
+
const { data } = (await dataInsert({
|
|
29
|
+
id,
|
|
30
|
+
table: "admin.dictionaries",
|
|
31
|
+
data: {
|
|
32
|
+
code: body.code,
|
|
33
|
+
name: body.name,
|
|
34
|
+
module: body.module,
|
|
35
|
+
description: body.description,
|
|
36
|
+
source: "custom",
|
|
37
|
+
system: false,
|
|
38
|
+
editable: body.editable === false ? false : true,
|
|
39
|
+
},
|
|
40
|
+
pg: client,
|
|
41
|
+
uid,
|
|
42
|
+
})) || {};
|
|
43
|
+
if (!data) {
|
|
44
|
+
throw new Error("dictionary insert error");
|
|
45
|
+
}
|
|
46
|
+
const values = await Promise.all((body.values || []).map(async (el) => {
|
|
47
|
+
return dataInsert({
|
|
48
|
+
table: "admin.dictionary_items",
|
|
49
|
+
data: {
|
|
50
|
+
dictionary_id: id,
|
|
51
|
+
code: el.code,
|
|
52
|
+
name: el.name,
|
|
53
|
+
description: el.description,
|
|
54
|
+
color: el.color,
|
|
55
|
+
icon: el.icon,
|
|
56
|
+
parent_id: el.parent_id,
|
|
57
|
+
sort_order: el.sort_order,
|
|
58
|
+
metadata: el.metadata,
|
|
59
|
+
system: false,
|
|
60
|
+
active: el.active === false ? false : true,
|
|
61
|
+
},
|
|
62
|
+
pg: client,
|
|
63
|
+
uid,
|
|
64
|
+
}).then((r) => r.data);
|
|
65
|
+
}));
|
|
66
|
+
await client.query("commit");
|
|
67
|
+
return { ...data, values };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
await client.query("rollback");
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
client.release();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.dictionary.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/delete.dictionary.ts"],"names":[],"mappings":"AAKA;;;GAGG;AAEH,wBAA8B,gBAAgB,CAC5C,EACE,EAAE,EACF,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBA6BtB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {String} id Item ID
|
|
4
|
+
* @param {String} code Dictionary code (filename)
|
|
5
|
+
*/
|
|
6
|
+
export default function deleteDictionaryItem({ id, code, uid, }: {
|
|
7
|
+
id: string;
|
|
8
|
+
code: string;
|
|
9
|
+
uid: string;
|
|
10
|
+
}, pg?: any): Promise<any>;
|
|
11
|
+
//# sourceMappingURL=delete.dictionary.item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.dictionary.item.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/delete.dictionary.item.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AAEH,wBAA8B,oBAAoB,CAChD,EACE,EAAE,EACF,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBAiCtB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataDelete from "../../../plugins/crud/funcs/dataDelete.js";
|
|
3
|
+
import { BadRequestError, NotFoundError } from "../../../../errors.js";
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {String} id Item ID
|
|
7
|
+
* @param {String} code Dictionary code (filename)
|
|
8
|
+
*/
|
|
9
|
+
export default async function deleteDictionaryItem({ id, code, uid, }, pg = pgClients.client) {
|
|
10
|
+
if (!pg) {
|
|
11
|
+
throw new Error("empty pg");
|
|
12
|
+
}
|
|
13
|
+
if (!id) {
|
|
14
|
+
throw BadRequestError("not enough params: id");
|
|
15
|
+
}
|
|
16
|
+
if (!code) {
|
|
17
|
+
throw BadRequestError("not enough params: code");
|
|
18
|
+
}
|
|
19
|
+
const itemId = await pg
|
|
20
|
+
.query("select id from admin.dictionary_items where dictionary_id in (select id from admin.dictionaries where $1 in (id,code) ) and $2 in (id,code)", [code, id])
|
|
21
|
+
.then((r) => r.rows?.[0]?.id);
|
|
22
|
+
if (!itemId) {
|
|
23
|
+
throw NotFoundError("dictionary item not found");
|
|
24
|
+
}
|
|
25
|
+
const item = await dataDelete({
|
|
26
|
+
id: itemId,
|
|
27
|
+
table: "admin.dictionary_items",
|
|
28
|
+
pg,
|
|
29
|
+
uid,
|
|
30
|
+
});
|
|
31
|
+
return item;
|
|
32
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataDelete from "../../../plugins/crud/funcs/dataDelete.js";
|
|
3
|
+
import { BadRequestError, NotFoundError } from "../../../../errors.js";
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {String} id Dictionary ID
|
|
7
|
+
*/
|
|
8
|
+
export default async function deleteDictionary({ id, uid, }, pg = pgClients.client) {
|
|
9
|
+
if (!pg) {
|
|
10
|
+
throw new Error("empty pg");
|
|
11
|
+
}
|
|
12
|
+
if (!id) {
|
|
13
|
+
throw BadRequestError("not enough params: id");
|
|
14
|
+
}
|
|
15
|
+
const values = await pg
|
|
16
|
+
.query("delete from admin.dictionary_items where dictionary_id=$1 returning id,code,name,color,icon", [id])
|
|
17
|
+
.then((r) => r.rowCount || 0);
|
|
18
|
+
const row = await dataDelete({
|
|
19
|
+
table: "admin.dictionaries",
|
|
20
|
+
id,
|
|
21
|
+
uid,
|
|
22
|
+
pg,
|
|
23
|
+
});
|
|
24
|
+
if (!row) {
|
|
25
|
+
throw NotFoundError("dictionary not found");
|
|
26
|
+
}
|
|
27
|
+
return { ...row, values };
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.dictionaries.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/read.dictionaries.ts"],"names":[],"mappings":"AAIA,wBAA8B,gBAAgB,CAC5C,EACE,IAAI,EACJ,MAAc,GACf,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,EACD,EAAE,MAAmB,gBAqCtB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import { NotFoundError } from "../../../../errors.js";
|
|
3
|
+
export default async function readDictionaries({ code, values = false, }, pg = pgClients.client) {
|
|
4
|
+
if (!pg) {
|
|
5
|
+
throw new Error("empty pg");
|
|
6
|
+
}
|
|
7
|
+
if (!code) {
|
|
8
|
+
const rows = await pg
|
|
9
|
+
.query("select code,name,module,source from admin.dictionaries")
|
|
10
|
+
.then((r) => r.rows || []);
|
|
11
|
+
return { total: rows.length, rows };
|
|
12
|
+
}
|
|
13
|
+
// code is unique
|
|
14
|
+
const rows = await pg
|
|
15
|
+
.query("select id, code, name, module, description, source, editable, system from admin.dictionaries where $1 in (code, id) limit 1", [code])
|
|
16
|
+
.then((r) => r.rows || []);
|
|
17
|
+
if (!rows.length) {
|
|
18
|
+
throw NotFoundError("dictionary not found");
|
|
19
|
+
}
|
|
20
|
+
const items = await pg
|
|
21
|
+
.query("select code, name, description, color, icon, sort_order as sort, parent_id, active, system, metadata from admin.dictionary_items where dictionary_id=$1", [rows[0].id])
|
|
22
|
+
.then((r) => r.rows || []);
|
|
23
|
+
if (values) {
|
|
24
|
+
return items;
|
|
25
|
+
}
|
|
26
|
+
return { ...rows[0], values: items };
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.dictionary.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/update.dictionary.ts"],"names":[],"mappings":"AAIA;;;GAGG;AAEH,wBAA8B,gBAAgB,CAC5C,EACE,EAAE,EACF,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBAyDtB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {String} id Item ID
|
|
4
|
+
* @param {String} code Dictionary code (filename)
|
|
5
|
+
* @param {String} body.code Item code
|
|
6
|
+
*/
|
|
7
|
+
export default function updateDictionaryItem({ id, code, body, uid, }: {
|
|
8
|
+
id: string;
|
|
9
|
+
code: string;
|
|
10
|
+
body: Record<string, any>;
|
|
11
|
+
uid: string;
|
|
12
|
+
}, pg?: any): Promise<any>;
|
|
13
|
+
//# sourceMappingURL=update.dictionary.item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.dictionary.item.d.ts","sourceRoot":"","sources":["../../../../../server/routes/dictionaries/functions/update.dictionary.item.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AAEH,wBAA8B,oBAAoB,CAChD,EACE,EAAE,EACF,IAAI,EACJ,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,EACD,EAAE,MAAmB,gBAiDtB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataUpdate from "../../../plugins/crud/funcs/dataUpdate.js";
|
|
3
|
+
import updateDictionary from "./update.dictionary.js";
|
|
4
|
+
import { BadRequestError, NotFoundError } from "../../../../errors.js";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {String} id Item ID
|
|
8
|
+
* @param {String} code Dictionary code (filename)
|
|
9
|
+
* @param {String} body.code Item code
|
|
10
|
+
*/
|
|
11
|
+
export default async function updateDictionaryItem({ id, code, body, uid, }, pg = pgClients.client) {
|
|
12
|
+
if (!pg) {
|
|
13
|
+
throw new Error("empty pg");
|
|
14
|
+
}
|
|
15
|
+
if (!code) {
|
|
16
|
+
throw BadRequestError("not enough params: code");
|
|
17
|
+
}
|
|
18
|
+
if (!body) {
|
|
19
|
+
throw BadRequestError("not enough params: body");
|
|
20
|
+
}
|
|
21
|
+
const { system, id: dictionaryId } = await pg
|
|
22
|
+
.query("select id from admin.dictionaries where $1 in (id,code)", [code])
|
|
23
|
+
.then((r) => ({ system: r.rows?.[0]?.system, id: r.rows?.[0]?.id }));
|
|
24
|
+
if (!dictionaryId) {
|
|
25
|
+
throw NotFoundError("dictionary not found");
|
|
26
|
+
}
|
|
27
|
+
const itemId = await pg
|
|
28
|
+
.query("select id from admin.dictionary_items where $1 in (id,code)", [id])
|
|
29
|
+
.then((r) => r.rows?.[0]?.id);
|
|
30
|
+
if (!itemId) {
|
|
31
|
+
throw NotFoundError("dictionary item not found");
|
|
32
|
+
}
|
|
33
|
+
// make custom
|
|
34
|
+
if (system) {
|
|
35
|
+
await updateDictionary({ id: dictionaryId, body: { system: false }, uid }, pg);
|
|
36
|
+
}
|
|
37
|
+
const row = await dataUpdate({
|
|
38
|
+
id: itemId,
|
|
39
|
+
table: "admin.dictionary_items",
|
|
40
|
+
data: {
|
|
41
|
+
...body,
|
|
42
|
+
sort_order: body.sort,
|
|
43
|
+
},
|
|
44
|
+
pg,
|
|
45
|
+
uid,
|
|
46
|
+
});
|
|
47
|
+
return row;
|
|
48
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pgClients from "../../../plugins/pg/pgClients.js";
|
|
2
|
+
import dataInsert from "../../../plugins/crud/funcs/dataInsert.js";
|
|
3
|
+
import dataUpdate from "../../../plugins/crud/funcs/dataUpdate.js";
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {String} id Dictionary ID
|
|
7
|
+
*/
|
|
8
|
+
export default async function updateDictionary({ id, body, uid, }, pg = pgClients.client) {
|
|
9
|
+
if (!pg) {
|
|
10
|
+
throw new Error("empty pg");
|
|
11
|
+
}
|
|
12
|
+
if (!id) {
|
|
13
|
+
throw new Error("not enough params: id");
|
|
14
|
+
}
|
|
15
|
+
if (!body) {
|
|
16
|
+
throw new Error("not enough params: body");
|
|
17
|
+
}
|
|
18
|
+
const row = await dataUpdate({
|
|
19
|
+
id,
|
|
20
|
+
table: "admin.dictionaries",
|
|
21
|
+
data: body,
|
|
22
|
+
pg,
|
|
23
|
+
uid,
|
|
24
|
+
});
|
|
25
|
+
if (body.values?.length) {
|
|
26
|
+
const client = await pg.connect();
|
|
27
|
+
try {
|
|
28
|
+
await client.query("begin");
|
|
29
|
+
await client.query("delete from admin.dictionary_items where dictionary_id = $1", [id]);
|
|
30
|
+
const values = await Promise.all(body.values.map(async (item) => dataInsert({
|
|
31
|
+
table: "admin.dictionary_items",
|
|
32
|
+
data: {
|
|
33
|
+
...item,
|
|
34
|
+
dictionary_id: id,
|
|
35
|
+
},
|
|
36
|
+
pg: client,
|
|
37
|
+
uid,
|
|
38
|
+
}).then((r) => r.data)));
|
|
39
|
+
await client.query("commit");
|
|
40
|
+
return { ...row, values };
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
await client.query("rollback");
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
client.release();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return row;
|
|
51
|
+
}
|