@sanity/cli 8.25.0 → 8.27.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.
Files changed (127) hide show
  1. package/README.md +3 -2
  2. package/dist/actions/build/shouldAutoUpdate.js +1 -26
  3. package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
  4. package/dist/actions/context/mcpEndpoint.js +165 -0
  5. package/dist/actions/context/mcpEndpoint.js.map +1 -0
  6. package/dist/actions/context/resolveOrganizationId.js +8 -1
  7. package/dist/actions/context/resolveOrganizationId.js.map +1 -1
  8. package/dist/actions/deploy/deployApp.js +10 -3
  9. package/dist/actions/deploy/deployApp.js.map +1 -1
  10. package/dist/actions/deploy/deployStudio.js +11 -4
  11. package/dist/actions/deploy/deployStudio.js.map +1 -1
  12. package/dist/actions/init/initAction.js +3 -3
  13. package/dist/actions/init/initAction.js.map +1 -1
  14. package/dist/actions/init/plan/verifyCoupon.js +0 -1
  15. package/dist/actions/init/plan/verifyCoupon.js.map +1 -1
  16. package/dist/actions/init/scaffoldTemplate.js +1 -1
  17. package/dist/actions/init/scaffoldTemplate.js.map +1 -1
  18. package/dist/commands/api.js +10 -0
  19. package/dist/commands/api.js.map +1 -1
  20. package/dist/commands/backups/download.js +6 -0
  21. package/dist/commands/backups/download.js.map +1 -1
  22. package/dist/commands/context/create.js +8 -22
  23. package/dist/commands/context/create.js.map +1 -1
  24. package/dist/commands/context/delete.js +8 -1
  25. package/dist/commands/context/delete.js.map +1 -1
  26. package/dist/commands/context/issues/list.js +0 -5
  27. package/dist/commands/context/issues/list.js.map +1 -1
  28. package/dist/commands/context/list.js +6 -14
  29. package/dist/commands/context/list.js.map +1 -1
  30. package/dist/commands/context/mcp/create.js +152 -0
  31. package/dist/commands/context/mcp/create.js.map +1 -0
  32. package/dist/commands/context/mcp/delete.js +82 -0
  33. package/dist/commands/context/mcp/delete.js.map +1 -0
  34. package/dist/commands/context/mcp/get.js +42 -0
  35. package/dist/commands/context/mcp/get.js.map +1 -0
  36. package/dist/commands/context/mcp/list.js +87 -0
  37. package/dist/commands/context/mcp/list.js.map +1 -0
  38. package/dist/commands/context/mcp/status.js +98 -0
  39. package/dist/commands/context/mcp/status.js.map +1 -0
  40. package/dist/commands/context/mcp/update.js +225 -0
  41. package/dist/commands/context/mcp/update.js.map +1 -0
  42. package/dist/commands/context/query.js +6 -14
  43. package/dist/commands/context/query.js.map +1 -1
  44. package/dist/commands/context/update.js +12 -1
  45. package/dist/commands/context/update.js.map +1 -1
  46. package/dist/commands/datasets/create.js +6 -0
  47. package/dist/commands/datasets/create.js.map +1 -1
  48. package/dist/commands/datasets/embeddings/enable.js +6 -0
  49. package/dist/commands/datasets/embeddings/enable.js.map +1 -1
  50. package/dist/commands/datasets/import.js +6 -0
  51. package/dist/commands/datasets/import.js.map +1 -1
  52. package/dist/commands/deploy.js +7 -0
  53. package/dist/commands/deploy.js.map +1 -1
  54. package/dist/commands/documents/validate.js +6 -0
  55. package/dist/commands/documents/validate.js.map +1 -1
  56. package/dist/commands/exec.js +4 -2
  57. package/dist/commands/exec.js.map +1 -1
  58. package/dist/commands/init.js +13 -0
  59. package/dist/commands/init.js.map +1 -1
  60. package/dist/commands/manifest/extract.js +6 -0
  61. package/dist/commands/manifest/extract.js.map +1 -1
  62. package/dist/commands/media/create-aspect.js +7 -0
  63. package/dist/commands/media/create-aspect.js.map +1 -1
  64. package/dist/commands/migrations/run.js +6 -0
  65. package/dist/commands/migrations/run.js.map +1 -1
  66. package/dist/commands/organizations/create.js +6 -0
  67. package/dist/commands/organizations/create.js.map +1 -1
  68. package/dist/commands/organizations/update.js +6 -0
  69. package/dist/commands/organizations/update.js.map +1 -1
  70. package/dist/commands/schemas/delete.js +6 -0
  71. package/dist/commands/schemas/delete.js.map +1 -1
  72. package/dist/commands/schemas/deploy.js +6 -0
  73. package/dist/commands/schemas/deploy.js.map +1 -1
  74. package/dist/commands/schemas/extract.js +28 -3
  75. package/dist/commands/schemas/extract.js.map +1 -1
  76. package/dist/commands/schemas/list.js +6 -0
  77. package/dist/commands/schemas/list.js.map +1 -1
  78. package/dist/commands/schemas/validate.js +6 -0
  79. package/dist/commands/schemas/validate.js.map +1 -1
  80. package/dist/commands/tokens/rotate.js +6 -0
  81. package/dist/commands/tokens/rotate.js.map +1 -1
  82. package/dist/commands/typegen/generate.js +25 -1
  83. package/dist/commands/typegen/generate.js.map +1 -1
  84. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +6 -0
  85. package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
  86. package/dist/generated/apiRoutes.js +22 -0
  87. package/dist/generated/apiRoutes.js.map +1 -1
  88. package/dist/hooks/prerun/setupTelemetry.js +2 -3
  89. package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
  90. package/dist/prompts/promptForText.js +12 -0
  91. package/dist/prompts/promptForText.js.map +1 -0
  92. package/dist/services/context.js +174 -1
  93. package/dist/services/context.js.map +1 -1
  94. package/dist/services/telemetry.js +4 -2
  95. package/dist/services/telemetry.js.map +1 -1
  96. package/dist/telemetry/cli.telemetry.js +1 -1
  97. package/dist/telemetry/cli.telemetry.js.map +1 -1
  98. package/dist/telemetry/init.telemetry.js +1 -1
  99. package/dist/telemetry/init.telemetry.js.map +1 -1
  100. package/dist/telemetry/typegen.telemetry.js +12 -0
  101. package/dist/telemetry/typegen.telemetry.js.map +1 -0
  102. package/dist/util/parseArguments.js +12 -40
  103. package/dist/util/parseArguments.js.map +1 -1
  104. package/dist/util/sharedFlags.js.map +1 -1
  105. package/dist/util/telemetry/cliCommandIdentity.js +222 -0
  106. package/dist/util/telemetry/cliCommandIdentity.js.map +1 -0
  107. package/dist/util/telemetry/cliTelemetryFlags.js +186 -0
  108. package/dist/util/telemetry/cliTelemetryFlags.js.map +1 -0
  109. package/dist/util/telemetry/commandTelemetry.js +56 -11
  110. package/dist/util/telemetry/commandTelemetry.js.map +1 -1
  111. package/dist/util/telemetry/createTelemetryStore.js +13 -5
  112. package/dist/util/telemetry/createTelemetryStore.js.map +1 -1
  113. package/dist/util/telemetry/createTraceId.js +3 -3
  114. package/dist/util/telemetry/createTraceId.js.map +1 -1
  115. package/dist/util/telemetry/flushTelemetryFiles.js +14 -4
  116. package/dist/util/telemetry/flushTelemetryFiles.js.map +1 -1
  117. package/dist/util/telemetry/logger.js +1 -1
  118. package/dist/util/telemetry/logger.js.map +1 -1
  119. package/dist/util/telemetry/readNDJSON.js +1 -1
  120. package/dist/util/telemetry/readNDJSON.js.map +1 -1
  121. package/dist/util/telemetry/sanitizeTelemetryEvent.js +304 -0
  122. package/dist/util/telemetry/sanitizeTelemetryEvent.js.map +1 -0
  123. package/dist/util/telemetry/trace.js +4 -7
  124. package/dist/util/telemetry/trace.js.map +1 -1
  125. package/oclif.config.js +1 -1
  126. package/oclif.manifest.json +2380 -1526
  127. package/package.json +8 -11
