@mulmoclaude/core 0.8.1 → 0.8.2
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/collection/core/dynamicIcon.d.ts +24 -0
- package/dist/collection/core/schema.d.ts +55 -0
- package/dist/collection/core/where.d.ts +32 -0
- package/dist/collection/index.cjs +5 -1
- package/dist/collection/index.d.ts +2 -0
- package/dist/collection/index.js +2 -2
- package/dist/collection/registry/server/index.cjs +1 -1
- package/dist/collection/registry/server/index.js +1 -1
- package/dist/collection/server/discovery.d.ts +51 -0
- package/dist/collection/server/dynamicIcon.d.ts +10 -0
- package/dist/collection/server/index.cjs +2 -1
- package/dist/collection/server/index.d.ts +1 -0
- package/dist/collection/server/index.js +2 -2
- package/dist/collection-watchers/index.cjs +1 -1
- package/dist/collection-watchers/index.js +1 -1
- package/dist/{deriveAll-Cb9rWjan.cjs → deriveAll-BQ_p5HSB.cjs} +149 -1
- package/dist/deriveAll-BQ_p5HSB.cjs.map +1 -0
- package/dist/{deriveAll-D3wFH4Tw.js → deriveAll-CMFXDQ_G.js} +126 -2
- package/dist/deriveAll-CMFXDQ_G.js.map +1 -0
- package/dist/feeds/index.cjs +2 -2
- package/dist/feeds/index.js +2 -2
- package/dist/feeds/server/index.cjs +3 -3
- package/dist/feeds/server/index.js +3 -3
- package/dist/{ingestTypes-DhJ63Ogd.cjs → ingestTypes-C7EheYZX.cjs} +2 -2
- package/dist/{ingestTypes-DhJ63Ogd.cjs.map → ingestTypes-C7EheYZX.cjs.map} +1 -1
- package/dist/{ingestTypes-BtMZogMX.js → ingestTypes-CmJeOUJc.js} +2 -2
- package/dist/{ingestTypes-BtMZogMX.js.map → ingestTypes-CmJeOUJc.js.map} +1 -1
- package/dist/{server-BDxrLT41.js → server-DKXXFTbw.js} +96 -4
- package/dist/server-DKXXFTbw.js.map +1 -0
- package/dist/{server-U2d7Fb1h.cjs → server-G6GtOdaW.cjs} +101 -3
- package/dist/server-G6GtOdaW.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/deriveAll-Cb9rWjan.cjs.map +0 -1
- package/dist/deriveAll-D3wFH4Tw.js.map +0 -1
- package/dist/server-BDxrLT41.js.map +0 -1
- package/dist/server-U2d7Fb1h.cjs.map +0 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CollectionItem, CollectionSchema, DynamicIconSource, DynamicIconSpec } from './schema';
|
|
2
|
+
/** Reduce `records` to the one record that decides the effective icon, per
|
|
3
|
+
* `source`'s `where` filter + `from` strategy:
|
|
4
|
+
* - pool = `source.where`-filtered records, or every record when unset;
|
|
5
|
+
* - an empty pool resolves to `null` (no source record → fallback);
|
|
6
|
+
* - `from: "first"` / `"when"` → the first pool record (storage order);
|
|
7
|
+
* - `from: "latest"` (default), with `orderBy` given → the pool record
|
|
8
|
+
* whose `String(record[orderBy])` sorts highest;
|
|
9
|
+
* - `from: "latest"`, with no `orderBy` → the last pool record.
|
|
10
|
+
* `recordsById` (the source collection's records keyed by primaryKey)
|
|
11
|
+
* resolves any `valueFrom` reference inside `source.where`; omitted for
|
|
12
|
+
* callers with no cross-record lookups. */
|
|
13
|
+
export declare function selectDynamicRecord(records: CollectionItem[], source: DynamicIconSource, orderBy: string | undefined, recordsById?: Record<string, CollectionItem>): CollectionItem | null;
|
|
14
|
+
/** Map a resolved source record to the effective icon: `spec.fallback`
|
|
15
|
+
* (or the collection's own static `icon`) when there's no record or no
|
|
16
|
+
* rule matches; otherwise the `icon` of the first rule whose `where`
|
|
17
|
+
* matches the record. `recordsById` resolves any `valueFrom` reference
|
|
18
|
+
* inside a rule's `where`, same as `selectDynamicRecord`. */
|
|
19
|
+
export declare function resolveIcon(record: CollectionItem | null, spec: DynamicIconSpec, staticIcon: string, recordsById?: Record<string, CollectionItem>): string;
|
|
20
|
+
/** The first field key (declaration order) whose type is `date` or
|
|
21
|
+
* `datetime` — the default `orderBy` for `from: "latest"` when a
|
|
22
|
+
* `DynamicIconSource` doesn't name one. `undefined` when the schema has
|
|
23
|
+
* no date-like field. */
|
|
24
|
+
export declare function firstDateField(schema: CollectionSchema): string | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Where } from './where';
|
|
1
2
|
/** Minimal "this collection is a feed" descriptor carried on the schema.
|
|
2
3
|
* Deliberately narrow — the canonical collection contract stays
|
|
3
4
|
* independent of the host's feeds subsystem. The host's richer retrieval
|
|
@@ -226,6 +227,48 @@ export interface CollectionAction {
|
|
|
226
227
|
* shown. */
|
|
227
228
|
when?: CollectionWhen;
|
|
228
229
|
}
|
|
230
|
+
/** One rule in a `dynamicIcon.rules` list: when the resolved source
|
|
231
|
+
* record matches `where` (an AND of typed conditions, see {@link Where}),
|
|
232
|
+
* the collection's effective launcher icon becomes `icon`. Evaluated top
|
|
233
|
+
* to bottom — the first match wins. */
|
|
234
|
+
export interface DynamicIconRule {
|
|
235
|
+
where: Where;
|
|
236
|
+
icon: string;
|
|
237
|
+
}
|
|
238
|
+
/** Where a {@link DynamicIconSpec}'s source record comes from: a (possibly
|
|
239
|
+
* cross-collection) pool of records, optionally narrowed by `where` and
|
|
240
|
+
* reduced to a single record by `from`. */
|
|
241
|
+
export interface DynamicIconSource {
|
|
242
|
+
/** Slug of the collection to read records from — the collection itself
|
|
243
|
+
* (self-reference) or another one (cross-collection). Required. */
|
|
244
|
+
collection: string;
|
|
245
|
+
/** How to reduce the (optionally `where`-filtered) pool to one record.
|
|
246
|
+
* `"latest"` (default): the record with the greatest `orderBy` value.
|
|
247
|
+
* `"first"` / `"when"`: the first record in the pool (storage order). */
|
|
248
|
+
from?: "latest" | "first" | "when";
|
|
249
|
+
/** Field compared for `from: "latest"`. Defaults to the source schema's
|
|
250
|
+
* first `date`/`datetime` field (declaration order); when the source
|
|
251
|
+
* has none, `"latest"` falls back to the last pool record. */
|
|
252
|
+
orderBy?: string;
|
|
253
|
+
/** Optional predicate (AND of typed conditions) narrowing the pool
|
|
254
|
+
* before `from` reduces it to one record (e.g. restrict a shared
|
|
255
|
+
* weather collection to one region). */
|
|
256
|
+
where?: Where;
|
|
257
|
+
}
|
|
258
|
+
/** Declarative "data state → icon" mapping for a collection's launcher
|
|
259
|
+
* shortcut icon (see `CollectionSchema.dynamicIcon`). When absent, the
|
|
260
|
+
* launcher icon is the static `schema.icon`, unchanged from before this
|
|
261
|
+
* field existed. */
|
|
262
|
+
export interface DynamicIconSpec {
|
|
263
|
+
/** The record the `rules` are evaluated against. Required. */
|
|
264
|
+
source: DynamicIconSource;
|
|
265
|
+
/** First-match-wins list of "resolved record matches `where` → `icon`"
|
|
266
|
+
* rules. */
|
|
267
|
+
rules: DynamicIconRule[];
|
|
268
|
+
/** Icon used when no source record resolves or no rule matches.
|
|
269
|
+
* Defaults to the collection's own static `schema.icon`. */
|
|
270
|
+
fallback?: string;
|
|
271
|
+
}
|
|
229
272
|
export interface CollectionFieldSpec {
|
|
230
273
|
type: CollectionFieldType;
|
|
231
274
|
label: string;
|
|
@@ -426,12 +469,24 @@ export interface CollectionSchema {
|
|
|
426
469
|
* `ingest.template`, and the worker edits the records itself. The host's
|
|
427
470
|
* feeds subsystem narrows this to its richer `IngestSpec`. */
|
|
428
471
|
ingest?: CollectionIngest;
|
|
472
|
+
/** Optional data-driven override for the launcher shortcut icon: when
|
|
473
|
+
* set, the host resolves a record from `dynamicIcon.source` and maps
|
|
474
|
+
* it through `dynamicIcon.rules` to compute `CollectionSummary.icon`
|
|
475
|
+
* instead of using this static `icon`. Absent ⇒ unchanged static-icon
|
|
476
|
+
* behaviour. See `computeCollectionIcon` (server) and
|
|
477
|
+
* `selectDynamicRecord`/`resolveIcon` (pure resolver). */
|
|
478
|
+
dynamicIcon?: DynamicIconSpec;
|
|
429
479
|
}
|
|
430
480
|
export interface CollectionSummary {
|
|
431
481
|
slug: string;
|
|
432
482
|
title: string;
|
|
433
483
|
icon: string;
|
|
434
484
|
source: CollectionSource;
|
|
485
|
+
/** Slugs of the source collection(s) a `dynamicIcon` icon was computed
|
|
486
|
+
* from — present only when `schema.dynamicIcon` is set. Lets a client
|
|
487
|
+
* know which collection change-channel(s) to watch for a live icon
|
|
488
|
+
* update (see `useDynamicShortcutIcons`). */
|
|
489
|
+
iconSources?: string[];
|
|
435
490
|
}
|
|
436
491
|
export interface CollectionDetail extends CollectionSummary {
|
|
437
492
|
schema: CollectionSchema;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Comparison operators one `WhereCond` may apply to `record[field]`. */
|
|
2
|
+
export type WhereOp = "eq" | "ne" | "in" | "gt" | "gte" | "lt" | "lte" | "contains";
|
|
3
|
+
/** Reads the comparison value from a field instead of a schema literal:
|
|
4
|
+
* - `record` set → another record: `recordsById[record][field]` (e.g. a
|
|
5
|
+
* `_config` singleton's `defaultCity`, following a per-user setting);
|
|
6
|
+
* - `record` omitted → the SAME record being matched (field-to-field, e.g.
|
|
7
|
+
* `spent > budget`). */
|
|
8
|
+
export interface ValueRef {
|
|
9
|
+
record?: string;
|
|
10
|
+
field: string;
|
|
11
|
+
}
|
|
12
|
+
/** One typed condition: `record[field] <op> value`. The comparison value is
|
|
13
|
+
* either a literal `value` (a plain string for every op except `in`, which
|
|
14
|
+
* takes the allowed set) or a `valueFrom` reference resolved against the
|
|
15
|
+
* `recordsById` map passed to `matchesWhere`. Exactly one of the two is
|
|
16
|
+
* expected — enforced by zod at the schema boundary (`server/discovery.ts`),
|
|
17
|
+
* not here. */
|
|
18
|
+
export interface WhereCond {
|
|
19
|
+
field: string;
|
|
20
|
+
op: WhereOp;
|
|
21
|
+
value?: string | string[];
|
|
22
|
+
valueFrom?: ValueRef;
|
|
23
|
+
}
|
|
24
|
+
/** A `where` clause is the AND of its conditions — every one must match. */
|
|
25
|
+
export type Where = WhereCond[];
|
|
26
|
+
/** True when `record` satisfies every condition in `where` (AND). An empty
|
|
27
|
+
* `where` matches everything. `recordsById` — the source collection's
|
|
28
|
+
* records keyed by primaryKey — resolves any `valueFrom` reference;
|
|
29
|
+
* omitted (default `{}`) for callers with no cross-record lookups, in
|
|
30
|
+
* which case every `valueFrom` condition is UNRESOLVED and so never
|
|
31
|
+
* matches. */
|
|
32
|
+
export declare function matchesWhere(where: Where, record: Record<string, unknown>, recordsById?: Record<string, Record<string, unknown>>): boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_deriveAll = require("../deriveAll-
|
|
2
|
+
const require_deriveAll = require("../deriveAll-BQ_p5HSB.cjs");
|
|
3
3
|
//#region src/collection/core/presentCollection.ts
|
|
4
4
|
var TOOL_NAME = "presentCollection";
|
|
5
5
|
var TOOL_DEFINITION = {
|
|
@@ -769,12 +769,14 @@ exports.errorMessage = errorMessage;
|
|
|
769
769
|
exports.evaluateDerived = require_deriveAll.evaluateDerived;
|
|
770
770
|
exports.executePresentCollection = executePresentCollection;
|
|
771
771
|
exports.fieldVisible = fieldVisible;
|
|
772
|
+
exports.firstDateField = require_deriveAll.firstDateField;
|
|
772
773
|
exports.firstMissingRequiredField = firstMissingRequiredField;
|
|
773
774
|
exports.isFieldDrivenEvery = require_deriveAll.isFieldDrivenEvery;
|
|
774
775
|
exports.isSortableField = isSortableField;
|
|
775
776
|
exports.itemIdOf = itemIdOf;
|
|
776
777
|
exports.itemLabelOf = itemLabelOf;
|
|
777
778
|
exports.labelFieldFor = labelFieldFor;
|
|
779
|
+
exports.matchesWhere = require_deriveAll.matchesWhere;
|
|
778
780
|
exports.monthAnchorDate = monthAnchorDate;
|
|
779
781
|
exports.nextSortDirection = nextSortDirection;
|
|
780
782
|
exports.numericSortValue = numericSortValue;
|
|
@@ -783,8 +785,10 @@ exports.parseIsoDateTime = parseIsoDateTime;
|
|
|
783
785
|
exports.parseTimeRange = parseTimeRange;
|
|
784
786
|
exports.recordSpan = recordSpan;
|
|
785
787
|
exports.resolveEnumColor = resolveEnumColor;
|
|
788
|
+
exports.resolveIcon = require_deriveAll.resolveIcon;
|
|
786
789
|
exports.resolveRowRefs = require_deriveAll.resolveRowRefs;
|
|
787
790
|
exports.rowFromItem = rowFromItem;
|
|
791
|
+
exports.selectDynamicRecord = require_deriveAll.selectDynamicRecord;
|
|
788
792
|
exports.shortHexId = shortHexId;
|
|
789
793
|
exports.sortItems = sortItems;
|
|
790
794
|
exports.spanCoversDay = spanCoversDay;
|
|
@@ -4,6 +4,8 @@ export * from './core/presentCollection';
|
|
|
4
4
|
export * from './core/enumColors';
|
|
5
5
|
export * from './core/draft';
|
|
6
6
|
export * from './core/actionVisible';
|
|
7
|
+
export * from './core/where';
|
|
8
|
+
export * from './core/dynamicIcon';
|
|
7
9
|
export * from './core/derivedFormula';
|
|
8
10
|
export * from './core/deriveAll';
|
|
9
11
|
export * from './core/sortItems';
|
package/dist/collection/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as resolveIcon, c as AGENT_INGEST_KIND, d as embedTargetId, f as isFieldDrivenEvery, i as firstDateField, l as FEED_SCHEDULES, n as resolveRowRefs, o as selectDynamicRecord, r as evaluateDerived, s as matchesWhere, t as deriveAll, u as INGEST_KINDS } from "../deriveAll-CMFXDQ_G.js";
|
|
2
2
|
//#region src/collection/core/presentCollection.ts
|
|
3
3
|
var TOOL_NAME = "presentCollection";
|
|
4
4
|
var TOOL_DEFINITION = {
|
|
@@ -735,6 +735,6 @@ function defangForPrompt(value) {
|
|
|
735
735
|
return value.replace(/[<>]/g, "").replace(/`/g, "'").replace(/\$\{/g, "$ {").replace(/\s+/g, " ").slice(0, DEFANG_MAX_LEN);
|
|
736
736
|
}
|
|
737
737
|
//#endregion
|
|
738
|
-
export { AGENT_INGEST_KIND, ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, TOOL_DEFINITION, TOOL_NAME, actionVisible, assignLanes, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, compareSortValues, compareYmd, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, embedTargetId, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldVisible, firstMissingRequiredField, isFieldDrivenEvery, isSortableField, itemIdOf, itemLabelOf, labelFieldFor, monthAnchorDate, nextSortDirection, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, recordSpan, resolveEnumColor, resolveRowRefs, rowFromItem, shortHexId, sortItems, spanCoversDay, stringSortValue, whenMatches, ymdKey };
|
|
738
|
+
export { AGENT_INGEST_KIND, ENUM_ALERT, ENUM_NEUTRAL, ENUM_NUDGE, FEED_SCHEDULES, INGEST_KINDS, MINUTES_PER_DAY, TOOL_DEFINITION, TOOL_NAME, actionVisible, assignLanes, boolSortValue, bucketRecords, buildMonthGrid, buildUpdatedRecord, coerceInlineValue, compareSortValues, compareYmd, dateOf, dateSortValue, daySlice, defangForPrompt, deriveAll, draftToRecord, embedTargetId, emptyRow, enumColorClasses, enumSortValue, enumValueIndex, errorMessage, evaluateDerived, executePresentCollection, fieldVisible, firstDateField, firstMissingRequiredField, isFieldDrivenEvery, isSortableField, itemIdOf, itemLabelOf, labelFieldFor, matchesWhere, monthAnchorDate, nextSortDirection, numericSortValue, parseIsoDate, parseIsoDateTime, parseTimeRange, recordSpan, resolveEnumColor, resolveIcon, resolveRowRefs, rowFromItem, selectDynamicRecord, shortHexId, sortItems, spanCoversDay, stringSortValue, whenMatches, ymdKey };
|
|
739
739
|
|
|
740
740
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("../../../rolldown-runtime-D6vf50IK.cjs");
|
|
3
|
-
const require_server = require("../../../server-
|
|
3
|
+
const require_server = require("../../../server-G6GtOdaW.cjs");
|
|
4
4
|
const require_collection_paths = require("../../paths.cjs");
|
|
5
5
|
const require_types = require("../../../types-CNqkLT4M.cjs");
|
|
6
6
|
const require_skill_bridge_index = require("../../../skill-bridge/index.cjs");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as safeRecordId, R as writeFileAtomic, X as log, _ as CollectionSchemaZ, b as loadCollection, m as errorMessage, p as ONE_SECOND_MS, q as collectionsRegistriesConfigPath, v as acceptParsedSchema } from "../../../server-DKXXFTbw.js";
|
|
2
2
|
import { isSafeActionTemplatePath } from "../../paths.js";
|
|
3
3
|
import { n as parseRegistryIndex, r as isRecord, t as OFFICIAL_REGISTRY_NAME } from "../../../types-BKVZrtyc.js";
|
|
4
4
|
import { claudeSkillDir, dataSkillDir, mirrorSkillWrite } from "../../../skill-bridge/index.js";
|
|
@@ -192,6 +192,57 @@ export declare const CollectionSchemaZ: z.ZodObject<{
|
|
|
192
192
|
role: z.ZodString;
|
|
193
193
|
template: z.ZodString;
|
|
194
194
|
}, z.core.$strip>], "kind">>;
|
|
195
|
+
dynamicIcon: z.ZodOptional<z.ZodObject<{
|
|
196
|
+
source: z.ZodObject<{
|
|
197
|
+
collection: z.ZodString;
|
|
198
|
+
from: z.ZodOptional<z.ZodEnum<{
|
|
199
|
+
latest: "latest";
|
|
200
|
+
first: "first";
|
|
201
|
+
when: "when";
|
|
202
|
+
}>>;
|
|
203
|
+
orderBy: z.ZodOptional<z.ZodString>;
|
|
204
|
+
where: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
205
|
+
field: z.ZodString;
|
|
206
|
+
op: z.ZodEnum<{
|
|
207
|
+
eq: "eq";
|
|
208
|
+
ne: "ne";
|
|
209
|
+
in: "in";
|
|
210
|
+
gt: "gt";
|
|
211
|
+
gte: "gte";
|
|
212
|
+
lt: "lt";
|
|
213
|
+
lte: "lte";
|
|
214
|
+
contains: "contains";
|
|
215
|
+
}>;
|
|
216
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
217
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
218
|
+
record: z.ZodOptional<z.ZodString>;
|
|
219
|
+
field: z.ZodString;
|
|
220
|
+
}, z.core.$strip>>;
|
|
221
|
+
}, z.core.$strip>>>;
|
|
222
|
+
}, z.core.$strip>;
|
|
223
|
+
rules: z.ZodArray<z.ZodObject<{
|
|
224
|
+
where: z.ZodArray<z.ZodObject<{
|
|
225
|
+
field: z.ZodString;
|
|
226
|
+
op: z.ZodEnum<{
|
|
227
|
+
eq: "eq";
|
|
228
|
+
ne: "ne";
|
|
229
|
+
in: "in";
|
|
230
|
+
gt: "gt";
|
|
231
|
+
gte: "gte";
|
|
232
|
+
lt: "lt";
|
|
233
|
+
lte: "lte";
|
|
234
|
+
contains: "contains";
|
|
235
|
+
}>;
|
|
236
|
+
value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
237
|
+
valueFrom: z.ZodOptional<z.ZodObject<{
|
|
238
|
+
record: z.ZodOptional<z.ZodString>;
|
|
239
|
+
field: z.ZodString;
|
|
240
|
+
}, z.core.$strip>>;
|
|
241
|
+
}, z.core.$strip>>;
|
|
242
|
+
icon: z.ZodString;
|
|
243
|
+
}, z.core.$strip>>;
|
|
244
|
+
fallback: z.ZodOptional<z.ZodString>;
|
|
245
|
+
}, z.core.$strip>>;
|
|
195
246
|
}, z.core.$strip>;
|
|
196
247
|
/** Result of the post-Zod acceptance gates: the resolved record dir on
|
|
197
248
|
* success, or a one-line reason discovery would skip the schema. */
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DiscoveryOptions } from './discovery';
|
|
2
|
+
import { LoadedCollection } from './discoveredCollection';
|
|
3
|
+
/** Compute the effective launcher icon for `collection`: its static
|
|
4
|
+
* `schema.icon` when it declares no `dynamicIcon`, else the icon
|
|
5
|
+
* resolved from `dynamicIcon.source`'s RAW stored records (no
|
|
6
|
+
* derive/enrich — the icon rules match against stored values) via the
|
|
7
|
+
* pure resolver. Fails soft on any read/discovery error (missing source
|
|
8
|
+
* collection, filesystem error): falls back to `dynamicIcon.fallback ??
|
|
9
|
+
* schema.icon` rather than surfacing to the collections list. */
|
|
10
|
+
export declare function computeCollectionIcon(collection: LoadedCollection, opts?: DiscoveryOptions): Promise<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_server = require("../../server-
|
|
2
|
+
const require_server = require("../../server-G6GtOdaW.cjs");
|
|
3
3
|
const require_collection_paths = require("../paths.cjs");
|
|
4
4
|
exports.COMPUTED_TYPES = require_server.COMPUTED_TYPES;
|
|
5
5
|
exports.CollectionSchemaZ = require_server.CollectionSchemaZ;
|
|
@@ -8,6 +8,7 @@ exports.acceptParsedSchema = require_server.acceptParsedSchema;
|
|
|
8
8
|
exports.advanceTriggerDate = require_server.advanceTriggerDate;
|
|
9
9
|
exports.buildActionSeedPrompt = require_server.buildActionSeedPrompt;
|
|
10
10
|
exports.buildCollectionActionSeedPrompt = require_server.buildCollectionActionSeedPrompt;
|
|
11
|
+
exports.computeCollectionIcon = require_server.computeCollectionIcon;
|
|
11
12
|
exports.computeSuccessor = require_server.computeSuccessor;
|
|
12
13
|
exports.configureCollectionHost = require_server.configureCollectionHost;
|
|
13
14
|
exports.daysInMonth = require_server.daysInMonth;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as listItems, B as isContainedInRoot, C as COMPUTED_TYPES, D as buildCollectionActionSeedPrompt, E as buildActionSeedPrompt, F as readSkillTemplate, G as safeRecordId, H as itemFilePath, I as resolveCreateItemId, J as configureCollectionHost, K as safeSlugName, L as writeItem, M as readCustomViewHtml, N as readCustomViewI18n, O as deleteItem, P as readItem, Q as setCollectionChangePublisher, S as toSummary, T as validateRecordObject, U as resolveDataDir, V as isContainedInWorkspace, W as resolveTemplatePath, X as log, Y as getWorkspaceRoot, Z as publishCollectionChange, _ as CollectionSchemaZ, a as computeSuccessor, b as loadCollection, c as isTriggerDue, d as resolveEvery, f as successorId, g as enrichItems, h as computeCollectionIcon, i as advanceTriggerDate, j as promptPathsFor, k as generateItemId, l as maybeSpawnSuccessor, n as deleteCollection, o as daysInMonth, r as deleteCollectionRefusalMessage, s as formatCivil, t as deleteCustomView, u as parseCivil, v as acceptParsedSchema, w as validateCollectionRecords, x as toDetail, y as discoverCollections, z as SCHEMA_FILE } from "../../server-DKXXFTbw.js";
|
|
2
2
|
import { isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath, isSafeTemplatePath } from "../paths.js";
|
|
3
|
-
export { COMPUTED_TYPES, CollectionSchemaZ, SCHEMA_FILE, acceptParsedSchema, advanceTriggerDate, buildActionSeedPrompt, buildCollectionActionSeedPrompt, computeSuccessor, configureCollectionHost, daysInMonth, deleteCollection, deleteCollectionRefusalMessage, deleteCustomView, deleteItem, discoverCollections, enrichItems, formatCivil, generateItemId, getWorkspaceRoot, isContainedInRoot, isContainedInWorkspace, isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath, isSafeTemplatePath, isTriggerDue, itemFilePath, listItems, loadCollection, log, maybeSpawnSuccessor, parseCivil, promptPathsFor, publishCollectionChange, readCustomViewHtml, readCustomViewI18n, readItem, readSkillTemplate, resolveCreateItemId, resolveDataDir, resolveEvery, resolveTemplatePath, safeRecordId, safeSlugName, setCollectionChangePublisher, successorId, toDetail, toSummary, validateCollectionRecords, validateRecordObject, writeItem };
|
|
3
|
+
export { COMPUTED_TYPES, CollectionSchemaZ, SCHEMA_FILE, acceptParsedSchema, advanceTriggerDate, buildActionSeedPrompt, buildCollectionActionSeedPrompt, computeCollectionIcon, computeSuccessor, configureCollectionHost, daysInMonth, deleteCollection, deleteCollectionRefusalMessage, deleteCustomView, deleteItem, discoverCollections, enrichItems, formatCivil, generateItemId, getWorkspaceRoot, isContainedInRoot, isContainedInWorkspace, isSafeActionTemplatePath, isSafeCustomViewI18nPath, isSafeCustomViewPath, isSafeTemplatePath, isTriggerDue, itemFilePath, listItems, loadCollection, log, maybeSpawnSuccessor, parseCivil, promptPathsFor, publishCollectionChange, readCustomViewHtml, readCustomViewI18n, readItem, readSkillTemplate, resolveCreateItemId, resolveDataDir, resolveEvery, resolveTemplatePath, safeRecordId, safeSlugName, setCollectionChangePublisher, successorId, toDetail, toSummary, validateCollectionRecords, validateRecordObject, writeItem };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_collection_index = require("../collection/index.cjs");
|
|
3
|
-
const require_server = require("../server-
|
|
3
|
+
const require_server = require("../server-G6GtOdaW.cjs");
|
|
4
4
|
const require_notifier = require("../notifier-bS8IEeLA.cjs");
|
|
5
5
|
let node_fs = require("node:fs");
|
|
6
6
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { whenMatches } from "../collection/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as listItems, P as readItem, b as loadCollection, c as isTriggerDue, l as maybeSpawnSuccessor, y as discoverCollections } from "../server-DKXXFTbw.js";
|
|
3
3
|
import { d as publish, m as updateForPlugin, n as clear, s as listAll } from "../notifier-ChpY0XrY.js";
|
|
4
4
|
import { watch } from "node:fs";
|
|
5
5
|
import { mkdir } from "node:fs/promises";
|
|
@@ -38,6 +38,130 @@ function embedTargetId(field, record) {
|
|
|
38
38
|
return "";
|
|
39
39
|
}
|
|
40
40
|
//#endregion
|
|
41
|
+
//#region src/collection/core/where.ts
|
|
42
|
+
/** True when `record[field]` is absent (`undefined`/`null`) — the only case
|
|
43
|
+
* where `ne` and every other op disagree on the result. */
|
|
44
|
+
function isMissing(raw) {
|
|
45
|
+
return raw === void 0 || raw === null;
|
|
46
|
+
}
|
|
47
|
+
/** The effective comparison value for `cond`: its literal `value`, or — for
|
|
48
|
+
* a `valueFrom` reference — the target field read out of `recordsById`.
|
|
49
|
+
* `undefined` means UNRESOLVED (no such record, or the field on it is
|
|
50
|
+
* missing); the caller must treat that as "never matches", not as a
|
|
51
|
+
* literal `undefined` value to compare against. */
|
|
52
|
+
function resolveValue(cond, record, recordsById) {
|
|
53
|
+
if (!cond.valueFrom) return cond.value;
|
|
54
|
+
const { record: refRecord, field } = cond.valueFrom;
|
|
55
|
+
const raw = (refRecord === void 0 ? record : recordsById[refRecord])?.[field];
|
|
56
|
+
return isMissing(raw) ? void 0 : String(raw);
|
|
57
|
+
}
|
|
58
|
+
function matchesNumericOp(operator, left, right) {
|
|
59
|
+
if (operator === "gt") return left > right;
|
|
60
|
+
if (operator === "gte") return left >= right;
|
|
61
|
+
if (operator === "lt") return left < right;
|
|
62
|
+
return left <= right;
|
|
63
|
+
}
|
|
64
|
+
/** `Number("")` / `Number(" ")` are `0`, not `NaN`, so treat a blank string
|
|
65
|
+
* as non-numeric explicitly — an empty field must fail a numeric compare,
|
|
66
|
+
* not read as zero. */
|
|
67
|
+
function toNumber(raw) {
|
|
68
|
+
return raw.trim() === "" ? NaN : Number(raw);
|
|
69
|
+
}
|
|
70
|
+
function matchesNumeric(operator, raw, value) {
|
|
71
|
+
if (Array.isArray(value)) return false;
|
|
72
|
+
const left = toNumber(raw);
|
|
73
|
+
const right = toNumber(value);
|
|
74
|
+
if (Number.isNaN(left) || Number.isNaN(right)) return false;
|
|
75
|
+
return matchesNumericOp(operator, left, right);
|
|
76
|
+
}
|
|
77
|
+
/** True when the present string `raw` satisfies `operator` against the
|
|
78
|
+
* resolved `value` (field known to exist — MISSING is handled by the
|
|
79
|
+
* caller before this runs, and an UNRESOLVED `valueFrom` never reaches
|
|
80
|
+
* here either). */
|
|
81
|
+
function matchesPresent(operator, raw, value) {
|
|
82
|
+
switch (operator) {
|
|
83
|
+
case "eq": return raw === String(value);
|
|
84
|
+
case "ne": return raw !== String(value);
|
|
85
|
+
case "in": return Array.isArray(value) && value.includes(raw);
|
|
86
|
+
case "contains": return raw.includes(String(value));
|
|
87
|
+
case "gt":
|
|
88
|
+
case "gte":
|
|
89
|
+
case "lt":
|
|
90
|
+
case "lte": return matchesNumeric(operator, raw, value);
|
|
91
|
+
default: return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** True when `record` satisfies one condition, given `recordsById` to
|
|
95
|
+
* resolve a `valueFrom` reference. Two independent MISSING cases, checked
|
|
96
|
+
* in order:
|
|
97
|
+
* - `record[cond.field]` absent (`undefined`/`null`) → matches only `ne`
|
|
98
|
+
* (vacuously true — "not equal to X" holds when there's no value at
|
|
99
|
+
* all); every other op is false. Unchanged from the literal-`value`
|
|
100
|
+
* behaviour, regardless of whether `valueFrom` would also resolve.
|
|
101
|
+
* - the resolved comparison value is UNRESOLVED (a `valueFrom` whose
|
|
102
|
+
* target record/field doesn't exist) → false for EVERY op, including
|
|
103
|
+
* `ne` — a broken reference must never spuriously match. */
|
|
104
|
+
function matchesCond(cond, record, recordsById) {
|
|
105
|
+
const raw = record[cond.field];
|
|
106
|
+
if (isMissing(raw)) return cond.op === "ne";
|
|
107
|
+
const value = resolveValue(cond, record, recordsById);
|
|
108
|
+
if (value === void 0) return false;
|
|
109
|
+
return matchesPresent(cond.op, String(raw), value);
|
|
110
|
+
}
|
|
111
|
+
/** True when `record` satisfies every condition in `where` (AND). An empty
|
|
112
|
+
* `where` matches everything. `recordsById` — the source collection's
|
|
113
|
+
* records keyed by primaryKey — resolves any `valueFrom` reference;
|
|
114
|
+
* omitted (default `{}`) for callers with no cross-record lookups, in
|
|
115
|
+
* which case every `valueFrom` condition is UNRESOLVED and so never
|
|
116
|
+
* matches. */
|
|
117
|
+
function matchesWhere(where, record, recordsById = {}) {
|
|
118
|
+
return where.every((cond) => matchesCond(cond, record, recordsById));
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/collection/core/dynamicIcon.ts
|
|
122
|
+
/** The record with the greatest `String(record[field])` (localeCompare) —
|
|
123
|
+
* ties keep the first-seen record (stable left-to-right `reduce`). */
|
|
124
|
+
function latestByField(pool, field) {
|
|
125
|
+
return pool.reduce((latest, candidate) => String(candidate[field] ?? "").localeCompare(String(latest[field] ?? "")) > 0 ? candidate : latest);
|
|
126
|
+
}
|
|
127
|
+
/** Reduce `records` to the one record that decides the effective icon, per
|
|
128
|
+
* `source`'s `where` filter + `from` strategy:
|
|
129
|
+
* - pool = `source.where`-filtered records, or every record when unset;
|
|
130
|
+
* - an empty pool resolves to `null` (no source record → fallback);
|
|
131
|
+
* - `from: "first"` / `"when"` → the first pool record (storage order);
|
|
132
|
+
* - `from: "latest"` (default), with `orderBy` given → the pool record
|
|
133
|
+
* whose `String(record[orderBy])` sorts highest;
|
|
134
|
+
* - `from: "latest"`, with no `orderBy` → the last pool record.
|
|
135
|
+
* `recordsById` (the source collection's records keyed by primaryKey)
|
|
136
|
+
* resolves any `valueFrom` reference inside `source.where`; omitted for
|
|
137
|
+
* callers with no cross-record lookups. */
|
|
138
|
+
function selectDynamicRecord(records, source, orderBy, recordsById = {}) {
|
|
139
|
+
const { where } = source;
|
|
140
|
+
const pool = where ? records.filter((record) => matchesWhere(where, record, recordsById)) : records;
|
|
141
|
+
if (pool.length === 0) return null;
|
|
142
|
+
if (source.from === "first" || source.from === "when") return pool[0];
|
|
143
|
+
return orderBy ? latestByField(pool, orderBy) : pool[pool.length - 1];
|
|
144
|
+
}
|
|
145
|
+
/** Map a resolved source record to the effective icon: `spec.fallback`
|
|
146
|
+
* (or the collection's own static `icon`) when there's no record or no
|
|
147
|
+
* rule matches; otherwise the `icon` of the first rule whose `where`
|
|
148
|
+
* matches the record. `recordsById` resolves any `valueFrom` reference
|
|
149
|
+
* inside a rule's `where`, same as `selectDynamicRecord`. */
|
|
150
|
+
function resolveIcon(record, spec, staticIcon, recordsById = {}) {
|
|
151
|
+
const fallback = spec.fallback ?? staticIcon;
|
|
152
|
+
if (!record) return fallback;
|
|
153
|
+
const matched = spec.rules.find((rule) => matchesWhere(rule.where, record, recordsById));
|
|
154
|
+
return matched ? matched.icon : fallback;
|
|
155
|
+
}
|
|
156
|
+
var isDateLikeField = (field) => field.type === "date" || field.type === "datetime";
|
|
157
|
+
/** The first field key (declaration order) whose type is `date` or
|
|
158
|
+
* `datetime` — the default `orderBy` for `from: "latest"` when a
|
|
159
|
+
* `DynamicIconSource` doesn't name one. `undefined` when the schema has
|
|
160
|
+
* no date-like field. */
|
|
161
|
+
function firstDateField(schema) {
|
|
162
|
+
return Object.entries(schema.fields).find(([, field]) => isDateLikeField(field))?.[0];
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
41
165
|
//#region src/collection/core/derivedFormula.ts
|
|
42
166
|
function evaluateDerived(formula, ctx) {
|
|
43
167
|
let tokens;
|
|
@@ -413,17 +537,41 @@ Object.defineProperty(exports, "evaluateDerived", {
|
|
|
413
537
|
return evaluateDerived;
|
|
414
538
|
}
|
|
415
539
|
});
|
|
540
|
+
Object.defineProperty(exports, "firstDateField", {
|
|
541
|
+
enumerable: true,
|
|
542
|
+
get: function() {
|
|
543
|
+
return firstDateField;
|
|
544
|
+
}
|
|
545
|
+
});
|
|
416
546
|
Object.defineProperty(exports, "isFieldDrivenEvery", {
|
|
417
547
|
enumerable: true,
|
|
418
548
|
get: function() {
|
|
419
549
|
return isFieldDrivenEvery;
|
|
420
550
|
}
|
|
421
551
|
});
|
|
552
|
+
Object.defineProperty(exports, "matchesWhere", {
|
|
553
|
+
enumerable: true,
|
|
554
|
+
get: function() {
|
|
555
|
+
return matchesWhere;
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
Object.defineProperty(exports, "resolveIcon", {
|
|
559
|
+
enumerable: true,
|
|
560
|
+
get: function() {
|
|
561
|
+
return resolveIcon;
|
|
562
|
+
}
|
|
563
|
+
});
|
|
422
564
|
Object.defineProperty(exports, "resolveRowRefs", {
|
|
423
565
|
enumerable: true,
|
|
424
566
|
get: function() {
|
|
425
567
|
return resolveRowRefs;
|
|
426
568
|
}
|
|
427
569
|
});
|
|
570
|
+
Object.defineProperty(exports, "selectDynamicRecord", {
|
|
571
|
+
enumerable: true,
|
|
572
|
+
get: function() {
|
|
573
|
+
return selectDynamicRecord;
|
|
574
|
+
}
|
|
575
|
+
});
|
|
428
576
|
|
|
429
|
-
//# sourceMappingURL=deriveAll-
|
|
577
|
+
//# sourceMappingURL=deriveAll-BQ_p5HSB.cjs.map
|