@easy-cms/drizzle 1.27.0 → 1.29.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/index.d.ts +13 -0
- package/dist/index.js +195 -33
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -126,7 +126,13 @@ interface ColumnModel {
|
|
|
126
126
|
readonly locale?: string;
|
|
127
127
|
/** The default locale's column, used when a query names no locale. */
|
|
128
128
|
readonly defaultLocale?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* A relationship to several collections (#327) has two columns, `<field>_relation_to` and
|
|
131
|
+
* `<field>_value`: which part of `{ relationTo, value }` this one holds.
|
|
132
|
+
*/
|
|
133
|
+
readonly part?: PolymorphicPart;
|
|
129
134
|
}
|
|
135
|
+
type PolymorphicPart = 'relationTo' | 'value';
|
|
130
136
|
/** A child table holding array rows or hasMany values. */
|
|
131
137
|
interface ChildModel {
|
|
132
138
|
readonly kind: 'array' | 'values';
|
|
@@ -213,6 +219,13 @@ declare class Migrator {
|
|
|
213
219
|
private statistics;
|
|
214
220
|
/** Renames become drop + add unless interactive. */
|
|
215
221
|
private changes;
|
|
222
|
+
/**
|
|
223
|
+
* A relationship that gets several collections (#327) keeps its values: the id moves from
|
|
224
|
+
* `<field>` to `<field>_value`, with the first collection of `to` as `<field>_relation_to`
|
|
225
|
+
* (list the collection it had first). Back to one collection, the values of that collection
|
|
226
|
+
* stay and the others are removed, with a warning.
|
|
227
|
+
*/
|
|
228
|
+
private relationMoves;
|
|
216
229
|
/**
|
|
217
230
|
* A new default locale changes which locale the plain column holds (`title` is the default
|
|
218
231
|
* locale's, `title__en` another's). Moves the values so every locale keeps its own.
|
package/dist/index.js
CHANGED
|
@@ -24,10 +24,19 @@ function setAt(data, path, value) {
|
|
|
24
24
|
}
|
|
25
25
|
current[path[path.length - 1]] = value;
|
|
26
26
|
}
|
|
27
|
-
var columnPath = (column) =>
|
|
27
|
+
var columnPath = (column) => {
|
|
28
|
+
const path = column.locale === void 0 ? column.path : [...column.path, column.locale];
|
|
29
|
+
return column.part === void 0 ? path : [...path, column.part];
|
|
30
|
+
};
|
|
28
31
|
function rowToData(model, row) {
|
|
29
32
|
const data = {};
|
|
30
33
|
for (const column of model.columns) setAt(data, columnPath(column), row[column.column] ?? null);
|
|
34
|
+
for (const column of model.columns) {
|
|
35
|
+
if (column.part !== "value") continue;
|
|
36
|
+
const path = columnPath(column).slice(0, -1);
|
|
37
|
+
const pair = getAt(data, path);
|
|
38
|
+
if (pair && pair.value === null && pair.relationTo === null) setAt(data, path, null);
|
|
39
|
+
}
|
|
31
40
|
for (const child of model.children)
|
|
32
41
|
setAt(
|
|
33
42
|
data,
|
|
@@ -67,7 +76,9 @@ async function attachChildren(db, model, rows, docs) {
|
|
|
67
76
|
const list = getAt(docs[index], path);
|
|
68
77
|
if (!Array.isArray(list)) return;
|
|
69
78
|
const id = locale === void 0 ? childRow.id : String(childRow.id).replace(new RegExp(`:${locale}$`), "");
|
|
70
|
-
list.push(
|
|
79
|
+
list.push(
|
|
80
|
+
child.kind === "array" ? { id, ...childDocs?.[i] } : "relation_to" in childRow ? { relationTo: childRow.relation_to, value: childRow.value } : childRow.value
|
|
81
|
+
);
|
|
71
82
|
});
|
|
72
83
|
}
|
|
73
84
|
}
|
|
@@ -104,10 +115,12 @@ async function insertChildren(db, model, parentId, data) {
|
|
|
104
115
|
async function insertChild(db, child, parentId, items, locale) {
|
|
105
116
|
const localeColumn = locale === void 0 ? {} : { _locale: locale };
|
|
106
117
|
if (child.kind === "values") {
|
|
118
|
+
const polymorphic = "relation_to" in child.table.table;
|
|
107
119
|
const rows = items.map((value, i) => ({
|
|
108
120
|
_parent_id: parentId,
|
|
109
121
|
_order: i,
|
|
110
|
-
value
|
|
122
|
+
// Several collections (#327): `{ relationTo, value }`.
|
|
123
|
+
...polymorphic ? { relation_to: value.relationTo, value: value.value } : { value },
|
|
111
124
|
...localeColumn
|
|
112
125
|
}));
|
|
113
126
|
for (const part of chunks(rows)) await db.insert(child.table.table).values(part);
|
|
@@ -176,7 +189,7 @@ import { SchemaError } from "@easy-cms/core";
|
|
|
176
189
|
// src/schema.ts
|
|
177
190
|
import { createHash } from "crypto";
|
|
178
191
|
import { ConfigError } from "@easy-cms/core";
|
|
179
|
-
import { isHasMany } from "@easy-cms/core/internal";
|
|
192
|
+
import { isHasMany, isPolymorphic } from "@easy-cms/core/internal";
|
|
180
193
|
function tableModels(schema) {
|
|
181
194
|
const all = [];
|
|
182
195
|
const walk = (model) => {
|
|
@@ -345,6 +358,7 @@ function buildTable(builder, name, kind, fields, options) {
|
|
|
345
358
|
}
|
|
346
359
|
if (kind === "values" && options.valueField) {
|
|
347
360
|
const valueKind = columnKind(options.valueField);
|
|
361
|
+
if (isPolymorphic(options.valueField)) add("relation_to", dialect.text("relation_to"), "text");
|
|
348
362
|
add("value", makeColumn(dialect, "value", valueKind), valueKind);
|
|
349
363
|
indexes.push({ column: "value", unique: false });
|
|
350
364
|
}
|
|
@@ -387,21 +401,34 @@ function buildTable(builder, name, kind, fields, options) {
|
|
|
387
401
|
} else {
|
|
388
402
|
const kindOfColumn = columnKind(field);
|
|
389
403
|
const localization = field.localized ? builder.localization : null;
|
|
390
|
-
const
|
|
404
|
+
const parts = isPolymorphic(
|
|
405
|
+
field
|
|
406
|
+
) ? [
|
|
407
|
+
{ suffix: "_relation_to", part: "relationTo", kind: "text" },
|
|
408
|
+
{ suffix: "_value", part: "value", kind: kindOfColumn }
|
|
409
|
+
] : [{ suffix: "", kind: kindOfColumn }];
|
|
410
|
+
const targets = (localization ? localization.locales.map((locale) => ({
|
|
391
411
|
column: locale === localization.defaultLocale ? base : `${base}__${snake(locale)}`,
|
|
392
412
|
locale
|
|
393
|
-
})) : [{ column: base, locale: void 0 }]
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
413
|
+
})) : [{ column: base, locale: void 0 }]).flatMap(
|
|
414
|
+
({ column, locale }) => parts.map(({ suffix, part, kind: kind2 }) => ({
|
|
415
|
+
column: locale === void 0 ? `${base}${suffix}` : column.replace(base, `${base}${suffix}`),
|
|
416
|
+
locale,
|
|
417
|
+
part,
|
|
418
|
+
kind: kind2
|
|
419
|
+
}))
|
|
420
|
+
);
|
|
421
|
+
for (const { column, locale, part, kind: partKind } of targets) {
|
|
422
|
+
add(column, makeColumn(dialect, column, partKind), partKind);
|
|
423
|
+
const model2 = locale === void 0 ? { path: fieldPath, field, column } : {
|
|
424
|
+
path: fieldPath,
|
|
425
|
+
field,
|
|
426
|
+
column,
|
|
427
|
+
locale,
|
|
428
|
+
defaultLocale: locale === localization?.defaultLocale
|
|
429
|
+
};
|
|
430
|
+
columnModels.push(part ? { ...model2, part } : model2);
|
|
431
|
+
if (part === "relationTo") continue;
|
|
405
432
|
if (topLevel && kind === "root" && (field.unique || field.type === "slug") && field.uniqueWithin !== void 0) {
|
|
406
433
|
const within = [field.uniqueWithin].flat().map(snake);
|
|
407
434
|
indexes.push({
|
|
@@ -547,7 +574,10 @@ var Migrator = class {
|
|
|
547
574
|
/** Renames become drop + add unless interactive. */
|
|
548
575
|
async changes(prev, cur, interactive) {
|
|
549
576
|
const { dialect } = this.options;
|
|
550
|
-
const moves =
|
|
577
|
+
const moves = [
|
|
578
|
+
...this.localeMoves(prev, metaOf(prev), metaOf(cur)),
|
|
579
|
+
...this.relationMoves(prev)
|
|
580
|
+
];
|
|
551
581
|
const [from, to] = [withoutMeta(prev), withoutMeta(cur)];
|
|
552
582
|
if (interactive && moves.length === 0) return dialect.migration(from, to);
|
|
553
583
|
const union = unionSnapshot(from, to);
|
|
@@ -557,6 +587,62 @@ var Migrator = class {
|
|
|
557
587
|
...await dialect.migration(union, to)
|
|
558
588
|
];
|
|
559
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* A relationship that gets several collections (#327) keeps its values: the id moves from
|
|
592
|
+
* `<field>` to `<field>_value`, with the first collection of `to` as `<field>_relation_to`
|
|
593
|
+
* (list the collection it had first). Back to one collection, the values of that collection
|
|
594
|
+
* stay and the others are removed, with a warning.
|
|
595
|
+
*/
|
|
596
|
+
relationMoves(prev) {
|
|
597
|
+
const q = (name) => this.q(name);
|
|
598
|
+
const text = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
599
|
+
const statements = [];
|
|
600
|
+
const lost = /* @__PURE__ */ new Set();
|
|
601
|
+
for (const model of tableModels(this.options.schema)) {
|
|
602
|
+
const old = snapshotTable(prev, model.name);
|
|
603
|
+
if (!old) continue;
|
|
604
|
+
const has = (column) => Object.hasOwn(old.columns ?? {}, column);
|
|
605
|
+
if (model.kind === "values" && model.valueField?.type === "relationship") {
|
|
606
|
+
const to = model.valueField.to;
|
|
607
|
+
if (typeof to !== "string" && !has("relation_to"))
|
|
608
|
+
statements.push(
|
|
609
|
+
`UPDATE ${q(model.name)} SET ${q("relation_to")} = ${text(to[0])} WHERE ${q("relation_to")} IS NULL`
|
|
610
|
+
);
|
|
611
|
+
if (typeof to === "string" && has("relation_to")) {
|
|
612
|
+
statements.push(
|
|
613
|
+
`DELETE FROM ${q(model.name)} WHERE ${q("relation_to")} IS NULL OR ${q("relation_to")} <> ${text(to)}`
|
|
614
|
+
);
|
|
615
|
+
lost.add(model.name);
|
|
616
|
+
}
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
for (const column of model.columns) {
|
|
620
|
+
const { field } = column;
|
|
621
|
+
if (field.type !== "relationship") continue;
|
|
622
|
+
if (column.part === "value" && typeof field.to !== "string") {
|
|
623
|
+
const before = column.column.replace(/_value(?=__|$)/, "");
|
|
624
|
+
const relationTo = column.column.replace(/_value(?=__|$)/, "_relation_to");
|
|
625
|
+
if (has(column.column) || !has(before)) continue;
|
|
626
|
+
statements.push(
|
|
627
|
+
`UPDATE ${q(model.name)} SET ${q(column.column)} = ${q(before)}, ${q(relationTo)} = ${text(field.to[0])} WHERE ${q(before)} IS NOT NULL`
|
|
628
|
+
);
|
|
629
|
+
} else if (column.part === void 0 && typeof field.to === "string") {
|
|
630
|
+
const value = column.column.replace(/(?=__|$)/, "_value");
|
|
631
|
+
const relationTo = column.column.replace(/(?=__|$)/, "_relation_to");
|
|
632
|
+
if (has(column.column) || !has(value) || !has(relationTo)) continue;
|
|
633
|
+
statements.push(
|
|
634
|
+
`UPDATE ${q(model.name)} SET ${q(column.column)} = ${q(value)} WHERE ${q(relationTo)} = ${text(field.to)}`
|
|
635
|
+
);
|
|
636
|
+
lost.add(`${model.name}.${column.column}`);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (lost.size > 0)
|
|
641
|
+
this.options.logger.warn(
|
|
642
|
+
`Links to other collections are removed from ${[...lost].join(", ")}: those relationships now have one collection.`
|
|
643
|
+
);
|
|
644
|
+
return statements;
|
|
645
|
+
}
|
|
560
646
|
/**
|
|
561
647
|
* A new default locale changes which locale the plain column holds (`title` is the default
|
|
562
648
|
* locale's, `title__en` another's). Moves the values so every locale keeps its own.
|
|
@@ -579,7 +665,7 @@ var Migrator = class {
|
|
|
579
665
|
if (!column.defaultLocale || !has(column.column)) continue;
|
|
580
666
|
const base = column.column;
|
|
581
667
|
const moved = model.columns.find(
|
|
582
|
-
(c) => c.path.join(".") === column.path.join(".") && c.locale === was.defaultLocale
|
|
668
|
+
(c) => c.path.join(".") === column.path.join(".") && c.part === column.part && c.locale === was.defaultLocale
|
|
583
669
|
);
|
|
584
670
|
if (moved && !has(moved.column)) keep.push(`${q(moved.column)} = ${q(base)}`);
|
|
585
671
|
clear.push(`${q(base)} = NULL`);
|
|
@@ -764,7 +850,7 @@ function extensionHint(error) {
|
|
|
764
850
|
|
|
765
851
|
// src/query.ts
|
|
766
852
|
import { QueryError } from "@easy-cms/core";
|
|
767
|
-
import { parseId, TRIGRAM_LIKE_MIN } from "@easy-cms/core/internal";
|
|
853
|
+
import { isPolymorphic as isPolymorphic2, parseId, TRIGRAM_LIKE_MIN } from "@easy-cms/core/internal";
|
|
768
854
|
import {
|
|
769
855
|
and as and2,
|
|
770
856
|
asc as asc2,
|
|
@@ -802,6 +888,14 @@ var SYSTEM_COLUMNS = {
|
|
|
802
888
|
updatedAt: "updated_at"
|
|
803
889
|
};
|
|
804
890
|
var col2 = (model, name) => model.table[name];
|
|
891
|
+
var PARTS = /* @__PURE__ */ new Set(["relationTo", "value"]);
|
|
892
|
+
function polymorphicPart(segment, shown, to) {
|
|
893
|
+
if (segment !== void 0 && PARTS.has(segment)) return segment;
|
|
894
|
+
if (segment !== void 0 && to.includes(segment)) return { collection: segment };
|
|
895
|
+
throw new QueryError(
|
|
896
|
+
`"${shown}" links to several collections: query "${shown}.relationTo" and "${shown}.value", or "${shown}.<collection>" (${to.map((t) => `"${shown}.${t}"`).join(", ")})`
|
|
897
|
+
);
|
|
898
|
+
}
|
|
805
899
|
var ID_FIELD = { name: "id", type: "relationship", to: "" };
|
|
806
900
|
var LIKE_TYPES = /* @__PURE__ */ new Set(["text", "textarea", "email", "slug", "select"]);
|
|
807
901
|
var JSON_TYPES = {
|
|
@@ -836,6 +930,16 @@ function resolveJsonValue(fields, rest, shown, localization, blocks) {
|
|
|
836
930
|
}
|
|
837
931
|
const inner = rest.slice(next);
|
|
838
932
|
const shownHere = [shown, ...rest.slice(0, next)].join(".");
|
|
933
|
+
if (isPolymorphic2(field)) {
|
|
934
|
+
if (inner.length > 1) throw new QueryError(`Cannot query inside "${shownHere}"`);
|
|
935
|
+
const part = polymorphicPart(inner[0], shownHere, field.to);
|
|
936
|
+
if (typeof part === "object")
|
|
937
|
+
throw new QueryError(
|
|
938
|
+
`Inside blocks, query "${shownHere}.relationTo" and "${shownHere}.value"`
|
|
939
|
+
);
|
|
940
|
+
const value = part === "value" ? { type: "integer", field } : { type: "text", field: void 0 };
|
|
941
|
+
return field.hasMany ? { lists: [path], path: [part], ...value } : { lists: [], path: [...path, part], ...value };
|
|
942
|
+
}
|
|
839
943
|
if ("hasMany" in field && field.hasMany === true) {
|
|
840
944
|
if (inner.length > 0) throw new QueryError(`Cannot query inside "${shownHere}"`);
|
|
841
945
|
return { lists: [path], path: [], type: JSON_TYPES[field.type] ?? "text", field };
|
|
@@ -903,6 +1007,33 @@ function resolvePath(model, segments, drafts, localization = null) {
|
|
|
903
1007
|
const value = resolveJsonValue(rows, rest, shown, localization, true);
|
|
904
1008
|
return { kind: "blocks", column: col2(model, column2.column), value };
|
|
905
1009
|
}
|
|
1010
|
+
if (isPolymorphic2(field)) {
|
|
1011
|
+
if (last + 1 < segments.length - 1)
|
|
1012
|
+
throw new QueryError(`Cannot query inside "${segments.slice(0, last + 2).join(".")}"`);
|
|
1013
|
+
const shownField = segments.slice(0, last + 1).join(".");
|
|
1014
|
+
const named = segments[last + 1];
|
|
1015
|
+
const part = named === void 0 ? "value" : polymorphicPart(named, shownField, field.to);
|
|
1016
|
+
const columnOfPart = (wanted) => {
|
|
1017
|
+
const found = model.columns.find(
|
|
1018
|
+
(c) => same(c) && c.part === wanted && (!field.localized || (locale === void 0 ? c.defaultLocale : c.locale === locale))
|
|
1019
|
+
);
|
|
1020
|
+
if (!found) throw new QueryError(`Unknown locale "${locale}" for "${shown}"`);
|
|
1021
|
+
return col2(model, found.column);
|
|
1022
|
+
};
|
|
1023
|
+
if (typeof part === "object")
|
|
1024
|
+
return {
|
|
1025
|
+
kind: "column",
|
|
1026
|
+
column: columnOfPart("value"),
|
|
1027
|
+
field,
|
|
1028
|
+
collection: { slug: part.collection, column: columnOfPart("relationTo") }
|
|
1029
|
+
};
|
|
1030
|
+
return {
|
|
1031
|
+
kind: "column",
|
|
1032
|
+
column: columnOfPart(part),
|
|
1033
|
+
field: part === "value" ? field : void 0,
|
|
1034
|
+
...named === void 0 ? { bare: field.to } : {}
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
906
1037
|
if (last < segments.length - 1) {
|
|
907
1038
|
throw new QueryError(`Cannot query inside "${shown}" (${field.type} field)`);
|
|
908
1039
|
}
|
|
@@ -1011,8 +1142,32 @@ var WhereBuilder = class {
|
|
|
1011
1142
|
);
|
|
1012
1143
|
const parts = entries.map(([op, value]) => {
|
|
1013
1144
|
if (!OPERATORS.has(op)) throw new QueryError(`Unknown operator "${op}" on "${path}"`);
|
|
1014
|
-
if (target.kind === "column")
|
|
1145
|
+
if (target.kind === "column") {
|
|
1146
|
+
if (target.bare && op !== "exists") polymorphicPart(void 0, path, target.bare);
|
|
1147
|
+
if (target.collection) {
|
|
1148
|
+
const { slug, column } = target.collection;
|
|
1149
|
+
const is = eq2(column, slug);
|
|
1150
|
+
if (op === "exists")
|
|
1151
|
+
return value === false ? or(isNull(column), ne(column, slug)) : is;
|
|
1152
|
+
if (op === "not_equals" || op === "not_in") {
|
|
1153
|
+
const positive = op === "not_equals" ? "equals" : "in";
|
|
1154
|
+
const match = operatorSQL(
|
|
1155
|
+
this.dialect,
|
|
1156
|
+
target.column,
|
|
1157
|
+
target.field,
|
|
1158
|
+
positive,
|
|
1159
|
+
value,
|
|
1160
|
+
path
|
|
1161
|
+
);
|
|
1162
|
+
return or(isNull(column), not(and2(is, match)));
|
|
1163
|
+
}
|
|
1164
|
+
return and2(
|
|
1165
|
+
is,
|
|
1166
|
+
operatorSQL(this.dialect, target.column, target.field, op, value, path)
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1015
1169
|
return operatorSQL(this.dialect, target.column, target.field, op, value, path);
|
|
1170
|
+
}
|
|
1016
1171
|
if (target.kind === "blocks") return this.blocks(target, op, value, path);
|
|
1017
1172
|
return this.child(model, target.child, target.rest, op, value, path, target.locale);
|
|
1018
1173
|
});
|
|
@@ -1068,18 +1223,25 @@ var WhereBuilder = class {
|
|
|
1068
1223
|
this.db.select({ one: sql`1` }).from(table.table).where(condition ? and2(link, condition) : link)
|
|
1069
1224
|
);
|
|
1070
1225
|
if (child.kind === "values") {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
);
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
);
|
|
1082
|
-
|
|
1226
|
+
let valueColumn = col2(table, "value");
|
|
1227
|
+
let valueField = table.valueField;
|
|
1228
|
+
let only;
|
|
1229
|
+
if (valueField && isPolymorphic2(valueField)) {
|
|
1230
|
+
if (rest.length > 1) throw new QueryError(`Cannot query inside "${path}"`);
|
|
1231
|
+
const shown = rest.length === 1 ? path.split(".").slice(0, -1).join(".") : path;
|
|
1232
|
+
const part = rest.length === 0 && op === "exists" ? "value" : polymorphicPart(rest[0], shown, valueField.to);
|
|
1233
|
+
if (part === "relationTo") {
|
|
1234
|
+
valueColumn = col2(table, "relation_to");
|
|
1235
|
+
valueField = void 0;
|
|
1236
|
+
} else if (typeof part === "object") only = eq2(col2(table, "relation_to"), part.collection);
|
|
1237
|
+
} else if (rest.length > 0) throw new QueryError(`Cannot query inside "${path}"`);
|
|
1238
|
+
if (op === "exists") return value === false ? not(subquery(only)) : subquery(only);
|
|
1239
|
+
const matching = (operator) => subquery(
|
|
1240
|
+
and2(only, operatorSQL(this.dialect, valueColumn, valueField, operator, value, path))
|
|
1241
|
+
);
|
|
1242
|
+
if (op === "not_equals") return not(matching("equals"));
|
|
1243
|
+
if (op === "not_in") return not(matching("in"));
|
|
1244
|
+
return matching(op);
|
|
1083
1245
|
}
|
|
1084
1246
|
if (rest.length === 0) {
|
|
1085
1247
|
if (op !== "exists") throw new QueryError(`"${path}" is an array; query one of its fields`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easy-cms/drizzle",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
4
4
|
"description": "Shared Drizzle ORM layer for Easy CMS database adapters",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"drizzle-orm": "0.45.4"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@easy-cms/core": "^1.
|
|
26
|
+
"@easy-cms/core": "^1.29.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@easy-cms/core": "^1.
|
|
29
|
+
"@easy-cms/core": "^1.29.0"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public"
|