@formant/formant-cli 0.1.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 (147) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +322 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.js +5 -0
  5. package/dist/base-command.d.ts +38 -0
  6. package/dist/base-command.js +66 -0
  7. package/dist/base-command.js.map +1 -0
  8. package/dist/commands/analytics/query.d.ts +12 -0
  9. package/dist/commands/analytics/query.js +82 -0
  10. package/dist/commands/analytics/query.js.map +1 -0
  11. package/dist/commands/analytics/tables.d.ts +9 -0
  12. package/dist/commands/analytics/tables.js +34 -0
  13. package/dist/commands/analytics/tables.js.map +1 -0
  14. package/dist/commands/commands/for-device.d.ts +12 -0
  15. package/dist/commands/commands/for-device.js +33 -0
  16. package/dist/commands/commands/for-device.js.map +1 -0
  17. package/dist/commands/commands/get.d.ts +11 -0
  18. package/dist/commands/commands/get.js +133 -0
  19. package/dist/commands/commands/get.js.map +1 -0
  20. package/dist/commands/commands/history.d.ts +13 -0
  21. package/dist/commands/commands/history.js +49 -0
  22. package/dist/commands/commands/history.js.map +1 -0
  23. package/dist/commands/commands/list.d.ts +9 -0
  24. package/dist/commands/commands/list.js +31 -0
  25. package/dist/commands/commands/list.js.map +1 -0
  26. package/dist/commands/commands/send.d.ts +37 -0
  27. package/dist/commands/commands/send.js +260 -0
  28. package/dist/commands/commands/send.js.map +1 -0
  29. package/dist/commands/devices/config.d.ts +10 -0
  30. package/dist/commands/devices/config.js +38 -0
  31. package/dist/commands/devices/config.js.map +1 -0
  32. package/dist/commands/devices/get.d.ts +10 -0
  33. package/dist/commands/devices/get.js +35 -0
  34. package/dist/commands/devices/get.js.map +1 -0
  35. package/dist/commands/devices/last-seen.d.ts +10 -0
  36. package/dist/commands/devices/last-seen.js +25 -0
  37. package/dist/commands/devices/last-seen.js.map +1 -0
  38. package/dist/commands/devices/list.d.ts +20 -0
  39. package/dist/commands/devices/list.js +133 -0
  40. package/dist/commands/devices/list.js.map +1 -0
  41. package/dist/commands/devices/streams.d.ts +12 -0
  42. package/dist/commands/devices/streams.js +56 -0
  43. package/dist/commands/devices/streams.js.map +1 -0
  44. package/dist/commands/event-triggers/get.d.ts +10 -0
  45. package/dist/commands/event-triggers/get.js +29 -0
  46. package/dist/commands/event-triggers/get.js.map +1 -0
  47. package/dist/commands/event-triggers/list.d.ts +9 -0
  48. package/dist/commands/event-triggers/list.js +30 -0
  49. package/dist/commands/event-triggers/list.js.map +1 -0
  50. package/dist/commands/events/get.d.ts +10 -0
  51. package/dist/commands/events/get.js +35 -0
  52. package/dist/commands/events/get.js.map +1 -0
  53. package/dist/commands/events/list.d.ts +17 -0
  54. package/dist/commands/events/list.js +81 -0
  55. package/dist/commands/events/list.js.map +1 -0
  56. package/dist/commands/fleets/get.d.ts +10 -0
  57. package/dist/commands/fleets/get.js +28 -0
  58. package/dist/commands/fleets/get.js.map +1 -0
  59. package/dist/commands/fleets/list.d.ts +9 -0
  60. package/dist/commands/fleets/list.js +27 -0
  61. package/dist/commands/fleets/list.js.map +1 -0
  62. package/dist/commands/investigations/analytics.d.ts +15 -0
  63. package/dist/commands/investigations/analytics.js +69 -0
  64. package/dist/commands/investigations/analytics.js.map +1 -0
  65. package/dist/commands/investigations/get.d.ts +10 -0
  66. package/dist/commands/investigations/get.js +38 -0
  67. package/dist/commands/investigations/get.js.map +1 -0
  68. package/dist/commands/investigations/list.d.ts +12 -0
  69. package/dist/commands/investigations/list.js +41 -0
  70. package/dist/commands/investigations/list.js.map +1 -0
  71. package/dist/commands/investigations/run.d.ts +15 -0
  72. package/dist/commands/investigations/run.js +96 -0
  73. package/dist/commands/investigations/run.js.map +1 -0
  74. package/dist/commands/investigations/runs-list.d.ts +18 -0
  75. package/dist/commands/investigations/runs-list.js +57 -0
  76. package/dist/commands/investigations/runs-list.js.map +1 -0
  77. package/dist/commands/investigations/runs.d.ts +12 -0
  78. package/dist/commands/investigations/runs.js +30 -0
  79. package/dist/commands/investigations/runs.js.map +1 -0
  80. package/dist/commands/investigations/stats.d.ts +11 -0
  81. package/dist/commands/investigations/stats.js +40 -0
  82. package/dist/commands/investigations/stats.js.map +1 -0
  83. package/dist/commands/investigations/trigger.d.ts +14 -0
  84. package/dist/commands/investigations/trigger.js +43 -0
  85. package/dist/commands/investigations/trigger.js.map +1 -0
  86. package/dist/commands/kv/get.d.ts +10 -0
  87. package/dist/commands/kv/get.js +28 -0
  88. package/dist/commands/kv/get.js.map +1 -0
  89. package/dist/commands/kv/list.d.ts +13 -0
  90. package/dist/commands/kv/list.js +73 -0
  91. package/dist/commands/kv/list.js.map +1 -0
  92. package/dist/commands/kv/set.d.ts +11 -0
  93. package/dist/commands/kv/set.js +40 -0
  94. package/dist/commands/kv/set.js.map +1 -0
  95. package/dist/commands/query/index.d.ts +19 -0
  96. package/dist/commands/query/index.js +105 -0
  97. package/dist/commands/query/index.js.map +1 -0
  98. package/dist/commands/query/latest-values.d.ts +14 -0
  99. package/dist/commands/query/latest-values.js +102 -0
  100. package/dist/commands/query/latest-values.js.map +1 -0
  101. package/dist/commands/schedules/get.d.ts +10 -0
  102. package/dist/commands/schedules/get.js +29 -0
  103. package/dist/commands/schedules/get.js.map +1 -0
  104. package/dist/commands/schedules/list.d.ts +9 -0
  105. package/dist/commands/schedules/list.js +29 -0
  106. package/dist/commands/schedules/list.js.map +1 -0
  107. package/dist/commands/signals/count.d.ts +13 -0
  108. package/dist/commands/signals/count.js +43 -0
  109. package/dist/commands/signals/count.js.map +1 -0
  110. package/dist/commands/signals/get.d.ts +13 -0
  111. package/dist/commands/signals/get.js +80 -0
  112. package/dist/commands/signals/get.js.map +1 -0
  113. package/dist/commands/signals/list.d.ts +9 -0
  114. package/dist/commands/signals/list.js +30 -0
  115. package/dist/commands/signals/list.js.map +1 -0
  116. package/dist/commands/signals/query.d.ts +14 -0
  117. package/dist/commands/signals/query.js +52 -0
  118. package/dist/commands/signals/query.js.map +1 -0
  119. package/dist/commands/users/get.d.ts +10 -0
  120. package/dist/commands/users/get.js +28 -0
  121. package/dist/commands/users/get.js.map +1 -0
  122. package/dist/commands/users/list.d.ts +9 -0
  123. package/dist/commands/users/list.js +28 -0
  124. package/dist/commands/users/list.js.map +1 -0
  125. package/dist/help.d.ts +4 -0
  126. package/dist/help.js +91 -0
  127. package/dist/help.js.map +1 -0
  128. package/dist/hooks/init.d.ts +3 -0
  129. package/dist/hooks/init.js +7 -0
  130. package/dist/hooks/init.js.map +1 -0
  131. package/dist/index.d.ts +1 -0
  132. package/dist/index.js +2 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/lib/api.d.ts +12 -0
  135. package/dist/lib/api.js +46 -0
  136. package/dist/lib/api.js.map +1 -0
  137. package/dist/lib/auth.d.ts +17 -0
  138. package/dist/lib/auth.js +41 -0
  139. package/dist/lib/auth.js.map +1 -0
  140. package/dist/lib/config.d.ts +7 -0
  141. package/dist/lib/config.js +21 -0
  142. package/dist/lib/config.js.map +1 -0
  143. package/dist/lib/formatters.d.ts +17 -0
  144. package/dist/lib/formatters.js +53 -0
  145. package/dist/lib/formatters.js.map +1 -0
  146. package/oclif.manifest.json +2683 -0
  147. package/package.json +117 -0
