@plumix/plugin-media 0.2.0 → 0.3.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/builder.d.ts +105 -50
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +153 -47
- package/dist/builder.js.map +1 -1
- package/dist/fields.d.ts +1 -2
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +1 -1
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lookup.d.ts +30 -6
- package/dist/lookup.d.ts.map +1 -1
- package/dist/lookup.js +48 -4
- package/dist/lookup.js.map +1 -1
- package/package.json +2 -2
package/dist/builder.d.ts
CHANGED
|
@@ -1,61 +1,116 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Label } from "plumix/i18n";
|
|
2
|
+
import type { FieldBuilder, MediaListMetaBoxField, MediaMetaBoxField, MetaBoxFieldSpan, MetaBoxFieldValidate, MetaFieldCondition, MetaFieldConditionRule } from "plumix/plugin";
|
|
3
|
+
import type { MediaFieldScope, MediaReference } from "./lookup.js";
|
|
4
|
+
/** One read element: the hydrated `MediaReference`, or the bare id after `.returns("id")`. */
|
|
5
|
+
type MediaReadItem<Returns extends "id" | "hydrated"> = Returns extends "id" ? string : MediaReference;
|
|
2
6
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `mediaLookupAdapter`'s `list({ ids })` path on the server (security
|
|
7
|
-
* boundary — re-validated at write time). Format: a single MIME prefix
|
|
8
|
-
* string (`"image/"` matches every `image/*` mime) OR a readonly array
|
|
9
|
-
* of exact MIME matches (`["image/png", "application/pdf"]`).
|
|
10
|
-
*
|
|
11
|
-
* `default` is the media entry's id.
|
|
7
|
+
* The phantom read type. A single reference is always optional (a
|
|
8
|
+
* target can be deleted after the id is written); a multi reference
|
|
9
|
+
* reads a dense array, present once `.required()` guarantees a write.
|
|
12
10
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
11
|
+
type MediaReadValue<Multiple extends boolean, Required extends boolean, Returns extends "id" | "hydrated"> = Multiple extends true ? Required extends true ? readonly MediaReadItem<Returns>[] : readonly MediaReadItem<Returns>[] | undefined : MediaReadItem<Returns> | undefined;
|
|
12
|
+
/** The phantom stored shape — bare ids; `.required()` narrows optionality. */
|
|
13
|
+
type MediaStoredValue<Multiple extends boolean, Required extends boolean> = Multiple extends true ? Required extends true ? readonly string[] : readonly string[] | undefined : Required extends true ? string : string | undefined;
|
|
14
|
+
interface MediaFieldState {
|
|
15
|
+
readonly visibleWhen?: MetaFieldCondition;
|
|
16
|
+
readonly label?: Label;
|
|
17
|
+
readonly description?: Label;
|
|
18
|
+
readonly default?: string | readonly string[];
|
|
19
|
+
readonly required?: true;
|
|
20
|
+
readonly multiple?: true;
|
|
21
|
+
readonly returns?: "id";
|
|
22
|
+
readonly max?: number;
|
|
19
23
|
readonly span?: MetaBoxFieldSpan;
|
|
20
|
-
readonly
|
|
24
|
+
readonly capability?: string;
|
|
25
|
+
readonly showInApi?: true;
|
|
26
|
+
readonly sanitize?: (value: unknown) => unknown;
|
|
27
|
+
readonly validate?: MetaBoxFieldValidate;
|
|
21
28
|
}
|
|
22
29
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
30
|
+
* Fluent chain for the `media` reference field —
|
|
31
|
+
* `media("hero").accept("image/")`. Mirrors the core reference
|
|
32
|
+
* builders (`entry` / `term` / `user`): `.accept()` refines the picker
|
|
33
|
+
* MIME filter, `.multiple()` flips to an id array, `.returns("id")`
|
|
34
|
+
* opts out of read-time hydration. Immutable — every call returns a
|
|
35
|
+
* fresh instance.
|
|
25
36
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* Single-value only — `mediaList()` covers the multi case.
|
|
37
|
+
* Storage is the bare media id (an id array under `.multiple()`); reads
|
|
38
|
+
* hydrate to the {@link MediaReference} summary by default so themes
|
|
39
|
+
* render a media field (URL included) without a manual fetch.
|
|
31
40
|
*/
|
|
32
|
-
export declare
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
readonly
|
|
40
|
-
|
|
41
|
-
readonly
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
export declare class MediaFieldBuilder<K extends string = string, Multiple extends boolean = false, Required extends boolean = false, Returns extends "id" | "hydrated" = "hydrated"> implements FieldBuilder {
|
|
42
|
+
#private;
|
|
43
|
+
/** Phantom literal key of the field — type-level only, never assigned. */
|
|
44
|
+
readonly _key: K;
|
|
45
|
+
/** Phantom read type — hydrated `MediaReference` by default, id after `.returns("id")`. */
|
|
46
|
+
readonly _value: MediaReadValue<Multiple, Required, Returns>;
|
|
47
|
+
/** Phantom stored shape — bare ids; `.required()` narrows optionality. */
|
|
48
|
+
readonly _stored: MediaStoredValue<Multiple, Required>;
|
|
49
|
+
/** Phantom cardinality marker backing the compile-time gate on `.multiple()` / `.max()`. */
|
|
50
|
+
readonly _multiple: Multiple;
|
|
51
|
+
constructor(key: string, scope?: MediaFieldScope, state?: MediaFieldState);
|
|
52
|
+
/**
|
|
53
|
+
* Filter the picker (and re-validate on write) by MIME. A single
|
|
54
|
+
* prefix string (`"image/"` matches every `image/*`) or a readonly
|
|
55
|
+
* array of exact MIME matches (`["image/png", "application/pdf"]`).
|
|
56
|
+
*/
|
|
57
|
+
accept(accept: string | readonly string[]): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
58
|
+
/**
|
|
59
|
+
* Store an array of ids instead of a single one — reads become a
|
|
60
|
+
* dense array. Declare cardinality before `.required()` narrows the
|
|
61
|
+
* shapes; the `this`-type gate blocks a post-narrowing `.multiple()`.
|
|
62
|
+
*/
|
|
63
|
+
multiple(this: MediaFieldBuilder<K, false, false, Returns>): MediaFieldBuilder<K, true, false, Returns>;
|
|
64
|
+
/** Cap the array length — multi-value fields only. */
|
|
65
|
+
max(this: MediaFieldBuilder<K, true, Required, Returns>, max: number): MediaFieldBuilder<K, true, Required, Returns>;
|
|
66
|
+
/** Read the bare stored id(s) instead of the hydrated summary. */
|
|
67
|
+
returns(shape: "id"): MediaFieldBuilder<K, Multiple, Required, "id">;
|
|
68
|
+
/** Mark the field required — enforced at write time by the constraint walker. */
|
|
69
|
+
required(): MediaFieldBuilder<K, Multiple, true, Returns>;
|
|
70
|
+
/** Override the derived (humanized-key) label. */
|
|
71
|
+
label(label: Label): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
72
|
+
/** Help text rendered under the label. */
|
|
73
|
+
description(description: Label): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
74
|
+
/** Prefill for absent keys — a stored id (or id array for multi fields). */
|
|
75
|
+
default(value: Multiple extends true ? readonly string[] : string): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
76
|
+
/** Column span within the box's 12-column grid — a universal layout hint. */
|
|
77
|
+
span(span: MetaBoxFieldSpan): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
78
|
+
/** Capability gate for this field — see `MetaBoxFieldBase.capability`. */
|
|
79
|
+
capability(capability: string): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
80
|
+
/** Opt this field's value into public REST responses (default-deny). */
|
|
81
|
+
showInApi(): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
82
|
+
/** Rule factory: this field's stored id equals `value`. */
|
|
83
|
+
is(value: string): MetaFieldConditionRule;
|
|
84
|
+
/** Rule factory: this field's stored id differs from `value`. */
|
|
85
|
+
isNot(value: string): MetaFieldConditionRule;
|
|
86
|
+
/** Rule factory: this field has no value (unset or cleared). */
|
|
87
|
+
isEmpty(): MetaFieldConditionRule;
|
|
88
|
+
/** Rule factory: this field has a value. */
|
|
89
|
+
isNotEmpty(): MetaFieldConditionRule;
|
|
90
|
+
/** Rule factory: the selection includes `id` — multi-value only. */
|
|
91
|
+
contains(this: MediaFieldBuilder<K, true, Required, Returns>, id: string): MetaFieldConditionRule;
|
|
92
|
+
/** Rule factory: the selection does not include `id` — multi-value only. */
|
|
93
|
+
notContains(this: MediaFieldBuilder<K, true, Required, Returns>, id: string): MetaFieldConditionRule;
|
|
94
|
+
/**
|
|
95
|
+
* Show this field only when every rule passes (one AND group).
|
|
96
|
+
* Replaces any previously declared condition; `.orVisibleWhen()`
|
|
97
|
+
* adds alternatives.
|
|
98
|
+
*/
|
|
99
|
+
visibleWhen(...rules: MetaFieldConditionRule[]): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
100
|
+
/** Add an OR alternative — one more AND group of rules. */
|
|
101
|
+
orVisibleWhen(...rules: MetaFieldConditionRule[]): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
102
|
+
/** Normalising transform, applied after coercion and before persistence. */
|
|
103
|
+
sanitize(sanitize: (value: unknown) => unknown): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
104
|
+
/** Custom validation — `true` for valid, or an i18n-able failure message. */
|
|
105
|
+
validate(validate: MetaBoxFieldValidate): MediaFieldBuilder<K, Multiple, Required, Returns>;
|
|
106
|
+
/** Compile the chain into the wire/manifest field definition. */
|
|
107
|
+
build(): Multiple extends true ? MediaListMetaBoxField : MediaMetaBoxField;
|
|
48
108
|
}
|
|
49
109
|
/**
|
|
50
|
-
* Build a typed `
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* Picker stays open across selections (so authors can pick several
|
|
55
|
-
* without re-opening) and auto-stops when `max` is reached.
|
|
56
|
-
* Selected items render as a vertical list with up/down reorder
|
|
57
|
-
* and per-item removal; drag-reorder is deferred to a follow-up
|
|
58
|
-
* (see `MediaListPickerField`).
|
|
110
|
+
* Build a typed `media` reference field — `media("hero")`. The picker
|
|
111
|
+
* opens the Media Library in modal mode; `.accept()` filters the grid
|
|
112
|
+
* (and re-validates on write), `.multiple()` stores an id array.
|
|
59
113
|
*/
|
|
60
|
-
export declare function
|
|
114
|
+
export declare function media<K extends string>(key: K): MediaFieldBuilder<K>;
|
|
115
|
+
export {};
|
|
61
116
|
//# sourceMappingURL=builder.d.ts.map
|
package/dist/builder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
|
package/dist/builder.js
CHANGED
|
@@ -1,55 +1,161 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
// "heroImage" → "Hero image". Derived default for fields authored
|
|
3
|
+
// without `.label()`. Kept local — the plugin can't reach core's
|
|
4
|
+
// private `humanizeFieldKey`, and the rule is a one-liner.
|
|
5
|
+
function humanizeFieldKey(key) {
|
|
6
|
+
const spaced = key
|
|
7
|
+
.replaceAll(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
8
|
+
.replaceAll(/[_:-]+/g, " ")
|
|
9
|
+
.trim()
|
|
10
|
+
.toLowerCase();
|
|
11
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
14
|
+
* Fluent chain for the `media` reference field —
|
|
15
|
+
* `media("hero").accept("image/")`. Mirrors the core reference
|
|
16
|
+
* builders (`entry` / `term` / `user`): `.accept()` refines the picker
|
|
17
|
+
* MIME filter, `.multiple()` flips to an id array, `.returns("id")`
|
|
18
|
+
* opts out of read-time hydration. Immutable — every call returns a
|
|
19
|
+
* fresh instance.
|
|
8
20
|
*
|
|
9
|
-
*
|
|
21
|
+
* Storage is the bare media id (an id array under `.multiple()`); reads
|
|
22
|
+
* hydrate to the {@link MediaReference} summary by default so themes
|
|
23
|
+
* render a media field (URL included) without a manual fetch.
|
|
10
24
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
export class MediaFieldBuilder {
|
|
26
|
+
#key;
|
|
27
|
+
#scope;
|
|
28
|
+
#state;
|
|
29
|
+
constructor(key, scope = {}, state = {}) {
|
|
30
|
+
this.#key = key;
|
|
31
|
+
this.#scope = scope;
|
|
32
|
+
this.#state = state;
|
|
33
|
+
}
|
|
34
|
+
#fork(patch, scope = this.#scope) {
|
|
35
|
+
return new _a(this.#key, scope, { ...this.#state, ...patch });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Filter the picker (and re-validate on write) by MIME. A single
|
|
39
|
+
* prefix string (`"image/"` matches every `image/*`) or a readonly
|
|
40
|
+
* array of exact MIME matches (`["image/png", "application/pdf"]`).
|
|
41
|
+
*/
|
|
42
|
+
accept(accept) {
|
|
43
|
+
return this.#fork({}, { accept });
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Store an array of ids instead of a single one — reads become a
|
|
47
|
+
* dense array. Declare cardinality before `.required()` narrows the
|
|
48
|
+
* shapes; the `this`-type gate blocks a post-narrowing `.multiple()`.
|
|
49
|
+
*/
|
|
50
|
+
multiple() {
|
|
51
|
+
return this.#fork({ multiple: true });
|
|
52
|
+
}
|
|
53
|
+
/** Cap the array length — multi-value fields only. */
|
|
54
|
+
max(max) {
|
|
55
|
+
return this.#fork({ max });
|
|
56
|
+
}
|
|
57
|
+
/** Read the bare stored id(s) instead of the hydrated summary. */
|
|
58
|
+
returns(shape) {
|
|
59
|
+
return this.#fork({ returns: shape });
|
|
60
|
+
}
|
|
61
|
+
/** Mark the field required — enforced at write time by the constraint walker. */
|
|
62
|
+
required() {
|
|
63
|
+
return this.#fork({ required: true });
|
|
64
|
+
}
|
|
65
|
+
/** Override the derived (humanized-key) label. */
|
|
66
|
+
label(label) {
|
|
67
|
+
return this.#fork({ label });
|
|
68
|
+
}
|
|
69
|
+
/** Help text rendered under the label. */
|
|
70
|
+
description(description) {
|
|
71
|
+
return this.#fork({ description });
|
|
72
|
+
}
|
|
73
|
+
/** Prefill for absent keys — a stored id (or id array for multi fields). */
|
|
74
|
+
default(value) {
|
|
75
|
+
return this.#fork({ default: value });
|
|
76
|
+
}
|
|
77
|
+
/** Column span within the box's 12-column grid — a universal layout hint. */
|
|
78
|
+
span(span) {
|
|
79
|
+
return this.#fork({ span });
|
|
80
|
+
}
|
|
81
|
+
/** Capability gate for this field — see `MetaBoxFieldBase.capability`. */
|
|
82
|
+
capability(capability) {
|
|
83
|
+
return this.#fork({ capability });
|
|
84
|
+
}
|
|
85
|
+
/** Opt this field's value into public REST responses (default-deny). */
|
|
86
|
+
showInApi() {
|
|
87
|
+
return this.#fork({ showInApi: true });
|
|
88
|
+
}
|
|
89
|
+
/** Rule factory: this field's stored id equals `value`. */
|
|
90
|
+
is(value) {
|
|
91
|
+
return { key: this.#key, op: "eq", value };
|
|
92
|
+
}
|
|
93
|
+
/** Rule factory: this field's stored id differs from `value`. */
|
|
94
|
+
isNot(value) {
|
|
95
|
+
return { key: this.#key, op: "neq", value };
|
|
96
|
+
}
|
|
97
|
+
/** Rule factory: this field has no value (unset or cleared). */
|
|
98
|
+
isEmpty() {
|
|
99
|
+
return { key: this.#key, op: "empty" };
|
|
100
|
+
}
|
|
101
|
+
/** Rule factory: this field has a value. */
|
|
102
|
+
isNotEmpty() {
|
|
103
|
+
return { key: this.#key, op: "not_empty" };
|
|
104
|
+
}
|
|
105
|
+
/** Rule factory: the selection includes `id` — multi-value only. */
|
|
106
|
+
contains(id) {
|
|
107
|
+
return { key: this.#key, op: "contains", value: id };
|
|
108
|
+
}
|
|
109
|
+
/** Rule factory: the selection does not include `id` — multi-value only. */
|
|
110
|
+
notContains(id) {
|
|
111
|
+
return { key: this.#key, op: "not_contains", value: id };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Show this field only when every rule passes (one AND group).
|
|
115
|
+
* Replaces any previously declared condition; `.orVisibleWhen()`
|
|
116
|
+
* adds alternatives.
|
|
117
|
+
*/
|
|
118
|
+
visibleWhen(...rules) {
|
|
119
|
+
return this.#fork({ visibleWhen: [rules] });
|
|
120
|
+
}
|
|
121
|
+
/** Add an OR alternative — one more AND group of rules. */
|
|
122
|
+
orVisibleWhen(...rules) {
|
|
123
|
+
return this.#fork({
|
|
124
|
+
visibleWhen: [...(this.#state.visibleWhen ?? []), rules],
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** Normalising transform, applied after coercion and before persistence. */
|
|
128
|
+
sanitize(sanitize) {
|
|
129
|
+
return this.#fork({ sanitize });
|
|
130
|
+
}
|
|
131
|
+
/** Custom validation — `true` for valid, or an i18n-able failure message. */
|
|
132
|
+
validate(validate) {
|
|
133
|
+
return this.#fork({ validate });
|
|
134
|
+
}
|
|
135
|
+
/** Compile the chain into the wire/manifest field definition. */
|
|
136
|
+
build() {
|
|
137
|
+
const { multiple, ...state } = this.#state;
|
|
138
|
+
const target = multiple
|
|
139
|
+
? { kind: "media", scope: this.#scope, multiple: true }
|
|
140
|
+
: { kind: "media", scope: this.#scope };
|
|
141
|
+
const field = {
|
|
142
|
+
...state,
|
|
143
|
+
key: this.#key,
|
|
144
|
+
label: state.label ?? humanizeFieldKey(this.#key),
|
|
145
|
+
type: "json",
|
|
146
|
+
inputType: multiple ? "mediaList" : "media",
|
|
147
|
+
referenceTarget: target,
|
|
148
|
+
};
|
|
149
|
+
return field;
|
|
150
|
+
}
|
|
24
151
|
}
|
|
152
|
+
_a = MediaFieldBuilder;
|
|
25
153
|
/**
|
|
26
|
-
* Build a typed `
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* Picker stays open across selections (so authors can pick several
|
|
31
|
-
* without re-opening) and auto-stops when `max` is reached.
|
|
32
|
-
* Selected items render as a vertical list with up/down reorder
|
|
33
|
-
* and per-item removal; drag-reorder is deferred to a follow-up
|
|
34
|
-
* (see `MediaListPickerField`).
|
|
154
|
+
* Build a typed `media` reference field — `media("hero")`. The picker
|
|
155
|
+
* opens the Media Library in modal mode; `.accept()` filters the grid
|
|
156
|
+
* (and re-validates on write), `.multiple()` stores an id array.
|
|
35
157
|
*/
|
|
36
|
-
export function
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
key: options.key,
|
|
40
|
-
label: options.label,
|
|
41
|
-
type: "json",
|
|
42
|
-
inputType: "mediaList",
|
|
43
|
-
referenceTarget: {
|
|
44
|
-
kind: "media",
|
|
45
|
-
scope,
|
|
46
|
-
multiple: true,
|
|
47
|
-
},
|
|
48
|
-
max: options.max,
|
|
49
|
-
required: options.required,
|
|
50
|
-
description: options.description,
|
|
51
|
-
default: options.default,
|
|
52
|
-
span: options.span,
|
|
53
|
-
};
|
|
158
|
+
export function media(key) {
|
|
159
|
+
return new MediaFieldBuilder(key);
|
|
54
160
|
}
|
|
55
161
|
//# sourceMappingURL=builder.js.map
|
package/dist/builder.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":";AAcA,kEAAkE;AAClE,iEAAiE;AACjE,2DAA2D;AAC3D,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,GAAG;SACf,UAAU,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACzC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC;SAC1B,IAAI,EAAE;SACN,WAAW,EAAE,CAAC;IACjB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAkDD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,iBAAiB;IAenB,IAAI,CAAS;IACb,MAAM,CAAkB;IACxB,MAAM,CAAkB;IAEjC,YACE,GAAW,EACX,QAAyB,EAAE,EAC3B,QAAyB,EAAE;QAE3B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAKH,KAA+B,EAC/B,QAAyB,IAAI,CAAC,MAAM;QAEpC,OAAO,IAAI,EAAiB,CAC1B,IAAI,CAAC,IAAI,EACT,KAAK,EACL,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,CAC7B,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CACJ,MAAkC;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,QAAQ;QAGN,OAAO,IAAI,CAAC,KAAK,CAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,sDAAsD;IACtD,GAAG,CAED,GAAW;QAEX,OAAO,IAAI,CAAC,KAAK,CAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,kEAAkE;IAClE,OAAO,CAAC,KAAW;QACjB,OAAO,IAAI,CAAC,KAAK,CAA2B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,iFAAiF;IACjF,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,KAAY;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,0CAA0C;IAC1C,WAAW,CACT,WAAkB;QAElB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,4EAA4E;IAC5E,OAAO,CACL,KAAyD;QAEzD,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,6EAA6E;IAC7E,IAAI,CACF,IAAsB;QAEtB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,0EAA0E;IAC1E,UAAU,CACR,UAAkB;QAElB,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,wEAAwE;IACxE,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,2DAA2D;IAC3D,EAAE,CAAC,KAAa;QACd,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAC,KAAa;QACjB,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9C,CAAC;IAED,gEAAgE;IAChE,OAAO;QACL,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IACzC,CAAC;IAED,4CAA4C;IAC5C,UAAU;QACR,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC;IAC7C,CAAC;IAED,oEAAoE;IACpE,QAAQ,CAEN,EAAU;QAEV,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACvD,CAAC;IAED,4EAA4E;IAC5E,WAAW,CAET,EAAU;QAEV,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACH,WAAW,CACT,GAAG,KAA+B;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,2DAA2D;IAC3D,aAAa,CACX,GAAG,KAA+B;QAElC,OAAO,IAAI,CAAC,KAAK,CAAC;YAChB,WAAW,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC;SACzD,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,QAAQ,CACN,QAAqC;QAErC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,6EAA6E;IAC7E,QAAQ,CACN,QAA8B;QAE9B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,iEAAiE;IACjE,KAAK;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3C,MAAM,MAAM,GAAoB,QAAQ;YACtC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;YACvD,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG;YACZ,GAAG,KAAK;YACR,GAAG,EAAE,IAAI,CAAC,IAAI;YACd,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;YACjD,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO;YAC3C,eAAe,EAAE,MAAM;SACxB,CAAC;QACF,OAAO,KAEc,CAAC;IACxB,CAAC;CACF;;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAmB,GAAM;IAC5C,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/fields.d.ts
CHANGED
package/dist/fields.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/fields.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
// with `media()` (the plugin descriptor factory) exported from the
|
|
4
4
|
// package root. Mirrors the `plumix/fields` subpath convention from
|
|
5
5
|
// core.
|
|
6
|
-
export { media,
|
|
6
|
+
export { media, MediaFieldBuilder } from "./builder.js";
|
|
7
7
|
//# sourceMappingURL=fields.js.map
|
package/dist/fields.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.js","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,sEAAsE;AACtE,mEAAmE;AACnE,oEAAoE;AACpE,QAAQ;AAER,OAAO,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"fields.js","sourceRoot":"","sources":["../src/fields.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,sEAAsE;AACtE,mEAAmE;AACnE,oEAAoE;AACpE,QAAQ;AAER,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PluginDescriptor } from "plumix/plugin";
|
|
2
2
|
import { DEFAULT_ACCEPTED_TYPES } from "./mime.js";
|
|
3
|
-
export type { MediaFieldScope } from "./lookup.js";
|
|
3
|
+
export type { MediaFieldScope, MediaReference } from "./lookup.js";
|
|
4
4
|
export { DEFAULT_ACCEPTED_TYPES };
|
|
5
5
|
/** Default max upload size — 25 MiB. */
|
|
6
6
|
export declare const DEFAULT_MAX_UPLOAD_SIZE: number;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAKnD,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAKnD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,EAAE,sBAAsB,EAAE,CAAC;AAElC,wCAAwC;AACxC,eAAO,MAAM,uBAAuB,QAAmB,CAAC;AAgExD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,UAAU,kBAAkB;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,KAAK,CACnB,OAAO,GAAE,kBAAuB,GAC/B,gBAAgB,CAAC,SAAS,CAAC,CA8G7B"}
|
package/dist/lookup.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { HydratedReference, LookupResult } from "plumix/plugin";
|
|
2
2
|
/**
|
|
3
3
|
* Public scope shape for the `media` reference field. Carried on the
|
|
4
4
|
* field's `referenceTarget.scope`; the media `LookupAdapter` consumes
|
|
@@ -14,12 +14,32 @@ import type { LookupAdapter } from "plumix/plugin";
|
|
|
14
14
|
export interface MediaFieldScope {
|
|
15
15
|
readonly accept?: string | readonly string[];
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Hydrated shape of a `media` reference — the read pipeline resolves
|
|
19
|
+
* stored ids into this at read time, so themes can render a media meta
|
|
20
|
+
* field (URL included) without a manual fetch. `id` stays the stored
|
|
21
|
+
* string id so a hydrated value posted back through a meta write
|
|
22
|
+
* self-heals to the plain id.
|
|
23
|
+
*/
|
|
24
|
+
export interface MediaReference extends HydratedReference {
|
|
25
|
+
readonly title: string;
|
|
26
|
+
readonly mime: string;
|
|
27
|
+
readonly size: number;
|
|
28
|
+
readonly alt: string | null;
|
|
29
|
+
readonly url: string;
|
|
30
|
+
readonly thumbnailUrl: string;
|
|
31
|
+
readonly width: number | null;
|
|
32
|
+
readonly height: number | null;
|
|
33
|
+
}
|
|
34
|
+
declare module "plumix/plugin" {
|
|
35
|
+
interface ReferenceHydrationShapes {
|
|
36
|
+
readonly media: MediaReference;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
17
39
|
/**
|
|
18
40
|
* Server-side adapter for the `media` reference field. Storage is the
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* value on every write so reads render thumbnails without an extra
|
|
22
|
-
* resolve round-trip.
|
|
41
|
+
* plain media id; `hydrate` resolves ids into `MediaReference` (URL
|
|
42
|
+
* included) at read time through the shared meta pipeline.
|
|
23
43
|
*
|
|
24
44
|
* Queries:
|
|
25
45
|
* - `list({ ids })`: PK lookup via `inArray(entries.id, …)` + the
|
|
@@ -39,5 +59,9 @@ export interface MediaFieldScope {
|
|
|
39
59
|
* `media.confirm` (flips to published) — referencing one would point
|
|
40
60
|
* at an asset whose bytes haven't been verified.
|
|
41
61
|
*/
|
|
42
|
-
export declare const mediaLookupAdapter:
|
|
62
|
+
export declare const mediaLookupAdapter: {
|
|
63
|
+
list(ctx: import("@plumix/core").AppContext, options: import("@plumix/core").LookupListOptions<MediaFieldScope>): Promise<LookupResult[]>;
|
|
64
|
+
resolve(ctx: import("@plumix/core").AppContext, id: string, scope?: MediaFieldScope | undefined): Promise<LookupResult | null>;
|
|
65
|
+
hydrate(ctx: import("@plumix/core").AppContext, options: import("@plumix/core").LookupHydrateOptions<MediaFieldScope>): Promise<MediaReference[]>;
|
|
66
|
+
};
|
|
43
67
|
//# sourceMappingURL=lookup.d.ts.map
|
package/dist/lookup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../src/lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../src/lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,YAAY,EAEb,MAAM,eAAe,CAAC;AAiBvB;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,wBAAwB;QAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;KAChC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,eAAO,MAAM,kBAAkB;;;;CA6GW,CAAC"}
|
package/dist/lookup.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { and, desc, entries, eq, inArray, like, sql } from "plumix/plugin";
|
|
2
2
|
import { parseMediaMeta } from "./meta.js";
|
|
3
|
+
import { resolveMediaUrl, thumbnailFor } from "./read-service.js";
|
|
3
4
|
const MEDIA_ENTRY_TYPE = "media";
|
|
4
5
|
const DEFAULT_LIST_LIMIT = 24;
|
|
5
6
|
const MAX_LIST_LIMIT = 100;
|
|
@@ -10,10 +11,8 @@ const MEDIA_ROW_COLUMNS = {
|
|
|
10
11
|
};
|
|
11
12
|
/**
|
|
12
13
|
* Server-side adapter for the `media` reference field. Storage is the
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* value on every write so reads render thumbnails without an extra
|
|
16
|
-
* resolve round-trip.
|
|
14
|
+
* plain media id; `hydrate` resolves ids into `MediaReference` (URL
|
|
15
|
+
* included) at read time through the shared meta pipeline.
|
|
17
16
|
*
|
|
18
17
|
* Queries:
|
|
19
18
|
* - `list({ ids })`: PK lookup via `inArray(entries.id, …)` + the
|
|
@@ -33,6 +32,8 @@ const MEDIA_ROW_COLUMNS = {
|
|
|
33
32
|
* `media.confirm` (flips to published) — referencing one would point
|
|
34
33
|
* at an asset whose bytes haven't been verified.
|
|
35
34
|
*/
|
|
35
|
+
// `satisfies` keeps `hydrate`'s concrete `MediaReference` return type
|
|
36
|
+
// visible instead of widening to the contract's `HydratedReference`.
|
|
36
37
|
export const mediaLookupAdapter = {
|
|
37
38
|
async list(ctx, options) {
|
|
38
39
|
const conditions = [
|
|
@@ -98,6 +99,49 @@ export const mediaLookupAdapter = {
|
|
|
98
99
|
return null;
|
|
99
100
|
return toLookupResult(row.id, row.title, meta.mime);
|
|
100
101
|
},
|
|
102
|
+
async hydrate(ctx, options) {
|
|
103
|
+
const numericIds = options.ids
|
|
104
|
+
.map((id) => parseMediaId(id))
|
|
105
|
+
.filter((id) => id !== null);
|
|
106
|
+
if (numericIds.length === 0)
|
|
107
|
+
return [];
|
|
108
|
+
const conditions = [
|
|
109
|
+
eq(entries.type, MEDIA_ENTRY_TYPE),
|
|
110
|
+
eq(entries.status, "published"),
|
|
111
|
+
inArray(entries.id, numericIds),
|
|
112
|
+
];
|
|
113
|
+
const acceptCondition = buildAcceptCondition(options.scope?.accept);
|
|
114
|
+
if (acceptCondition)
|
|
115
|
+
conditions.push(acceptCondition);
|
|
116
|
+
const rows = await ctx.db
|
|
117
|
+
.select(MEDIA_ROW_COLUMNS)
|
|
118
|
+
.from(entries)
|
|
119
|
+
.where(and(...conditions))
|
|
120
|
+
.limit(numericIds.length);
|
|
121
|
+
const parsed = rows.flatMap((row) => {
|
|
122
|
+
const meta = parseMediaMeta(row.meta);
|
|
123
|
+
return meta ? [{ row, meta }] : [];
|
|
124
|
+
});
|
|
125
|
+
// `storage.url()` can be a signing round-trip — resolve the batch
|
|
126
|
+
// concurrently. Same URL resolution as `buildMediaItem`
|
|
127
|
+
// (read-service) so a hydrated reference and `media.get` agree.
|
|
128
|
+
return Promise.all(parsed.map(async ({ row, meta }) => {
|
|
129
|
+
const url = ctx.storage
|
|
130
|
+
? await resolveMediaUrl(ctx.storage, meta.storageKey, row.id, ctx.basePath)
|
|
131
|
+
: meta.storageKey;
|
|
132
|
+
return {
|
|
133
|
+
id: String(row.id),
|
|
134
|
+
title: row.title,
|
|
135
|
+
mime: meta.mime,
|
|
136
|
+
size: meta.size,
|
|
137
|
+
alt: meta.alt,
|
|
138
|
+
url,
|
|
139
|
+
thumbnailUrl: thumbnailFor(ctx, url, meta.mime),
|
|
140
|
+
width: meta.width,
|
|
141
|
+
height: meta.height,
|
|
142
|
+
};
|
|
143
|
+
}));
|
|
144
|
+
},
|
|
101
145
|
};
|
|
102
146
|
function parseMediaId(id) {
|
|
103
147
|
if (!/^[1-9]\d{0,15}$/.test(id))
|
package/dist/lookup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookup.js","sourceRoot":"","sources":["../src/lookup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lookup.js","sourceRoot":"","sources":["../src/lookup.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumix/plugin-media",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Media plugin for Plumix — uploads, library, and CDN delivery",
|
|
6
6
|
"license": "MIT",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@plumix/runtime-cloudflare": "0.6.0",
|
|
78
78
|
"@plumix/typescript-config": "0.0.0",
|
|
79
79
|
"@plumix/vitest-config": "0.0.0",
|
|
80
|
-
"plumix": "0.
|
|
80
|
+
"plumix": "0.7.0"
|
|
81
81
|
},
|
|
82
82
|
"prettier": "@plumix/prettier-config",
|
|
83
83
|
"plumix": {
|