@portel/photon-core 2.5.4 → 2.6.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/README.md CHANGED
@@ -510,6 +510,104 @@ See [CHANNELS.md](./CHANNELS.md) for full architecture documentation.
510
510
 
511
511
  ---
512
512
 
513
+ ### Managed Collections
514
+
515
+ Reactive collections that auto-emit events on mutations, enabling seamless real-time sync between server and client.
516
+
517
+ #### Level 1: Zero Effort (just import)
518
+
519
+ ```typescript
520
+ import { PhotonMCP } from '@portel/photon-core';
521
+
522
+ export default class TodoList extends PhotonMCP {
523
+ items: Task[] = []; // Compiler transforms to ReactiveArray
524
+
525
+ async add(text: string) {
526
+ this.items.push({ id: crypto.randomUUID(), text });
527
+ // Auto-emits 'items:added' — no manual wiring
528
+ }
529
+ }
530
+ ```
531
+
532
+ The compiler detects `extends PhotonMCP` with `= []` array initializers and transforms them to `ReactiveArray` instances. The runtime auto-wires `_propertyName` and `_emitter` after instantiation.
533
+
534
+ **Available reactive types:** `Array` (alias for `ReactiveArray`), `Map` (`ReactiveMap`), `Set` (`ReactiveSet`)
535
+
536
+ **Event naming (Firebase-style):**
537
+
538
+ | Operation | Event | Data |
539
+ |-----------|-------|------|
540
+ | `push(item)` | `{prop}:added` | The item |
541
+ | `pop()` / `splice(i, 1)` | `{prop}:removed` | The removed item |
542
+ | `set(i, val)` | `{prop}:updated` | `{ index, value, previous }` |
543
+ | `replaceAll(items)` | `{prop}:changed` | All items |
544
+
545
+ #### Level 2: Rich Collections
546
+
547
+ `Collection<T>` extends `ReactiveArray<T>` with Laravel-style query chaining and auto-UI rendering hints.
548
+
549
+ ```typescript
550
+ import { PhotonMCP, Collection } from '@portel/photon-core';
551
+
552
+ type Product = { name: string; price: number; stock: number; category: string };
553
+
554
+ export default class ProductCatalog extends PhotonMCP {
555
+ products = new Collection<Product>();
556
+
557
+ async catalog() {
558
+ return this.products.where('stock', '>', 0).sortBy('price');
559
+ }
560
+
561
+ async dashboard() {
562
+ return this.products.where('category', 'Electronics').as('cards');
563
+ }
564
+
565
+ async cheapest() {
566
+ return this.products.sortBy('price').first();
567
+ }
568
+ }
569
+ ```
570
+
571
+ **Query methods** (immutable — return new `Collection<T>`):
572
+
573
+ | Method | Example |
574
+ |--------|---------|
575
+ | `where(key, op?, val)` | `.where('price', '>', 100)` or `.where('status', 'active')` |
576
+ | `query(fn)` | `.query(p => p.stock > 0)` |
577
+ | `collect(fn)` | `.collect(p => ({ ...p, label: p.name }))` |
578
+ | `pluck(key)` | `.pluck('name')` → `Collection<string>` |
579
+ | `sortBy(key \| fn, dir?)` | `.sortBy('price', 'desc')` |
580
+ | `groupBy(key \| fn)` | `.groupBy('category')` → `Record<string, Collection<T>>` |
581
+ | `unique(key?)` | `.unique('category')` |
582
+ | `take(n)` / `skip(n)` | `.take(10)` |
583
+
584
+ **Terminal methods:**
585
+
586
+ | Method | Return |
587
+ |--------|--------|
588
+ | `first(fn?)` / `last(fn?)` | `T \| undefined` |
589
+ | `count()` / `isEmpty()` | `number` / `boolean` |
590
+ | `sum(key?)` / `avg(key?)` | `number` |
591
+ | `min(key?)` / `max(key?)` | `T \| undefined` |
592
+ | `aggregate(fn, init)` | `U` |
593
+
594
+ **Rendering hints** for auto-UI:
595
+
596
+ ```typescript
597
+ // .as() attaches a format hint — auto-UI renders accordingly
598
+ this.products.where('stock', '>', 0).as('table');
599
+ this.products.where('category', 'Electronics').as('cards');
600
+ ```
601
+
602
+ Formats: `'table'` | `'cards'` | `'list'` | `'chart'` | `'grid'` | `'chips'`
603
+
604
+ Without `.as()`, `toJSON()` returns a plain array (backward compatible). With `.as()`, it returns:
605
+ ```json
606
+ { "_photonType": "collection:cards", "items": [...], "count": 3 }
607
+ ```
608
+
609
+ ---
610
+
513
611
  ## 🏗️ Building Custom Runtimes
514
612
 