@@ -0,0 +1,80 @@
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 SignalsGet extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'Signal ID (UUID)', required: true }),
7
+ };
8
+ static description = `Get detailed information about a specific signal by its ID.
9
+
10
+ Shows signal details including the triggering event, goal, status, and type (manual,
11
+ eventTrigger, schedule, slack). Use --trace to also fetch the event and event trigger
12
+ information.`;
13
+ static examples = [
14
+ '<%= config.bin %> signals get <signal-id>',
15
+ '<%= config.bin %> signals get <signal-id> --trace',
16
+ '<%= config.bin %> signals get <signal-id> --json',
17
+ ];
18
+ static flags = {
19
+ trace: Flags.boolean({
20
+ description: 'Fetch and display the triggering event and event trigger information',
21
+ }),
22
+ };
23
+ static summary = 'Get a signal by ID';
24
+ async run() {
25
+ const signal = await this.api('theopolis', `signals/${this.args.id}`, {
26
+ method: 'GET',
27
+ });
28
+ const result = { signal };
29
+ // If trace is enabled, fetch event and event trigger
30
+ if (this.flags.trace) {
31
+ // Fetch event if available
32
+ if (signal.eventId) {
33
+ try {
34
+ const event = await this.api('admin', `events/${signal.eventId}`, {
35
+ method: 'GET',
36
+ });
37
+ result.event = event;
38
+ }
39
+ catch {
40
+ // Event might not exist
41
+ }
42
+ }
43
+ // Fetch event trigger if available
44
+ if (signal.eventTriggerId) {
45
+ try {
46
+ const eventTrigger = await this.api('admin', `event-triggers/${signal.eventTriggerId}`, { method: 'GET' });
47
+ result.eventTrigger = eventTrigger;
48
+ }
49
+ catch {
50
+ // Event trigger might not exist
51
+ }
52
+ }
53
+ }
54
+ if (!this.jsonEnabled()) {
55
+ this.log(`\nSignal Details (${this.env}):\n`);
56
+ this.log(formatDetail(signal));
57
+ this.log('');
58
+ if (this.flags.trace) {
59
+ if (result.event) {
60
+ this.log(`Triggering Event:\n`);
61
+ this.log(formatDetail(result.event));
62
+ this.log('');
63
+ }
64
+ if (result.eventTrigger) {
65
+ this.log(`Event Trigger Configuration:\n`);
66
+ this.log(formatDetail(result.eventTrigger));
67
+ this.log('');
68
+ }
69
+ if (signal.type === 'schedule' && signal.scheduleCron) {
70
+ this.log(`Schedule: ${signal.scheduleCron}\n`);
71
+ }
72
+ if (signal.type === 'manual') {
73
+ this.log(`Type: Manual (created by user)\n`);
74
+ }
75
+ }
76
+ }
77
+ return result;
78
+ }
79
+ }
80
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../src/commands/signals/get.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class SignalsList extends BaseCommand<typeof SignalsList> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static summary: string;
6
+ run(): Promise<{
7
+ items: unknown[];
8
+ }>;
9
+ }
@@ -0,0 +1,30 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ import { formatTable } from '../../lib/formatters.js';
3
+ export default class SignalsList extends BaseCommand {
4
+ static description = `List all signals in your organization.
5
+
6
+ Signals are points of interest that trigger AI-powered investigations. They can be
7
+ created manually, generated from device events, scheduled, or from Slack/Teams integrations.`;
8
+ static examples = [
9
+ '<%= config.bin %> signals list',
10
+ '<%= config.bin %> signals list --json',
11
+ ];
12
+ static summary = 'List all signals';
13
+ async run() {
14
+ const result = await this.api('theopolis', 'signals', { method: 'GET' });
15
+ if (!this.jsonEnabled()) {
16
+ const columns = [
17
+ { key: 'id', label: 'ID', width: 40 },
18
+ { key: 'type', label: 'TYPE', width: 16 },
19
+ { key: 'status', label: 'STATUS', width: 12 },
20
+ { key: 'goal', label: 'GOAL', width: 40 },
21
+ { key: 'createdAt', label: 'CREATED', width: 26 },
22
+ ];
23
+ this.log(`\nSignals (${this.env} environment):\n`);
24
+ this.log(formatTable(result.items ?? [], columns));
25
+ this.log('');
26
+ }
27
+ return result;
28
+ }
29
+ }
30
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/signals/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAc,WAAW,EAAC,MAAM,yBAAyB,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAA+B;IACtE,MAAM,CAAU,WAAW,GAAG;;;6FAG6D,CAAA;IAE3F,MAAM,CAAU,QAAQ,GAAG;QACzB,gCAAgC;QAChC,uCAAuC;KACxC,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,kBAAkB,CAAA;IAErC,KAAK,CAAC,GAAG;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAC3B,WAAW,EACX,SAAS,EACT,EAAC,MAAM,EAAE,KAAK,EAAC,CAChB,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,GAAa;gBACxB,EAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAC;gBACnC,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAC;gBACvC,EAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAC;gBAC3C,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAC;gBACvC,EAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAC;aAChD,CAAA;YAED,IAAI,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAA;YAClD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;YAClD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class SignalsQuery extends BaseCommand<typeof SignalsQuery> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ end: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ start: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ static summary: string;
11
+ run(): Promise<{
12
+ items: unknown[];
13
+ }>;
14
+ }
@@ -0,0 +1,52 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatTable } from '../../lib/formatters.js';
4
+ export default class SignalsQuery extends BaseCommand {
5
+ static description = `Query signals by time range and type.
6
+
7
+ Signal types: manual, eventTrigger, schedule, slack.`;
8
+ static examples = [
9
+ '<%= config.bin %> signals query --start 2026-01-01',
10
+ '<%= config.bin %> signals query --start 2026-01-01 --end 2026-02-01 --type eventTrigger',
11
+ '<%= config.bin %> signals query --start 2026-01-01 --json',
12
+ ];
13
+ static flags = {
14
+ end: Flags.string({
15
+ description: 'End time (ISO 8601)',
16
+ }),
17
+ start: Flags.string({
18
+ description: 'Start time (ISO 8601)',
19
+ required: true,
20
+ }),
21
+ type: Flags.string({
22
+ description: 'Filter by signal type',
23
+ options: ['manual', 'eventTrigger', 'schedule', 'slack'],
24
+ }),
25
+ };
26
+ static summary = 'Query signals by time range';
27
+ async run() {
28
+ // Normalize dates to ISO 8601 datetime format
29
+ const body = {
30
+ startTime: this.normalizeDateTime(this.flags.start),
31
+ };
32
+ if (this.flags.end)
33
+ body.endTime = this.normalizeDateTime(this.flags.end);
34
+ if (this.flags.type)
35
+ body.type = this.flags.type;
36
+ const result = await this.api('theopolis', 'signals/query', { body });
37
+ if (!this.jsonEnabled()) {
38
+ const columns = [
39
+ { key: 'id', label: 'ID', width: 40 },
40
+ { key: 'type', label: 'TYPE', width: 16 },
41
+ { key: 'status', label: 'STATUS', width: 12 },
42
+ { key: 'goal', label: 'GOAL', width: 40 },
43
+ { key: 'createdAt', label: 'CREATED', width: 26 },
44
+ ];
45
+ this.log(`\nSignals (${this.env} environment):\n`);
46
+ this.log(formatTable(result.items ?? [], columns));
47
+ this.log('');
48
+ }
49
+ return result;
50
+ }
51
+ }
52
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/commands/signals/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AAEjC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAc,WAAW,EAAC,MAAM,yBAAyB,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,WAAgC;IACxE,MAAM,CAAU,WAAW,GAAG;;qDAEqB,CAAA;IAEnD,MAAM,CAAU,QAAQ,GAAG;QACzB,oDAAoD;QACpD,yFAAyF;QACzF,2DAA2D;KAC5D,CAAA;IAED,MAAM,CAAU,KAAK,GAAG;QACtB,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC;YAChB,WAAW,EAAE,qBAAqB;SACnC,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,WAAW,EAAE,uBAAuB;YACpC,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,WAAW,EAAE,uBAAuB;YACpC,OAAO,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,CAAC;SACzD,CAAC;KACH,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,6BAA6B,CAAA;IAEhD,KAAK,CAAC,GAAG;QACd,8CAA8C;QAC9C,MAAM,IAAI,GAA4B;YACpC,SAAS,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;SACpD,CAAA;QAED,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzE,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAA;QAEhD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAC3B,WAAW,EACX,eAAe,EACf,EAAC,IAAI,EAAC,CACP,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,GAAa;gBACxB,EAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAC;gBACnC,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAC;gBACvC,EAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAC;gBAC3C,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAC;gBACvC,EAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAC;aAChD,CAAA;YAED,IAAI,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAA;YAClD,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;YAClD,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 UsersGet extends BaseCommand<typeof UsersGet> {
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,28 @@
1
+ import { Args } from '@oclif/core';
2
+ import { BaseCommand } from '../../base-command.js';
3
+ import { formatDetail } from '../../lib/formatters.js';
4
+ export default class UsersGet extends BaseCommand {
5
+ static args = {
6
+ id: Args.string({ description: 'User ID (UUID)', required: true }),
7
+ };
8
+ static description = `Get detailed information about a user.
9
+
10
+ Shows user details including email, name, roles, and account settings.`;
11
+ static examples = [
12
+ '<%= config.bin %> users get <user-id>',
13
+ '<%= config.bin %> users get <user-id> --json',
14
+ ];
15
+ static summary = 'Get user details';
16
+ async run() {
17
+ const user = await this.api('admin', `users/${this.args.id}`, {
18
+ method: 'GET',
19
+ });
20
+ if (!this.jsonEnabled()) {
21
+ this.log(`\nUser Details (${this.env}):\n`);
22
+ this.log(formatDetail(user));
23
+ this.log('');
24
+ }
25
+ return user;
26
+ }
27
+ }
28
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../src/commands/users/get.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,QAAS,SAAQ,WAA4B;IAChE,MAAM,CAAU,IAAI,GAAG;QACrB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAC,WAAW,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC;KACjE,CAAA;IAED,MAAM,CAAU,WAAW,GAAG;;uEAEuC,CAAA;IAErE,MAAM,CAAU,QAAQ,GAAG;QACzB,uCAAuC;QACvC,8CAA8C;KAC/C,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,kBAAkB,CAAA;IAErC,KAAK,CAAC,GAAG;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAA0B,OAAO,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE;YACrF,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;YAC3C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;YAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ export default class UsersList extends BaseCommand<typeof UsersList> {
3
+ static description: string;
4
+ static examples: string[];
5
+ static summary: string;
6
+ run(): Promise<{
7
+ items: unknown[];
8
+ }>;
9
+ }
@@ -0,0 +1,28 @@
1
+ import { BaseCommand } from '../../base-command.js';
2
+ import { formatTable } from '../../lib/formatters.js';
3
+ export default class UsersList extends BaseCommand {
4
+ static description = `List all users in your organization.
5
+
6
+ Shows user accounts, their email addresses, and account status.`;
7
+ static examples = [
8
+ '<%= config.bin %> users list',
9
+ '<%= config.bin %> users list --json',
10
+ ];
11
+ static summary = 'List users';
12
+ async run() {
13
+ const result = await this.api('admin', 'users', { method: 'GET' });
14
+ if (!this.jsonEnabled()) {
15
+ const columns = [
16
+ { key: 'email', label: 'EMAIL', width: 40 },
17
+ { key: 'name', label: 'NAME', width: 30 },
18
+ { key: 'id', label: 'ID', width: 40 },
19
+ { key: 'enabled', label: 'ENABLED', width: 8 },
20
+ ];
21
+ this.log(`\nUsers (${this.env}):\n`);
22
+ this.log(formatTable(result.items ?? [], columns));
23
+ this.log('');
24
+ }
25
+ return result;
26
+ }
27
+ }
28
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/users/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAc,WAAW,EAAC,MAAM,yBAAyB,CAAA;AAEhE,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,WAA6B;IAClE,MAAM,CAAU,WAAW,GAAG;;gEAEgC,CAAA;IAE9D,MAAM,CAAU,QAAQ,GAAG;QACzB,8BAA8B;QAC9B,qCAAqC;KACtC,CAAA;IAED,MAAM,CAAU,OAAO,GAAG,YAAY,CAAA;IAE/B,KAAK,CAAC,GAAG;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAC3B,OAAO,EACP,OAAO,EACP,EAAC,MAAM,EAAE,KAAK,EAAC,CAChB,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,GAAa;gBACxB,EAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAC;gBACzC,EAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAC;gBACvC,EAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAC;gBACnC,EAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAC;aAC7C,CAAA;YAED,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;YACpC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAA;YAClD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC"}
package/dist/help.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { Help } from '@oclif/core';
2
+ export default class FcliHelp extends Help {
3
+ protected showRootHelp(): Promise<void>;
4
+ }
package/dist/help.js ADDED
@@ -0,0 +1,91 @@
1
+ import { Help } from '@oclif/core';
2
+ export default class FcliHelp extends Help {
3
+ async showRootHelp() {
4
+ const output = `
5
+ ███████╗ ██████╗██╗ ██╗
6
+ ██╔════╝██╔════╝██║ ██║ 🤖 Formant CLI v${this.config.version}
7
+ █████╗ ██║ ██║ ██║ ⚡ Manage your robot fleet
8
+ ██╔══╝ ██║ ██║ ██║ 🚀 from the command line
9
+ ██║ ╚██████╗███████╗██║
10
+ ╚═╝ ╚═════╝╚══════╝╚═╝
11
+
12
+ USAGE
13
+ $ fcli <command> [flags]
14
+
15
+ CONCEPTS
16
+ Device A robot or sensor in your fleet
17
+ Event Important occurrence emitted by a device
18
+ Signal Point of interest from an event, schedule, or manual trigger
19
+ Investigation AI-powered analysis workflow triggered by a signal
20
+ Query Retrieve telemetry and sensor data from devices
21
+
22
+ COMMANDS
23
+ devices List and inspect robots/sensors in your fleet
24
+ events View important events emitted by devices
25
+ query Retrieve telemetry data (battery, temperature, etc.)
26
+ signals Manage signals (points of interest that trigger analysis)
27
+ investigations Run and monitor AI-powered analysis workflows
28
+ commands Manage command templates and send commands to devices
29
+ event-triggers Manage event trigger rules
30
+ users Manage users in your organization
31
+ schedules Manage scheduled tasks
32
+ fleets Manage device groups
33
+ analytics Execute SQL queries against analytics data
34
+ kv Manage key-value store
35
+ help Display help for fcli
36
+
37
+ GLOBAL FLAGS
38
+ --dev Target the dev environment
39
+ --stage Target the stage environment
40
+ --json Format output as JSON
41
+ -h, --help Show help for a command
42
+
43
+ AUTHENTICATION
44
+ Set these environment variables (or use a .env file):
45
+ FORMANT_USER Service account email
46
+ FORMANT_PASSWORD Service account password
47
+
48
+ EXAMPLES
49
+ # List online robots and sensors
50
+ $ fcli devices list --dev
51
+ $ fcli devices list --tag location=warehouse --online
52
+ $ fcli devices config <device-id> --dev
53
+
54
+ # View critical events from a device
55
+ $ fcli events list --device <id> --severity critical --limit 20
56
+ $ fcli events get <event-id> --dev
57
+
58
+ # Query battery telemetry over time
59
+ $ fcli query --device <id> --stream battery_level --start 2026-01-01 --end 2026-01-02
60
+
61
+ # Trace investigation runs back to their origin
62
+ $ fcli investigations runs-list <investigation-id> --dev
63
+ $ fcli investigations run <investigation-id> <run-id> --trace-signal --dev
64
+ $ fcli signals get <signal-id> --trace --dev
65
+
66
+ # View signals and investigations
67
+ $ fcli signals query --start 2026-01-01 --end 2026-02-01
68
+ $ fcli investigations list
69
+ $ fcli investigations stats --start 2026-01-01 --end 2026-02-10
70
+
71
+ # Send commands to devices
72
+ $ fcli commands list --dev
73
+ $ fcli commands for-device <device-id> --dev
74
+ $ fcli commands send <device-id> <template-id> --param speed=5 --dev
75
+
76
+ # Manage event triggers and schedules
77
+ $ fcli event-triggers list --dev
78
+ $ fcli schedules list --dev
79
+
80
+ # Query analytics and latest values
81
+ $ fcli analytics query --sql "SELECT * FROM events LIMIT 10" --dev
82
+ $ fcli query latest-values --device <id> --stream battery_level --dev
83
+
84
+ LEARN MORE
85
+ Use 'fcli <command> --help' for detailed help on any command.
86
+ Use 'fcli <command> <subcommand> --help' for subcommand details.
87
+ `;
88
+ this.log(output);
89
+ }
90
+ }
91
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAEhC,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,IAAI;IACrB,KAAK,CAAC,YAAY;QACnC,MAAM,MAAM,GAAG;;qDAEkC,IAAI,CAAC,MAAM,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiFvE,CAAA;QAEG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAClB,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ import { Hook } from '@oclif/core';
2
+ declare const hook: Hook.Init;
3
+ export default hook;
@@ -0,0 +1,7 @@
1
+ import { config } from 'dotenv';
2
+ const hook = async function () {
3
+ // Load .env from current working directory (optional — env vars take precedence)
4
+ config();
5
+ };
6
+ export default hook;
7
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/hooks/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAAC,MAAM,QAAQ,CAAA;AAE7B,MAAM,IAAI,GAAc,KAAK;IAC3B,iFAAiF;IACjF,MAAM,EAAE,CAAA;AACV,CAAC,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1 @@
1
+ export { BaseCommand } from './base-command.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { BaseCommand } from './base-command.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { type Environment } from './config.js';
2
+ export type ApiTarget = 'admin' | 'query' | 'theopolis';
3
+ interface RequestOptions {
4
+ body?: unknown;
5
+ method?: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT';
6
+ query?: Record<string, string>;
7
+ }
8
+ /**
9
+ * Make an authenticated API request to a Formant service.
10
+ */
11
+ export declare function apiRequest<T = unknown>(env: Environment, target: ApiTarget, path: string, options?: RequestOptions): Promise<T>;
12
+ export {};
@@ -0,0 +1,46 @@
1
+ import { getUrls } from './config.js';
2
+ import { login } from './auth.js';
3
+ function buildBaseUrl(env, target) {
4
+ const urls = getUrls(env);
5
+ switch (target) {
6
+ case 'admin': {
7
+ return `${urls.adminApi}/v1/admin`;
8
+ }
9
+ case 'query': {
10
+ return `${urls.queryApi}/v1/queries`;
11
+ }
12
+ case 'theopolis': {
13
+ return `${urls.theopolis}/api`;
14
+ }
15
+ }
16
+ }
17
+ /**
18
+ * Make an authenticated API request to a Formant service.
19
+ */
20
+ export async function apiRequest(env, target, path, options = {}) {
21
+ const { body, method = body ? 'POST' : 'GET', query } = options;
22
+ const auth = await login(env);
23
+ let url = `${buildBaseUrl(env, target)}/${path}`;
24
+ if (query) {
25
+ const params = new URLSearchParams(query);
26
+ url += `?${params.toString()}`;
27
+ }
28
+ const headers = {
29
+ Authorization: `Bearer ${auth.accessToken}`,
30
+ 'Content-Type': 'application/json',
31
+ };
32
+ const res = await fetch(url, {
33
+ body: body ? JSON.stringify(body) : undefined,
34
+ headers,
35
+ method,
36
+ });
37
+ if (!res.ok) {
38
+ const text = await res.text();
39
+ throw new Error(`API error ${res.status} ${method} ${url}: ${text}`);
40
+ }
41
+ // Handle 204 No Content
42
+ if (res.status === 204)
43
+ return undefined;
44
+ return (await res.json());
45
+ }
46
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,OAAO,EAAC,MAAM,aAAa,CAAA;AACrD,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAU/B,SAAS,YAAY,CAAC,GAAgB,EAAE,MAAiB;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACzB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,QAAQ,WAAW,CAAA;QACpC,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,QAAQ,aAAa,CAAA;QACtC,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,OAAO,GAAG,IAAI,CAAC,SAAS,MAAM,CAAA;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAgB,EAChB,MAAiB,EACjB,IAAY,EACZ,UAA0B,EAAE;IAE5B,MAAM,EAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAC,GAAG,OAAO,CAAA;IAC7D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IAE7B,IAAI,GAAG,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAA;IAChD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAA;QACzC,GAAG,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAA;IAChC,CAAC;IAED,MAAM,OAAO,GAA2B;QACtC,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE;QAC3C,cAAc,EAAE,kBAAkB;KACnC,CAAA;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7C,OAAO;QACP,MAAM;KACP,CAAC,CAAA;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAC7B,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,IAAI,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC,CAAA;IACtE,CAAC;IAED,wBAAwB;IACxB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,SAAc,CAAA;IAE7C,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAA;AAChC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type Environment } from './config.js';
2
+ export interface AuthResult {
3
+ accessToken: string;
4
+ refreshToken?: string;
5
+ organizationId: string;
6
+ userId: string;
7
+ }
8
+ /**
9
+ * Authenticate with Formant using service account credentials.
10
+ * Reads FORMANT_USER and FORMANT_PASSWORD from environment.
11
+ * Caches tokens per environment for the lifetime of the CLI process.
12
+ */
13
+ export declare function login(env: Environment): Promise<AuthResult>;
14
+ /**
15
+ * Clear cached tokens (useful if a token expires mid-session).
16
+ */
17
+ export declare function clearTokenCache(): void;
@@ -0,0 +1,41 @@
1
+ import { getUrls } from './config.js';
2
+ // In-memory cache: one token per environment
3
+ const tokenCache = new Map();
4
+ /**
5
+ * Authenticate with Formant using service account credentials.
6
+ * Reads FORMANT_USER and FORMANT_PASSWORD from environment.
7
+ * Caches tokens per environment for the lifetime of the CLI process.
8
+ */
9
+ export async function login(env) {
10
+ const cached = tokenCache.get(env);
11
+ if (cached)
12
+ return cached;
13
+ const email = process.env.FORMANT_USER;
14
+ const password = process.env.FORMANT_PASSWORD;
15
+ if (!email || !password) {
16
+ throw new Error('Missing credentials. Set FORMANT_USER and FORMANT_PASSWORD environment variables (or in a .env file).');
17
+ }
18
+ const urls = getUrls(env);
19
+ const res = await fetch(`${urls.adminApi}/v1/admin/auth/login`, {
20
+ method: 'POST',
21
+ headers: { 'Content-Type': 'application/json' },
22
+ body: JSON.stringify({ email, password }),
23
+ });
24
+ if (!res.ok) {
25
+ const body = await res.text();
26
+ throw new Error(`Authentication failed (${res.status}): ${body}`);
27
+ }
28
+ const data = (await res.json());
29
+ if (!data.authentication?.accessToken) {
30
+ throw new Error('Authentication response missing access token. Check your credentials.');
31
+ }
32
+ tokenCache.set(env, data.authentication);
33
+ return data.authentication;
34
+ }
35
+ /**
36
+ * Clear cached tokens (useful if a token expires mid-session).
37
+ */
38
+ export function clearTokenCache() {
39
+ tokenCache.clear();
40
+ }
41
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,OAAO,EAAC,MAAM,aAAa,CAAA;AASrD,6CAA6C;AAC7C,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAA;AAErD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAgB;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAA;IAEzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAA;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAA;IAE7C,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,uGAAuG,CACxG,CAAA;IACH,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,sBAAsB,EAAE;QAC9D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;QAC7C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC;KACxC,CAAC,CAAA;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAC7B,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAkC,CAAA;IAEhE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAA;IAC1F,CAAC;IAED,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;IACxC,OAAO,IAAI,CAAC,cAAc,CAAA;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,UAAU,CAAC,KAAK,EAAE,CAAA;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type Environment = 'dev' | 'prod' | 'stage';
2
+ export interface EnvUrls {
3
+ adminApi: string;
4
+ queryApi: string;
5
+ theopolis: string;
6
+ }
7
+ export declare function getUrls(env: Environment): EnvUrls;
@@ -0,0 +1,21 @@
1
+ const ENVIRONMENTS = {
2
+ prod: {
3
+ adminApi: 'https://api.formant.io',
4
+ queryApi: 'https://api.formant.io',
5
+ theopolis: 'https://theopolis-prod-ad4d9de77f9a.herokuapp.com',
6
+ },
7
+ dev: {
8
+ adminApi: 'https://api-dev.formant.io',
9
+ queryApi: 'https://api-dev.formant.io',
10
+ theopolis: 'https://theopolis-dev-231bd5d86d0f.herokuapp.com',
11
+ },
12
+ stage: {
13
+ adminApi: 'https://api-stage.formant.io',
14
+ queryApi: 'https://api-stage.formant.io',
15
+ theopolis: 'https://theopolis-stage-80d087320b3d.herokuapp.com',
16
+ },
17
+ };
18
+ export function getUrls(env) {
19
+ return ENVIRONMENTS[env];
20
+ }
21
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAQA,MAAM,YAAY,GAAiC;IACjD,IAAI,EAAE;QACJ,QAAQ,EAAE,wBAAwB;QAClC,QAAQ,EAAE,wBAAwB;QAClC,SAAS,EAAE,mDAAmD;KAC/D;IACD,GAAG,EAAE;QACH,QAAQ,EAAE,4BAA4B;QACtC,QAAQ,EAAE,4BAA4B;QACtC,SAAS,EAAE,kDAAkD;KAC9D;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,8BAA8B;QACxC,QAAQ,EAAE,8BAA8B;QACxC,SAAS,EAAE,oDAAoD;KAChE;CACF,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,GAAgB;IACtC,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Minimal table formatter — aligns columns with padding.
3
+ * No external dependencies.
4
+ */
5
+ export interface Column {
6
+ key: string;
7
+ label: string;
8
+ width?: number;
9
+ }
10
+ /**
11
+ * Format an array of objects as an aligned table string.
12
+ */
13
+ export declare function formatTable(rows: Record<string, unknown>[], columns: Column[]): string;
14
+ /**
15
+ * Format a single object as a key-value detail view.
16
+ */
17
+ export declare function formatDetail(obj: Record<string, unknown>, labels?: Record<string, string>): string;