specweave 0.28.56 → 0.28.59

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.
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Background Import Worker
4
+ *
5
+ * Standalone script that runs import in a detached process.
6
+ * Survives terminal close - progress tracked via job state file.
7
+ *
8
+ * Usage:
9
+ * node import-worker.js <jobId> <projectPath>
10
+ *
11
+ * The worker reads job configuration from:
12
+ * .specweave/state/jobs/<jobId>/config.json
13
+ *
14
+ * And updates progress to:
15
+ * .specweave/state/background-jobs.json
16
+ */
17
+ import * as fs from 'fs';
18
+ import * as path from 'path';
19
+ import { fileURLToPath } from 'url';
20
+ // Worker-specific imports (loaded dynamically to reduce startup time)
21
+ let ImportCoordinator;
22
+ let getJobManager;
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = path.dirname(__filename);
25
+ /**
26
+ * Main worker entry point
27
+ */
28
+ async function main() {
29
+ const args = process.argv.slice(2);
30
+ if (args.length < 2) {
31
+ console.error('Usage: import-worker.js <jobId> <projectPath>');
32
+ process.exit(1);
33
+ }
34
+ const jobId = args[0];
35
+ const projectPath = args[1];
36
+ // Write PID file for process management
37
+ const pidFile = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.pid');
38
+ fs.mkdirSync(path.dirname(pidFile), { recursive: true });
39
+ fs.writeFileSync(pidFile, process.pid.toString());
40
+ // Setup cleanup on exit
41
+ const cleanup = () => {
42
+ try {
43
+ if (fs.existsSync(pidFile)) {
44
+ fs.unlinkSync(pidFile);
45
+ }
46
+ }
47
+ catch {
48
+ // Ignore cleanup errors
49
+ }
50
+ };
51
+ process.on('exit', cleanup);
52
+ process.on('SIGTERM', () => {
53
+ cleanup();
54
+ process.exit(0);
55
+ });
56
+ process.on('SIGINT', () => {
57
+ cleanup();
58
+ process.exit(0);
59
+ });
60
+ try {
61
+ // Load job configuration
62
+ const configPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'config.json');
63
+ if (!fs.existsSync(configPath)) {
64
+ throw new Error(`Job config not found: ${configPath}`);
65
+ }
66
+ const jobConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
67
+ // Log to worker-specific log file
68
+ const logPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.log');
69
+ const log = (msg) => {
70
+ const timestamp = new Date().toISOString();
71
+ fs.appendFileSync(logPath, `[${timestamp}] ${msg}\n`);
72
+ };
73
+ log(`Worker started for job ${jobId}`);
74
+ log(`Project path: ${projectPath}`);
75
+ log(`PID: ${process.pid}`);
76
+ // Dynamically import heavy dependencies
77
+ const importCoordinatorModule = await import('../../importers/import-coordinator.js');
78
+ ImportCoordinator = importCoordinatorModule.ImportCoordinator;
79
+ const jobManagerModule = await import('../../core/background/job-manager.js');
80
+ getJobManager = jobManagerModule.getJobManager;
81
+ // Get job manager and mark as running
82
+ const jobManager = getJobManager(projectPath);
83
+ jobManager.startJob(jobId);
84
+ log('Dependencies loaded, starting import...');
85
+ // Setup progress tracking
86
+ const coordinatorConfig = jobConfig.coordinatorConfig;
87
+ let totalEstimate = 0;
88
+ let currentCount = 0;
89
+ coordinatorConfig.onProgressEnhanced = (info) => {
90
+ currentCount = info.current || currentCount;
91
+ if (info.total && info.total > totalEstimate) {
92
+ totalEstimate = info.total;
93
+ }
94
+ // Update job progress
95
+ jobManager.updateProgress(jobId, currentCount, info.sourceRepo || info.platform, undefined, undefined);
96
+ // Update total estimate if we now know more
97
+ const job = jobManager.getJob(jobId);
98
+ if (job && totalEstimate > job.progress.total) {
99
+ job.progress.total = totalEstimate;
100
+ // Force save with new total
101
+ jobManager.updateProgress(jobId, currentCount, info.sourceRepo || info.platform);
102
+ }
103
+ log(`Progress: ${currentCount}/${totalEstimate} - ${info.platform} ${info.sourceRepo || ''}`);
104
+ };
105
+ // Rate limit handling
106
+ coordinatorConfig.onRateLimitPause = (platform, seconds) => {
107
+ log(`Rate limited by ${platform}, pausing for ${seconds}s`);
108
+ jobManager.pauseJob(jobId);
109
+ // Set resume time
110
+ const job = jobManager.getJob(jobId);
111
+ if (job) {
112
+ job.resumeAfter = new Date(Date.now() + seconds * 1000);
113
+ }
114
+ };
115
+ // Execute import
116
+ const coordinator = new ImportCoordinator(coordinatorConfig);
117
+ const result = await coordinator.importAll();
118
+ log(`Import complete: ${result.totalCount} items imported`);
119
+ // Mark job as complete
120
+ jobManager.completeJob(jobId);
121
+ // Write result summary
122
+ const resultPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'result.json');
123
+ fs.writeFileSync(resultPath, JSON.stringify({
124
+ totalCount: result.totalCount,
125
+ completedAt: new Date().toISOString(),
126
+ summary: result.summary || {}
127
+ }, null, 2));
128
+ log('Worker finished successfully');
129
+ process.exit(0);
130
+ }
131
+ catch (error) {
132
+ // Log error
133
+ const logPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.log');
134
+ fs.appendFileSync(logPath, `[${new Date().toISOString()}] ERROR: ${error.message}\n`);
135
+ fs.appendFileSync(logPath, `${error.stack}\n`);
136
+ // Mark job as failed
137
+ try {
138
+ const jobManagerModule = await import('../../core/background/job-manager.js');
139
+ const jobManager = jobManagerModule.getJobManager(projectPath);
140
+ jobManager.completeJob(jobId, error.message);
141
+ }
142
+ catch {
143
+ // Ignore if can't update job
144
+ }
145
+ console.error(`Worker error: ${error.message}`);
146
+ process.exit(1);
147
+ }
148
+ }
149
+ // Run worker
150
+ main().catch((error) => {
151
+ console.error('Fatal worker error:', error);
152
+ process.exit(1);
153
+ });
154
+ //# sourceMappingURL=import-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-worker.js","sourceRoot":"","sources":["../../../../src/cli/workers/import-worker.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,15 @@
5
5
  * - Repository cloning (multi-repo setup)
