@boboddy/sdk 0.2.14-alpha → 0.2.15-alpha

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.
@@ -6,9 +6,38 @@ export interface AuthProfile {
6
6
  }
7
7
  export interface AuthFile {
8
8
  profiles: Record<string, AuthProfile>;
9
+ /**
10
+ * A random id generated on first read and persisted here, alongside (not
11
+ * inside) any per-baseUrl profile — it identifies this machine/install
12
+ * before any account exists, so pre-auth CLI telemetry (init started,
13
+ * requirements verified) has a stable distinct id to key events to. See
14
+ * `getOrCreateAnonymousId`.
15
+ */
16
+ anonymousId?: string;
17
+ /**
18
+ * User-level telemetry opt-out, set via `boboddy telemetry disable` (or the
19
+ * `BOBODDY_TELEMETRY_DISABLED` env var, checked separately at the call
20
+ * site). Global — unlike `profiles`, it is not scoped to a `baseUrl`.
21
+ */
22
+ telemetryDisabled?: boolean;
9
23
  }
24
+ /** Test-only. Redirects every read/write in this module under `dir`. */
25
+ export declare function setHomeDirForTests(dir: string | undefined): void;
10
26
  export declare const getAuthFilePath: () => string;
11
27
  export declare const loadAuthFile: () => AuthFile;
12
28
  export declare const loadAuthProfile: (baseUrl: string) => AuthProfile | null;
13
29
  export declare const saveAuthProfile: (baseUrl: string, profile: AuthProfile) => void;
14
30
  export declare const deleteAuthProfile: (baseUrl: string) => void;
31
+ /**
32
+ * The persisted pre-auth distinct id for this machine/install, creating and
33
+ * persisting one the first time it is read. Stable across every command
34
+ * invocation until `~/.boboddy.json` is deleted (e.g. by `boboddy auth
35
+ * logout` clearing the last profile — see `deleteAuthProfile` above, which
36
+ * only removes the file once no profiles remain; a bare id-only file is left
37
+ * alone by that path since it always re-reads via `loadAuthFile`).
38
+ */
39
+ export declare const getOrCreateAnonymousId: () => string;
40
+ /** The persisted telemetry opt-out flag. Defaults to `false` (enabled). */
41
+ export declare const isTelemetryDisabled: () => boolean;
42
+ /** Persist the telemetry opt-out flag, leaving profiles/anonymousId intact. */
43
+ export declare const setTelemetryDisabled: (disabled: boolean) => void;
@@ -1,4 +1,4 @@
1
- export { deleteAuthProfile, getAuthFilePath, loadAuthFile, loadAuthProfile, saveAuthProfile, } from "./auth-file";
1
+ export { deleteAuthProfile, getAuthFilePath, getOrCreateAnonymousId, isTelemetryDisabled, loadAuthFile, loadAuthProfile, saveAuthProfile, setTelemetryDisabled, } from "./auth-file";
2
2
  export type { AuthFile, AuthProfile } from "./auth-file";
3
3
  export { resolveBoboddyBaseUrl } from "./base-url";
4
4
  export { loadProjectConfig, PROJECT_CONFIG_RELATIVE_PATH, } from "./project-config";
@@ -141,8 +141,11 @@ import {
141
141
  } from "fs";
142
142
  import { dirname, join } from "path";
143
143
  import { homedir } from "os";
144
- var LEGACY_AUTH_FILE_PATH = join(homedir(), ".boboddy");
145
- var AUTH_FILE_PATH = join(homedir(), ".boboddy.json");
144
+ import { randomUUID } from "crypto";
145
+ var homeDirOverrideForTests;
146
+ var resolveHomeDir = () => homeDirOverrideForTests ?? homedir();
147
+ var legacyAuthFilePath = () => join(resolveHomeDir(), ".boboddy");
148
+ var authFilePath = () => join(resolveHomeDir(), ".boboddy.json");
146
149
  var EMPTY_AUTH_FILE = {
147
150
  profiles: {}
148
151
  };
