jirallm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/cli/commands/auth.d.ts +7 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +69 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +5 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +191 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +198 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/orgs.d.ts +8 -0
- package/dist/cli/commands/orgs.d.ts.map +1 -0
- package/dist/cli/commands/orgs.js +81 -0
- package/dist/cli/commands/orgs.js.map +1 -0
- package/dist/cli/commands/profiles.d.ts +2 -0
- package/dist/cli/commands/profiles.d.ts.map +1 -0
- package/dist/cli/commands/profiles.js +20 -0
- package/dist/cli/commands/profiles.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +7 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +130 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +267 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/issueKey.d.ts +13 -0
- package/dist/cli/issueKey.d.ts.map +1 -0
- package/dist/cli/issueKey.js +50 -0
- package/dist/cli/issueKey.js.map +1 -0
- package/dist/cli/issueKey.test.d.ts +2 -0
- package/dist/cli/issueKey.test.d.ts.map +1 -0
- package/dist/cli/issueKey.test.js +48 -0
- package/dist/cli/issueKey.test.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +49 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +173 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/config.test.d.ts +2 -0
- package/dist/lib/config.test.d.ts.map +1 -0
- package/dist/lib/config.test.js +130 -0
- package/dist/lib/config.test.js.map +1 -0
- package/dist/lib/configSchema.d.ts +42 -0
- package/dist/lib/configSchema.d.ts.map +1 -0
- package/dist/lib/configSchema.js +41 -0
- package/dist/lib/configSchema.js.map +1 -0
- package/dist/lib/credentials.d.ts +8 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +62 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/credentials.test.d.ts +2 -0
- package/dist/lib/credentials.test.d.ts.map +1 -0
- package/dist/lib/credentials.test.js +35 -0
- package/dist/lib/credentials.test.js.map +1 -0
- package/dist/lib/exporter.d.ts +28 -0
- package/dist/lib/exporter.d.ts.map +1 -0
- package/dist/lib/exporter.js +149 -0
- package/dist/lib/exporter.js.map +1 -0
- package/dist/lib/jiraClient.d.ts +129 -0
- package/dist/lib/jiraClient.d.ts.map +1 -0
- package/dist/lib/jiraClient.js +308 -0
- package/dist/lib/jiraClient.js.map +1 -0
- package/dist/lib/platform.d.ts +9 -0
- package/dist/lib/platform.d.ts.map +1 -0
- package/dist/lib/platform.js +82 -0
- package/dist/lib/platform.js.map +1 -0
- package/dist/lib/runCommand.d.ts +7 -0
- package/dist/lib/runCommand.d.ts.map +1 -0
- package/dist/lib/runCommand.js +26 -0
- package/dist/lib/runCommand.js.map +1 -0
- package/dist/lib/videoFrameExtractor.d.ts +22 -0
- package/dist/lib/videoFrameExtractor.d.ts.map +1 -0
- package/dist/lib/videoFrameExtractor.js +234 -0
- package/dist/lib/videoFrameExtractor.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import TOML from '@iarna/toml';
|
|
5
|
+
import { getToken } from './credentials.js';
|
|
6
|
+
import { parseConfig } from './configSchema.js';
|
|
7
|
+
export function resolveConfigPath() {
|
|
8
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
9
|
+
if (xdg)
|
|
10
|
+
return join(xdg, 'jirallm', 'config.toml');
|
|
11
|
+
return join(homedir(), '.config', 'jirallm', 'config.toml');
|
|
12
|
+
}
|
|
13
|
+
function expandTilde(value) {
|
|
14
|
+
if (!value)
|
|
15
|
+
return value;
|
|
16
|
+
if (value === '~')
|
|
17
|
+
return homedir();
|
|
18
|
+
if (value.startsWith('~/'))
|
|
19
|
+
return join(homedir(), value.slice(2));
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
export function readConfig(path = resolveConfigPath()) {
|
|
23
|
+
if (!existsSync(path))
|
|
24
|
+
return {};
|
|
25
|
+
const raw = readFileSync(path, 'utf-8');
|
|
26
|
+
const parsed = TOML.parse(raw);
|
|
27
|
+
return parseConfig(parsed, path);
|
|
28
|
+
}
|
|
29
|
+
export function writeConfig(config, path = resolveConfigPath()) {
|
|
30
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
31
|
+
writeFileSync(path, TOML.stringify(config), 'utf-8');
|
|
32
|
+
}
|
|
33
|
+
function buildOrg(name, raw) {
|
|
34
|
+
const orgs = raw.orgs ?? {};
|
|
35
|
+
const r = orgs[name];
|
|
36
|
+
if (!r) {
|
|
37
|
+
const known = Object.keys(orgs).join(', ') || '(none)';
|
|
38
|
+
throw new Error(`Organization "${name}" not found in config. Known orgs: ${known}`);
|
|
39
|
+
}
|
|
40
|
+
const projects = {};
|
|
41
|
+
for (const [key, p] of Object.entries(r.projects ?? {})) {
|
|
42
|
+
projects[key] = { key, outputDir: expandTilde(p.output_dir) };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
name,
|
|
46
|
+
baseUrl: r.base_url,
|
|
47
|
+
userEmail: r.user_email,
|
|
48
|
+
includeSubtasks: r.include_subtasks,
|
|
49
|
+
videoFrames: r.video_frames
|
|
50
|
+
? {
|
|
51
|
+
enabled: r.video_frames.enabled,
|
|
52
|
+
fps: r.video_frames.fps,
|
|
53
|
+
quality: r.video_frames.quality,
|
|
54
|
+
maxFrames: r.video_frames.max_frames,
|
|
55
|
+
similarityThreshold: r.video_frames.similarity_threshold,
|
|
56
|
+
}
|
|
57
|
+
: undefined,
|
|
58
|
+
projects,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function pickProject(org, projectKey) {
|
|
62
|
+
if (!projectKey) {
|
|
63
|
+
const keys = Object.keys(org.projects).join(', ') || '(none)';
|
|
64
|
+
throw new Error(`No project specified for org "${org.name}". Available projects: ${keys}`);
|
|
65
|
+
}
|
|
66
|
+
const project = org.projects[projectKey];
|
|
67
|
+
if (!project) {
|
|
68
|
+
const keys = Object.keys(org.projects).join(', ') || '(none)';
|
|
69
|
+
throw new Error(`Project "${projectKey}" not found in org "${org.name}". Available projects: ${keys}`);
|
|
70
|
+
}
|
|
71
|
+
return project;
|
|
72
|
+
}
|
|
73
|
+
export function listOrgs(raw = readConfig()) {
|
|
74
|
+
return Object.keys(raw.orgs ?? {});
|
|
75
|
+
}
|
|
76
|
+
export function findOrgsByProjectKey(projectKey, raw = readConfig()) {
|
|
77
|
+
const matches = [];
|
|
78
|
+
for (const [name, org] of Object.entries(raw.orgs ?? {})) {
|
|
79
|
+
if (org.projects && projectKey in org.projects)
|
|
80
|
+
matches.push(name);
|
|
81
|
+
}
|
|
82
|
+
return matches;
|
|
83
|
+
}
|
|
84
|
+
export async function loadProfile(opts = {}) {
|
|
85
|
+
const path = opts.configPath ?? resolveConfigPath();
|
|
86
|
+
const raw = readConfig(path);
|
|
87
|
+
const orgName = opts.org;
|
|
88
|
+
if (!orgName) {
|
|
89
|
+
throw new Error('No --org provided and the issue key prefix did not match a configured project. ' +
|
|
90
|
+
'Pass --org or run `jirallm init`.');
|
|
91
|
+
}
|
|
92
|
+
const org = buildOrg(orgName, raw);
|
|
93
|
+
const project = pickProject(org, opts.project);
|
|
94
|
+
const apiToken = await getToken(orgName);
|
|
95
|
+
if (!apiToken) {
|
|
96
|
+
throw new Error(`No API token found for org "${orgName}". Run \`jirallm auth set --org ${orgName}\`.`);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
org,
|
|
100
|
+
project,
|
|
101
|
+
apiToken,
|
|
102
|
+
config: {
|
|
103
|
+
baseUrl: org.baseUrl,
|
|
104
|
+
userEmail: org.userEmail,
|
|
105
|
+
projectKey: project.key,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function orgToRaw(org) {
|
|
110
|
+
const raw = {
|
|
111
|
+
base_url: org.baseUrl,
|
|
112
|
+
user_email: org.userEmail,
|
|
113
|
+
};
|
|
114
|
+
if (org.includeSubtasks !== undefined)
|
|
115
|
+
raw.include_subtasks = org.includeSubtasks;
|
|
116
|
+
if (org.videoFrames) {
|
|
117
|
+
raw.video_frames = {
|
|
118
|
+
enabled: org.videoFrames.enabled,
|
|
119
|
+
fps: org.videoFrames.fps,
|
|
120
|
+
quality: org.videoFrames.quality,
|
|
121
|
+
max_frames: org.videoFrames.maxFrames,
|
|
122
|
+
similarity_threshold: org.videoFrames.similarityThreshold,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const projects = {};
|
|
126
|
+
for (const [key, p] of Object.entries(org.projects)) {
|
|
127
|
+
const rp = {};
|
|
128
|
+
if (p.outputDir)
|
|
129
|
+
rp.output_dir = p.outputDir;
|
|
130
|
+
projects[key] = rp;
|
|
131
|
+
}
|
|
132
|
+
raw.projects = projects;
|
|
133
|
+
return raw;
|
|
134
|
+
}
|
|
135
|
+
export function upsertOrg(org, configPath = resolveConfigPath()) {
|
|
136
|
+
const raw = readConfig(configPath);
|
|
137
|
+
raw.orgs = raw.orgs ?? {};
|
|
138
|
+
raw.orgs[org.name] = orgToRaw(org);
|
|
139
|
+
writeConfig(raw, configPath);
|
|
140
|
+
}
|
|
141
|
+
export function upsertProject(orgName, project, configPath = resolveConfigPath()) {
|
|
142
|
+
const raw = readConfig(configPath);
|
|
143
|
+
if (!raw.orgs?.[orgName]) {
|
|
144
|
+
throw new Error(`Organization "${orgName}" not found. Create it first via \`jirallm init\`.`);
|
|
145
|
+
}
|
|
146
|
+
const orgRaw = raw.orgs[orgName];
|
|
147
|
+
orgRaw.projects = orgRaw.projects ?? {};
|
|
148
|
+
const rp = {};
|
|
149
|
+
if (project.outputDir)
|
|
150
|
+
rp.output_dir = project.outputDir;
|
|
151
|
+
orgRaw.projects[project.key] = rp;
|
|
152
|
+
writeConfig(raw, configPath);
|
|
153
|
+
}
|
|
154
|
+
export function removeOrg(name, configPath = resolveConfigPath()) {
|
|
155
|
+
const raw = readConfig(configPath);
|
|
156
|
+
if (!raw.orgs?.[name])
|
|
157
|
+
return { removed: false };
|
|
158
|
+
delete raw.orgs[name];
|
|
159
|
+
writeConfig(raw, configPath);
|
|
160
|
+
return { removed: true };
|
|
161
|
+
}
|
|
162
|
+
export function removeProject(orgName, projectKey, configPath = resolveConfigPath()) {
|
|
163
|
+
const raw = readConfig(configPath);
|
|
164
|
+
const orgRaw = raw.orgs?.[orgName];
|
|
165
|
+
if (!orgRaw)
|
|
166
|
+
return { removed: false };
|
|
167
|
+
if (!orgRaw.projects?.[projectKey])
|
|
168
|
+
return { removed: false };
|
|
169
|
+
delete orgRaw.projects[projectKey];
|
|
170
|
+
writeConfig(raw, configPath);
|
|
171
|
+
return { removed: true };
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/lib/config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
+
vi.mock('./credentials.js', () => ({
|
|
6
|
+
getToken: vi.fn(async (_name) => 'fake-token'),
|
|
7
|
+
}));
|
|
8
|
+
import { findOrgsByProjectKey, loadProfile, readConfig, upsertOrg, upsertProject, } from './config.js';
|
|
9
|
+
import { getToken } from './credentials.js';
|
|
10
|
+
const mockedGetToken = vi.mocked(getToken);
|
|
11
|
+
let tmpDir;
|
|
12
|
+
let configPath;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'jirallm-cfg-'));
|
|
15
|
+
configPath = join(tmpDir, 'config.toml');
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
const SAMPLE_CONFIG = `[orgs.widgets]
|
|
21
|
+
base_url = "https://widgets.atlassian.net"
|
|
22
|
+
user_email = "user@widgets.example"
|
|
23
|
+
|
|
24
|
+
[orgs.widgets.projects.WID]
|
|
25
|
+
output_dir = "~/jira/widgets"
|
|
26
|
+
|
|
27
|
+
[orgs.acme]
|
|
28
|
+
base_url = "https://acme.atlassian.net"
|
|
29
|
+
user_email = "user@acme.example"
|
|
30
|
+
|
|
31
|
+
[orgs.acme.projects.PROJ]
|
|
32
|
+
output_dir = "~/jira/acme/proj"
|
|
33
|
+
|
|
34
|
+
[orgs.acme.projects.CORE]
|
|
35
|
+
output_dir = "~/jira/acme/core"
|
|
36
|
+
|
|
37
|
+
[orgs.acme.projects.LIB]
|
|
38
|
+
`;
|
|
39
|
+
describe('loadProfile', () => {
|
|
40
|
+
it('throws helpful error when nothing is configured', async () => {
|
|
41
|
+
await expect(loadProfile({ configPath })).rejects.toThrow(/--org/);
|
|
42
|
+
});
|
|
43
|
+
it('resolves org and project selectors', async () => {
|
|
44
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
45
|
+
const r = await loadProfile({ org: 'acme', project: 'CORE', configPath });
|
|
46
|
+
expect(r.org.name).toBe('acme');
|
|
47
|
+
expect(r.project.key).toBe('CORE');
|
|
48
|
+
expect(r.config.projectKey).toBe('CORE');
|
|
49
|
+
expect(r.config.baseUrl).toBe('https://acme.atlassian.net');
|
|
50
|
+
expect(r.project.outputDir).toMatch(/jira\/acme\/core$/);
|
|
51
|
+
expect(r.project.outputDir?.startsWith('~')).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('errors when no project is provided', async () => {
|
|
54
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
55
|
+
await expect(loadProfile({ org: 'widgets', configPath })).rejects.toThrow(/No project specified/);
|
|
56
|
+
});
|
|
57
|
+
it('errors when no org is provided', async () => {
|
|
58
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
59
|
+
await expect(loadProfile({ configPath })).rejects.toThrow(/--org/);
|
|
60
|
+
});
|
|
61
|
+
it('errors when org has no token', async () => {
|
|
62
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
63
|
+
mockedGetToken.mockResolvedValueOnce(undefined);
|
|
64
|
+
await expect(loadProfile({ org: 'acme', project: 'PROJ', configPath })).rejects.toThrow(/No API token/);
|
|
65
|
+
});
|
|
66
|
+
it('errors on missing org', async () => {
|
|
67
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
68
|
+
await expect(loadProfile({ org: 'nope', project: 'PROJ', configPath })).rejects.toThrow(/not found/);
|
|
69
|
+
});
|
|
70
|
+
it('errors on missing project under known org', async () => {
|
|
71
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
72
|
+
await expect(loadProfile({ org: 'acme', project: 'NOPE', configPath })).rejects.toThrow(/not found in org/);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('upsertOrg + upsertProject', () => {
|
|
76
|
+
it('writes and round-trips an org with projects', () => {
|
|
77
|
+
upsertOrg({
|
|
78
|
+
name: 'fresh',
|
|
79
|
+
baseUrl: 'https://fresh.example',
|
|
80
|
+
userEmail: 'f@x.example',
|
|
81
|
+
videoFrames: { enabled: true, fps: 7, maxFrames: 20 },
|
|
82
|
+
projects: {},
|
|
83
|
+
}, configPath);
|
|
84
|
+
upsertProject('fresh', { key: 'FR', outputDir: '/tmp/fr' }, configPath);
|
|
85
|
+
upsertProject('fresh', { key: 'FR2' }, configPath);
|
|
86
|
+
const raw = readConfig(configPath);
|
|
87
|
+
expect(raw.orgs?.fresh.base_url).toBe('https://fresh.example');
|
|
88
|
+
expect(raw.orgs?.fresh.video_frames?.fps).toBe(7);
|
|
89
|
+
expect(raw.orgs?.fresh.projects?.FR.output_dir).toBe('/tmp/fr');
|
|
90
|
+
expect(raw.orgs?.fresh.projects?.FR2).toBeDefined();
|
|
91
|
+
});
|
|
92
|
+
it('upsertProject errors if org missing', () => {
|
|
93
|
+
expect(() => upsertProject('nope', { key: 'X' }, configPath)).toThrow(/not found/);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
describe('findOrgsByProjectKey', () => {
|
|
97
|
+
it('returns empty when no match', () => {
|
|
98
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
99
|
+
expect(findOrgsByProjectKey('NOPE', readConfig(configPath))).toEqual([]);
|
|
100
|
+
});
|
|
101
|
+
it('returns the single org when only one matches', () => {
|
|
102
|
+
writeFileSync(configPath, SAMPLE_CONFIG);
|
|
103
|
+
expect(findOrgsByProjectKey('WID', readConfig(configPath))).toEqual(['widgets']);
|
|
104
|
+
});
|
|
105
|
+
it('returns multiple orgs when several share the project key', () => {
|
|
106
|
+
writeFileSync(configPath, `${SAMPLE_CONFIG}\n[orgs.widgets.projects.PROJ]\noutput_dir = "~/jira/widgets/proj"\n`);
|
|
107
|
+
const matches = findOrgsByProjectKey('PROJ', readConfig(configPath));
|
|
108
|
+
expect(matches.sort()).toEqual(['acme', 'widgets']);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('config validation (Zod)', () => {
|
|
112
|
+
it('rejects missing base_url with field path', () => {
|
|
113
|
+
writeFileSync(configPath, `[orgs.acme]\nuser_email = "u@x.example"\n`);
|
|
114
|
+
expect(() => readConfig(configPath)).toThrow(/orgs\.acme\.base_url/);
|
|
115
|
+
});
|
|
116
|
+
it('rejects wrong type for video_frames.fps', () => {
|
|
117
|
+
writeFileSync(configPath, `[orgs.acme]\nbase_url = "https://x.example"\nuser_email = "u@x.example"\n[orgs.acme.video_frames]\nfps = "five"\n`);
|
|
118
|
+
expect(() => readConfig(configPath)).toThrow(/orgs\.acme\.video_frames\.fps/);
|
|
119
|
+
});
|
|
120
|
+
it('rejects unknown keys at the org level', () => {
|
|
121
|
+
writeFileSync(configPath, `[orgs.acme]\nbase_url = "https://x.example"\nuser_email = "u@x.example"\nbasee_url = "typo"\n`);
|
|
122
|
+
expect(() => readConfig(configPath)).toThrow(/orgs\.acme/);
|
|
123
|
+
});
|
|
124
|
+
it('accepts an empty file', () => {
|
|
125
|
+
writeFileSync(configPath, '');
|
|
126
|
+
expect(() => readConfig(configPath)).not.toThrow();
|
|
127
|
+
expect(readConfig(configPath)).toEqual({});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/lib/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const projectRawSchema: z.ZodObject<{
|
|
3
|
+
output_dir: z.ZodOptional<z.ZodString>;
|
|
4
|
+
}, z.core.$strict>;
|
|
5
|
+
declare const orgRawSchema: z.ZodObject<{
|
|
6
|
+
base_url: z.ZodURL;
|
|
7
|
+
user_email: z.ZodEmail;
|
|
8
|
+
include_subtasks: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
video_frames: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
11
|
+
fps: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
quality: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
max_frames: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
similarity_threshold: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, z.core.$strict>>;
|
|
16
|
+
projects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
17
|
+
output_dir: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, z.core.$strict>>>;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
declare const configRawSchema: z.ZodObject<{
|
|
21
|
+
orgs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
22
|
+
base_url: z.ZodURL;
|
|
23
|
+
user_email: z.ZodEmail;
|
|
24
|
+
include_subtasks: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
video_frames: z.ZodOptional<z.ZodObject<{
|
|
26
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
fps: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
quality: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
max_frames: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
similarity_threshold: z.ZodOptional<z.ZodNumber>;
|
|
31
|
+
}, z.core.$strict>>;
|
|
32
|
+
projects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
33
|
+
output_dir: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strict>>>;
|
|
35
|
+
}, z.core.$strict>>>;
|
|
36
|
+
}, z.core.$strict>;
|
|
37
|
+
export type RawProject = z.infer<typeof projectRawSchema>;
|
|
38
|
+
export type RawOrg = z.infer<typeof orgRawSchema>;
|
|
39
|
+
export type RawConfig = z.infer<typeof configRawSchema>;
|
|
40
|
+
export declare function parseConfig(input: unknown, sourcePath?: string): RawConfig;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=configSchema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configSchema.d.ts","sourceRoot":"","sources":["../../src/lib/configSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,QAAA,MAAM,gBAAgB;;kBAIX,CAAC;AAEZ,QAAA,MAAM,YAAY;;;;;;;;;;;;;;kBAQP,CAAC;AAEZ,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;kBAIV,CAAC;AAEZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAU1E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const videoFramesRawSchema = z
|
|
3
|
+
.object({
|
|
4
|
+
enabled: z.boolean().optional(),
|
|
5
|
+
fps: z.number().optional(),
|
|
6
|
+
quality: z.number().optional(),
|
|
7
|
+
max_frames: z.number().optional(),
|
|
8
|
+
similarity_threshold: z.number().optional(),
|
|
9
|
+
})
|
|
10
|
+
.strict();
|
|
11
|
+
const projectRawSchema = z
|
|
12
|
+
.object({
|
|
13
|
+
output_dir: z.string().optional(),
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
16
|
+
const orgRawSchema = z
|
|
17
|
+
.object({
|
|
18
|
+
base_url: z.url(),
|
|
19
|
+
user_email: z.email(),
|
|
20
|
+
include_subtasks: z.boolean().optional(),
|
|
21
|
+
video_frames: videoFramesRawSchema.optional(),
|
|
22
|
+
projects: z.record(z.string(), projectRawSchema).optional(),
|
|
23
|
+
})
|
|
24
|
+
.strict();
|
|
25
|
+
const configRawSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
orgs: z.record(z.string(), orgRawSchema).optional(),
|
|
28
|
+
})
|
|
29
|
+
.strict();
|
|
30
|
+
export function parseConfig(input, sourcePath) {
|
|
31
|
+
const result = configRawSchema.safeParse(input);
|
|
32
|
+
if (result.success)
|
|
33
|
+
return result.data;
|
|
34
|
+
const lines = result.error.issues.map((issue) => {
|
|
35
|
+
const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
36
|
+
return ` ${path}: ${issue.message}`;
|
|
37
|
+
});
|
|
38
|
+
const where = sourcePath ? ` at ${sourcePath}` : '';
|
|
39
|
+
throw new Error(`Invalid jirallm config${where}:\n${lines.join('\n')}`);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=configSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configSchema.js","sourceRoot":"","sources":["../../src/lib/configSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,oBAAoB,GAAG,CAAC;KAC3B,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5C,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE;IACrB,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACxC,YAAY,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC7C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,eAAe,GAAG,CAAC;KACtB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,QAAQ,EAAE;CACpD,CAAC;KACD,MAAM,EAAE,CAAC;AAMZ,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,UAAmB;IAC7D,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC;IAEvC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACrE,OAAO,KAAK,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function getToken(orgName: string): Promise<string | undefined>;
|
|
2
|
+
export declare function setToken(orgName: string, token: string): Promise<void>;
|
|
3
|
+
export declare function removeToken(orgName: string): Promise<boolean>;
|
|
4
|
+
export declare function hasStoredToken(orgName: string): Promise<boolean>;
|
|
5
|
+
export declare const __test: {
|
|
6
|
+
resetKeytarCache: () => void;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAyBA,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS3E;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAInE;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAStE;AAED,eAAO,MAAM,MAAM;;CAKlB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const SERVICE = 'jirallm';
|
|
2
|
+
let keytarLoadPromise;
|
|
3
|
+
let cachedKeytar;
|
|
4
|
+
async function loadKeytar() {
|
|
5
|
+
if (keytarLoadPromise)
|
|
6
|
+
return keytarLoadPromise;
|
|
7
|
+
keytarLoadPromise = (async () => {
|
|
8
|
+
try {
|
|
9
|
+
const mod = (await import('keytar'));
|
|
10
|
+
cachedKeytar = (mod.default ?? mod);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
cachedKeytar = undefined;
|
|
14
|
+
}
|
|
15
|
+
return cachedKeytar;
|
|
16
|
+
})();
|
|
17
|
+
return keytarLoadPromise;
|
|
18
|
+
}
|
|
19
|
+
export async function getToken(orgName) {
|
|
20
|
+
const keytar = await loadKeytar();
|
|
21
|
+
if (!keytar)
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
const t = await keytar.getPassword(SERVICE, `${orgName}:api_token`);
|
|
25
|
+
return t ?? undefined;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function setToken(orgName, token) {
|
|
32
|
+
const keytar = await loadKeytar();
|
|
33
|
+
if (!keytar) {
|
|
34
|
+
throw new Error('OS keychain (keytar) is unavailable. Run `pnpm rebuild keytar` after `pnpm approve-builds`.');
|
|
35
|
+
}
|
|
36
|
+
await keytar.setPassword(SERVICE, `${orgName}:api_token`, token);
|
|
37
|
+
}
|
|
38
|
+
export async function removeToken(orgName) {
|
|
39
|
+
const keytar = await loadKeytar();
|
|
40
|
+
if (!keytar)
|
|
41
|
+
return false;
|
|
42
|
+
return keytar.deletePassword(SERVICE, `${orgName}:api_token`);
|
|
43
|
+
}
|
|
44
|
+
export async function hasStoredToken(orgName) {
|
|
45
|
+
const keytar = await loadKeytar();
|
|
46
|
+
if (!keytar)
|
|
47
|
+
return false;
|
|
48
|
+
try {
|
|
49
|
+
const t = await keytar.getPassword(SERVICE, `${orgName}:api_token`);
|
|
50
|
+
return Boolean(t);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export const __test = {
|
|
57
|
+
resetKeytarCache: () => {
|
|
58
|
+
keytarLoadPromise = undefined;
|
|
59
|
+
cachedKeytar = undefined;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/lib/credentials.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,SAAS,CAAC;AAQ1B,IAAI,iBAA0D,CAAC;AAC/D,IAAI,YAAgC,CAAC;AAErC,KAAK,UAAU,UAAU;IACvB,IAAI,iBAAiB;QAAE,OAAO,iBAAiB,CAAC;IAChD,iBAAiB,GAAG,CAAC,KAAK,IAAI,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAA2C,CAAC;YAC/E,YAAY,GAAG,CAAC,GAAG,CAAC,OAAO,IAAK,GAAyB,CAAkB,CAAC;QAC9E,CAAC;QAAC,MAAM,CAAC;YACP,YAAY,GAAG,SAAS,CAAC;QAC3B,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC,EAAE,CAAC;IACL,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,OAAO,YAAY,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,SAAS,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAe,EAAE,KAAa;IAC3D,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,OAAO,YAAY,EAAE,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,OAAO,YAAY,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,OAAO,YAAY,CAAC,CAAC;QACpE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gBAAgB,EAAE,GAAG,EAAE;QACrB,iBAAiB,GAAG,SAAS,CAAC;QAC9B,YAAY,GAAG,SAAS,CAAC;IAC3B,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.test.d.ts","sourceRoot":"","sources":["../../src/lib/credentials.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
const store = new Map();
|
|
3
|
+
vi.mock('keytar', () => {
|
|
4
|
+
const k = (s, a) => `${s}::${a}`;
|
|
5
|
+
return {
|
|
6
|
+
default: {
|
|
7
|
+
getPassword: vi.fn(async (s, a) => store.get(k(s, a)) ?? null),
|
|
8
|
+
setPassword: vi.fn(async (s, a, p) => {
|
|
9
|
+
store.set(k(s, a), p);
|
|
10
|
+
}),
|
|
11
|
+
deletePassword: vi.fn(async (s, a) => store.delete(k(s, a))),
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
import { getToken, setToken, removeToken, hasStoredToken, __test } from './credentials.js';
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
store.clear();
|
|
18
|
+
__test.resetKeytarCache();
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
store.clear();
|
|
22
|
+
});
|
|
23
|
+
describe('credentials', () => {
|
|
24
|
+
it('round-trips token via keychain', async () => {
|
|
25
|
+
await setToken('work', 'tok-1');
|
|
26
|
+
expect(await hasStoredToken('work')).toBe(true);
|
|
27
|
+
expect(await getToken('work')).toBe('tok-1');
|
|
28
|
+
expect(await removeToken('work')).toBe(true);
|
|
29
|
+
expect(await getToken('work')).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
it('returns undefined when no keychain entry exists', async () => {
|
|
32
|
+
expect(await getToken('anything')).toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=credentials.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.test.js","sourceRoot":"","sources":["../../src/lib/credentials.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;IACrB,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACjD,OAAO;QACL,OAAO,EAAE;YACP,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;YAC9E,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE;gBAC3D,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,CAAC,CAAC;YACF,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SAC7E;KACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE3F,UAAU,CAAC,GAAG,EAAE;IACd,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,MAAM,CAAC,gBAAgB,EAAE,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type JiraConfig } from './jiraClient.js';
|
|
2
|
+
export type ExportOptions = {
|
|
3
|
+
outputDir: string;
|
|
4
|
+
includeSubtasks?: boolean;
|
|
5
|
+
includeParentEpic?: boolean;
|
|
6
|
+
videoFrames?: {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
fps?: number;
|
|
9
|
+
quality?: number;
|
|
10
|
+
maxFrames?: number;
|
|
11
|
+
similarityThreshold?: number;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export type ExportResult = {
|
|
15
|
+
imported: string[];
|
|
16
|
+
updated: string[];
|
|
17
|
+
failed: Array<{
|
|
18
|
+
key: string;
|
|
19
|
+
error: string;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
export declare class JiraExporter {
|
|
23
|
+
private client;
|
|
24
|
+
constructor(config: JiraConfig, apiToken: string);
|
|
25
|
+
exportIssue(issueKey: string, options: ExportOptions): Promise<string>;
|
|
26
|
+
exportIssues(issueKeys: string[], options: ExportOptions): Promise<ExportResult>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/lib/exporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,UAAU,EAAqB,MAAM,iBAAiB,CAAC;AAGjF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE;QACZ,OAAO,EAAE,OAAO,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C,CAAC;AAoEF,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM;IAI1C,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IA0EtE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAuBvF"}
|