@mainwp/control 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +583 -0
  3. package/bin/_exit.js +12 -0
  4. package/bin/dev.js +7 -0
  5. package/bin/run.js +7 -0
  6. package/dist/chat/chat-engine.d.ts +213 -0
  7. package/dist/chat/chat-engine.d.ts.map +1 -0
  8. package/dist/chat/chat-engine.js +636 -0
  9. package/dist/chat/chat-engine.js.map +1 -0
  10. package/dist/chat/index.d.ts +10 -0
  11. package/dist/chat/index.d.ts.map +1 -0
  12. package/dist/chat/index.js +14 -0
  13. package/dist/chat/index.js.map +1 -0
  14. package/dist/chat/providers/anthropic.d.ts +52 -0
  15. package/dist/chat/providers/anthropic.d.ts.map +1 -0
  16. package/dist/chat/providers/anthropic.js +292 -0
  17. package/dist/chat/providers/anthropic.js.map +1 -0
  18. package/dist/chat/providers/gemini.d.ts +52 -0
  19. package/dist/chat/providers/gemini.d.ts.map +1 -0
  20. package/dist/chat/providers/gemini.js +284 -0
  21. package/dist/chat/providers/gemini.js.map +1 -0
  22. package/dist/chat/providers/index.d.ts +19 -0
  23. package/dist/chat/providers/index.d.ts.map +1 -0
  24. package/dist/chat/providers/index.js +23 -0
  25. package/dist/chat/providers/index.js.map +1 -0
  26. package/dist/chat/providers/local.d.ts +37 -0
  27. package/dist/chat/providers/local.d.ts.map +1 -0
  28. package/dist/chat/providers/local.js +130 -0
  29. package/dist/chat/providers/local.js.map +1 -0
  30. package/dist/chat/providers/openai-compatible.d.ts +155 -0
  31. package/dist/chat/providers/openai-compatible.d.ts.map +1 -0
  32. package/dist/chat/providers/openai-compatible.js +264 -0
  33. package/dist/chat/providers/openai-compatible.js.map +1 -0
  34. package/dist/chat/providers/openai.d.ts +24 -0
  35. package/dist/chat/providers/openai.d.ts.map +1 -0
  36. package/dist/chat/providers/openai.js +62 -0
  37. package/dist/chat/providers/openai.js.map +1 -0
  38. package/dist/chat/providers/openrouter.d.ts +26 -0
  39. package/dist/chat/providers/openrouter.d.ts.map +1 -0
  40. package/dist/chat/providers/openrouter.js +65 -0
  41. package/dist/chat/providers/openrouter.js.map +1 -0
  42. package/dist/chat/providers/provider-fetch.d.ts +15 -0
  43. package/dist/chat/providers/provider-fetch.d.ts.map +1 -0
  44. package/dist/chat/providers/provider-fetch.js +35 -0
  45. package/dist/chat/providers/provider-fetch.js.map +1 -0
  46. package/dist/chat/providers/provider.d.ts +214 -0
  47. package/dist/chat/providers/provider.d.ts.map +1 -0
  48. package/dist/chat/providers/provider.js +166 -0
  49. package/dist/chat/providers/provider.js.map +1 -0
  50. package/dist/chat/providers/sse-reader.d.ts +21 -0
  51. package/dist/chat/providers/sse-reader.d.ts.map +1 -0
  52. package/dist/chat/providers/sse-reader.js +48 -0
  53. package/dist/chat/providers/sse-reader.js.map +1 -0
  54. package/dist/chat/system-prompt.d.ts +33 -0
  55. package/dist/chat/system-prompt.d.ts.map +1 -0
  56. package/dist/chat/system-prompt.js +166 -0
  57. package/dist/chat/system-prompt.js.map +1 -0
  58. package/dist/chat/tool-envelope.d.ts +72 -0
  59. package/dist/chat/tool-envelope.d.ts.map +1 -0
  60. package/dist/chat/tool-envelope.js +263 -0
  61. package/dist/chat/tool-envelope.js.map +1 -0
  62. package/dist/commands/abilities/info.d.ts +21 -0
  63. package/dist/commands/abilities/info.d.ts.map +1 -0
  64. package/dist/commands/abilities/info.js +80 -0
  65. package/dist/commands/abilities/info.js.map +1 -0
  66. package/dist/commands/abilities/list.d.ts +19 -0
  67. package/dist/commands/abilities/list.d.ts.map +1 -0
  68. package/dist/commands/abilities/list.js +98 -0
  69. package/dist/commands/abilities/list.js.map +1 -0
  70. package/dist/commands/abilities/run.d.ts +75 -0
  71. package/dist/commands/abilities/run.d.ts.map +1 -0
  72. package/dist/commands/abilities/run.js +468 -0
  73. package/dist/commands/abilities/run.js.map +1 -0
  74. package/dist/commands/chat.d.ts +54 -0
  75. package/dist/commands/chat.d.ts.map +1 -0
  76. package/dist/commands/chat.js +384 -0
  77. package/dist/commands/chat.js.map +1 -0
  78. package/dist/commands/config/show.d.ts +54 -0
  79. package/dist/commands/config/show.d.ts.map +1 -0
  80. package/dist/commands/config/show.js +324 -0
  81. package/dist/commands/config/show.js.map +1 -0
  82. package/dist/commands/doctor.d.ts +77 -0
  83. package/dist/commands/doctor.d.ts.map +1 -0
  84. package/dist/commands/doctor.js +412 -0
  85. package/dist/commands/doctor.js.map +1 -0
  86. package/dist/commands/jobs/watch.d.ts +50 -0
  87. package/dist/commands/jobs/watch.d.ts.map +1 -0
  88. package/dist/commands/jobs/watch.js +269 -0
  89. package/dist/commands/jobs/watch.js.map +1 -0
  90. package/dist/commands/login.d.ts +25 -0
  91. package/dist/commands/login.d.ts.map +1 -0
  92. package/dist/commands/login.js +165 -0
  93. package/dist/commands/login.js.map +1 -0
  94. package/dist/commands/profile/delete.d.ts +22 -0
  95. package/dist/commands/profile/delete.d.ts.map +1 -0
  96. package/dist/commands/profile/delete.js +57 -0
  97. package/dist/commands/profile/delete.js.map +1 -0
  98. package/dist/commands/profile/list.d.ts +19 -0
  99. package/dist/commands/profile/list.d.ts.map +1 -0
  100. package/dist/commands/profile/list.js +53 -0
  101. package/dist/commands/profile/list.js.map +1 -0
  102. package/dist/commands/profile/use.d.ts +22 -0
  103. package/dist/commands/profile/use.d.ts.map +1 -0
  104. package/dist/commands/profile/use.js +46 -0
  105. package/dist/commands/profile/use.js.map +1 -0
  106. package/dist/config/fs-utils.d.ts +14 -0
  107. package/dist/config/fs-utils.d.ts.map +1 -0
  108. package/dist/config/fs-utils.js +31 -0
  109. package/dist/config/fs-utils.js.map +1 -0
  110. package/dist/config/keychain.d.ts +53 -0
  111. package/dist/config/keychain.d.ts.map +1 -0
  112. package/dist/config/keychain.js +175 -0
  113. package/dist/config/keychain.js.map +1 -0
  114. package/dist/config/profile-store.d.ts +85 -0
  115. package/dist/config/profile-store.d.ts.map +1 -0
  116. package/dist/config/profile-store.js +228 -0
  117. package/dist/config/profile-store.js.map +1 -0
  118. package/dist/config/settings.d.ts +71 -0
  119. package/dist/config/settings.d.ts.map +1 -0
  120. package/dist/config/settings.js +151 -0
  121. package/dist/config/settings.js.map +1 -0
  122. package/dist/core/abilities-executor.d.ts +126 -0
  123. package/dist/core/abilities-executor.d.ts.map +1 -0
  124. package/dist/core/abilities-executor.js +264 -0
  125. package/dist/core/abilities-executor.js.map +1 -0
  126. package/dist/core/batch-manager.d.ts +113 -0
  127. package/dist/core/batch-manager.d.ts.map +1 -0
  128. package/dist/core/batch-manager.js +244 -0
  129. package/dist/core/batch-manager.js.map +1 -0
  130. package/dist/core/http-client.d.ts +111 -0
  131. package/dist/core/http-client.d.ts.map +1 -0
  132. package/dist/core/http-client.js +329 -0
  133. package/dist/core/http-client.js.map +1 -0
  134. package/dist/core/safety-controller.d.ts +114 -0
  135. package/dist/core/safety-controller.d.ts.map +1 -0
  136. package/dist/core/safety-controller.js +229 -0
  137. package/dist/core/safety-controller.js.map +1 -0
  138. package/dist/hooks/command-not-found.d.ts +12 -0
  139. package/dist/hooks/command-not-found.d.ts.map +1 -0
  140. package/dist/hooks/command-not-found.js +58 -0
  141. package/dist/hooks/command-not-found.js.map +1 -0
  142. package/dist/index.d.ts +7 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +7 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/lib/base-command.d.ts +123 -0
  147. package/dist/lib/base-command.d.ts.map +1 -0
  148. package/dist/lib/base-command.js +285 -0
  149. package/dist/lib/base-command.js.map +1 -0
  150. package/dist/output/formatter.d.ts +48 -0
  151. package/dist/output/formatter.d.ts.map +1 -0
  152. package/dist/output/formatter.js +138 -0
  153. package/dist/output/formatter.js.map +1 -0
  154. package/dist/output/json-envelope.d.ts +43 -0
  155. package/dist/output/json-envelope.d.ts.map +1 -0
  156. package/dist/output/json-envelope.js +73 -0
  157. package/dist/output/json-envelope.js.map +1 -0
  158. package/dist/utils/audit-logger.d.ts +97 -0
  159. package/dist/utils/audit-logger.d.ts.map +1 -0
  160. package/dist/utils/audit-logger.js +169 -0
  161. package/dist/utils/audit-logger.js.map +1 -0
  162. package/dist/utils/colors.d.ts +29 -0
  163. package/dist/utils/colors.d.ts.map +1 -0
  164. package/dist/utils/colors.js +36 -0
  165. package/dist/utils/colors.js.map +1 -0
  166. package/dist/utils/errors.d.ts +107 -0
  167. package/dist/utils/errors.d.ts.map +1 -0
  168. package/dist/utils/errors.js +149 -0
  169. package/dist/utils/errors.js.map +1 -0
  170. package/dist/utils/exit-codes.d.ts +21 -0
  171. package/dist/utils/exit-codes.d.ts.map +1 -0
  172. package/dist/utils/exit-codes.js +20 -0
  173. package/dist/utils/exit-codes.js.map +1 -0
  174. package/dist/utils/format.d.ts +64 -0
  175. package/dist/utils/format.d.ts.map +1 -0
  176. package/dist/utils/format.js +69 -0
  177. package/dist/utils/format.js.map +1 -0
  178. package/dist/utils/prompt.d.ts +34 -0
  179. package/dist/utils/prompt.d.ts.map +1 -0
  180. package/dist/utils/prompt.js +132 -0
  181. package/dist/utils/prompt.js.map +1 -0
  182. package/dist/utils/retry.d.ts +59 -0
  183. package/dist/utils/retry.d.ts.map +1 -0
  184. package/dist/utils/retry.js +96 -0
  185. package/dist/utils/retry.js.map +1 -0
  186. package/dist/utils/terminal-sanitizer.d.ts +60 -0
  187. package/dist/utils/terminal-sanitizer.d.ts.map +1 -0
  188. package/dist/utils/terminal-sanitizer.js +166 -0
  189. package/dist/utils/terminal-sanitizer.js.map +1 -0
  190. package/dist/validation/input-sanitizer.d.ts +76 -0
  191. package/dist/validation/input-sanitizer.d.ts.map +1 -0
  192. package/dist/validation/input-sanitizer.js +199 -0
  193. package/dist/validation/input-sanitizer.js.map +1 -0
  194. package/dist/validation/schema-validator.d.ts +75 -0
  195. package/dist/validation/schema-validator.d.ts.map +1 -0
  196. package/dist/validation/schema-validator.js +147 -0
  197. package/dist/validation/schema-validator.js.map +1 -0
  198. package/oclif.manifest.json +857 -0
  199. package/package.json +101 -0
  200. package/scripts/completions/README.md +221 -0
  201. package/scripts/completions/mainwpcontrol.bash +193 -0
  202. package/scripts/completions/mainwpcontrol.zsh +267 -0
  203. package/scripts/completions/profile-completer.sh +35 -0
  204. package/scripts/completions/regenerate.sh +78 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Abilities Executor for mainwpcontrol
