@coffer-org/sdk 2.2.1 → 3.1.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.
@@ -17,6 +17,13 @@ export interface Condition {
17
17
  $or?: Condition[];
18
18
  }
19
19
  export type Values = Record<string, unknown>;
20
+ export declare const COMPILABLE_SCALAR_OPS: Set<string>;
21
+ export declare const COMPILABLE_ARRAY_OPS: Set<string>;
20
22
  export declare function evalCondition(cond: Condition | undefined, values: Values): boolean;
21
23
  export declare function resolveFlag(v: boolean | Condition | undefined, values: Values): boolean;
24
+ export declare function conditionKeys(cond: Condition | undefined): string[];
25
+ export declare function visibleOptions<T extends {
26
+ value?: string;
27
+ when?: Condition;
28
+ }>(options: T[], values: Values, keep?: string | string[]): T[];
22
29
  export declare function describeCondition(cond: Condition | undefined, labelOf: (field: string) => string, valueLabelOf?: (field: string, value: Scalar) => string): string[];
package/dist/condition.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import sift from 'sift';
2
+ export const COMPILABLE_SCALAR_OPS = new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte']);
3
+ export const COMPILABLE_ARRAY_OPS = new Set(['$in', '$nin']);
2
4
  const createEqualsOperation = sift
3
5
  .createEqualsOperation;
4
6
  const isScalar = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
@@ -62,6 +64,26 @@ function describePredicate(label, pred, vl) {
62
64
  }
63
65
  return out;
64
66
  }
