@formant/formant-cli 0.1.0 → 0.3.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 (56) hide show
  1. package/README.md +380 -116
  2. package/dist/base-command.d.ts +5 -0
  3. package/dist/base-command.js +9 -0
  4. package/dist/base-command.js.map +1 -1
  5. package/dist/commands/devices/create.d.ts +13 -0
  6. package/dist/commands/devices/create.js +62 -0
  7. package/dist/commands/devices/create.js.map +1 -0
  8. package/dist/commands/devices/delete.d.ts +10 -0
  9. package/dist/commands/devices/delete.js +49 -0
  10. package/dist/commands/devices/delete.js.map +1 -0
  11. package/dist/commands/devices/rename.d.ts +11 -0
  12. package/dist/commands/devices/rename.js +42 -0
  13. package/dist/commands/devices/rename.js.map +1 -0
  14. package/dist/commands/devices/tag.d.ts +13 -0
  15. package/dist/commands/devices/tag.js +69 -0
  16. package/dist/commands/devices/tag.js.map +1 -0
  17. package/dist/commands/devices/untag.d.ts +13 -0
  18. package/dist/commands/devices/untag.js +79 -0
  19. package/dist/commands/devices/untag.js.map +1 -0
  20. package/dist/commands/ingest/batch.d.ts +21 -0
  21. package/dist/commands/ingest/batch.js +170 -0
  22. package/dist/commands/ingest/batch.js.map +1 -0
  23. package/dist/commands/ingest/bitset.d.ts +15 -0
  24. package/dist/commands/ingest/bitset.js +128 -0
  25. package/dist/commands/ingest/bitset.js.map +1 -0
  26. package/dist/commands/ingest/health.d.ts +15 -0
  27. package/dist/commands/ingest/health.js +94 -0
  28. package/dist/commands/ingest/health.js.map +1 -0
  29. package/dist/commands/ingest/image.d.ts +15 -0
  30. package/dist/commands/ingest/image.js +99 -0
  31. package/dist/commands/ingest/image.js.map +1 -0
  32. package/dist/commands/ingest/json.d.ts +16 -0
  33. package/dist/commands/ingest/json.js +92 -0
  34. package/dist/commands/ingest/json.js.map +1 -0
  35. package/dist/commands/ingest/numeric.d.ts +16 -0
  36. package/dist/commands/ingest/numeric.js +83 -0
  37. package/dist/commands/ingest/numeric.js.map +1 -0
  38. package/dist/commands/ingest/text.d.ts +16 -0
  39. package/dist/commands/ingest/text.js +80 -0
  40. package/dist/commands/ingest/text.js.map +1 -0
  41. package/dist/commands/ingest/video.d.ts +16 -0
  42. package/dist/commands/ingest/video.js +120 -0
  43. package/dist/commands/ingest/video.js.map +1 -0
  44. package/dist/commands/org/get.d.ts +7 -0
  45. package/dist/commands/org/get.js +54 -0
  46. package/dist/commands/org/get.js.map +1 -0
  47. package/dist/commands/org/update.d.ts +11 -0
  48. package/dist/commands/org/update.js +75 -0
  49. package/dist/commands/org/update.js.map +1 -0
  50. package/dist/help.js +103 -53
  51. package/dist/help.js.map +1 -1
  52. package/dist/lib/api.d.ts +1 -1
  53. package/dist/lib/api.js +3 -0
  54. package/dist/lib/api.js.map +1 -1
  55. package/oclif.manifest.json +1861 -612
  56. package/package.json +7 -1
