@sembix/cli 1.3.0 → 1.4.1

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 (204) hide show
  1. package/COMMANDS.md +1522 -0
  2. package/QUICKSTART.md +829 -0
  3. package/README.md +1949 -285
  4. package/USAGE-EXAMPLES.md +872 -0
  5. package/dist/commands/configure.d.ts.map +1 -1
  6. package/dist/commands/configure.js +172 -2
  7. package/dist/commands/configure.js.map +1 -1
  8. package/dist/commands/index.d.ts +10 -0
  9. package/dist/commands/index.d.ts.map +1 -0
  10. package/dist/commands/index.js +11 -0
  11. package/dist/commands/index.js.map +1 -0
  12. package/dist/commands/login.d.ts +19 -0
  13. package/dist/commands/login.d.ts.map +1 -0
  14. package/dist/commands/login.js +118 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/commands/logout.d.ts +21 -0
  17. package/dist/commands/logout.d.ts.map +1 -0
  18. package/dist/commands/logout.js +66 -0
  19. package/dist/commands/logout.js.map +1 -0
  20. package/dist/commands/profile-project.d.ts +14 -0
  21. package/dist/commands/profile-project.d.ts.map +1 -0
  22. package/dist/commands/profile-project.js +123 -0
  23. package/dist/commands/profile-project.js.map +1 -0
  24. package/dist/commands/profile.d.ts +26 -0
  25. package/dist/commands/profile.d.ts.map +1 -0
  26. package/dist/commands/profile.js +177 -0
  27. package/dist/commands/profile.js.map +1 -0
  28. package/dist/commands/project.d.ts +16 -0
  29. package/dist/commands/project.d.ts.map +1 -0
  30. package/dist/commands/project.js +153 -0
  31. package/dist/commands/project.js.map +1 -0
  32. package/dist/commands/setup.js +1 -1
  33. package/dist/commands/setup.js.map +1 -1
  34. package/dist/commands/update.js +2 -2
  35. package/dist/commands/update.js.map +1 -1
  36. package/dist/commands/workflow.d.ts +91 -0
  37. package/dist/commands/workflow.d.ts.map +1 -0
  38. package/dist/commands/workflow.js +1201 -0
  39. package/dist/commands/workflow.js.map +1 -0
  40. package/dist/config-schema.d.ts +23 -0
  41. package/dist/config-schema.d.ts.map +1 -1
  42. package/dist/config-schema.js +21 -1
  43. package/dist/config-schema.js.map +1 -1
  44. package/dist/config.d.ts +4 -0
  45. package/dist/config.d.ts.map +1 -1
  46. package/dist/config.js +23 -2
  47. package/dist/config.js.map +1 -1
  48. package/dist/index.js +318 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/prompts/project-selection.d.ts +8 -0
  51. package/dist/prompts/project-selection.d.ts.map +1 -0
  52. package/dist/prompts/project-selection.js +132 -0
  53. package/dist/prompts/project-selection.js.map +1 -0
  54. package/dist/prompts/workflow-inputs.d.ts +10 -0
  55. package/dist/prompts/workflow-inputs.d.ts.map +1 -0
  56. package/dist/prompts/workflow-inputs.js +71 -0
  57. package/dist/prompts/workflow-inputs.js.map +1 -0
  58. package/dist/prompts/workflow-selection.d.ts +8 -0
  59. package/dist/prompts/workflow-selection.d.ts.map +1 -0
  60. package/dist/prompts/workflow-selection.js +147 -0
  61. package/dist/prompts/workflow-selection.js.map +1 -0
  62. package/dist/sembix-cli-1.4.1.tgz +0 -0
  63. package/dist/services/cognito-auth.d.ts +92 -0
  64. package/dist/services/cognito-auth.d.ts.map +1 -0
  65. package/dist/services/cognito-auth.js +319 -0
  66. package/dist/services/cognito-auth.js.map +1 -0
  67. package/dist/services/studio-api-client.d.ts +127 -0
  68. package/dist/services/studio-api-client.d.ts.map +1 -0
  69. package/dist/services/studio-api-client.js +291 -0
  70. package/dist/services/studio-api-client.js.map +1 -0
  71. package/dist/types/studio.d.ts +82 -0
  72. package/dist/types/studio.d.ts.map +1 -0
  73. package/dist/types/studio.js +7 -0
  74. package/dist/types/studio.js.map +1 -0
  75. package/dist/types.d.ts +283 -0
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/types.js +5 -0
  78. package/dist/types.js.map +1 -1
  79. package/dist/utils/browser-auth.d.ts +45 -0
  80. package/dist/utils/browser-auth.d.ts.map +1 -0
  81. package/dist/utils/browser-auth.js +168 -0
  82. package/dist/utils/browser-auth.js.map +1 -0
  83. package/dist/utils/cognito-auth.d.ts +3 -0
  84. package/dist/utils/cognito-auth.d.ts.map +1 -0
  85. package/dist/utils/cognito-auth.js +3 -0
  86. package/dist/utils/cognito-auth.js.map +1 -0
  87. package/dist/utils/config-file.d.ts +40 -0
  88. package/dist/utils/config-file.d.ts.map +1 -1
  89. package/dist/utils/config-file.js +158 -4
  90. package/dist/utils/config-file.js.map +1 -1
  91. package/dist/utils/environment.d.ts +22 -0
  92. package/dist/utils/environment.d.ts.map +1 -0
  93. package/dist/utils/environment.js +39 -0
  94. package/dist/utils/environment.js.map +1 -0
  95. package/dist/utils/error-handler.d.ts +53 -0
  96. package/dist/utils/error-handler.d.ts.map +1 -0
  97. package/dist/utils/error-handler.js +174 -0
  98. package/dist/utils/error-handler.js.map +1 -0
  99. package/dist/utils/fuzzy-match.d.ts +31 -0
  100. package/dist/utils/fuzzy-match.d.ts.map +1 -0
  101. package/dist/utils/fuzzy-match.js +138 -0
  102. package/dist/utils/fuzzy-match.js.map +1 -0
  103. package/dist/utils/github.d.ts +2 -2
  104. package/dist/utils/github.d.ts.map +1 -1
  105. package/dist/utils/github.js +30 -10
  106. package/dist/utils/github.js.map +1 -1
  107. package/dist/utils/input-parser.d.ts +14 -0
  108. package/dist/utils/input-parser.d.ts.map +1 -0
  109. package/dist/utils/input-parser.js +34 -0
  110. package/dist/utils/input-parser.js.map +1 -0
  111. package/dist/utils/output.d.ts +55 -0
  112. package/dist/utils/output.d.ts.map +1 -0
  113. package/dist/utils/output.js +80 -0
  114. package/dist/utils/output.js.map +1 -0
  115. package/dist/utils/recent-workflows.d.ts +37 -0
  116. package/dist/utils/recent-workflows.d.ts.map +1 -0
  117. package/dist/utils/recent-workflows.js +172 -0
  118. package/dist/utils/recent-workflows.js.map +1 -0
  119. package/dist/utils/studio-api-client.d.ts +3 -0
  120. package/dist/utils/studio-api-client.d.ts.map +1 -0
  121. package/dist/utils/studio-api-client.js +3 -0
  122. package/dist/utils/studio-api-client.js.map +1 -0
  123. package/dist/utils/studio-api.d.ts +53 -0
  124. package/dist/utils/studio-api.d.ts.map +1 -0
  125. package/dist/utils/studio-api.js +102 -0
  126. package/dist/utils/studio-api.js.map +1 -0
  127. package/dist/utils/studio-config.d.ts +74 -0
  128. package/dist/utils/studio-config.d.ts.map +1 -0
  129. package/dist/utils/studio-config.js +213 -0
  130. package/dist/utils/studio-config.js.map +1 -0
  131. package/dist/utils/token-manager.d.ts +4 -0
  132. package/dist/utils/token-manager.d.ts.map +1 -0
  133. package/dist/utils/token-manager.js +3 -0
  134. package/dist/utils/token-manager.js.map +1 -0
  135. package/dist/utils/ui.d.ts +55 -1
  136. package/dist/utils/ui.d.ts.map +1 -1
  137. package/dist/utils/ui.js +151 -2
  138. package/dist/utils/ui.js.map +1 -1
  139. package/package.json +4 -1
  140. package/dist/__tests__/config-schema.test.d.ts +0 -2
  141. package/dist/__tests__/config-schema.test.d.ts.map +0 -1
  142. package/dist/__tests__/config-schema.test.js +0 -471
  143. package/dist/__tests__/config-schema.test.js.map +0 -1
  144. package/dist/__tests__/config.test.d.ts +0 -2
  145. package/dist/__tests__/config.test.d.ts.map +0 -1
  146. package/dist/__tests__/config.test.js +0 -75
  147. package/dist/__tests__/config.test.js.map +0 -1
  148. package/dist/__tests__/integration/configure.test.d.ts +0 -2
  149. package/dist/__tests__/integration/configure.test.d.ts.map +0 -1
  150. package/dist/__tests__/integration/configure.test.js +0 -247
  151. package/dist/__tests__/integration/configure.test.js.map +0 -1
  152. package/dist/__tests__/integration/fixtures/configs.d.ts +0 -477
  153. package/dist/__tests__/integration/fixtures/configs.d.ts.map +0 -1
  154. package/dist/__tests__/integration/fixtures/configs.js +0 -175
  155. package/dist/__tests__/integration/fixtures/configs.js.map +0 -1
  156. package/dist/__tests__/integration/helpers/cli-runner.d.ts +0 -63
  157. package/dist/__tests__/integration/helpers/cli-runner.d.ts.map +0 -1
  158. package/dist/__tests__/integration/helpers/cli-runner.js +0 -152
  159. package/dist/__tests__/integration/helpers/cli-runner.js.map +0 -1
  160. package/dist/__tests__/integration/helpers/command-runner.d.ts +0 -53
  161. package/dist/__tests__/integration/helpers/command-runner.d.ts.map +0 -1
  162. package/dist/__tests__/integration/helpers/command-runner.js +0 -117
  163. package/dist/__tests__/integration/helpers/command-runner.js.map +0 -1
  164. package/dist/__tests__/integration/studio-create.test.d.ts +0 -2
  165. package/dist/__tests__/integration/studio-create.test.d.ts.map +0 -1
  166. package/dist/__tests__/integration/studio-create.test.js +0 -209
  167. package/dist/__tests__/integration/studio-create.test.js.map +0 -1
  168. package/dist/__tests__/integration/studio-update.test.d.ts +0 -2
  169. package/dist/__tests__/integration/studio-update.test.d.ts.map +0 -1
  170. package/dist/__tests__/integration/studio-update.test.js +0 -166
  171. package/dist/__tests__/integration/studio-update.test.js.map +0 -1
  172. package/dist/commands/__tests__/configure.test.d.ts +0 -2
  173. package/dist/commands/__tests__/configure.test.d.ts.map +0 -1
  174. package/dist/commands/__tests__/configure.test.js +0 -229
  175. package/dist/commands/__tests__/configure.test.js.map +0 -1
  176. package/dist/prompts/__tests__/environment-setup.test.d.ts +0 -2
  177. package/dist/prompts/__tests__/environment-setup.test.d.ts.map +0 -1
  178. package/dist/prompts/__tests__/environment-setup.test.js +0 -206
  179. package/dist/prompts/__tests__/environment-setup.test.js.map +0 -1
  180. package/dist/prompts/__tests__/hub-integration.test.d.ts +0 -2
  181. package/dist/prompts/__tests__/hub-integration.test.d.ts.map +0 -1
  182. package/dist/prompts/__tests__/hub-integration.test.js +0 -126
  183. package/dist/prompts/__tests__/hub-integration.test.js.map +0 -1
  184. package/dist/prompts/__tests__/prompt-helpers.test.d.ts +0 -2
  185. package/dist/prompts/__tests__/prompt-helpers.test.d.ts.map +0 -1
  186. package/dist/prompts/__tests__/prompt-helpers.test.js +0 -235
  187. package/dist/prompts/__tests__/prompt-helpers.test.js.map +0 -1
  188. package/dist/sembix-cli-1.3.0.tgz +0 -0
  189. package/dist/utils/__tests__/config-file.test.d.ts +0 -2
  190. package/dist/utils/__tests__/config-file.test.d.ts.map +0 -1
  191. package/dist/utils/__tests__/config-file.test.js +0 -218
  192. package/dist/utils/__tests__/config-file.test.js.map +0 -1
  193. package/dist/utils/__tests__/config-loader.test.d.ts +0 -2
  194. package/dist/utils/__tests__/config-loader.test.d.ts.map +0 -1
  195. package/dist/utils/__tests__/config-loader.test.js +0 -325
  196. package/dist/utils/__tests__/config-loader.test.js.map +0 -1
  197. package/dist/utils/__tests__/github.test.d.ts +0 -2
  198. package/dist/utils/__tests__/github.test.d.ts.map +0 -1
  199. package/dist/utils/__tests__/github.test.js +0 -282
  200. package/dist/utils/__tests__/github.test.js.map +0 -1
  201. package/dist/utils/__tests__/ui.test.d.ts +0 -2
  202. package/dist/utils/__tests__/ui.test.d.ts.map +0 -1
  203. package/dist/utils/__tests__/ui.test.js +0 -256
  204. package/dist/utils/__tests__/ui.test.js.map +0 -1
