@feltdb/core 0.5.3 → 0.5.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/cell.d.ts.map +1 -1
- package/dist/cell.js +63 -59
- package/dist/create/managed-account.js +11 -4
- package/dist/create/package-versions.js +1 -1
- package/dist/create/server-source/crates/feltdb/src/lib.rs +31 -0
- package/dist/create/server-source/crates/feltdb/src/state_contract.rs +39 -3
- package/dist/create/server-source/crates/feltdb-server/src/auth.rs +12 -6
- package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +7 -4
- package/dist/create/server-source/crates/feltdb-server/src/main.rs +142 -30
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +4 -0
- package/dist/error-codes.d.ts +1 -1
- package/dist/error-codes.d.ts.map +1 -1
- package/dist/error-codes.js +5 -3
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/studio-app/assets/index-D8oLrr60.js +28 -0
- package/dist/studio-app/index.html +1 -1
- package/dist/telemetry.d.ts +82 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +255 -0
- package/package.json +1 -1
- package/dist/studio-app/assets/index-Z92yFC4z.js +0 -28
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#17211b"/><title>FeltDB Studio</title> <script type="module" crossorigin src="/assets/index-
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#17211b"/><title>FeltDB Studio</title> <script type="module" crossorigin src="/assets/index-D8oLrr60.js"></script>
|
|
2
2
|
<link rel="stylesheet" crossorigin href="/assets/index-C1GWyazR.css">
|
|
3
3
|
</head><body><div id="root"></div></body></html>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeltDB Adoption Telemetry
|
|
3
|
+
*
|
|
4
|
+
* Privacy-preserving, anonymous telemetry for adoption analytics.
|
|
5
|
+
* No source code, project names, filesystem paths, or PII collected.
|
|
6
|
+
* Fail-open: telemetry failures never affect FeltDB operation.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Telemetry event types
|
|
10
|
+
*/
|
|
11
|
+
export type TelemetryEventType = 'initialize' | 'write' | 'query' | 'sync' | 'agent_operation' | 'production_activity';
|
|
12
|
+
/**
|
|
13
|
+
* Telemetry event payload
|
|
14
|
+
*/
|
|
15
|
+
export interface TelemetryEvent {
|
|
16
|
+
event: TelemetryEventType;
|
|
17
|
+
installation_id: string;
|
|
18
|
+
core_version: string;
|
|
19
|
+
runtime: 'node' | 'browser';
|
|
20
|
+
os: string;
|
|
21
|
+
timestamp: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Telemetry client
|
|
25
|
+
* Handles event collection and transport
|
|
26
|
+
*/
|
|
27
|
+
export declare class TelemetryClient {
|
|
28
|
+
private identity;
|
|
29
|
+
private enabled;
|
|
30
|
+
private readonly batchSize;
|
|
31
|
+
private eventQueue;
|
|
32
|
+
private flushTimer;
|
|
33
|
+
private coreVersion;
|
|
34
|
+
private runtime;
|
|
35
|
+
constructor(coreVersion?: string);
|
|
36
|
+
/**
|
|
37
|
+
* Emit a telemetry event
|
|
38
|
+
*/
|
|
39
|
+
emit(eventType: TelemetryEventType): void;
|
|
40
|
+
/**
|
|
41
|
+
* Flush pending events to telemetry server
|
|
42
|
+
*/
|
|
43
|
+
private flush;
|
|
44
|
+
/**
|
|
45
|
+
* Schedule a flush for pending events
|
|
46
|
+
*/
|
|
47
|
+
private scheduleFlush;
|
|
48
|
+
/**
|
|
49
|
+
* Send events to telemetry server
|
|
50
|
+
* Uses fire-and-forget with short timeout
|
|
51
|
+
*/
|
|
52
|
+
private sendEvents;
|
|
53
|
+
/**
|
|
54
|
+
* Get normalized OS name
|
|
55
|
+
*/
|
|
56
|
+
private getOS;
|
|
57
|
+
/**
|
|
58
|
+
* Enable telemetry
|
|
59
|
+
*/
|
|
60
|
+
enable(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Disable telemetry
|
|
63
|
+
*/
|
|
64
|
+
disable(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Check if telemetry is enabled
|
|
67
|
+
*/
|
|
68
|
+
isEnabled(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Force flush all pending events
|
|
71
|
+
*/
|
|
72
|
+
forceFlush(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get or create global telemetry client
|
|
76
|
+
*/
|
|
77
|
+
export declare function getTelemetryClient(coreVersion?: string): TelemetryClient;
|
|
78
|
+
/**
|
|
79
|
+
* Emit a telemetry event using global client
|
|
80
|
+
*/
|
|
81
|
+
export declare function emitTelemetry(eventType: TelemetryEventType): void;
|
|
82
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,OAAO,GACP,OAAO,GACP,MAAM,GACN,iBAAiB,GACjB,qBAAqB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAiED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAM;IAChC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAA8B;gBAEjC,WAAW,GAAE,MAAgB;IAczC;;OAEG;IACH,IAAI,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI;IA6BzC;;OAEG;YACW,KAAK;IAqBnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;;OAGG;YACW,UAAU;IA6BxB;;OAEG;IACH,OAAO,CAAC,KAAK;IAkBb;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,OAAO,IAAI,IAAI;IASf;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAKlC;AAOD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CAKxE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeltDB Adoption Telemetry
|
|
3
|
+
*
|
|
4
|
+
* Privacy-preserving, anonymous telemetry for adoption analytics.
|
|
5
|
+
* No source code, project names, filesystem paths, or PII collected.
|
|
6
|
+
* Fail-open: telemetry failures never affect FeltDB operation.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from 'crypto';
|
|
9
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'fs';
|
|
10
|
+
import { homedir, platform } from 'os';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
import { release } from 'os';
|
|
13
|
+
/**
|
|
14
|
+
* Installation identity manager
|
|
15
|
+
* Generates and persists a unique, anonymous installation ID
|
|
16
|
+
*/
|
|
17
|
+
class InstallationIdentity {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.id = null;
|
|
20
|
+
const feltdbDir = join(homedir(), '.feltdb');
|
|
21
|
+
this.identityFile = join(feltdbDir, 'install-id');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get or create installation ID
|
|
25
|
+
*/
|
|
26
|
+
getId() {
|
|
27
|
+
if (this.id) {
|
|
28
|
+
return this.id;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
// Try to read existing ID
|
|
32
|
+
if (existsSync(this.identityFile)) {
|
|
33
|
+
const content = readFileSync(this.identityFile, 'utf-8').trim();
|
|
34
|
+
if (content && this.isValidUUID(content)) {
|
|
35
|
+
this.id = content;
|
|
36
|
+
return this.id;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Create new ID
|
|
40
|
+
this.id = randomUUID();
|
|
41
|
+
this.persistId();
|
|
42
|
+
return this.id;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
// Fallback: generate in-memory ID if persistence fails
|
|
46
|
+
// This allows telemetry to work even if file system access fails
|
|
47
|
+
if (!this.id) {
|
|
48
|
+
this.id = randomUUID();
|
|
49
|
+
}
|
|
50
|
+
return this.id;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
persistId() {
|
|
54
|
+
try {
|
|
55
|
+
const feltdbDir = join(homedir(), '.feltdb');
|
|
56
|
+
if (!existsSync(feltdbDir)) {
|
|
57
|
+
mkdirSync(feltdbDir, { recursive: true, mode: 0o700 });
|
|
58
|
+
}
|
|
59
|
+
writeFileSync(this.identityFile, this.id, { mode: 0o600 });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// Silent fail - telemetry persistence failure should not affect operation
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
isValidUUID(str) {
|
|
66
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
67
|
+
return uuidRegex.test(str);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Telemetry client
|
|
72
|
+
* Handles event collection and transport
|
|
73
|
+
*/
|
|
74
|
+
export class TelemetryClient {
|
|
75
|
+
constructor(coreVersion = '0.5.3') {
|
|
76
|
+
this.batchSize = 10;
|
|
77
|
+
this.eventQueue = [];
|
|
78
|
+
this.flushTimer = null;
|
|
79
|
+
this.runtime = 'node';
|
|
80
|
+
this.coreVersion = coreVersion;
|
|
81
|
+
this.identity = new InstallationIdentity();
|
|
82
|
+
// Check if telemetry is disabled
|
|
83
|
+
this.enabled = process.env.FELTDB_TELEMETRY !== '0' &&
|
|
84
|
+
process.env.FELTDB_TELEMETRY !== 'false';
|
|
85
|
+
// Detect browser environment
|
|
86
|
+
if (typeof window !== 'undefined' && typeof process === 'undefined') {
|
|
87
|
+
this.runtime = 'browser';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Emit a telemetry event
|
|
92
|
+
*/
|
|
93
|
+
emit(eventType) {
|
|
94
|
+
if (!this.enabled) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const event = {
|
|
99
|
+
event: eventType,
|
|
100
|
+
installation_id: this.identity.getId(),
|
|
101
|
+
core_version: this.coreVersion,
|
|
102
|
+
runtime: this.runtime,
|
|
103
|
+
os: this.getOS(),
|
|
104
|
+
timestamp: new Date().toISOString(),
|
|
105
|
+
};
|
|
106
|
+
this.eventQueue.push(event);
|
|
107
|
+
// Flush if batch size reached
|
|
108
|
+
if (this.eventQueue.length >= this.batchSize) {
|
|
109
|
+
this.flush();
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Schedule flush if not already scheduled
|
|
113
|
+
this.scheduleFlush();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
// Silent fail - telemetry errors should never affect application
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Flush pending events to telemetry server
|
|
122
|
+
*/
|
|
123
|
+
async flush() {
|
|
124
|
+
if (this.eventQueue.length === 0 || !this.enabled) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Clear timer
|
|
128
|
+
if (this.flushTimer) {
|
|
129
|
+
clearTimeout(this.flushTimer);
|
|
130
|
+
this.flushTimer = null;
|
|
131
|
+
}
|
|
132
|
+
const events = this.eventQueue.splice(0, this.batchSize);
|
|
133
|
+
try {
|
|
134
|
+
await this.sendEvents(events);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
// Silent fail - put events back if send fails (fire-and-forget)
|
|
138
|
+
// Don't retry to avoid blocking
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Schedule a flush for pending events
|
|
143
|
+
*/
|
|
144
|
+
scheduleFlush() {
|
|
145
|
+
if (this.flushTimer || !this.enabled) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Flush after 5 seconds or when batch fills
|
|
149
|
+
this.flushTimer = setTimeout(() => {
|
|
150
|
+
this.flush().catch(() => {
|
|
151
|
+
// Silent fail
|
|
152
|
+
});
|
|
153
|
+
}, 5000);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Send events to telemetry server
|
|
157
|
+
* Uses fire-and-forget with short timeout
|
|
158
|
+
*/
|
|
159
|
+
async sendEvents(events) {
|
|
160
|
+
const endpoint = process.env.FELTDB_TELEMETRY_ENDPOINT ||
|
|
161
|
+
'https://kendel.feltdb.com/api/v1/telemetry/events';
|
|
162
|
+
// Timeout after 3 seconds - don't block application
|
|
163
|
+
const controller = new AbortController();
|
|
164
|
+
const timeoutId = setTimeout(() => controller.abort(), 3000);
|
|
165
|
+
try {
|
|
166
|
+
const response = await fetch(endpoint, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
headers: {
|
|
169
|
+
'Content-Type': 'application/json',
|
|
170
|
+
},
|
|
171
|
+
body: JSON.stringify({ events }),
|
|
172
|
+
signal: controller.signal,
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
// Server rejected events - silent fail
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
// Network error, timeout, or abort - silent fail
|
|
180
|
+
// Telemetry should never block or crash the application
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
clearTimeout(timeoutId);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get normalized OS name
|
|
188
|
+
*/
|
|
189
|
+
getOS() {
|
|
190
|
+
const platformName = platform();
|
|
191
|
+
const osVersion = release();
|
|
192
|
+
switch (platformName) {
|
|
193
|
+
case 'darwin':
|
|
194
|
+
return 'macos';
|
|
195
|
+
case 'linux':
|
|
196
|
+
return 'linux';
|
|
197
|
+
case 'win32':
|
|
198
|
+
return 'windows';
|
|
199
|
+
case 'freebsd':
|
|
200
|
+
return 'freebsd';
|
|
201
|
+
default:
|
|
202
|
+
return platformName;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Enable telemetry
|
|
207
|
+
*/
|
|
208
|
+
enable() {
|
|
209
|
+
this.enabled = true;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Disable telemetry
|
|
213
|
+
*/
|
|
214
|
+
disable() {
|
|
215
|
+
this.enabled = false;
|
|
216
|
+
this.eventQueue = [];
|
|
217
|
+
if (this.flushTimer) {
|
|
218
|
+
clearTimeout(this.flushTimer);
|
|
219
|
+
this.flushTimer = null;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Check if telemetry is enabled
|
|
224
|
+
*/
|
|
225
|
+
isEnabled() {
|
|
226
|
+
return this.enabled;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Force flush all pending events
|
|
230
|
+
*/
|
|
231
|
+
async forceFlush() {
|
|
232
|
+
while (this.eventQueue.length > 0) {
|
|
233
|
+
await this.flush();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Global telemetry client instance
|
|
239
|
+
*/
|
|
240
|
+
let globalTelemetryClient = null;
|
|
241
|
+
/**
|
|
242
|
+
* Get or create global telemetry client
|
|
243
|
+
*/
|
|
244
|
+
export function getTelemetryClient(coreVersion) {
|
|
245
|
+
if (!globalTelemetryClient) {
|
|
246
|
+
globalTelemetryClient = new TelemetryClient(coreVersion);
|
|
247
|
+
}
|
|
248
|
+
return globalTelemetryClient;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Emit a telemetry event using global client
|
|
252
|
+
*/
|
|
253
|
+
export function emitTelemetry(eventType) {
|
|
254
|
+
getTelemetryClient().emit(eventType);
|
|
255
|
+
}
|
package/package.json
CHANGED