@powerhousedao/academy 3.2.0-staging.0 → 3.2.0-staging.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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 3.2.0-staging.2 (2025-07-01)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **reactor-api,reactor-local:** allow providing processors to be instantiated and enable drive analytics ([1a3800fc2](https://github.com/powerhouse-inc/powerhouse/commit/1a3800fc2))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - acaldas @acaldas
10
+
11
+ ## 3.2.0-staging.1 (2025-07-01)
12
+
13
+ ### 🚀 Features
14
+
15
+ - **academy:** add Drive Analytics documentation and examples ([430ca8fab](https://github.com/powerhouse-inc/powerhouse/commit/430ca8fab))
16
+ - **connect:** use atom store and provider from state library ([d617a1fe2](https://github.com/powerhouse-inc/powerhouse/commit/d617a1fe2))
17
+
18
+ ### ❤️ Thank You
19
+
20
+ - Guillermo Puente
21
+ - ryanwolhuter
22
+
1
23
  ## 3.2.0-staging.0 (2025-06-26)
2
24
 
3
25
  This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
@@ -0,0 +1,467 @@
1
+ # Drive Analytics
2
+
3
+ Drive Analytics provides automated monitoring and insights into document drive operations within Powerhouse applications. This system tracks user interactions, document modifications, and drive activity to help developers understand usage patterns and system performance.
4
+
5
+ ## Overview
6
+
7
+ The Drive Analytics system consists of two specialized processors that automatically collect metrics from document drives:
8
+
9
+ 1. **Drive Analytics Processor**: Tracks file and folder operations (creation, deletion, moves, etc.)
10
+ 2. **Document Analytics Processor**: Tracks document content changes and state modifications
11
+
12
+ These processors run in the background, converting operations into structured time-series data that can be queried and visualized in real-time.
13
+
14
+ ## Available Metrics in Connect
15
+
16
+ Connect applications have Drive Analytics enabled by default through the `ReactorAnalyticsProvider`. When enabled, the system automatically tracks:
17
+
18
+ ### Drive Operations Metrics
19
+ - **File Creation**: New documents added to drives
20
+ - **Folder Creation**: New directories created
21
+ - **File Updates**: Document content modifications
22
+ - **Node Updates**: Metadata changes
23
+ - **File Moves**: Documents relocated between folders
24
+ - **File Copies**: Document duplication
25
+ - **File Deletions**: Documents removed from drives
26
+
27
+ ### Document Operations Metrics
28
+ - **State Changes**: Document model state modifications
29
+
30
+ ## Data Sources and Structure
31
+
32
+ Drive Analytics organizes data using hierarchical source paths that allow precise querying of different analytics contexts:
33
+
34
+ ### Drive Analytics Sources
35
+ Pattern: `ph/drive/{driveId}/{branch}/{scope}`
36
+ - **driveId**: Unique identifier for the document drive
37
+ - **branch**: Branch name (e.g., "main", "dev")
38
+ - **scope**: Operation scope ("global" for shared operations, "local" for device-specific)
39
+
40
+ Example: `ph/drive/abc123/main/global`
41
+
42
+ ### Document Analytics Sources
43
+ Pattern: `ph/doc/{driveId}/{documentId}/{branch}/{scope}`
44
+ - **driveId**: Drive containing the document
45
+ - **documentId**: Specific document identifier
46
+ - **branch**: Branch name
47
+ - **scope**: Operation scope
48
+
49
+ Example: `ph/doc/abc123/doc456/main/global`
50
+
51
+ ## Available Metrics
52
+
53
+ ### DriveOperations
54
+ Tracks file system operations within drives:
55
+ - **Value**: Always 1 (counter metric)
56
+ - **Purpose**: Count drive-level operations like file creation, deletion, moves
57
+ - **Source Pattern**: `ph/drive/*`
58
+
59
+ ### DocumentOperations
60
+ Tracks document content and state changes:
61
+ - **Value**: Always 1 (counter metric)
62
+ - **Purpose**: Count document-specific operations like state changes
63
+ - **Source Pattern**: `ph/doc/*`
64
+
65
+ ## Complete Dimensions Reference
66
+
67
+ ### Drive Analytics Dimensions
68
+
69
+ #### 1. Drive Dimension
70
+ **Pattern**: `ph/drive/{driveId}/{branch}/{scope}/{revision}`
71
+ **Purpose**: Identifies the drive context with revision information
72
+ ```tsx
73
+ // Examples
74
+ "ph/drive/abc123/main/global/42"
75
+ "ph/drive/my-drive/feature-branch/local/15"
76
+ ```
77
+
78
+ #### 2. Operation Dimension
79
+ **Pattern**: `ph/drive/operation/{operationType}/{operationIndex}`
80
+ **Purpose**: Identifies specific operation types and their sequence
81
+
82
+ **Available Operation Types**:
83
+ - **ADD_FILE**: Create new file
84
+ - **ADD_FOLDER**: Create new folder
85
+ - **UPDATE_FILE**: Modify file content
86
+ - **UPDATE_NODE**: Modify node metadata
87
+ - **MOVE_NODE**: Move file/folder to different location
88
+ - **COPY_NODE**: Duplicate existing file/folder
89
+ - **DELETE_NODE**: Remove file/folder
90
+
91
+ ```tsx
92
+ // Examples
93
+ "ph/drive/operation/ADD_FILE/5"
94
+ "ph/drive/operation/DELETE_NODE/23"
95
+ "ph/drive/operation/MOVE_NODE/12"
96
+ ```
97
+
98
+ #### 3. Target Dimension
99
+ **Pattern**: `ph/drive/target/{targetType}/{targetId}`
100
+ **Purpose**: Identifies what was targeted by the operation
101
+
102
+ **Target Types**:
103
+ - **DRIVE**: Operation affects the drive itself
104
+ - **NODE**: Operation affects a specific file/folder
105
+
106
+ ```tsx
107
+ // Examples
108
+ "ph/drive/target/DRIVE/abc123"
109
+ "ph/drive/target/NODE/file456"
110
+ "ph/drive/target/NODE/folder789"
111
+ ```
112
+
113
+ #### 4. Action Type Dimension
114
+ **Pattern**: `ph/drive/actionType/{actionType}/{targetId}`
115
+ **Purpose**: Categorizes operations by their effect
116
+
117
+ **Action Types**:
118
+ - **CREATED**: New items added (ADD_FILE, ADD_FOLDER)
119
+ - **DUPLICATED**: Items copied (COPY_NODE)
120
+ - **UPDATED**: Existing items modified (UPDATE_FILE, UPDATE_NODE)
121
+ - **MOVED**: Items relocated (MOVE_NODE)
122
+ - **REMOVED**: Items deleted (DELETE_NODE)
123
+
124
+ ```tsx
125
+ // Examples
126
+ "ph/drive/actionType/CREATED/file123"
127
+ "ph/drive/actionType/MOVED/folder456"
128
+ "ph/drive/actionType/REMOVED/doc789"
129
+ ```
130
+
131
+ ### Document Analytics Dimensions
132
+
133
+ #### 1. Drive Dimension
134
+ **Pattern**: `ph/doc/drive/{driveId}/{branch}/{scope}/{revision}`
135
+ **Purpose**: Drive context for document operations
136
+ ```tsx
137
+ // Examples
138
+ "ph/doc/drive/abc123/main/global/42"
139
+ ```
140
+
141
+ #### 2. Operation Dimension
142
+ **Pattern**: `ph/doc/operation/{operationType}/{operationIndex}`
143
+ **Purpose**: Document-specific operation identification
144
+ ```tsx
145
+ // Examples (document model operations vary by document type)
146
+ "ph/doc/operation/SET_STATE/15"
147
+ "ph/doc/operation/ADD_ITEM/8"
148
+ "ph/doc/operation/UPDATE_PROPERTY/22"
149
+ ```
150
+
151
+ #### 3. Target Dimension
152
+ **Pattern**: `ph/doc/target/{driveId}/{targetType}/{documentId}`
153
+ **Purpose**: Document target identification
154
+
155
+ **Target Types**:
156
+ - **DRIVE**: Document is the drive document itself (driveId === documentId)
157
+ - **NODE**: Document is a regular document within the drive
158
+
159
+ ```tsx
160
+ // Examples
161
+ "ph/doc/target/abc123/DRIVE/abc123" // Drive document
162
+ "ph/doc/target/abc123/NODE/doc456" // Regular document
163
+ ```
164
+
165
+ ## Query Parameters
166
+
167
+ ### Time Range
168
+ - **start**: DateTime object for query start time
169
+ - **end**: DateTime object for query end time
170
+ - **granularity**: Time bucketing (Total, Hourly, Daily, Weekly, Monthly)
171
+
172
+ ### Filtering with Select
173
+
174
+ Use the `select` parameter to filter by specific dimension values:
175
+
176
+ ```tsx
177
+ select: {
178
+ // Filter by specific drives
179
+ drive: [
180
+ AnalyticsPath.fromString("ph/drive/abc123"),
181
+ AnalyticsPath.fromString("ph/drive/xyz789")
182
+ ],
183
+
184
+ // Filter by operation types
185
+ operation: [
186
+ AnalyticsPath.fromString("ph/drive/operation/ADD_FILE"),
187
+ AnalyticsPath.fromString("ph/drive/operation/UPDATE_FILE")
188
+ ],
189
+
190
+ // Filter by action types
191
+ actionType: [
192
+ AnalyticsPath.fromString("ph/drive/actionType/CREATED"),
193
+ AnalyticsPath.fromString("ph/drive/actionType/UPDATED")
194
+ ],
195
+
196
+ // Filter by targets
197
+ target: [
198
+ AnalyticsPath.fromString("ph/drive/target/NODE")
199
+ ]
200
+ }
201
+ ```
202
+
203
+ ### Level of Detail (LOD)
204
+
205
+ Control how deeply dimensions are grouped:
206
+
207
+ ```tsx
208
+ lod: {
209
+ drive: 1, // Group by drive only (ignore branch/scope/revision)
210
+ operation: 1, // Group by operation type only (ignore index)
211
+ actionType: 1, // Group by action type only (ignore target ID)
212
+ target: 1 // Group by target type only (ignore target ID)
213
+ }
214
+ ```
215
+
216
+ ## Querying Analytics Data
217
+
218
+ ### Using the useAnalyticsQuery Hook
219
+
220
+ The primary way to access drive analytics is through the `useAnalyticsQuery` hook:
221
+
222
+ ```tsx
223
+ import { useAnalyticsQuery, AnalyticsGranularity, AnalyticsPath, DateTime } from '@powerhousedao/reactor-browser/analytics';
224
+
225
+ function DriveUsageChart({ driveId }: { driveId: string }) {
226
+ const { data, isLoading } = useAnalyticsQuery({
227
+ start: DateTime.now().minus({ days: 7 }),
228
+ end: DateTime.now(),
229
+ granularity: AnalyticsGranularity.Daily,
230
+ metrics: ["DriveOperations"],
231
+ select: {
232
+ drive: [AnalyticsPath.fromString(`ph/drive/${driveId}`)],
233
+ actionType: [
234
+ AnalyticsPath.fromString("ph/drive/actionType/CREATED"),
235
+ AnalyticsPath.fromString("ph/drive/actionType/UPDATED"),
236
+ AnalyticsPath.fromString("ph/drive/actionType/REMOVED")
237
+ ]
238
+ },
239
+ lod: {
240
+ drive: 1,
241
+ actionType: 1
242
+ }
243
+ });
244
+
245
+ if (isLoading) return <div>Loading analytics...</div>;
246
+
247
+ return (
248
+ <div>
249
+ {/* Render your chart using the analytics data */}
250
+ {data?.rows.map(row => (
251
+ <div key={row.metric}>
252
+ {row.metric}: {row.value}
253
+ </div>
254
+ ))}
255
+ </div>
256
+ );
257
+ }
258
+ ```
259
+
260
+ ### Using the useDriveAnalytics Hook
261
+
262
+ For common drive analytics queries, use the specialized `useDriveAnalytics` hook:
263
+
264
+ ```tsx
265
+ import { useDriveAnalytics } from '@powerhousedao/common/drive-analytics';
266
+ import { AnalyticsGranularity } from '@powerhousedao/reactor-browser/analytics';
267
+
268
+ function DriveInsights({ driveIds }: { driveIds: string[] }) {
269
+ const analytics = useDriveAnalytics({
270
+ filters: {
271
+ driveId: driveIds,
272
+ operation: ["ADD_FILE", "UPDATE_FILE", "DELETE_NODE"],
273
+ actionType: ["CREATED", "UPDATED", "REMOVED"]
274
+ },
275
+ from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(), // 7 days ago
276
+ to: new Date().toISOString(),
277
+ granularity: AnalyticsGranularity.Daily,
278
+ levelOfDetail: { drive: 1, operation: 1 }
279
+ });
280
+
281
+ if (analytics.isLoading) return <div>Loading...</div>;
282
+
283
+ return (
284
+ <div>
285
+ <h3>Drive Activity Summary</h3>
286
+ {analytics.data?.rows.map((row, index) => (
287
+ <div key={index}>
288
+ <strong>{row.dimensions.find(d => d.name === 'actionType')?.path}</strong>: {row.value}
289
+ </div>
290
+ ))}
291
+ </div>
292
+ );
293
+ }
294
+ ```
295
+
296
+ ### Using the useDocumentAnalytics Hook
297
+
298
+ For document-specific analytics queries, use the `useDocumentAnalytics` hook:
299
+
300
+ ```tsx
301
+ import { useDocumentAnalytics } from '@powerhousedao/common/drive-analytics';
302
+ import { AnalyticsGranularity } from '@powerhousedao/reactor-browser/analytics';
303
+
304
+ function DocumentInsights({ driveId, documentIds }: { driveId: string, documentIds: string[] }) {
305
+ const analytics = useDocumentAnalytics({
306
+ filters: {
307
+ driveId: [driveId],
308
+ documentId: documentIds,
309
+ target: ["NODE"], // Focus on document nodes vs drive documents
310
+ branch: ["main"],
311
+ scope: ["global"]
312
+ },
313
+ from: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), // 24 hours ago
314
+ to: new Date().toISOString(),
315
+ granularity: AnalyticsGranularity.Hourly,
316
+ levelOfDetail: {
317
+ drive: 1,
318
+ operation: 1,
319
+ target: 1
320
+ }
321
+ });
322
+
323
+ if (analytics.isLoading) return <div>Loading...</div>;
324
+
325
+ return (
326
+ <div>
327
+ <h3>Document Activity Summary</h3>
328
+ {analytics.data?.rows.map((row, index) => (
329
+ <div key={index}>
330
+ Document Operations: {row.value}
331
+ </div>
332
+ ))}
333
+ </div>
334
+ );
335
+ }
336
+ ```
337
+
338
+ ## Advanced Query Examples
339
+
340
+ ### Filter by Multiple Criteria
341
+
342
+ ```tsx
343
+ // Get file creations and updates for specific drives in the last 24 hours
344
+ const { data } = useAnalyticsQuery({
345
+ start: DateTime.now().minus({ hours: 24 }),
346
+ end: DateTime.now(),
347
+ granularity: AnalyticsGranularity.Hourly,
348
+ metrics: ["DriveOperations"],
349
+ select: {
350
+ drive: [
351
+ AnalyticsPath.fromString("ph/drive/project-a"),
352
+ AnalyticsPath.fromString("ph/drive/project-b")
353
+ ],
354
+ operation: [
355
+ AnalyticsPath.fromString("ph/drive/operation/ADD_FILE"),
356
+ AnalyticsPath.fromString("ph/drive/operation/UPDATE_FILE")
357
+ ],
358
+ target: [
359
+ AnalyticsPath.fromString("ph/drive/target/NODE")
360
+ ]
361
+ },
362
+ lod: {
363
+ drive: 1,
364
+ operation: 1
365
+ }
366
+ });
367
+ ```
368
+
369
+ ### Compare Document vs Drive Operations
370
+
371
+ ```tsx
372
+ // Using the specialized hooks for easier comparison
373
+ const driveOps = useDriveAnalytics({
374
+ filters: { driveId: [driveId] },
375
+ from: DateTime.now().minus({ days: 1 }).toISO(),
376
+ to: DateTime.now().toISO(),
377
+ granularity: AnalyticsGranularity.Total
378
+ });
379
+
380
+ const docOps = useDocumentAnalytics({
381
+ filters: { driveId: [driveId] },
382
+ from: DateTime.now().minus({ days: 1 }).toISO(),
383
+ to: DateTime.now().toISO(),
384
+ granularity: AnalyticsGranularity.Total
385
+ });
386
+
387
+ // Or using useAnalyticsQuery directly
388
+ const driveOpsQuery = useAnalyticsQuery({
389
+ start: DateTime.now().minus({ days: 1 }),
390
+ end: DateTime.now(),
391
+ granularity: AnalyticsGranularity.Total,
392
+ metrics: ["DriveOperations"],
393
+ select: {
394
+ drive: [AnalyticsPath.fromString(`ph/drive/${driveId}`)]
395
+ }
396
+ });
397
+
398
+ const docOpsQuery = useAnalyticsQuery({
399
+ start: DateTime.now().minus({ days: 1 }),
400
+ end: DateTime.now(),
401
+ granularity: AnalyticsGranularity.Total,
402
+ metrics: ["DocumentOperations"],
403
+ select: {
404
+ drive: [AnalyticsPath.fromString(`ph/doc/drive/${driveId}`)]
405
+ }
406
+ });
407
+ ```
408
+
409
+ ### Real-time Activity Monitoring
410
+
411
+ ```tsx
412
+ // Monitor specific drive for real-time updates
413
+ const { data } = useAnalyticsQuery(
414
+ {
415
+ start: DateTime.now().minus({ minutes: 10 }),
416
+ end: DateTime.now(),
417
+ granularity: AnalyticsGranularity.Total,
418
+ metrics: ["DriveOperations"],
419
+ select: {
420
+ drive: [AnalyticsPath.fromString(`ph/drive/${driveId}`)]
421
+ }
422
+ },
423
+ {
424
+ sources: [AnalyticsPath.fromString(`ph/drive/${driveId}`)],
425
+ refetchInterval: 5000 // Poll every 5 seconds
426
+ }
427
+ );
428
+ ```
429
+
430
+ ## Real-time Updates
431
+
432
+ Analytics queries can automatically update when new data is available by specifying sources:
433
+
434
+ ```tsx
435
+ const { data } = useAnalyticsQuery(
436
+ {
437
+ start: DateTime.now().minus({ hours: 1 }),
438
+ end: DateTime.now(),
439
+ granularity: AnalyticsGranularity.Total,
440
+ metrics: ["DriveOperations"]
441
+ },
442
+ {
443
+ sources: [AnalyticsPath.fromString(`ph/drive/${driveId}`)]
444
+ }
445
+ );
446
+
447
+ // This query will automatically refetch when new operations occur in the specified drive
448
+ ```
449
+
450
+
451
+ ## Configuration in Connect
452
+
453
+ Drive Analytics is automatically enabled in Connect applications through feature flags:
454
+
455
+ ```tsx
456
+ // In apps/connect/src/context/reactor-analytics.tsx
457
+ export function ReactorAnalyticsProvider({ children }: PropsWithChildren) {
458
+ return (
459
+ <AnalyticsProvider options={{ databaseName: "connect:analytics" }}>
460
+ {connectConfig.analytics.driveAnalyticsEnabled && (
461
+ <DriveAnalyticsProcessor />
462
+ )}
463
+ {children}
464
+ </AnalyticsProvider>
465
+ );
466
+ }
467
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/academy",
3
- "version": "3.2.0-staging.0",
3
+ "version": "3.2.0-staging.2",
4
4
  "homepage": "https://powerhouse.academy",
5
5
  "repository": {
6
6
  "type": "git",