@tanstack/cli 0.63.1 → 0.64.0
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/cli.js +33 -1
- package/dist/telemetry.js +60 -12
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { Command, InvalidArgumentError } from 'commander';
|
|
3
|
+
import { Command, InvalidArgumentError, Option } from 'commander';
|
|
4
4
|
import { cancel, confirm, intro, isCancel, log } from '@clack/prompts';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import semver from 'semver';
|
|
@@ -37,6 +37,19 @@ function sanitizeIdList(values) {
|
|
|
37
37
|
.map((value) => sanitizeId(value))
|
|
38
38
|
.filter((value) => Boolean(value))));
|
|
39
39
|
}
|
|
40
|
+
const AGENT_FLAG = '--agent';
|
|
41
|
+
function addHiddenAgentFlag(cmd) {
|
|
42
|
+
if (cmd.options.some((option) => option.long === AGENT_FLAG)) {
|
|
43
|
+
return cmd;
|
|
44
|
+
}
|
|
45
|
+
cmd.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp());
|
|
46
|
+
return cmd;
|
|
47
|
+
}
|
|
48
|
+
function getInvocationTelemetryProperties() {
|
|
49
|
+
return {
|
|
50
|
+
invoked_by_agent: process.argv.includes(AGENT_FLAG),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
40
53
|
function getStarterTelemetryProperties(value) {
|
|
41
54
|
if (!value) {
|
|
42
55
|
return {};
|
|
@@ -275,6 +288,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
275
288
|
const startedAt = Date.now();
|
|
276
289
|
currentTelemetry = telemetry;
|
|
277
290
|
telemetry.captureCommandStarted(command, {
|
|
291
|
+
...getInvocationTelemetryProperties(),
|
|
278
292
|
...opts.properties,
|
|
279
293
|
cli_version: VERSION,
|
|
280
294
|
});
|
|
@@ -295,6 +309,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
295
309
|
.name(name)
|
|
296
310
|
.description(`${appName} CLI`)
|
|
297
311
|
.version(VERSION, '-v, --version', 'output the current version');
|
|
312
|
+
addHiddenAgentFlag(program);
|
|
298
313
|
// Helper to create the create command action handler
|
|
299
314
|
async function handleCreate(projectName, options) {
|
|
300
315
|
try {
|
|
@@ -507,6 +522,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
507
522
|
}
|
|
508
523
|
// Helper to configure create command options
|
|
509
524
|
function configureCreateCommand(cmd) {
|
|
525
|
+
addHiddenAgentFlag(cmd);
|
|
510
526
|
cmd.argument('[project-name]', 'name of the project');
|
|
511
527
|
if (!defaultFramework) {
|
|
512
528
|
cmd.option('--framework <type>', `project framework (${availableFrameworks.join(', ')})`, (value) => {
|
|
@@ -624,6 +640,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
624
640
|
program
|
|
625
641
|
.command('libraries')
|
|
626
642
|
.description('List TanStack libraries')
|
|
643
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
627
644
|
.option('--group <group>', `filter by group (${LIBRARY_GROUPS.join(', ')})`)
|
|
628
645
|
.option('--json', 'output JSON for automation', false)
|
|
629
646
|
.action(async (options) => {
|
|
@@ -681,6 +698,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
681
698
|
program
|
|
682
699
|
.command('doc')
|
|
683
700
|
.description('Fetch a TanStack documentation page')
|
|
701
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
684
702
|
.argument('<library>', 'library ID (eg. query, router, table)')
|
|
685
703
|
.argument('<path>', 'documentation path (eg. framework/react/overview)')
|
|
686
704
|
.option('--docs-version <version>', 'docs version (default: latest)', 'latest')
|
|
@@ -757,6 +775,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
757
775
|
program
|
|
758
776
|
.command('search-docs')
|
|
759
777
|
.description('Search TanStack documentation')
|
|
778
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
760
779
|
.argument('<query>', 'search query')
|
|
761
780
|
.option('--library <id>', 'filter to specific library')
|
|
762
781
|
.option('--framework <name>', 'filter to specific framework')
|
|
@@ -804,6 +823,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
804
823
|
program
|
|
805
824
|
.command('ecosystem')
|
|
806
825
|
.description('List TanStack ecosystem partners')
|
|
826
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
807
827
|
.option('--category <category>', 'filter by category')
|
|
808
828
|
.option('--library <id>', 'filter by TanStack library')
|
|
809
829
|
.option('--json', 'output JSON for automation', false)
|
|
@@ -873,6 +893,7 @@ export function cli({ name, appName, forcedAddOns = [], forcedDeployment, defaul
|
|
|
873
893
|
program
|
|
874
894
|
.command('pin-versions')
|
|
875
895
|
.description('Pin versions of the TanStack libraries')
|
|
896
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
876
897
|
.action(async () => {
|
|
877
898
|
try {
|
|
878
899
|
await runWithTelemetry('pin-versions', {}, async (telemetry) => {
|
|
@@ -943,6 +964,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
943
964
|
telemetryCommand
|
|
944
965
|
.command('status')
|
|
945
966
|
.description('Show anonymous telemetry status')
|
|
967
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
946
968
|
.option('--json', 'output JSON for automation', false)
|
|
947
969
|
.action(async (options) => {
|
|
948
970
|
const status = await getTelemetryStatus({ createIfMissing: true });
|
|
@@ -966,6 +988,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
966
988
|
telemetryCommand
|
|
967
989
|
.command('enable')
|
|
968
990
|
.description('Enable anonymous telemetry')
|
|
991
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
969
992
|
.action(async () => {
|
|
970
993
|
await setTelemetryEnabled(true);
|
|
971
994
|
console.log('Anonymous telemetry enabled');
|
|
@@ -973,6 +996,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
973
996
|
telemetryCommand
|
|
974
997
|
.command('disable')
|
|
975
998
|
.description('Disable anonymous telemetry')
|
|
999
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
976
1000
|
.action(async () => {
|
|
977
1001
|
await setTelemetryEnabled(false);
|
|
978
1002
|
console.log('Anonymous telemetry disabled');
|
|
@@ -980,6 +1004,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
980
1004
|
// === ADD SUBCOMMAND ===
|
|
981
1005
|
program
|
|
982
1006
|
.command('add')
|
|
1007
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
983
1008
|
.argument('[add-on...]', 'Name of the add-ons (or add-ons separated by spaces or commas)')
|
|
984
1009
|
.option('--forced', 'Force the add-on to be added', false)
|
|
985
1010
|
.action(async (addOns, options) => {
|
|
@@ -1032,6 +1057,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1032
1057
|
addOnCommand
|
|
1033
1058
|
.command('init')
|
|
1034
1059
|
.description('Initialize an add-on from the current project')
|
|
1060
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1035
1061
|
.action(async () => {
|
|
1036
1062
|
try {
|
|
1037
1063
|
await runWithTelemetry('add-on:init', {}, async () => {
|
|
@@ -1046,6 +1072,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1046
1072
|
addOnCommand
|
|
1047
1073
|
.command('compile')
|
|
1048
1074
|
.description('Update add-on from the current project')
|
|
1075
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1049
1076
|
.action(async () => {
|
|
1050
1077
|
try {
|
|
1051
1078
|
await runWithTelemetry('add-on:compile', {}, async () => {
|
|
@@ -1060,6 +1087,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1060
1087
|
addOnCommand
|
|
1061
1088
|
.command('dev')
|
|
1062
1089
|
.description('Watch project files and continuously refresh .add-on and add-on.json')
|
|
1090
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1063
1091
|
.action(async () => {
|
|
1064
1092
|
try {
|
|
1065
1093
|
await runWithTelemetry('add-on:dev', {}, async () => {
|
|
@@ -1076,6 +1104,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1076
1104
|
templateCommand
|
|
1077
1105
|
.command('init')
|
|
1078
1106
|
.description('Initialize a project template from the current project')
|
|
1107
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1079
1108
|
.action(async () => {
|
|
1080
1109
|
try {
|
|
1081
1110
|
await runWithTelemetry('template:init', {}, async () => {
|
|
@@ -1090,6 +1119,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1090
1119
|
templateCommand
|
|
1091
1120
|
.command('compile')
|
|
1092
1121
|
.description('Compile the template JSON file for the current project')
|
|
1122
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1093
1123
|
.action(async () => {
|
|
1094
1124
|
try {
|
|
1095
1125
|
await runWithTelemetry('template:compile', {}, async () => {
|
|
@@ -1106,6 +1136,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1106
1136
|
starterCommand
|
|
1107
1137
|
.command('init')
|
|
1108
1138
|
.description('Deprecated alias: initialize a project template')
|
|
1139
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1109
1140
|
.action(async () => {
|
|
1110
1141
|
try {
|
|
1111
1142
|
await runWithTelemetry('starter:init', {}, async () => {
|
|
@@ -1120,6 +1151,7 @@ Remove your node_modules directory and package lock file and re-install.`);
|
|
|
1120
1151
|
starterCommand
|
|
1121
1152
|
.command('compile')
|
|
1122
1153
|
.description('Deprecated alias: compile the template JSON file')
|
|
1154
|
+
.addOption(new Option(AGENT_FLAG, 'internal: invocation originated from an agent').hideHelp())
|
|
1123
1155
|
.action(async () => {
|
|
1124
1156
|
try {
|
|
1125
1157
|
await runWithTelemetry('starter:compile', {}, async () => {
|
package/dist/telemetry.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { version as nodeVersion } from 'node:process';
|
|
2
2
|
import { getTelemetryStatus, markTelemetryNoticeSeen, TELEMETRY_NOTICE_VERSION, } from './telemetry-config.js';
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const POSTHOG_PROJECT_TOKEN = 'phc_xJ2VBahJBzy3BShLhuGpw7EyoSuQtgwXXvhE9BYtHuKQ';
|
|
3
|
+
const TELEMETRY_TRANSPORT_ENDPOINT = 'https://www.google-analytics.com/g/collect';
|
|
4
|
+
const TELEMETRY_PROPERTY_ID = 'G-JMT1Z50SPS';
|
|
6
5
|
const TELEMETRY_NOTICE = 'TanStack CLI sends anonymous usage telemetry by default. It never sends project names, paths, raw search text, template URLs, add-on config values, or raw error messages. Disable it with `tanstack telemetry disable` or `TANSTACK_CLI_TELEMETRY_DISABLED=1`.';
|
|
7
6
|
const TELEMETRY_TIMEOUT_MS = 1200;
|
|
7
|
+
const TELEMETRY_VALUE_MAX_LENGTH = 500;
|
|
8
|
+
const TELEMETRY_NUMERIC_PREFIX = 'epn.';
|
|
9
|
+
const TELEMETRY_STRING_PREFIX = 'ep.';
|
|
8
10
|
let telemetryStatusPromise;
|
|
9
11
|
function getNodeMajorVersion() {
|
|
10
12
|
return Number.parseInt(nodeVersion.replace(/^v/, '').split('.')[0] || '0', 10);
|
|
@@ -26,6 +28,57 @@ function cleanProperties(value) {
|
|
|
26
28
|
}
|
|
27
29
|
return value;
|
|
28
30
|
}
|
|
31
|
+
function truncateValue(value) {
|
|
32
|
+
return value.length > TELEMETRY_VALUE_MAX_LENGTH
|
|
33
|
+
? `${value.slice(0, TELEMETRY_VALUE_MAX_LENGTH - 1)}…`
|
|
34
|
+
: value;
|
|
35
|
+
}
|
|
36
|
+
function normalizeParamKey(key) {
|
|
37
|
+
const normalized = key.replace(/[^a-zA-Z0-9_]/g, '_').replace(/^_+/, '');
|
|
38
|
+
const prefixed = /^[a-zA-Z]/.test(normalized)
|
|
39
|
+
? normalized
|
|
40
|
+
: `p_${normalized || 'value'}`;
|
|
41
|
+
return prefixed.slice(0, 40);
|
|
42
|
+
}
|
|
43
|
+
function normalizeParamValue(value) {
|
|
44
|
+
if (value === undefined || value === null) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (typeof value === 'boolean') {
|
|
48
|
+
return value ? 1 : 0;
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === 'number') {
|
|
51
|
+
return Number.isFinite(value) ? value : undefined;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === 'string') {
|
|
54
|
+
return truncateValue(value);
|
|
55
|
+
}
|
|
56
|
+
const cleaned = cleanProperties(value);
|
|
57
|
+
if (cleaned === undefined) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return truncateValue(JSON.stringify(cleaned));
|
|
61
|
+
}
|
|
62
|
+
function createTelemetryRequestBody(event, distinctId, properties) {
|
|
63
|
+
const params = new URLSearchParams({
|
|
64
|
+
cid: distinctId,
|
|
65
|
+
en: event,
|
|
66
|
+
tid: TELEMETRY_PROPERTY_ID,
|
|
67
|
+
v: '2',
|
|
68
|
+
});
|
|
69
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
70
|
+
const normalizedValue = normalizeParamValue(value);
|
|
71
|
+
if (normalizedValue === undefined) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const normalizedKey = normalizeParamKey(key);
|
|
75
|
+
const paramName = typeof normalizedValue === 'number'
|
|
76
|
+
? `${TELEMETRY_NUMERIC_PREFIX}${normalizedKey}`
|
|
77
|
+
: `${TELEMETRY_STRING_PREFIX}${normalizedKey}`;
|
|
78
|
+
params.append(paramName, String(normalizedValue));
|
|
79
|
+
}
|
|
80
|
+
return params.toString();
|
|
81
|
+
}
|
|
29
82
|
function getErrorCode(error) {
|
|
30
83
|
if (!error || typeof error !== 'object') {
|
|
31
84
|
return 'unknown_error';
|
|
@@ -63,17 +116,12 @@ async function postEvent(event, distinctId, properties) {
|
|
|
63
116
|
controller.abort();
|
|
64
117
|
}, TELEMETRY_TIMEOUT_MS);
|
|
65
118
|
try {
|
|
66
|
-
await fetch(
|
|
119
|
+
await fetch(TELEMETRY_TRANSPORT_ENDPOINT, {
|
|
67
120
|
method: 'POST',
|
|
68
121
|
headers: {
|
|
69
|
-
'Content-Type': 'application/
|
|
122
|
+
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
|
70
123
|
},
|
|
71
|
-
body:
|
|
72
|
-
api_key: POSTHOG_PROJECT_TOKEN,
|
|
73
|
-
distinct_id: distinctId,
|
|
74
|
-
event,
|
|
75
|
-
properties,
|
|
76
|
-
}),
|
|
124
|
+
body: createTelemetryRequestBody(event, distinctId, properties),
|
|
77
125
|
signal: controller.signal,
|
|
78
126
|
});
|
|
79
127
|
}
|
|
@@ -171,7 +219,7 @@ export class TelemetryClient {
|
|
|
171
219
|
}
|
|
172
220
|
baseProperties() {
|
|
173
221
|
return {
|
|
174
|
-
|
|
222
|
+
client_lib: 'tanstack-cli',
|
|
175
223
|
disabled_by: this.disabledBy,
|
|
176
224
|
node_major: getNodeMajorVersion(),
|
|
177
225
|
os_arch: process.arch,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"description": "TanStack CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"tempy": "^3.1.0",
|
|
42
42
|
"validate-npm-package-name": "^7.0.0",
|
|
43
43
|
"zod": "^3.24.2",
|
|
44
|
-
"@tanstack/create": "0.63.
|
|
44
|
+
"@tanstack/create": "0.63.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@playwright/test": "^1.58.2",
|