@affectively/dash 5.0.1 → 5.1.1

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.
Files changed (45) hide show
  1. package/README.md +21 -0
  2. package/dist/src/api/firebase/auth/index.d.ts +137 -0
  3. package/dist/src/api/firebase/auth/index.js +352 -0
  4. package/dist/src/api/firebase/auth/providers.d.ts +254 -0
  5. package/dist/src/api/firebase/auth/providers.js +518 -0
  6. package/dist/src/api/firebase/database/index.d.ts +104 -0
  7. package/dist/src/api/firebase/database/index.js +351 -0
  8. package/dist/src/api/firebase/errors.d.ts +15 -0
  9. package/dist/src/api/firebase/errors.js +215 -0
  10. package/dist/src/api/firebase/firestore/data-types.d.ts +116 -0
  11. package/dist/src/api/firebase/firestore/data-types.js +280 -0
  12. package/dist/src/api/firebase/firestore/index.d.ts +7 -0
  13. package/dist/src/api/firebase/firestore/index.js +13 -0
  14. package/dist/src/api/firebase/firestore/listeners.d.ts +20 -0
  15. package/dist/src/api/firebase/firestore/listeners.js +50 -0
  16. package/dist/src/api/firebase/firestore/operations.d.ts +123 -0
  17. package/dist/src/api/firebase/firestore/operations.js +490 -0
  18. package/dist/src/api/firebase/firestore/query.d.ts +118 -0
  19. package/dist/src/api/firebase/firestore/query.js +418 -0
  20. package/dist/src/api/firebase/index.d.ts +11 -0
  21. package/dist/src/api/firebase/index.js +16 -0
  22. package/dist/src/api/firebase/storage/index.d.ts +100 -0
  23. package/dist/src/api/firebase/storage/index.js +286 -0
  24. package/dist/src/api/firebase/types.d.ts +340 -0
  25. package/dist/src/api/firebase/types.js +4 -0
  26. package/dist/src/auth/manager.d.ts +5 -1
  27. package/dist/src/auth/manager.js +19 -6
  28. package/dist/src/index.d.ts +5 -0
  29. package/dist/src/index.js +10 -0
  30. package/dist/src/sync/aeon/config.d.ts +21 -0
  31. package/dist/src/sync/aeon/config.js +14 -0
  32. package/dist/src/sync/aeon/delta-adapter.d.ts +62 -0
  33. package/dist/src/sync/aeon/delta-adapter.js +98 -0
  34. package/dist/src/sync/aeon/index.d.ts +18 -0
  35. package/dist/src/sync/aeon/index.js +19 -0
  36. package/dist/src/sync/aeon/offline-adapter.d.ts +110 -0
  37. package/dist/src/sync/aeon/offline-adapter.js +227 -0
  38. package/dist/src/sync/aeon/presence-adapter.d.ts +114 -0
  39. package/dist/src/sync/aeon/presence-adapter.js +157 -0
  40. package/dist/src/sync/aeon/schema-adapter.d.ts +95 -0
  41. package/dist/src/sync/aeon/schema-adapter.js +163 -0
  42. package/dist/src/sync/hybrid-provider.d.ts +67 -2
  43. package/dist/src/sync/hybrid-provider.js +128 -9
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +7 -1
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Presence Adapter for Dash
3
+ *
4
+ * Bridges Yjs awareness protocol with Aeon's AgentPresenceManager.
5
+ * Provides rich presence features: cursor tracking, active sections, roles.
6
+ */
7
+ import { AgentPresenceManager, } from '@affectively/aeon';
8
+ /**
9
+ * Adapter that syncs Yjs awareness with Aeon presence
10
+ */
11
+ export class DashPresenceAdapter {
12
+ aeonPresence;
13
+ yjsAwareness;
14
+ localAgentId;
15
+ roomId;
16
+ constructor(roomId, awareness) {
17
+ this.roomId = roomId;
18
+ this.yjsAwareness = awareness;
19
+ this.localAgentId = `agent-${awareness.clientID}`;
20
+ this.aeonPresence = new AgentPresenceManager(roomId);
21
+ // Register local agent
22
+ this.aeonPresence.agentJoined(this.localAgentId, `User ${awareness.clientID}`, 'user');
23
+ // Bidirectional sync setup
24
+ this.setupYjsToAeonSync();
25
+ this.setupAeonToYjsSync();
26
+ }
27
+ /**
28
+ * Sync Yjs awareness updates to Aeon presence
29
+ */
30
+ setupYjsToAeonSync() {
31
+ this.yjsAwareness.on('update', ({ added, updated, removed }) => {
32
+ const states = this.yjsAwareness.getStates();
33
+ // Handle added/updated
34
+ for (const clientId of [...added, ...updated]) {
35
+ const state = states.get(clientId);
36
+ if (state) {
37
+ const agentId = `agent-${clientId}`;
38
+ if (added.includes(clientId)) {
39
+ this.aeonPresence.agentJoined(agentId, state.user?.name || `User ${clientId}`, state.user?.role || 'user', state.metadata);
40
+ }
41
+ // Sync cursor and section if present
42
+ if (state.cursor) {
43
+ this.aeonPresence.updateCursor(agentId, state.cursor.x ?? 0, state.cursor.y ?? 0, state.cursor.path ?? '');
44
+ }
45
+ if (state.activeSection) {
46
+ this.aeonPresence.updateActiveSection(agentId, state.activeSection);
47
+ }
48
+ // Heartbeat to keep presence alive
49
+ this.aeonPresence.heartbeat(agentId);
50
+ }
51
+ }
52
+ // Handle removed
53
+ for (const clientId of removed) {
54
+ this.aeonPresence.agentLeft(`agent-${clientId}`);
55
+ }
56
+ });
57
+ }
58
+ /**
59
+ * Sync Aeon presence updates back to Yjs awareness
60
+ */
61
+ setupAeonToYjsSync() {
62
+ // When local presence updates via Aeon API, reflect to Yjs
63
+ this.aeonPresence.on('cursor_updated', ({ agentId, cursorPosition }) => {
64
+ if (agentId === this.localAgentId) {
65
+ this.yjsAwareness.setLocalStateField('cursor', cursorPosition);
66
+ }
67
+ });
68
+ this.aeonPresence.on('section_updated', ({ agentId, activeSection }) => {
69
+ if (agentId === this.localAgentId) {
70
+ this.yjsAwareness.setLocalStateField('activeSection', activeSection);
71
+ }
72
+ });
73
+ }
74
+ // ============================================
75
+ // Rich Presence API
76
+ // ============================================
77
+ /**
78
+ * Update local cursor position
79
+ */
80
+ updateCursor(x, y, path) {
81
+ this.aeonPresence.updateCursor(this.localAgentId, x, y, path);
82
+ }
83
+ /**
84
+ * Update local active section
85
+ */
86
+ updateActiveSection(section) {
87
+ this.aeonPresence.updateActiveSection(this.localAgentId, section);
88
+ }
89
+ /**
90
+ * Update local user info
91
+ */
92
+ updateUserInfo(name, role = 'user') {
93
+ this.aeonPresence.updatePresence(this.localAgentId, {
94
+ agentId: this.localAgentId,
95
+ name,
96
+ role,
97
+ status: 'online',
98
+ });
99
+ // Also sync to Yjs awareness
100
+ this.yjsAwareness.setLocalStateField('user', { name, role });
101
+ }
102
+ /**
103
+ * Get all online agents
104
+ */
105
+ getOnlineAgents() {
106
+ return this.aeonPresence.getOnlineAgents();
107
+ }
108
+ /**
109
+ * Get all agents (including offline)
110
+ */
111
+ getAllAgents() {
112
+ return this.aeonPresence.getAllAgents();
113
+ }
114
+ /**
115
+ * Get presence for specific agent
116
+ */
117
+ getPresence(agentId) {
118
+ return this.aeonPresence.getPresence(agentId);
119
+ }
120
+ /**
121
+ * Get agents in a specific section
122
+ */
123
+ getAgentsInSection(section) {
124
+ return this.aeonPresence.getInSection(section);
125
+ }
126
+ /**
127
+ * Get presence statistics
128
+ */
129
+ getStats() {
130
+ return this.aeonPresence.getPresenceStats();
131
+ }
132
+ /**
133
+ * Get local agent ID
134
+ */
135
+ getLocalAgentId() {
136
+ return this.localAgentId;
137
+ }
138
+ /**
139
+ * Subscribe to presence events
140
+ */
141
+ on(event, handler) {
142
+ this.aeonPresence.on(event, handler);
143
+ }
144
+ /**
145
+ * Unsubscribe from presence events
146
+ */
147
+ off(event, handler) {
148
+ this.aeonPresence.off(event, handler);
149
+ }
150
+ /**
151
+ * Cleanup
152
+ */
153
+ destroy() {
154
+ this.aeonPresence.agentLeft(this.localAgentId);
155
+ this.aeonPresence.destroy();
156
+ }
157
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Schema Adapter for Dash
3
+ *
4
+ * Bridges Aeon's SchemaVersionManager with Dash's LensEngine.
5
+ * Provides migration tracking, version compatibility checks, and audit trails.
6
+ */
7
+ import { type SchemaVersion, type Migration, type MigrationResult } from '@affectively/aeon';
8
+ import { LensEngine, type LensOp } from '../../schema/lens.js';
9
+ /**
10
+ * Adapter that bridges Aeon versioning with Dash's Lens system
11
+ */
12
+ export declare class DashSchemaAdapter {
13
+ private versionManager;
14
+ private migrationEngine;
15
+ private migrationTracker;
16
+ private lensEngine;
17
+ constructor(lensEngine: LensEngine);
18
+ /**
19
+ * Register a schema version with associated Lens operations
20
+ */
21
+ registerVersion(version: string, description: string, lensOps?: LensOp[], breaking?: boolean): void;
22
+ /**
23
+ * Register a migration for a version upgrade
24
+ */
25
+ registerMigration(id: string, fromVersion: string, toVersion: string, migrate: (data: unknown) => unknown, rollback?: (data: unknown) => unknown): void;
26
+ /**
27
+ * Execute a migration on data
28
+ */
29
+ executeMigration(migrationId: string, data: unknown): Promise<MigrationResult>;
30
+ /**
31
+ * Rollback a migration
32
+ */
33
+ rollbackMigration(migrationId: string, data: unknown): Promise<MigrationResult>;
34
+ /**
35
+ * Migrate data using Lens transformations
36
+ */
37
+ migrateWithLens(data: Record<string, unknown>, fromVersion: number, toVersion: number): Record<string, unknown>;
38
+ /**
39
+ * Get current version
40
+ */
41
+ getCurrentVersion(): SchemaVersion;
42
+ /**
43
+ * Get a specific version by string
44
+ */
45
+ getVersion(version: string): SchemaVersion | undefined;
46
+ /**
47
+ * Get migration by ID
48
+ */
49
+ getMigration(id: string): Migration | undefined;
50
+ /**
51
+ * Check if migration is needed
52
+ */
53
+ needsMigration(fromVersion: string, toVersion: string): boolean;
54
+ /**
55
+ * Get migration path between versions
56
+ */
57
+ getMigrationPath(fromVersion: string, toVersion: string): SchemaVersion[];
58
+ /**
59
+ * Get pending migrations
60
+ */
61
+ getPendingMigrations(): Migration[];
62
+ /**
63
+ * Get migration statistics
64
+ */
65
+ getStatistics(): {
66
+ engine: {
67
+ totalExecuted: number;
68
+ successful: number;
69
+ failed: number;
70
+ successRate: number;
71
+ totalDurationMs: number;
72
+ averageDurationMs: number;
73
+ totalAffected: number;
74
+ };
75
+ tracker: {
76
+ total: number;
77
+ applied: number;
78
+ failed: number;
79
+ pending: number;
80
+ rolledBack: number;
81
+ successRate: number;
82
+ totalDurationMs: number;
83
+ averageDurationMs: number;
84
+ totalItemsAffected: number;
85
+ };
86
+ };
87
+ /**
88
+ * Format version for display
89
+ */
90
+ formatVersion(version: SchemaVersion): string;
91
+ }
92
+ /**
93
+ * Create a schema adapter from an existing LensEngine
94
+ */
95
+ export declare function createSchemaAdapter(lensEngine: LensEngine): DashSchemaAdapter;
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Schema Adapter for Dash
3
+ *
4
+ * Bridges Aeon's SchemaVersionManager with Dash's LensEngine.
5
+ * Provides migration tracking, version compatibility checks, and audit trails.
6
+ */
7
+ import { SchemaVersionManager, MigrationEngine, MigrationTracker, } from '@affectively/aeon';
8
+ /**
9
+ * Adapter that bridges Aeon versioning with Dash's Lens system
10
+ */
11
+ export class DashSchemaAdapter {
12
+ versionManager;
13
+ migrationEngine;
14
+ migrationTracker;
15
+ lensEngine;
16
+ constructor(lensEngine) {
17
+ this.versionManager = new SchemaVersionManager();
18
+ this.migrationEngine = new MigrationEngine();
19
+ this.migrationTracker = new MigrationTracker();
20
+ this.lensEngine = lensEngine;
21
+ }
22
+ /**
23
+ * Register a schema version with associated Lens operations
24
+ */
25
+ registerVersion(version, description, lensOps, breaking = false) {
26
+ const [major, minor, patch] = version.split('.').map(Number);
27
+ // Register with Aeon
28
+ this.versionManager.registerVersion({
29
+ major,
30
+ minor,
31
+ patch,
32
+ timestamp: new Date().toISOString(),
33
+ description,
34
+ breaking,
35
+ });
36
+ // Register Lens if provided
37
+ if (lensOps && major > 1) {
38
+ this.lensEngine.registerLens(major - 1, major, lensOps);
39
+ }
40
+ }
41
+ /**
42
+ * Register a migration for a version upgrade
43
+ */
44
+ registerMigration(id, fromVersion, toVersion, migrate, rollback) {
45
+ const migration = {
46
+ id,
47
+ name: `${fromVersion} -> ${toVersion}`,
48
+ version: toVersion,
49
+ description: `Migrate from ${fromVersion} to ${toVersion}`,
50
+ timestamp: new Date().toISOString(),
51
+ up: migrate,
52
+ down: rollback,
53
+ };
54
+ this.migrationEngine.registerMigration(migration);
55
+ }
56
+ /**
57
+ * Execute a migration on data
58
+ */
59
+ async executeMigration(migrationId, data) {
60
+ const result = await this.migrationEngine.executeMigration(migrationId, data);
61
+ // Track the migration
62
+ const record = {
63
+ id: `record-${Date.now()}`,
64
+ migrationId,
65
+ timestamp: new Date().toISOString(),
66
+ version: result.migrationId,
67
+ direction: 'up',
68
+ status: result.success ? 'applied' : 'failed',
69
+ duration: result.duration,
70
+ itemsAffected: result.itemsAffected,
71
+ errorMessage: result.errors.length > 0 ? result.errors.join(', ') : undefined,
72
+ appliedBy: 'dash-schema-adapter',
73
+ };
74
+ this.migrationTracker.recordMigration(record);
75
+ return result;
76
+ }
77
+ /**
78
+ * Rollback a migration
79
+ */
80
+ async rollbackMigration(migrationId, data) {
81
+ const result = await this.migrationEngine.rollbackMigration(migrationId, data);
82
+ // Track the rollback
83
+ const record = {
84
+ id: `record-${Date.now()}`,
85
+ migrationId,
86
+ timestamp: new Date().toISOString(),
87
+ version: result.migrationId,
88
+ direction: 'down',
89
+ status: result.success ? 'rolled-back' : 'failed',
90
+ duration: result.duration,
91
+ itemsAffected: result.itemsAffected,
92
+ errorMessage: result.errors.length > 0 ? result.errors.join(', ') : undefined,
93
+ appliedBy: 'dash-schema-adapter',
94
+ };
95
+ this.migrationTracker.recordMigration(record);
96
+ return result;
97
+ }
98
+ /**
99
+ * Migrate data using Lens transformations
100
+ */
101
+ migrateWithLens(data, fromVersion, toVersion) {
102
+ return this.lensEngine.migrate(data, fromVersion, toVersion);
103
+ }
104
+ /**
105
+ * Get current version
106
+ */
107
+ getCurrentVersion() {
108
+ return this.versionManager.getCurrentVersion();
109
+ }
110
+ /**
111
+ * Get a specific version by string
112
+ */
113
+ getVersion(version) {
114
+ return this.versionManager.getVersion(version);
115
+ }
116
+ /**
117
+ * Get migration by ID
118
+ */
119
+ getMigration(id) {
120
+ return this.migrationEngine.getMigration(id);
121
+ }
122
+ /**
123
+ * Check if migration is needed
124
+ */
125
+ needsMigration(fromVersion, toVersion) {
126
+ return this.versionManager.canMigrate(fromVersion, toVersion);
127
+ }
128
+ /**
129
+ * Get migration path between versions
130
+ */
131
+ getMigrationPath(fromVersion, toVersion) {
132
+ const from = this.versionManager.parseVersion(fromVersion);
133
+ const to = this.versionManager.parseVersion(toVersion);
134
+ return this.versionManager.getMigrationPath(from, to);
135
+ }
136
+ /**
137
+ * Get pending migrations
138
+ */
139
+ getPendingMigrations() {
140
+ return this.migrationEngine.getPendingMigrations();
141
+ }
142
+ /**
143
+ * Get migration statistics
144
+ */
145
+ getStatistics() {
146
+ return {
147
+ engine: this.migrationEngine.getStatistics(),
148
+ tracker: this.migrationTracker.getStatistics(),
149
+ };
150
+ }
151
+ /**
152
+ * Format version for display
153
+ */
154
+ formatVersion(version) {
155
+ return `${version.major}.${version.minor}.${version.patch}`;
156
+ }
157
+ }
158
+ /**
159
+ * Create a schema adapter from an existing LensEngine
160
+ */
161
+ export function createSchemaAdapter(lensEngine) {
162
+ return new DashSchemaAdapter(lensEngine);
163
+ }
@@ -1,6 +1,10 @@
1
1
  import * as Y from 'yjs';
2
2
  import { Observable } from 'lib0/observable';
3
3
  import * as awarenessProtocol from 'y-protocols/awareness';
4
+ import { type AeonConfig } from './aeon/config.js';
5
+ import { DashDeltaAdapter } from './aeon/delta-adapter.js';
6
+ import { DashPresenceAdapter } from './aeon/presence-adapter.js';
7
+ import { DashOfflineAdapter } from './aeon/offline-adapter.js';
4
8
  export declare class HybridProvider extends Observable<string> {
5
9
  private doc;
6
10
  private ws;
@@ -11,8 +15,13 @@ export declare class HybridProvider extends Observable<string> {
11
15
  awareness: awarenessProtocol.Awareness;
12
16
  private writer;
13
17
  private highFrequencyMode;
14
- constructor(url: string, roomName: string, doc: Y.Doc, { awareness }?: {
15
- awareness?: awarenessProtocol.Awareness | undefined;
18
+ private aeonConfig;
19
+ private deltaAdapter;
20
+ private presenceAdapter;
21
+ private offlineAdapter;
22
+ constructor(url: string, roomName: string, doc: Y.Doc, { awareness, aeonConfig, }?: {
23
+ awareness?: awarenessProtocol.Awareness;
24
+ aeonConfig?: AeonConfig;
16
25
  });
17
26
  private connect;
18
27
  private connectWebSocket;
@@ -25,6 +34,29 @@ export declare class HybridProvider extends Observable<string> {
25
34
  private onDocUpdate;
26
35
  private onAwarenessUpdate;
27
36
  destroy(): void;
37
+ /**
38
+ * Get the delta adapter for compression stats
39
+ */
40
+ getDeltaAdapter(): DashDeltaAdapter | null;
41
+ /**
42
+ * Get the presence adapter for rich presence features
43
+ */
44
+ getPresenceAdapter(): DashPresenceAdapter | null;
45
+ /**
46
+ * Get the offline adapter for queue management
47
+ */
48
+ getOfflineAdapter(): DashOfflineAdapter | null;
49
+ /**
50
+ * Get Aeon configuration
51
+ */
52
+ getAeonConfig(): AeonConfig;
53
+ /**
54
+ * Process offline queue when back online
55
+ */
56
+ processOfflineQueue(): Promise<{
57
+ synced: number;
58
+ failed: number;
59
+ }>;
28
60
  /**
29
61
  * Get comprehensive connection status
30
62
  */
@@ -57,6 +89,10 @@ export declare class HybridProvider extends Observable<string> {
57
89
  * Get full provider status for debugging
58
90
  */
59
91
  getProviderStatus(): ProviderStatus;
92
+ /**
93
+ * Get Aeon-specific status
94
+ */
95
+ getAeonStatus(): AeonStatus;
60
96
  }
61
97
  export interface ConnectionStatus {
62
98
  connected: boolean;
@@ -104,4 +140,33 @@ export interface ProviderStatus {
104
140
  states: AwarenessState[];
105
141
  };
106
142
  document: DocumentState;
143
+ aeon: AeonStatus;
144
+ }
145
+ export interface AeonStatus {
146
+ enabled: {
147
+ deltaSync: boolean;
148
+ richPresence: boolean;
149
+ offlineQueue: boolean;
150
+ };
151
+ delta: {
152
+ totalOperations: number;
153
+ totalFull: number;
154
+ totalDelta: number;
155
+ totalOriginalSize: number;
156
+ totalDeltaSize: number;
157
+ averageReductionPercent: number;
158
+ } | null;
159
+ offline: {
160
+ pending: number;
161
+ syncing: number;
162
+ failed: number;
163
+ synced: number;
164
+ totalOperations: number;
165
+ } | null;
166
+ presence: {
167
+ total: number;
168
+ online: number;
169
+ away: number;
170
+ offline: number;
171
+ } | null;
107
172
  }