insta 0.0.57 → 0.0.58
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/README.md +1 -1
- package/dist/telemetry.js +22 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -233,7 +233,7 @@ build never reaches a production installer.
|
|
|
233
233
|
| `INSTA_PROJECT_ID` · `INSTA_ORG_ID` · `INSTA_BRANCH` | Target a project, org or branch without linking |
|
|
234
234
|
| `INSTA_PASSWORD` | Password for non-interactive login |
|
|
235
235
|
| `INSTA_NO_AUTOUPDATE` | Disable self-update |
|
|
236
|
-
| `INSTA_NO_TELEMETRY` · `DO_NOT_TRACK` | Disable usage analytics. Each command sends one event (command, flags, outcome, version, OS) to the same PostHog project as the console. Only ids, enums and numbers among the arguments are kept — names, branches, keys, paths, secret values, free text and error messages never leave the machine; custom API hosts report nothing |
|
|
236
|
+
| `INSTA_NO_TELEMETRY` · `DO_NOT_TRACK` | Disable usage analytics. Each command sends one event (command, flags, outcome, version, OS) to the same PostHog project as the console. Only ids, enums and numbers among the arguments are kept — names, branches, keys, paths, secret values, free text and error messages never leave the machine; custom API hosts report nothing. Before you sign in, events carry a random id stored in `~/.insta/telemetry.json`; the first command after you sign in sends one extra event merging that id into your account, and the first command after the session ends (logout, `env use`) retires it |
|
|
237
237
|
|
|
238
238
|
## Agent skills
|
|
239
239
|
|
package/dist/telemetry.js
CHANGED
|
@@ -18,6 +18,7 @@ const PROJECT_KEYS = {
|
|
|
18
18
|
};
|
|
19
19
|
// The send is awaited before the process exits, so it gets one bounded attempt and no retry.
|
|
20
20
|
const SEND_TIMEOUT_MS = 1500;
|
|
21
|
+
const ID_FILE = join(os.homedir(), '.insta', 'telemetry.json');
|
|
21
22
|
const REDACTED = '[REDACTED]';
|
|
22
23
|
const oneOf = (values) => (v) => values.includes(v);
|
|
23
24
|
const ID = (v) => /^(?:[0-9a-f]{8}-[0-9a-f-]{27}|[a-z]+_[\w-]{1,64}|(?=.*\d)[\w-]{1,64})$/i.test(v);
|
|
@@ -144,6 +145,7 @@ export function buildCommandEvent(command, args, options, outcome, ctx) {
|
|
|
144
145
|
auth_kind: token ? (token.startsWith('insta_') ? 'api_key' : 'session') : null,
|
|
145
146
|
project_id: ctx.project?.projectId ?? null,
|
|
146
147
|
org_id: ctx.project?.orgId ?? null,
|
|
148
|
+
...(ctx.project ? { $groups: { project: ctx.project.projectId, ...(ID(ctx.project.orgId) ? { org: ctx.project.orgId } : {}) } } : {}),
|
|
147
149
|
tty: ctx.tty,
|
|
148
150
|
ci: !!ctx.env.CI,
|
|
149
151
|
agent: detectAgent(ctx.env),
|
|
@@ -154,20 +156,22 @@ export function buildCommandEvent(command, args, options, outcome, ctx) {
|
|
|
154
156
|
},
|
|
155
157
|
};
|
|
156
158
|
}
|
|
157
|
-
export async function
|
|
159
|
+
export async function readState(file = ID_FILE) {
|
|
158
160
|
try {
|
|
159
161
|
const parsed = JSON.parse(await readFile(file, 'utf8'));
|
|
160
162
|
if (typeof parsed.anonymousId === 'string' && parsed.anonymousId)
|
|
161
|
-
return parsed
|
|
163
|
+
return parsed;
|
|
162
164
|
}
|
|
163
165
|
catch { }
|
|
164
|
-
|
|
166
|
+
return writeState({ anonymousId: randomUUID() }, file);
|
|
167
|
+
}
|
|
168
|
+
async function writeState(state, file = ID_FILE) {
|
|
165
169
|
try {
|
|
166
170
|
await mkdir(dirname(file), { recursive: true });
|
|
167
|
-
await writeFile(file, JSON.stringify(
|
|
171
|
+
await writeFile(file, JSON.stringify(state, null, 2));
|
|
168
172
|
}
|
|
169
173
|
catch { }
|
|
170
|
-
return
|
|
174
|
+
return state;
|
|
171
175
|
}
|
|
172
176
|
export async function sendBatch(key, batch, fetchImpl = fetch) {
|
|
173
177
|
try {
|
|
@@ -201,16 +205,27 @@ export async function trackCommand(cmd, args, outcome, cliVersion, deps = {}) {
|
|
|
201
205
|
if (!key)
|
|
202
206
|
return;
|
|
203
207
|
const project = await (deps.loadProject ?? readProject)();
|
|
208
|
+
const userId = config.user?.id;
|
|
209
|
+
let state = await readState(deps.idFile);
|
|
210
|
+
// Session gone or switched: the id belongs to the account that left, so later commands get a fresh one.
|
|
211
|
+
if (state.identifiedAs && state.identifiedAs !== userId)
|
|
212
|
+
state = await writeState({ anonymousId: randomUUID() }, deps.idFile);
|
|
204
213
|
const event = buildCommandEvent(command, args.flat(), cmd.opts(), outcome, {
|
|
205
214
|
cliVersion,
|
|
206
215
|
channel: deps.channel ?? detectChannel(),
|
|
207
216
|
config,
|
|
208
217
|
project,
|
|
209
|
-
anonymousId:
|
|
218
|
+
anonymousId: state.anonymousId,
|
|
210
219
|
env,
|
|
211
220
|
tty: deps.tty ?? !!process.stdout.isTTY,
|
|
212
221
|
});
|
|
213
|
-
|
|
222
|
+
const batch = [event];
|
|
223
|
+
const merge = userId !== undefined && state.identifiedAs !== userId;
|
|
224
|
+
if (merge)
|
|
225
|
+
batch.push({ event: '$identify', distinct_id: userId, timestamp: event.timestamp, properties: { $anon_distinct_id: state.anonymousId } });
|
|
226
|
+
const sent = await sendBatch(key, batch, deps.fetchImpl);
|
|
227
|
+
if (merge && sent)
|
|
228
|
+
await writeState({ ...state, identifiedAs: userId }, deps.idFile);
|
|
214
229
|
}
|
|
215
230
|
catch { }
|
|
216
231
|
}
|