6
6
  * - Issue import (10K+ items from GitHub/JIRA/ADO)
7
7
  * - External sync operations
8
+ *
9
+ * ASYNC ARCHITECTURE (2025-12-01):
10
+ * - Jobs spawn as detached processes that survive terminal close
11
+ * - Progress tracked via filesystem (.specweave/state/jobs/)
12
+ * - Check status: /specweave:jobs
13
+ * - Resume: /specweave:jobs --resume <jobId>
14
+ * - Kill: /specweave:jobs --kill <jobId>
8
15
  */
9
16
  export * from './types.js';
10
17
  export * from './job-manager.js';
18
+ export * from './job-launcher.js';
11
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/background/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/background/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
@@ -5,7 +5,15 @@
5
5
  * - Repository cloning (multi-repo setup)
6
6
  * - Issue import (10K+ items from GitHub/JIRA/ADO)
7
7
  * - External sync operations
8
+ *
9
+ * ASYNC ARCHITECTURE (2025-12-01):
10
+ * - Jobs spawn as detached processes that survive terminal close
11
+ * - Progress tracked via filesystem (.specweave/state/jobs/)
12
+ * - Check status: /specweave:jobs
13
+ * - Resume: /specweave:jobs --resume <jobId>
14
+ * - Kill: /specweave:jobs --kill <jobId>
8
15
  */
9
16
  export * from './types.js';
10
17
  export * from './job-manager.js';
