rimecms 0.29.0 → 0.30.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/adapter-sqlite/area.server.js +8 -8
- package/dist/adapter-sqlite/generate-schema/column.server.d.ts +13 -0
- package/dist/adapter-sqlite/generate-schema/column.server.js +77 -0
- package/dist/adapter-sqlite/generate-schema/index.server.js +7 -12
- package/dist/adapter-sqlite/generate-schema/root.server.js +35 -39
- package/dist/adapter-sqlite/generate-schema/templates.server.d.ts +12 -0
- package/dist/adapter-sqlite/generate-schema/templates.server.js +19 -0
- package/dist/adapter-sqlite/index.server.d.ts +1 -2
- package/dist/adapter-sqlite/index.server.js +0 -2
- package/dist/adapter-sqlite/relations.server.js +6 -1
- package/dist/adapter-sqlite/util.server.d.ts +1 -6
- package/dist/adapter-sqlite/util.server.js +6 -0
- package/dist/adapter-sqlite/where.server.js +17 -16
- package/dist/adapter-sqlite/with.server.js +9 -9
- package/dist/core/collections/auth/fields.d.ts +2 -182
- package/dist/core/collections/config/augment-auth.server.js +1 -1
- package/dist/core/collections/config/augment-nested.server.js +1 -1
- package/dist/core/collections/config/augment-upload.js +2 -2
- package/dist/core/collections/config/augment-upload.server.js +4 -1
- package/dist/core/collections/operations/duplicate.js +30 -11
- package/dist/core/collections/operations/updateById.js +6 -5
- package/dist/core/collections/rest/duplicate.server.js +7 -3
- package/dist/core/collections/upload/disk/delete.server.d.ts +1 -1
- package/dist/core/collections/upload/disk/delete.server.js +48 -1
- package/dist/core/collections/upload/hooks/clean-up-files.server.js +2 -2
- package/dist/core/collections/upload/hooks/extract-path.server.d.ts +1 -1
- package/dist/core/collections/upload/hooks/extract-path.server.js +1 -1
- package/dist/core/collections/upload/hooks/process-file-upload.server.js +3 -3
- package/dist/core/config/server/validate.server.js +50 -30
- package/dist/core/config/shared/find-thumbnail.js +12 -12
- package/dist/core/config/shared/find-title.js +13 -13
- package/dist/core/config/shared/upload-directories.js +1 -1
- package/dist/core/constant.server.d.ts +1 -0
- package/dist/core/constant.server.js +2 -0
- package/dist/core/dev/cache/index.server.js +9 -9
- package/dist/core/dev/cli/build/index.js +2 -2
- package/dist/core/dev/cli/clear/index.server.js +2 -1
- package/dist/core/dev/cli/generate/index.server.js +3 -2
- package/dist/core/dev/cli/init/index.server.js +1 -1
- package/dist/core/dev/generate/routes/index.server.js +2 -2
- package/dist/core/dev/generate/types/index.server.js +17 -17
- package/dist/core/dev/vite/index.server.js +21 -5
- package/dist/core/fields/builders/boolean-builder.d.ts +3 -1
- package/dist/core/fields/builders/boolean-builder.js +3 -0
- package/dist/core/fields/builders/field-builder.d.ts +35 -2
- package/dist/core/fields/builders/field-builder.js +33 -2
- package/dist/core/fields/builders/form-field-builder.d.ts +71 -12
- package/dist/core/fields/builders/form-field-builder.js +96 -6
- package/dist/core/fields/builders/select-builder.d.ts +4 -1
- package/dist/core/fields/builders/select-builder.js +3 -0
- package/dist/core/fields/util.d.ts +8 -16
- package/dist/core/fields/util.js +49 -83
- package/dist/core/handlers/routes.server.js +16 -3
- package/dist/core/naming.d.ts +34 -0
- package/dist/core/naming.js +39 -0
- package/dist/core/operations/blocks/diff.server.js +1 -1
- package/dist/core/operations/blocks/extract.server.js +1 -1
- package/dist/core/operations/configMap/buildTreeMap.d.ts +3 -2
- package/dist/core/operations/configMap/buildTreeMap.js +1 -1
- package/dist/core/operations/configMap/index.d.ts +2 -1
- package/dist/core/operations/configMap/index.js +13 -13
- package/dist/core/operations/configMap/types.d.ts +2 -2
- package/dist/core/operations/hooks/before-read/process-document-fields.server.js +14 -17
- package/dist/core/operations/hooks/before-upsert/data-config-map.server.js +1 -1
- package/dist/core/operations/hooks/before-upsert/original-config-map.server.js +1 -1
- package/dist/core/operations/hooks/before-upsert/set-default-values.server.d.ts +2 -4
- package/dist/core/operations/hooks/before-upsert/set-default-values.server.js +10 -15
- package/dist/core/operations/hooks/before-upsert/validate-fields.server.js +49 -31
- package/dist/core/operations/relations/extract.server.js +5 -5
- package/dist/core/operations/shared/fallback-data-from-original.js +2 -2
- package/dist/core/operations/tree/diff.server.js +1 -1
- package/dist/core/operations/tree/extract.server.js +1 -1
- package/dist/core/plugins/cache/cache.server.js +3 -3
- package/dist/fields/blocks/component/AddBlockButton.svelte +7 -7
- package/dist/fields/blocks/component/AddBlockButton.svelte.d.ts +2 -2
- package/dist/fields/blocks/component/Blocks.svelte +6 -7
- package/dist/fields/blocks/component/props.d.ts +2 -2
- package/dist/fields/blocks/index.d.ts +1 -1
- package/dist/fields/blocks/index.js +3 -3
- package/dist/fields/blocks/index.server.js +1 -1
- package/dist/fields/checkbox/component/Checkbox.svelte +2 -2
- package/dist/fields/checkbox/component/props.d.ts +2 -2
- package/dist/fields/checkbox/index.server.d.ts +1 -2
- package/dist/fields/checkbox/index.server.js +1 -10
- package/dist/fields/combobox/component/ComboBox.svelte +3 -3
- package/dist/fields/combobox/component/props.d.ts +2 -2
- package/dist/fields/combobox/index.server.d.ts +1 -2
- package/dist/fields/combobox/index.server.js +2 -11
- package/dist/fields/component/index.d.ts +1 -1
- package/dist/fields/date/component/Date.svelte +4 -4
- package/dist/fields/date/component/Date.svelte.d.ts +2 -2
- package/dist/fields/date/index.d.ts +3 -1
- package/dist/fields/date/index.js +3 -0
- package/dist/fields/date/index.server.d.ts +1 -2
- package/dist/fields/date/index.server.js +1 -10
- package/dist/fields/email/component/Email.svelte +5 -6
- package/dist/fields/email/component/props.d.ts +2 -3
- package/dist/fields/email/index.d.ts +3 -2
- package/dist/fields/email/index.js +4 -1
- package/dist/fields/email/index.server.d.ts +0 -3
- package/dist/fields/email/index.server.js +0 -9
- package/dist/fields/group/component/Group.svelte +9 -15
- package/dist/fields/group/component/Group.svelte.d.ts +2 -2
- package/dist/fields/group/index.d.ts +4 -2
- package/dist/fields/group/index.server.js +2 -2
- package/dist/fields/index.server.d.ts +1 -4
- package/dist/fields/index.server.js +17 -13
- package/dist/fields/link/component/Link.svelte +5 -5
- package/dist/fields/link/component/props.d.ts +2 -2
- package/dist/fields/link/index.d.ts +4 -1
- package/dist/fields/link/index.js +9 -10
- package/dist/fields/link/runtime.d.ts +2 -0
- package/dist/fields/link/runtime.js +1 -0
- package/dist/fields/link/{index.server.d.ts → runtime.server.d.ts} +1 -2
- package/dist/fields/link/{index.server.js → runtime.server.js} +2 -11
- package/dist/fields/number/component/Number.svelte +6 -6
- package/dist/fields/number/component/props.d.ts +2 -2
- package/dist/fields/number/index.d.ts +4 -10
- package/dist/fields/number/index.js +3 -4
- package/dist/fields/number/index.server.d.ts +1 -2
- package/dist/fields/number/index.server.js +1 -10
- package/dist/fields/radio/component/Radio.svelte +6 -7
- package/dist/fields/radio/component/props.d.ts +2 -2
- package/dist/fields/radio/index.server.d.ts +1 -2
- package/dist/fields/radio/index.server.js +2 -11
- package/dist/fields/relation/component/Relation.svelte +18 -14
- package/dist/fields/relation/component/Relation.svelte.d.ts +2 -2
- package/dist/fields/relation/index.d.ts +7 -4
- package/dist/fields/relation/index.js +8 -47
- package/dist/fields/relation/runtime.d.ts +5 -0
- package/dist/fields/relation/runtime.js +4 -0
- package/dist/fields/relation/runtime.server.d.ts +8 -0
- package/dist/fields/relation/runtime.server.js +49 -0
- package/dist/fields/rich-text/component/RichText.svelte +5 -5
- package/dist/fields/rich-text/component/props.d.ts +2 -2
- package/dist/fields/rich-text/core/features/fields/fields.svelte +2 -2
- package/dist/fields/rich-text/index.d.ts +2 -0
- package/dist/fields/rich-text/index.js +3 -0
- package/dist/fields/rich-text/index.server.d.ts +1 -2
- package/dist/fields/rich-text/index.server.js +1 -10
- package/dist/fields/select/component/Select.svelte +16 -16
- package/dist/fields/select/component/props.d.ts +2 -2
- package/dist/fields/select/index.d.ts +2 -0
- package/dist/fields/select/index.js +3 -0
- package/dist/fields/select/index.server.d.ts +1 -2
- package/dist/fields/select/index.server.js +2 -17
- package/dist/fields/slug/component/Slug.svelte +14 -10
- package/dist/fields/slug/component/Slug.svelte.d.ts +2 -2
- package/dist/fields/slug/index.d.ts +5 -2
- package/dist/fields/slug/index.js +3 -0
- package/dist/fields/slug/index.server.d.ts +1 -2
- package/dist/fields/slug/index.server.js +1 -10
- package/dist/fields/tabs/component/Tabs.svelte +15 -15
- package/dist/fields/tabs/component/Tabs.svelte.d.ts +2 -2
- package/dist/fields/tabs/index.d.ts +4 -16
- package/dist/fields/tabs/index.js +1 -8
- package/dist/fields/tabs/index.server.js +3 -3
- package/dist/fields/text/component/Text.svelte +5 -5
- package/dist/fields/text/component/props.d.ts +2 -3
- package/dist/fields/text/index.d.ts +4 -10
- package/dist/fields/text/index.js +3 -4
- package/dist/fields/text/index.server.d.ts +1 -2
- package/dist/fields/text/index.server.js +1 -10
- package/dist/fields/textarea/component/TextArea.svelte +3 -3
- package/dist/fields/textarea/component/props.d.ts +2 -2
- package/dist/fields/textarea/index.d.ts +4 -1
- package/dist/fields/textarea/index.js +3 -0
- package/dist/fields/textarea/index.server.d.ts +1 -2
- package/dist/fields/textarea/index.server.js +1 -10
- package/dist/fields/time/component/Time.svelte +5 -5
- package/dist/fields/time/component/Time.svelte.d.ts +1 -1
- package/dist/fields/time/component/props.d.ts +2 -2
- package/dist/fields/time/index.d.ts +2 -0
- package/dist/fields/time/index.js +3 -0
- package/dist/fields/time/index.server.d.ts +1 -2
- package/dist/fields/time/index.server.js +1 -10
- package/dist/fields/toggle/component/Toggle.svelte +3 -3
- package/dist/fields/toggle/component/Toggle.svelte.d.ts +1 -1
- package/dist/fields/toggle/component/props.d.ts +2 -2
- package/dist/fields/toggle/index.d.ts +2 -1
- package/dist/fields/toggle/index.server.d.ts +1 -2
- package/dist/fields/toggle/index.server.js +1 -10
- package/dist/fields/tree/component/AddItemButton.svelte +1 -2
- package/dist/fields/tree/component/Tree.svelte +6 -6
- package/dist/fields/tree/component/TreeBlock.svelte +5 -12
- package/dist/fields/tree/component/props.d.ts +3 -3
- package/dist/fields/tree/index.d.ts +3 -1
- package/dist/fields/tree/index.js +2 -2
- package/dist/fields/types.d.ts +11 -5
- package/dist/panel/components/fields/FieldsPreview.svelte +4 -5
- package/dist/panel/components/fields/Hint.svelte +5 -4
- package/dist/panel/components/fields/Hint.svelte.d.ts +3 -2
- package/dist/panel/components/fields/Label.svelte +6 -11
- package/dist/panel/components/fields/Label.svelte.d.ts +3 -2
- package/dist/panel/components/fields/LabelFor.svelte +4 -4
- package/dist/panel/components/fields/LabelFor.svelte.d.ts +2 -1
- package/dist/panel/components/fields/RenderFields.svelte +11 -16
- package/dist/panel/components/fields/{root.svelte.d.ts → fieldset.svelte.d.ts} +1 -1
- package/dist/panel/components/fields/{root.svelte.js → fieldset.svelte.js} +1 -1
- package/dist/panel/components/fields/index.d.ts +5 -5
- package/dist/panel/components/fields/index.js +2 -2
- package/dist/panel/components/sections/document/AuthFooter.svelte +2 -7
- package/dist/panel/components/sections/live/LiveEditPanel.svelte +2 -2
- package/dist/panel/context/collection.svelte.js +9 -9
- package/dist/panel/context/documentForm.svelte.d.ts +8 -21
- package/dist/panel/context/documentForm.svelte.js +45 -52
- package/dist/panel/context/form.svelte.d.ts +4 -3
- package/dist/panel/context/form.svelte.js +14 -16
- package/dist/panel/pages/auth/fields.d.ts +4 -4
- package/dist/panel/pages/auth/fields.js +6 -22
- package/dist/panel/pages/auth/reset-password/ResetPassword.svelte +3 -10
- package/dist/util/doc.js +15 -17
- package/package.json +3 -2
- package/dist/fields/relation/index.server.d.ts +0 -4
- package/dist/fields/relation/index.server.js +0 -13
|
@@ -3,10 +3,14 @@ export class FieldBuilder {
|
|
|
3
3
|
_metaUrl;
|
|
4
4
|
constructor(type) {
|
|
5
5
|
this.field = {
|
|
6
|
+
name: '',
|
|
6
7
|
type,
|
|
7
8
|
live: true
|
|
8
9
|
};
|
|
9
10
|
}
|
|
11
|
+
get name() {
|
|
12
|
+
return this.field.name;
|
|
13
|
+
}
|
|
10
14
|
className(str) {
|
|
11
15
|
this.field.className = str;
|
|
12
16
|
return this;
|
|
@@ -25,8 +29,35 @@ export class FieldBuilder {
|
|
|
25
29
|
get type() {
|
|
26
30
|
return this.field.type;
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Raw field data, plus the couple of properties that a bare `this.field`
|
|
34
|
+
* read can't give you: `localized`/`root` default to `false` here since
|
|
35
|
+
* only FormFieldBuilder fields ever set them — container fields like Tabs
|
|
36
|
+
* answer `false` rather than making every caller check
|
|
37
|
+
* `instanceof FormFieldBuilder` first just to ask this one question.
|
|
38
|
+
* Everything else on `T` (Tabs' `tabs`, Blocks' `blocks`, ...) comes
|
|
39
|
+
* through unchanged via the spread — no per-subclass override needed.
|
|
40
|
+
*/
|
|
41
|
+
get get() {
|
|
42
|
+
return { ...this.field, localized: false, root: false };
|
|
43
|
+
}
|
|
44
|
+
/** Behavior the builder runs on your behalf (invoking a stored function) —
|
|
45
|
+
* see `.get` for plain data reads. Fields without an access concept
|
|
46
|
+
* (Tabs) default every check to allowed, matching how the field-less case
|
|
47
|
+
* already behaved. Params are unused here but must match FormFieldBuilder's
|
|
48
|
+
* override signature — TS checks generic-constraint satisfaction
|
|
49
|
+
* (`T extends FieldBuilder<any>`) strictly, not with the bivariant
|
|
50
|
+
* leniency normal overrides get, so a param-less base signature breaks
|
|
51
|
+
* assignability everywhere. */
|
|
52
|
+
get run() {
|
|
53
|
+
return {
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
55
|
+
canRead: (..._args) => true,
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
|
+
canCreate: (..._args) => true,
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
59
|
+
canUpdate: (..._args) => true
|
|
60
|
+
};
|
|
30
61
|
}
|
|
31
62
|
get component() {
|
|
32
63
|
return null;
|
|
@@ -1,16 +1,54 @@
|
|
|
1
1
|
import type { FieldPanelTableConfig } from '../../../types.js';
|
|
2
2
|
import type { Dic } from '../../../util/types.js';
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
import type { RequestEvent } from '@sveltejs/kit';
|
|
4
|
+
import type { FieldAccess, FieldHook, FieldHookClient, FieldHookContext, FieldHookShared, FieldValidationFunc, FieldWidth, FormField } from '../../../fields/types.js';
|
|
5
|
+
import { FieldBuilder, type FieldRun } from './field-builder.js';
|
|
6
|
+
/** Adapter-agnostic storage primitive — column syntax only, not default-value semantics. */
|
|
7
|
+
export type DataType = 'text' | 'boolean' | 'number' | 'timestamp' | 'json';
|
|
8
|
+
/** Method-syntax, same reasoning as `FieldRun` — keeps `run`'s params
|
|
9
|
+
* bivariant across concrete field types so e.g. `SlugFieldBuilder` still
|
|
10
|
+
* satisfies a prop typed `FormFieldBuilder<FormField>`. */
|
|
11
|
+
export type FormFieldRun<T extends FormField> = FieldRun & {
|
|
12
|
+
isEmpty(value: unknown): boolean;
|
|
13
|
+
validate(value: unknown, context: Parameters<FieldValidationFunc<T>>[1]): true | string;
|
|
14
|
+
condition(doc: Dic, siblings: Dic): boolean;
|
|
15
|
+
onChange(value: unknown, context: Parameters<FieldHookClient>[1]): void;
|
|
16
|
+
beforeRead(value: unknown, context: Omit<FieldHookContext<T>, 'config'>): Promise<any>;
|
|
17
|
+
beforeSave(value: unknown, context: FieldHookContext<T>): Promise<any>;
|
|
18
|
+
beforeValidate(value: unknown, context: Parameters<FieldHookShared>[1]): Promise<any>;
|
|
19
|
+
/** Resolves `field.defaultValue` — calling it if it's a `DefaultValueFn`,
|
|
20
|
+
* returning it as-is otherwise. Every field type stores `defaultValue` as
|
|
21
|
+
* plain data (never a fluent-setter name collision on `.field` itself),
|
|
22
|
+
* but several concrete builders (Select, Link, Slug, Relation) *do* expose
|
|
23
|
+
* a `.defaultValue(...)` fluent setter — bare `config.defaultValue` on
|
|
24
|
+
* those would silently return that setter, not the stored value. */
|
|
25
|
+
defaultValue(context?: {
|
|
26
|
+
event?: RequestEvent;
|
|
27
|
+
}): unknown;
|
|
28
|
+
};
|
|
29
|
+
export type ReferentialAction = 'cascade' | 'set null' | 'restrict' | 'no action';
|
|
30
|
+
export type FieldReferenceOptions = {
|
|
31
|
+
onDelete?: ReferentialAction;
|
|
32
|
+
onUpdate?: ReferentialAction;
|
|
33
|
+
/** Referenced table is this field's own table (self-FK); adapters need this
|
|
34
|
+
* to emit a `(): any =>` accessor and avoid a TS circular-declaration error. */
|
|
35
|
+
selfReferencing?: boolean;
|
|
36
|
+
};
|
|
37
|
+
export type FieldReference = FieldReferenceOptions & {
|
|
38
|
+
table: string;
|
|
39
|
+
};
|
|
40
|
+
export declare class FormFieldBuilder<T extends FormField = FormField> extends FieldBuilder<T> {
|
|
41
|
+
/** Every concrete leaf field builder is expected to implement a
|
|
42
|
+
* `get dataType(): DataType` accessor (see e.g. `$lib/fields/text/index.ts`).
|
|
43
|
+
* Not declared here — TS doesn't allow `declare` on accessors in this
|
|
44
|
+
* project's config, and a plain base field would conflict with subclasses
|
|
45
|
+
* that need a computed getter (e.g. `select`, whose dataType depends on
|
|
46
|
+
* `many`). Container builders (Group/Tabs/Blocks/Tree) never get asked,
|
|
47
|
+
* since the adapter's tree-walker special-cases them before reaching the
|
|
48
|
+
* generic column-rendering branch; `column.server.ts` reads `.dataType`
|
|
49
|
+
* via a narrow cast for the same reason it already casts `unique`. */
|
|
50
|
+
_references: FieldReference | null;
|
|
12
51
|
constructor(name: string, type: string);
|
|
13
|
-
get name(): string;
|
|
14
52
|
label(label: string): this;
|
|
15
53
|
hidden(): this;
|
|
16
54
|
localized(): this;
|
|
@@ -19,17 +57,38 @@ export declare class FormFieldBuilder<T extends FormField> extends FieldBuilder<
|
|
|
19
57
|
table(params?: FieldPanelTableConfig | number): this;
|
|
20
58
|
width(value: FieldWidth): this;
|
|
21
59
|
required(bool?: boolean): this;
|
|
60
|
+
/**
|
|
61
|
+
* Force the field to be on the root table — usefull for fields that
|
|
62
|
+
* should not be versioned (ex: _parent for nested structures should
|
|
63
|
+
* always be on the root table to prevent different versions from having
|
|
64
|
+
* different parents).
|
|
65
|
+
*/
|
|
66
|
+
_root(): this;
|
|
67
|
+
/** `label`/`localized`/`root`/`required` are the only properties that need
|
|
68
|
+
* anything beyond a plain `this.field` read (a fallback default, or a
|
|
69
|
+
* boolean coercion) — everything else a concrete field type adds
|
|
70
|
+
* (Group's `fields`, Relation's `relationTo`, Select's `options`, ...)
|
|
71
|
+
* comes through unchanged via the spread, no per-subclass override needed. */
|
|
72
|
+
get get(): T & {
|
|
73
|
+
localized: boolean;
|
|
74
|
+
root: boolean;
|
|
75
|
+
label: string;
|
|
76
|
+
required: boolean;
|
|
77
|
+
};
|
|
22
78
|
access(access: {
|
|
23
79
|
create?: FieldAccess;
|
|
24
80
|
read?: FieldAccess;
|
|
25
81
|
update?: FieldAccess;
|
|
26
82
|
}): this;
|
|
27
83
|
onChange(hook: FieldHookClient): this;
|
|
84
|
+
/** Behavior the builder runs on your behalf — invoking a stored function or
|
|
85
|
+
* hook list, not a data read (see `.get` for that). */
|
|
86
|
+
get run(): FormFieldRun<T>;
|
|
28
87
|
hint(hint: string): this;
|
|
29
88
|
clone(): typeof this;
|
|
30
|
-
$
|
|
89
|
+
/** Server-side schema concern, same family as $beforeRead/$beforeSave. */
|
|
90
|
+
$references(table: string, options?: FieldReferenceOptions): this;
|
|
31
91
|
$beforeRead(hook: FieldHook<T>): this;
|
|
32
92
|
$beforeSave(hook: FieldHook<T>): this;
|
|
33
93
|
beforeValidate(hook: FieldHookShared): this;
|
|
34
94
|
}
|
|
35
|
-
export {};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { capitalize } from '../../../util/string.js';
|
|
1
2
|
import cloneDeep from 'clone-deep';
|
|
2
3
|
import { FieldBuilder } from './field-builder.js';
|
|
3
4
|
export class FormFieldBuilder extends FieldBuilder {
|
|
4
|
-
|
|
5
|
+
/** Every concrete leaf field builder is expected to implement a
|
|
6
|
+
* `get dataType(): DataType` accessor (see e.g. `$lib/fields/text/index.ts`).
|
|
7
|
+
* Not declared here — TS doesn't allow `declare` on accessors in this
|
|
8
|
+
* project's config, and a plain base field would conflict with subclasses
|
|
9
|
+
* that need a computed getter (e.g. `select`, whose dataType depends on
|
|
10
|
+
* `many`). Container builders (Group/Tabs/Blocks/Tree) never get asked,
|
|
11
|
+
* since the adapter's tree-walker special-cases them before reaching the
|
|
12
|
+
* generic column-rendering branch; `column.server.ts` reads `.dataType`
|
|
13
|
+
* via a narrow cast for the same reason it already casts `unique`. */
|
|
14
|
+
_references = null;
|
|
5
15
|
constructor(name, type) {
|
|
6
16
|
super(type);
|
|
7
17
|
this.field.name = name;
|
|
@@ -15,9 +25,6 @@ export class FormFieldBuilder extends FieldBuilder {
|
|
|
15
25
|
};
|
|
16
26
|
return this;
|
|
17
27
|
}
|
|
18
|
-
get name() {
|
|
19
|
-
return this.field.name;
|
|
20
|
-
}
|
|
21
28
|
label(label) {
|
|
22
29
|
this.field.label = label;
|
|
23
30
|
return this;
|
|
@@ -58,6 +65,30 @@ export class FormFieldBuilder extends FieldBuilder {
|
|
|
58
65
|
this.field.required = typeof bool === 'undefined' ? true : bool;
|
|
59
66
|
return this;
|
|
60
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Force the field to be on the root table — usefull for fields that
|
|
70
|
+
* should not be versioned (ex: _parent for nested structures should
|
|
71
|
+
* always be on the root table to prevent different versions from having
|
|
72
|
+
* different parents).
|
|
73
|
+
*/
|
|
74
|
+
_root() {
|
|
75
|
+
this.field._root = true;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
/** `label`/`localized`/`root`/`required` are the only properties that need
|
|
79
|
+
* anything beyond a plain `this.field` read (a fallback default, or a
|
|
80
|
+
* boolean coercion) — everything else a concrete field type adds
|
|
81
|
+
* (Group's `fields`, Relation's `relationTo`, Select's `options`, ...)
|
|
82
|
+
* comes through unchanged via the spread, no per-subclass override needed. */
|
|
83
|
+
get get() {
|
|
84
|
+
return {
|
|
85
|
+
...this.field,
|
|
86
|
+
localized: !!this.field.localized,
|
|
87
|
+
root: !!this.field._root,
|
|
88
|
+
label: this.field.label || capitalize(this.field.name),
|
|
89
|
+
required: !!this.field.required
|
|
90
|
+
};
|
|
91
|
+
}
|
|
61
92
|
access(access) {
|
|
62
93
|
this.field.access = { ...this.field.access, ...access };
|
|
63
94
|
return this;
|
|
@@ -67,6 +98,64 @@ export class FormFieldBuilder extends FieldBuilder {
|
|
|
67
98
|
this.field.hooks.onChange.push(hook);
|
|
68
99
|
return this;
|
|
69
100
|
}
|
|
101
|
+
/** Behavior the builder runs on your behalf — invoking a stored function or
|
|
102
|
+
* hook list, not a data read (see `.get` for that). */
|
|
103
|
+
get run() {
|
|
104
|
+
return {
|
|
105
|
+
isEmpty: (value) => this.field.isEmpty(value),
|
|
106
|
+
validate: (value, context) => {
|
|
107
|
+
if (this.field.validate) {
|
|
108
|
+
return this.field.validate(value, { ...context, config: this.field });
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
},
|
|
112
|
+
condition: (doc, siblings) => {
|
|
113
|
+
if (this.field.condition) {
|
|
114
|
+
try {
|
|
115
|
+
return this.field.condition(doc, siblings);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.error(err.message);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
},
|
|
124
|
+
canRead: (...args) => !!this.field.access?.read?.(...args),
|
|
125
|
+
canCreate: (...args) => !!this.field.access?.create?.(...args),
|
|
126
|
+
canUpdate: (...args) => !!this.field.access?.update?.(...args),
|
|
127
|
+
onChange: (value, context) => {
|
|
128
|
+
for (const hook of this.field.hooks?.onChange ?? []) {
|
|
129
|
+
hook(value, context);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
beforeRead: async (value, context) => {
|
|
133
|
+
let result = value;
|
|
134
|
+
for (const hook of this.field.hooks?.beforeRead ?? []) {
|
|
135
|
+
result = await hook(result, { ...context, config: this.field });
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
},
|
|
139
|
+
beforeSave: async (value, context) => {
|
|
140
|
+
let result = value;
|
|
141
|
+
for (const hook of this.field.hooks?.beforeSave ?? []) {
|
|
142
|
+
result = await hook(result, { ...context, config: this.field });
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
},
|
|
146
|
+
beforeValidate: async (value, context) => {
|
|
147
|
+
let result = value;
|
|
148
|
+
for (const hook of this.field.hooks?.beforeValidate ?? []) {
|
|
149
|
+
result = await hook(result, { ...context, config: this.field });
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
},
|
|
153
|
+
defaultValue: (context = {}) => {
|
|
154
|
+
const value = this.field.defaultValue;
|
|
155
|
+
return typeof value === 'function' ? value(context) : value;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
70
159
|
hint(hint) {
|
|
71
160
|
this.field.hint = hint;
|
|
72
161
|
return this;
|
|
@@ -83,8 +172,9 @@ export class FormFieldBuilder extends FieldBuilder {
|
|
|
83
172
|
clone.field = cloneDeep(this.field);
|
|
84
173
|
return clone;
|
|
85
174
|
}
|
|
86
|
-
$
|
|
87
|
-
|
|
175
|
+
/** Server-side schema concern, same family as $beforeRead/$beforeSave. */
|
|
176
|
+
$references(table, options) {
|
|
177
|
+
this._references = { table, ...options };
|
|
88
178
|
return this;
|
|
89
179
|
}
|
|
90
180
|
$beforeRead(hook) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { DataType } from './form-field-builder.js';
|
|
1
2
|
import { FormFieldBuilder } from './form-field-builder.js';
|
|
2
|
-
import type { DefaultValueFn, FormField, Option } from '../../../fields/types.js';
|
|
3
|
+
import type { DefaultValueFn, FieldValidationFunc, FormField, Option } from '../../../fields/types.js';
|
|
3
4
|
type FieldWithOptions = FormField & {
|
|
4
5
|
options: Option[];
|
|
5
6
|
defaultValue?: (string | DefaultValueFn<string>) | (string[] | DefaultValueFn<string[]>);
|
|
6
7
|
many?: boolean;
|
|
8
|
+
validate?: FieldValidationFunc<FieldWithOptions>;
|
|
7
9
|
};
|
|
8
10
|
declare class PickFieldBuilder<T extends FieldWithOptions = FieldWithOptions> extends FormFieldBuilder<T> {
|
|
9
11
|
constructor(name: string, type: string);
|
|
@@ -17,6 +19,7 @@ declare class PickFieldBuilder<T extends FieldWithOptions = FieldWithOptions> ex
|
|
|
17
19
|
}
|
|
18
20
|
export declare class PickOneFieldBuilder<T extends FieldWithOptions = FieldWithOptions> extends PickFieldBuilder<T> {
|
|
19
21
|
defaultValue(value: string | DefaultValueFn<string>): this;
|
|
22
|
+
get dataType(): DataType;
|
|
20
23
|
}
|
|
21
24
|
export declare class PickManyFieldBuilder<T extends FieldWithOptions = FieldWithOptions> extends PickFieldBuilder<T> {
|
|
22
25
|
defaultValue(value: string[] | DefaultValueFn<string[]>): this;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Field, FormField, SeparatorField } from '../../fields/types.js';
|
|
2
2
|
import type { Dic } from '../../util/types.js';
|
|
3
|
+
import type { FormFieldBuilder } from './builders/form-field-builder.js';
|
|
3
4
|
import type { FieldBuilder } from './builders/index.js';
|
|
4
5
|
/**
|
|
5
6
|
* Checks if a field is a presentative field (currently only separator fields).
|
|
@@ -10,24 +11,15 @@ export declare const isPresentative: (field: Field) => field is SeparatorField;
|
|
|
10
11
|
* Checks if a field is a form field (has a name property).
|
|
11
12
|
* Form fields are fields that can store data in documents.
|
|
12
13
|
*/
|
|
13
|
-
export declare const isFormField: (field:
|
|
14
|
+
export declare const isFormField: <T extends Field>(field: FieldBuilder<T>) => field is FormFieldBuilder<T & FormField>;
|
|
14
15
|
/**
|
|
15
16
|
* Checks if a form field is not hidden.
|
|
16
17
|
*/
|
|
17
|
-
export declare const isNotHidden: (field:
|
|
18
|
+
export declare const isNotHidden: <T extends FormField>(field: FormFieldBuilder<T>) => boolean;
|
|
18
19
|
/**
|
|
19
20
|
* Checks if a field has live updates enabled.
|
|
20
21
|
*/
|
|
21
22
|
export declare const isLiveField: (field: Field) => boolean | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* Flattens a nested field structure into an array of form fields.
|
|
24
|
-
* Handles special field types like tabs, tree, and blocks.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* // Flattens a tabs field into its constituent form fields
|
|
28
|
-
* const fields = [tabsField].reduce(toFormFields, []);
|
|
29
|
-
*/
|
|
30
|
-
export declare function toFormFields(prev: any[], curr: any): any;
|
|
31
23
|
/**
|
|
32
24
|
* Creates an object with empty values based on field configurations.
|
|
33
25
|
* Uses defaultValue if specified, otherwise undefined.
|
|
@@ -43,7 +35,7 @@ export declare function toFormFields(prev: any[], curr: any): any;
|
|
|
43
35
|
* ]}
|
|
44
36
|
* ]);
|
|
45
37
|
*/
|
|
46
|
-
export declare const emptyValuesFromFieldConfig: <T extends
|
|
38
|
+
export declare const emptyValuesFromFieldConfig: <T extends FormFieldBuilder>(arr: T[]) => Dic;
|
|
47
39
|
/**
|
|
48
40
|
* Converts a path with numeric indices to a regex pattern
|
|
49
41
|
* Numbers between dots or between dot and colon are converted to \d+
|
|
@@ -59,13 +51,13 @@ export declare function pathToRegex(path: string): RegExp;
|
|
|
59
51
|
* Retrieves a field configuration by its dot-notation path
|
|
60
52
|
* @example
|
|
61
53
|
* // Get the title field in the attributes group
|
|
62
|
-
* const titleField =
|
|
54
|
+
* const titleField = getFieldAtPath('attributes.title', collection.fields);
|
|
63
55
|
*
|
|
64
56
|
* // Get the title field in a specific block
|
|
65
|
-
* const titleField =
|
|
57
|
+
* const titleField = getFieldAtPath('attributes.layout.2:blockType.title', collection.fields);
|
|
66
58
|
*
|
|
67
59
|
*/
|
|
68
|
-
export declare const
|
|
60
|
+
export declare const getFieldAtPath: (path: string, fields: FieldBuilder[]) => FormFieldBuilder<FormField> | undefined;
|
|
69
61
|
/**
|
|
70
62
|
* Traverses a FieldBuilder[] tree and returns the subset of builders to pass to
|
|
71
63
|
* RenderFields, along with the path prefix those builders should be rendered at.
|
|
@@ -74,7 +66,7 @@ export declare const getFieldConfigByPath: (path: string, fields: Field[]) => Fo
|
|
|
74
66
|
* Blocks are treated as endpoints — the blocks builder itself is returned
|
|
75
67
|
* regardless of any index:blockType suffix in the path.
|
|
76
68
|
*/
|
|
77
|
-
export declare function
|
|
69
|
+
export declare function getFieldListAtPath(fieldPath: string, fields: FieldBuilder[], parentPath?: string): {
|
|
78
70
|
fields: FieldBuilder[];
|
|
79
71
|
path: string;
|
|
80
72
|
};
|
package/dist/core/fields/util.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BlocksBuilder
|
|
2
|
-
import { GroupFieldBuilder
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { BlocksBuilder } from '../../fields/blocks/index.js';
|
|
2
|
+
import { GroupFieldBuilder } from '../../fields/group/index.js';
|
|
3
|
+
import { TabsBuilder } from '../../fields/tabs/index.js';
|
|
4
|
+
import { TreeBuilder } from '../../fields/tree/index.js';
|
|
5
5
|
import { normalizeFieldPath } from '../../util/doc.js';
|
|
6
6
|
/**
|
|
7
7
|
* Checks if a field is a presentative field (currently only separator fields).
|
|
@@ -12,48 +12,15 @@ export const isPresentative = (field) => ['separator'].includes(field.type);
|
|
|
12
12
|
* Checks if a field is a form field (has a name property).
|
|
13
13
|
* Form fields are fields that can store data in documents.
|
|
14
14
|
*/
|
|
15
|
-
export const isFormField = (field) =>
|
|
15
|
+
export const isFormField = (field) => field.name !== '';
|
|
16
16
|
/**
|
|
17
17
|
* Checks if a form field is not hidden.
|
|
18
18
|
*/
|
|
19
|
-
export const isNotHidden = (field) => !field.hidden;
|
|
19
|
+
export const isNotHidden = (field) => !field.get.hidden;
|
|
20
20
|
/**
|
|
21
21
|
* Checks if a field has live updates enabled.
|
|
22
22
|
*/
|
|
23
23
|
export const isLiveField = (field) => field.live;
|
|
24
|
-
/**
|
|
25
|
-
* Flattens a nested field structure into an array of form fields.
|
|
26
|
-
* Handles special field types like tabs, tree, and blocks.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Flattens a tabs field into its constituent form fields
|
|
30
|
-
* const fields = [tabsField].reduce(toFormFields, []);
|
|
31
|
-
*/
|
|
32
|
-
export function toFormFields(prev, curr) {
|
|
33
|
-
if (curr.type === 'tabs') {
|
|
34
|
-
return curr.tabs.reduce(toFormFields, prev);
|
|
35
|
-
}
|
|
36
|
-
else if (curr.type === 'tree') {
|
|
37
|
-
curr = {
|
|
38
|
-
...curr,
|
|
39
|
-
fields: curr.fields.reduce(toFormFields, [])
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
else if (curr.type === 'blocks') {
|
|
43
|
-
curr = {
|
|
44
|
-
...curr,
|
|
45
|
-
blocks: curr.blocks.map((b) => ({
|
|
46
|
-
...b,
|
|
47
|
-
fields: b.fields.reduce(toFormFields, [])
|
|
48
|
-
}))
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
else if ('fields' in curr) {
|
|
52
|
-
return curr.fields.reduce(toFormFields, prev);
|
|
53
|
-
}
|
|
54
|
-
prev.push(curr);
|
|
55
|
-
return prev;
|
|
56
|
-
}
|
|
57
24
|
/**
|
|
58
25
|
* Creates an object with empty values based on field configurations.
|
|
59
26
|
* Uses defaultValue if specified, otherwise undefined.
|
|
@@ -73,24 +40,23 @@ export const emptyValuesFromFieldConfig = (arr) => {
|
|
|
73
40
|
return Object.fromEntries(arr.map((config) => {
|
|
74
41
|
let emptyValue;
|
|
75
42
|
// Handle group fields - create nested object structure
|
|
76
|
-
if (
|
|
77
|
-
emptyValue = emptyValuesFromFieldConfig(config.fields.filter(isFormField));
|
|
43
|
+
if (config instanceof GroupFieldBuilder) {
|
|
44
|
+
emptyValue = emptyValuesFromFieldConfig(config.get.fields.filter(isFormField));
|
|
78
45
|
}
|
|
79
46
|
// Handle tabs fields - create nested object structure for each tab
|
|
80
|
-
else if (
|
|
47
|
+
else if (config instanceof TabsBuilder) {
|
|
81
48
|
const tabsValue = {};
|
|
82
|
-
const tabs = config.tabs;
|
|
49
|
+
const tabs = config.get.tabs;
|
|
83
50
|
for (const tab of tabs) {
|
|
84
51
|
if ('fields' in tab) {
|
|
85
|
-
tabsValue[tab.name] = emptyValuesFromFieldConfig(tab.fields.filter(isFormField));
|
|
52
|
+
tabsValue[tab.name] = emptyValuesFromFieldConfig(tab.get.fields.filter(isFormField));
|
|
86
53
|
}
|
|
87
54
|
}
|
|
88
55
|
emptyValue = tabsValue;
|
|
89
56
|
}
|
|
90
57
|
// Handle default values
|
|
91
|
-
else
|
|
92
|
-
emptyValue =
|
|
93
|
-
typeof config.defaultValue === 'function' ? config.defaultValue() : config.defaultValue;
|
|
58
|
+
else {
|
|
59
|
+
emptyValue = config.run.defaultValue();
|
|
94
60
|
}
|
|
95
61
|
return [config.name, emptyValue];
|
|
96
62
|
}));
|
|
@@ -118,13 +84,13 @@ export function pathToRegex(path) {
|
|
|
118
84
|
* Retrieves a field configuration by its dot-notation path
|
|
119
85
|
* @example
|
|
120
86
|
* // Get the title field in the attributes group
|
|
121
|
-
* const titleField =
|
|
87
|
+
* const titleField = getFieldAtPath('attributes.title', collection.fields);
|
|
122
88
|
*
|
|
123
89
|
* // Get the title field in a specific block
|
|
124
|
-
* const titleField =
|
|
90
|
+
* const titleField = getFieldAtPath('attributes.layout.2:blockType.title', collection.fields);
|
|
125
91
|
*
|
|
126
92
|
*/
|
|
127
|
-
export const
|
|
93
|
+
export const getFieldAtPath = (path, fields) => {
|
|
128
94
|
const parts = path.split('.');
|
|
129
95
|
const findInFields = (currentFields, remainingParts) => {
|
|
130
96
|
if (remainingParts.length === 0)
|
|
@@ -132,10 +98,10 @@ export const getFieldConfigByPath = (path, fields) => {
|
|
|
132
98
|
const currentPart = remainingParts[0];
|
|
133
99
|
for (const field of currentFields) {
|
|
134
100
|
// Handle tabs
|
|
135
|
-
if (
|
|
136
|
-
const tab = field.tabs.find((t) => t.name === currentPart);
|
|
101
|
+
if (field instanceof TabsBuilder) {
|
|
102
|
+
const tab = field.get.tabs.find((t) => t.name === currentPart);
|
|
137
103
|
if (tab) {
|
|
138
|
-
return findInFields(tab.fields, remainingParts.slice(1));
|
|
104
|
+
return findInFields(tab.get.fields, remainingParts.slice(1));
|
|
139
105
|
}
|
|
140
106
|
continue;
|
|
141
107
|
}
|
|
@@ -145,22 +111,22 @@ export const getFieldConfigByPath = (path, fields) => {
|
|
|
145
111
|
if (remainingParts.length === 1) {
|
|
146
112
|
return field;
|
|
147
113
|
}
|
|
148
|
-
if (
|
|
149
|
-
return findInFields(field.fields, remainingParts.slice(1));
|
|
114
|
+
if (field instanceof GroupFieldBuilder) {
|
|
115
|
+
return findInFields(field.get.fields, remainingParts.slice(1));
|
|
150
116
|
}
|
|
151
117
|
// Handle blocks
|
|
152
|
-
if (
|
|
118
|
+
if (field instanceof BlocksBuilder && remainingParts.length > 1) {
|
|
153
119
|
// const blockPartPattern = /:[a-zA-Z0-9]+/
|
|
154
120
|
const blockType = remainingParts[1].split(':')[1];
|
|
155
121
|
if (blockType) {
|
|
156
|
-
const block = field.blocks.find((b) => b.name === blockType);
|
|
122
|
+
const block = field.get.blocks.find((b) => b.name === blockType);
|
|
157
123
|
if (block) {
|
|
158
|
-
return findInFields(block.fields, remainingParts.slice(2));
|
|
124
|
+
return findInFields(block.get.fields, remainingParts.slice(2));
|
|
159
125
|
}
|
|
160
126
|
}
|
|
161
127
|
}
|
|
162
|
-
if (
|
|
163
|
-
return findInFields(field.fields, remainingParts.slice(2));
|
|
128
|
+
if (field instanceof TreeBuilder) {
|
|
129
|
+
return findInFields(field.get.fields, remainingParts.slice(2));
|
|
164
130
|
}
|
|
165
131
|
}
|
|
166
132
|
}
|
|
@@ -177,67 +143,67 @@ export const getFieldConfigByPath = (path, fields) => {
|
|
|
177
143
|
* Blocks are treated as endpoints — the blocks builder itself is returned
|
|
178
144
|
* regardless of any index:blockType suffix in the path.
|
|
179
145
|
*/
|
|
180
|
-
export function
|
|
146
|
+
export function getFieldListAtPath(fieldPath, fields, parentPath = '') {
|
|
181
147
|
if (!fieldPath)
|
|
182
|
-
return { fields
|
|
148
|
+
return { fields, path: parentPath };
|
|
183
149
|
const dotIndex = fieldPath.indexOf('.');
|
|
184
150
|
const head = dotIndex === -1 ? fieldPath : fieldPath.slice(0, dotIndex);
|
|
185
151
|
const tail = dotIndex === -1 ? '' : fieldPath.slice(dotIndex + 1);
|
|
186
152
|
const isEndpoint = fieldPath.split('.').length === 1;
|
|
187
153
|
const nextParentPath = normalizeFieldPath(`${parentPath}${parentPath ? '.' : ''}${head}`);
|
|
188
|
-
for (const
|
|
154
|
+
for (const field of fields) {
|
|
189
155
|
// ── Tabs container: navigate into the matching tab
|
|
190
|
-
if (
|
|
191
|
-
const tab =
|
|
156
|
+
if (field instanceof TabsBuilder) {
|
|
157
|
+
const tab = field.field.tabs.find((t) => t.name === head);
|
|
192
158
|
if (!tab)
|
|
193
159
|
continue;
|
|
194
160
|
if (isEndpoint) {
|
|
195
161
|
// Path targets the tab → return all its inner fields
|
|
196
|
-
return { fields: tab.
|
|
162
|
+
return { fields: tab.get.fields, path: nextParentPath };
|
|
197
163
|
}
|
|
198
|
-
return
|
|
164
|
+
return getFieldListAtPath(tail, tab.get.fields, nextParentPath);
|
|
199
165
|
}
|
|
200
|
-
if (!isFormField(
|
|
166
|
+
if (!isFormField(field))
|
|
201
167
|
continue;
|
|
202
168
|
// ── Group field: navigate into children
|
|
203
|
-
if (
|
|
204
|
-
const children =
|
|
169
|
+
if (field instanceof GroupFieldBuilder && field.name === head) {
|
|
170
|
+
const children = field.get.fields;
|
|
205
171
|
if (isEndpoint)
|
|
206
172
|
return { fields: children, path: nextParentPath };
|
|
207
|
-
return
|
|
173
|
+
return getFieldListAtPath(tail, children, nextParentPath);
|
|
208
174
|
}
|
|
209
175
|
// —— Blocks
|
|
210
|
-
if (
|
|
176
|
+
if (field instanceof BlocksBuilder && field.name === head) {
|
|
211
177
|
const blockType = tail.split('.')[0]?.split(':')[1];
|
|
212
178
|
const isInnerBlockLookup = tail.split('.').length > 1;
|
|
213
179
|
const nextParentPathWithBlockIndex = `${nextParentPath}.${tail.split('.')[0]}`;
|
|
214
180
|
if (blockType) {
|
|
215
|
-
const block =
|
|
216
|
-
if (!isInnerBlockLookup && block?.
|
|
181
|
+
const block = field.get.blocks.find((b) => b.name === blockType);
|
|
182
|
+
if (!isInnerBlockLookup && block?.get.fields) {
|
|
217
183
|
return {
|
|
218
|
-
fields: block
|
|
184
|
+
fields: block.get.fields,
|
|
219
185
|
path: normalizeFieldPath(nextParentPathWithBlockIndex)
|
|
220
186
|
};
|
|
221
187
|
}
|
|
222
188
|
if (block) {
|
|
223
|
-
return
|
|
189
|
+
return getFieldListAtPath(tail.split('.').slice(1).join('.'), block.get.fields, normalizeFieldPath(nextParentPathWithBlockIndex));
|
|
224
190
|
}
|
|
225
191
|
}
|
|
226
|
-
return { fields: [
|
|
192
|
+
return { fields: [field], path: parentPath };
|
|
227
193
|
}
|
|
228
194
|
// Tree
|
|
229
|
-
if (
|
|
230
|
-
const children =
|
|
195
|
+
if (field instanceof TreeBuilder && field.name === head) {
|
|
196
|
+
const children = field.get.fields;
|
|
231
197
|
const nextParentPathWithIndex = `${nextParentPath}.${tail.split('.')[0]}`;
|
|
232
198
|
if (isEndpoint)
|
|
233
199
|
return { fields: children, path: nextParentPath };
|
|
234
|
-
return
|
|
200
|
+
return getFieldListAtPath(tail.split('.').slice(1).join('.'), children, nextParentPathWithIndex);
|
|
235
201
|
}
|
|
236
202
|
// Direct unique field match
|
|
237
|
-
if (isEndpoint && isFormField(
|
|
238
|
-
return { fields: [
|
|
203
|
+
if (isEndpoint && isFormField(field) && field.name === fieldPath) {
|
|
204
|
+
return { fields: [field], path: parentPath };
|
|
239
205
|
}
|
|
240
206
|
}
|
|
241
207
|
console.warn(`[LiveEditPanel] fieldPath "${fieldPath}" not found in config fields`);
|
|
242
|
-
return { fields
|
|
208
|
+
return { fields, path: parentPath };
|
|
243
209
|
}
|