@@ -0,0 +1,172 @@
1
+ import { homedir } from 'os';
2
+ import { join } from 'path';
3
+ import { promises as fs } from 'fs';
4
+ import { existsSync } from 'fs';
5
+ const CACHE_DIR = join(homedir(), '.sembix');
6
+ const CACHE_FILE = join(CACHE_DIR, 'recent-workflows.json');
7
+ const MAX_ENTRIES = 50;
8
+ const MAX_ENTRIES_PER_PROFILE = 10;
9
+ const CACHE_VERSION = '1.0';
10
+ /**
11
+ * Adds or updates a recent workflow entry
12
+ * Increments use count if entry already exists
13
+ */
14
+ export async function addRecentWorkflow(profileName, projectId, projectName, workflowId, workflowName) {
15
+ const cache = await loadCache();
16
+ // Find existing entry
17
+ const existingIndex = cache.entries.findIndex(e => e.profileName === profileName &&
18
+ e.projectId === projectId &&
19
+ e.workflowId === workflowId);
20
+ if (existingIndex >= 0) {
21
+ // Update existing entry
22
+ cache.entries[existingIndex].lastUsed = new Date().toISOString();
23
+ cache.entries[existingIndex].useCount++;
24
+ cache.entries[existingIndex].projectName = projectName; // update in case changed
25
+ cache.entries[existingIndex].workflowName = workflowName; // update in case changed
26
+ }
27
+ else {
28
+ // Add new entry
29
+ cache.entries.push({
30
+ profileName,
31
+ projectId,
32
+ projectName,
33
+ workflowId,
34
+ workflowName,
35
+ lastUsed: new Date().toISOString(),
36
+ useCount: 1
37
+ });
38
+ }
39
+ // Evict old entries if needed
40
+ await evictOldEntries(cache);
41
+ await saveCache(cache);
42
+ }
43
+ /**
44
+ * Gets recent workflows for a profile, optionally filtered by project
45
+ * Sorted by use count (desc) then last used (desc)
46
+ */
47
+ export async function getRecentWorkflows(profileName, projectId, limit = 10) {
48
+ const cache = await loadCache();
49
+ let filtered = cache.entries.filter(e => e.profileName === profileName);
50
+ if (projectId) {
51
+ filtered = filtered.filter(e => e.projectId === projectId);
52
+ }
53
+ // Sort by useCount (desc), then lastUsed (desc)
54
+ filtered.sort((a, b) => {
55
+ if (b.useCount !== a.useCount) {
56
+ return b.useCount - a.useCount;
57
+ }
58
+ return new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime();
59
+ });
60
+ return filtered.slice(0, limit);
61
+ }
62
+ /**
63
+ * Gets recent projects for a profile
64
+ * Returns unique projects sorted by most recently used workflow
65
+ */
66
+ export async function getRecentProjects(profileName, limit = 5) {
67
+ const cache = await loadCache();
68
+ const filtered = cache.entries.filter(e => e.profileName === profileName);
69
+ // Group by project and get most recent usage
70
+ const projectMap = new Map();
71
+ for (const entry of filtered) {
72
+ const existing = projectMap.get(entry.projectId);
73
+ if (!existing || new Date(entry.lastUsed) > new Date(existing.lastUsed)) {
74
+ projectMap.set(entry.projectId, {
75
+ projectId: entry.projectId,
76
+ projectName: entry.projectName,
77
+ lastUsed: entry.lastUsed
78
+ });
79
+ }
80
+ }
81
+ // Convert to array and sort by most recent
82
+ const projects = Array.from(projectMap.values());
83
+ projects.sort((a, b) => new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime());
84
+ return projects.slice(0, limit);
85
+ }
86
+ /**
87
+ * Clears all cached workflows for a specific profile
88
+ */
89
+ export async function clearCacheForProfile(profileName) {
90
+ const cache = await loadCache();
91
+ cache.entries = cache.entries.filter(e => e.profileName !== profileName);
92
+ await saveCache(cache);
93
+ }
94
+ /**
95
+ * Clears the entire cache
96
+ */
97
+ export async function clearCache() {
98
+ if (existsSync(CACHE_FILE)) {
99
+ await fs.unlink(CACHE_FILE);
100
+ }
101
+ }
102
+ /**
103
+ * Evicts old entries based on LRU and per-profile limits
104
+ */
105
+ async function evictOldEntries(cache) {
106
+ // Overall limit - keep most recently used
107
+ if (cache.entries.length > MAX_ENTRIES) {
108
+ cache.entries.sort((a, b) => new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime());
109
+ cache.entries = cache.entries.slice(0, MAX_ENTRIES);
110
+ }
111
+ // Per-profile limit - keep most frequently used within each profile
112
+ const profileGroups = new Map();
113
+ for (const entry of cache.entries) {
114
+ if (!profileGroups.has(entry.profileName)) {
115
+ profileGroups.set(entry.profileName, []);
116
+ }
117
+ profileGroups.get(entry.profileName).push(entry);
118
+ }
119
+ const kept = [];
120
+ for (const [, entries] of profileGroups) {
121
+ // Sort by useCount (desc), then lastUsed (desc)
122
+ entries.sort((a, b) => {
123
+ if (b.useCount !== a.useCount)
124
+ return b.useCount - a.useCount;
125
+ return new Date(b.lastUsed).getTime() - new Date(a.lastUsed).getTime();
126
+ });
127
+ kept.push(...entries.slice(0, MAX_ENTRIES_PER_PROFILE));
128
+ }
129
+ cache.entries = kept;
130
+ }
131
+ /**
132
+ * Loads the cache from disk
133
+ * Returns empty cache if file doesn't exist or can't be parsed
134
+ */
135
+ async function loadCache() {
136
+ try {
137
+ if (!existsSync(CACHE_FILE)) {
138
+ return { version: CACHE_VERSION, entries: [] };
139
+ }
140
+ const content = await fs.readFile(CACHE_FILE, 'utf-8');
141
+ const cache = JSON.parse(content);
142
+ // Validate version and structure
143
+ if (!cache.version || !Array.isArray(cache.entries)) {
144
+ return { version: CACHE_VERSION, entries: [] };
145
+ }
146
+ return cache;
147
+ }
148
+ catch {
149
+ // If we can't read or parse the cache, return empty cache
150
+ return { version: CACHE_VERSION, entries: [] };
151
+ }
152
+ }
153
+ /**
154
+ * Saves the cache to disk with restricted permissions
155
+ */
156
+ async function saveCache(cache) {
157
+ try {
158
+ // Ensure directory exists
159
+ if (!existsSync(CACHE_DIR)) {
160
+ await fs.mkdir(CACHE_DIR, { recursive: true, mode: 0o700 });
161
+ }
162
+ // Write cache file with restricted permissions (only user can read/write)
163
+ const content = JSON.stringify(cache, null, 2);
164
+ await fs.writeFile(CACHE_FILE, content, { mode: 0o600 });
165
+ }
166
+ catch (error) {
167
+ // Silently fail if we can't write the cache
168
+ // This shouldn't break the CLI functionality
169
+ console.error('Warning: Failed to save recent workflows cache:', error instanceof Error ? error.message : 'Unknown error');
170
+ }
171
+ }
172
+ //# sourceMappingURL=recent-workflows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent-workflows.js","sourceRoot":"","sources":["../../src/utils/recent-workflows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { StudioApiClient } from '../services/studio-api-client.js';
2
+ export type { StudioProfile, StudioAuthTokens, StartWorkflowConfiguration, WorkflowStartResponse, FetchWorkflowRunResponse, FetchWorkflowRunListItem, SearchParams } from '../types.js';
3
+ //# sourceMappingURL=studio-api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio-api-client.d.ts","sourceRoot":"","sources":["../../src/utils/studio-api-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGnE,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,YAAY,EACb,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Re-export from service layer
2
+ export { StudioApiClient } from '../services/studio-api-client.js';
3
+ //# sourceMappingURL=studio-api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio-api-client.js","sourceRoot":"","sources":["../../src/utils/studio-api-client.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { StudioApiClient } from '../services/studio-api-client.js';
2
+ import type { StudioProfile, StudioAuthTokens, StartWorkflowConfiguration, WorkflowStartResponse, FetchWorkflowRunResponse, FetchWorkflowRunListItem, SearchParams } from '../types.js';
3
+ /**
4
+ * Creates a Studio API client with automatic token refresh handling.
5
+ *
6
+ * This factory function:
7
+ * 1. Loads the specified profile (or default) and validates authentication
8
+ * 2. Creates a StudioApiClient instance
9
+ * 3. Wraps API calls to handle token refresh on 401 errors
10
+ *
11
+ * @param profileName - Optional profile name (defaults to active profile)
12
+ * @returns StudioApiClient instance with token refresh capability
13
+ * @throws Error if profile not found or tokens invalid/expired
14
+ */
15
+ export declare function createStudioApiClient(profileName?: string): Promise<StudioApiClient>;
16
+ /**
17
+ * Convenience function to start a workflow execution.
18
+ *
19
+ * @param projectId - Project ID containing the workflow
20
+ * @param workflowId - Workflow ID to execute
21
+ * @param startConfiguration - Workflow input configuration
22
+ * @param profileName - Optional profile name
23
+ * @returns Workflow start response with run ID and task ARN
24
+ */
25
+ export declare function startWorkflow(projectId: string, workflowId: string, startConfiguration: StartWorkflowConfiguration, profileName?: string): Promise<WorkflowStartResponse>;
26
+ /**
27
+ * Convenience function to get workflow run details.
28
+ *
29
+ * @param workflowId - Workflow ID
30
+ * @param runId - Run ID to fetch
31
+ * @param profileName - Optional profile name
32
+ * @returns Workflow run details
33
+ */
34
+ export declare function getWorkflowRun(workflowId: string, runId: string, profileName?: string): Promise<FetchWorkflowRunResponse>;
35
+ /**
36
+ * Convenience function to search workflow runs.
37
+ *
38
+ * @param params - Search parameters (filters, pagination, sorting)
39
+ * @param profileName - Optional profile name
40
+ * @returns List of workflow runs matching search criteria
41
+ */
42
+ export declare function searchWorkflowRuns(params: SearchParams, profileName?: string): Promise<FetchWorkflowRunListItem>;
43
+ /**
44
+ * Convenience function to stop a running workflow.
45
+ *
46
+ * @param projectId - Project ID containing the workflow
47
+ * @param workflowId - Workflow ID
48
+ * @param runId - Run ID to stop
49
+ * @param profileName - Optional profile name
50
+ */
51
+ export declare function stopWorkflowRun(projectId: string, workflowId: string, runId: string, profileName?: string): Promise<void>;
52
+ export type { StudioProfile, StudioAuthTokens, StartWorkflowConfiguration, WorkflowStartResponse, FetchWorkflowRunResponse, FetchWorkflowRunListItem, SearchParams };
53
+ //# sourceMappingURL=studio-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio-api.d.ts","sourceRoot":"","sources":["../../src/utils/studio-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOnE,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,YAAY,EACb,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA+C1F;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,0BAA0B,EAC9C,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAGhC;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAGnC;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,YAAY,EACpB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAGnC;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAGD,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,YAAY,EACb,CAAC"}
@@ -0,0 +1,102 @@
1
+ // Service layer imports
2
+ import { StudioApiClient } from '../services/studio-api-client.js';
3
+ import { CognitoAuthService } from '../services/cognito-auth.js';
4
+ // Utility imports
5
+ import { getAuthenticatedProfile, saveTokens } from './studio-config.js';
6
+ /**
7
+ * Creates a Studio API client with automatic token refresh handling.
8
+ *
9
+ * This factory function:
10
+ * 1. Loads the specified profile (or default) and validates authentication
11
+ * 2. Creates a StudioApiClient instance
12
+ * 3. Wraps API calls to handle token refresh on 401 errors
13
+ *
14
+ * @param profileName - Optional profile name (defaults to active profile)
15
+ * @returns StudioApiClient instance with token refresh capability
16
+ * @throws Error if profile not found or tokens invalid/expired
17
+ */
18
+ export async function createStudioApiClient(profileName) {
19
+ const { profile, tokens } = await getAuthenticatedProfile(profileName);
20
+ // Create base client
21
+ const client = new StudioApiClient(profile, tokens);
22
+ // Wrap client methods to handle token refresh on 401
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ const originalRequest = client._makeRequest.bind(client);
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ client._makeRequest = async function (method, path, body, queryParams) {
27
+ try {
28
+ return await originalRequest(method, path, body, queryParams);
29
+ }
30
+ catch (error) {
31
+ // If 401 error, attempt token refresh and retry
32
+ const errorWithStatus = error;
33
+ if (errorWithStatus.statusCode === 401) {
34
+ try {
35
+ const authService = new CognitoAuthService(profile);
36
+ const newTokens = await authService.refreshTokens(tokens.refreshToken);
37
+ // Save refreshed tokens
38
+ await saveTokens(profile.name, newTokens);
39
+ // Update client tokens
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ client.tokens = newTokens;
42
+ // Retry original request with new tokens
43
+ return await originalRequest(method, path, body, queryParams);
44
+ }
45
+ catch {
46
+ throw new Error(`Authentication failed and token refresh unsuccessful. Run "sembix login --profile ${profile.name}" to re-authenticate.`);
47
+ }
48
+ }
49
+ throw error;
50
+ }
51
+ };
52
+ return client;
53
+ }
54
+ /**
55
+ * Convenience function to start a workflow execution.
56
+ *
57
+ * @param projectId - Project ID containing the workflow
58
+ * @param workflowId - Workflow ID to execute
59
+ * @param startConfiguration - Workflow input configuration
60
+ * @param profileName - Optional profile name
61
+ * @returns Workflow start response with run ID and task ARN
62
+ */
63
+ export async function startWorkflow(projectId, workflowId, startConfiguration, profileName) {
64
+ const client = await createStudioApiClient(profileName);
65
+ return client.startWorkflow(projectId, workflowId, startConfiguration);
66
+ }
67
+ /**
68
+ * Convenience function to get workflow run details.
69
+ *
70
+ * @param workflowId - Workflow ID
71
+ * @param runId - Run ID to fetch
72
+ * @param profileName - Optional profile name
73
+ * @returns Workflow run details
74
+ */
75
+ export async function getWorkflowRun(workflowId, runId, profileName) {
76
+ const client = await createStudioApiClient(profileName);
77
+ return client.getWorkflowRun(workflowId, runId);
78
+ }
79
+ /**
80
+ * Convenience function to search workflow runs.
81
+ *
82
+ * @param params - Search parameters (filters, pagination, sorting)
83
+ * @param profileName - Optional profile name
84
+ * @returns List of workflow runs matching search criteria
85
+ */
86
+ export async function searchWorkflowRuns(params, profileName) {
87
+ const client = await createStudioApiClient(profileName);
88
+ return client.searchWorkflowRuns(params);
89
+ }
90
+ /**
91
+ * Convenience function to stop a running workflow.
92
+ *
93
+ * @param projectId - Project ID containing the workflow
94
+ * @param workflowId - Workflow ID
95
+ * @param runId - Run ID to stop
96
+ * @param profileName - Optional profile name
97
+ */
98
+ export async function stopWorkflowRun(projectId, workflowId, runId, profileName) {
99
+ const client = await createStudioApiClient(profileName);
100
+ return client.stopWorkflowRun(projectId, workflowId, runId);
101
+ }
102
+ //# sourceMappingURL=studio-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio-api.js","sourceRoot":"","sources":["../../src/utils/studio-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ export { readProfile, writeProfile, listProfiles, getDefaultProfile, setDefaultProfile, deleteProfile, type StudioProfile, type StudioConfig } from './config-file.js';
2
+ import type { StudioAuthTokens } from '../types.js';
3
+ import type { StudioProfile } from './config-file.js';
4
+ /**
5
+ * Saves authentication tokens for a profile
6
+ * Tokens are stored in ~/.sembix/tokens/{profile-name}.json with 0o600 permissions
7
+ *
8
+ * @param profileName - Name of the profile
9
+ * @param tokens - Authentication tokens to save
10
+ */
11
+ export declare function saveTokens(profileName: string, tokens: StudioAuthTokens): Promise<void>;
12
+ /**
13
+ * Loads authentication tokens for a profile
14
+ * Returns undefined if tokens don't exist or file cannot be read
15
+ *
16
+ * @param profileName - Name of the profile
17
+ * @returns Authentication tokens or undefined if not found
18
+ */
19
+ export declare function loadTokens(profileName: string): Promise<StudioAuthTokens | undefined>;
20
+ /**
21
+ * Deletes stored authentication tokens for a profile
22
+ *
23
+ * @param profileName - Name of the profile
24
+ */
25
+ export declare function deleteTokens(profileName: string): Promise<void>;
26
+ /**
27
+ * Checks if authentication tokens are still valid based on expiration time
28
+ *
29
+ * @param tokens - Authentication tokens to validate
30
+ * @returns true if tokens are valid and not expired
31
+ */
32
+ export declare function isTokenValid(tokens: StudioAuthTokens): boolean;
33
+ /**
34
+ * Lists all profiles that have stored authentication tokens
35
+ *
36
+ * @returns Array of profile names with stored tokens
37
+ */
38
+ export declare function listTokenProfiles(): Promise<string[]>;
39
+ /**
40
+ * Gets token information for a profile without exposing the token values
41
+ * Useful for displaying token status to users
42
+ *
43
+ * @param profileName - Name of the profile
44
+ * @returns Object with token status information or undefined if no tokens exist
45
+ */
46
+ export declare function getTokenInfo(profileName: string): Promise<{
47
+ expiresAt: string;
48
+ isValid: boolean;
49
+ } | undefined>;
50
+ /**
51
+ * Gets the active Studio profile, using the specified profile name or falling back to default
52
+ * Throws an error if no profile is found
53
+ *
54
+ * @param profileName - Optional profile name to use
55
+ * @returns The active Studio profile
56
+ * @throws Error if no profile is configured
57
+ */
58
+ export declare function getActiveProfile(profileName?: string): Promise<StudioProfile>;
59
+ /**
60
+ * Gets the active profile with valid authentication tokens
61
+ * Supports multiple authentication methods with priority:
62
+ * 1. Client credentials (CI/CD)
63
+ * 2. Stored tokens (file-based)
64
+ * 3. Interactive login (if TTY available)
65
+ *
66
+ * @param profileName - Optional profile name to use
67
+ * @returns Object containing the profile and valid tokens
68
+ * @throws Error if authentication fails
69
+ */
70
+ export declare function getAuthenticatedProfile(profileName?: string): Promise<{
71
+ profile: StudioProfile;
72
+ tokens: StudioAuthTokens;
73
+ }>;
74
+ //# sourceMappingURL=studio-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studio-config.d.ts","sourceRoot":"","sources":["../../src/utils/studio-config.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAwBtD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7F;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAW3F;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAU9D;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAY3D;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAAC,CASpH;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmBnF;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3E,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC,CAqED"}
@@ -0,0 +1,213 @@
1
+ import { homedir } from 'os';
2
+ import { join } from 'path';
3
+ import { promises as fs } from 'fs';
4
+ import { existsSync } from 'fs';
5
+ // Re-export profile management functions from config-file
6
+ export { readProfile, writeProfile, listProfiles, getDefaultProfile, setDefaultProfile, deleteProfile } from './config-file.js';
7
+ import { readProfile, getDefaultProfile } from './config-file.js';
8
+ import { hasClientCredentials, isInteractive } from './environment.js';
9
+ import { CognitoAuthService } from '../services/cognito-auth.js';
10
+ // Token storage directory
11
+ const TOKENS_DIR = join(homedir(), '.sembix', 'tokens');
12
+ /**
13
+ * Ensures the tokens directory exists with secure permissions
14
+ */
15
+ async function ensureTokensDirectory() {
16
+ if (!existsSync(TOKENS_DIR)) {
17
+ await fs.mkdir(TOKENS_DIR, { recursive: true, mode: 0o700 });
18
+ }
19
+ }
20
+ /**
21
+ * Gets the file path for a profile's token storage
22
+ */
23
+ function getTokenFilePath(profileName) {
24
+ return join(TOKENS_DIR, `${profileName}.json`);
25
+ }
26
+ /**
27
+ * Saves authentication tokens for a profile
28
+ * Tokens are stored in ~/.sembix/tokens/{profile-name}.json with 0o600 permissions
29
+ *
30
+ * @param profileName - Name of the profile
31
+ * @param tokens - Authentication tokens to save
32
+ */
33
+ export async function saveTokens(profileName, tokens) {
34
+ await ensureTokensDirectory();
35
+ const tokenFile = getTokenFilePath(profileName);
36
+ const content = JSON.stringify(tokens, null, 2);
37
+ await fs.writeFile(tokenFile, content, { mode: 0o600 });
38
+ }
39
+ /**
40
+ * Loads authentication tokens for a profile
41
+ * Returns undefined if tokens don't exist or file cannot be read
42
+ *
43
+ * @param profileName - Name of the profile
44
+ * @returns Authentication tokens or undefined if not found
45
+ */
46
+ export async function loadTokens(profileName) {
47
+ try {
48
+ const tokenFile = getTokenFilePath(profileName);
49
+ if (!existsSync(tokenFile)) {
50
+ return undefined;
51
+ }
52
+ const content = await fs.readFile(tokenFile, 'utf-8');
53
+ return JSON.parse(content);
54
+ }
55
+ catch {
56
+ return undefined;
57
+ }
58
+ }
59
+ /**
60
+ * Deletes stored authentication tokens for a profile
61
+ *
62
+ * @param profileName - Name of the profile
63
+ */
64
+ export async function deleteTokens(profileName) {
65
+ try {
66
+ const tokenFile = getTokenFilePath(profileName);
67
+ if (existsSync(tokenFile)) {
68
+ await fs.unlink(tokenFile);
69
+ }
70
+ }
71
+ catch {
72
+ // Ignore errors if file doesn't exist
73
+ }
74
+ }
75
+ /**
76
+ * Checks if authentication tokens are still valid based on expiration time
77
+ *
78
+ * @param tokens - Authentication tokens to validate
79
+ * @returns true if tokens are valid and not expired
80
+ */
81
+ export function isTokenValid(tokens) {
82
+ try {
83
+ const expiresAt = new Date(tokens.expiresAt);
84
+ const now = new Date();
85
+ // Add 5 minute buffer to account for clock skew and request time
86
+ const bufferMs = 5 * 60 * 1000;
87
+ return expiresAt.getTime() - now.getTime() > bufferMs;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ /**
94
+ * Lists all profiles that have stored authentication tokens
95
+ *
96
+ * @returns Array of profile names with stored tokens
97
+ */
98
+ export async function listTokenProfiles() {
99
+ try {
100
+ if (!existsSync(TOKENS_DIR)) {
101
+ return [];
102
+ }
103
+ const files = await fs.readdir(TOKENS_DIR);
104
+ return files
105
+ .filter(file => file.endsWith('.json'))
106
+ .map(file => file.replace('.json', ''));
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ }
112
+ /**
113
+ * Gets token information for a profile without exposing the token values
114
+ * Useful for displaying token status to users
115
+ *
116
+ * @param profileName - Name of the profile
117
+ * @returns Object with token status information or undefined if no tokens exist
118
+ */
119
+ export async function getTokenInfo(profileName) {
120
+ const tokens = await loadTokens(profileName);
121
+ if (!tokens) {
122
+ return undefined;
123
+ }
124
+ return {
125
+ expiresAt: tokens.expiresAt,
126
+ isValid: isTokenValid(tokens)
127
+ };
128
+ }
129
+ /**
130
+ * Gets the active Studio profile, using the specified profile name or falling back to default
131
+ * Throws an error if no profile is found
132
+ *
133
+ * @param profileName - Optional profile name to use
134
+ * @returns The active Studio profile
135
+ * @throws Error if no profile is configured
136
+ */
137
+ export async function getActiveProfile(profileName) {
138
+ // Try to get the specified profile or default profile
139
+ const targetProfile = profileName || await getDefaultProfile();
140
+ if (!targetProfile) {
141
+ throw new Error('No Studio profile configured. Run "sembix configure" to set up a profile.');
142
+ }
143
+ const profile = await readProfile(targetProfile);
144
+ if (!profile) {
145
+ throw new Error(`Profile "${targetProfile}" not found. Run "sembix profile list" to see available profiles.`);
146
+ }
147
+ return profile;
148
+ }
149
+ /**
150
+ * Gets the active profile with valid authentication tokens
151
+ * Supports multiple authentication methods with priority:
152
+ * 1. Client credentials (CI/CD)
153
+ * 2. Stored tokens (file-based)
154
+ * 3. Interactive login (if TTY available)
155
+ *
156
+ * @param profileName - Optional profile name to use
157
+ * @returns Object containing the profile and valid tokens
158
+ * @throws Error if authentication fails
159
+ */
160
+ export async function getAuthenticatedProfile(profileName) {
161
+ const profile = await getActiveProfile(profileName);
162
+ // Priority 1: Check for client credentials (CI/CD)
163
+ if (hasClientCredentials()) {
164
+ const clientId = process.env.SEMBIX_CLIENT_ID;
165
+ const clientSecret = process.env.SEMBIX_CLIENT_SECRET;
166
+ try {
167
+ const authService = new CognitoAuthService(profile);
168
+ const tokens = await authService.authenticateWithClientCredentials(clientId, clientSecret);
169
+ return { profile, tokens };
170
+ }
171
+ catch (error) {
172
+ throw new Error(`Client credentials authentication failed: ${error instanceof Error ? error.message : String(error)}\n\n` +
173
+ `Check that SEMBIX_CLIENT_ID and SEMBIX_CLIENT_SECRET are correct.`);
174
+ }
175
+ }
176
+ // Priority 2: Load stored tokens
177
+ let tokens = await loadTokens(profile.name);
178
+ if (!tokens) {
179
+ // No stored tokens - guide user based on environment
180
+ if (isInteractive()) {
181
+ throw new Error(`No authentication tokens found for profile "${profile.name}".\n\n` +
182
+ `Run: sembix login --profile ${profile.name}`);
183
+ }
184
+ else {
185
+ throw new Error(`No authentication tokens found for profile "${profile.name}".\n\n` +
186
+ `For CI/CD environments, set these environment variables:\n` +
187
+ ` SEMBIX_CLIENT_ID=<your-m2m-client-id>\n` +
188
+ ` SEMBIX_CLIENT_SECRET=<your-m2m-client-secret>\n\n` +
189
+ `For interactive environments, run: sembix login --profile ${profile.name}`);
190
+ }
191
+ }
192
+ // Validate token expiry
193
+ if (!isTokenValid(tokens)) {
194
+ // Try to refresh if we have a refresh token
195
+ if (tokens.refreshToken) {
196
+ try {
197
+ const authService = new CognitoAuthService(profile);
198
+ tokens = await authService.refreshTokens(tokens.refreshToken);
199
+ await saveTokens(profile.name, tokens);
200
+ return { profile, tokens };
201
+ }
202
+ catch {
203
+ // Refresh failed - need to re-authenticate
204
+ throw new Error(`Authentication tokens for profile "${profile.name}" have expired and could not be refreshed.\n\n` +
205
+ `Run: sembix login --profile ${profile.name}`);
206
+ }
207
+ }
208
+ throw new Error(`Authentication tokens for profile "${profile.name}" have expired.\n\n` +
209
+ `Run: sembix login --profile ${profile.name}`);
210
+ }
211
+ return { profile, tokens };
212
+ }
213
+ //# sourceMappingURL=studio-config.js.map