@tensorix/metahub 0.4.0 → 0.4.1
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/cli.js +165 -15
- package/dist/cli.js.map +5 -5
- package/dist/core/properties.d.ts +8 -0
- package/dist/core/properties.d.ts.map +1 -1
- package/dist/db-worker.js +56 -56
- package/dist/edge-worker.js +84 -6
- package/dist/index.js +159 -13
- package/dist/index.js.map +4 -4
- package/dist/metahub-sdk.js +6 -6
- package/dist/sw.js +4 -4
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui.js +122 -116
- package/package.json +2 -2
package/dist/edge-worker.js
CHANGED
|
@@ -639,16 +639,25 @@ var updateProperty = grouped(function updateProperty2(db, id, fields) {
|
|
|
639
639
|
if (fields.type !== undefined && !PROP_TYPES.has(fields.type))
|
|
640
640
|
throw new MhError("invalid_input", `unknown property type: ${fields.type}`);
|
|
641
641
|
const effectiveType = fields.type ?? cur.type;
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
642
|
+
let mergedConfig;
|
|
643
|
+
if (fields.config !== undefined) {
|
|
644
|
+
const merged = { ...cur.config ?? {} };
|
|
645
|
+
for (const [k, v] of Object.entries(fields.config)) {
|
|
646
|
+
if (v === null)
|
|
647
|
+
delete merged[k];
|
|
648
|
+
else
|
|
649
|
+
merged[k] = v;
|
|
650
|
+
}
|
|
651
|
+
mergedConfig = merged;
|
|
652
|
+
validateConfig(effectiveType, mergedConfig);
|
|
653
|
+
} else if (typeChanged)
|
|
654
|
+
validateConfig(fields.type, cur.config ?? undefined);
|
|
646
655
|
if (fields.name !== undefined)
|
|
647
656
|
emit(db, "properties", id, "name", fields.name);
|
|
648
657
|
if (fields.type !== undefined)
|
|
649
658
|
emit(db, "properties", id, "type", fields.type);
|
|
650
|
-
if (
|
|
651
|
-
emit(db, "properties", id, "config",
|
|
659
|
+
if (mergedConfig !== undefined)
|
|
660
|
+
emit(db, "properties", id, "config", mergedConfig);
|
|
652
661
|
if (fields.position !== undefined)
|
|
653
662
|
emit(db, "properties", id, "position", fields.position);
|
|
654
663
|
if (typeChanged) {
|
|
@@ -658,6 +667,75 @@ var updateProperty = grouped(function updateProperty2(db, id, fields) {
|
|
|
658
667
|
}
|
|
659
668
|
return getProperty(db, id);
|
|
660
669
|
});
|
|
670
|
+
function getSelectProperty(db, id) {
|
|
671
|
+
const prop = getProperty(db, id);
|
|
672
|
+
if (!prop)
|
|
673
|
+
throw new MhError("not_found", `no such property: ${id}`);
|
|
674
|
+
if (prop.type !== "select" && prop.type !== "multi_select")
|
|
675
|
+
throw new MhError("invalid_input", `${prop.type} property has no options`);
|
|
676
|
+
return { prop, options: prop.config?.options ?? [] };
|
|
677
|
+
}
|
|
678
|
+
var renameSelectOption = grouped(function renameSelectOption2(db, id, from, to) {
|
|
679
|
+
const { prop, options } = getSelectProperty(db, id);
|
|
680
|
+
to = to.trim();
|
|
681
|
+
if (!to)
|
|
682
|
+
throw new MhError("invalid_input", "option name must not be empty");
|
|
683
|
+
if (!options.includes(from))
|
|
684
|
+
throw new MhError("not_found", `no such option: ${from}`);
|
|
685
|
+
if (to === from)
|
|
686
|
+
return { property: prop, renamed: 0 };
|
|
687
|
+
if (options.includes(to))
|
|
688
|
+
throw new MhError("conflict", `option already exists: ${to}`);
|
|
689
|
+
emit(db, "properties", id, "config", {
|
|
690
|
+
...prop.config ?? {},
|
|
691
|
+
options: options.map((o) => o === from ? to : o)
|
|
692
|
+
});
|
|
693
|
+
let renamed = 0;
|
|
694
|
+
if (prop.type === "select") {
|
|
695
|
+
const rows = db.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(prop.database_id, id, from);
|
|
696
|
+
for (const r of rows)
|
|
697
|
+
emit(db, "records", r.id, id, to);
|
|
698
|
+
renamed = rows.length;
|
|
699
|
+
} else {
|
|
700
|
+
const rows = db.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(id, prop.database_id, id);
|
|
701
|
+
for (const r of rows) {
|
|
702
|
+
const vals = JSON.parse(r.v);
|
|
703
|
+
if (!Array.isArray(vals) || !vals.includes(from))
|
|
704
|
+
continue;
|
|
705
|
+
emit(db, "records", r.id, id, [...new Set(vals.map((v) => v === from ? to : v))]);
|
|
706
|
+
renamed++;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return { property: getProperty(db, id), renamed };
|
|
710
|
+
});
|
|
711
|
+
var removeSelectOption = grouped(function removeSelectOption2(db, id, name) {
|
|
712
|
+
const { prop, options } = getSelectProperty(db, id);
|
|
713
|
+
if (!options.includes(name))
|
|
714
|
+
throw new MhError("not_found", `no such option: ${name}`);
|
|
715
|
+
if (options.length === 1)
|
|
716
|
+
throw new MhError("invalid_input", "cannot remove the last option; delete the property instead");
|
|
717
|
+
emit(db, "properties", id, "config", {
|
|
718
|
+
...prop.config ?? {},
|
|
719
|
+
options: options.filter((o) => o !== name)
|
|
720
|
+
});
|
|
721
|
+
let cleared = 0;
|
|
722
|
+
if (prop.type === "select") {
|
|
723
|
+
const rows = db.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(prop.database_id, id, name);
|
|
724
|
+
for (const r of rows)
|
|
725
|
+
emit(db, "records", r.id, id, null);
|
|
726
|
+
cleared = rows.length;
|
|
727
|
+
} else {
|
|
728
|
+
const rows = db.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(id, prop.database_id, id);
|
|
729
|
+
for (const r of rows) {
|
|
730
|
+
const vals = JSON.parse(r.v);
|
|
731
|
+
if (!Array.isArray(vals) || !vals.includes(name))
|
|
732
|
+
continue;
|
|
733
|
+
emit(db, "records", r.id, id, vals.filter((v) => v !== name));
|
|
734
|
+
cleared++;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return { property: getProperty(db, id), cleared };
|
|
738
|
+
});
|
|
661
739
|
var removeProperty = grouped(function removeProperty2(db, id) {
|
|
662
740
|
const prop = getProperty(db, id);
|
|
663
741
|
if (!prop)
|
package/dist/index.js
CHANGED
|
@@ -953,7 +953,15 @@ function setPropertyWidth(db, id, width) {
|
|
|
953
953
|
const w = Math.max(80, Math.min(2000, Math.round(width)));
|
|
954
954
|
return updateProperty(db, id, { config: { ...cur.config ?? {}, width: w } });
|
|
955
955
|
}
|
|
956
|
-
|
|
956
|
+
function getSelectProperty(db, id) {
|
|
957
|
+
const prop = getProperty(db, id);
|
|
958
|
+
if (!prop)
|
|
959
|
+
throw new MhError("not_found", `no such property: ${id}`);
|
|
960
|
+
if (prop.type !== "select" && prop.type !== "multi_select")
|
|
961
|
+
throw new MhError("invalid_input", `${prop.type} property has no options`);
|
|
962
|
+
return { prop, options: prop.config?.options ?? [] };
|
|
963
|
+
}
|
|
964
|
+
var PROP_TYPES, PROPERTY_COLS, PROPERTY_SELECT, addProperty, updateProperty, renameSelectOption, removeSelectOption, removeProperty;
|
|
957
965
|
var init_properties = __esm(() => {
|
|
958
966
|
init_ids();
|
|
959
967
|
init_crdt();
|
|
@@ -996,16 +1004,25 @@ var init_properties = __esm(() => {
|
|
|
996
1004
|
if (fields.type !== undefined && !PROP_TYPES.has(fields.type))
|
|
997
1005
|
throw new MhError("invalid_input", `unknown property type: ${fields.type}`);
|
|
998
1006
|
const effectiveType = fields.type ?? cur.type;
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1007
|
+
let mergedConfig;
|
|
1008
|
+
if (fields.config !== undefined) {
|
|
1009
|
+
const merged = { ...cur.config ?? {} };
|
|
1010
|
+
for (const [k, v] of Object.entries(fields.config)) {
|
|
1011
|
+
if (v === null)
|
|
1012
|
+
delete merged[k];
|
|
1013
|
+
else
|
|
1014
|
+
merged[k] = v;
|
|
1015
|
+
}
|
|
1016
|
+
mergedConfig = merged;
|
|
1017
|
+
validateConfig(effectiveType, mergedConfig);
|
|
1018
|
+
} else if (typeChanged)
|
|
1019
|
+
validateConfig(fields.type, cur.config ?? undefined);
|
|
1003
1020
|
if (fields.name !== undefined)
|
|
1004
1021
|
emit(db, "properties", id, "name", fields.name);
|
|
1005
1022
|
if (fields.type !== undefined)
|
|
1006
1023
|
emit(db, "properties", id, "type", fields.type);
|
|
1007
|
-
if (
|
|
1008
|
-
emit(db, "properties", id, "config",
|
|
1024
|
+
if (mergedConfig !== undefined)
|
|
1025
|
+
emit(db, "properties", id, "config", mergedConfig);
|
|
1009
1026
|
if (fields.position !== undefined)
|
|
1010
1027
|
emit(db, "properties", id, "position", fields.position);
|
|
1011
1028
|
if (typeChanged) {
|
|
@@ -1015,6 +1032,67 @@ var init_properties = __esm(() => {
|
|
|
1015
1032
|
}
|
|
1016
1033
|
return getProperty(db, id);
|
|
1017
1034
|
});
|
|
1035
|
+
renameSelectOption = grouped(function renameSelectOption2(db, id, from, to) {
|
|
1036
|
+
const { prop, options } = getSelectProperty(db, id);
|
|
1037
|
+
to = to.trim();
|
|
1038
|
+
if (!to)
|
|
1039
|
+
throw new MhError("invalid_input", "option name must not be empty");
|
|
1040
|
+
if (!options.includes(from))
|
|
1041
|
+
throw new MhError("not_found", `no such option: ${from}`);
|
|
1042
|
+
if (to === from)
|
|
1043
|
+
return { property: prop, renamed: 0 };
|
|
1044
|
+
if (options.includes(to))
|
|
1045
|
+
throw new MhError("conflict", `option already exists: ${to}`);
|
|
1046
|
+
emit(db, "properties", id, "config", {
|
|
1047
|
+
...prop.config ?? {},
|
|
1048
|
+
options: options.map((o) => o === from ? to : o)
|
|
1049
|
+
});
|
|
1050
|
+
let renamed = 0;
|
|
1051
|
+
if (prop.type === "select") {
|
|
1052
|
+
const rows = db.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(prop.database_id, id, from);
|
|
1053
|
+
for (const r of rows)
|
|
1054
|
+
emit(db, "records", r.id, id, to);
|
|
1055
|
+
renamed = rows.length;
|
|
1056
|
+
} else {
|
|
1057
|
+
const rows = db.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(id, prop.database_id, id);
|
|
1058
|
+
for (const r of rows) {
|
|
1059
|
+
const vals = JSON.parse(r.v);
|
|
1060
|
+
if (!Array.isArray(vals) || !vals.includes(from))
|
|
1061
|
+
continue;
|
|
1062
|
+
emit(db, "records", r.id, id, [...new Set(vals.map((v) => v === from ? to : v))]);
|
|
1063
|
+
renamed++;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return { property: getProperty(db, id), renamed };
|
|
1067
|
+
});
|
|
1068
|
+
removeSelectOption = grouped(function removeSelectOption2(db, id, name) {
|
|
1069
|
+
const { prop, options } = getSelectProperty(db, id);
|
|
1070
|
+
if (!options.includes(name))
|
|
1071
|
+
throw new MhError("not_found", `no such option: ${name}`);
|
|
1072
|
+
if (options.length === 1)
|
|
1073
|
+
throw new MhError("invalid_input", "cannot remove the last option; delete the property instead");
|
|
1074
|
+
emit(db, "properties", id, "config", {
|
|
1075
|
+
...prop.config ?? {},
|
|
1076
|
+
options: options.filter((o) => o !== name)
|
|
1077
|
+
});
|
|
1078
|
+
let cleared = 0;
|
|
1079
|
+
if (prop.type === "select") {
|
|
1080
|
+
const rows = db.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? = ?").all(prop.database_id, id, name);
|
|
1081
|
+
for (const r of rows)
|
|
1082
|
+
emit(db, "records", r.id, id, null);
|
|
1083
|
+
cleared = rows.length;
|
|
1084
|
+
} else {
|
|
1085
|
+
const rows = db.query("SELECT id, data ->> ? AS v FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(id, prop.database_id, id);
|
|
1086
|
+
for (const r of rows) {
|
|
1087
|
+
const vals = JSON.parse(r.v);
|
|
1088
|
+
if (!Array.isArray(vals) || !vals.includes(name))
|
|
1089
|
+
continue;
|
|
1090
|
+
emit(db, "records", r.id, id, vals.filter((v) => v !== name));
|
|
1091
|
+
cleared++;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return { property: getProperty(db, id), cleared };
|
|
1095
|
+
});
|
|
1018
1096
|
removeProperty = grouped(function removeProperty2(db, id) {
|
|
1019
1097
|
const prop = getProperty(db, id);
|
|
1020
1098
|
if (!prop)
|
|
@@ -18488,7 +18566,7 @@ var package_default;
|
|
|
18488
18566
|
var init_package = __esm(() => {
|
|
18489
18567
|
package_default = {
|
|
18490
18568
|
name: "@tensorix/metahub",
|
|
18491
|
-
version: "0.4.
|
|
18569
|
+
version: "0.4.1",
|
|
18492
18570
|
description: "Metahub core library and CLI",
|
|
18493
18571
|
license: "AGPL-3.0-only",
|
|
18494
18572
|
type: "module",
|
|
@@ -18528,6 +18606,7 @@ var init_package = __esm(() => {
|
|
|
18528
18606
|
"@codemirror/commands": "6.10.4",
|
|
18529
18607
|
"@codemirror/state": "6.7.0",
|
|
18530
18608
|
"@codemirror/view": "6.43.4",
|
|
18609
|
+
"@joplin/turndown-plugin-gfm": "^1.0.67",
|
|
18531
18610
|
"@sqlite.org/sqlite-wasm": "^3.53.0-build1",
|
|
18532
18611
|
aws4fetch: "^1.0.20",
|
|
18533
18612
|
citty: "^0.1.6",
|
|
@@ -18536,7 +18615,6 @@ var init_package = __esm(() => {
|
|
|
18536
18615
|
preact: "^10.29.2",
|
|
18537
18616
|
"qrcode-generator": "^2.0.4",
|
|
18538
18617
|
turndown: "^7.2.4",
|
|
18539
|
-
"turndown-plugin-gfm": "^1.0.2",
|
|
18540
18618
|
zod: "^4.4.3"
|
|
18541
18619
|
},
|
|
18542
18620
|
devDependencies: {
|
|
@@ -26896,15 +26974,57 @@ var styles_default = ` :root {
|
|
|
26896
26974
|
.pop .typegrid .item .lico { margin:0 auto; }
|
|
26897
26975
|
.pop input.field { width:100%; border:1px solid var(--line-strong); border-radius:var(--radius-sm); padding:7px 9px; outline:none; background:var(--surface); margin:2px; }
|
|
26898
26976
|
.pop input.field:focus { border-color:var(--accent); }
|
|
26977
|
+
/* select-cell picker: search/create input at the top of the popover */
|
|
26978
|
+
.pop .selsearch { display:flex; align-items:center; gap:7px; margin:2px 2px 6px; padding:6px 9px;
|
|
26979
|
+
border:1px solid var(--line-strong); border-radius:var(--radius-sm); background:var(--surface); color:var(--muted); }
|
|
26980
|
+
.pop .selsearch:focus-within { border-color:var(--accent); }
|
|
26981
|
+
.pop .selsearch input { flex:1; width:0; min-width:0; border:0; background:transparent; outline:none;
|
|
26982
|
+
font:inherit; font-size:var(--fs-ui); color:var(--fg); }
|
|
26983
|
+
.pop .selsearch input::placeholder { color:var(--muted); }
|
|
26899
26984
|
.optrow { display:flex; align-items:center; gap:6px; padding:3px 4px; }
|
|
26900
26985
|
.optrow .chip { flex:1; }
|
|
26901
|
-
.optrow .
|
|
26902
|
-
.optrow .
|
|
26986
|
+
.optrow .grip { width:18px; height:22px; display:grid; place-items:center; color:var(--muted); cursor:grab; touch-action:none; flex:none; }
|
|
26987
|
+
.optrow .grip.dim { color:color-mix(in srgb,var(--muted) 40%,transparent); cursor:default; }
|
|
26988
|
+
.optrow .optlabel { flex:1; display:flex; min-width:0; text-align:left; cursor:pointer; }
|
|
26989
|
+
.optrow .x { width:22px; height:22px; display:grid; place-items:center; color:var(--muted); border-radius:5px; flex:none; }
|
|
26990
|
+
.optrow .x:hover { background:var(--hover-2); color:var(--fg); }
|
|
26991
|
+
.optrow .x.del:hover { color:var(--danger); }
|
|
26992
|
+
.optrow .x.ok:hover { color:var(--success); }
|
|
26993
|
+
/* edit-state buttons fade in alongside the pill's ring */
|
|
26994
|
+
.optrow .x.ok, .optrow .x.cancel { animation:optbtn-in .15s ease; }
|
|
26995
|
+
@keyframes optbtn-in { from { opacity:0; } }
|
|
26996
|
+
.optrow.drop-before { box-shadow:inset 0 2px 0 0 var(--accent); }
|
|
26997
|
+
.optrow.drop-after { box-shadow:inset 0 -2px 0 0 var(--accent); }
|
|
26998
|
+
/* In-place pill editor: mirrors .chip metrics exactly (padding/radius/type)
|
|
26999
|
+
so entering edit never changes the row's size \u2014 only a color-matched ring
|
|
27000
|
+
appears. Caret and selection reuse the option's own hue. */
|
|
27001
|
+
/* width:0 kills the input's intrinsic width (browser default ~20ch) so the
|
|
27002
|
+
popover doesn't widen when the row enters edit \u2014 flex:1 does the sizing.
|
|
27003
|
+
The entry animation only fades the ring in: the pill background must stay
|
|
27004
|
+
put or the swap from the chip reads as a flash. */
|
|
27005
|
+
.optrow input.optedit { flex:1; width:0; min-width:0; margin:0; border:0; font:inherit; font-size:var(--fs-sm); font-weight:500;
|
|
27006
|
+
padding:2px 8px; border-radius:5px; background:color-mix(in srgb,var(--c) 15%,transparent); color:var(--c);
|
|
27007
|
+
caret-color:var(--c); outline:1.5px solid color-mix(in srgb,var(--c) 50%,transparent); outline-offset:0;
|
|
27008
|
+
animation:optedit-in .18s ease; }
|
|
27009
|
+
@keyframes optedit-in { from { outline-color:transparent; } }
|
|
27010
|
+
.optrow input.optedit::selection { background:color-mix(in srgb,var(--c) 28%,transparent); }
|
|
27011
|
+
:root[data-resolved="dark"] .optrow input.optedit { background:color-mix(in srgb,var(--c) 22%,transparent);
|
|
27012
|
+
color:color-mix(in srgb,var(--c) 75%,#fff); caret-color:color-mix(in srgb,var(--c) 75%,#fff); }
|
|
27013
|
+
/* Ghost add-row: quiet until it's needed \u2014 plus icon in the grip slot, a
|
|
27014
|
+
bare borderless input; hover/focus tints the row like a menu item. */
|
|
27015
|
+
.optrow.optadd { border-radius:var(--radius-sm); }
|
|
27016
|
+
.optrow.optadd:hover, .optrow.optadd:focus-within { background:var(--hover-2); }
|
|
27017
|
+
.optrow.optadd input { flex:1; width:0; min-width:0; margin:0; border:0; background:transparent; font:inherit;
|
|
27018
|
+
font-size:var(--fs-sm); padding:2px 8px; color:var(--fg); outline:none; }
|
|
27019
|
+
.optrow.optadd input::placeholder { color:var(--muted); }
|
|
26903
27020
|
|
|
26904
27021
|
/* modal */
|
|
26905
27022
|
.modal-scrim { position:fixed; inset:0; background:rgba(15,15,25,.4); z-index:100; display:flex; align-items:center; justify-content:center;
|
|
26906
27023
|
opacity:0; pointer-events:none; transition:opacity .15s; padding:20px; }
|
|
26907
27024
|
.modal-scrim.open { opacity:1; pointer-events:auto; }
|
|
27025
|
+
/* opt-in (openModal aboveMenus): stack one dialog over the menu layer (115)
|
|
27026
|
+
so a confirm can appear without dismissing an open popover */
|
|
27027
|
+
.modal-scrim.above-menus { z-index:130; }
|
|
26908
27028
|
.modal { background:var(--bg); border-radius:var(--radius-xl); box-shadow:var(--shadow-lg); width:440px; max-width:100%; max-height:100%; display:flex; flex-direction:column; overflow:hidden; }
|
|
26909
27029
|
.modal-head { padding:20px 22px 0; }
|
|
26910
27030
|
.modal-head h3 { margin:0; font-size:18px; font-weight:700; letter-spacing:-.01em; }
|
|
@@ -31024,6 +31144,8 @@ var UpdatePropertyReq = exports_external.object({
|
|
|
31024
31144
|
position: exports_external.number().optional()
|
|
31025
31145
|
});
|
|
31026
31146
|
var SetWidthReq = exports_external.object({ width: exports_external.number() });
|
|
31147
|
+
var RenameOptionReq = exports_external.object({ from: exports_external.string(), to: exports_external.string() });
|
|
31148
|
+
var RemoveOptionReq = exports_external.object({ name: exports_external.string() });
|
|
31027
31149
|
var RecordValuesReq = exports_external.record(exports_external.string(), exports_external.any()).describe("Flat { column: value } cell patch (keyed by property name).");
|
|
31028
31150
|
var CreateDocumentReq = exports_external.object({
|
|
31029
31151
|
title: exports_external.string(),
|
|
@@ -31335,7 +31457,7 @@ var webuiRoutes = [
|
|
|
31335
31457
|
{
|
|
31336
31458
|
method: "PATCH",
|
|
31337
31459
|
path: "/api/property",
|
|
31338
|
-
summary: "Update a property: rename, change type, edit config
|
|
31460
|
+
summary: "Update a property: rename, change type, edit config, reorder. `config` is merged key-wise into the current config (set a key to null to remove it). Query: ?id=<id>",
|
|
31339
31461
|
request: UpdatePropertyReq,
|
|
31340
31462
|
response: PropertySchema,
|
|
31341
31463
|
handler: handle3(async (req, { db: db2 }) => {
|
|
@@ -31343,6 +31465,28 @@ var webuiRoutes = [
|
|
|
31343
31465
|
return updateProperty(db2, need3(req, "id"), body);
|
|
31344
31466
|
})
|
|
31345
31467
|
},
|
|
31468
|
+
{
|
|
31469
|
+
method: "POST",
|
|
31470
|
+
path: "/api/property/option/rename",
|
|
31471
|
+
summary: "Rename a select/multi_select option and rewrite every cell using the old name. Query: ?id=<id>",
|
|
31472
|
+
request: RenameOptionReq,
|
|
31473
|
+
response: exports_external.object({ property: PropertySchema, renamed: exports_external.number() }),
|
|
31474
|
+
handler: handle3(async (req, { db: db2 }) => {
|
|
31475
|
+
const body = await req.json();
|
|
31476
|
+
return renameSelectOption(db2, need3(req, "id"), body.from, body.to);
|
|
31477
|
+
})
|
|
31478
|
+
},
|
|
31479
|
+
{
|
|
31480
|
+
method: "POST",
|
|
31481
|
+
path: "/api/property/option/remove",
|
|
31482
|
+
summary: "Remove a select/multi_select option and clear it from every cell using it. Query: ?id=<id>",
|
|
31483
|
+
request: RemoveOptionReq,
|
|
31484
|
+
response: exports_external.object({ property: PropertySchema, cleared: exports_external.number() }),
|
|
31485
|
+
handler: handle3(async (req, { db: db2 }) => {
|
|
31486
|
+
const body = await req.json();
|
|
31487
|
+
return removeSelectOption(db2, need3(req, "id"), body.name);
|
|
31488
|
+
})
|
|
31489
|
+
},
|
|
31346
31490
|
{
|
|
31347
31491
|
method: "PATCH",
|
|
31348
31492
|
path: "/api/property/width",
|
|
@@ -31730,6 +31874,8 @@ export {
|
|
|
31730
31874
|
resolveEntity,
|
|
31731
31875
|
resolveData,
|
|
31732
31876
|
resolveCandidates,
|
|
31877
|
+
renameSelectOption,
|
|
31878
|
+
removeSelectOption,
|
|
31733
31879
|
removeProperty,
|
|
31734
31880
|
reconcile,
|
|
31735
31881
|
rebuildSearchIndex,
|
|
@@ -31868,4 +32014,4 @@ export {
|
|
|
31868
32014
|
BLOB_HASH_HEX
|
|
31869
32015
|
};
|
|
31870
32016
|
|
|
31871
|
-
//# debugId=
|
|
32017
|
+
//# debugId=9052D340AA681E6D64756E2164756E21
|