3
+ *
4
+ * Single execution pathway for all ability calls.
5
+ * INVARIANT: Both commands and chat route through this module.
6
+ */
7
+ import { createHttpClient } from './http-client.js';
8
+ import { APIError, InputError } from '../utils/errors.js';
9
+ import { getInputSanitizer } from '../validation/input-sanitizer.js';
10
+ /**
11
+ * Abilities Executor class
12
+ */
13
+ export class AbilitiesExecutor {
14
+ httpClient;
15
+ baseEndpoint = '/wp-json/wp-abilities/v1';
16
+ abilitiesCache = null;
17
+ cacheExpiry = 0;
18
+ cacheTTL = 5 * 60 * 1000; // 5 minutes
19
+ constructor(config) {
20
+ this.httpClient = createHttpClient(config);
21
+ }
22
+ /**
23
+ * List all available abilities
24
+ */
25
+ async listAbilities() {
26
+ await this.ensureCache();
27
+ // Return only full-name entries (cache also stores short names for lookups)
28
+ return Array.from(this.abilitiesCache?.entries() ?? [])
29
+ .filter(([key, ability]) => key === ability.name)
30
+ .map(([, ability]) => ability);
31
+ }
32
+ /**
33
+ * Get a single ability by name
34
+ */
35
+ async getAbility(name) {
36
+ await this.ensureCache();
37
+ return this.abilitiesCache?.get(this.normalizeName(name));
38
+ }
39
+ /**
40
+ * Execute an ability
41
+ *
42
+ * @param abilityName - The ability name (e.g., "list-sites-v1" or "mainwp/list-sites-v1")
43
+ * @param input - The input parameters
44
+ * @param options - Execution options (dryRun, confirm)
45
+ */
46
+ async execute(abilityName, input = {}, options) {
47
+ // Defense-in-depth: sanitize input before any processing
48
+ input = getInputSanitizer().sanitize(input);
49
+ const ability = await this.getAbility(abilityName);
50
+ if (!ability) {
51
+ throw new InputError(`Unknown ability: ${abilityName}`, undefined, 'List available abilities with `mainwpcontrol abilities list`');
52
+ }
53
+ // Build the request body
54
+ const body = this.buildRequestBody(input, options);
55
+ // Determine HTTP method based on annotations
56
+ const method = this.getHttpMethod(ability, options);
57
+ // Build the endpoint
58
+ // Ability names contain a namespace slash (e.g. "mainwp/list-sites-v1")
59
+ // which is part of the WordPress REST route — do NOT encode it.
60
+ const endpoint = `${this.baseEndpoint}/abilities/${ability.name}/run`;
61
+ try {
62
+ let response;
63
+ const requestOptions = options?.signal ? { signal: options.signal } : undefined;
64
+ if (method === 'GET') {
65
+ // For GET requests, nest input under input[key] (WordPress REST style).
66
+ // Control flags (dry_run, confirm) stay top-level.
67
+ const queryString = this.buildGetQueryString(input, options);
68
+ const url = queryString ? `${endpoint}?${queryString}` : endpoint;
69
+ response = await this.httpClient.get(url, requestOptions);
70
+ }
71
+ else if (method === 'DELETE') {
72
+ const queryString = this.buildGetQueryString(input, options);
73
+ const url = queryString ? `${endpoint}?${queryString}` : endpoint;
74
+ response = await this.httpClient.delete(url, requestOptions);
75
+ }
76
+ else {
77
+ // POST with JSON body
78
+ response = await this.httpClient.post(endpoint, body, requestOptions);
79
+ }
80
+ return this.normalizeResponse(response.data);
81
+ }
82
+ catch (error) {
83
+ if (error instanceof APIError) {
84
+ const errorObj = {
85
+ code: error.code,
86
+ message: error.message,
87
+ details: error.details,
88
+ };
89
+ if (error.hint) {
90
+ errorObj.hint = error.hint;
91
+ }
92
+ return {
93
+ success: false,
94
+ error: errorObj,
95
+ };
96
+ }
97
+ throw error;
98
+ }
99
+ }
100
+ /**
101
+ * Get ability categories
102
+ */
103
+ async getCategories() {
104
+ const abilities = await this.listAbilities();
105
+ const categories = new Set(abilities.map((a) => a.category));
106
+ return Array.from(categories).sort();
107
+ }
108
+ /**
109
+ * List abilities by category
110
+ */
111
+ async listByCategory(category) {
112
+ const abilities = await this.listAbilities();
113
+ return abilities.filter((a) => a.category.toLowerCase() === category.toLowerCase());
114
+ }
115
+ /**
116
+ * Ensure abilities cache is populated
117
+ */
118
+ async ensureCache() {
119
+ if (this.abilitiesCache && Date.now() < this.cacheExpiry) {
120
+ return;
121
+ }
122
+ this.abilitiesCache = new Map();
123
+ // Fetch all pages — API returns Ability[] with WP pagination headers.
124
+ let page = 1;
125
+ let totalPages = 1;
126
+ do {
127
+ const response = await this.httpClient.get(`${this.baseEndpoint}/abilities?per_page=100&page=${page}`);
128
+ const abilities = Array.isArray(response.data)
129
+ ? response.data
130
+ : response.data['abilities'] ?? [];
131
+ for (const ability of abilities) {
132
+ this.abilitiesCache.set(ability.name, ability);
133
+ const shortName = this.getShortName(ability.name);
134
+ if (shortName !== ability.name) {
135
+ this.abilitiesCache.set(shortName, ability);
136
+ }
137
+ }
138
+ // Read WP pagination header for total pages
139
+ const wpTotalPages = response.headers?.get?.('x-wp-totalpages');
140
+ if (wpTotalPages) {
141
+ totalPages = parseInt(wpTotalPages, 10) || 1;
142
+ }
143
+ page++;
144
+ } while (page <= totalPages);
145
+ this.cacheExpiry = Date.now() + this.cacheTTL;
146
+ }
147
+ /**
148
+ * Normalize ability name (handle with/without namespace)
149
+ */
150
+ normalizeName(name) {
151
+ // Remove leading slash if present
152
+ return name.replace(/^\//, '');
153
+ }
154
+ /**
155
+ * Get short name from full ability name
156
+ */
157
+ getShortName(fullName) {
158
+ const parts = fullName.split('/');
159
+ return parts[parts.length - 1] ?? fullName;
160
+ }
161
+ /**
162
+ * Build request body with execution options.
163
+ * The WP Abilities API expects: { input: { ...userInput, dry_run?, confirm? } }
164
+ */
165
+ buildRequestBody(input, options) {
166
+ const merged = { ...input };
167
+ // SECURITY: Strip control flags from user/LLM-provided input.
168
+ // These are set exclusively from execution options (CLI flags or safety flow).
169
+ delete merged['dry_run'];
170
+ delete merged['confirm'];
171
+ delete merged['user_confirmed'];
172
+ if (options?.dryRun) {
173
+ merged['dry_run'] = true;
174
+ }
175
+ if (options?.confirm) {
176
+ merged['confirm'] = true;
177
+ merged['user_confirmed'] = true;
178
+ }
179
+ return { input: merged };
180
+ }
181
+ /**
182
+ * Determine HTTP method based on ability annotations
183
+ */
184
+ getHttpMethod(ability, _options) {
185
+ const annotations = ability.meta?.annotations;
186
+ // If readonly, use GET
187
+ if (annotations?.readonly) {
188
+ return 'GET';
189
+ }
190
+ // If destructive and idempotent, use DELETE
191
+ if (annotations?.destructive && annotations?.idempotent) {
192
+ return 'DELETE';
193
+ }
194
+ // Default to POST for write operations
195
+ return 'POST';
196
+ }
197
+ /**
198
+ * Build query string for GET/DELETE requests with WordPress-style nesting.
199
+ * User input goes under input[key]=value; control flags stay top-level.
200
+ */
201
+ buildGetQueryString(input, options) {
202
+ const parts = [];
203
+ // SECURITY: Control flags managed exclusively by execution options
204
+ const controlFlags = ['dry_run', 'confirm', 'user_confirmed'];
205
+ // All params go under input[key] — the API treats input as a single object.
206
+ for (const [key, value] of Object.entries(input)) {
207
+ if (value === undefined || value === null)
208
+ continue;
209
+ if (controlFlags.includes(key))
210
+ continue;
211
+ const ek = encodeURIComponent(key);
212
+ if (Array.isArray(value)) {
213
+ // WordPress-style: input[key][0]=v0&input[key][1]=v1
214
+ value.forEach((v, i) => {
215
+ parts.push(`input[${ek}][${i}]=${encodeURIComponent(String(v))}`);
216
+ });
217
+ }
218
+ else if (typeof value === 'object') {
219
+ parts.push(`input[${ek}]=${encodeURIComponent(JSON.stringify(value))}`);
220
+ }
221
+ else {
222
+ parts.push(`input[${ek}]=${encodeURIComponent(String(value))}`);
223
+ }
224
+ }
225
+ if (options?.dryRun)
226
+ parts.push('input[dry_run]=true');
227
+ if (options?.confirm) {
228
+ parts.push('input[confirm]=true');
229
+ parts.push('input[user_confirmed]=true');
230
+ }
231
+ return parts.join('&');
232
+ }
233
+ /**
234
+ * Normalize API response to ExecutionResult
235
+ */
236
+ normalizeResponse(data) {
237
+ // If already in expected format, return as-is
238
+ if (typeof data === 'object' &&
239
+ data !== null &&
240
+ 'success' in data &&
241
+ typeof data['success'] === 'boolean') {
242
+ return data;
243
+ }
244
+ // Wrap raw data in success response
245
+ return {
246
+ success: true,
247
+ data: data,
248
+ };
249
+ }
250
+ /**
251
+ * Clear the abilities cache
252
+ */
253
+ clearCache() {
254
+ this.abilitiesCache = null;
255
+ this.cacheExpiry = 0;
256
+ }
257
+ }
258
+ /**
259
+ * Create an abilities executor from config
260
+ */
261
+ export function createAbilitiesExecutor(config) {
262
+ return new AbilitiesExecutor(config);
263
+ }
264
+ //# sourceMappingURL=abilities-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abilities-executor.js","sourceRoot":"","sources":["../../src/core/abilities-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Batch Manager for mainwpcontrol
3
+ *
4
+ * Handles batch operations with polling and resume capabilities.
5
+ * Provides exponential backoff for job status polling.
6
+ */
7
+ import { type HttpClientConfig } from './http-client.js';
8
+ /**
9
+ * Job status types
10
+ */
11
+ export type JobStatusType = 'pending' | 'running' | 'completed' | 'failed' | 'partial';
12
+ /**
13
+ * Job status response from API
14
+ */
15
+ export interface JobStatus {
16
+ /** Job identifier */
17
+ id: string;
18
+ /** Current job status */
19
+ status: JobStatusType;
20
+ /** Progress percentage (0-100) */
21
+ progress?: number | undefined;
22
+ /** Total items to process */
23
+ total?: number | undefined;
24
+ /** Items processed so far */
25
+ processed?: number | undefined;
26
+ /** Partial or complete results */
27
+ results?: unknown[] | undefined;
28
+ /** Errors encountered */
29
+ errors?: Array<{
30
+ item?: unknown | undefined;
31
+ message: string;
32
+ code?: string | undefined;
33
+ }> | undefined;
34
+ /** Job creation timestamp */
35
+ created_at?: string | undefined;
36
+ /** Job completion timestamp */
37
+ completed_at?: string | undefined;
38
+ }
39
+ /**
40
+ * Watch options for job polling
41
+ */
42
+ export interface WatchOptions {
43
+ /** Maximum total wait time in milliseconds (default: 5 minutes) */
44
+ maxWait?: number | undefined;
45
+ /** Initial poll delay in milliseconds (default: 1000) */
46
+ initialDelay?: number | undefined;
47
+ /** Maximum poll delay in milliseconds (default: 30000) */
48
+ maxDelay?: number | undefined;
49
+ /** Delay multiplier for backoff (default: 2) */
50
+ multiplier?: number | undefined;
51
+ /** Optional abort signal */
52
+ signal?: AbortSignal | undefined;
53
+ /** Callback for progress updates */
54
+ onProgress?: ((status: JobStatus) => void) | undefined;
55
+ }
56
+ /**
57
+ * Watch result
58
+ */
59
+ export interface WatchResult {
60
+ /** Final job status */
61
+ status: JobStatus;
62
+ /** Whether the operation timed out */
63
+ timedOut: boolean;
64
+ /** Total time spent waiting in milliseconds */
65
+ elapsed: number;
66
+ }
67
+ /**
68
+ * Batch Manager class
69
+ */
70
+ export declare class BatchManager {
71
+ private readonly httpClient;
72
+ private readonly baseEndpoint;
73
+ constructor(config: HttpClientConfig);
74
+ /**
75
+ * Watch a batch job status with exponential backoff polling
76
+ *
77
+ * Yields status updates as they're received.
78
+ * Completes when job finishes or times out.
79
+ */
80
+ watchJob(jobId: string, options?: WatchOptions): AsyncGenerator<JobStatus, WatchResult>;
81
+ /**
82
+ * Resume watching a batch job
83
+ *
84
+ * This is a convenience method that wraps watchJob for resuming
85
+ * a previously started job by its ID.
86
+ */
87
+ resumeJob(jobId: string, options?: WatchOptions): Promise<WatchResult>;
88
+ /**
89
+ * Get the current status of a batch job
90
+ */
91
+ getJobStatus(jobId: string, signal?: AbortSignal): Promise<JobStatus>;
92
+ /**
93
+ * Check if a status is terminal (job finished)
94
+ */
95
+ private isTerminalStatus;
96
+ /**
97
+ * Normalize API response to JobStatus, unwrapping success envelope if present
98
+ */
99
+ private normalizeJobStatus;
100
+ /**
101
+ * Parse job status string
102
+ */
103
+ private parseJobStatus;
104
+ /**
105
+ * Parse job errors
106
+ */
107
+ private parseJobErrors;
108
+ }
109
+ /**
110
+ * Create a batch manager from configuration
111
+ */
112
+ export declare function createBatchManager(config: HttpClientConfig): BatchManager;
113
+ //# sourceMappingURL=batch-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-manager.d.ts","sourceRoot":"","sources":["../../src/core/batch-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAIvF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,qBAAqB;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,yBAAyB;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAChC,yBAAyB;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC3B,CAAC,GAAG,SAAS,CAAC;IACf,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,4BAA4B;IAC5B,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,sCAAsC;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA8B;gBAE/C,MAAM,EAAE,gBAAgB;IAIpC;;;;;OAKG;IACI,QAAQ,CACb,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,YAAiB,GACzB,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC;IAmGzC;;;;;OAKG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAc5E;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;IAY3E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmC1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA2BtB;;OAEG;IACH,OAAO,CAAC,cAAc;CAwBvB;AAoBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,YAAY,CAEzE"}
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Batch Manager for mainwpcontrol
3
+ *
4
+ * Handles batch operations with polling and resume capabilities.
5
+ * Provides exponential backoff for job status polling.
6
+ */
7
+ import { createHttpClient } from './http-client.js';
8
+ import { APIError, NetworkError } from '../utils/errors.js';
9
+ import { ExponentialBackoff } from '../utils/retry.js';
10
+ /**
11
+ * Default configuration
12
+ */
13
+ const DEFAULTS = {
14
+ maxWait: 5 * 60 * 1000, // 5 minutes
15
+ initialDelay: 1000, // 1 second
16
+ maxDelay: 30000, // 30 seconds
17
+ multiplier: 2,
18
+ };
19
+ /**
20
+ * Batch Manager class
21
+ */
22
+ export class BatchManager {
23
+ httpClient;
24
+ baseEndpoint = '/wp-json/wp-abilities/v1';
25
+ constructor(config) {
26
+ this.httpClient = createHttpClient(config);
27
+ }
28
+ /**
29
+ * Watch a batch job status with exponential backoff polling
30
+ *
31
+ * Yields status updates as they're received.
32
+ * Completes when job finishes or times out.
33
+ */
34
+ async *watchJob(jobId, options = {}) {
35
+ const maxWait = options.maxWait ?? DEFAULTS.maxWait;
36
+ const startTime = Date.now();
37
+ const backoff = new ExponentialBackoff({
38
+ initialDelay: options.initialDelay ?? DEFAULTS.initialDelay,
39
+ maxDelay: options.maxDelay ?? DEFAULTS.maxDelay,
40
+ multiplier: options.multiplier ?? DEFAULTS.multiplier,
41
+ signal: options.signal,
42
+ });
43
+ let lastStatus;
44
+ let timedOut = false;
45
+ while (true) {
46
+ // Check timeout
47
+ const elapsed = Date.now() - startTime;
48
+ if (elapsed >= maxWait) {
49
+ timedOut = true;
50
+ break;
51
+ }
52
+ // Check abort
53
+ if (options.signal?.aborted) {
54
+ break;
55
+ }
56
+ // Fetch current status
57
+ try {
58
+ const status = await this.getJobStatus(jobId, options.signal);
59
+ lastStatus = status;
60
+ // Yield the status update
61
+ yield status;
62
+ // Call progress callback if provided
63
+ if (options.onProgress) {
64
+ options.onProgress(status);
65
+ }
66
+ // Check if job is complete
67
+ if (this.isTerminalStatus(status.status)) {
68
+ break;
69
+ }
70
+ // Wait before next poll
71
+ try {
72
+ const shouldContinue = await backoff.wait();
73
+ if (!shouldContinue) {
74
+ // Max retries exceeded or already aborted
75
+ break;
76
+ }
77
+ }
78
+ catch {
79
+ // Aborted during wait
80
+ break;
81
+ }
82
+ }
83
+ catch (error) {
84
+ // For network errors, continue polling
85
+ if (error instanceof NetworkError) {
86
+ try {
87
+ const shouldContinue = await backoff.wait();
88
+ if (!shouldContinue) {
89
+ break;
90
+ }
91
+ }
92
+ catch {
93
+ break;
94
+ }
95
+ continue;
96
+ }
97
+ // For other errors, throw
98
+ throw error;
99
+ }
100
+ }
101
+ const elapsed = Date.now() - startTime;
102
+ // If we don't have a status, create a placeholder
103
+ if (!lastStatus) {
104
+ lastStatus = {
105
+ id: jobId,
106
+ status: timedOut ? 'partial' : 'failed',
107
+ errors: [{ message: timedOut ? 'Polling timed out' : 'Polling aborted' }],
108
+ };
109
+ }
110
+ else if (timedOut && !this.isTerminalStatus(lastStatus.status)) {
111
+ // Mark as partial if timed out while still running
112
+ lastStatus = {
113
+ ...lastStatus,
114
+ status: 'partial',
115
+ };
116
+ }
117
+ return {
118
+ status: lastStatus,
119
+ timedOut,
120
+ elapsed,
121
+ };
122
+ }
123
+ /**
124
+ * Resume watching a batch job
125
+ *
126
+ * This is a convenience method that wraps watchJob for resuming
127
+ * a previously started job by its ID.
128
+ */
129
+ async resumeJob(jobId, options) {
130
+ const generator = this.watchJob(jobId, options);
131
+ // Consume the generator
132
+ while (true) {
133
+ const result = await generator.next();
134
+ if (result.done) {
135
+ return result.value;
136
+ }
137
+ // Status updates are handled via the generator, we just continue
138
+ }
139
+ }
140
+ /**
141
+ * Get the current status of a batch job
142
+ */
143
+ async getJobStatus(jobId, signal) {
144
+ const endpoint = `${this.baseEndpoint}/abilities/mainwp/get-batch-job-status-v1/run`;
145
+ const qs = `input[job_id]=${encodeURIComponent(jobId)}`;
146
+ const response = await this.httpClient.get(`${endpoint}?${qs}`, signal ? { signal } : undefined);
147
+ return this.normalizeJobStatus(response.data);
148
+ }
149
+ /**
150
+ * Check if a status is terminal (job finished)
151
+ */
152
+ isTerminalStatus(status) {
153
+ return status === 'completed' || status === 'failed' || status === 'partial';
154
+ }
155
+ /**
156
+ * Normalize API response to JobStatus, unwrapping success envelope if present
157
+ */
158
+ normalizeJobStatus(data) {
159
+ if (typeof data !== 'object' || data === null) {
160
+ throw new APIError('INVALID_RESPONSE', 'Invalid job status response');
161
+ }
162
+ const response = data;
163
+ // Unwrap success envelope if present
164
+ let fields = response;
165
+ if ('success' in response && 'data' in response) {
166
+ const inner = response['data'];
167
+ if (typeof inner !== 'object' || inner === null || Array.isArray(inner)) {
168
+ throw new APIError('INVALID_RESPONSE', 'Invalid job status data in success envelope');
169
+ }
170
+ fields = inner;
171
+ }
172
+ const id = String(fields['job_id'] ?? fields['id'] ?? '');
173
+ if (!id) {
174
+ throw new APIError('INVALID_RESPONSE', 'Job status response missing job ID');
175
+ }
176
+ return {
177
+ id,
178
+ status: this.parseJobStatus(fields['status']),
179
+ progress: typeof fields['progress'] === 'number' ? fields['progress'] : undefined,
180
+ total: typeof fields['total'] === 'number' ? fields['total'] : undefined,
181
+ processed: typeof fields['processed'] === 'number' ? fields['processed'] : undefined,
182
+ results: Array.isArray(fields['results']) ? fields['results'] : undefined,
183
+ errors: this.parseJobErrors(fields['errors']),
184
+ created_at: typeof fields['created_at'] === 'string' ? fields['created_at'] : undefined,
185
+ completed_at: typeof fields['completed_at'] === 'string' ? fields['completed_at'] : undefined,
186
+ };
187
+ }
188
+ /**
189
+ * Parse job status string
190
+ */
191
+ parseJobStatus(value) {
192
+ if (typeof value !== 'string') {
193
+ return 'pending';
194
+ }
195
+ const status = value.toLowerCase();
196
+ switch (status) {
197
+ case 'pending':
198
+ case 'running':
199
+ case 'completed':
200
+ case 'failed':
201
+ case 'partial':
202
+ return status;
203
+ case 'processing':
204
+ case 'in_progress':
205
+ return 'running';
206
+ case 'done':
207
+ case 'success':
208
+ return 'completed';
209
+ case 'error':
210
+ return 'failed';
211
+ default:
212
+ return 'pending';
213
+ }
214
+ }
215
+ /**
216
+ * Parse job errors
217
+ */
218
+ parseJobErrors(value) {
219
+ if (!Array.isArray(value)) {
220
+ return undefined;
221
+ }
222
+ return value.map((error) => {
223
+ if (typeof error === 'string') {
224
+ return { message: error, item: undefined, code: undefined };
225
+ }
226
+ if (typeof error === 'object' && error !== null) {
227
+ const e = error;
228
+ return {
229
+ item: e['item'],
230
+ message: String(e['message'] ?? e['error'] ?? 'Unknown error'),
231
+ code: typeof e['code'] === 'string' ? e['code'] : undefined,
232
+ };
233
+ }
234
+ return { message: String(error), item: undefined, code: undefined };
235
+ });
236
+ }
237
+ }
238
+ /**
239
+ * Create a batch manager from configuration
240
+ */
241
+ export function createBatchManager(config) {
242
+ return new BatchManager(config);
243
+ }
244
+ //# sourceMappingURL=batch-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-manager.js","sourceRoot":"","sources":["../../src/core/batch-manager.ts"],"names":[],"mappings":"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"}