@proletariat/cli 0.3.59 → 0.3.61

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,113 @@
1
+ /**
2
+ * Multi-Source Provider Configuration
3
+ *
4
+ * Allows a workspace to have multiple external ticket providers configured
5
+ * simultaneously (e.g. Linear for engineering, Asana for product, Shortcut
6
+ * for design). Each source entry includes a provider type, API key reference,
7
+ * team/project ID, and an identifier prefix used for routing ticket keys to
8
+ * the correct provider.
9
+ *
10
+ * Stored as a JSON array in workspace_settings under the key
11
+ * `work.provider_sources`.
12
+ */
13
+ import Database from 'better-sqlite3';
14
+ import type { WorkSourceProvider } from './config.js';
15
+ /**
16
+ * A single provider source entry in the multi-source configuration.
17
+ *
18
+ * Example: { id: 'eng-linear', provider: 'linear', apiKeyRef: 'linear.api_key',
19
+ * teamProjectId: 'ENG', prefix: 'ENG-', label: 'Engineering' }
20
+ */
21
+ export interface ProviderSourceEntry {
22
+ /** Unique identifier for this source config (user-chosen, slug-like) */
23
+ id: string;
24
+ /** Provider type (linear, jira, asana, shortcut, trello, monday) */
25
+ provider: WorkSourceProvider;
26
+ /**
27
+ * Reference to the API key. Can be:
28
+ * - A workspace_settings key (e.g. 'linear.api_key')
29
+ * - An environment variable name (e.g. 'PRLT_LINEAR_API_KEY')
30
+ */
31
+ apiKeyRef: string;
32
+ /**
33
+ * Team or project identifier in the external system.
34
+ * e.g. Linear team key 'ENG', Jira project key 'PROJ', Asana project GID.
35
+ */
36
+ teamProjectId: string;
37
+ /**
38
+ * Prefix used for routing ticket keys to this provider.
39
+ * e.g. 'ENG-' means ticket keys starting with 'ENG-' route to this source.
40
+ * Must end with a separator character (typically '-').
41
+ */
42
+ prefix: string;
43
+ /** Optional human-readable label for display purposes */
44
+ label?: string;
45
+ }
46
+ export interface ProviderSourceValidationError {
47
+ field: string;
48
+ message: string;
49
+ }
50
+ export declare function validateProviderSourceEntry(entry: Partial<ProviderSourceEntry>): ProviderSourceValidationError[];
51
+ /**
52
+ * Load all provider source entries from the database.
53
+ * Returns an empty array if none are configured.
54
+ */
55
+ export declare function loadProviderSources(db: Database.Database): ProviderSourceEntry[];
56
+ /**
57
+ * Save the full list of provider source entries to the database.
58
+ */
59
+ export declare function saveProviderSources(db: Database.Database, sources: ProviderSourceEntry[]): void;
60
+ /**
61
+ * Add a new provider source entry. Returns validation errors if invalid,
62
+ * or throws if an entry with the same id already exists.
63
+ */
64
+ export declare function addProviderSource(db: Database.Database, entry: ProviderSourceEntry): ProviderSourceValidationError[];
65
+ /**
66
+ * Update an existing provider source entry by id.
67
+ * Returns validation errors if the update is invalid, or if the entry is not found.
68
+ */
69
+ export declare function updateProviderSource(db: Database.Database, id: string, updates: Partial<Omit<ProviderSourceEntry, 'id'>>): ProviderSourceValidationError[];
70
+ /**
71
+ * Remove a provider source entry by id.
72
+ * Returns true if removed, false if not found.
73
+ */
74
+ export declare function removeProviderSource(db: Database.Database, id: string): boolean;
75
+ /**
76
+ * Get a single provider source entry by id.
77
+ */
78
+ export declare function getProviderSourceById(db: Database.Database, id: string): ProviderSourceEntry | null;
79
+ /**
80
+ * Resolve which provider source should handle a given ticket key based on
81
+ * its prefix. Matching is case-insensitive and selects the longest matching
82
+ * prefix (most specific match wins).
83
+ *
84
+ * Example: given sources with prefixes ['ENG-', 'PROD-', 'DES-'],
85
+ * resolveProviderByPrefix(db, 'ENG-123') → source with prefix 'ENG-'
86
+ * resolveProviderByPrefix(db, 'PROD-456') → source with prefix 'PROD-'
87
+ * resolveProviderByPrefix(db, 'UNKNOWN-789') → null
88
+ */
89
+ export declare function resolveProviderByPrefix(db: Database.Database, ticketKey: string): ProviderSourceEntry | null;
90
+ /**
91
+ * Pure function variant that operates on an in-memory list of sources.
92
+ * Useful for testing and batch operations.
93
+ */
94
+ export declare function resolveProviderByPrefixFromList(sources: ProviderSourceEntry[], ticketKey: string): ProviderSourceEntry | null;
95
+ /**
96
+ * Get all configured prefixes and their provider mappings.
97
+ * Useful for displaying the routing table to the user.
98
+ */
99
+ export declare function getRoutingTable(db: Database.Database): Array<{
100
+ prefix: string;
101
+ provider: WorkSourceProvider;
102
+ label: string;
103
+ id: string;
104
+ }>;
105
+ /**
106
+ * Resolve the actual API key value from a ProviderSourceEntry's apiKeyRef.
107
+ *
108
+ * Resolution order:
109
+ * 1. If apiKeyRef matches an environment variable name, use its value
110
+ * 2. If apiKeyRef matches a workspace_settings key, use its value
111
+ * 3. Return null if neither resolves
112
+ */
113
+ export declare function resolveApiKey(db: Database.Database, entry: ProviderSourceEntry): string | null;
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Multi-Source Provider Configuration
3
+ *
4
+ * Allows a workspace to have multiple external ticket providers configured
5
+ * simultaneously (e.g. Linear for engineering, Asana for product, Shortcut
6
+ * for design). Each source entry includes a provider type, API key reference,
7
+ * team/project ID, and an identifier prefix used for routing ticket keys to
8
+ * the correct provider.
9
+ *
10
+ * Stored as a JSON array in workspace_settings under the key
11
+ * `work.provider_sources`.
12
+ */
13
+ import { WORK_SOURCE_PROVIDERS, isWorkSourceProvider } from './config.js';
14
+ const SETTINGS_TABLE = 'workspace_settings';
15
+ const PROVIDER_SOURCES_KEY = 'work.provider_sources';
16
+ export function validateProviderSourceEntry(entry) {
17
+ const errors = [];
18
+ if (!entry.id || entry.id.trim().length === 0) {
19
+ errors.push({ field: 'id', message: 'id is required' });
20
+ }
21
+ else if (!/^[a-z0-9][a-z0-9_-]*$/.test(entry.id)) {
22
+ errors.push({
23
+ field: 'id',
24
+ message: 'id must be lowercase alphanumeric with hyphens/underscores, starting with a letter or digit',
25
+ });
26
+ }
27
+ if (!entry.provider) {
28
+ errors.push({ field: 'provider', message: 'provider is required' });
29
+ }
30
+ else if (!isWorkSourceProvider(entry.provider)) {
31
+ errors.push({
32
+ field: 'provider',
33
+ message: `provider must be one of: ${WORK_SOURCE_PROVIDERS.join(', ')}`,
34
+ });
35
+ }
36
+ if (!entry.apiKeyRef || entry.apiKeyRef.trim().length === 0) {
37
+ errors.push({ field: 'apiKeyRef', message: 'apiKeyRef is required' });
38
+ }
39
+ if (!entry.teamProjectId || entry.teamProjectId.trim().length === 0) {
40
+ errors.push({ field: 'teamProjectId', message: 'teamProjectId is required' });
41
+ }
42
+ if (!entry.prefix || entry.prefix.trim().length === 0) {
43
+ errors.push({ field: 'prefix', message: 'prefix is required' });
44
+ }
45
+ return errors;
46
+ }
47
+ // =============================================================================
48
+ // Persistence
49
+ // =============================================================================
50
+ function getRawSetting(db, key) {
51
+ const row = db
52
+ .prepare(`SELECT value FROM ${SETTINGS_TABLE} WHERE key = ?`)
53
+ .get(key);
54
+ return row?.value ?? null;
55
+ }
56
+ function setRawSetting(db, key, value) {
57
+ db.prepare(`
58
+ INSERT INTO ${SETTINGS_TABLE} (key, value)
59
+ VALUES (?, ?)
60
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
61
+ `).run(key, value);
62
+ }
63
+ function deleteRawSetting(db, key) {
64
+ db.prepare(`DELETE FROM ${SETTINGS_TABLE} WHERE key = ?`).run(key);
65
+ }
66
+ /**
67
+ * Load all provider source entries from the database.
68
+ * Returns an empty array if none are configured.
69
+ */
70
+ export function loadProviderSources(db) {
71
+ const raw = getRawSetting(db, PROVIDER_SOURCES_KEY);
72
+ if (!raw)
73
+ return [];
74
+ try {
75
+ const parsed = JSON.parse(raw);
76
+ if (!Array.isArray(parsed))
77
+ return [];
78
+ return parsed.filter((entry) => typeof entry === 'object' &&
79
+ entry !== null &&
80
+ typeof entry.id === 'string' &&
81
+ typeof entry.provider === 'string');
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ }
87
+ /**
88
+ * Save the full list of provider source entries to the database.
89
+ */
90
+ export function saveProviderSources(db, sources) {
91
+ if (sources.length === 0) {
92
+ deleteRawSetting(db, PROVIDER_SOURCES_KEY);
93
+ return;
94
+ }
95
+ setRawSetting(db, PROVIDER_SOURCES_KEY, JSON.stringify(sources));
96
+ }
97
+ /**
98
+ * Add a new provider source entry. Returns validation errors if invalid,
99
+ * or throws if an entry with the same id already exists.
100
+ */
101
+ export function addProviderSource(db, entry) {
102
+ const errors = validateProviderSourceEntry(entry);
103
+ if (errors.length > 0)
104
+ return errors;
105
+ const existing = loadProviderSources(db);
106
+ if (existing.some((e) => e.id === entry.id)) {
107
+ return [{ field: 'id', message: `A provider source with id "${entry.id}" already exists` }];
108
+ }
109
+ if (existing.some((e) => e.prefix.toUpperCase() === entry.prefix.toUpperCase())) {
110
+ return [{ field: 'prefix', message: `A provider source with prefix "${entry.prefix}" already exists` }];
111
+ }
112
+ existing.push(entry);
113
+ saveProviderSources(db, existing);
114
+ return [];
115
+ }
116
+ /**
117
+ * Update an existing provider source entry by id.
118
+ * Returns validation errors if the update is invalid, or if the entry is not found.
119
+ */
120
+ export function updateProviderSource(db, id, updates) {
121
+ const sources = loadProviderSources(db);
122
+ const index = sources.findIndex((e) => e.id === id);
123
+ if (index === -1) {
124
+ return [{ field: 'id', message: `No provider source found with id "${id}"` }];
125
+ }
126
+ const merged = { ...sources[index], ...updates };
127
+ const errors = validateProviderSourceEntry(merged);
128
+ if (errors.length > 0)
129
+ return errors;
130
+ // Check prefix uniqueness against other entries
131
+ if (updates.prefix &&
132
+ sources.some((e, i) => i !== index && e.prefix.toUpperCase() === updates.prefix.toUpperCase())) {
133
+ return [{ field: 'prefix', message: `A provider source with prefix "${updates.prefix}" already exists` }];
134
+ }
135
+ sources[index] = merged;
136
+ saveProviderSources(db, sources);
137
+ return [];
138
+ }
139
+ /**
140
+ * Remove a provider source entry by id.
141
+ * Returns true if removed, false if not found.
142
+ */
143
+ export function removeProviderSource(db, id) {
144
+ const sources = loadProviderSources(db);
145
+ const filtered = sources.filter((e) => e.id !== id);
146
+ if (filtered.length === sources.length)
147
+ return false;
148
+ saveProviderSources(db, filtered);
149
+ return true;
150
+ }
151
+ /**
152
+ * Get a single provider source entry by id.
153
+ */
154
+ export function getProviderSourceById(db, id) {
155
+ const sources = loadProviderSources(db);
156
+ return sources.find((e) => e.id === id) ?? null;
157
+ }
158
+ // =============================================================================
159
+ // Prefix-Based Routing
160
+ // =============================================================================
161
+ /**
162
+ * Resolve which provider source should handle a given ticket key based on
163
+ * its prefix. Matching is case-insensitive and selects the longest matching
164
+ * prefix (most specific match wins).
165
+ *
166
+ * Example: given sources with prefixes ['ENG-', 'PROD-', 'DES-'],
167
+ * resolveProviderByPrefix(db, 'ENG-123') → source with prefix 'ENG-'
168
+ * resolveProviderByPrefix(db, 'PROD-456') → source with prefix 'PROD-'
169
+ * resolveProviderByPrefix(db, 'UNKNOWN-789') → null
170
+ */
171
+ export function resolveProviderByPrefix(db, ticketKey) {
172
+ const sources = loadProviderSources(db);
173
+ return resolveProviderByPrefixFromList(sources, ticketKey);
174
+ }
175
+ /**
176
+ * Pure function variant that operates on an in-memory list of sources.
177
+ * Useful for testing and batch operations.
178
+ */
179
+ export function resolveProviderByPrefixFromList(sources, ticketKey) {
180
+ const upperKey = ticketKey.toUpperCase();
181
+ let bestMatch = null;
182
+ let bestLength = 0;
183
+ for (const source of sources) {
184
+ const upperPrefix = source.prefix.toUpperCase();
185
+ if (upperKey.startsWith(upperPrefix) && upperPrefix.length > bestLength) {
186
+ bestMatch = source;
187
+ bestLength = upperPrefix.length;
188
+ }
189
+ }
190
+ return bestMatch;
191
+ }
192
+ /**
193
+ * Get all configured prefixes and their provider mappings.
194
+ * Useful for displaying the routing table to the user.
195
+ */
196
+ export function getRoutingTable(db) {
197
+ const sources = loadProviderSources(db);
198
+ return sources.map((s) => ({
199
+ prefix: s.prefix,
200
+ provider: s.provider,
201
+ label: s.label ?? s.id,
202
+ id: s.id,
203
+ }));
204
+ }
205
+ // =============================================================================
206
+ // API Key Resolution
207
+ // =============================================================================
208
+ /**
209
+ * Resolve the actual API key value from a ProviderSourceEntry's apiKeyRef.
210
+ *
211
+ * Resolution order:
212
+ * 1. If apiKeyRef matches an environment variable name, use its value
213
+ * 2. If apiKeyRef matches a workspace_settings key, use its value
214
+ * 3. Return null if neither resolves
215
+ */
216
+ export function resolveApiKey(db, entry) {
217
+ // Try environment variable first
218
+ const envValue = process.env[entry.apiKeyRef];
219
+ if (envValue)
220
+ return envValue;
221
+ // Try workspace_settings key
222
+ const dbValue = getRawSetting(db, entry.apiKeyRef);
223
+ if (dbValue)
224
+ return dbValue;
225
+ return null;
226
+ }
227
+ //# sourceMappingURL=provider-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-sources.js","sourceRoot":"","sources":["../../../src/lib/work-source/provider-sources.ts"],"names":[],"mappings":"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"}