@coffer-org/sdk 2.1.2 → 2.2.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/field-presets.d.ts +17 -0
- package/dist/field-presets.js +30 -1
- package/dist/fields/normalize.d.ts +4 -0
- package/dist/fields/normalize.js +2 -0
- package/dist/fields.d.ts +1 -0
- package/dist/fields.js +25 -5
- package/dist/shelf.d.ts +1 -0
- package/dist/shelf.js +3 -1
- package/package.json +1 -1
package/dist/field-presets.d.ts
CHANGED
|
@@ -152,6 +152,22 @@ export declare function snippet(o: CodeOpts & {
|
|
|
152
152
|
key?: undefined;
|
|
153
153
|
value?: undefined;
|
|
154
154
|
}): FieldMeta;
|
|
155
|
+
export declare const SOURCE_DEFAULT_MAX_BYTES = 262144;
|
|
156
|
+
export declare function isBinaryText(v: string): boolean;
|
|
157
|
+
export interface SourceOpts extends FieldCoreOpts {
|
|
158
|
+
label?: string;
|
|
159
|
+
}
|
|
160
|
+
export declare function source(o: SourceOpts & {
|
|
161
|
+
key: string;
|
|
162
|
+
}): FieldItem;
|
|
163
|
+
export declare function source(o: SourceOpts & {
|
|
164
|
+
value: unknown;
|
|
165
|
+
key?: undefined;
|
|
166
|
+
}): StaticEl;
|
|
167
|
+
export declare function source(o: SourceOpts & {
|
|
168
|
+
key?: undefined;
|
|
169
|
+
value?: undefined;
|
|
170
|
+
}): FieldMeta;
|
|
155
171
|
export interface RatingOpts extends FieldCoreOpts {
|
|
156
172
|
label?: string;
|
|
157
173
|
}
|
|
@@ -242,6 +258,7 @@ export declare const presets: {
|
|
|
242
258
|
tags: typeof tags;
|
|
243
259
|
markdown: typeof markdown;
|
|
244
260
|
snippet: typeof snippet;
|
|
261
|
+
source: typeof source;
|
|
245
262
|
rating: typeof rating;
|
|
246
263
|
duration: typeof duration;
|
|
247
264
|
reminder: typeof reminder;
|
package/dist/field-presets.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { real, int, text, date, select, string, group, vmsg, jsonRefined, typeErr, optionalize, applyMultiple, wrapKey, normalizeOpts, } from "./fields.js";
|
|
2
|
+
import { real, int, text, date, select, string, group, vmsg, jsonRefined, typeErr, reqTypeErr, optionalize, applyMultiple, wrapKey, normalizeOpts, } from "./fields.js";
|
|
3
3
|
export function email(raw) {
|
|
4
4
|
const o = normalizeOpts(raw);
|
|
5
5
|
const required = o.required ?? false;
|
|
@@ -225,6 +225,34 @@ export function snippet(raw) {
|
|
|
225
225
|
};
|
|
226
226
|
return wrapKey(norm, meta);
|
|
227
227
|
}
|
|
228
|
+
export const SOURCE_DEFAULT_MAX_BYTES = 262_144;
|
|
229
|
+
export function isBinaryText(v) {
|
|
230
|
+
return v.includes('\x00') || v.includes('�');
|
|
231
|
+
}
|
|
232
|
+
export function source(raw) {
|
|
233
|
+
const o = normalizeOpts(raw);
|
|
234
|
+
const required = o.required ?? false;
|
|
235
|
+
const ext = o.ext ?? 'txt';
|
|
236
|
+
const maxBytes = o.maxBytes ?? SOURCE_DEFAULT_MAX_BYTES;
|
|
237
|
+
const s = z.string(reqTypeErr()).superRefine((v, ctx) => {
|
|
238
|
+
if (isBinaryText(v)) {
|
|
239
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: vmsg('source_binary') });
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (new TextEncoder().encode(v).length > maxBytes)
|
|
243
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: vmsg('source_too_large', { maxBytes }) });
|
|
244
|
+
});
|
|
245
|
+
const meta = {
|
|
246
|
+
kind: 'source',
|
|
247
|
+
label: o.label ?? '',
|
|
248
|
+
required,
|
|
249
|
+
prim: 'text',
|
|
250
|
+
column: 'text',
|
|
251
|
+
hints: { ext, maxBytes, noEditControl: true },
|
|
252
|
+
zod: optionalize(s, required),
|
|
253
|
+
};
|
|
254
|
+
return wrapKey(o, meta);
|
|
255
|
+
}
|
|
228
256
|
export function rating(raw) {
|
|
229
257
|
const o = normalizeOpts(raw);
|
|
230
258
|
const required = o.required ?? false;
|
|
@@ -328,6 +356,7 @@ export const presets = {
|
|
|
328
356
|
tags,
|
|
329
357
|
markdown,
|
|
330
358
|
snippet,
|
|
359
|
+
source,
|
|
331
360
|
rating,
|
|
332
361
|
duration,
|
|
333
362
|
reminder,
|
|
@@ -13,6 +13,8 @@ export interface Rules {
|
|
|
13
13
|
unique?: string[];
|
|
14
14
|
fixed?: boolean;
|
|
15
15
|
exts?: string[];
|
|
16
|
+
ext?: string;
|
|
17
|
+
maxBytes?: number;
|
|
16
18
|
lead?: number;
|
|
17
19
|
by?: FieldItem;
|
|
18
20
|
}
|
|
@@ -66,6 +68,8 @@ export type NormalizedOpts = {
|
|
|
66
68
|
unique?: string[];
|
|
67
69
|
fixed?: boolean;
|
|
68
70
|
exts?: string[];
|
|
71
|
+
ext?: string;
|
|
72
|
+
maxBytes?: number;
|
|
69
73
|
lead?: number;
|
|
70
74
|
by?: FieldItem;
|
|
71
75
|
min?: number | string;
|
package/dist/fields/normalize.js
CHANGED
package/dist/fields.d.ts
CHANGED
package/dist/fields.js
CHANGED
|
@@ -509,13 +509,30 @@ export function check(raw) {
|
|
|
509
509
|
const required = o.required ?? false;
|
|
510
510
|
const multiple = o.multiple ?? false;
|
|
511
511
|
const slots = o.slots && o.slots.length > 0 ? o.slots : [''];
|
|
512
|
+
const contentFields = o.fields?.length
|
|
513
|
+
? o.fields
|
|
514
|
+
: [string({ key: 'text', label: 'core.fields.text' })];
|
|
515
|
+
const contentKeys = new Set();
|
|
516
|
+
for (const f of contentFields) {
|
|
517
|
+
if (contentKeys.has(f.key))
|
|
518
|
+
throw new Error(`[field.check] duplicate content field '${f.key}'`);
|
|
519
|
+
if (/^check\d+$/.test(f.key))
|
|
520
|
+
throw new Error(`[field.check] content field '${f.key}' is reserved for checkbox slots`);
|
|
521
|
+
if (!multiple && (f.type.virtual || f.type.columns))
|
|
522
|
+
throw new Error(`[field.check] single content field '${f.key}' must be a scalar stored field`);
|
|
523
|
+
contentKeys.add(f.key);
|
|
524
|
+
}
|
|
525
|
+
const checkFields = slots.map((label, i) => boolean({ key: `check${i}`, label: label || 'core.fields.check' }));
|
|
512
526
|
if (multiple) {
|
|
513
|
-
const fields =
|
|
514
|
-
fields.push(string({ key: 'text', label: 'core.fields.text' }));
|
|
527
|
+
const fields = [...checkFields, ...contentFields];
|
|
515
528
|
return group({ key: o.key, label: o.label ?? o.key, multiple: true, required: required, fields, view: { kind: 'checklist' } });
|
|
516
529
|
}
|
|
517
|
-
const shape = {
|
|
518
|
-
const columns = {
|
|
530
|
+
const shape = {};
|
|
531
|
+
const columns = {};
|
|
532
|
+
for (const f of contentFields) {
|
|
533
|
+
shape[f.key] = f.type.zod;
|
|
534
|
+
columns[f.key] = f.type.column;
|
|
535
|
+
}
|
|
519
536
|
slots.forEach((_, i) => {
|
|
520
537
|
shape[`check${i}`] = z.boolean();
|
|
521
538
|
columns[`check${i}`] = 'boolean';
|
|
@@ -536,7 +553,10 @@ export function check(raw) {
|
|
|
536
553
|
required,
|
|
537
554
|
prim: 'check',
|
|
538
555
|
column: 'text',
|
|
539
|
-
hints: {
|
|
556
|
+
hints: {
|
|
557
|
+
slots,
|
|
558
|
+
fields: contentFields.map((f) => ({ key: f.key, ...toClient(f.type) })),
|
|
559
|
+
},
|
|
540
560
|
columns,
|
|
541
561
|
zod: optionalize(s, required),
|
|
542
562
|
};
|
package/dist/shelf.d.ts
CHANGED
package/dist/shelf.js
CHANGED
|
@@ -68,7 +68,9 @@ export function defineShelf(m) {
|
|
|
68
68
|
const dup = keys.find((k, i) => keys.indexOf(k) !== i);
|
|
69
69
|
if (dup)
|
|
70
70
|
throw new Error(`[shelf] ${m.library}/${m.shelf}: duplicate key '${dup}'`);
|
|
71
|
-
if (m.
|
|
71
|
+
if (m.single && !m.claude)
|
|
72
|
+
throw new Error(`[shelf] ${m.library}/${m.shelf}: single shelf requires \`claude\` — the agent cannot find it otherwise`);
|
|
73
|
+
if (m.standalone !== false && !m.single && !m.views?.list?.fields?.length)
|
|
72
74
|
console.warn(`[shelf] ${m.library}/${m.shelf}: standalone shelf without an explicit views.list`);
|
|
73
75
|
return m;
|
|
74
76
|
}
|