18
+ export * from './job-launcher.js';
11
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/background/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/background/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Background Job Launcher
3
+ *
4
+ * Spawns import workers as detached processes that survive terminal close.
5
+ * Progress tracked via file system - check with /specweave:jobs
6
+ */
7
+ import type { BackgroundJob, JobType } from './types.js';
8
+ export interface LaunchOptions {
9
+ /** Job type */
10
+ type: JobType;
11
+ /** Project path */
12
+ projectPath: string;
13
+ /** Coordinator config for import */
14
+ coordinatorConfig: any;
15
+ /** Estimated total items (can be updated by worker) */
16
+ estimatedTotal?: number;
17
+ /** Run in foreground (blocking) instead of background */
18
+ foreground?: boolean;
19
+ }
20
+ export interface LaunchResult {
21
+ job: BackgroundJob;
22
+ /** PID of background process (undefined if foreground) */
23
+ pid?: number;
24
+ /** Whether running in background */
25
+ isBackground: boolean;
26
+ }
27
+ /**
28
+ * Launch an import job
29
+ *
30
+ * @param options Launch configuration
31
+ * @returns Job info and process details
32
+ */
33
+ export declare function launchImportJob(options: LaunchOptions): Promise<LaunchResult>;
34
+ /**
35
+ * Check if a background job is still running
36
+ */
37
+ export declare function isJobRunning(projectPath: string, jobId: string): boolean;
38
+ /**
39
+ * Kill a background job
40
+ */
41
+ export declare function killJob(projectPath: string, jobId: string): boolean;
42
+ /**
43
+ * Get worker log output
44
+ */
45
+ export declare function getJobLog(projectPath: string, jobId: string, tailLines?: number): string;
46
+ /**
47
+ * Get job result (after completion)
48
+ */
49
+ export declare function getJobResult(projectPath: string, jobId: string): any | null;
50
+ /**
51
+ * Clean up old job directories
52
+ */
53
+ export declare function cleanupOldJobs(projectPath: string, keepDays?: number): void;
54
+ //# sourceMappingURL=job-launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-launcher.d.ts","sourceRoot":"","sources":["../../../../src/core/background/job-launcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAmB,MAAM,YAAY,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,IAAI,EAAE,OAAO,CAAC;IACd,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,iBAAiB,EAAE,GAAG,CAAC;IACvB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAiFnF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAiBxE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAqBnE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAexF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAY3E;AA0BD;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,IAAI,CA8B9E"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Background Job Launcher
3
+ *
4
+ * Spawns import workers as detached processes that survive terminal close.
5
+ * Progress tracked via file system - check with /specweave:jobs
6
+ */
7
+ import { spawn } from 'child_process';
8
+ import * as fs from '../../utils/fs-native.js';
9
+ import * as path from 'path';
10
+ import { getJobManager } from './job-manager.js';
11
+ /**
12
+ * Launch an import job
13
+ *
14
+ * @param options Launch configuration
15
+ * @returns Job info and process details
16
+ */
17
+ export async function launchImportJob(options) {
18
+ const { type, projectPath, coordinatorConfig, estimatedTotal = 100, foreground = false } = options;
19
+ // Create job via job manager
20
+ const jobManager = getJobManager(projectPath);
21
+ const provider = coordinatorConfig.github ? 'github' :
22
+ coordinatorConfig.jira ? 'jira' :
23
+ coordinatorConfig.ado ? 'ado' : 'github';
24
+ const jobConfig = {
25
+ type: 'import-issues',
26
+ provider: provider,
27
+ projectPath,
28
+ timeRangeMonths: coordinatorConfig.importConfig?.timeRangeMonths || 3,
29
+ repositories: coordinatorConfig.githubRepositories?.map((r) => `${r.owner}/${r.repo}`)
30
+ };
31
+ const job = jobManager.createJob(type, jobConfig, estimatedTotal);
32
+ // Create job-specific directory for config and logs
33
+ const jobDir = path.join(projectPath, '.specweave', 'state', 'jobs', job.id);
34
+ fs.ensureDirSync(jobDir);
35
+ // Write coordinator config for worker
36
+ const configPath = path.join(jobDir, 'config.json');
37
+ fs.writeFileSync(configPath, JSON.stringify({
38
+ jobId: job.id,
39
+ projectPath,
40
+ coordinatorConfig,
41
+ startedAt: new Date().toISOString()
42
+ }, null, 2));
43
+ // If foreground mode, return job without spawning worker
44
+ // Caller will handle the import directly
45
+ if (foreground) {
46
+ return {
47
+ job,
48
+ isBackground: false
49
+ };
50
+ }
51
+ // Find worker script path
52
+ const workerPath = findWorkerPath();
53
+ if (!workerPath) {
54
+ // Fallback to foreground if worker not found
55
+ console.warn('Background worker not found, running in foreground');
56
+ return {
57
+ job,
58
+ isBackground: false
59
+ };
60
+ }
61
+ // Spawn detached process
62
+ const child = spawn('node', [workerPath, job.id, projectPath], {
63
+ detached: true,
64
+ stdio: 'ignore',
65
+ cwd: projectPath,
66
+ env: {
67
+ ...process.env,
68
+ // Pass any necessary env vars
69
+ SPECWEAVE_BACKGROUND_JOB: '1'
70
+ }
71
+ });
72
+ // Unref to allow parent to exit independently
73
+ child.unref();
74
+ // Update job with PID
75
+ const updatedJob = jobManager.getJob(job.id);
76
+ if (updatedJob) {
77
+ updatedJob.pid = child.pid;
78
+ updatedJob.isBackground = true;
79
+ }
80
+ return {
81
+ job: updatedJob || job,
82
+ pid: child.pid,
83
+ isBackground: true
84
+ };
85
+ }
86
+ /**
87
+ * Check if a background job is still running
88
+ */
89
+ export function isJobRunning(projectPath, jobId) {
90
+ const pidFile = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.pid');
91
+ if (!fs.existsSync(pidFile)) {
92
+ return false;
93
+ }
94
+ try {
95
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
96
+ // Check if process is running (signal 0 doesn't kill, just checks)
97
+ process.kill(pid, 0);
98
+ return true;
99
+ }
100
+ catch {
101
+ // Process not running or no permission
102
+ return false;
103
+ }
104
+ }
105
+ /**
106
+ * Kill a background job
107
+ */
108
+ export function killJob(projectPath, jobId) {
109
+ const pidFile = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.pid');
110
+ if (!fs.existsSync(pidFile)) {
111
+ return false;
112
+ }
113
+ try {
114
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
115
+ // Send SIGTERM for graceful shutdown
116
+ process.kill(pid, 'SIGTERM');
117
+ // Update job status
118
+ const jobManager = getJobManager(projectPath);
119
+ jobManager.pauseJob(jobId);
120
+ return true;
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ }
126
+ /**
127
+ * Get worker log output
128
+ */
129
+ export function getJobLog(projectPath, jobId, tailLines) {
130
+ const logPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'worker.log');
131
+ if (!fs.existsSync(logPath)) {
132
+ return '';
133
+ }
134
+ const content = fs.readFileSync(logPath, 'utf-8');
135
+ if (tailLines && tailLines > 0) {
136
+ const lines = content.split('\n');
137
+ return lines.slice(-tailLines).join('\n');
138
+ }
139
+ return content;
140
+ }
141
+ /**
142
+ * Get job result (after completion)
143
+ */
144
+ export function getJobResult(projectPath, jobId) {
145
+ const resultPath = path.join(projectPath, '.specweave', 'state', 'jobs', jobId, 'result.json');
146
+ if (!fs.existsSync(resultPath)) {
147
+ return null;
148
+ }
149
+ try {
150
+ return JSON.parse(fs.readFileSync(resultPath, 'utf-8'));
151
+ }
152
+ catch {
153
+ return null;
154
+ }
155
+ }
156
+ /**
157
+ * Find the worker script path
158
+ */
159
+ function findWorkerPath() {
160
+ // Try relative paths from different locations
161
+ const possiblePaths = [
162
+ // From dist/src/core/background (compiled)
163
+ path.join(__dirname, '../../cli/workers/import-worker.js'),
164
+ // From src/core/background (dev)
165
+ path.join(__dirname, '../../../dist/src/cli/workers/import-worker.js'),
166
+ // Global install
167
+ path.join(__dirname, '../../../../cli/workers/import-worker.js'),
168
+ ];
169
+ for (const p of possiblePaths) {
170
+ const resolved = path.resolve(p);
171
+ if (fs.existsSync(resolved)) {
172
+ return resolved;
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ /**
178
+ * Clean up old job directories
179
+ */
180
+ export function cleanupOldJobs(projectPath, keepDays = 7) {
181
+ const jobsDir = path.join(projectPath, '.specweave', 'state', 'jobs');
182
+ if (!fs.existsSync(jobsDir)) {
183
+ return;
184
+ }
185
+ const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
186
+ try {
187
+ const entries = fs.readdirSync(jobsDir);
188
+ for (const entry of entries) {
189
+ const jobDir = path.join(jobsDir, entry);
190
+ const stat = fs.statSync(jobDir);
191
+ if (stat.isDirectory() && stat.mtimeMs < cutoff) {
192
+ // Check job status before deleting
193
+ const jobManager = getJobManager(projectPath);
194
+ const job = jobManager.getJob(entry);
195
+ // Only delete completed/failed jobs
196
+ if (!job || job.status === 'completed' || job.status === 'failed') {
197
+ fs.rmSync(jobDir, { recursive: true, force: true });
198
+ }
199
+ }
200
+ }
201
+ }
202
+ catch {
203
+ // Ignore cleanup errors
204
+ }
205
+ }
206
+ //# sourceMappingURL=job-launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-launcher.js","sourceRoot":"","sources":["../../../../src/core/background/job-launcher.ts"],"names":[],"mappings":"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"}
@@ -19,12 +19,18 @@ export declare class ADOImporter implements Importer {
19
19
  */
20
20
  import(config?: ImportConfig): Promise<ExternalItem[]>;
21
21
  /**
22
- * Paginate through work items using WIQL (200 per page)
22
+ * Paginate through work items using WIQL with date-based pagination for 100K+ items
23
23
  *
24
24
  * CRITICAL FIX (2025-12-01): Also fetch missing parent items (Epics/Capabilities)
25
25
  * Problem: If a parent Epic wasn't modified recently, it won't be in the WIQL results,
26
26
  * causing all its child User Stories to be grouped into one generic folder.
27
27
  * Solution: After fetching all items, identify missing parents and fetch them separately.
28
+ *
29
+ * ENHANCEMENT (2025-12-01): Date-based pagination to handle 100K+ items
30
+ * ADO WIQL has a 20K ID limit per query. For larger projects, we need to:
31
+ * 1. Run initial WIQL query (up to 20K IDs)
32
+ * 2. If we hit the limit, run another query with older date range
33
+ * 3. Keep paginating by date until we have all items or hit maxItems
28
34
  */
29
35
  paginate(config?: ImportConfig): AsyncGenerator<ExternalItem[], void, unknown>;
30
36
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ado-importer.d.ts","sourceRoot":"","sources":["../../../src/importers/ado-importer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAoCnF;;GAEG;AACH,qBAAa,WAAY,YAAW,QAAQ;IAC1C,QAAQ,CAAC,QAAQ,EAAG,KAAK,CAAU;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;gBAER,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAYzD;;OAEG;IACG,MAAM,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUhE;;;;;;;OAOG;IACI,QAAQ,CAAC,MAAM,GAAE,YAAiB,GAAG,cAAc,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC;IAyHzF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;YACW,cAAc;IA8B5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0E7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;CAkBhC"}
1
+ {"version":3,"file":"ado-importer.d.ts","sourceRoot":"","sources":["../../../src/importers/ado-importer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAoCnF;;GAEG;AACH,qBAAa,WAAY,YAAW,QAAQ;IAC1C,QAAQ,CAAC,QAAQ,EAAG,KAAK,CAAU;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;gBAER,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAYzD;;OAEG;IACG,MAAM,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUhE;;;;;;;;;;;;;OAaG;IACI,QAAQ,CAAC,MAAM,GAAE,YAAiB,GAAG,cAAc,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC;IA0KzF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAgB5B;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;YACW,cAAc;IA8B5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA2E7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;CAkBhC"}