@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.
@@ -0,0 +1,3 @@
1
+ export * from "./static-view";
2
+ export * from "./static-view-data";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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 () => this.unregisterStream(viewName);
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 () => this.unregisterStream(viewName);
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 streamAlreadyExists = cache.hasActiveStream(viewName);
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 (streamAlreadyExists) {
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 a function to unregister when done
53
+ * Returns object with unsubscribe function and whether stream was reused
50
54
  */
51
55
  registerStream(viewName: string, createStream: () => {
52
56
  unsubscribe: () => void;
53
- }): () => void;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc",
3
3
  "type": "module",
4
- "version": "0.3.3",
4
+ "version": "0.3.4",
5
5
  "private": false,
6
6
  "author": "Przemysław Krasiński [arcote.tech]",
7
7
  "description": "Arc framework core rewrite with improved event emission and type safety",