@@ -0,0 +1,222 @@
1
+ // Command paths only: positional user input must never become command identity.
2
+ const commandPaths = new Set([
3
+ 'api',
4
+ 'assets upload',
5
+ 'backup disable',
6
+ 'backup download',
7
+ 'backup enable',
8
+ 'backup list',
9
+ 'backups disable',
10
+ 'backups download',
11
+ 'backups enable',
12
+ 'backups list',
13
+ 'blueprints add',
14
+ 'blueprints config',
15
+ 'blueprints deploy',
16
+ 'blueprints destroy',
17
+ 'blueprints doctor',
18
+ 'blueprints info',
19
+ 'blueprints init',
20
+ 'blueprints logs',
21
+ 'blueprints mint-deploy-token',
22
+ 'blueprints plan',
23
+ 'blueprints promote',
24
+ 'blueprints stacks',
25
+ 'build',
26
+ 'check',
27
+ 'codemod',
28
+ 'context build',
29
+ 'context create',
30
+ 'context delete',
31
+ 'context entries get',
32
+ 'context entries list',
33
+ 'context entries rebuild',
34
+ 'context get',
35
+ 'context imports create',
36
+ 'context imports delete',
37
+ 'context imports download',
38
+ 'context imports get',
39
+ 'context imports list',
40
+ 'context issues apply',
41
+ 'context issues dismiss',
42
+ 'context issues get',
43
+ 'context issues list',
44
+ 'context issues reopen',
45
+ 'context issues resolve',
46
+ 'context jobs get',
47
+ 'context list',
48
+ 'context mcp create',
49
+ 'context mcp delete',
50
+ 'context mcp get',
51
+ 'context mcp list',
52
+ 'context mcp status',
53
+ 'context mcp update',
54
+ 'context query',
55
+ 'context refresh',
56
+ 'context update',
57
+ 'cors add',
58
+ 'cors delete',
59
+ 'cors list',
60
+ 'dataset alias create',
61
+ 'dataset alias delete',
62
+ 'dataset alias link',
63
+ 'dataset alias unlink',
64
+ 'dataset copy',
65
+ 'dataset create',
66
+ 'dataset delete',
67
+ 'dataset export',
68
+ 'dataset import',
69
+ 'dataset list',
70
+ 'datasets alias create',
71
+ 'datasets alias delete',
72
+ 'datasets alias link',
73
+ 'datasets alias unlink',
74
+ 'datasets copy',
75
+ 'datasets create',
76
+ 'datasets delete',
77
+ 'datasets embeddings disable',
78
+ 'datasets embeddings enable',
79
+ 'datasets embeddings status',
80
+ 'datasets export',
81
+ 'datasets import',
82
+ 'datasets list',
83
+ 'datasets visibility get',
84
+ 'datasets visibility set',
85
+ 'dataset visibility get',
86
+ 'dataset visibility set',
87
+ 'debug',
88
+ 'deploy',
89
+ 'dev',
90
+ 'docs browse',
91
+ 'docs read',
92
+ 'docs search',
93
+ 'doctor',
94
+ 'documents create',
95
+ 'documents delete',
96
+ 'documents get',
97
+ 'documents query',
98
+ 'documents validate',
99
+ 'exec',
100
+ 'functions add',
101
+ 'functions build',
102
+ 'functions deploy',
103
+ 'functions dev',
104
+ 'functions env add',
105
+ 'functions env list',
106
+ 'functions env remove',
107
+ 'functions list',
108
+ 'functions logs',
109
+ 'functions test',
110
+ 'graphql deploy',
111
+ 'graphql list',
112
+ 'graphql undeploy',
113
+ 'help',
114
+ 'hook list',
115
+ 'hooks attempt',
116
+ 'hooks create',
117
+ 'hooks delete',
118
+ 'hooks list',
119
+ 'hooks logs',
120
+ 'init',
121
+ 'init plugin',
122
+ 'install',
123
+ 'learn',
124
+ 'login',
125
+ 'logout',
126
+ 'manage',
127
+ 'manifest extract',
128
+ 'mcp configure',
129
+ 'media create-aspect',
130
+ 'media delete-aspect',
131
+ 'media deploy-aspect',
132
+ 'media export',
133
+ 'media import',
134
+ 'media prune-aspect-data',
135
+ 'media pull-aspects',
136
+ 'migration create',
137
+ 'migration list',
138
+ 'migration run',
139
+ 'migrations create',
140
+ 'migrations list',
141
+ 'migrations run',
142
+ 'new',
143
+ 'openapi get',
144
+ 'openapi list',
145
+ 'organizations create',
146
+ 'organizations delete',
147
+ 'organizations get',
148
+ 'organizations list',
149
+ 'organizations update',
150
+ 'preview',
151
+ 'projects create',
152
+ 'projects list',
153
+ 'projects unclaimed',
154
+ 'schema delete',
155
+ 'schema deploy',
156
+ 'schema extract',
157
+ 'schema list',
158
+ 'schemas delete',
159
+ 'schemas deploy',
160
+ 'schemas extract',
161
+ 'schemas list',
162
+ 'schemas validate',
163
+ 'schema validate',
164
+ 'skills install',
165
+ 'telemetry disable',
166
+ 'telemetry enable',
167
+ 'telemetry status',
168
+ 'tokens create',
169
+ 'tokens delete',
170
+ 'tokens list',
171
+ 'tokens rotate',
172
+ 'typegen generate',
173
+ 'undeploy',
174
+ 'uninstall',
175
+ 'upgrade',
176
+ 'users invite',
177
+ 'users list',
178
+ 'versions',
179
+ 'whoami',
180
+ 'workflows abort',
181
+ 'workflows blueprint generate',
182
+ 'workflows definition delete',
183
+ 'workflows definition diff',
184
+ 'workflows definition list',
185
+ 'workflows definition show',
186
+ 'workflows deploy',
187
+ 'workflows diagnose',
188
+ 'workflows fire-action',
189
+ 'workflows list',
190
+ 'workflows nuke',
191
+ 'workflows reset-activity',
192
+ 'workflows set-stage',
193
+ 'workflows show',
194
+ 'workflows start',
195
+ 'workflows tail'
196
+ ]);
197
+ const knownRoots = new Set([
198
+ ...commandPaths
199
+ ].map((path)=>path.split(' ')[0]));
200
+ export function commandIdentity(group, args) {
201
+ const root = typeof group === 'string' ? group.split(':') : [];
202
+ const parts = [
203
+ ...root,
204
+ ...Array.isArray(args) ? args : []
205
+ ];
206
+ if (!knownRoots.has(root[0])) return {
207
+ commandArguments: [],
208
+ groupOrCommand: 'unknown'
209
+ };
210
+ let commandArguments = [];
211
+ for(let length = 2; length <= Math.min(parts.length, 4); length++){
212
+ const candidate = parts.slice(0, length);
213
+ if (!candidate.every((part)=>typeof part === 'string')) break;
214
+ if (commandPaths.has(candidate.join(' '))) commandArguments = candidate.slice(1);
215
+ }
216
+ return {
217
+ commandArguments,
218
+ groupOrCommand: root[0]
219
+ };
220
+ }
221
+
222
+ //# sourceMappingURL=cliCommandIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/util/telemetry/cliCommandIdentity.ts"],"sourcesContent":["// Command paths only: positional user input must never become command identity.\nconst commandPaths = new Set([\n 'api',\n 'assets upload',\n 'backup disable',\n 'backup download',\n 'backup enable',\n 'backup list',\n 'backups disable',\n 'backups download',\n 'backups enable',\n 'backups list',\n 'blueprints add',\n 'blueprints config',\n 'blueprints deploy',\n 'blueprints destroy',\n 'blueprints doctor',\n 'blueprints info',\n 'blueprints init',\n 'blueprints logs',\n 'blueprints mint-deploy-token',\n 'blueprints plan',\n 'blueprints promote',\n 'blueprints stacks',\n 'build',\n 'check',\n 'codemod',\n 'context build',\n 'context create',\n 'context delete',\n 'context entries get',\n 'context entries list',\n 'context entries rebuild',\n 'context get',\n 'context imports create',\n 'context imports delete',\n 'context imports download',\n 'context imports get',\n 'context imports list',\n 'context issues apply',\n 'context issues dismiss',\n 'context issues get',\n 'context issues list',\n 'context issues reopen',\n 'context issues resolve',\n 'context jobs get',\n 'context list',\n 'context mcp create',\n 'context mcp delete',\n 'context mcp get',\n 'context mcp list',\n 'context mcp status',\n 'context mcp update',\n 'context query',\n 'context refresh',\n 'context update',\n 'cors add',\n 'cors delete',\n 'cors list',\n 'dataset alias create',\n 'dataset alias delete',\n 'dataset alias link',\n 'dataset alias unlink',\n 'dataset copy',\n 'dataset create',\n 'dataset delete',\n 'dataset export',\n 'dataset import',\n 'dataset list',\n 'datasets alias create',\n 'datasets alias delete',\n 'datasets alias link',\n 'datasets alias unlink',\n 'datasets copy',\n 'datasets create',\n 'datasets delete',\n 'datasets embeddings disable',\n 'datasets embeddings enable',\n 'datasets embeddings status',\n 'datasets export',\n 'datasets import',\n 'datasets list',\n 'datasets visibility get',\n 'datasets visibility set',\n 'dataset visibility get',\n 'dataset visibility set',\n 'debug',\n 'deploy',\n 'dev',\n 'docs browse',\n 'docs read',\n 'docs search',\n 'doctor',\n 'documents create',\n 'documents delete',\n 'documents get',\n 'documents query',\n 'documents validate',\n 'exec',\n 'functions add',\n 'functions build',\n 'functions deploy',\n 'functions dev',\n 'functions env add',\n 'functions env list',\n 'functions env remove',\n 'functions list',\n 'functions logs',\n 'functions test',\n 'graphql deploy',\n 'graphql list',\n 'graphql undeploy',\n 'help',\n 'hook list',\n 'hooks attempt',\n 'hooks create',\n 'hooks delete',\n 'hooks list',\n 'hooks logs',\n 'init',\n 'init plugin',\n 'install',\n 'learn',\n 'login',\n 'logout',\n 'manage',\n 'manifest extract',\n 'mcp configure',\n 'media create-aspect',\n 'media delete-aspect',\n 'media deploy-aspect',\n 'media export',\n 'media import',\n 'media prune-aspect-data',\n 'media pull-aspects',\n 'migration create',\n 'migration list',\n 'migration run',\n 'migrations create',\n 'migrations list',\n 'migrations run',\n 'new',\n 'openapi get',\n 'openapi list',\n 'organizations create',\n 'organizations delete',\n 'organizations get',\n 'organizations list',\n 'organizations update',\n 'preview',\n 'projects create',\n 'projects list',\n 'projects unclaimed',\n 'schema delete',\n 'schema deploy',\n 'schema extract',\n 'schema list',\n 'schemas delete',\n 'schemas deploy',\n 'schemas extract',\n 'schemas list',\n 'schemas validate',\n 'schema validate',\n 'skills install',\n 'telemetry disable',\n 'telemetry enable',\n 'telemetry status',\n 'tokens create',\n 'tokens delete',\n 'tokens list',\n 'tokens rotate',\n 'typegen generate',\n 'undeploy',\n 'uninstall',\n 'upgrade',\n 'users invite',\n 'users list',\n 'versions',\n 'whoami',\n 'workflows abort',\n 'workflows blueprint generate',\n 'workflows definition delete',\n 'workflows definition diff',\n 'workflows definition list',\n 'workflows definition show',\n 'workflows deploy',\n 'workflows diagnose',\n 'workflows fire-action',\n 'workflows list',\n 'workflows nuke',\n 'workflows reset-activity',\n 'workflows set-stage',\n 'workflows show',\n 'workflows start',\n 'workflows tail',\n])\n\nconst knownRoots = new Set([...commandPaths].map((path) => path.split(' ')[0]))\n\nexport function commandIdentity(group: unknown, args: unknown) {\n const root = typeof group === 'string' ? group.split(':') : []\n const parts = [...root, ...(Array.isArray(args) ? args : [])]\n if (!knownRoots.has(root[0])) return {commandArguments: [], groupOrCommand: 'unknown'}\n\n let commandArguments: string[] = []\n for (let length = 2; length <= Math.min(parts.length, 4); length++) {\n const candidate = parts.slice(0, length)\n if (!candidate.every((part) => typeof part === 'string')) break\n if (commandPaths.has(candidate.join(' '))) commandArguments = candidate.slice(1)\n }\n return {commandArguments, groupOrCommand: root[0]}\n}\n"],"names":["commandPaths","Set","knownRoots","map","path","split","commandIdentity","group","args","root","parts","Array","isArray","has","commandArguments","groupOrCommand","length","Math","min","candidate","slice","every","part","join"],"mappings":"AAAA,gFAAgF;AAChF,MAAMA,eAAe,IAAIC,IAAI;IAC3B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,aAAa,IAAID,IAAI;OAAID;CAAa,CAACG,GAAG,CAAC,CAACC,OAASA,KAAKC,KAAK,CAAC,IAAI,CAAC,EAAE;AAE7E,OAAO,SAASC,gBAAgBC,KAAc,EAAEC,IAAa;IAC3D,MAAMC,OAAO,OAAOF,UAAU,WAAWA,MAAMF,KAAK,CAAC,OAAO,EAAE;IAC9D,MAAMK,QAAQ;WAAID;WAAUE,MAAMC,OAAO,CAACJ,QAAQA,OAAO,EAAE;KAAE;IAC7D,IAAI,CAACN,WAAWW,GAAG,CAACJ,IAAI,CAAC,EAAE,GAAG,OAAO;QAACK,kBAAkB,EAAE;QAAEC,gBAAgB;IAAS;IAErF,IAAID,mBAA6B,EAAE;IACnC,IAAK,IAAIE,SAAS,GAAGA,UAAUC,KAAKC,GAAG,CAACR,MAAMM,MAAM,EAAE,IAAIA,SAAU;QAClE,MAAMG,YAAYT,MAAMU,KAAK,CAAC,GAAGJ;QACjC,IAAI,CAACG,UAAUE,KAAK,CAAC,CAACC,OAAS,OAAOA,SAAS,WAAW;QAC1D,IAAItB,aAAaa,GAAG,CAACM,UAAUI,IAAI,CAAC,OAAOT,mBAAmBK,UAAUC,KAAK,CAAC;IAChF;IACA,OAAO;QAACN;QAAkBC,gBAAgBN,IAAI,CAAC,EAAE;IAAA;AACnD"}
@@ -0,0 +1,186 @@
1
+ // This catalog grants collection of flag names. Values require a separate enum.
2
+ // Removing an entry always reduces collection, including for pinned clients.
3
+ const knownFlags = new Set([
4
+ 'aspect',
5
+ 'bare',
6
+ 'cadence',
7
+ 'config-path',
8
+ 'coupon',
9
+ 'create-project',
10
+ 'dataset',
11
+ 'debug',
12
+ 'debug-metafile-path',
13
+ 'description',
14
+ 'embeddings-projection',
15
+ 'env',
16
+ 'field',
17
+ 'file',
18
+ 'filename',
19
+ 'force',
20
+ 'format',
21
+ 'from-export',
22
+ 'from-url',
23
+ 'generation',
24
+ 'git',
25
+ 'header',
26
+ 'help',
27
+ 'host',
28
+ 'include',
29
+ 'input',
30
+ 'json',
31
+ 'level',
32
+ 'limit',
33
+ 'manifest-dir',
34
+ 'method',
35
+ 'mode',
36
+ 'name',
37
+ 'offset',
38
+ 'order',
39
+ 'organization',
40
+ 'out',
41
+ 'output',
42
+ 'output-path',
43
+ 'package-manager',
44
+ 'params',
45
+ 'path',
46
+ 'port',
47
+ 'project',
48
+ 'project-id',
49
+ 'project-name',
50
+ 'projection',
51
+ 'query',
52
+ 'raw-field',
53
+ 'sort',
54
+ 'template',
55
+ 'template-token',
56
+ 'text',
57
+ 'title',
58
+ 'token',
59
+ 'type',
60
+ 'url',
61
+ 'version',
62
+ 'visibility',
63
+ 'watch',
64
+ 'watch-patterns',
65
+ 'workspace',
66
+ 'yes'
67
+ ]);
68
+ const values = {
69
+ cadence: [
70
+ 'weekly',
71
+ 'monthly'
72
+ ],
73
+ format: [
74
+ 'json',
75
+ 'ndjson',
76
+ 'pretty',
77
+ 'yaml'
78
+ ],
79
+ generation: [
80
+ 'gen1',
81
+ 'gen2',
82
+ 'gen3'
83
+ ],
84
+ level: [
85
+ 'error',
86
+ 'warning',
87
+ 'info'
88
+ ],
89
+ method: [
90
+ 'GET',
91
+ 'POST',
92
+ 'PUT',
93
+ 'PATCH',
94
+ 'DELETE',
95
+ 'HEAD',
96
+ 'OPTIONS'
97
+ ],
98
+ mode: [
99
+ 'stream',
100
+ 'cursor'
101
+ ],
102
+ order: [
103
+ 'asc',
104
+ 'desc'
105
+ ],
106
+ 'package-manager': [
107
+ 'npm',
108
+ 'pnpm',
109
+ 'yarn',
110
+ 'bun'
111
+ ],
112
+ type: [
113
+ 'image',
114
+ 'file'
115
+ ],
116
+ visibility: [
117
+ 'public',
118
+ 'private'
119
+ ]
120
+ };
121
+ const aliases = {
122
+ d: 'debug',
123
+ F: 'field',
124
+ f: 'raw-field',
125
+ H: 'header',
126
+ h: 'help',
127
+ i: 'include',
128
+ j: 'json',
129
+ t: 'token',
130
+ v: 'version',
131
+ X: 'method',
132
+ y: 'yes'
133
+ };
134
+ const shortBooleans = new Set([
135
+ 'd',
136
+ 'h',
137
+ 'i',
138
+ 'j',
139
+ 'v',
140
+ 'y'
141
+ ]);
142
+ function flag(name, value) {
143
+ if (!knownFlags.has(name)) return undefined;
144
+ if (Object.hasOwn(values, name) && value !== undefined && values[name].includes(value)) {
145
+ return `--${name}=${value}`;
146
+ }
147
+ return `--${name}`;
148
+ }
149
+ export function sanitizeCliFlags(input) {
150
+ if (!Array.isArray(input)) return [];
151
+ const result = [];
152
+ for (const argument of input){
153
+ if (argument === '--') break;
154
+ if (typeof argument !== 'string') continue;
155
+ const long = /^--([A-Za-z][A-Za-z0-9-]*)(?:=([\s\S]*))?$/.exec(argument);
156
+ if (long) {
157
+ const safe = flag(long[1], long[2]);
158
+ if (safe) result.push(safe);
159
+ continue;
160
+ }
161
+ if (!/^-[A-Za-z]/.test(argument)) continue;
162
+ for(let index = 1; index < argument.length; index++){
163
+ const short = argument[index];
164
+ if (!Object.hasOwn(aliases, short)) break;
165
+ const name = aliases[short];
166
+ if (shortBooleans.has(short)) {
167
+ result.push(`--${name}`);
168
+ continue;
169
+ }
170
+ const safe = flag(name, argument.slice(index + 1).replace(/^=/, ''));
171
+ if (safe) result.push(safe);
172
+ break;
173
+ }
174
+ }
175
+ return result;
176
+ }
177
+ export function sanitizeCliFlagRecord(input) {
178
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return {};
179
+ const result = {};
180
+ for (const [name, value] of Object.entries(input)){
181
+ if (knownFlags.has(name)) result[name] = Boolean(value);
182
+ }
183
+ return result;
184
+ }
185
+
186
+ //# sourceMappingURL=cliTelemetryFlags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/util/telemetry/cliTelemetryFlags.ts"],"sourcesContent":["// This catalog grants collection of flag names. Values require a separate enum.\n// Removing an entry always reduces collection, including for pinned clients.\nconst knownFlags = new Set([\n 'aspect',\n 'bare',\n 'cadence',\n 'config-path',\n 'coupon',\n 'create-project',\n 'dataset',\n 'debug',\n 'debug-metafile-path',\n 'description',\n 'embeddings-projection',\n 'env',\n 'field',\n 'file',\n 'filename',\n 'force',\n 'format',\n 'from-export',\n 'from-url',\n 'generation',\n 'git',\n 'header',\n 'help',\n 'host',\n 'include',\n 'input',\n 'json',\n 'level',\n 'limit',\n 'manifest-dir',\n 'method',\n 'mode',\n 'name',\n 'offset',\n 'order',\n 'organization',\n 'out',\n 'output',\n 'output-path',\n 'package-manager',\n 'params',\n 'path',\n 'port',\n 'project',\n 'project-id',\n 'project-name',\n 'projection',\n 'query',\n 'raw-field',\n 'sort',\n 'template',\n 'template-token',\n 'text',\n 'title',\n 'token',\n 'type',\n 'url',\n 'version',\n 'visibility',\n 'watch',\n 'watch-patterns',\n 'workspace',\n 'yes',\n])\nconst values: Record<string, readonly string[]> = {\n cadence: ['weekly', 'monthly'],\n format: ['json', 'ndjson', 'pretty', 'yaml'],\n generation: ['gen1', 'gen2', 'gen3'],\n level: ['error', 'warning', 'info'],\n method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],\n mode: ['stream', 'cursor'],\n order: ['asc', 'desc'],\n 'package-manager': ['npm', 'pnpm', 'yarn', 'bun'],\n type: ['image', 'file'],\n visibility: ['public', 'private'],\n}\nconst aliases: Record<string, string> = {\n d: 'debug',\n F: 'field',\n f: 'raw-field',\n H: 'header',\n h: 'help',\n i: 'include',\n j: 'json',\n t: 'token',\n v: 'version',\n X: 'method',\n y: 'yes',\n}\nconst shortBooleans = new Set(['d', 'h', 'i', 'j', 'v', 'y'])\n\nfunction flag(name: string, value?: string): string | undefined {\n if (!knownFlags.has(name)) return undefined\n if (Object.hasOwn(values, name) && value !== undefined && values[name].includes(value)) {\n return `--${name}=${value}`\n }\n return `--${name}`\n}\n\nexport function sanitizeCliFlags(input: unknown): string[] {\n if (!Array.isArray(input)) return []\n const result: string[] = []\n for (const argument of input) {\n if (argument === '--') break\n if (typeof argument !== 'string') continue\n const long = /^--([A-Za-z][A-Za-z0-9-]*)(?:=([\\s\\S]*))?$/.exec(argument)\n if (long) {\n const safe = flag(long[1], long[2])\n if (safe) result.push(safe)\n continue\n }\n if (!/^-[A-Za-z]/.test(argument)) continue\n for (let index = 1; index < argument.length; index++) {\n const short = argument[index]\n if (!Object.hasOwn(aliases, short)) break\n const name = aliases[short]\n if (shortBooleans.has(short)) {\n result.push(`--${name}`)\n continue\n }\n const safe = flag(name, argument.slice(index + 1).replace(/^=/, ''))\n if (safe) result.push(safe)\n break\n }\n }\n return result\n}\n\nexport function sanitizeCliFlagRecord(input: unknown): Record<string, boolean> {\n if (!input || typeof input !== 'object' || Array.isArray(input)) return {}\n const result: Record<string, boolean> = {}\n for (const [name, value] of Object.entries(input)) {\n if (knownFlags.has(name)) result[name] = Boolean(value)\n }\n return result\n}\n"],"names":["knownFlags","Set","values","cadence","format","generation","level","method","mode","order","type","visibility","aliases","d","F","f","H","h","i","j","t","v","X","y","shortBooleans","flag","name","value","has","undefined","Object","hasOwn","includes","sanitizeCliFlags","input","Array","isArray","result","argument","long","exec","safe","push","test","index","length","short","slice","replace","sanitizeCliFlagRecord","entries","Boolean"],"mappings":"AAAA,gFAAgF;AAChF,6EAA6E;AAC7E,MAAMA,aAAa,IAAIC,IAAI;IACzB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,SAA4C;IAChDC,SAAS;QAAC;QAAU;KAAU;IAC9BC,QAAQ;QAAC;QAAQ;QAAU;QAAU;KAAO;IAC5CC,YAAY;QAAC;QAAQ;QAAQ;KAAO;IACpCC,OAAO;QAAC;QAAS;QAAW;KAAO;IACnCC,QAAQ;QAAC;QAAO;QAAQ;QAAO;QAAS;QAAU;QAAQ;KAAU;IACpEC,MAAM;QAAC;QAAU;KAAS;IAC1BC,OAAO;QAAC;QAAO;KAAO;IACtB,mBAAmB;QAAC;QAAO;QAAQ;QAAQ;KAAM;IACjDC,MAAM;QAAC;QAAS;KAAO;IACvBC,YAAY;QAAC;QAAU;KAAU;AACnC;AACA,MAAMC,UAAkC;IACtCC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;IACHC,GAAG;AACL;AACA,MAAMC,gBAAgB,IAAIvB,IAAI;IAAC;IAAK;IAAK;IAAK;IAAK;IAAK;CAAI;AAE5D,SAASwB,KAAKC,IAAY,EAAEC,KAAc;IACxC,IAAI,CAAC3B,WAAW4B,GAAG,CAACF,OAAO,OAAOG;IAClC,IAAIC,OAAOC,MAAM,CAAC7B,QAAQwB,SAASC,UAAUE,aAAa3B,MAAM,CAACwB,KAAK,CAACM,QAAQ,CAACL,QAAQ;QACtF,OAAO,CAAC,EAAE,EAAED,KAAK,CAAC,EAAEC,OAAO;IAC7B;IACA,OAAO,CAAC,EAAE,EAAED,MAAM;AACpB;AAEA,OAAO,SAASO,iBAAiBC,KAAc;IAC7C,IAAI,CAACC,MAAMC,OAAO,CAACF,QAAQ,OAAO,EAAE;IACpC,MAAMG,SAAmB,EAAE;IAC3B,KAAK,MAAMC,YAAYJ,MAAO;QAC5B,IAAII,aAAa,MAAM;QACvB,IAAI,OAAOA,aAAa,UAAU;QAClC,MAAMC,OAAO,6CAA6CC,IAAI,CAACF;QAC/D,IAAIC,MAAM;YACR,MAAME,OAAOhB,KAAKc,IAAI,CAAC,EAAE,EAAEA,IAAI,CAAC,EAAE;YAClC,IAAIE,MAAMJ,OAAOK,IAAI,CAACD;YACtB;QACF;QACA,IAAI,CAAC,aAAaE,IAAI,CAACL,WAAW;QAClC,IAAK,IAAIM,QAAQ,GAAGA,QAAQN,SAASO,MAAM,EAAED,QAAS;YACpD,MAAME,QAAQR,QAAQ,CAACM,MAAM;YAC7B,IAAI,CAACd,OAAOC,MAAM,CAACnB,SAASkC,QAAQ;YACpC,MAAMpB,OAAOd,OAAO,CAACkC,MAAM;YAC3B,IAAItB,cAAcI,GAAG,CAACkB,QAAQ;gBAC5BT,OAAOK,IAAI,CAAC,CAAC,EAAE,EAAEhB,MAAM;gBACvB;YACF;YACA,MAAMe,OAAOhB,KAAKC,MAAMY,SAASS,KAAK,CAACH,QAAQ,GAAGI,OAAO,CAAC,MAAM;YAChE,IAAIP,MAAMJ,OAAOK,IAAI,CAACD;YACtB;QACF;IACF;IACA,OAAOJ;AACT;AAEA,OAAO,SAASY,sBAAsBf,KAAc;IAClD,IAAI,CAACA,SAAS,OAAOA,UAAU,YAAYC,MAAMC,OAAO,CAACF,QAAQ,OAAO,CAAC;IACzE,MAAMG,SAAkC,CAAC;IACzC,KAAK,MAAM,CAACX,MAAMC,MAAM,IAAIG,OAAOoB,OAAO,CAAChB,OAAQ;QACjD,IAAIlC,WAAW4B,GAAG,CAACF,OAAOW,MAAM,CAACX,KAAK,GAAGyB,QAAQxB;IACnD;IACA,OAAOU;AACT"}
@@ -17,18 +17,63 @@
17
17
  })
