@arcote.tech/arc 0.3.3 → 0.3.4
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/context-element/static-view/index.d.ts +3 -0
- package/dist/context-element/static-view/static-view-data.d.ts +15 -0
- package/dist/context-element/static-view/static-view.d.ts +129 -0
- package/dist/index.js +17 -5
- package/dist/streaming/streaming-query-cache.d.ts +9 -2
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static View Data - Type definitions for static view configuration
|
|
3
|
+
*/
|
|
4
|
+
import type { ArcObjectAny } from "../../elements/object";
|
|
5
|
+
/**
|
|
6
|
+
* Static view data structure
|
|
7
|
+
*/
|
|
8
|
+
export interface ArcStaticViewData {
|
|
9
|
+
name: string;
|
|
10
|
+
id: any;
|
|
11
|
+
schema: ArcObjectAny;
|
|
12
|
+
items: any[];
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=static-view-data.d.ts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arc Static View - Read-only view with hardcoded data
|
|
3
|
+
*
|
|
4
|
+
* Static views contain data defined at build time, not populated from events.
|
|
5
|
+
* Useful for product catalogs, pricing tiers, configuration options, etc.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Define items at build time via addItems()
|
|
9
|
+
* - Query via find/findOne (same interface as regular views)
|
|
10
|
+
* - No event handlers (read-only)
|
|
11
|
+
* - No database storage (in-memory)
|
|
12
|
+
* - Always public (no protectBy)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const products = staticView("products", productId, {
|
|
17
|
+
* name: string(),
|
|
18
|
+
* price: number(),
|
|
19
|
+
* }).addItems([
|
|
20
|
+
* { _id: "basic", name: "Basic Plan", price: 9.99 },
|
|
21
|
+
* { _id: "pro", name: "Pro Plan", price: 29.99 },
|
|
22
|
+
* ]);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import type { ArcObjectAny, ArcRawShape } from "../../elements/object";
|
|
26
|
+
import { ArcObject } from "../../elements/object";
|
|
27
|
+
import type { ModelAdapters } from "../../model/model-adapters";
|
|
28
|
+
import type { Merge } from "../../utils";
|
|
29
|
+
import type { $type } from "../../utils/types/get-type";
|
|
30
|
+
import { ArcContextElement } from "../context-element";
|
|
31
|
+
import type { ArcStaticViewData } from "./static-view-data";
|
|
32
|
+
/** Item type for static view */
|
|
33
|
+
export type ArcStaticViewItem<Id, Schema extends ArcObjectAny> = {
|
|
34
|
+
_id: Id extends {
|
|
35
|
+
deserialize: (...args: any) => any;
|
|
36
|
+
} ? $type<Id> : Id;
|
|
37
|
+
} & $type<Schema>;
|
|
38
|
+
/**
|
|
39
|
+
* Arc Static View class
|
|
40
|
+
*/
|
|
41
|
+
export declare class ArcStaticView<const Data extends ArcStaticViewData> extends ArcContextElement<Data["name"]> {
|
|
42
|
+
private readonly data;
|
|
43
|
+
constructor(data: Data);
|
|
44
|
+
/**
|
|
45
|
+
* Get view ID schema
|
|
46
|
+
*/
|
|
47
|
+
get id(): Data["id"];
|
|
48
|
+
/**
|
|
49
|
+
* Get view schema
|
|
50
|
+
*/
|
|
51
|
+
get schema(): Data["schema"];
|
|
52
|
+
/**
|
|
53
|
+
* Get static items
|
|
54
|
+
*/
|
|
55
|
+
get items(): Data["items"];
|
|
56
|
+
/**
|
|
57
|
+
* Set view description for documentation
|
|
58
|
+
*/
|
|
59
|
+
description<const Desc extends string>(description: Desc): ArcStaticView<Merge<Data, {
|
|
60
|
+
description: Desc;
|
|
61
|
+
}>>;
|
|
62
|
+
/**
|
|
63
|
+
* Add static items to the view
|
|
64
|
+
*/
|
|
65
|
+
addItems<const Items extends ArcStaticViewItem<Data["id"], Data["schema"]>[]>(items: Items): ArcStaticView<Merge<Data, {
|
|
66
|
+
items: Items;
|
|
67
|
+
}>>;
|
|
68
|
+
/**
|
|
69
|
+
* Generate query context for this static view
|
|
70
|
+
* Returns find/findOne methods that query the static items
|
|
71
|
+
*/
|
|
72
|
+
queryContext(_adapters: ModelAdapters): {
|
|
73
|
+
find: (options?: {
|
|
74
|
+
where?: Record<string, any>;
|
|
75
|
+
orderBy?: Record<string, "asc" | "desc">;
|
|
76
|
+
limit?: number;
|
|
77
|
+
}) => Promise<Data["items"]>;
|
|
78
|
+
findOne: (where?: Record<string, any>) => Promise<Data["items"][number] | undefined>;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Check if an item matches a where clause
|
|
82
|
+
*/
|
|
83
|
+
private matchesWhere;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create a new static view with the given name, ID schema, and data schema
|
|
87
|
+
*
|
|
88
|
+
* @param name - Unique view name
|
|
89
|
+
* @param id - ID schema for view records
|
|
90
|
+
* @param schema - Data schema for view records
|
|
91
|
+
* @returns New static view instance ready for configuration
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const plans = staticView("plans", planId, {
|
|
96
|
+
* name: string(),
|
|
97
|
+
* price: number(),
|
|
98
|
+
* }).addItems([
|
|
99
|
+
* { _id: "free", name: "Free", price: 0 },
|
|
100
|
+
* { _id: "pro", name: "Pro", price: 19.99 },
|
|
101
|
+
* ]);
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function staticView<const Name extends string, Id, Schema extends ArcObjectAny | ArcRawShape>(name: Name, id: Id, schema: Schema): ArcStaticView<{
|
|
105
|
+
name: Name;
|
|
106
|
+
id: Id;
|
|
107
|
+
schema: ArcObject<ArcRawShape, [{
|
|
108
|
+
name: "type";
|
|
109
|
+
validator: (value: any) => false | {
|
|
110
|
+
current: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
|
|
111
|
+
expected: "object";
|
|
112
|
+
};
|
|
113
|
+
}, {
|
|
114
|
+
name: "schema";
|
|
115
|
+
validator: (value: any) => false | {
|
|
116
|
+
[x: string]: unknown;
|
|
117
|
+
};
|
|
118
|
+
}]> | (Schema & ArcObject<any, any>);
|
|
119
|
+
items: [];
|
|
120
|
+
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Type alias for any static view (used in collections)
|
|
123
|
+
*/
|
|
124
|
+
export type ArcStaticViewAny = ArcStaticView<any>;
|
|
125
|
+
/**
|
|
126
|
+
* Helper type to extract static view record type
|
|
127
|
+
*/
|
|
128
|
+
export type ArcStaticViewRecord<View extends ArcStaticViewAny> = View extends ArcStaticView<infer Data> ? ArcStaticViewItem<Data["id"], Data["schema"]> : never;
|
|
129
|
+
//# sourceMappingURL=static-view.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -3551,6 +3551,10 @@ class StreamingQueryCache {
|
|
|
3551
3551
|
}
|
|
3552
3552
|
return this.stores.get(viewName);
|
|
3553
3553
|
}
|
|
3554
|
+
hasData(viewName) {
|
|
3555
|
+
const store = this.stores.get(viewName);
|
|
3556
|
+
return store ? store.hasData() : false;
|
|
3557
|
+
}
|
|
3554
3558
|
hasActiveStream(viewName) {
|
|
3555
3559
|
return this.activeStreams.has(viewName);
|
|
3556
3560
|
}
|
|
@@ -3558,14 +3562,20 @@ class StreamingQueryCache {
|
|
|
3558
3562
|
const existing = this.activeStreams.get(viewName);
|
|
3559
3563
|
if (existing) {
|
|
3560
3564
|
existing.refCount++;
|
|
3561
|
-
return
|
|
3565
|
+
return {
|
|
3566
|
+
unsubscribe: () => this.unregisterStream(viewName),
|
|
3567
|
+
wasReused: true
|
|
3568
|
+
};
|
|
3562
3569
|
}
|
|
3563
3570
|
const streamConn = createStream();
|
|
3564
3571
|
this.activeStreams.set(viewName, {
|
|
3565
3572
|
unsubscribe: streamConn.unsubscribe,
|
|
3566
3573
|
refCount: 1
|
|
3567
3574
|
});
|
|
3568
|
-
return
|
|
3575
|
+
return {
|
|
3576
|
+
unsubscribe: () => this.unregisterStream(viewName),
|
|
3577
|
+
wasReused: false
|
|
3578
|
+
};
|
|
3569
3579
|
}
|
|
3570
3580
|
unregisterStream(viewName) {
|
|
3571
3581
|
const stream = this.activeStreams.get(viewName);
|
|
@@ -3627,6 +3637,9 @@ class StreamingQueryCache {
|
|
|
3627
3637
|
class StreamingStore {
|
|
3628
3638
|
data = new Map;
|
|
3629
3639
|
listeners = new Set;
|
|
3640
|
+
hasData() {
|
|
3641
|
+
return this.data.size > 0;
|
|
3642
|
+
}
|
|
3630
3643
|
setAll(items) {
|
|
3631
3644
|
this.data.clear();
|
|
3632
3645
|
for (const item of items) {
|
|
@@ -3781,14 +3794,13 @@ function streamingLiveQuery(model, queryFn, callback, options) {
|
|
|
3781
3794
|
executeQuery();
|
|
3782
3795
|
});
|
|
3783
3796
|
unsubscribers.push(cacheUnsub);
|
|
3784
|
-
const
|
|
3785
|
-
const streamUnsub = cache.registerStream(viewName, () => {
|
|
3797
|
+
const { unsubscribe: streamUnsub, wasReused } = cache.registerStream(viewName, () => {
|
|
3786
3798
|
return queryWire.stream(viewName, {}, (data) => {
|
|
3787
3799
|
cache.setViewData(viewName, data);
|
|
3788
3800
|
}, authToken);
|
|
3789
3801
|
});
|
|
3790
3802
|
unsubscribers.push(streamUnsub);
|
|
3791
|
-
if (
|
|
3803
|
+
if (wasReused && cache.hasData(viewName)) {
|
|
3792
3804
|
executeQuery();
|
|
3793
3805
|
}
|
|
3794
3806
|
}
|
|
@@ -40,17 +40,24 @@ export declare class StreamingQueryCache {
|
|
|
40
40
|
getStore<Item extends {
|
|
41
41
|
_id: string;
|
|
42
42
|
}>(viewName: string): StreamingQueryCacheStore<Item>;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a store has any data
|
|
45
|
+
*/
|
|
46
|
+
hasData(viewName: string): boolean;
|
|
43
47
|
/**
|
|
44
48
|
* Check if a stream is already active for a view
|
|
45
49
|
*/
|
|
46
50
|
hasActiveStream(viewName: string): boolean;
|
|
47
51
|
/**
|
|
48
52
|
* Register an active stream for a view (increment ref count if exists)
|
|
49
|
-
* Returns
|
|
53
|
+
* Returns object with unsubscribe function and whether stream was reused
|
|
50
54
|
*/
|
|
51
55
|
registerStream(viewName: string, createStream: () => {
|
|
52
56
|
unsubscribe: () => void;
|
|
53
|
-
}):
|
|
57
|
+
}): {
|
|
58
|
+
unsubscribe: () => void;
|
|
59
|
+
wasReused: boolean;
|
|
60
|
+
};
|
|
54
61
|
/**
|
|
55
62
|
* Unregister from a stream (decrement ref count, close if zero)
|
|
56
63
|
*/
|
package/package.json
CHANGED