67
+ export function conditionKeys(cond) {
68
+ if (!cond)
69
+ return [];
70
+ const out = [];
71
+ for (const [key, spec] of Object.entries(cond)) {
72
+ if (spec === undefined)
73
+ continue;
74
+ if (key === '$and' || key === '$or') {
75
+ for (const c of spec)
76
+ out.push(...conditionKeys(c));
77
+ continue;
78
+ }
79
+ out.push(key);
80
+ }
81
+ return [...new Set(out)];
82
+ }
83
+ export function visibleOptions(options, values, keep) {
84
+ const kept = keep === undefined ? undefined : new Set(Array.isArray(keep) ? keep : [keep]);
85
+ return options.filter((o) => (kept !== undefined && o.value !== undefined && kept.has(o.value)) || (o.when ? evalCondition(o.when, values) : true));
86
+ }
65
87
  export function describeCondition(cond, labelOf, valueLabelOf) {
66
88
  if (!cond)
67
89
  return [];
@@ -0,0 +1,12 @@
1
+ import { type LayoutEl } from './fields.ts';
2
+ export interface DeriveCtx {
3
+ record: Record<string, unknown>;
4
+ }
5
+ export type DeriveFn = (ctx: DeriveCtx) => unknown;
6
+ export interface DeriveSpec {
7
+ deps: string[];
8
+ fn: DeriveFn;
9
+ }
10
+ export declare function derivedEntries(fields: LayoutEl[]): [string, DeriveSpec][];
11
+ export declare function applyDerived(fields: LayoutEl[], record: Record<string, unknown>): Record<string, unknown>;
12
+ export declare function derivableKeys(fields: LayoutEl[]): Set<string>;
package/dist/derive.js ADDED
@@ -0,0 +1,42 @@
1
+ import { isField, isGroup } from "./fields.js";
2
+ export function derivedEntries(fields) {
3
+ const out = [];
4
+ for (const it of fields) {
5
+ if (isField(it)) {
6
+ const spec = it.type.derive;
7
+ if (spec)
8
+ out.push([it.key, spec]);
9
+ }
10
+ else if (isGroup(it) && !it.key) {
11
+ out.push(...derivedEntries(it.fields));
12
+ }
13
+ }
14
+ return out;
15
+ }
16
+ export function applyDerived(fields, record) {
17
+ const out = {};
18
+ for (const [key, spec] of derivedEntries(fields)) {
19
+ try {
20
+ out[key] = spec.fn({ record });
21
+ }
22
+ catch (e) {
23
+ console.warn(`[derive] '${key}' threw`, e);
24
+ }
25
+ }
26
+ return out;
27
+ }
28
+ export function derivableKeys(fields) {
29
+ const keys = new Set();
30
+ for (const it of fields) {
31
+ if (isField(it))
32
+ keys.add(it.key);
33
+ else if (isGroup(it)) {
34
+ if (it.key)
35
+ keys.add(it.key);
36
+ if (!it.key)
37
+ for (const k of derivableKeys(it.fields))
38
+ keys.add(k);
39
+ }
40
+ }
41
+ return keys;
42
+ }
@@ -375,7 +375,7 @@ export function source(raw) {
375
375
  required,
376
376
  prim: 'text',
377
377
  column: 'text',
378
- hints: { ext, maxBytes, noEditControl: true },
378
+ hints: { ext, maxBytes, noEditControl: true, ...(o.key ? { fileName: o.key } : {}) },
379
379
  zod: optionalize(s, required),
380
380
  };
381
381
  return wrapKey(o, meta);
package/dist/fields.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { type UnitsSpec } from './units.ts';
2
3
  export { vmsg, reqErr, typeErr, reqTypeErr, jsonRefined, optionalize, jsonValue, decodeVmsg, validateField, } from './fields/validation.ts';
3
4
  import type { Condition } from './condition.ts';
4
5
  export type { Rules, View, FieldConfig } from './fields/normalize.ts';
@@ -23,6 +24,7 @@ export interface OptionItem {
23
24
  title: string;
24
25
  icon?: OptionIcon;
25
26
  subtitle?: string;
27
+ when?: Condition;
26
28
  }
27
29
  declare const __fieldItemBrand: unique symbol;
28
30
  export interface FieldItem {
@@ -95,10 +97,12 @@ export interface FieldClient {
95
97
  relation?: {
96
98
  library: string;
97
99
  shelf: string;
100
+ filter?: Condition;
98
101
  };
99
102
  virtual?: boolean;
100
103
  default?: string | number | boolean | null;
101
104
  json?: true;
105
+ derived?: true;
102
106
  columns?: Record<string, ColumnType>;
103
107
  hidden?: boolean | Condition;
104
108
  }
@@ -180,6 +184,7 @@ export interface FieldCoreOpts {
180
184
  emphasis?: 'hero' | 'muted';
181
185
  noLabel?: boolean;
182
186
  role?: 'cover' | 'avatar';
187
+ derive?: import('./derive.ts').DeriveSpec;
183
188
  }
184
189
  export declare function wrapKey(opts: {
185
190
  key?: string;
@@ -190,10 +195,12 @@ export declare function wrapKey(opts: {
190
195
  emphasis?: 'hero' | 'muted';
191
196
  noLabel?: boolean;
192
197
  role?: 'cover' | 'avatar';
198
+ derive?: import('./derive.ts').DeriveSpec;
193
199
  }, meta: FieldMeta): FieldItem | StaticEl | FieldMeta;
194
200
  export interface FieldMeta extends FieldClient {
195
201
  column: ColumnType;
196
202
  zod: z.ZodTypeAny;
203
+ derive?: import('./derive.ts').DeriveSpec;
197
204
  }
198
205
  export declare function isJsonStored(field: FieldMeta | FieldClient): boolean;
199
206
  export { LANGUAGES, SEX_OPTIONS, WEEKDAY_OPTIONS } from './fields/constants.ts';
@@ -372,6 +379,7 @@ export interface RelationOpts extends FieldCoreOpts {
372
379
  options: {
373
380
  library: string;
374
381
  shelf: string;
382
+ filter?: Condition;
375
383
  };
376
384
  }
377
385
  export declare function relation(o: RelationOpts & {
@@ -427,6 +435,27 @@ export declare function measured(o: MeasuredOpts & {
427
435
  key?: undefined;
428
436
  value?: undefined;
429
437
  }): FieldMeta;
438
+ export type UnitScope = string;
439
+ export interface UnitOpts extends FieldCoreOpts {
440
+ options: UnitsSpec;
441
+ }
442
+ export declare function unit(o: UnitOpts & {
443
+ key: string;
444
+ }): FieldItem;
445
+ export declare function unit(o: UnitOpts & {
446
+ key?: undefined;
447
+ value?: undefined;
448
+ }): FieldMeta;
449
+ export interface AmountOpts extends FieldCoreOpts {
450
+ unitFrom: UnitScope;
451
+ }
452
+ export declare function amount(o: AmountOpts & {
453
+ key: string;
454
+ }): FieldItem;
455
+ export declare function amount(o: AmountOpts & {
456
+ key?: undefined;
457
+ value?: undefined;
458
+ }): FieldMeta;
430
459
  export type MoneyOpts = FieldCoreOpts;
431
460
  export declare function money(o: MoneyOpts & {
432
461
  key: string;
@@ -667,6 +696,8 @@ declare const PRIMITIVES: {
667
696
  json: typeof json;
668
697
  check: typeof check;
669
698
  measured: typeof measured;
699
+ unit: typeof unit;
700
+ amount: typeof amount;
670
701
  money: typeof money;
671
702
  code: typeof code;
672
703
  geo: typeof geo;
package/dist/fields.js CHANGED
@@ -127,6 +127,8 @@ export function wrapKey(opts, meta) {
127
127
  m = { ...m, default: opts.default };
128
128
  if (opts.hidden !== undefined)
129
129
  m = { ...m, hidden: opts.hidden };
130
+ if (opts.derive)
131
+ m = { ...m, derive: opts.derive, derived: true, hints: { ...m.hints, noEditControl: true } };
130
132
  if (opts.key)
131
133
  return { key: opts.key, type: m };
132
134
  if ('value' in opts && opts.value !== undefined)
@@ -451,10 +453,20 @@ export function select(raw) {
451
453
  const meta = applyMultiple(base, o.multiple ?? false);
452
454
  return wrapKey(o, meta);
453
455
  }
456
+ function assertFlatEqualityFilter(filter) {
457
+ for (const [key, value] of Object.entries(filter)) {
458
+ if (key.startsWith('$'))
459
+ throw new Error(`[relation] filter key '${key}' is an operator — only flat equality is allowed here`);
460
+ if (value === undefined || (value !== null && typeof value === 'object'))
461
+ throw new Error(`[relation] filter key '${key}' has a non-scalar value — only flat equality is allowed here`);
462
+ }
463
+ }
454
464
  export function relation(raw) {
455
465
  const o = normalizeOpts(raw);
456
466
  const required = o.required ?? false;
457
467
  const multi = o.multiple ?? false;
468
+ if (raw.options.filter)
469
+ assertFlatEqualityFilter(raw.options.filter);
458
470
  let s;
459
471
  if (multi) {
460
472
  s = z.unknown().superRefine((raw, ctx) => {
@@ -476,7 +488,11 @@ export function relation(raw) {
476
488
  prim: 'relation',
477
489
  column: multi ? 'text' : 'integer',
478
490
  hints: { multi, displayKey: o.displayKey ?? 'name' },
479
- relation: { library: raw.options.library, shelf: raw.options.shelf },
491
+ relation: {
492
+ library: raw.options.library,
493
+ shelf: raw.options.shelf,
494
+ ...(raw.options.filter && { filter: raw.options.filter }),
495
+ },
480
496
  ...(multi && { json: true }),
481
497
  zod: optionalize(s, required),
482
498
  };
@@ -635,6 +651,45 @@ export function measured(raw) {
635
651
  };
636
652
  return wrapKey(o, meta);
637
653
  }
654
+ export function unit(raw) {
655
+ const o = normalizeOpts(raw);
656
+ const required = o.required ?? false;
657
+ const units = resolveUnits(o.options);
658
+ const s = z
659
+ .string(reqErr())
660
+ .refine((v) => units.some((u) => u.value === v), { message: vmsg('measured_unit') });
661
+ const meta = {
662
+ kind: 'unit',
663
+ label: o.label ?? '',
664
+ required,
665
+ prim: 'select',
666
+ column: 'text',
667
+ hints: { source: typeof o.options === 'string' ? o.options : null },
668
+ options: units.map((u) => ({ value: u.value, title: u.label })),
669
+ zod: optionalize(s, required),
670
+ };
671
+ return wrapKey(o, meta);
672
+ }
673
+ export function amount(raw) {
674
+ const o = normalizeOpts(raw);
675
+ const required = o.required ?? false;
676
+ const cfg = (o.config ?? {});
677
+ let s = z.coerce.number(typeErr());
678
+ if (cfg.min != null)
679
+ s = s.min(cfg.min, { message: vmsg('min', { min: cfg.min }) });
680
+ if (cfg.max != null)
681
+ s = s.max(cfg.max, { message: vmsg('max', { max: cfg.max }) });
682
+ const meta = {
683
+ kind: 'amount',
684
+ label: o.label ?? '',
685
+ required,
686
+ prim: 'number',
687
+ column: 'real',
688
+ hints: { unitFrom: o.unitFrom, min: cfg.min, max: cfg.max, step: cfg.step ?? 'any' },
689
+ zod: optionalize(s, required),
690
+ };
691
+ return wrapKey(o, meta);
692
+ }
638
693
  export function money(raw) {
639
694
  const o = normalizeOpts(raw);
640
695
  const required = o.required ?? false;
@@ -1022,6 +1077,8 @@ const PRIMITIVES = {
1022
1077
  json,
1023
1078
  check,
1024
1079
  measured,
1080
+ unit,
1081
+ amount,
1025
1082
  money,
1026
1083
  code,
1027
1084
  geo,
@@ -1065,6 +1122,6 @@ export const field = new Proxy({}, {
1065
1122
  has: (_t, k) => k in composedField(),
1066
1123
  });
1067
1124
  export function toClient(field) {
1068
- const { kind, label, required, prim, hints, options, relation, virtual, json, hidden } = field;
1069
- return { kind, label, required, prim, hints, options, relation, virtual, json, hidden };
1125
+ const { kind, label, required, prim, hints, options, relation, virtual, json, hidden, derived } = field;
1126
+ return { kind, label, required, prim, hints, options, relation, virtual, json, hidden, derived };
1070
1127
  }
package/dist/plugin.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { ShelfDef } from './shelf.ts';
3
3
  import type { ExtendDef } from './extend.ts';
4
4
  import type { OptionItem } from './fields.ts';
5
5
  import type { SettingsDef } from './settings.ts';
6
+ import type { ShowcaseDef } from './showcase.ts';
6
7
  export interface FieldContrib {
7
8
  library: string;
8
9
  shelf: string;
@@ -24,6 +25,7 @@ export interface PluginManifest {
24
25
  fieldContribs?: FieldContrib[];
25
26
  optionLists?: NamedOptionList[];
26
27
  settings?: SettingsDef;
28
+ showcases?: ShowcaseDef[];
27
29
  }
28
30
  export declare const BASE_PLUGIN = "core";
29
31
  export declare function definePlugin(p: PluginManifest): PluginManifest;
package/dist/shelf.d.ts CHANGED
@@ -1,14 +1,11 @@
1
1
  import { z } from 'zod';
2
2
  import type { FieldMeta, LayoutEl, ColumnType } from './fields.ts';
3
3
  import type { FieldClient, GroupEl, PseudoEl } from './fields.ts';
4
- export interface ShelfListView {
5
- kind?: string;
6
- fields: string[];
7
- }
8
4
  export interface ShelfViews {
9
5
  title?: string;
10
6
  inline?: string[];
11
- list?: ShelfListView;
7
+ list?: string[];
8
+ listKind?: string;
12
9
  groupBy?: string[];
13
10
  defaultGroupBy?: string;
14
11
  select?: {
package/dist/shelf.js CHANGED
@@ -2,6 +2,8 @@ import { z } from 'zod';
2
2
  import { toClient, isField, isGroup, isStatic, isCollectionGroup, isEmbeddedGroup } from "./fields.js";
3
3
  import { resolveFlag } from "./condition.js";
4
4
  import { parseUrl } from "./fields/url.js";
5
+ import { vmsg } from "./fields/validation.js";
6
+ import { derivedEntries, derivableKeys } from "./derive.js";
5
7
  export function fieldEntries(items) {
6
8
  const out = [];
7
9
  for (const it of items) {
@@ -70,24 +72,45 @@ export function defineShelf(m) {
70
72
  throw new Error(`[shelf] ${m.library}/${m.shelf}: duplicate key '${dup}'`);
71
73
  if (m.single && !m.claude)
72
74
  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)
75
+ if (m.views?.list !== undefined && !Array.isArray(m.views.list))
76
+ throw new Error(`[shelf] ${m.library}/${m.shelf}: views.list is a flat array of field keys — ` +
77
+ `the { kind, fields } form is gone; use views.list: [...] plus views.listKind`);
78
+ if (m.standalone !== false && !m.single && !m.views?.list?.length)
74
79
  console.warn(`[shelf] ${m.library}/${m.shelf}: standalone shelf without an explicit views.list`);
80
+ if (m.views?.title && !ownFieldEntries(m.fields).some(([k]) => k === m.views.title))
81
+ throw new Error(`[shelf] ${m.library}/${m.shelf}: views.title '${m.views.title}' is not a field`);
82
+ if (m.views?.list?.includes(titleKey(m)))
83
+ console.warn(`[shelf] ${m.library}/${m.shelf}: views.list repeats the title '${titleKey(m)}' — the title is declared separately`);
84
+ const titles = ownFieldEntries(m.fields).filter(([, f]) => f.kind === 'title');
85
+ if (titles.length > 1)
86
+ console.warn(`[shelf] ${m.library}/${m.shelf}: ${titles.length} title fields (${titles.map(([k]) => k).join(', ')}) — '${titles[0][0]}' wins`);
87
+ if (m.standalone !== false && !m.single && titleKey(m) === 'id')
88
+ console.warn(`[shelf] ${m.library}/${m.shelf}: no title declared (field.title() or views.title) — the record renders no heading`);
89
+ const known = derivableKeys(m.fields);
90
+ for (const [key, spec] of derivedEntries(m.fields)) {
91
+ for (const dep of spec.deps) {
92
+ if (!known.has(dep))
93
+ throw new Error(`[defineShelf] ${m.library}/${m.shelf}: derive on '${key}' depends on unknown key '${dep}'`);
94
+ }
95
+ }
75
96
  return m;
76
97
  }
77
98
  export const SYSTEM_FIELDS = ['id', 'createdAt', 'updatedAt'];
99
+ function ownFieldEntries(items) {
100
+ const out = [];
101
+ for (const it of items) {
102
+ if (isField(it))
103
+ out.push([it.key, it.type]);
104
+ else if (isGroup(it) && !isCollectionGroup(it) && !isEmbeddedGroup(it))
105
+ out.push(...ownFieldEntries(it.fields));
106
+ }
107
+ return out;
108
+ }
78
109
  export function titleKey(m) {
79
110
  if (m.views?.title)
80
111
  return m.views.title;
81
- const fm = fieldMap(m.fields);
82
- const inlineNonImage = m.views?.inline?.find((k) => fm[k] && !isImageKind(fm[k].kind));
83
- if (inlineNonImage)
84
- return inlineNonImage;
85
- if (fm['name'])
86
- return 'name';
87
- const firstText = fieldEntries(m.fields).find(([, f]) => !f.virtual && isTextPrim(f.prim));
88
- if (firstText)
89
- return firstText[0];
90
- return 'id';
112
+ const declared = ownFieldEntries(m.fields).find(([, f]) => f.kind === 'title');
113
+ return declared ? declared[0] : 'id';
91
114
  }
92
115
  export function recordTitle(m, record) {
93
116
  return String(record[titleKey(m)] ?? record['id'] ?? '');
@@ -128,13 +151,11 @@ export function inlineText(m, row) {
128
151
  }
129
152
  export function viewKeys(m) {
130
153
  const tk = titleKey(m);
131
- const rest = m.views?.list?.fields?.length
132
- ? realKeys(m, m.views.list.fields.filter((k) => k !== tk))
133
- : [];
154
+ const rest = m.views?.list?.length ? realKeys(m, m.views.list.filter((k) => k !== tk)) : [];
134
155
  return [tk, ...rest];
135
156
  }
136
157
  export function listKind(m) {
137
- return m.views?.list?.kind ?? 'table';
158
+ return m.views?.listKind ?? 'table';
138
159
  }
139
160
  const GROUPABLE_PRIMS = new Set(['select', 'checkbox', 'relation']);
140
161
  export function groupableFields(m) {
@@ -198,6 +219,10 @@ export function buildShape(fields, partial) {
198
219
  if (isField(it)) {
199
220
  if (it.type.virtual)
200
221
  continue;
222
+ if (it.type.derive) {
223
+ shape[it.key] = z.never({ error: () => vmsg('derived') }).optional();
224
+ continue;
225
+ }
201
226
  shape[it.key] = partial ? it.type.zod.optional() : it.type.zod;
202
227
  }
203
228
  else if (isGroup(it)) {
@@ -0,0 +1,15 @@
1
+ import type { Condition } from './condition.ts';
2
+ export interface ShowcaseDef {
3
+ id: string;
4
+ library: string;
5
+ label: string;
6
+ icon: string;
7
+ source: {
8
+ library: string;
9
+ shelf: string;
10
+ };
11
+ filter: Condition;
12
+ columns: string[];
13
+ createDefaults?: Record<string, unknown>;
14
+ }
15
+ export declare function defineShowcase(s: ShowcaseDef): ShowcaseDef;
@@ -0,0 +1,35 @@
1
+ import { COMPILABLE_SCALAR_OPS, COMPILABLE_ARRAY_OPS } from "./condition.js";
2
+ const COMPILABLE_OPS = new Set([...COMPILABLE_SCALAR_OPS, ...COMPILABLE_ARRAY_OPS]);
3
+ function assertCompilableOps(cond, id) {
4
+ for (const [key, spec] of Object.entries(cond)) {
5
+ if (spec === undefined)
6
+ continue;
7
+ if (key === '$and' || key === '$or') {
8
+ for (const c of spec)
9
+ assertCompilableOps(c, id);
10
+ continue;
11
+ }
12
+ if (typeof spec === 'object' && spec !== null) {
13
+ for (const op of Object.keys(spec)) {
14
+ if (!COMPILABLE_OPS.has(op)) {
15
+ throw new Error(`[showcase] ${id}: operator '${op}' on '${key}' does not compile to SQL`);
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ export function defineShowcase(s) {
22
+ if (!s.id)
23
+ throw new Error('[showcase] missing id');
24
+ if (!s.library)
25
+ throw new Error(`[showcase] ${s.id}: missing library`);
26
+ if (!s.source?.library || !s.source?.shelf)
27
+ throw new Error(`[showcase] ${s.id}: missing source library/shelf`);
28
+ if (!s.columns?.length)
29
+ throw new Error(`[showcase] ${s.id}: columns must not be empty`);
30
+ if (!s.filter || Object.keys(s.filter).length === 0) {
31
+ throw new Error(`[showcase] ${s.id}: filter must not be empty — an unfiltered showcase is the shelf itself`);
32
+ }
33
+ assertCompilableOps(s.filter, s.id);
34
+ return s;
35
+ }
@@ -5,7 +5,7 @@ export const USERS_SHELF = defineShelf({
5
5
  library: '',
6
6
  label: 'auth.usersTitle',
7
7
  icon: 'lucide:users',
8
- views: { list: { fields: ['login', 'displayName', 'role', 'disabled'] } },
8
+ views: { title: 'login', list: ['displayName', 'role', 'disabled'] },
9
9
  fields: [
10
10
  field.string({ key: 'login', label: 'auth.fieldLogin' }),
11
11
  field.string({ key: 'displayName', label: 'auth.fieldDisplayName' }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffer-org/sdk",
3
- "version": "2.2.1",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=24"
@@ -13,6 +13,14 @@
13
13
  "types": "./dist/index.d.ts",
14
14
  "default": "./dist/index.js"
15
15
  },
16
+ "./derive": {
17
+ "types": "./dist/derive.d.ts",
18
+ "default": "./dist/derive.js"
19
+ },
20
+ "./showcase": {
21
+ "types": "./dist/showcase.d.ts",
22
+ "default": "./dist/showcase.js"
23
+ },
16
24
  "./*": {
17
25
  "types": "./dist/*.d.ts",
18
26
  "default": "./dist/*.js"