18
18
  };
19
19
  }
20
- export function redactTelemetryArguments(arguments_, commandTelemetry) {
21
- let forwarding = false;
22
- return arguments_.map((argument)=>{
23
- if (argument === '--') {
24
- forwarding = true;
25
- return argument;
20
+ export function collectTelemetryFlags(argv, flags, telemetry) {
21
+ const definitions = new Map();
22
+ for (const [name, flag] of Object.entries(flags)){
23
+ const canonical = `--${name}`;
24
+ const definition = {
25
+ canonical,
26
+ option: flag.type === 'option',
27
+ redact: telemetry?.redactedFlags.some((entry)=>entry.canonical === canonical) ?? false
28
+ };
29
+ definitions.set(canonical, definition);
30
+ for (const alias of flag.aliases ?? []){
31
+ definitions.set(`${alias.length === 1 ? '-' : '--'}${alias}`, definition);
26
32
  }
27
- if (forwarding) return argument;
28
- const isShortOption = argument.startsWith('-') && !argument.startsWith('--');
29
- const redactedFlag = commandTelemetry?.redactedFlags.find(({ flags })=>flags.some((syntax)=>syntax.startsWith('--') ? argument === syntax || argument.startsWith(`${syntax}=`) : isShortOption && argument.startsWith(syntax)));
30
- return redactedFlag?.canonical ?? argument;
31
- });
33
+ for (const char of [
34
+ flag.char,
35
+ ...flag.charAliases ?? []
36
+ ]){
37
+ if (char) definitions.set(`-${char}`, definition);
38
+ }
39
+ if (flag.type === 'boolean' && flag.allowNo) {
40
+ definitions.set(`--no-${name}`, {
41
+ ...definition,
42
+ canonical: `--no-${name}`
43
+ });
44
+ }
45
+ }
46
+ const result = [];
47
+ for(let index = 0; index < argv.length; index++){
48
+ const argument = argv[index];
49
+ if (argument === '--') break;
50
+ if (!argument.startsWith('-') || argument === '-') continue;
51
+ if (argument.startsWith('--')) {
52
+ const separator = argument.indexOf('=');
53
+ const name = separator === -1 ? argument : argument.slice(0, separator);
54
+ const flag = definitions.get(name);
55
+ // An unknown option may consume the next token, including a known flag's spelling.
56
+ // Stop rather than interpreting private input as telemetry.
57
+ if (!flag) break;
58
+ const value = separator === -1 ? undefined : argument.slice(separator + 1);
59
+ result.push(flag.redact || !flag.option || value === undefined ? flag.canonical : `${flag.canonical}=${value}`);
60
+ if (flag.option && separator === -1) index++;
61
+ continue;
62
+ }
63
+ for(let offset = 1; offset < argument.length; offset++){
64
+ const flag = definitions.get(`-${argument[offset]}`);
65
+ if (!flag) return result;
66
+ if (!flag.option) {
67
+ result.push(flag.canonical);
68
+ continue;
69
+ }
70
+ const value = argument.slice(offset + 1);
71
+ result.push(flag.redact || !value ? flag.canonical : `${flag.canonical}=${value.replace(/^=/, '')}`);
72
+ if (!value) index++;
73
+ break;
74
+ }
75
+ }
76
+ return result;
32
77
  }
33
78
 
34
79
  //# sourceMappingURL=commandTelemetry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/util/telemetry/commandTelemetry.ts"],"sourcesContent":["import {type Interfaces} from '@oclif/core'\n\ninterface RedactedFlag {\n canonical: string\n flags: readonly string[]\n}\n\n/** @internal */\nexport interface CommandTelemetry {\n redactedFlags: readonly RedactedFlag[]\n}\n\ntype OptionFlagName<Flags extends Interfaces.FlagInput> = string &\n {\n [Name in keyof Flags]: Flags[Name] extends {type: 'option'} ? Name : never\n }[keyof Flags]\n\ntype CommandTelemetryConfig<Flags extends Interfaces.FlagInput> = {\n redact?: readonly OptionFlagName<Flags>[]\n}\n\n/** @internal */\nexport function defineCommandTelemetry<const Flags extends Interfaces.FlagInput>(\n flags: Flags,\n config: CommandTelemetryConfig<Flags>,\n): CommandTelemetry {\n return {\n redactedFlags: (config.redact ?? []).map((name) => {\n const flag = flags[name]\n const aliases = flag?.aliases ?? []\n\n return {\n canonical: `--${name}`,\n flags: [\n `--${name}`,\n ...aliases.map((alias) => `${alias.length === 1 ? '-' : '--'}${alias}`),\n ...(flag?.char ? [`-${flag.char}`] : []),\n ...(flag?.charAliases ?? []).map((alias) => `-${alias}`),\n ],\n }\n }),\n }\n}\n\nexport function redactTelemetryArguments(\n arguments_: string[],\n commandTelemetry?: CommandTelemetry,\n): string[] {\n let forwarding = false\n\n return arguments_.map((argument) => {\n if (argument === '--') {\n forwarding = true\n return argument\n }\n\n if (forwarding) return argument\n\n const isShortOption = argument.startsWith('-') && !argument.startsWith('--')\n const redactedFlag = commandTelemetry?.redactedFlags.find(({flags}) =>\n flags.some((syntax) =>\n syntax.startsWith('--')\n ? argument === syntax || argument.startsWith(`${syntax}=`)\n : isShortOption && argument.startsWith(syntax),\n ),\n )\n\n return redactedFlag?.canonical ?? argument\n })\n}\n"],"names":["defineCommandTelemetry","flags","config","redactedFlags","redact","map","name","flag","aliases","canonical","alias","length","char","charAliases","redactTelemetryArguments","arguments_","commandTelemetry","forwarding","argument","isShortOption","startsWith","redactedFlag","find","some","syntax"],"mappings":"AAqBA,cAAc,GACd,OAAO,SAASA,uBACdC,KAAY,EACZC,MAAqC;IAErC,OAAO;QACLC,eAAe,AAACD,CAAAA,OAAOE,MAAM,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;YACxC,MAAMC,OAAON,KAAK,CAACK,KAAK;YACxB,MAAME,UAAUD,MAAMC,WAAW,EAAE;YAEnC,OAAO;gBACLC,WAAW,CAAC,EAAE,EAAEH,MAAM;gBACtBL,OAAO;oBACL,CAAC,EAAE,EAAEK,MAAM;uBACRE,QAAQH,GAAG,CAAC,CAACK,QAAU,GAAGA,MAAMC,MAAM,KAAK,IAAI,MAAM,OAAOD,OAAO;uBAClEH,MAAMK,OAAO;wBAAC,CAAC,CAAC,EAAEL,KAAKK,IAAI,EAAE;qBAAC,GAAG,EAAE;uBACpC,AAACL,CAAAA,MAAMM,eAAe,EAAE,AAAD,EAAGR,GAAG,CAAC,CAACK,QAAU,CAAC,CAAC,EAAEA,OAAO;iBACxD;YACH;QACF;IACF;AACF;AAEA,OAAO,SAASI,yBACdC,UAAoB,EACpBC,gBAAmC;IAEnC,IAAIC,aAAa;IAEjB,OAAOF,WAAWV,GAAG,CAAC,CAACa;QACrB,IAAIA,aAAa,MAAM;YACrBD,aAAa;YACb,OAAOC;QACT;QAEA,IAAID,YAAY,OAAOC;QAEvB,MAAMC,gBAAgBD,SAASE,UAAU,CAAC,QAAQ,CAACF,SAASE,UAAU,CAAC;QACvE,MAAMC,eAAeL,kBAAkBb,cAAcmB,KAAK,CAAC,EAACrB,KAAK,EAAC,GAChEA,MAAMsB,IAAI,CAAC,CAACC,SACVA,OAAOJ,UAAU,CAAC,QACdF,aAAaM,UAAUN,SAASE,UAAU,CAAC,GAAGI,OAAO,CAAC,CAAC,IACvDL,iBAAiBD,SAASE,UAAU,CAACI;QAI7C,OAAOH,cAAcZ,aAAaS;IACpC;AACF"}
1
+ {"version":3,"sources":["../../../src/util/telemetry/commandTelemetry.ts"],"sourcesContent":["import {type Interfaces} from '@oclif/core'\n\ninterface RedactedFlag {\n canonical: string\n flags: readonly string[]\n}\n\n/** @internal */\nexport interface CommandTelemetry {\n redactedFlags: readonly RedactedFlag[]\n}\n\ntype OptionFlagName<Flags extends Interfaces.FlagInput> = string &\n {\n [Name in keyof Flags]: Flags[Name] extends {type: 'option'} ? Name : never\n }[keyof Flags]\n\ntype CommandTelemetryConfig<Flags extends Interfaces.FlagInput> = {\n redact?: readonly OptionFlagName<Flags>[]\n}\n\n/** @internal */\nexport function defineCommandTelemetry<const Flags extends Interfaces.FlagInput>(\n flags: Flags,\n config: CommandTelemetryConfig<Flags>,\n): CommandTelemetry {\n return {\n redactedFlags: (config.redact ?? []).map((name) => {\n const flag = flags[name]\n const aliases = flag?.aliases ?? []\n\n return {\n canonical: `--${name}`,\n flags: [\n `--${name}`,\n ...aliases.map((alias) => `${alias.length === 1 ? '-' : '--'}${alias}`),\n ...(flag?.char ? [`-${flag.char}`] : []),\n ...(flag?.charAliases ?? []).map((alias) => `-${alias}`),\n ],\n }\n }),\n }\n}\n\ninterface TelemetryFlag {\n canonical: string\n option: boolean\n redact: boolean\n}\n\nexport function collectTelemetryFlags(\n argv: string[],\n flags: Interfaces.FlagInput,\n telemetry?: CommandTelemetry,\n): string[] {\n const definitions = new Map<string, TelemetryFlag>()\n for (const [name, flag] of Object.entries(flags)) {\n const canonical = `--${name}`\n const definition = {\n canonical,\n option: flag.type === 'option',\n redact: telemetry?.redactedFlags.some((entry) => entry.canonical === canonical) ?? false,\n }\n definitions.set(canonical, definition)\n for (const alias of flag.aliases ?? []) {\n definitions.set(`${alias.length === 1 ? '-' : '--'}${alias}`, definition)\n }\n for (const char of [flag.char, ...(flag.charAliases ?? [])]) {\n if (char) definitions.set(`-${char}`, definition)\n }\n if (flag.type === 'boolean' && flag.allowNo) {\n definitions.set(`--no-${name}`, {...definition, canonical: `--no-${name}`})\n }\n }\n\n const result: string[] = []\n for (let index = 0; index < argv.length; index++) {\n const argument = argv[index]\n if (argument === '--') break\n if (!argument.startsWith('-') || argument === '-') continue\n\n if (argument.startsWith('--')) {\n const separator = argument.indexOf('=')\n const name = separator === -1 ? argument : argument.slice(0, separator)\n const flag = definitions.get(name)\n // An unknown option may consume the next token, including a known flag's spelling.\n // Stop rather than interpreting private input as telemetry.\n if (!flag) break\n const value = separator === -1 ? undefined : argument.slice(separator + 1)\n result.push(\n flag.redact || !flag.option || value === undefined\n ? flag.canonical\n : `${flag.canonical}=${value}`,\n )\n if (flag.option && separator === -1) index++\n continue\n }\n\n for (let offset = 1; offset < argument.length; offset++) {\n const flag = definitions.get(`-${argument[offset]}`)\n if (!flag) return result\n if (!flag.option) {\n result.push(flag.canonical)\n continue\n }\n const value = argument.slice(offset + 1)\n result.push(\n flag.redact || !value ? flag.canonical : `${flag.canonical}=${value.replace(/^=/, '')}`,\n )\n if (!value) index++\n break\n }\n }\n\n return result\n}\n"],"names":["defineCommandTelemetry","flags","config","redactedFlags","redact","map","name","flag","aliases","canonical","alias","length","char","charAliases","collectTelemetryFlags","argv","telemetry","definitions","Map","Object","entries","definition","option","type","some","entry","set","allowNo","result","index","argument","startsWith","separator","indexOf","slice","get","value","undefined","push","offset","replace"],"mappings":"AAqBA,cAAc,GACd,OAAO,SAASA,uBACdC,KAAY,EACZC,MAAqC;IAErC,OAAO;QACLC,eAAe,AAACD,CAAAA,OAAOE,MAAM,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;YACxC,MAAMC,OAAON,KAAK,CAACK,KAAK;YACxB,MAAME,UAAUD,MAAMC,WAAW,EAAE;YAEnC,OAAO;gBACLC,WAAW,CAAC,EAAE,EAAEH,MAAM;gBACtBL,OAAO;oBACL,CAAC,EAAE,EAAEK,MAAM;uBACRE,QAAQH,GAAG,CAAC,CAACK,QAAU,GAAGA,MAAMC,MAAM,KAAK,IAAI,MAAM,OAAOD,OAAO;uBAClEH,MAAMK,OAAO;wBAAC,CAAC,CAAC,EAAEL,KAAKK,IAAI,EAAE;qBAAC,GAAG,EAAE;uBACpC,AAACL,CAAAA,MAAMM,eAAe,EAAE,AAAD,EAAGR,GAAG,CAAC,CAACK,QAAU,CAAC,CAAC,EAAEA,OAAO;iBACxD;YACH;QACF;IACF;AACF;AAQA,OAAO,SAASI,sBACdC,IAAc,EACdd,KAA2B,EAC3Be,SAA4B;IAE5B,MAAMC,cAAc,IAAIC;IACxB,KAAK,MAAM,CAACZ,MAAMC,KAAK,IAAIY,OAAOC,OAAO,CAACnB,OAAQ;QAChD,MAAMQ,YAAY,CAAC,EAAE,EAAEH,MAAM;QAC7B,MAAMe,aAAa;YACjBZ;YACAa,QAAQf,KAAKgB,IAAI,KAAK;YACtBnB,QAAQY,WAAWb,cAAcqB,KAAK,CAACC,QAAUA,MAAMhB,SAAS,KAAKA,cAAc;QACrF;QACAQ,YAAYS,GAAG,CAACjB,WAAWY;QAC3B,KAAK,MAAMX,SAASH,KAAKC,OAAO,IAAI,EAAE,CAAE;YACtCS,YAAYS,GAAG,CAAC,GAAGhB,MAAMC,MAAM,KAAK,IAAI,MAAM,OAAOD,OAAO,EAAEW;QAChE;QACA,KAAK,MAAMT,QAAQ;YAACL,KAAKK,IAAI;eAAML,KAAKM,WAAW,IAAI,EAAE;SAAE,CAAE;YAC3D,IAAID,MAAMK,YAAYS,GAAG,CAAC,CAAC,CAAC,EAAEd,MAAM,EAAES;QACxC;QACA,IAAId,KAAKgB,IAAI,KAAK,aAAahB,KAAKoB,OAAO,EAAE;YAC3CV,YAAYS,GAAG,CAAC,CAAC,KAAK,EAAEpB,MAAM,EAAE;gBAAC,GAAGe,UAAU;gBAAEZ,WAAW,CAAC,KAAK,EAAEH,MAAM;YAAA;QAC3E;IACF;IAEA,MAAMsB,SAAmB,EAAE;IAC3B,IAAK,IAAIC,QAAQ,GAAGA,QAAQd,KAAKJ,MAAM,EAAEkB,QAAS;QAChD,MAAMC,WAAWf,IAAI,CAACc,MAAM;QAC5B,IAAIC,aAAa,MAAM;QACvB,IAAI,CAACA,SAASC,UAAU,CAAC,QAAQD,aAAa,KAAK;QAEnD,IAAIA,SAASC,UAAU,CAAC,OAAO;YAC7B,MAAMC,YAAYF,SAASG,OAAO,CAAC;YACnC,MAAM3B,OAAO0B,cAAc,CAAC,IAAIF,WAAWA,SAASI,KAAK,CAAC,GAAGF;YAC7D,MAAMzB,OAAOU,YAAYkB,GAAG,CAAC7B;YAC7B,mFAAmF;YACnF,4DAA4D;YAC5D,IAAI,CAACC,MAAM;YACX,MAAM6B,QAAQJ,cAAc,CAAC,IAAIK,YAAYP,SAASI,KAAK,CAACF,YAAY;YACxEJ,OAAOU,IAAI,CACT/B,KAAKH,MAAM,IAAI,CAACG,KAAKe,MAAM,IAAIc,UAAUC,YACrC9B,KAAKE,SAAS,GACd,GAAGF,KAAKE,SAAS,CAAC,CAAC,EAAE2B,OAAO;YAElC,IAAI7B,KAAKe,MAAM,IAAIU,cAAc,CAAC,GAAGH;YACrC;QACF;QAEA,IAAK,IAAIU,SAAS,GAAGA,SAAST,SAASnB,MAAM,EAAE4B,SAAU;YACvD,MAAMhC,OAAOU,YAAYkB,GAAG,CAAC,CAAC,CAAC,EAAEL,QAAQ,CAACS,OAAO,EAAE;YACnD,IAAI,CAAChC,MAAM,OAAOqB;YAClB,IAAI,CAACrB,KAAKe,MAAM,EAAE;gBAChBM,OAAOU,IAAI,CAAC/B,KAAKE,SAAS;gBAC1B;YACF;YACA,MAAM2B,QAAQN,SAASI,KAAK,CAACK,SAAS;YACtCX,OAAOU,IAAI,CACT/B,KAAKH,MAAM,IAAI,CAACgC,QAAQ7B,KAAKE,SAAS,GAAG,GAAGF,KAAKE,SAAS,CAAC,CAAC,EAAE2B,MAAMI,OAAO,CAAC,MAAM,KAAK;YAEzF,IAAI,CAACJ,OAAOP;YACZ;QACF;IACF;IAEA,OAAOD;AACT"}
@@ -3,6 +3,7 @@ import { mkdir } from 'node:fs/promises';
3
3
  import { dirname } from 'node:path';
4
4
  import { generateTelemetryFilePath } from './generateTelemetryFilePath.js';
5
5
  import { createLogger } from './logger.js';
6
+ import { sanitizeTelemetryEvent, telemetryError } from './sanitizeTelemetryEvent.js';
6
7
  import { telemetryStoreDebug } from './telemetryStoreDebug.js';
7
8
  /**
8
9
  * Creates a file-based telemetry store with cached consent and reliable synchronous I/O.
@@ -29,7 +30,7 @@ import { telemetryStoreDebug } from './telemetryStoreDebug.js';
29
30
  cachedConsent = await options.resolveConsent();
30
31
  telemetryStoreDebug('Cached consent status: %s', cachedConsent.status);
31
32
  } catch (error) {
32
- telemetryStoreDebug('Failed to initialize consent, treating as undetermined: %o', error);
33
+ telemetryStoreDebug('Failed to initialize consent, treating as undetermined: %o', telemetryError(error));
33
34
  cachedConsent = {
34
35
  reason: 'fetchError',
35
36
  status: 'undetermined'
@@ -46,7 +47,7 @@ import { telemetryStoreDebug } from './telemetryStoreDebug.js';
46
47
  });
47
48
  telemetryStoreDebug('Created directory structure for: %s', filePath);
48
49
  } catch (error) {
49
- telemetryStoreDebug('Failed to initialize file path: %o', error);
50
+ telemetryStoreDebug('Failed to initialize file path: %o', telemetryError(error));
50
51
  filePath = null;
51
52
  }
52
53
  };
@@ -65,11 +66,18 @@ import { telemetryStoreDebug } from './telemetryStoreDebug.js';
65
66
  appendFileSync(filePath, JSON.stringify(event) + '\n', 'utf8');
66
67
  telemetryStoreDebug('Successfully wrote event to file: %s', filePath);
67
68
  } catch (error) {
68
- telemetryStoreDebug('Failed to write telemetry event: %o', error);
69
+ telemetryStoreDebug('Failed to write telemetry event: %o', telemetryError(error));
69
70
  // Silent failure - don't break CLI functionality
70
71
  }
71
72
  };
72
- const emit = (event)=>{
73
+ const emit = (input)=>{
74
+ let event;
75
+ try {
76
+ event = sanitizeTelemetryEvent(input);
77
+ } catch {
78
+ telemetryStoreDebug('Skipping an unserializable telemetry event');
79
+ return;
80
+ }
73
81
  if (!initComplete) {
74
82
  telemetryStoreDebug('Init pending, buffering event: %s', event.type);
75
83
  eventBuffer.push(event);
@@ -90,7 +98,7 @@ import { telemetryStoreDebug } from './telemetryStoreDebug.js';
90
98
  for (const [index, result] of results.entries()){
91
99
  if (result.status === 'rejected') {
92
100
  const type = index === 0 ? 'consent' : 'file path';
93
- telemetryStoreDebug('Error initializing %s: %o', type, result.reason);
101
+ telemetryStoreDebug('Error initializing %s: %o', type, telemetryError(result.reason));
94
102
  }
95
103
  }
96
104
  initComplete = true;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/util/telemetry/createTelemetryStore.ts"],"sourcesContent":["import {appendFileSync} from 'node:fs'\nimport {mkdir} from 'node:fs/promises'\nimport {dirname} from 'node:path'\n\nimport {\n type CLITelemetryStore,\n type ConsentInformation,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {type TelemetryEvent} from '@sanity/telemetry'\n\nimport {generateTelemetryFilePath} from './generateTelemetryFilePath.js'\nimport {createLogger} from './logger.js'\nimport {telemetryStoreDebug} from './telemetryStoreDebug.js'\n\n/**\n * FILE MANAGEMENT STRATEGY:\n *\n * The telemetry system uses a multi-file approach to handle concurrent CLI processes:\n *\n * 1. WRITING (per session):\n * - Each CLI session gets a unique file: telemetry-\\{hash\\}-\\{env\\}-\\{sessionId\\}.ndjson\n * - Prevents write conflicts when multiple CLI commands run simultaneously\n * - Events are written using an RxJS queue for ordered processing with retry logic\n *\n * 2. FLUSHING (aggregate all sessions):\n * - findTelemetryFiles() discovers ALL telemetry files for user/environment\n * - Events are collected from all session files and sent as a batch\n * - Files are deleted after successful transmission\n *\n * 3. CLEANUP (background maintenance):\n * - cleanupOldTelemetryFiles() removes stale files older than 7 days\n * - Prevents disk space accumulation from abandoned sessions\n */\n\ninterface CreateTelemetryStoreOptions {\n resolveConsent: () => Promise<ConsentInformation>\n}\n\n/**\n * Creates a file-based telemetry store with cached consent and reliable synchronous I/O.\n *\n * Key optimizations:\n * - Consent resolved once at creation and cached (vs checking on every emit)\n * - File path generated and directory created once during initialization\n * - Synchronous file writes to ensure events are captured even during process exit\n *\n * @param sessionId - Unique session identifier for file isolation\n * @param options - Configuration options\n * @returns TelemetryStore instance compatible with the telemetry interface\n *\n * @internal\n */\nexport function createTelemetryStore(\n sessionId: string,\n options: CreateTelemetryStoreOptions,\n): CLITelemetryStore {\n telemetryStoreDebug('Creating telemetry store with sessionId: %s', sessionId)\n\n let cachedConsent: ConsentInformation | null = null\n let filePath: string | null = null\n let initComplete = false\n const eventBuffer: TelemetryEvent[] = []\n\n const initializeConsent = async () => {\n if (cachedConsent) return\n\n try {\n cachedConsent = await options.resolveConsent()\n telemetryStoreDebug('Cached consent status: %s', cachedConsent.status)\n } catch (error) {\n telemetryStoreDebug('Failed to initialize consent, treating as undetermined: %o', error)\n cachedConsent = {reason: 'fetchError', status: 'undetermined'}\n }\n }\n\n const initializeFilePath = async () => {\n if (filePath) return\n\n try {\n filePath = await generateTelemetryFilePath(sessionId)\n telemetryStoreDebug('Generated file path: %s', filePath)\n\n await mkdir(dirname(filePath), {recursive: true})\n telemetryStoreDebug('Created directory structure for: %s', filePath)\n } catch (error) {\n telemetryStoreDebug('Failed to initialize file path: %o', error)\n filePath = null\n }\n }\n\n const writeEvent = (event: TelemetryEvent) => {\n if (!filePath) {\n telemetryStoreDebug('No file path, skipping event: %s', event.type)\n return\n }\n\n telemetryStoreDebug('Emitting event: %s', event.type)\n\n try {\n // We use synchronous file writes to ensure telemetry events are captured even when\n // the process exits abruptly (process.exit, uncaught exceptions, SIGTERM, etc.).\n // The performance impact is probably negligible and is worth the trade-off\n // for 100% reliability. Async writes would be lost when the event loop\n // shuts down during process exit.\n appendFileSync(filePath, JSON.stringify(event) + '\\n', 'utf8')\n telemetryStoreDebug('Successfully wrote event to file: %s', filePath)\n } catch (error) {\n telemetryStoreDebug('Failed to write telemetry event: %o', error)\n // Silent failure - don't break CLI functionality\n }\n }\n\n const emit = (event: TelemetryEvent) => {\n if (!initComplete) {\n telemetryStoreDebug('Init pending, buffering event: %s', event.type)\n eventBuffer.push(event)\n return\n }\n\n if (!cachedConsent || cachedConsent.status !== 'granted') {\n telemetryStoreDebug(\n 'Consent not granted (%s), skipping event: %s',\n cachedConsent?.status ?? 'unresolved',\n event.type,\n )\n return\n }\n\n writeEvent(event)\n }\n\n const logger = createLogger<TelemetryUserProperties>(sessionId, emit)\n\n // Initialize both consent and file path concurrently\n Promise.allSettled([initializeConsent(), initializeFilePath()]).then((results) => {\n for (const [index, result] of results.entries()) {\n if (result.status === 'rejected') {\n const type = index === 0 ? 'consent' : 'file path'\n telemetryStoreDebug('Error initializing %s: %o', type, result.reason)\n }\n }\n\n initComplete = true\n\n if (cachedConsent?.status === 'granted' && filePath) {\n telemetryStoreDebug('Flushing %d buffered event(s)', eventBuffer.length)\n for (const event of eventBuffer) {\n writeEvent(event)\n }\n } else {\n telemetryStoreDebug(\n 'Discarding %d buffered event(s), consent: %s',\n eventBuffer.length,\n cachedConsent?.status ?? 'unresolved',\n )\n }\n eventBuffer.length = 0\n })\n\n return logger\n}\n"],"names":["appendFileSync","mkdir","dirname","generateTelemetryFilePath","createLogger","telemetryStoreDebug","createTelemetryStore","sessionId","options","cachedConsent","filePath","initComplete","eventBuffer","initializeConsent","resolveConsent","status","error","reason","initializeFilePath","recursive","writeEvent","event","type","JSON","stringify","emit","push","logger","Promise","allSettled","then","results","index","result","entries","length"],"mappings":"AAAA,SAAQA,cAAc,QAAO,UAAS;AACtC,SAAQC,KAAK,QAAO,mBAAkB;AACtC,SAAQC,OAAO,QAAO,YAAW;AASjC,SAAQC,yBAAyB,QAAO,iCAAgC;AACxE,SAAQC,YAAY,QAAO,cAAa;AACxC,SAAQC,mBAAmB,QAAO,2BAA0B;AA0B5D;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASC,qBACdC,SAAiB,EACjBC,OAAoC;IAEpCH,oBAAoB,+CAA+CE;IAEnE,IAAIE,gBAA2C;IAC/C,IAAIC,WAA0B;IAC9B,IAAIC,eAAe;IACnB,MAAMC,cAAgC,EAAE;IAExC,MAAMC,oBAAoB;QACxB,IAAIJ,eAAe;QAEnB,IAAI;YACFA,gBAAgB,MAAMD,QAAQM,cAAc;YAC5CT,oBAAoB,6BAA6BI,cAAcM,MAAM;QACvE,EAAE,OAAOC,OAAO;YACdX,oBAAoB,8DAA8DW;YAClFP,gBAAgB;gBAACQ,QAAQ;gBAAcF,QAAQ;YAAc;QAC/D;IACF;IAEA,MAAMG,qBAAqB;QACzB,IAAIR,UAAU;QAEd,IAAI;YACFA,WAAW,MAAMP,0BAA0BI;YAC3CF,oBAAoB,2BAA2BK;YAE/C,MAAMT,MAAMC,QAAQQ,WAAW;gBAACS,WAAW;YAAI;YAC/Cd,oBAAoB,uCAAuCK;QAC7D,EAAE,OAAOM,OAAO;YACdX,oBAAoB,sCAAsCW;YAC1DN,WAAW;QACb;IACF;IAEA,MAAMU,aAAa,CAACC;QAClB,IAAI,CAACX,UAAU;YACbL,oBAAoB,oCAAoCgB,MAAMC,IAAI;YAClE;QACF;QAEAjB,oBAAoB,sBAAsBgB,MAAMC,IAAI;QAEpD,IAAI;YACF,mFAAmF;YACnF,iFAAiF;YACjF,2EAA2E;YAC3E,uEAAuE;YACvE,kCAAkC;YAClCtB,eAAeU,UAAUa,KAAKC,SAAS,CAACH,SAAS,MAAM;YACvDhB,oBAAoB,wCAAwCK;QAC9D,EAAE,OAAOM,OAAO;YACdX,oBAAoB,uCAAuCW;QAC3D,iDAAiD;QACnD;IACF;IAEA,MAAMS,OAAO,CAACJ;QACZ,IAAI,CAACV,cAAc;YACjBN,oBAAoB,qCAAqCgB,MAAMC,IAAI;YACnEV,YAAYc,IAAI,CAACL;YACjB;QACF;QAEA,IAAI,CAACZ,iBAAiBA,cAAcM,MAAM,KAAK,WAAW;YACxDV,oBACE,gDACAI,eAAeM,UAAU,cACzBM,MAAMC,IAAI;YAEZ;QACF;QAEAF,WAAWC;IACb;IAEA,MAAMM,SAASvB,aAAsCG,WAAWkB;IAEhE,qDAAqD;IACrDG,QAAQC,UAAU,CAAC;QAAChB;QAAqBK;KAAqB,EAAEY,IAAI,CAAC,CAACC;QACpE,KAAK,MAAM,CAACC,OAAOC,OAAO,IAAIF,QAAQG,OAAO,GAAI;YAC/C,IAAID,OAAOlB,MAAM,KAAK,YAAY;gBAChC,MAAMO,OAAOU,UAAU,IAAI,YAAY;gBACvC3B,oBAAoB,6BAA6BiB,MAAMW,OAAOhB,MAAM;YACtE;QACF;QAEAN,eAAe;QAEf,IAAIF,eAAeM,WAAW,aAAaL,UAAU;YACnDL,oBAAoB,iCAAiCO,YAAYuB,MAAM;YACvE,KAAK,MAAMd,SAAST,YAAa;gBAC/BQ,WAAWC;YACb;QACF,OAAO;YACLhB,oBACE,gDACAO,YAAYuB,MAAM,EAClB1B,eAAeM,UAAU;QAE7B;QACAH,YAAYuB,MAAM,GAAG;IACvB;IAEA,OAAOR;AACT"}
1
+ {"version":3,"sources":["../../../src/util/telemetry/createTelemetryStore.ts"],"sourcesContent":["import {appendFileSync} from 'node:fs'\nimport {mkdir} from 'node:fs/promises'\nimport {dirname} from 'node:path'\n\nimport {\n type CLITelemetryStore,\n type ConsentInformation,\n type TelemetryUserProperties,\n} from '@sanity/cli-core'\nimport {type TelemetryEvent} from '@sanity/telemetry'\n\nimport {generateTelemetryFilePath} from './generateTelemetryFilePath.js'\nimport {createLogger} from './logger.js'\nimport {sanitizeTelemetryEvent, telemetryError} from './sanitizeTelemetryEvent.js'\nimport {telemetryStoreDebug} from './telemetryStoreDebug.js'\n\n/**\n * FILE MANAGEMENT STRATEGY:\n *\n * The telemetry system uses a multi-file approach to handle concurrent CLI processes:\n *\n * 1. WRITING (per session):\n * - Each CLI session gets a unique file: telemetry-\\{hash\\}-\\{env\\}-\\{sessionId\\}.ndjson\n * - Prevents write conflicts when multiple CLI commands run simultaneously\n * - Events are written using an RxJS queue for ordered processing with retry logic\n *\n * 2. FLUSHING (aggregate all sessions):\n * - findTelemetryFiles() discovers ALL telemetry files for user/environment\n * - Events are collected from all session files and sent as a batch\n * - Files are deleted after successful transmission\n *\n * 3. CLEANUP (background maintenance):\n * - cleanupOldTelemetryFiles() removes stale files older than 7 days\n * - Prevents disk space accumulation from abandoned sessions\n */\n\ninterface CreateTelemetryStoreOptions {\n resolveConsent: () => Promise<ConsentInformation>\n}\n\n/**\n * Creates a file-based telemetry store with cached consent and reliable synchronous I/O.\n *\n * Key optimizations:\n * - Consent resolved once at creation and cached (vs checking on every emit)\n * - File path generated and directory created once during initialization\n * - Synchronous file writes to ensure events are captured even during process exit\n *\n * @param sessionId - Unique session identifier for file isolation\n * @param options - Configuration options\n * @returns TelemetryStore instance compatible with the telemetry interface\n *\n * @internal\n */\nexport function createTelemetryStore(\n sessionId: string,\n options: CreateTelemetryStoreOptions,\n): CLITelemetryStore {\n telemetryStoreDebug('Creating telemetry store with sessionId: %s', sessionId)\n\n let cachedConsent: ConsentInformation | null = null\n let filePath: string | null = null\n let initComplete = false\n const eventBuffer: TelemetryEvent[] = []\n\n const initializeConsent = async () => {\n if (cachedConsent) return\n\n try {\n cachedConsent = await options.resolveConsent()\n telemetryStoreDebug('Cached consent status: %s', cachedConsent.status)\n } catch (error) {\n telemetryStoreDebug(\n 'Failed to initialize consent, treating as undetermined: %o',\n telemetryError(error),\n )\n cachedConsent = {reason: 'fetchError', status: 'undetermined'}\n }\n }\n\n const initializeFilePath = async () => {\n if (filePath) return\n\n try {\n filePath = await generateTelemetryFilePath(sessionId)\n telemetryStoreDebug('Generated file path: %s', filePath)\n\n await mkdir(dirname(filePath), {recursive: true})\n telemetryStoreDebug('Created directory structure for: %s', filePath)\n } catch (error) {\n telemetryStoreDebug('Failed to initialize file path: %o', telemetryError(error))\n filePath = null\n }\n }\n\n const writeEvent = (event: TelemetryEvent) => {\n if (!filePath) {\n telemetryStoreDebug('No file path, skipping event: %s', event.type)\n return\n }\n\n telemetryStoreDebug('Emitting event: %s', event.type)\n\n try {\n // We use synchronous file writes to ensure telemetry events are captured even when\n // the process exits abruptly (process.exit, uncaught exceptions, SIGTERM, etc.).\n // The performance impact is probably negligible and is worth the trade-off\n // for 100% reliability. Async writes would be lost when the event loop\n // shuts down during process exit.\n appendFileSync(filePath, JSON.stringify(event) + '\\n', 'utf8')\n telemetryStoreDebug('Successfully wrote event to file: %s', filePath)\n } catch (error) {\n telemetryStoreDebug('Failed to write telemetry event: %o', telemetryError(error))\n // Silent failure - don't break CLI functionality\n }\n }\n\n const emit = (input: TelemetryEvent) => {\n let event: TelemetryEvent\n try {\n event = sanitizeTelemetryEvent(input)\n } catch {\n telemetryStoreDebug('Skipping an unserializable telemetry event')\n return\n }\n if (!initComplete) {\n telemetryStoreDebug('Init pending, buffering event: %s', event.type)\n eventBuffer.push(event)\n return\n }\n\n if (!cachedConsent || cachedConsent.status !== 'granted') {\n telemetryStoreDebug(\n 'Consent not granted (%s), skipping event: %s',\n cachedConsent?.status ?? 'unresolved',\n event.type,\n )\n return\n }\n\n writeEvent(event)\n }\n\n const logger = createLogger<TelemetryUserProperties>(sessionId, emit)\n\n // Initialize both consent and file path concurrently\n Promise.allSettled([initializeConsent(), initializeFilePath()]).then((results) => {\n for (const [index, result] of results.entries()) {\n if (result.status === 'rejected') {\n const type = index === 0 ? 'consent' : 'file path'\n telemetryStoreDebug('Error initializing %s: %o', type, telemetryError(result.reason))\n }\n }\n\n initComplete = true\n\n if (cachedConsent?.status === 'granted' && filePath) {\n telemetryStoreDebug('Flushing %d buffered event(s)', eventBuffer.length)\n for (const event of eventBuffer) {\n writeEvent(event)\n }\n } else {\n telemetryStoreDebug(\n 'Discarding %d buffered event(s), consent: %s',\n eventBuffer.length,\n cachedConsent?.status ?? 'unresolved',\n )\n }\n eventBuffer.length = 0\n })\n\n return logger\n}\n"],"names":["appendFileSync","mkdir","dirname","generateTelemetryFilePath","createLogger","sanitizeTelemetryEvent","telemetryError","telemetryStoreDebug","createTelemetryStore","sessionId","options","cachedConsent","filePath","initComplete","eventBuffer","initializeConsent","resolveConsent","status","error","reason","initializeFilePath","recursive","writeEvent","event","type","JSON","stringify","emit","input","push","logger","Promise","allSettled","then","results","index","result","entries","length"],"mappings":"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"}