@@ -1,5 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import { apiRequest } from './lib/api.js';
3
+ import { login } from './lib/auth.js';
3
4
  /**
4
5
  * Abstract base command for all fcli commands.
5
6
  * Provides global --env flag, --json support, and authenticated API helpers.
@@ -47,6 +48,14 @@ export class BaseCommand extends Command {
47
48
  async api(target, path, options) {
48
49
  return apiRequest(this.env, target, path, options);
49
50
  }
51
+ /**
52
+ * Get the organization ID from the authenticated session.
53
+ * Uses the cached login token so no extra network call if already authenticated.
54
+ */
55
+ async getOrgId() {
56
+ const auth = await login(this.env);
57
+ return auth.organizationId;
58
+ }
50
59
  async catch(err) {
51
60
  throw err;
52
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,KAAK,EAAa,MAAM,aAAa,CAAA;AAEtD,OAAO,EAAiB,UAAU,EAAC,MAAM,cAAc,CAAA;AAQvD;;;GAGG;AACH,MAAM,OAAgB,WAAsC,SAAQ,OAAO;IACzE,MAAM,CAAC,cAAc,GAAG,IAAI,CAAA;IAE5B,MAAM,CAAC,SAAS,GAAG;QACjB,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;YACjB,WAAW,EAAE,4BAA4B;YACzC,SAAS,EAAE,CAAC,OAAO,CAAC;YACpB,SAAS,EAAE,QAAQ;SACpB,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,WAAW,EAAE,8BAA8B;YAC3C,SAAS,EAAE,CAAC,KAAK,CAAC;YAClB,SAAS,EAAE,QAAQ;SACpB,CAAC;KACH,CAAA;IAES,KAAK,CAAmB;IACxB,IAAI,CAAkB;IAEhC,2DAA2D;IAC3D,IAAc,GAAG;QACf,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO,KAAK,CAAA;QAChC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,OAAO,OAAO,CAAA;QACpC,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;QAClB,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;YACrC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;YACpB,SAAS,EAAG,KAAK,CAAC,IAA2B,CAAC,SAAS;YACvD,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK;YACtB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;SACzB,CAAC,CAAA;QAEF,IAAI,CAAC,KAAK,GAAG,KAAyB,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,IAAuB,CAAA;IACrC,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,GAAG,CACjB,MAAiB,EACjB,IAAY,EACZ,OAAgH;QAEhH,OAAO,UAAU,CAAI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IACvD,CAAC;IAEkB,KAAK,CAAC,KAAK,CAAC,GAAgC;QAC7D,MAAM,GAAG,CAAA;IACX,CAAC;IAED;;;OAGG;IACO,iBAAiB,CAAC,OAAe;QACzC,2EAA2E;QAC3E,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,2DAA2D;QAC3D,OAAO,GAAG,OAAO,YAAY,CAAA;IAC/B,CAAC"}
1
+ {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,KAAK,EAAa,MAAM,aAAa,CAAA;AAEtD,OAAO,EAAiB,UAAU,EAAC,MAAM,cAAc,CAAA;AACvD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAA;AAQnC;;;GAGG;AACH,MAAM,OAAgB,WAAsC,SAAQ,OAAO;IACzE,MAAM,CAAC,cAAc,GAAG,IAAI,CAAA;IAE5B,MAAM,CAAC,SAAS,GAAG;QACjB,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;YACjB,WAAW,EAAE,4BAA4B;YACzC,SAAS,EAAE,CAAC,OAAO,CAAC;YACpB,SAAS,EAAE,QAAQ;SACpB,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,WAAW,EAAE,8BAA8B;YAC3C,SAAS,EAAE,CAAC,KAAK,CAAC;YAClB,SAAS,EAAE,QAAQ;SACpB,CAAC;KACH,CAAA;IAES,KAAK,CAAmB;IACxB,IAAI,CAAkB;IAEhC,2DAA2D;IAC3D,IAAc,GAAG;QACf,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG;YAAE,OAAO,KAAK,CAAA;QAChC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK;YAAE,OAAO,OAAO,CAAA;QACpC,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;QAClB,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;YACrC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;YACpB,SAAS,EAAG,KAAK,CAAC,IAA2B,CAAC,SAAS;YACvD,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK;YACtB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;SACzB,CAAC,CAAA;QAEF,IAAI,CAAC,KAAK,GAAG,KAAyB,CAAA;QACtC,IAAI,CAAC,IAAI,GAAG,IAAuB,CAAA;IACrC,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,GAAG,CACjB,MAAiB,EACjB,IAAY,EACZ,OAAgH;QAEhH,OAAO,UAAU,CAAI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IACvD,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,QAAQ;QACtB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAClC,OAAO,IAAI,CAAC,cAAc,CAAA;IAC5B,CAAC;IAEkB,KAAK,CAAC,KAAK,CAAC,GAAgC;QAC7D,MAAM,GAAG,CAAA;IACX,CAAC;IAED;;;OAGG;IACO,iBAAiB,CAAC,OAAe;QACzC,2EAA2E;QAC3E,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,2DAA2D;QAC3D,OAAO,GAAG,OAAO,YAAY,CAAA;IAC/B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DevicesCreate extends BaseCommand<typeof DevicesCreate> {
3
+ static args: {
4
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ tag: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ static summary: string;
12
+ run(): Promise<Record<string, unknown>>;
13
+ }
@@ -0,0 +1,62 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatDetail } from '../../lib/formatters.js';
4
+ export default class DevicesCreate extends BaseCommand {
5
+ static args = {
6
+ name: Args.string({ description: 'Name for the new device', required: true }),
7
+ };
8
+ static description = `Create a new device in your fleet.
9
+
10
+ The device is created as enabled by default. You can optionally specify tags.`;
11
+ static examples = [
12
+ '<%= config.bin %> devices create my-robot',
13
+ '<%= config.bin %> devices create my-robot --tag location=warehouse --tag env=prod',
14
+ '<%= config.bin %> devices create my-robot --json',
15
+ ];
16
+ static flags = {
17
+ tag: Flags.string({
18
+ char: 't',
19
+ description: 'Tag to apply (key=value), can be specified multiple times',
20
+ multiple: true,
21
+ }),
22
+ };
23
+ static summary = 'Create a new device';
24
+ async run() {
25
+ const body = {
26
+ enabled: true,
27
+ name: this.args.name,
28
+ type: 'default',
29
+ };
30
+ if (this.flags.tag && this.flags.tag.length > 0) {
31
+ const tags = {};
32
+ for (const t of this.flags.tag) {
33
+ const [key, ...rest] = t.split('=');
34
+ const value = rest.join('=');
35
+ if (!key || !value) {
36
+ this.error(`Invalid tag format: "${t}". Use key=value.`);
37
+ }
38
+ tags[key] = value;
39
+ }
40
+ body.tags = tags;
41
+ }
42
+ const device = await this.api('admin', 'devices', {
43
+ body,
44
+ method: 'POST',
45
+ });
46
+ if (!this.jsonEnabled()) {
47
+ this.log(`\nDevice Created (${this.env}):\n`);
48
+ this.log(formatDetail(device, {
49
+ createdAt: 'Created',
50
+ enabled: 'Enabled',
51
+ id: 'ID',
52
+ name: 'Name',
53
+ organizationId: 'Organization',
54
+ tags: 'Tags',
55
+ type: 'Type',
56
+ }));
57
+ this.log('');
58
+ }
59
+ return device;
60
+ }
61
+ }
62
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/devices/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AAEvC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAA;AAEpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAiC;IAC1E,MAAM,CAAU,IAAI,GAAG;QACrB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAC,WAAW,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC;KAC5E,CAAA;IAED,MAAM,CAAU,WAAW,GAAG;;8EAE8C,CAAA;IAE5E,MAAM,CAAU,QAAQ,GAAG;QACzB,2CAA2C;QAC3C,mFAAmF;QACnF,kDAAkD;KACnD,CAAA;IAED,MAAM,CAAU,KAAK,GAAG;QACtB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC;YAChB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,2DAA2D;YACxE,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,qBAAqB,CAAA;IAExC,KAAK,CAAC,GAAG;QACd,MAAM,IAAI,GAA4B;YACpC,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;YACpB,IAAI,EAAE,SAAS;SAChB,CAAA;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAA2B,EAAE,CAAA;YACvC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC/B,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACnC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC5B,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;oBACnB,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,mBAAmB,CAAC,CAAA;gBAC1D,CAAC;gBAED,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;YACnB,CAAC;YAED,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,SAAS,EAAE;YACzE,IAAI;YACJ,MAAM,EAAE,MAAM;SACf,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE;gBAC5B,SAAS,EAAE,SAAS;gBACpB,OAAO,EAAE,SAAS;gBAClB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,MAAM;gBACZ,cAAc,EAAE,cAAc;gBAC9B,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;aACb,CAAC,CAAC,CAAA;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DevicesDelete extends BaseCommand<typeof DevicesDelete> {
3
+ static args: {
4
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static summary: string;
9
+ run(): Promise<Record<string, unknown>>;
10
+ }
@@ -0,0 +1,49 @@
1
+ import { Args } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatDetail } from '../../lib/formatters.js';
4
+ export default class DevicesDelete extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'Device ID (UUID)', required: true }),
7
+ };
8
+ static description = `Delete (disable) a device from your fleet.
9
+
10
+ This performs a soft-delete by disabling the device. The device and its telemetry
11
+ history are preserved but it will no longer appear in device listings.`;
12
+ static examples = [
13
+ '<%= config.bin %> devices delete <device-id>',
14
+ '<%= config.bin %> devices delete <device-id> --json',
15
+ ];
16
+ static summary = 'Delete (disable) a device';
17
+ async run() {
18
+ const deviceId = this.args.id;
19
+ // Fetch the device first to confirm it exists and get its name
20
+ const device = await this.api('admin', `devices/${deviceId}`, {
21
+ method: 'GET',
22
+ });
23
+ if (!device.enabled) {
24
+ if (!this.jsonEnabled()) {
25
+ this.log(`\nDevice "${device.name}" (${deviceId}) is already disabled.\n`);
26
+ }
27
+ return { ...device, alreadyDisabled: true };
28
+ }
29
+ // Soft-delete: disable the device
30
+ const updated = await this.api('admin', `devices/${deviceId}`, {
31
+ body: { enabled: false },
32
+ method: 'PATCH',
33
+ });
34
+ if (!this.jsonEnabled()) {
35
+ this.log(`\nDevice Deleted (${this.env}):\n`);
36
+ this.log(` Device "${device.name}" (${deviceId}) has been disabled.\n`);
37
+ this.log(formatDetail(updated, {
38
+ enabled: 'Enabled',
39
+ id: 'ID',
40
+ name: 'Name',
41
+ type: 'Type',
42
+ updatedAt: 'Updated',
43
+ }));
44
+ this.log('');
45
+ }
46
+ return updated;
47
+ }
48
+ }
49
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/devices/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAEhC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAA;AAEpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAiC;IAC1E,MAAM,CAAU,IAAI,GAAG;QACrB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAC,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC;KACnE,CAAA;IAED,MAAM,CAAU,WAAW,GAAG;;;uEAGuC,CAAA;IAErE,MAAM,CAAU,QAAQ,GAAG;QACzB,8CAA8C;QAC9C,qDAAqD;KACtD,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,2BAA2B,CAAA;IAE9C,KAAK,CAAC,GAAG;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;QAE7B,+DAA+D;QAC/D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,WAAW,QAAQ,EAAE,EAAE;YACrF,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;QAEF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,IAAI,MAAM,QAAQ,0BAA0B,CAAC,CAAA;YAC5E,CAAC;YAED,OAAO,EAAC,GAAG,MAAM,EAAE,eAAe,EAAE,IAAI,EAAC,CAAA;QAC3C,CAAC;QAED,kCAAkC;QAClC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,WAAW,QAAQ,EAAE,EAAE;YACtF,IAAI,EAAE,EAAC,OAAO,EAAE,KAAK,EAAC;YACtB,MAAM,EAAE,OAAO;SAChB,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,IAAI,MAAM,QAAQ,wBAAwB,CAAC,CAAA;YACxE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE;gBAC7B,OAAO,EAAE,SAAS;gBAClB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,SAAS;aACrB,CAAC,CAAC,CAAA;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DevicesRename extends BaseCommand<typeof DevicesRename> {
3
+ static args: {
4
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static summary: string;
10
+ run(): Promise<Record<string, unknown>>;
11
+ }
@@ -0,0 +1,42 @@
1
+ import { Args } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatDetail } from '../../lib/formatters.js';
4
+ export default class DevicesRename extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'Device ID (UUID)', required: true }),
7
+ name: Args.string({ description: 'New name for the device', required: true }),
8
+ };
9
+ static description = 'Rename a device by updating its name.';
10
+ static examples = [
11
+ '<%= config.bin %> devices rename <device-id> new-robot-name',
12
+ '<%= config.bin %> devices rename <device-id> new-robot-name --json',
13
+ ];
14
+ static summary = 'Rename a device';
15
+ async run() {
16
+ const { id: deviceId, name: newName } = this.args;
17
+ // Fetch the device first to confirm it exists and get the old name
18
+ const device = await this.api('admin', `devices/${deviceId}`, {
19
+ method: 'GET',
20
+ });
21
+ const oldName = device.name;
22
+ const updated = await this.api('admin', `devices/${deviceId}`, {
23
+ body: { name: newName },
24
+ method: 'PATCH',
25
+ });
26
+ if (!this.jsonEnabled()) {
27
+ this.log(`\nDevice Renamed (${this.env}):\n`);
28
+ this.log(` "${oldName}" → "${newName}"\n`);
29
+ this.log(formatDetail(updated, {
30
+ enabled: 'Enabled',
31
+ id: 'ID',
32
+ name: 'Name',
33
+ tags: 'Tags',
34
+ type: 'Type',
35
+ updatedAt: 'Updated',
36
+ }));
37
+ this.log('');
38
+ }
39
+ return updated;
40
+ }
41
+ }
42
+ //# sourceMappingURL=rename.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename.js","sourceRoot":"","sources":["../../../src/commands/devices/rename.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAEhC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAA;AAEpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAiC;IAC1E,MAAM,CAAU,IAAI,GAAG;QACrB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAC,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC;QAClE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAC,WAAW,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC;KAC5E,CAAA;IAED,MAAM,CAAU,WAAW,GAAG,uCAAuC,CAAA;IAErE,MAAM,CAAU,QAAQ,GAAG;QACzB,6DAA6D;QAC7D,oEAAoE;KACrE,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,iBAAiB,CAAA;IAEpC,KAAK,CAAC,GAAG;QACd,MAAM,EAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAC,GAAG,IAAI,CAAC,IAAI,CAAA;QAE/C,mEAAmE;QACnE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,WAAW,QAAQ,EAAE,EAAE;YACrF,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,MAAM,CAAC,IAAc,CAAA;QAErC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,WAAW,QAAQ,EAAE,EAAE;YACtF,IAAI,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC;YACrB,MAAM,EAAE,OAAO;SAChB,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,QAAQ,OAAO,KAAK,CAAC,CAAA;YAC3C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE;gBAC7B,OAAO,EAAE,SAAS;gBAClB,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,SAAS;aACrB,CAAC,CAAC,CAAA;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DevicesTag extends BaseCommand<typeof DevicesTag> {
3
+ static args: {
4
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ tag: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ static summary: string;
12
+ run(): Promise<Record<string, unknown>>;
13
+ }
@@ -0,0 +1,69 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatTable } from '../../lib/formatters.js';
4
+ export default class DevicesTag extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'Device ID (UUID)', required: true }),
7
+ };
8
+ static description = `Add or update tags on a device.
9
+
10
+ Tags are key-value pairs. If a tag key already exists, its value will be updated.
11
+ Specify one or more tags with --tag key=value.`;
12
+ static examples = [
13
+ '<%= config.bin %> devices tag <device-id> --tag location=warehouse',
14
+ '<%= config.bin %> devices tag <device-id> --tag env=prod --tag region=us-east',
15
+ '<%= config.bin %> devices tag <device-id> --tag location=factory --json',
16
+ ];
17
+ static flags = {
18
+ tag: Flags.string({
19
+ char: 't',
20
+ description: 'Tag to add or update (key=value), can be specified multiple times',
21
+ multiple: true,
22
+ required: true,
23
+ }),
24
+ };
25
+ static summary = 'Add or update tags on a device';
26
+ async run() {
27
+ const deviceId = this.args.id;
28
+ // Parse the new tags
29
+ const newTags = {};
30
+ for (const t of this.flags.tag) {
31
+ const [key, ...rest] = t.split('=');
32
+ const value = rest.join('=');
33
+ if (!key || !value) {
34
+ this.error(`Invalid tag format: "${t}". Use key=value.`);
35
+ }
36
+ newTags[key] = value;
37
+ }
38
+ // Fetch current device to get existing tags
39
+ const device = await this.api('admin', `devices/${deviceId}`, {
40
+ method: 'GET',
41
+ });
42
+ const currentTags = device.tags ?? {};
43
+ const mergedTags = { ...currentTags, ...newTags };
44
+ // Patch the device with merged tags
45
+ const updated = await this.api('admin', `devices/${deviceId}`, {
46
+ body: { tags: mergedTags },
47
+ method: 'PATCH',
48
+ });
49
+ const updatedTags = updated.tags ?? {};
50
+ if (!this.jsonEnabled()) {
51
+ this.log(`\nTags Updated — ${device.name} (${this.env}):\n`);
52
+ const rows = Object.entries(updatedTags)
53
+ .filter(([key]) => !key.startsWith('$.'))
54
+ .map(([key, value]) => {
55
+ const isNew = key in newTags;
56
+ return { key, status: isNew ? '✓' : '', value };
57
+ });
58
+ const columns = [
59
+ { key: 'key', label: 'KEY', width: 25 },
60
+ { key: 'value', label: 'VALUE', width: 35 },
61
+ { key: 'status', label: '', width: 4 },
62
+ ];
63
+ this.log(formatTable(rows, columns));
64
+ this.log('');
65
+ }
66
+ return updated;
67
+ }
68
+ }
69
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../../src/commands/devices/tag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class DevicesUntag extends BaseCommand<typeof DevicesUntag> {
3
+ static args: {
4
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ key: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ static summary: string;
12
+ run(): Promise<Record<string, unknown>>;
13
+ }
@@ -0,0 +1,79 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatTable } from '../../lib/formatters.js';
4
+ export default class DevicesUntag extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'Device ID (UUID)', required: true }),
7
+ };
8
+ static description = `Remove tags from a device.
9
+
10
+ Specify one or more tag keys to remove with --key.`;
11
+ static examples = [
12
+ '<%= config.bin %> devices untag <device-id> --key location',
13
+ '<%= config.bin %> devices untag <device-id> --key env --key region',
14
+ '<%= config.bin %> devices untag <device-id> --key location --json',
15
+ ];
16
+ static flags = {
17
+ key: Flags.string({
18
+ char: 'k',
19
+ description: 'Tag key to remove, can be specified multiple times',
20
+ multiple: true,
21
+ required: true,
22
+ }),
23
+ };
24
+ static summary = 'Remove tags from a device';
25
+ async run() {
26
+ const deviceId = this.args.id;
27
+ // Fetch current device to get existing tags
28
+ const device = await this.api('admin', `devices/${deviceId}`, {
29
+ method: 'GET',
30
+ });
31
+ const currentTags = device.tags ?? {};
32
+ const updatedTags = { ...currentTags };
33
+ const removed = [];
34
+ const notFound = [];
35
+ for (const key of this.flags.key) {
36
+ if (key in updatedTags) {
37
+ delete updatedTags[key];
38
+ removed.push(key);
39
+ }
40
+ else {
41
+ notFound.push(key);
42
+ }
43
+ }
44
+ if (removed.length === 0) {
45
+ if (!this.jsonEnabled()) {
46
+ this.log(`\nNo matching tags found on device "${device.name}".`);
47
+ this.log(`Keys not found: ${notFound.join(', ')}\n`);
48
+ }
49
+ return { ...device, removedTags: [], notFound };
50
+ }
51
+ // Patch the device with updated tags
52
+ const updated = await this.api('admin', `devices/${deviceId}`, {
53
+ body: { tags: updatedTags },
54
+ method: 'PATCH',
55
+ });
56
+ const finalTags = updated.tags ?? {};
57
+ if (!this.jsonEnabled()) {
58
+ this.log(`\nTags Removed — ${device.name} (${this.env}):\n`);
59
+ this.log(` Removed: ${removed.join(', ')}`);
60
+ if (notFound.length > 0) {
61
+ this.log(` Not found: ${notFound.join(', ')}`);
62
+ }
63
+ const rows = Object.entries(finalTags)
64
+ .filter(([key]) => !key.startsWith('$.'))
65
+ .map(([key, value]) => ({ key, value }));
66
+ if (rows.length > 0) {
67
+ this.log('\n Remaining tags:\n');
68
+ const columns = [
69
+ { key: 'key', label: 'KEY', width: 25 },
70
+ { key: 'value', label: 'VALUE', width: 35 },
71
+ ];
72
+ this.log(formatTable(rows, columns));
73
+ }
74
+ this.log('');
75
+ }
76
+ return updated;
77
+ }
78
+ }
79
+ //# sourceMappingURL=untag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untag.js","sourceRoot":"","sources":["../../../src/commands/devices/untag.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ interface IngestBatchRequest {
3
+ items: Array<{
4
+ deviceId: string;
5
+ name: string;
6
+ type: 'bitset' | 'health' | 'image' | 'json' | 'numeric' | 'text' | 'video';
7
+ tags: Record<string, string>;
8
+ points: Array<[number, unknown]>;
9
+ }>;
10
+ }
11
+ export default class IngestBatch extends BaseCommand<typeof IngestBatch> {
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
+ };
18
+ static summary: string;
19
+ run(): Promise<IngestBatchRequest>;
20
+ }
21
+ export {};
@@ -0,0 +1,170 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Flags } from '@oclif/core';
3
+ import { BaseCommand } from '../../base-command.js';
4
+ export default class IngestBatch extends BaseCommand {
5
+ static description = `Ingest multiple data points in a single batch request.
6
+
7
+ Reads a JSON file (or stdin) containing a batch ingestion payload and sends all data points
8
+ in a single API request. This is more efficient than sending individual data points when you
9
+ have multiple values to ingest.
10
+
11
+ INPUT FORMAT:
12
+ The input JSON must have the following structure:
13
+ {
14
+ "items": [
15
+ {
16
+ "deviceId": "device-uuid", // Required: Device ID (UUID)
17
+ "name": "stream-name", // Required: Stream name
18
+ "type": "numeric|text|json|...", // Required: Data type (see below)
19
+ "tags": {"key": "value"}, // Optional: Tags object (string key-value pairs)
20
+ "points": [[timestamp_ms, value]] // Required: Array of [timestamp, value] pairs
21
+ }
22
+ ]
23
+ }
24
+
25
+ SUPPORTED TYPES AND VALUE FORMATS:
26
+ - numeric: Number value
27
+ Example: "points": [[1708272000000, 42.5]]
28
+
29
+ - text: String value
30
+ Example: "points": [[1708272000000, "hello world"]]
31
+
32
+ - json: JSON object encoded as string
33
+ Example: "points": [[1708272000000, "{\\"x\\":10,\\"y\\":20}"]]
34
+
35
+ - image: Object with url (required), size and annotations (optional)
36
+ Example: "points": [[1708272000000, {"url": "https://example.com/img.jpg", "size": 102400}]]
37
+
38
+ - video: Object with url, duration, mimeType (required), size (optional)
39
+ Example: "points": [[1708272000000, {"url": "https://example.com/vid.mp4", "duration": 30000, "mimeType": "video/mp4"}]]
40
+
41
+ - bitset: Object with keys array and values array (1-1000 pairs)
42
+ Example: "points": [[1708272000000, {"keys": ["door", "window"], "values": [true, false]}]]
43
+
44
+ - health: Object with status (required) and clockSkewMs (optional)
45
+ Example: "points": [[1708272000000, {"status": "operational", "clockSkewMs": 150}]]
46
+ Valid status values: "unknown", "operational", "offline", "error"
47
+
48
+ Each item can have multiple points (timestamp/value pairs) for the same stream.
49
+ Timestamps are Unix milliseconds (use Date.now() for current time).`;
50
+ static examples = [
51
+ `<%= config.bin %> ingest batch --file data.json`,
52
+ `<%= config.bin %> ingest batch --stdin < data.json`,
53
+ `cat payload.json | <%= config.bin %> ingest batch --stdin`,
54
+ `# Example payload.json with multiple types:
55
+ {
56
+ "items": [
57
+ {
58
+ "deviceId": "abc-123",
59
+ "name": "battery_level",
60
+ "type": "numeric",
61
+ "tags": {"env": "prod"},
62
+ "points": [[1708272000000, 42.5], [1708272060000, 41.8]]
63
+ },
64
+ {
65
+ "deviceId": "abc-123",
66
+ "name": "status",
67
+ "type": "text",
68
+ "tags": {"env": "prod"},
69
+ "points": [[1708272000000, "operational"]]
70
+ },
71
+ {
72
+ "deviceId": "abc-123",
73
+ "name": "health",
74
+ "type": "health",
75
+ "tags": {},
76
+ "points": [[1708272000000, {"status": "operational"}]]
77
+ }
78
+ ]
79
+ }`,
80
+ ];
81
+ static flags = {
82
+ file: Flags.string({
83
+ char: 'f',
84
+ description: 'Path to JSON file containing batch payload',
85
+ exclusive: ['stdin'],
86
+ }),
87
+ stdin: Flags.boolean({
88
+ description: 'Read JSON payload from stdin',
89
+ exclusive: ['file'],
90
+ }),
91
+ };
92
+ static summary = 'Ingest batch data from file or stdin';
93
+ async run() {
94
+ // Ensure either --file or --stdin is specified
95
+ if (!this.flags.file && !this.flags.stdin) {
96
+ this.error('Must specify either --file <path> or --stdin');
97
+ }
98
+ // Read input
99
+ let inputJson;
100
+ if (this.flags.file) {
101
+ try {
102
+ inputJson = readFileSync(this.flags.file, 'utf8');
103
+ }
104
+ catch (error) {
105
+ this.error(`Failed to read file "${this.flags.file}": ${error instanceof Error ? error.message : 'Unknown error'}`);
106
+ }
107
+ }
108
+ else {
109
+ // Read from stdin
110
+ const chunks = [];
111
+ for await (const chunk of process.stdin) {
112
+ chunks.push(chunk);
113
+ }
114
+ inputJson = Buffer.concat(chunks).toString('utf8');
115
+ if (!inputJson.trim()) {
116
+ this.error('No data received from stdin');
117
+ }
118
+ }
119
+ // Parse JSON
120
+ let body;
121
+ try {
122
+ body = JSON.parse(inputJson);
123
+ }
124
+ catch (error) {
125
+ this.error(`Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}. Input must be valid JSON.`);
126
+ }
127
+ // Validate structure
128
+ if (!body || typeof body !== 'object') {
129
+ this.error('Input must be a JSON object');
130
+ }
131
+ if (!Array.isArray(body.items)) {
132
+ this.error('Input must have an "items" array');
133
+ }
134
+ if (body.items.length === 0) {
135
+ this.error('Items array cannot be empty');
136
+ }
137
+ // Basic validation of items
138
+ for (const [index, item] of body.items.entries()) {
139
+ if (!item.deviceId) {
140
+ this.error(`Item ${index}: Missing required field "deviceId"`);
141
+ }
142
+ if (!item.name) {
143
+ this.error(`Item ${index}: Missing required field "name"`);
144
+ }
145
+ if (!item.type) {
146
+ this.error(`Item ${index}: Missing required field "type"`);
147
+ }
148
+ const validTypes = ['numeric', 'text', 'json', 'image', 'video', 'bitset', 'health'];
149
+ if (!validTypes.includes(item.type)) {
150
+ this.error(`Item ${index}: Invalid type "${item.type}". Must be one of: ${validTypes.join(', ')}`);
151
+ }
152
+ if (!Array.isArray(item.points)) {
153
+ this.error(`Item ${index}: "points" must be an array`);
154
+ }
155
+ if (item.points.length === 0) {
156
+ this.error(`Item ${index}: "points" array cannot be empty`);
157
+ }
158
+ }
159
+ // Count total points
160
+ const totalPoints = body.items.reduce((sum, item) => sum + item.points.length, 0);
161
+ // Send request (expect 204 No Content)
162
+ await this.api('ingest', 'batch', { body, method: 'POST' });
163
+ if (!this.jsonEnabled()) {
164
+ this.log(`\n✓ Ingested batch: ${body.items.length} stream(s), ${totalPoints} data point(s) (${this.env})\n`);
165
+ }
166
+ // Return the request body for --json output
167
+ return body;
168
+ }
169
+ }
170
+ //# sourceMappingURL=batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../src/commands/ingest/batch.ts"],"names":[],"mappings":"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"}