@formo/cli 0.1.0 → 1.0.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/README.md +328 -44
- package/dist/commands/alerts.d.ts +1 -0
- package/dist/commands/alerts.js +11 -30
- package/dist/commands/analytics.d.ts +25 -0
- package/dist/commands/analytics.js +153 -0
- package/dist/commands/contracts.d.ts +12 -0
- package/dist/commands/contracts.js +18 -10
- package/dist/commands/import.d.ts +4 -0
- package/dist/commands/import.js +9 -5
- package/dist/commands/profiles.d.ts +29 -2
- package/dist/commands/profiles.js +257 -25
- package/dist/commands/query.d.ts +2 -0
- package/dist/commands/query.js +25 -0
- package/dist/commands/segments.d.ts +4 -0
- package/dist/commands/segments.js +10 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +117 -132
- package/dist/lib/client.d.ts +26 -0
- package/dist/lib/client.js +30 -7
- package/package.json +11 -2
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.profiles = void 0;
|
|
3
|
+
exports.profilesLabels = exports.profiles = void 0;
|
|
4
4
|
exports.getProfileRun = getProfileRun;
|
|
5
|
+
exports.parseSearchConditions = parseSearchConditions;
|
|
5
6
|
exports.searchProfilesRun = searchProfilesRun;
|
|
7
|
+
exports.buildUpdateProfileBody = buildUpdateProfileBody;
|
|
8
|
+
exports.updateProfileRun = updateProfileRun;
|
|
9
|
+
exports.buildCreateLabelBody = buildCreateLabelBody;
|
|
10
|
+
exports.createProfileLabelRun = createProfileLabelRun;
|
|
11
|
+
exports.buildDeleteLabelBody = buildDeleteLabelBody;
|
|
12
|
+
exports.deleteProfileLabelRun = deleteProfileLabelRun;
|
|
6
13
|
const incur_1 = require("incur");
|
|
7
14
|
const client_1 = require("../lib/client");
|
|
8
15
|
exports.profiles = incur_1.Cli.create('profiles', {
|
|
@@ -35,20 +42,70 @@ exports.profiles.command('get', {
|
|
|
35
42
|
description: 'Get profile with expanded labels and chains',
|
|
36
43
|
},
|
|
37
44
|
],
|
|
45
|
+
hint: 'Requires profiles:read scope on your API key.',
|
|
38
46
|
run({ args, options }) {
|
|
39
47
|
return getProfileRun(args.address, options.expand);
|
|
40
48
|
},
|
|
41
49
|
});
|
|
50
|
+
// Accepted first segments for a FilterCondition `field`, mirroring the API's
|
|
51
|
+
// parseField(). A field whose prefix is not one of these is silently ignored
|
|
52
|
+
// server-side (no error, no filtering — the search returns everything), so we
|
|
53
|
+
// reject it client-side with an actionable message instead.
|
|
54
|
+
const CONDITION_FIELD_PREFIXES = new Set([
|
|
55
|
+
'user',
|
|
56
|
+
'users',
|
|
57
|
+
'chain',
|
|
58
|
+
'chains',
|
|
59
|
+
'app',
|
|
60
|
+
'apps',
|
|
61
|
+
'token',
|
|
62
|
+
'tokens',
|
|
63
|
+
'label',
|
|
64
|
+
'labels',
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Parse and validate the --conditions JSON. Ensures it is an array of
|
|
68
|
+
* `{ field, op, value }` objects whose `field` is a typed path (e.g.
|
|
69
|
+
* `users.net_worth_usd`) — a bare name like `net_worth_usd` is silently
|
|
70
|
+
* dropped by the API, so it is rejected here. Exported for unit testing.
|
|
71
|
+
*/
|
|
72
|
+
function parseSearchConditions(raw) {
|
|
73
|
+
let parsed;
|
|
74
|
+
try {
|
|
75
|
+
parsed = JSON.parse(raw);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
throw new Error('--conditions must be a valid JSON array of FilterCondition objects');
|
|
79
|
+
}
|
|
80
|
+
if (!Array.isArray(parsed)) {
|
|
81
|
+
throw new Error('--conditions must be a valid JSON array of FilterCondition objects');
|
|
82
|
+
}
|
|
83
|
+
for (const cond of parsed) {
|
|
84
|
+
if (!cond || typeof cond !== 'object' || Array.isArray(cond)) {
|
|
85
|
+
throw new Error('--conditions: each entry must be an object with field, op, value');
|
|
86
|
+
}
|
|
87
|
+
const field = cond.field;
|
|
88
|
+
if (typeof field !== 'string' || field.length === 0) {
|
|
89
|
+
throw new Error('--conditions: each entry must have a non-empty string "field"');
|
|
90
|
+
}
|
|
91
|
+
if (!field.includes('.') || !CONDITION_FIELD_PREFIXES.has(field.split('.')[0])) {
|
|
92
|
+
throw new Error(`--conditions: field "${field}" must be a typed path — prefix it with ` +
|
|
93
|
+
'users., chains., apps., tokens., or labels. ' +
|
|
94
|
+
'(a bare name is silently ignored by the API and returns the entire unfiltered dataset)');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return parsed;
|
|
98
|
+
}
|
|
42
99
|
function searchProfilesRun(options) {
|
|
43
100
|
(0, client_1.requireApiKey)();
|
|
44
101
|
const client = (0, client_1.createClient)();
|
|
45
102
|
const params = {};
|
|
46
103
|
if (options.address)
|
|
47
104
|
params.address = options.address;
|
|
48
|
-
if (options.
|
|
49
|
-
params.
|
|
50
|
-
if (options.
|
|
51
|
-
params.
|
|
105
|
+
if (options.page !== undefined)
|
|
106
|
+
params.page = options.page;
|
|
107
|
+
if (options.size !== undefined)
|
|
108
|
+
params.size = options.size;
|
|
52
109
|
if (options.orderBy)
|
|
53
110
|
params.order_by = options.orderBy;
|
|
54
111
|
if (options.orderDir)
|
|
@@ -57,15 +114,10 @@ function searchProfilesRun(options) {
|
|
|
57
114
|
params.expand = options.expand;
|
|
58
115
|
let body;
|
|
59
116
|
if (options.conditions) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
body = { conditions, logic: options.logic ?? 'and' };
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
throw new Error('--conditions must be valid JSON array of FilterCondition objects');
|
|
68
|
-
}
|
|
117
|
+
body = {
|
|
118
|
+
conditions: parseSearchConditions(options.conditions),
|
|
119
|
+
logic: options.logic ?? 'and',
|
|
120
|
+
};
|
|
69
121
|
}
|
|
70
122
|
return client.request({ method: 'get', url: '/v0/profiles/', params, data: body });
|
|
71
123
|
}
|
|
@@ -73,8 +125,8 @@ exports.profiles.command('search', {
|
|
|
73
125
|
description: 'Search wallet profiles with optional filters',
|
|
74
126
|
options: incur_1.z.object({
|
|
75
127
|
address: incur_1.z.string().optional().describe('Filter by wallet address'),
|
|
76
|
-
|
|
77
|
-
|
|
128
|
+
page: incur_1.z.coerce.number().optional().describe('Page number (1-indexed, default 1)'),
|
|
129
|
+
size: incur_1.z.coerce.number().optional().describe('Page size (default 100, max 1000)'),
|
|
78
130
|
orderBy: incur_1.z
|
|
79
131
|
.enum([
|
|
80
132
|
'last_onchain',
|
|
@@ -96,35 +148,215 @@ exports.profiles.command('search', {
|
|
|
96
148
|
conditions: incur_1.z
|
|
97
149
|
.string()
|
|
98
150
|
.optional()
|
|
99
|
-
.describe('JSON array of FilterCondition objects
|
|
151
|
+
.describe('JSON array of FilterCondition objects: [{"field","op","value"}]. ' +
|
|
152
|
+
'The "field" MUST be a typed path — a bare name like "net_worth_usd" is silently ignored. ' +
|
|
153
|
+
'Profile: users.net_worth_usd, users.volume, users.revenue, users.points. ' +
|
|
154
|
+
'Engagement: users.device, users.browser, users.os, users.location, users.lifecycle. ' +
|
|
155
|
+
'Socials: users.ens, users.farcaster, users.lens, etc. ' +
|
|
156
|
+
'Chains: chains.balance or chains.{chain_id}.balance. ' +
|
|
157
|
+
'Apps: apps.{app_id}.balance. Tokens: tokens.{address}.balance ' +
|
|
158
|
+
'(optional "scope":"any"|"protocol" + "appId"). Labels: labels.{tag_id}. ' +
|
|
159
|
+
'op: eq, neq, gt, gte, lt, lte, in, nin.'),
|
|
100
160
|
logic: incur_1.z
|
|
101
161
|
.enum(['and', 'or'])
|
|
102
162
|
.optional()
|
|
103
163
|
.describe('Logic operator for combining conditions: "and" (default) or "or"'),
|
|
104
164
|
}),
|
|
105
165
|
examples: [
|
|
106
|
-
{ options: {
|
|
166
|
+
{ options: { size: 10 }, description: 'List first 10 profiles' },
|
|
107
167
|
{
|
|
108
|
-
options: { orderBy: 'net_worth_usd', orderDir: 'desc',
|
|
168
|
+
options: { orderBy: 'net_worth_usd', orderDir: 'desc', size: 5 },
|
|
109
169
|
description: 'Top 5 profiles by net worth',
|
|
110
170
|
},
|
|
171
|
+
{
|
|
172
|
+
options: { page: 2, size: 20 },
|
|
173
|
+
description: 'Get the second page of 20 profiles',
|
|
174
|
+
},
|
|
111
175
|
{
|
|
112
176
|
options: {
|
|
113
|
-
conditions: '[{"field":"net_worth_usd","op":"gt","value":10000}]',
|
|
114
|
-
|
|
177
|
+
conditions: '[{"field":"users.net_worth_usd","op":"gt","value":10000}]',
|
|
178
|
+
size: 20,
|
|
115
179
|
},
|
|
116
|
-
description: 'Search profiles with net worth >
|
|
180
|
+
description: 'Search profiles with net worth > $10k',
|
|
117
181
|
},
|
|
118
182
|
{
|
|
119
183
|
options: {
|
|
120
|
-
conditions: '[{"field":"net_worth_usd","op":"gt","value":10000},{"field":"
|
|
184
|
+
conditions: '[{"field":"users.net_worth_usd","op":"gt","value":10000},{"field":"users.volume","op":"gt","value":1000}]',
|
|
121
185
|
logic: 'or',
|
|
122
|
-
|
|
186
|
+
size: 20,
|
|
187
|
+
},
|
|
188
|
+
description: 'Search profiles matching either condition (net worth or volume)',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
options: {
|
|
192
|
+
conditions: '[{"field":"chains.1.balance","op":"gt","value":1000}]',
|
|
193
|
+
size: 20,
|
|
123
194
|
},
|
|
124
|
-
description: 'Search profiles
|
|
195
|
+
description: 'Search profiles with > $1k balance on Ethereum (chain 1)',
|
|
125
196
|
},
|
|
126
197
|
],
|
|
198
|
+
hint: 'Requires profiles:read scope on your API key. Filter "field" must be a typed path (e.g. users.net_worth_usd) — bare names are ignored by the API.',
|
|
127
199
|
run({ args: _args, options }) {
|
|
128
200
|
return searchProfilesRun(options);
|
|
129
201
|
},
|
|
130
202
|
});
|
|
203
|
+
function buildUpdateProfileBody(options) {
|
|
204
|
+
let body;
|
|
205
|
+
try {
|
|
206
|
+
body = JSON.parse(options.properties);
|
|
207
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
208
|
+
throw new Error('not an object');
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
throw new Error('--properties must be a JSON object of property keys');
|
|
212
|
+
}
|
|
213
|
+
if (Object.keys(body).length === 0) {
|
|
214
|
+
throw new Error('--properties must contain at least one key');
|
|
215
|
+
}
|
|
216
|
+
return body;
|
|
217
|
+
}
|
|
218
|
+
function updateProfileRun(address, options) {
|
|
219
|
+
(0, client_1.requireApiKey)();
|
|
220
|
+
const client = (0, client_1.createClient)();
|
|
221
|
+
return client.put(`/v0/profiles/${encodeURIComponent(address)}/properties`, buildUpdateProfileBody(options));
|
|
222
|
+
}
|
|
223
|
+
exports.profiles.command('update', {
|
|
224
|
+
description: 'Merge-update identity properties on a wallet profile',
|
|
225
|
+
args: incur_1.z.object({
|
|
226
|
+
address: incur_1.z.string().describe('Wallet address (0x... or ENS name)'),
|
|
227
|
+
}),
|
|
228
|
+
options: incur_1.z.object({
|
|
229
|
+
properties: incur_1.z
|
|
230
|
+
.string()
|
|
231
|
+
.describe('JSON object of properties to merge. Allowed keys: user_id, display_name, email, farcaster, discord, twitter, telegram, instagram, website, github, linkedin, facebook, tiktok, youtube, reddit, avatar, description, location, ens, lens, basenames, linea'),
|
|
232
|
+
}),
|
|
233
|
+
examples: [
|
|
234
|
+
{
|
|
235
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
236
|
+
options: {
|
|
237
|
+
properties: '{"display_name":"Vitalik","twitter":"VitalikButerin"}',
|
|
238
|
+
},
|
|
239
|
+
description: 'Set display name and Twitter handle',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
243
|
+
options: { properties: '{"email":"alice@example.com"}' },
|
|
244
|
+
description: 'Set just the email',
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
hint: 'Requires profiles:write scope on your API key. Only the listed keys are accepted; unknown keys are rejected.',
|
|
248
|
+
run({ args, options }) {
|
|
249
|
+
return updateProfileRun(args.address, options);
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
// ── Labels sub-resource ──
|
|
253
|
+
exports.profilesLabels = incur_1.Cli.create('labels', {
|
|
254
|
+
description: 'Manage labels on a wallet profile',
|
|
255
|
+
});
|
|
256
|
+
function buildCreateLabelBody(options) {
|
|
257
|
+
if (options.labels) {
|
|
258
|
+
try {
|
|
259
|
+
const parsed = JSON.parse(options.labels);
|
|
260
|
+
if (!Array.isArray(parsed) || parsed.length === 0)
|
|
261
|
+
throw new Error('not a non-empty array');
|
|
262
|
+
return parsed;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
throw new Error('--labels must be a non-empty JSON array of UserLabelInput objects');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (options.tagId) {
|
|
269
|
+
const single = { tag_id: options.tagId };
|
|
270
|
+
if (options.value)
|
|
271
|
+
single.value = options.value;
|
|
272
|
+
if (options.chainId)
|
|
273
|
+
single.chain_id = options.chainId;
|
|
274
|
+
return single;
|
|
275
|
+
}
|
|
276
|
+
throw new Error('Provide --tag-id (single label) or --labels (batch JSON array)');
|
|
277
|
+
}
|
|
278
|
+
function createProfileLabelRun(address, options) {
|
|
279
|
+
(0, client_1.requireApiKey)();
|
|
280
|
+
const client = (0, client_1.createClient)();
|
|
281
|
+
return client.post(`/v0/profiles/${encodeURIComponent(address)}/labels`, buildCreateLabelBody(options));
|
|
282
|
+
}
|
|
283
|
+
exports.profilesLabels.command('create', {
|
|
284
|
+
description: 'Upsert one or more labels on a wallet profile',
|
|
285
|
+
args: incur_1.z.object({
|
|
286
|
+
address: incur_1.z.string().describe('Wallet address (0x... or ENS name)'),
|
|
287
|
+
}),
|
|
288
|
+
options: incur_1.z.object({
|
|
289
|
+
tagId: incur_1.z
|
|
290
|
+
.string()
|
|
291
|
+
.optional()
|
|
292
|
+
.describe('Label identifier (e.g. "vip", "airdrop_eligible")'),
|
|
293
|
+
value: incur_1.z.string().optional().describe('Optional label value (e.g. tier name, country code)'),
|
|
294
|
+
chainId: incur_1.z.string().optional().describe('Optional chain identifier the label applies to'),
|
|
295
|
+
labels: incur_1.z
|
|
296
|
+
.string()
|
|
297
|
+
.optional()
|
|
298
|
+
.describe('JSON array of UserLabelInput objects for batch upsert'),
|
|
299
|
+
}),
|
|
300
|
+
examples: [
|
|
301
|
+
{
|
|
302
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
303
|
+
options: { tagId: 'vip' },
|
|
304
|
+
description: 'Tag a wallet as VIP',
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
308
|
+
options: { tagId: 'tier', value: 'gold', chainId: '1' },
|
|
309
|
+
description: 'Apply a tiered label scoped to a chain',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
313
|
+
options: { labels: '[{"tag_id":"vip"},{"tag_id":"airdrop_eligible","chain_id":"1"}]' },
|
|
314
|
+
description: 'Apply multiple labels in one call',
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
hint: 'Requires profiles:write scope on your API key.',
|
|
318
|
+
run({ args, options }) {
|
|
319
|
+
return createProfileLabelRun(args.address, options);
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
function buildDeleteLabelBody(options) {
|
|
323
|
+
if (!options.tagId) {
|
|
324
|
+
throw new Error('--tag-id is required');
|
|
325
|
+
}
|
|
326
|
+
const body = { tag_id: options.tagId };
|
|
327
|
+
if (options.chainId)
|
|
328
|
+
body.chain_id = options.chainId;
|
|
329
|
+
return body;
|
|
330
|
+
}
|
|
331
|
+
function deleteProfileLabelRun(address, options) {
|
|
332
|
+
(0, client_1.requireApiKey)();
|
|
333
|
+
const client = (0, client_1.createClient)();
|
|
334
|
+
return client.delete(`/v0/profiles/${encodeURIComponent(address)}/labels`, { data: buildDeleteLabelBody(options) });
|
|
335
|
+
}
|
|
336
|
+
exports.profilesLabels.command('delete', {
|
|
337
|
+
description: 'Delete a label from a wallet profile',
|
|
338
|
+
args: incur_1.z.object({
|
|
339
|
+
address: incur_1.z.string().describe('Wallet address (0x... or ENS name)'),
|
|
340
|
+
}),
|
|
341
|
+
options: incur_1.z.object({
|
|
342
|
+
tagId: incur_1.z.string().describe('Label identifier to delete'),
|
|
343
|
+
chainId: incur_1.z.string().optional().describe('Optional chain identifier to scope the deletion'),
|
|
344
|
+
}),
|
|
345
|
+
examples: [
|
|
346
|
+
{
|
|
347
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
348
|
+
options: { tagId: 'vip' },
|
|
349
|
+
description: 'Remove the vip label',
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
args: { address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' },
|
|
353
|
+
options: { tagId: 'tier', chainId: '1' },
|
|
354
|
+
description: 'Remove a chain-scoped label',
|
|
355
|
+
},
|
|
356
|
+
],
|
|
357
|
+
hint: 'Requires profiles:write scope on your API key.',
|
|
358
|
+
run({ args, options }) {
|
|
359
|
+
return deleteProfileLabelRun(args.address, options);
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
exports.profiles.command(exports.profilesLabels);
|
package/dist/commands/query.d.ts
CHANGED
package/dist/commands/query.js
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.query = void 0;
|
|
3
4
|
exports.queryRunRun = queryRunRun;
|
|
5
|
+
const incur_1 = require("incur");
|
|
4
6
|
const client_1 = require("../lib/client");
|
|
7
|
+
exports.query = incur_1.Cli.create('query', {
|
|
8
|
+
description: 'SQL analytics query commands',
|
|
9
|
+
});
|
|
5
10
|
function queryRunRun(sql) {
|
|
6
11
|
(0, client_1.requireApiKey)();
|
|
7
12
|
const client = (0, client_1.createClient)();
|
|
8
13
|
return client.post('/v0/query/', { query: sql });
|
|
9
14
|
}
|
|
15
|
+
exports.query.command('run', {
|
|
16
|
+
description: 'Run a SQL query against your Formo analytics data',
|
|
17
|
+
args: incur_1.z.object({
|
|
18
|
+
sql: incur_1.z.string().describe('SQL query string to execute'),
|
|
19
|
+
}),
|
|
20
|
+
examples: [
|
|
21
|
+
{
|
|
22
|
+
args: { sql: 'SELECT count(*) FROM events' },
|
|
23
|
+
description: 'Count all events',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
args: { sql: 'SELECT address, net_worth_usd FROM wallet_profiles ORDER BY net_worth_usd DESC LIMIT 10' },
|
|
27
|
+
description: 'Top 10 wallets by net worth',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
hint: 'Requires query:read scope on your API key.',
|
|
31
|
+
run({ args }) {
|
|
32
|
+
return queryRunRun(args.sql);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
@@ -5,5 +5,9 @@ export interface CreateSegmentOptions {
|
|
|
5
5
|
title: string;
|
|
6
6
|
filterSets: string;
|
|
7
7
|
}
|
|
8
|
+
export declare function buildCreateSegmentBody(options: CreateSegmentOptions): {
|
|
9
|
+
title: string;
|
|
10
|
+
filterSets: unknown;
|
|
11
|
+
};
|
|
8
12
|
export declare function createSegmentRun(options: CreateSegmentOptions): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
9
13
|
export declare function deleteSegmentRun(segmentId: string): Promise<import("axios").AxiosResponse<any, any, {}>>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.segments = void 0;
|
|
4
4
|
exports.listSegmentsRun = listSegmentsRun;
|
|
5
|
+
exports.buildCreateSegmentBody = buildCreateSegmentBody;
|
|
5
6
|
exports.createSegmentRun = createSegmentRun;
|
|
6
7
|
exports.deleteSegmentRun = deleteSegmentRun;
|
|
7
8
|
const incur_1 = require("incur");
|
|
@@ -23,20 +24,23 @@ exports.segments.command('list', {
|
|
|
23
24
|
return listSegmentsRun();
|
|
24
25
|
},
|
|
25
26
|
});
|
|
26
|
-
function
|
|
27
|
-
(0, client_1.requireApiKey)();
|
|
28
|
-
const client = (0, client_1.createClient)();
|
|
27
|
+
function buildCreateSegmentBody(options) {
|
|
29
28
|
let parsedFilterSets;
|
|
30
29
|
try {
|
|
31
30
|
parsedFilterSets = JSON.parse(options.filterSets);
|
|
32
31
|
}
|
|
33
32
|
catch {
|
|
34
|
-
throw new Error('--
|
|
33
|
+
throw new Error('--filter-sets must be a valid JSON array');
|
|
35
34
|
}
|
|
36
|
-
return
|
|
35
|
+
return {
|
|
37
36
|
title: options.title,
|
|
38
37
|
filterSets: parsedFilterSets,
|
|
39
|
-
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function createSegmentRun(options) {
|
|
41
|
+
(0, client_1.requireApiKey)();
|
|
42
|
+
const client = (0, client_1.createClient)();
|
|
43
|
+
return client.post('/v0/segments/', buildCreateSegmentBody(options));
|
|
40
44
|
}
|
|
41
45
|
exports.segments.command('create', {
|
|
42
46
|
description: 'Create a new user segment',
|
package/dist/index.d.ts
CHANGED