515
613
  Photon Core is designed to be the foundation for custom runtimes. Here are examples:
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Collection<T> — Rich queryable collection with Laravel-style chaining
3
+ *
4
+ * Extends ReactiveArray<T> so mutations auto-emit events. Query methods return
5
+ * new immutable Collection instances (no emitter wired) that can be further
6
+ * chained or serialized.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { PhotonMCP, Collection } from '@portel/photon-core';
11
+ *
12
+ * export default class ProductCatalog extends PhotonMCP {
13
+ * products = new Collection<Product>();
14
+ *
15
+ * async catalog() {
16
+ * return this.products.where('stock', '>', 0).sortBy('price');
17
+ * }
18
+ *
19
+ * async dashboard() {
20
+ * return this.products.where('category', 'Electronics').as('cards');
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ import { ReactiveArray, type Emitter } from './ReactiveArray.js';
26
+ /** Comparison operators for where() clauses */
27
+ export type CompareOp = '=' | '!=' | '>' | '<' | '>=' | '<=' | '===';
28
+ /** Rendering format hints for auto-UI */
29
+ export type RenderFormat = 'table' | 'cards' | 'list' | 'chart' | 'grid' | 'chips';
30
+ /** Rendering hint attached via .as() */
31
+ export interface RenderHint {
32
+ format: RenderFormat;
33
+ options?: Record<string, unknown>;
34
+ }
35
+ export declare class Collection<T> extends ReactiveArray<T> {
36
+ /** Rendering hint set by .as() */
37
+ _renderHint: RenderHint | null;
38
+ /**
39
+ * Create a new Collection with optional initial items.
40
+ * Items are loaded without triggering events.
41
+ */
42
+ constructor(items?: T[]);
43
+ /**
44
+ * Create a Collection bound to a property name and emitter (for runtime wiring).
45
+ */
46
+ static create<T>(propertyName: string, emitter: Emitter, initialItems?: T[]): Collection<T>;
47
+ /**
48
+ * Create a Collection from an existing array.
49
+ */
50
+ static from<T>(items: T[]): Collection<T>;
51
+ private _result;
52
+ /**
53
+ * Filter items by field comparison.
54
+ *
55
+ * Shorthand: `where('status', 'active')` → equality check
56
+ * Full: `where('price', '>', 100)` → comparison
57
+ */
58
+ where(key: keyof T & string, opOrVal: CompareOp | T[keyof T], val?: T[keyof T]): Collection<T>;
59
+ /**
60
+ * Filter items with a predicate function.
61
+ */
62
+ query(fn: (item: T) => boolean): Collection<T>;
63
+ /**
64
+ * Transform each item.
65
+ */
66
+ collect<U>(fn: (item: T) => U): Collection<U>;
67
+ /**
68
+ * Extract a single field from each item.
69
+ */
70
+ pluck<K extends keyof T>(key: K): Collection<T[K]>;
71
+ /**
72
+ * Sort by a key or comparator function.
73
+ * Returns a new sorted Collection (does NOT mutate).
74
+ */
75
+ sortBy(keyOrFn: (keyof T & string) | ((a: T, b: T) => number), direction?: 'asc' | 'desc'): Collection<T>;
76
+ /**
77
+ * Group items by a key or function.
78
+ * Returns a record of group-name → Collection.
79
+ */
80
+ groupBy(keyOrFn: (keyof T & string) | ((item: T) => string)): Record<string, Collection<T>>;
81
+ /**
82
+ * Remove duplicates, optionally by a key.
83
+ */
84
+ unique(key?: keyof T & string): Collection<T>;
85
+ /**
86
+ * Take the first n items.
87
+ */
88
+ take(n: number): Collection<T>;
89
+ /**
90
+ * Skip the first n items.
91
+ */
92
+ skip(n: number): Collection<T>;
93
+ /**
94
+ * Get the first item, optionally matching a predicate.
95
+ */
96
+ first(fn?: (item: T) => boolean): T | undefined;
97
+ /**
98
+ * Get the last item, optionally matching a predicate.
99
+ */
100
+ last(fn?: (item: T) => boolean): T | undefined;
101
+ /**
102
+ * Count items.
103
+ */
104
+ count(): number;
105
+ /**
106
+ * Check if collection is empty.
107
+ */
108
+ isEmpty(): boolean;
109
+ /**
110
+ * Sum numeric values, optionally by key.
111
+ */
112
+ sum(key?: keyof T & string): number;
113
+ /**
114
+ * Average of numeric values, optionally by key.
115
+ */
116
+ avg(key?: keyof T & string): number;
117
+ /**
118
+ * Item with minimum value (by key or raw comparison).
119
+ */
120
+ min(key?: keyof T & string): T | undefined;
121
+ /**
122
+ * Item with maximum value (by key or raw comparison).
123
+ */
124
+ max(key?: keyof T & string): T | undefined;
125
+ /**
126
+ * Reduce the collection to a single value.
127
+ */
128
+ aggregate<U>(fn: (acc: U, item: T) => U, initial: U): U;
129
+ /**
130
+ * Attach a rendering hint for auto-UI.
131
+ * Returns `this` for chaining at the end of a query.
132
+ */
133
+ as(format: RenderFormat, options?: Record<string, unknown>): this;
134
+ /**
135
+ * Custom serialization.
136
+ * - Without `.as()`: plain array (backward compatible)
137
+ * - With `.as()`: metadata object with `_photonType`, items, and count
138
+ */
139
+ toJSON(): T[] | {
140
+ _photonType: string;
141
+ items: T[];
142
+ count: number;
143
+ renderOptions?: Record<string, unknown>;
144
+ };
145
+ }
146
+ //# sourceMappingURL=Collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/collections/Collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Collection<T> — Rich queryable collection with Laravel-style chaining
3
+ *
4
+ * Extends ReactiveArray<T> so mutations auto-emit events. Query methods return
5
+ * new immutable Collection instances (no emitter wired) that can be further
6
+ * chained or serialized.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { PhotonMCP, Collection } from '@portel/photon-core';
11
+ *
12
+ * export default class ProductCatalog extends PhotonMCP {
13
+ * products = new Collection<Product>();
14
+ *
15
+ * async catalog() {
16
+ * return this.products.where('stock', '>', 0).sortBy('price');
17
+ * }
18
+ *
19
+ * async dashboard() {
20
+ * return this.products.where('category', 'Electronics').as('cards');
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ import { ReactiveArray } from './ReactiveArray.js';
26
+ // No-op emitter for query result collections (immutable — no events)
27
+ const NOOP_EMITTER = () => { };
28
+ export class Collection extends ReactiveArray {
29
+ /** Rendering hint set by .as() */
30
+ _renderHint = null;
31
+ /**
32
+ * Create a new Collection with optional initial items.
33
+ * Items are loaded without triggering events.
34
+ */
35
+ constructor(items) {
36
+ super();
37
+ if (items && items.length > 0) {
38
+ globalThis.Array.prototype.push.apply(this, items);
39
+ }
40
+ }
41
+ /**
42
+ * Create a Collection bound to a property name and emitter (for runtime wiring).
43
+ */
44
+ static create(propertyName, emitter, initialItems) {
45
+ const col = new Collection(initialItems);
46
+ col._propertyName = propertyName;
47
+ col._emitter = emitter;
48
+ return col;
49
+ }
50
+ /**
51
+ * Create a Collection from an existing array.
52
+ */
53
+ static from(items) {
54
+ return new Collection(items);
55
+ }
56
+ // ─── Helper: create an immutable query-result Collection ───
57
+ _result(items) {
58
+ const col = new Collection(items);
59
+ col._emitter = NOOP_EMITTER;
60
+ return col;
61
+ }
62
+ // ─── Query Methods (immutable — return new Collection) ───
63
+ /**
64
+ * Filter items by field comparison.
65
+ *
66
+ * Shorthand: `where('status', 'active')` → equality check
67
+ * Full: `where('price', '>', 100)` → comparison
68
+ */
69
+ where(key, opOrVal, val) {
70
+ let op;
71
+ let compareVal;
72
+ if (val === undefined) {
73
+ // Shorthand: where('status', 'active') → equality
74
+ op = '=';
75
+ compareVal = opOrVal;
76
+ }
77
+ else {
78
+ op = opOrVal;
79
+ compareVal = val;
80
+ }
81
+ return this._result(globalThis.Array.prototype.filter.call(this, (item) => {
82
+ const fieldVal = item[key];
83
+ switch (op) {
84
+ case '=': return fieldVal == compareVal;
85
+ case '===': return fieldVal === compareVal;
86
+ case '!=': return fieldVal != compareVal;
87
+ case '>': return fieldVal > compareVal;
88
+ case '<': return fieldVal < compareVal;
89
+ case '>=': return fieldVal >= compareVal;
90
+ case '<=': return fieldVal <= compareVal;
91
+ default: return false;
92
+ }
93
+ }));
94
+ }
95
+ /**
96
+ * Filter items with a predicate function.
97
+ */
98
+ query(fn) {
99
+ return this._result(globalThis.Array.prototype.filter.call(this, fn));
100
+ }
101
+ /**
102
+ * Transform each item.
103
+ */
104
+ collect(fn) {
105
+ return this._result(globalThis.Array.prototype.map.call(this, fn));
106
+ }
107
+ /**
108
+ * Extract a single field from each item.
109
+ */
110
+ pluck(key) {
111
+ return this._result(globalThis.Array.prototype.map.call(this, (item) => item[key]));
112
+ }
113
+ /**
114
+ * Sort by a key or comparator function.
115
+ * Returns a new sorted Collection (does NOT mutate).
116
+ */
117
+ sortBy(keyOrFn, direction = 'asc') {
118
+ const items = globalThis.Array.from(this);
119
+ if (typeof keyOrFn === 'function') {
120
+ items.sort(keyOrFn);
121
+ }
122
+ else {
123
+ const key = keyOrFn;
124
+ items.sort((a, b) => {
125
+ const aVal = a[key];
126
+ const bVal = b[key];
127
+ if (aVal < bVal)
128
+ return direction === 'asc' ? -1 : 1;
129
+ if (aVal > bVal)
130
+ return direction === 'asc' ? 1 : -1;
131
+ return 0;
132
+ });
133
+ }
134
+ return this._result(items);
135
+ }
136
+ /**
137
+ * Group items by a key or function.
138
+ * Returns a record of group-name → Collection.
139
+ */
140
+ groupBy(keyOrFn) {
141
+ const groups = {};
142
+ for (let i = 0; i < this.length; i++) {
143
+ const item = this[i];
144
+ const groupKey = typeof keyOrFn === 'function'
145
+ ? keyOrFn(item)
146
+ : String(item[keyOrFn]);
147
+ if (!groups[groupKey])
148
+ groups[groupKey] = [];
149
+ groups[groupKey].push(item);
150
+ }
151
+ const result = {};
152
+ for (const [k, v] of Object.entries(groups)) {
153
+ result[k] = this._result(v);
154
+ }
155
+ return result;
156
+ }
157
+ /**
158
+ * Remove duplicates, optionally by a key.
159
+ */
160
+ unique(key) {
161
+ const seen = new globalThis.Set();
162
+ const items = [];
163
+ for (let i = 0; i < this.length; i++) {
164
+ const item = this[i];
165
+ const val = key ? item[key] : item;
166
+ if (!seen.has(val)) {
167
+ seen.add(val);
168
+ items.push(item);
169
+ }
170
+ }
171
+ return this._result(items);
172
+ }
173
+ /**
174
+ * Take the first n items.
175
+ */
176
+ take(n) {
177
+ return this._result(globalThis.Array.prototype.slice.call(this, 0, n));
178
+ }
179
+ /**
180
+ * Skip the first n items.
181
+ */
182
+ skip(n) {
183
+ return this._result(globalThis.Array.prototype.slice.call(this, n));
184
+ }
185
+ // ─── Terminal Methods ───
186
+ /**
187
+ * Get the first item, optionally matching a predicate.
188
+ */
189
+ first(fn) {
190
+ if (!fn)
191
+ return this[0];
192
+ for (let i = 0; i < this.length; i++) {
193
+ if (fn(this[i]))
194
+ return this[i];
195
+ }
196
+ return undefined;
197
+ }
198
+ /**
199
+ * Get the last item, optionally matching a predicate.
200
+ */
201
+ last(fn) {
202
+ if (!fn)
203
+ return this[this.length - 1];
204
+ for (let i = this.length - 1; i >= 0; i--) {
205
+ if (fn(this[i]))
206
+ return this[i];
207
+ }
208
+ return undefined;
209
+ }
210
+ /**
211
+ * Count items.
212
+ */
213
+ count() {
214
+ return this.length;
215
+ }
216
+ /**
217
+ * Check if collection is empty.
218
+ */
219
+ isEmpty() {
220
+ return this.length === 0;
221
+ }
222
+ /**
223
+ * Sum numeric values, optionally by key.
224
+ */
225
+ sum(key) {
226
+ let total = 0;
227
+ for (let i = 0; i < this.length; i++) {
228
+ const val = key ? this[i][key] : this[i];
229
+ total += Number(val) || 0;
230
+ }
231
+ return total;
232
+ }
233
+ /**
234
+ * Average of numeric values, optionally by key.
235
+ */
236
+ avg(key) {
237
+ if (this.length === 0)
238
+ return 0;
239
+ return this.sum(key) / this.length;
240
+ }
241
+ /**
242
+ * Item with minimum value (by key or raw comparison).
243
+ */
244
+ min(key) {
245
+ if (this.length === 0)
246
+ return undefined;
247
+ let minItem = this[0];
248
+ let minVal = key ? minItem[key] : minItem;
249
+ for (let i = 1; i < this.length; i++) {
250
+ const val = key ? this[i][key] : this[i];
251
+ if (val < minVal) {
252
+ minItem = this[i];
253
+ minVal = val;
254
+ }
255
+ }
256
+ return minItem;
257
+ }
258
+ /**
259
+ * Item with maximum value (by key or raw comparison).
260
+ */
261
+ max(key) {
262
+ if (this.length === 0)
263
+ return undefined;
264
+ let maxItem = this[0];
265
+ let maxVal = key ? maxItem[key] : maxItem;
266
+ for (let i = 1; i < this.length; i++) {
267
+ const val = key ? this[i][key] : this[i];
268
+ if (val > maxVal) {
269
+ maxItem = this[i];
270
+ maxVal = val;
271
+ }
272
+ }
273
+ return maxItem;
274
+ }
275
+ /**
276
+ * Reduce the collection to a single value.
277
+ */
278
+ aggregate(fn, initial) {
279
+ let acc = initial;
280
+ for (let i = 0; i < this.length; i++) {
281
+ acc = fn(acc, this[i]);
282
+ }
283
+ return acc;
284
+ }
285
+ // ─── Rendering Hints ───
286
+ /**
287
+ * Attach a rendering hint for auto-UI.
288
+ * Returns `this` for chaining at the end of a query.
289
+ */
290
+ as(format, options) {
291
+ this._renderHint = { format, options };
292
+ return this;
293
+ }
294
+ /**
295
+ * Custom serialization.
296
+ * - Without `.as()`: plain array (backward compatible)
297
+ * - With `.as()`: metadata object with `_photonType`, items, and count
298
+ */
299
+ toJSON() {
300
+ const items = globalThis.Array.from(this);
301
+ if (!this._renderHint) {
302
+ return items;
303
+ }
304
+ return {
305
+ _photonType: `collection:${this._renderHint.format}`,
306
+ items,
307
+ count: items.length,
308
+ ...(this._renderHint.options ? { renderOptions: this._renderHint.options } : {}),
309
+ };
310
+ }
311
+ }
312
+ //# sourceMappingURL=Collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/collections/Collection.ts"],"names":[],"mappings":"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"}
@@ -51,6 +51,7 @@
51
51
  export { ReactiveArray, type Emitter } from './ReactiveArray.js';
52
52
  export { ReactiveMap } from './ReactiveMap.js';
53
53
  export { ReactiveSet } from './ReactiveSet.js';
54
+ export { Collection, type RenderHint, type RenderFormat, type CompareOp } from './Collection.js';
54
55
  export { ReactiveArray as Array } from './ReactiveArray.js';
55
56
  export { ReactiveMap as Map } from './ReactiveMap.js';
56
57
  export { ReactiveSet as Set } from './ReactiveSet.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAI/C,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjG,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC"}
@@ -51,6 +51,7 @@
51
51
  export { ReactiveArray } from './ReactiveArray.js';
52
52
  export { ReactiveMap } from './ReactiveMap.js';
53
53
  export { ReactiveSet } from './ReactiveSet.js';
54
+ export { Collection } from './Collection.js';
54
55
  // Level 1 exports: Shadow global types for zero-effort reactivity
55
56
  // Just `import { Array } from '@portel/photon-core'` and use normally
56
57
  export { ReactiveArray as Array } from './ReactiveArray.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,kEAAkE;AAClE,sEAAsE;AACtE,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAsD,MAAM,iBAAiB,CAAC;AAEjG,kEAAkE;AAClE,sEAAsE;AACtE,OAAO,EAAE,aAAa,IAAI,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -61,6 +61,6 @@ export { discoverAssets, autoDiscoverAssets, } from './asset-discovery.js';
61
61
  export { Array, // Shadows global Array
62
62
  Map, // Shadows global Map
63
63
  Set, // Shadows global Set
64
- ReactiveArray, ReactiveMap, ReactiveSet, type Emitter, } from './collections/index.js';
64
+ ReactiveArray, ReactiveMap, ReactiveSet, type Emitter, Collection, type RenderHint, type RenderFormat, type CompareOp, } from './collections/index.js';
65
65
  export { PhotonUIType, isPhotonUIType, Field, type FieldDefinition, type FieldType, type FieldAlignment, type BaseFieldOptions, type TextFieldOptions, type NumberFieldOptions, type CurrencyFieldOptions, type DateFieldOptions, type DateFormat, type ImageFieldOptions, type BadgeFieldOptions, type RatingFieldOptions, type PriceFieldOptions, type StockFieldOptions, type ActionItem, type ActionsFieldOptions, type RenderFunction, getFieldValue, formatFieldLabel, interpolateTemplate, renderFieldToText, renderFieldToStructured, type RenderedField, Table, type TableColumn, type TableOptions, type ColumnType, Cards, type CardFieldMapping, type CardsOptions, Chart, type ChartType, type ChartSeries, type ChartDataPoint, type ChartOptions, Stats, type StatItem, type StatFormat, type StatsOptions, Progress, type ProgressBar, type ProgressStep, type ProgressStyle, type StepStatus, type ProgressOptions, Form, type FormField, type FieldType as FormFieldType, type FormOptions, } from './ui-types/index.js';
66
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -142,7 +142,9 @@ Array, // Shadows global Array
142
142
  Map, // Shadows global Map
143
143
  Set, // Shadows global Set
144
144
  // Level 2: Explicit control - use .create() for custom wiring
145
- ReactiveArray, ReactiveMap, ReactiveSet, } from './collections/index.js';
145
+ ReactiveArray, ReactiveMap, ReactiveSet,
146
+ // Level 2+: Rich queryable collection with rendering hints
147
+ Collection, } from './collections/index.js';
146
148
  // ===== PURPOSE-DRIVEN UI TYPES =====
147
149
  // Polymorphic return types that auto-render with appropriate UI
148
150
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,yCAAyC;AACzC,gEAAgE;AAChE,OAAO;AASL,iBAAiB;AACjB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,UAAU,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,MAAM;AAEN,WAAW;AACX,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,gBAAgB;AAEhB,oBAAoB;AACpB,gBAAgB,EAChB,cAAc,EACd,UAAU;AAEV,aAAa;AACb,SAAS;AAET,iBAAiB;AACjB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa;AAEb,SAAS;AACT,MAAM,EACN,YAAY,EACZ,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,yCAAyC;AACzC,oDAAoD;AACpD,OAAO;AAeL,aAAa;AACb,SAAS,EAET,QAAQ,EACR,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,cAAc;AAEd,oBAAoB;AACpB,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,yBAAyB,EACzB,gBAAgB;AAEhB,oBAAoB;AACpB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,cAAc;AAEd,cAAc;AACd,MAAM,EACN,OAAO,EACP,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,sCAAsC;AAEtC,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,wBAAwB;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,0CAA0C;AAC1C,OAAO,EACL,WAAW,EACX,SAAS,EACT,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,kBAAkB,GAEnB,MAAM,oBAAoB,CAAC;AAE5B,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,8CAA8C;AAC9C,OAAO;AACL,cAAc;AACd,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,WAAW;AAEX,sBAAsB;AACtB,wBAAwB,EACxB,gBAAgB;AAEhB,WAAW;AACX,gBAAgB;AAEhB,iBAAiB;AACjB,WAAW;AAEX,qBAAqB;AACrB,uBAAuB,EACvB,eAAe;AAEf,UAAU;AACV,eAAe;AAmDf,uBAAuB;AACvB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,EACV,aAAa,GAQd,MAAM,gBAAgB,CAAC;AAExB,8BAA8B;AAC9B,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,wBAAwB,EACxB,aAAa,EACb,oBAAoB,EACpB,QAAQ,EACR,UAAU,EACV,SAAS,EACT,WAAW,EAGX,iBAAiB,IAAI,yBAAyB,GAM/C,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EAKL,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,cAAc,EAEd,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,kBAAkB;AAClB,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAE9B,gBAAgB;AAChB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAExC,4CAA4C;AAC5C,qCAAqC;AACrC,cAAc,0BAA0B,CAAC;AAEzC,iDAAiD;AACjD,cAAc,sBAAsB,CAAC;AAErC,gDAAgD;AAChD,qEAAqE;AACrE,cAAc,gBAAgB,CAAC;AAE/B,oCAAoC;AACpC,6EAA6E;AAC7E,cAAc,qBAAqB,CAAC;AAEpC,2BAA2B;AAC3B,qDAAqD;AACrD,OAAO,EACL,QAAQ,EACR,cAAc,EACd,cAAc,GAEf,MAAM,iBAAiB,CAAC;AAEzB,gCAAgC;AAChC,mEAAmE;AACnE,OAAO,EAQL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB,uCAAuC;AACvC,gEAAgE;AAChE,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,8BAA8B;AAC9B,4CAA4C;AAC5C,OAAO,EACL,OAAO,EACP,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,oCAAoC;AACpC,+CAA+C;AAC/C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,cAAc,GAGf,MAAM,gBAAgB,CAAC;AAExB,kCAAkC;AAClC,oDAAoD;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,yBAAyB;AACzB,uCAAuC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,4BAA4B;AAC5B,2DAA2D;AAC3D,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAE5B,yBAAyB;AACzB,oDAAoD;AACpD,OAAO,EACL,WAAW,EACX,eAAe,EAGf,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,cAAc,EACd,OAAO,EACP,KAAK,EACL,OAAO,EACP,UAAU,EACV,SAAS,EACT,cAAc,EACd,OAAO,EACP,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,UAAU,EACV,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,8BAA8B;AAC9B,6DAA6D;AAC7D,OAAO,EACL,cAAc,EACd,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,kCAAkC;AAClC,4DAA4D;AAC5D,OAAO;AACL,kEAAkE;AAClE,KAAK,EAAG,uBAAuB;AAC/B,GAAG,EAAK,qBAAqB;AAC7B,GAAG,EAAK,qBAAqB;AAC7B,8DAA8D;AAC9D,aAAa,EACb,WAAW,EACX,WAAW,GAEZ,MAAM,wBAAwB,CAAC;AAEhC,sCAAsC;AACtC,gEAAgE;AAChE,OAAO;AACL,OAAO;AACP,YAAY,EACZ,cAAc;AAEd,mCAAmC;AACnC,KAAK,EAkBL,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB;AAGvB,eAAe;AACf,KAAK,EAIL,KAAK;AAIL,gBAAgB;AAChB,KAAK,EAKL,KAAK,EAIL,QAAQ;AAOR,cAAc;AACd,IAAI,GAIL,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portel/photon-core",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "description": "Core library for parsing, loading, and managing .photon.ts files - runtime-agnostic foundation for building custom Photon runtimes",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Collection<T> — Rich queryable collection with Laravel-style chaining
3
+ *
4
+ * Extends ReactiveArray<T> so mutations auto-emit events. Query methods return
5
+ * new immutable Collection instances (no emitter wired) that can be further
6
+ * chained or serialized.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { PhotonMCP, Collection } from '@portel/photon-core';
11
+ *
12
+ * export default class ProductCatalog extends PhotonMCP {
13
+ * products = new Collection<Product>();
14
+ *
15
+ * async catalog() {
16
+ * return this.products.where('stock', '>', 0).sortBy('price');
17
+ * }
18
+ *
19
+ * async dashboard() {
20
+ * return this.products.where('category', 'Electronics').as('cards');
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+
26
+ import { ReactiveArray, type Emitter } from './ReactiveArray.js';
27
+
28
+ /** Comparison operators for where() clauses */
29
+ export type CompareOp = '=' | '!=' | '>' | '<' | '>=' | '<=' | '===';
30
+
31
+ /** Rendering format hints for auto-UI */
32
+ export type RenderFormat = 'table' | 'cards' | 'list' | 'chart' | 'grid' | 'chips';
33
+
34
+ /** Rendering hint attached via .as() */
35
+ export interface RenderHint {
36
+ format: RenderFormat;
37
+ options?: Record<string, unknown>;
38
+ }
39
+
40
+ // No-op emitter for query result collections (immutable — no events)
41
+ const NOOP_EMITTER: Emitter = () => {};
42
+
43
+ export class Collection<T> extends ReactiveArray<T> {
44
+ /** Rendering hint set by .as() */
45
+ _renderHint: RenderHint | null = null;
46
+
47
+ /**
48
+ * Create a new Collection with optional initial items.
49
+ * Items are loaded without triggering events.
50
+ */
51
+ constructor(items?: T[]) {
52
+ super();
53
+ if (items && items.length > 0) {
54
+ globalThis.Array.prototype.push.apply(this, items);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Create a Collection bound to a property name and emitter (for runtime wiring).
60
+ */
61
+ static override create<T>(
62
+ propertyName: string,
63
+ emitter: Emitter,
64
+ initialItems?: T[]
65
+ ): Collection<T> {
66
+ const col = new Collection<T>(initialItems);
67
+ (col as any)._propertyName = propertyName;
68
+ (col as any)._emitter = emitter;
69
+ return col;
70
+ }
71
+
72
+ /**
73
+ * Create a Collection from an existing array.
74
+ */
75
+ static from<T>(items: T[]): Collection<T> {
76
+ return new Collection<T>(items);
77
+ }
78
+
79
+ // ─── Helper: create an immutable query-result Collection ───
80
+
81
+ private _result<U>(items: U[]): Collection<U> {
82
+ const col = new Collection<U>(items);
83
+ (col as any)._emitter = NOOP_EMITTER;
84
+ return col;
85
+ }
86
+
87
+ // ─── Query Methods (immutable — return new Collection) ───
88
+
89
+ /**
90
+ * Filter items by field comparison.
91
+ *
92
+ * Shorthand: `where('status', 'active')` → equality check
93
+ * Full: `where('price', '>', 100)` → comparison
94
+ */
95
+ where(key: keyof T & string, opOrVal: CompareOp | T[keyof T], val?: T[keyof T]): Collection<T> {
96
+ let op: CompareOp;
97
+ let compareVal: unknown;
98
+
99
+ if (val === undefined) {
100
+ // Shorthand: where('status', 'active') → equality
101
+ op = '=';
102
+ compareVal = opOrVal;
103
+ } else {
104
+ op = opOrVal as CompareOp;
105
+ compareVal = val;
106
+ }
107
+
108
+ return this._result(
109
+ globalThis.Array.prototype.filter.call(this, (item: T) => {
110
+ const fieldVal = (item as Record<string, unknown>)[key];
111
+ switch (op) {
112
+ case '=': return fieldVal == compareVal;
113
+ case '===': return fieldVal === compareVal;
114
+ case '!=': return fieldVal != compareVal;
115
+ case '>': return (fieldVal as number) > (compareVal as number);
116
+ case '<': return (fieldVal as number) < (compareVal as number);
117
+ case '>=': return (fieldVal as number) >= (compareVal as number);
118
+ case '<=': return (fieldVal as number) <= (compareVal as number);
119
+ default: return false;
120
+ }
121
+ }) as T[]
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Filter items with a predicate function.
127
+ */
128
+ query(fn: (item: T) => boolean): Collection<T> {
129
+ return this._result(
130
+ globalThis.Array.prototype.filter.call(this, fn) as T[]
131
+ );
132
+ }
133
+
134
+ /**
135
+ * Transform each item.
136
+ */
137
+ collect<U>(fn: (item: T) => U): Collection<U> {
138
+ return this._result(
139
+ globalThis.Array.prototype.map.call(this, fn) as U[]
140
+ );
141
+ }
142
+
143
+ /**
144
+ * Extract a single field from each item.
145
+ */
146
+ pluck<K extends keyof T>(key: K): Collection<T[K]> {
147
+ return this._result(
148
+ globalThis.Array.prototype.map.call(this, (item: T) => item[key]) as T[K][]
149
+ );
150
+ }
151
+
152
+ /**
153
+ * Sort by a key or comparator function.
154
+ * Returns a new sorted Collection (does NOT mutate).
155
+ */
156
+ sortBy(keyOrFn: keyof T & string | ((a: T, b: T) => number), direction: 'asc' | 'desc' = 'asc'): Collection<T> {
157
+ const items = globalThis.Array.from(this) as T[];
158
+ if (typeof keyOrFn === 'function') {
159
+ items.sort(keyOrFn);
160
+ } else {
161
+ const key = keyOrFn;
162
+ items.sort((a, b) => {
163
+ const aVal = (a as Record<string, unknown>)[key] as number;
164
+ const bVal = (b as Record<string, unknown>)[key] as number;
165
+ if (aVal < bVal) return direction === 'asc' ? -1 : 1;
166
+ if (aVal > bVal) return direction === 'asc' ? 1 : -1;
167
+ return 0;
168
+ });
169
+ }
170
+ return this._result(items);
171
+ }
172
+
173
+ /**
174
+ * Group items by a key or function.
175
+ * Returns a record of group-name → Collection.
176
+ */
177
+ groupBy(keyOrFn: keyof T & string | ((item: T) => string)): Record<string, Collection<T>> {
178
+ const groups: Record<string, T[]> = {};
179
+ for (let i = 0; i < this.length; i++) {
180
+ const item = this[i];
181
+ const groupKey = typeof keyOrFn === 'function'
182
+ ? keyOrFn(item)
183
+ : String((item as Record<string, unknown>)[keyOrFn]);
184
+ if (!groups[groupKey]) groups[groupKey] = [];
185
+ groups[groupKey].push(item);
186
+ }
187
+ const result: Record<string, Collection<T>> = {};
188
+ for (const [k, v] of Object.entries(groups)) {
189
+ result[k] = this._result(v);
190
+ }
191
+ return result;
192
+ }
193
+
194
+ /**
195
+ * Remove duplicates, optionally by a key.
196
+ */
197
+ unique(key?: keyof T & string): Collection<T> {
198
+ const seen = new globalThis.Set<unknown>();
199
+ const items: T[] = [];
200
+ for (let i = 0; i < this.length; i++) {
201
+ const item = this[i];
202
+ const val = key ? (item as Record<string, unknown>)[key] : item;
203
+ if (!seen.has(val)) {
204
+ seen.add(val);
205
+ items.push(item);
206
+ }
207
+ }
208
+ return this._result(items);
209
+ }
210
+
211
+ /**
212
+ * Take the first n items.
213
+ */
214
+ take(n: number): Collection<T> {
215
+ return this._result(globalThis.Array.prototype.slice.call(this, 0, n) as T[]);
216
+ }
217
+
218
+ /**
219
+ * Skip the first n items.
220
+ */
221
+ skip(n: number): Collection<T> {
222
+ return this._result(globalThis.Array.prototype.slice.call(this, n) as T[]);
223
+ }
224
+
225
+ // ─── Terminal Methods ───
226
+
227
+ /**
228
+ * Get the first item, optionally matching a predicate.
229
+ */
230
+ first(fn?: (item: T) => boolean): T | undefined {
231
+ if (!fn) return this[0];
232
+ for (let i = 0; i < this.length; i++) {
233
+ if (fn(this[i])) return this[i];
234
+ }
235
+ return undefined;
236
+ }
237
+
238
+ /**
239
+ * Get the last item, optionally matching a predicate.
240
+ */
241
+ last(fn?: (item: T) => boolean): T | undefined {
242
+ if (!fn) return this[this.length - 1];
243
+ for (let i = this.length - 1; i >= 0; i--) {
244
+ if (fn(this[i])) return this[i];
245
+ }
246
+ return undefined;
247
+ }
248
+
249
+ /**
250
+ * Count items.
251
+ */
252
+ count(): number {
253
+ return this.length;
254
+ }
255
+
256
+ /**
257
+ * Check if collection is empty.
258
+ */
259
+ isEmpty(): boolean {
260
+ return this.length === 0;
261
+ }
262
+
263
+ /**
264
+ * Sum numeric values, optionally by key.
265
+ */
266
+ sum(key?: keyof T & string): number {
267
+ let total = 0;
268
+ for (let i = 0; i < this.length; i++) {
269
+ const val = key ? (this[i] as Record<string, unknown>)[key] : this[i];
270
+ total += Number(val) || 0;
271
+ }
272
+ return total;
273
+ }
274
+
275
+ /**
276
+ * Average of numeric values, optionally by key.
277
+ */
278
+ avg(key?: keyof T & string): number {
279
+ if (this.length === 0) return 0;
280
+ return this.sum(key) / this.length;
281
+ }
282
+
283
+ /**
284
+ * Item with minimum value (by key or raw comparison).
285
+ */
286
+ min(key?: keyof T & string): T | undefined {
287
+ if (this.length === 0) return undefined;
288
+ let minItem = this[0];
289
+ let minVal = key ? (minItem as Record<string, unknown>)[key] : minItem;
290
+ for (let i = 1; i < this.length; i++) {
291
+ const val = key ? (this[i] as Record<string, unknown>)[key] : this[i];
292
+ if ((val as number) < (minVal as number)) {
293
+ minItem = this[i];
294
+ minVal = val;
295
+ }
296
+ }
297
+ return minItem;
298
+ }
299
+
300
+ /**
301
+ * Item with maximum value (by key or raw comparison).
302
+ */
303
+ max(key?: keyof T & string): T | undefined {
304
+ if (this.length === 0) return undefined;
305
+ let maxItem = this[0];
306
+ let maxVal = key ? (maxItem as Record<string, unknown>)[key] : maxItem;
307
+ for (let i = 1; i < this.length; i++) {
308
+ const val = key ? (this[i] as Record<string, unknown>)[key] : this[i];
309
+ if ((val as number) > (maxVal as number)) {
310
+ maxItem = this[i];
311
+ maxVal = val;
312
+ }
313
+ }
314
+ return maxItem;
315
+ }
316
+
317
+ /**
318
+ * Reduce the collection to a single value.
319
+ */
320
+ aggregate<U>(fn: (acc: U, item: T) => U, initial: U): U {
321
+ let acc = initial;
322
+ for (let i = 0; i < this.length; i++) {
323
+ acc = fn(acc, this[i]);
324
+ }
325
+ return acc;
326
+ }
327
+
328
+ // ─── Rendering Hints ───
329
+
330
+ /**
331
+ * Attach a rendering hint for auto-UI.
332
+ * Returns `this` for chaining at the end of a query.
333
+ */
334
+ as(format: RenderFormat, options?: Record<string, unknown>): this {
335
+ this._renderHint = { format, options };
336
+ return this;
337
+ }
338
+
339
+ /**
340
+ * Custom serialization.
341
+ * - Without `.as()`: plain array (backward compatible)
342
+ * - With `.as()`: metadata object with `_photonType`, items, and count
343
+ */
344
+ toJSON(): T[] | { _photonType: string; items: T[]; count: number; renderOptions?: Record<string, unknown> } {
345
+ const items = globalThis.Array.from(this) as T[];
346
+ if (!this._renderHint) {
347
+ return items;
348
+ }
349
+ return {
350
+ _photonType: `collection:${this._renderHint.format}`,
351
+ items,
352
+ count: items.length,
353
+ ...(this._renderHint.options ? { renderOptions: this._renderHint.options } : {}),
354
+ };
355
+ }
356
+ }
@@ -52,6 +52,7 @@
52
52
  export { ReactiveArray, type Emitter } from './ReactiveArray.js';
53
53
  export { ReactiveMap } from './ReactiveMap.js';
54
54
  export { ReactiveSet } from './ReactiveSet.js';
55
+ export { Collection, type RenderHint, type RenderFormat, type CompareOp } from './Collection.js';
55
56
 
56
57
  // Level 1 exports: Shadow global types for zero-effort reactivity
57
58
  // Just `import { Array } from '@portel/photon-core'` and use normally
package/src/index.ts CHANGED
@@ -453,6 +453,11 @@ export {
453
453
  ReactiveMap,
454
454
  ReactiveSet,
455
455
  type Emitter,
456
+ // Level 2+: Rich queryable collection with rendering hints
457
+ Collection,
458
+ type RenderHint,
459
+ type RenderFormat,
460
+ type CompareOp,
456
461
  } from './collections/index.js';
457
462
 
458
463
  // ===== PURPOSE-DRIVEN UI TYPES =====