@fink-andreas/pi-linear-tools 0.1.0 → 0.2.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/CHANGELOG.md +20 -1
- package/README.md +18 -2
- package/extensions/pi-linear-tools.js +454 -109
- package/package.json +4 -2
- package/src/auth/callback-server.js +337 -0
- package/src/auth/index.js +246 -0
- package/src/auth/oauth.js +281 -0
- package/src/auth/pkce.js +111 -0
- package/src/auth/token-refresh.js +210 -0
- package/src/auth/token-store.js +415 -0
- package/src/cli.js +232 -59
- package/src/handlers.js +7 -2
- package/src/linear-client.js +36 -6
- package/src/linear.js +13 -1
- package/src/settings.js +107 -6
package/src/settings.js
CHANGED
|
@@ -10,8 +10,13 @@ import { debug, warn, error as logError } from './logger.js';
|
|
|
10
10
|
|
|
11
11
|
export function getDefaultSettings() {
|
|
12
12
|
return {
|
|
13
|
-
schemaVersion:
|
|
14
|
-
|
|
13
|
+
schemaVersion: 2,
|
|
14
|
+
authMethod: 'api-key', // 'api-key' or 'oauth'
|
|
15
|
+
apiKey: null, // Legacy API key (migrated from linearApiKey)
|
|
16
|
+
oauth: {
|
|
17
|
+
clientId: 'a3e177176c6697611367f1a2405d4a34',
|
|
18
|
+
redirectUri: 'http://localhost:34711/callback',
|
|
19
|
+
},
|
|
15
20
|
defaultTeam: null,
|
|
16
21
|
defaultWorkspace: null,
|
|
17
22
|
projects: {},
|
|
@@ -21,12 +26,70 @@ export function getDefaultSettings() {
|
|
|
21
26
|
function migrateSettings(settings) {
|
|
22
27
|
const migrated = { ...(settings || {}) };
|
|
23
28
|
|
|
29
|
+
// Set default schema version if not set
|
|
24
30
|
if (migrated.schemaVersion === undefined) {
|
|
25
31
|
migrated.schemaVersion = 1;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
// Migration from schema version 1 to 2
|
|
35
|
+
if (migrated.schemaVersion === 1) {
|
|
36
|
+
debug('Migrating settings from schema version 1 to 2');
|
|
37
|
+
|
|
38
|
+
// Migrate linearApiKey to apiKey
|
|
39
|
+
if (migrated.linearApiKey !== undefined) {
|
|
40
|
+
migrated.apiKey = migrated.linearApiKey;
|
|
41
|
+
delete migrated.linearApiKey;
|
|
42
|
+
} else {
|
|
43
|
+
migrated.apiKey = null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Set default auth method
|
|
47
|
+
migrated.authMethod = 'api-key';
|
|
48
|
+
|
|
49
|
+
// Add OAuth config
|
|
50
|
+
if (!migrated.oauth || typeof migrated.oauth !== 'object') {
|
|
51
|
+
migrated.oauth = {
|
|
52
|
+
clientId: 'a3e177176c6697611367f1a2405d4a34',
|
|
53
|
+
redirectUri: 'http://localhost:34711/callback',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Update schema version
|
|
58
|
+
migrated.schemaVersion = 2;
|
|
59
|
+
|
|
60
|
+
debug('Settings migration to version 2 complete');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Ensure authMethod is set
|
|
64
|
+
if (migrated.authMethod === undefined) {
|
|
65
|
+
migrated.authMethod = 'api-key';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Ensure apiKey is set (for backward compatibility)
|
|
69
|
+
if (migrated.apiKey === undefined) {
|
|
70
|
+
migrated.apiKey = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Ensure oauth config exists
|
|
74
|
+
if (!migrated.oauth || typeof migrated.oauth !== 'object') {
|
|
75
|
+
migrated.oauth = {
|
|
76
|
+
clientId: 'a3e177176c6697611367f1a2405d4a34',
|
|
77
|
+
redirectUri: 'http://localhost:34711/callback',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Ensure oauth has clientId and redirectUri
|
|
82
|
+
if (migrated.oauth.clientId === undefined) {
|
|
83
|
+
migrated.oauth.clientId = 'a3e177176c6697611367f1a2405d4a34';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (migrated.oauth.redirectUri === undefined) {
|
|
87
|
+
migrated.oauth.redirectUri = 'http://localhost:34711/callback';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Legacy: ensure linearApiKey is null (for validation)
|
|
91
|
+
if (migrated.linearApiKey !== undefined) {
|
|
92
|
+
delete migrated.linearApiKey;
|
|
30
93
|
}
|
|
31
94
|
|
|
32
95
|
if (migrated.defaultTeam === undefined) {
|
|
@@ -37,10 +100,17 @@ function migrateSettings(settings) {
|
|
|
37
100
|
migrated.defaultWorkspace = null;
|
|
38
101
|
}
|
|
39
102
|
|
|
103
|
+
// Remove deprecated debug_reload field
|
|
104
|
+
if (Object.prototype.hasOwnProperty.call(migrated, 'debug_reload')) {
|
|
105
|
+
delete migrated.debug_reload;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Ensure projects is an object
|
|
40
109
|
if (!migrated.projects || typeof migrated.projects !== 'object' || Array.isArray(migrated.projects)) {
|
|
41
110
|
migrated.projects = {};
|
|
42
111
|
}
|
|
43
112
|
|
|
113
|
+
// Migrate project scopes
|
|
44
114
|
for (const [projectId, cfg] of Object.entries(migrated.projects)) {
|
|
45
115
|
if (!cfg || typeof cfg !== 'object' || Array.isArray(cfg)) {
|
|
46
116
|
migrated.projects[projectId] = { scope: { team: null } };
|
|
@@ -71,8 +141,39 @@ export function validateSettings(settings) {
|
|
|
71
141
|
errors.push('settings.schemaVersion must be a positive number');
|
|
72
142
|
}
|
|
73
143
|
|
|
74
|
-
|
|
75
|
-
|
|
144
|
+
// Validate authMethod
|
|
145
|
+
if (settings.authMethod !== undefined && settings.authMethod !== null) {
|
|
146
|
+
if (typeof settings.authMethod !== 'string') {
|
|
147
|
+
errors.push('settings.authMethod must be a string');
|
|
148
|
+
} else if (
|
|
149
|
+
!['api-key', 'oauth'].includes(settings.authMethod)
|
|
150
|
+
) {
|
|
151
|
+
errors.push('settings.authMethod must be "api-key" or "oauth"');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Validate apiKey (for backward compatibility)
|
|
156
|
+
if (settings.apiKey !== null && settings.apiKey !== undefined && typeof settings.apiKey !== 'string') {
|
|
157
|
+
errors.push('settings.apiKey must be a string or null');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Reject legacy linearApiKey field
|
|
161
|
+
if (settings.linearApiKey !== undefined) {
|
|
162
|
+
errors.push('settings.linearApiKey is deprecated. Use settings.apiKey instead.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Validate oauth config
|
|
166
|
+
if (settings.oauth !== undefined && settings.oauth !== null) {
|
|
167
|
+
if (typeof settings.oauth !== 'object' || Array.isArray(settings.oauth)) {
|
|
168
|
+
errors.push('settings.oauth must be an object');
|
|
169
|
+
} else {
|
|
170
|
+
if (settings.oauth.clientId !== undefined && typeof settings.oauth.clientId !== 'string') {
|
|
171
|
+
errors.push('settings.oauth.clientId must be a string');
|
|
172
|
+
}
|
|
173
|
+
if (settings.oauth.redirectUri !== undefined && typeof settings.oauth.redirectUri !== 'string') {
|
|
174
|
+
errors.push('settings.oauth.redirectUri must be a string');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
76
177
|
}
|
|
77
178
|
|
|
78
179
|
if (settings.defaultTeam !== null && settings.defaultTeam !== undefined && typeof settings.defaultTeam !== 'string') {
|