@coffer-org/sdk 1.6.0 → 1.8.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/fields/convert.d.ts +14 -0
- package/dist/fields/convert.js +79 -0
- package/dist/fields.d.ts +6 -13
- package/dist/fields.js +7 -5
- package/dist/shelf.d.ts +3 -0
- package/dist/shelf.js +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ColumnType } from '../fields.ts';
|
|
2
|
+
export interface ColumnConversion {
|
|
3
|
+
from: string[];
|
|
4
|
+
to: {
|
|
5
|
+
name: string;
|
|
6
|
+
type: ColumnType;
|
|
7
|
+
}[];
|
|
8
|
+
map(src: Record<string, unknown>): Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare const URL_PARTS: readonly ["scheme", "username", "password", "host", "port", "path", "query", "hash"];
|
|
11
|
+
export declare function urlToLink(key: string): ColumnConversion;
|
|
12
|
+
export declare function linkToUrl(key: string): ColumnConversion;
|
|
13
|
+
export declare function scalarToArray(key: string): ColumnConversion;
|
|
14
|
+
export declare function arrayToScalar(key: string): ColumnConversion;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { parseUrl, buildUrl } from "./url.js";
|
|
2
|
+
export const URL_PARTS = ['scheme', 'username', 'password', 'host', 'port', 'path', 'query', 'hash'];
|
|
3
|
+
const urlColumns = (key) => URL_PARTS.map((p) => ({ name: `${key}__${p}`, type: p === 'port' ? 'integer' : 'text' }));
|
|
4
|
+
function partsToValue(key, src) {
|
|
5
|
+
const v = {};
|
|
6
|
+
for (const p of URL_PARTS) {
|
|
7
|
+
const raw = src[`${key}__${p}`];
|
|
8
|
+
if (raw == null || raw === '')
|
|
9
|
+
continue;
|
|
10
|
+
if (p === 'port') {
|
|
11
|
+
const n = Number(raw);
|
|
12
|
+
if (Number.isFinite(n))
|
|
13
|
+
v.port = n;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
v[p] = String(raw);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return v;
|
|
20
|
+
}
|
|
21
|
+
export function urlToLink(key) {
|
|
22
|
+
return {
|
|
23
|
+
from: URL_PARTS.map((p) => `${key}__${p}`),
|
|
24
|
+
to: [{ name: key, type: 'text' }],
|
|
25
|
+
map: (src) => ({ [key]: buildUrl(partsToValue(key, src)) || null }),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function linkToUrl(key) {
|
|
29
|
+
return {
|
|
30
|
+
from: [key],
|
|
31
|
+
to: urlColumns(key),
|
|
32
|
+
map: (src) => {
|
|
33
|
+
const raw = src[key];
|
|
34
|
+
const v = raw == null ? null : parseUrl(String(raw));
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const p of URL_PARTS)
|
|
37
|
+
out[`${key}__${p}`] = v?.[p] ?? null;
|
|
38
|
+
return out;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function scalarToArray(key) {
|
|
43
|
+
return {
|
|
44
|
+
from: [key],
|
|
45
|
+
to: [{ name: key, type: 'text' }],
|
|
46
|
+
map: (src) => {
|
|
47
|
+
const raw = src[key];
|
|
48
|
+
if (raw == null || raw === '')
|
|
49
|
+
return { [key]: null };
|
|
50
|
+
if (isJsonArray(raw))
|
|
51
|
+
return { [key]: raw };
|
|
52
|
+
return { [key]: JSON.stringify([raw]) };
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function arrayToScalar(key) {
|
|
57
|
+
return {
|
|
58
|
+
from: [key],
|
|
59
|
+
to: [{ name: key, type: 'text' }],
|
|
60
|
+
map: (src) => {
|
|
61
|
+
const raw = src[key];
|
|
62
|
+
if (raw == null || raw === '')
|
|
63
|
+
return { [key]: null };
|
|
64
|
+
if (!isJsonArray(raw))
|
|
65
|
+
return { [key]: raw };
|
|
66
|
+
try {
|
|
67
|
+
const arr = JSON.parse(String(raw));
|
|
68
|
+
const first = arr[0];
|
|
69
|
+
return { [key]: first == null ? null : typeof first === 'object' ? JSON.stringify(first) : first };
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return { [key]: raw };
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function isJsonArray(v) {
|
|
78
|
+
return typeof v === 'string' && v.trimStart().startsWith('[');
|
|
79
|
+
}
|
package/dist/fields.d.ts
CHANGED
|
@@ -105,6 +105,7 @@ export interface FieldClient {
|
|
|
105
105
|
export declare function group(o: {
|
|
106
106
|
key?: string;
|
|
107
107
|
label?: string;
|
|
108
|
+
icon?: string;
|
|
108
109
|
fields: LayoutEl[];
|
|
109
110
|
multiple?: boolean;
|
|
110
111
|
required?: boolean;
|
|
@@ -115,34 +116,27 @@ export declare function group(o: {
|
|
|
115
116
|
view?: {
|
|
116
117
|
display?: GroupDisplay;
|
|
117
118
|
kind?: string;
|
|
118
|
-
icon?: string;
|
|
119
119
|
};
|
|
120
120
|
}): GroupEl;
|
|
121
121
|
export declare function row(o: {
|
|
122
122
|
label?: string;
|
|
123
|
+
icon?: string;
|
|
123
124
|
fields: LayoutEl[];
|
|
124
|
-
view?: {
|
|
125
|
-
icon?: string;
|
|
126
|
-
};
|
|
127
125
|
}): GroupEl;
|
|
128
126
|
export declare function table(o: {
|
|
129
127
|
key: string;
|
|
130
128
|
label: string;
|
|
129
|
+
icon?: string;
|
|
131
130
|
fields: LayoutEl[];
|
|
132
131
|
rules?: {
|
|
133
132
|
unique?: string[];
|
|
134
133
|
};
|
|
135
134
|
required?: boolean;
|
|
136
|
-
view?: {
|
|
137
|
-
icon?: string;
|
|
138
|
-
};
|
|
139
135
|
}): GroupEl;
|
|
140
136
|
export declare function sheet(o: {
|
|
141
137
|
label?: string;
|
|
138
|
+
icon?: string;
|
|
142
139
|
fields: LayoutEl[][];
|
|
143
|
-
view?: {
|
|
144
|
-
icon?: string;
|
|
145
|
-
};
|
|
146
140
|
}): GroupEl;
|
|
147
141
|
export declare function url(o: {
|
|
148
142
|
key: string;
|
|
@@ -153,15 +147,13 @@ type ContainerFactory = typeof row | typeof group | typeof table;
|
|
|
153
147
|
export declare function keyed(o: {
|
|
154
148
|
key: string;
|
|
155
149
|
label: string;
|
|
150
|
+
icon?: string;
|
|
156
151
|
container?: ContainerFactory;
|
|
157
152
|
by: FieldItem;
|
|
158
153
|
fields: LayoutEl[];
|
|
159
154
|
fixed?: boolean;
|
|
160
155
|
unique?: string[];
|
|
161
156
|
required?: boolean;
|
|
162
|
-
view?: {
|
|
163
|
-
icon?: string;
|
|
164
|
-
};
|
|
165
157
|
}): GroupEl;
|
|
166
158
|
export declare const isStorageGroup: (g: GroupEl) => boolean;
|
|
167
159
|
export declare const isCollectionGroup: (g: GroupEl) => boolean;
|
|
@@ -208,6 +200,7 @@ export interface FieldMeta extends FieldClient {
|
|
|
208
200
|
export declare function isJsonStored(field: FieldMeta | FieldClient): boolean;
|
|
209
201
|
export { LANGUAGES, SEX_OPTIONS, WEEKDAY_OPTIONS } from './fields/constants.ts';
|
|
210
202
|
export { parseUrl, buildUrl, hrefOf, type UrlValue } from './fields/url.ts';
|
|
203
|
+
export { URL_PARTS, urlToLink, linkToUrl, scalarToArray, arrayToScalar, type ColumnConversion, } from './fields/convert.ts';
|
|
211
204
|
export declare function applyMultiple(base: FieldMeta, multiple: boolean): FieldMeta;
|
|
212
205
|
export type StringOpts = FieldCoreOpts;
|
|
213
206
|
export declare function string(o: StringOpts & {
|
package/dist/fields.js
CHANGED
|
@@ -35,7 +35,7 @@ export function group(o) {
|
|
|
35
35
|
required: o.required,
|
|
36
36
|
unique: r.unique,
|
|
37
37
|
label: o.label,
|
|
38
|
-
icon:
|
|
38
|
+
icon: o.icon,
|
|
39
39
|
display: v.display ?? 'wrap',
|
|
40
40
|
kind: v.kind,
|
|
41
41
|
fixed: r.fixed,
|
|
@@ -43,17 +43,18 @@ export function group(o) {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
export function row(o) {
|
|
46
|
-
return group({ label: o.label, fields: o.fields, view: {
|
|
46
|
+
return group({ label: o.label, icon: o.icon, fields: o.fields, view: { display: 'scroll' } });
|
|
47
47
|
}
|
|
48
48
|
export function table(o) {
|
|
49
49
|
return group({
|
|
50
50
|
key: o.key,
|
|
51
51
|
label: o.label,
|
|
52
|
+
icon: o.icon,
|
|
52
53
|
fields: o.fields,
|
|
53
54
|
multiple: true,
|
|
54
55
|
required: o.required,
|
|
55
56
|
rules: o.rules,
|
|
56
|
-
view: {
|
|
57
|
+
view: { display: 'table' },
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
export function sheet(o) {
|
|
@@ -63,7 +64,7 @@ export function sheet(o) {
|
|
|
63
64
|
flat.push(brk());
|
|
64
65
|
flat.push(...rowFields);
|
|
65
66
|
});
|
|
66
|
-
return group({ label: o.label, fields: flat, view: {
|
|
67
|
+
return group({ label: o.label, icon: o.icon, fields: flat, view: { display: 'sheet' } });
|
|
67
68
|
}
|
|
68
69
|
export function url(o) {
|
|
69
70
|
return group({
|
|
@@ -87,7 +88,7 @@ export function keyed(o) {
|
|
|
87
88
|
if (o.fixed && o.by.type.prim !== 'select')
|
|
88
89
|
throw new Error(`[field.keyed] fixed requires by=select (enumerated), got '${o.by.type.prim}'`);
|
|
89
90
|
const make = (o.container ?? group);
|
|
90
|
-
const g = make({ label: o.label, fields: [o.by, ...o.fields]
|
|
91
|
+
const g = make({ label: o.label, icon: o.icon, fields: [o.by, ...o.fields] });
|
|
91
92
|
return {
|
|
92
93
|
...g,
|
|
93
94
|
key: o.key,
|
|
@@ -139,6 +140,7 @@ export function isJsonStored(field) {
|
|
|
139
140
|
}
|
|
140
141
|
export { LANGUAGES, SEX_OPTIONS, WEEKDAY_OPTIONS } from "./fields/constants.js";
|
|
141
142
|
export { parseUrl, buildUrl, hrefOf } from "./fields/url.js";
|
|
143
|
+
export { URL_PARTS, urlToLink, linkToUrl, scalarToArray, arrayToScalar, } from "./fields/convert.js";
|
|
142
144
|
function resolveDate(v) {
|
|
143
145
|
return v === 'today' ? new Date().toISOString().slice(0, 10) : v;
|
|
144
146
|
}
|
package/dist/shelf.d.ts
CHANGED
|
@@ -43,6 +43,9 @@ export declare function inlineText(m: ShelfDef, row: Record<string, unknown>): s
|
|
|
43
43
|
export declare function tableKeys(m: ShelfDef): string[];
|
|
44
44
|
export declare function groupableFields(m: ShelfDef): string[];
|
|
45
45
|
export declare function defaultGroupField(m: ShelfDef): string | undefined;
|
|
46
|
+
export declare function coverKey(m: ShelfDef): string | undefined;
|
|
47
|
+
export declare function listKeys(m: ShelfDef): string[];
|
|
48
|
+
export declare function storageColumnsFor(m: ShelfDef, keys: string[]): string[];
|
|
46
49
|
export declare function buildShape(fields: LayoutEl[], partial: boolean): z.ZodRawShape;
|
|
47
50
|
export declare function buildZodObject(m: ShelfDef): z.ZodTypeAny;
|
|
48
51
|
export declare function buildZodObjectPartial(m: ShelfDef): z.ZodTypeAny;
|
package/dist/shelf.js
CHANGED
|
@@ -132,6 +132,45 @@ export function defaultGroupField(m) {
|
|
|
132
132
|
}
|
|
133
133
|
return groupableFields(m)[0];
|
|
134
134
|
}
|
|
135
|
+
export function coverKey(m) {
|
|
136
|
+
return fieldEntries(m.fields).find(([, f]) => f.kind === 'cover')?.[0];
|
|
137
|
+
}
|
|
138
|
+
export function listKeys(m) {
|
|
139
|
+
const fm = fieldMap(m.fields);
|
|
140
|
+
const out = [];
|
|
141
|
+
const add = (k) => {
|
|
142
|
+
if (!k || k === 'id' || out.includes(k))
|
|
143
|
+
return;
|
|
144
|
+
if (!fm[k] || fm[k].virtual)
|
|
145
|
+
return;
|
|
146
|
+
out.push(k);
|
|
147
|
+
};
|
|
148
|
+
add(titleKey(m));
|
|
149
|
+
tableKeys(m).forEach(add);
|
|
150
|
+
groupableFields(m).forEach(add);
|
|
151
|
+
inlineKeys(m).forEach(add);
|
|
152
|
+
add(inlineImageKey(m));
|
|
153
|
+
add(coverKey(m));
|
|
154
|
+
const sel = m.views?.select;
|
|
155
|
+
if (sel) {
|
|
156
|
+
add(sel.icon);
|
|
157
|
+
(Array.isArray(sel.title) ? sel.title : [sel.title]).forEach(add);
|
|
158
|
+
add(sel.subtitle);
|
|
159
|
+
}
|
|
160
|
+
return ['id', ...out];
|
|
161
|
+
}
|
|
162
|
+
export function storageColumnsFor(m, keys) {
|
|
163
|
+
const fm = fieldMap(m.fields);
|
|
164
|
+
const out = new Set(['id']);
|
|
165
|
+
for (const k of keys) {
|
|
166
|
+
const f = fm[k];
|
|
167
|
+
if (!f || f.virtual)
|
|
168
|
+
continue;
|
|
169
|
+
for (const [col] of storageColumns(k, f))
|
|
170
|
+
out.add(col);
|
|
171
|
+
}
|
|
172
|
+
return [...out];
|
|
173
|
+
}
|
|
135
174
|
export function buildShape(fields, partial) {
|
|
136
175
|
const shape = {};
|
|
137
176
|
for (const it of fields) {
|