@@ -162,13 +165,20 @@ function isAuthProfile(value) {
162
165
  function isAuthFile(value) {
163
166
  if (typeof value !== "object" || value === null)
164
167
  return false;
165
- const profiles = value["profiles"];
168
+ const obj = value;
169
+ const profiles = obj["profiles"];
166
170
  if (typeof profiles !== "object" || profiles === null)
167
171
  return false;
168
172
  for (const profile of Object.values(profiles)) {
169
173
  if (!isAuthProfile(profile))
170
174
  return false;
171
175
  }
176
+ if (obj["anonymousId"] !== undefined && typeof obj["anonymousId"] !== "string") {
177
+ return false;
178
+ }
179
+ if (obj["telemetryDisabled"] !== undefined && typeof obj["telemetryDisabled"] !== "boolean") {
180
+ return false;
181
+ }
172
182
  return true;
173
183
  }
174
184
  var ensureFilePermissions = (filePath) => {
@@ -176,7 +186,7 @@ var ensureFilePermissions = (filePath) => {
176
186
  chmodSync(filePath, 384);
177
187
  } catch {}
178
188
  };
179
- var getAuthFilePath = () => AUTH_FILE_PATH;
189
+ var getAuthFilePath = () => authFilePath();
180
190
  var loadAuthFileFromPath = (filePath) => {
181
191
  if (!existsSync(filePath))
182
192
  return EMPTY_AUTH_FILE;
@@ -196,22 +206,27 @@ var loadAuthFileFromPath = (filePath) => {
196
206
  return parsed;
197
207
  };
198
208
  var loadAuthFile = () => {
199
- if (existsSync(AUTH_FILE_PATH)) {
200
- return loadAuthFileFromPath(AUTH_FILE_PATH);
209
+ const authFile = authFilePath();
210
+ if (existsSync(authFile)) {
211
+ return loadAuthFileFromPath(authFile);
201
212
  }
202
- return loadAuthFileFromPath(LEGACY_AUTH_FILE_PATH);
213
+ return loadAuthFileFromPath(legacyAuthFilePath());
203
214
  };
204
215
  var writeAuthFile = (data) => {
205
- const parentDirectory = dirname(AUTH_FILE_PATH);
216
+ const authFile = authFilePath();
217
+ const parentDirectory = dirname(authFile);
206
218
  if (!existsSync(parentDirectory)) {
207
219
  mkdirSync(parentDirectory, { recursive: true });
208
220
  }
209
- const temporaryPath = `${AUTH_FILE_PATH}.${String(process.pid)}.${String(Date.now())}.tmp`;
221
+ const temporaryPath = `${authFile}.${String(process.pid)}.${String(Date.now())}.tmp`;
210
222
  writeFileSync(temporaryPath, `${JSON.stringify(data, null, 2)}
211
- `, { encoding: "utf8", mode: 384 });
223
+ `, {
224
+ encoding: "utf8",
225
+ mode: 384
226
+ });
212
227
  ensureFilePermissions(temporaryPath);
213
- renameSync(temporaryPath, AUTH_FILE_PATH);
214
- ensureFilePermissions(AUTH_FILE_PATH);
228
+ renameSync(temporaryPath, authFile);
229
+ ensureFilePermissions(authFile);
215
230
  };
216
231
  var loadAuthProfile = (baseUrl) => {
217
232
  const authFile = loadAuthFile();
@@ -228,14 +243,28 @@ var deleteAuthProfile = (baseUrl) => {
228
243
  return;
229
244
  const remainingProfiles = Object.fromEntries(Object.entries(authFile.profiles).filter(([profileBaseUrl]) => profileBaseUrl !== baseUrl));
230
245
  if (Object.keys(remainingProfiles).length === 0) {
231
- rmSync(AUTH_FILE_PATH, { force: true });
232
- if (existsSync(LEGACY_AUTH_FILE_PATH) && lstatSync(LEGACY_AUTH_FILE_PATH).isFile()) {
233
- rmSync(LEGACY_AUTH_FILE_PATH, { force: true });
246
+ rmSync(authFilePath(), { force: true });
247
+ const legacyPath = legacyAuthFilePath();
248
+ if (existsSync(legacyPath) && lstatSync(legacyPath).isFile()) {
249
+ rmSync(legacyPath, { force: true });
234
250
  }
235
251
  return;
236
252
  }
237
253
  writeAuthFile({ profiles: remainingProfiles });
238
254
  };
255
+ var getOrCreateAnonymousId = () => {
256
+ const authFile = loadAuthFile();
257
+ if (authFile.anonymousId)
258
+ return authFile.anonymousId;
259
+ const anonymousId = randomUUID();
260
+ writeAuthFile({ ...authFile, anonymousId });
261
+ return anonymousId;
262
+ };
263
+ var isTelemetryDisabled = () => loadAuthFile().telemetryDisabled === true;
264
+ var setTelemetryDisabled = (disabled) => {
265
+ const authFile = loadAuthFile();
266
+ writeAuthFile({ ...authFile, telemetryDisabled: disabled });
267
+ };
239
268
  // src/defaults/base-url.ts
240
269
  var DEFAULT_BASE_URL = "https://app.boboddy.dev";
241
270
  var trimTrailingSlashes = (value) => {
@@ -309,12 +338,15 @@ async function loadPushDefaults(opts) {
309
338
  return { baseUrl, projectId, accessToken };
310
339
  }
311
340
  export {
341
+ setTelemetryDisabled,
312
342
  saveAuthProfile,
313
343
  resolveBoboddyBaseUrl,
314
344
  loadPushDefaults,
315
345
  loadProjectConfig,
316
346
  loadAuthProfile,
317
347
  loadAuthFile,
348
+ isTelemetryDisabled,
349
+ getOrCreateAnonymousId,
318
350
  getAuthFilePath,
319
351
  deleteAuthProfile,
320
352
  PROJECT_CONFIG_RELATIVE_PATH
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@boboddy/sdk",
4
- "version": "0.2.14-alpha",
4
+ "version": "0.2.15-alpha",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {