@glpkg/config 0.2.1 → 0.3.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/dist/cli.js +95 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +204 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -75,6 +75,24 @@ program
|
|
|
75
75
|
const packageCmd = program
|
|
76
76
|
.command('package')
|
|
77
77
|
.description('Manage package registry metadata');
|
|
78
|
+
// Add package manually
|
|
79
|
+
packageCmd
|
|
80
|
+
.command('add <package-name>')
|
|
81
|
+
.description('Add package with GitLab group lookup')
|
|
82
|
+
.requiredOption('-g, --group <group>', 'GitLab group name')
|
|
83
|
+
.option('--host <host>', 'GitLab host', 'gitlab.com')
|
|
84
|
+
.action(async (packageName, options) => {
|
|
85
|
+
try {
|
|
86
|
+
console.log(`Looking up group "${options.group}" on ${options.host}...`);
|
|
87
|
+
const info = await (0, index_1.addPackageManually)(packageName, options.group, options.host);
|
|
88
|
+
console.log('✓ Package added successfully');
|
|
89
|
+
console.log(JSON.stringify(info, null, 2));
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error('✗ Failed to add package:', error.message);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
78
96
|
// Get package info
|
|
79
97
|
packageCmd
|
|
80
98
|
.command('get <package-name>')
|
|
@@ -132,6 +150,83 @@ packageCmd
|
|
|
132
150
|
process.exit(1);
|
|
133
151
|
}
|
|
134
152
|
});
|
|
153
|
+
// Scope management commands
|
|
154
|
+
const scopeCmd = program
|
|
155
|
+
.command('scope')
|
|
156
|
+
.description('Manage scope to GitLab group mappings');
|
|
157
|
+
// Set scope mapping
|
|
158
|
+
scopeCmd
|
|
159
|
+
.command('set <scope> <group>')
|
|
160
|
+
.description('Map a scope to a GitLab group (e.g., scope set @ist microature)')
|
|
161
|
+
.option('--host <host>', 'GitLab host', 'gitlab.com')
|
|
162
|
+
.action(async (scope, group, options) => {
|
|
163
|
+
try {
|
|
164
|
+
console.log(`Looking up group "${group}" on ${options.host}...`);
|
|
165
|
+
const mapping = await (0, index_1.setScopeMapping)(scope, group, options.host);
|
|
166
|
+
console.log('✓ Scope mapping saved');
|
|
167
|
+
console.log(JSON.stringify(mapping, null, 2));
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error('✗ Failed to set scope mapping:', error.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
// Get scope mapping
|
|
175
|
+
scopeCmd
|
|
176
|
+
.command('get <scope>')
|
|
177
|
+
.description('Get scope mapping information')
|
|
178
|
+
.action((scope) => {
|
|
179
|
+
const mapping = (0, index_1.getScopeMapping)(scope);
|
|
180
|
+
if (mapping) {
|
|
181
|
+
console.log(JSON.stringify(mapping, null, 2));
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
console.error('✗ Scope not found:', scope);
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
// List all scope mappings
|
|
189
|
+
scopeCmd
|
|
190
|
+
.command('list')
|
|
191
|
+
.description('List all scope mappings')
|
|
192
|
+
.action(() => {
|
|
193
|
+
const metadata = (0, index_1.getAllScopes)();
|
|
194
|
+
const scopes = Object.values(metadata.scopes);
|
|
195
|
+
if (scopes.length === 0) {
|
|
196
|
+
console.log('No scope mappings found');
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
console.log(JSON.stringify(metadata, null, 2));
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
// Remove scope mapping
|
|
203
|
+
scopeCmd
|
|
204
|
+
.command('remove <scope>')
|
|
205
|
+
.description('Remove scope mapping')
|
|
206
|
+
.action((scope) => {
|
|
207
|
+
const removed = (0, index_1.removeScopeMapping)(scope);
|
|
208
|
+
if (removed) {
|
|
209
|
+
console.log('✓ Scope mapping removed:', scope);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
console.error('✗ Scope not found:', scope);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
// Clear all scope mappings
|
|
217
|
+
scopeCmd
|
|
218
|
+
.command('clear')
|
|
219
|
+
.description('Clear all scope mappings')
|
|
220
|
+
.action(() => {
|
|
221
|
+
try {
|
|
222
|
+
(0, index_1.clearAllScopes)();
|
|
223
|
+
console.log('✓ All scope mappings cleared');
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('✗ Failed to clear scope mappings:', error.message);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
135
230
|
program.parse();
|
|
136
231
|
// Show help if no command provided
|
|
137
232
|
if (!process.argv.slice(2).length) {
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,39 @@ export interface PackageInfo {
|
|
|
35
35
|
export interface PackageRegistryMetadata {
|
|
36
36
|
packages: Record<string, PackageInfo>;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Scope mapping information
|
|
40
|
+
*/
|
|
41
|
+
export interface ScopeMapping {
|
|
42
|
+
/** Scope name without @ (e.g., "ist") */
|
|
43
|
+
scope: string;
|
|
44
|
+
/** GitLab group name */
|
|
45
|
+
group: string;
|
|
46
|
+
/** GitLab group ID */
|
|
47
|
+
groupId: number;
|
|
48
|
+
/** GitLab host */
|
|
49
|
+
gitlabHost: string;
|
|
50
|
+
/** Registry URL for this scope */
|
|
51
|
+
registryUrl: string;
|
|
52
|
+
/** Created timestamp */
|
|
53
|
+
createdAt: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Scope registry metadata structure
|
|
57
|
+
*/
|
|
58
|
+
export interface ScopeRegistryMetadata {
|
|
59
|
+
scopes: Record<string, ScopeMapping>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* GitLab group API response
|
|
63
|
+
*/
|
|
64
|
+
interface GitLabGroupResponse {
|
|
65
|
+
id: number;
|
|
66
|
+
name: string;
|
|
67
|
+
path: string;
|
|
68
|
+
full_path: string;
|
|
69
|
+
web_url: string;
|
|
70
|
+
}
|
|
38
71
|
/**
|
|
39
72
|
* Save GitLab token to user config directory
|
|
40
73
|
* @param token - GitLab personal access token
|
|
@@ -56,6 +89,7 @@ export declare function hasToken(): boolean;
|
|
|
56
89
|
export declare function removeToken(): void;
|
|
57
90
|
/**
|
|
58
91
|
* Get package information by package name
|
|
92
|
+
* Falls back to scope mapping if package is not directly registered
|
|
59
93
|
* @param packageName - Package name (e.g., "@another/lib-name")
|
|
60
94
|
* @returns Package info or null if not found
|
|
61
95
|
*/
|
|
@@ -92,3 +126,49 @@ export declare function hasPackageInfo(packageName: string): boolean;
|
|
|
92
126
|
* Clear all package registry metadata
|
|
93
127
|
*/
|
|
94
128
|
export declare function clearAllPackages(): void;
|
|
129
|
+
/**
|
|
130
|
+
* Get scope mapping by scope name
|
|
131
|
+
* @param scope - Scope name (with or without @)
|
|
132
|
+
*/
|
|
133
|
+
export declare function getScopeMapping(scope: string): ScopeMapping | null;
|
|
134
|
+
/**
|
|
135
|
+
* Get all scope mappings
|
|
136
|
+
*/
|
|
137
|
+
export declare function getAllScopes(): ScopeRegistryMetadata;
|
|
138
|
+
/**
|
|
139
|
+
* Save scope mapping
|
|
140
|
+
* @param mapping - Scope mapping to save
|
|
141
|
+
*/
|
|
142
|
+
export declare function saveScopeMapping(mapping: ScopeMapping): void;
|
|
143
|
+
/**
|
|
144
|
+
* Remove scope mapping
|
|
145
|
+
* @param scope - Scope name to remove
|
|
146
|
+
* @returns true if removed, false if not found
|
|
147
|
+
*/
|
|
148
|
+
export declare function removeScopeMapping(scope: string): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Clear all scope mappings
|
|
151
|
+
*/
|
|
152
|
+
export declare function clearAllScopes(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Fetch GitLab group information by group name
|
|
155
|
+
* @param groupName - GitLab group/namespace name
|
|
156
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
157
|
+
* @returns Group information or throws error
|
|
158
|
+
*/
|
|
159
|
+
export declare function fetchGitLabGroup(groupName: string, gitlabHost?: string): Promise<GitLabGroupResponse>;
|
|
160
|
+
/**
|
|
161
|
+
* Add package manually with GitLab group lookup
|
|
162
|
+
* @param packageName - Package name (e.g., "@ist/monitor-server")
|
|
163
|
+
* @param groupName - GitLab group name
|
|
164
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
165
|
+
*/
|
|
166
|
+
export declare function addPackageManually(packageName: string, groupName: string, gitlabHost?: string): Promise<PackageInfo>;
|
|
167
|
+
/**
|
|
168
|
+
* Set scope mapping with GitLab group lookup
|
|
169
|
+
* @param scope - Scope name (e.g., "@ist" or "ist")
|
|
170
|
+
* @param groupName - GitLab group name
|
|
171
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
172
|
+
*/
|
|
173
|
+
export declare function setScopeMapping(scope: string, groupName: string, gitlabHost?: string): Promise<ScopeMapping>;
|
|
174
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -44,12 +44,21 @@ exports.savePackageInfo = savePackageInfo;
|
|
|
44
44
|
exports.removePackageInfo = removePackageInfo;
|
|
45
45
|
exports.hasPackageInfo = hasPackageInfo;
|
|
46
46
|
exports.clearAllPackages = clearAllPackages;
|
|
47
|
+
exports.getScopeMapping = getScopeMapping;
|
|
48
|
+
exports.getAllScopes = getAllScopes;
|
|
49
|
+
exports.saveScopeMapping = saveScopeMapping;
|
|
50
|
+
exports.removeScopeMapping = removeScopeMapping;
|
|
51
|
+
exports.clearAllScopes = clearAllScopes;
|
|
52
|
+
exports.fetchGitLabGroup = fetchGitLabGroup;
|
|
53
|
+
exports.addPackageManually = addPackageManually;
|
|
54
|
+
exports.setScopeMapping = setScopeMapping;
|
|
47
55
|
const fs = __importStar(require("fs"));
|
|
48
56
|
const path = __importStar(require("path"));
|
|
49
57
|
const os = __importStar(require("os"));
|
|
50
58
|
const CONFIG_DIR = path.join(os.homedir(), '.config', 'gitlab-config');
|
|
51
59
|
const TOKEN_FILE = path.join(CONFIG_DIR, 'token');
|
|
52
60
|
const PACKAGE_REGISTRY_FILE = path.join(CONFIG_DIR, 'package-registry.json');
|
|
61
|
+
const SCOPE_REGISTRY_FILE = path.join(CONFIG_DIR, 'scope-registry.json');
|
|
53
62
|
/**
|
|
54
63
|
* Ensure the config directory exists
|
|
55
64
|
*/
|
|
@@ -126,14 +135,51 @@ function savePackageRegistry(metadata) {
|
|
|
126
135
|
ensureConfigDir();
|
|
127
136
|
fs.writeFileSync(PACKAGE_REGISTRY_FILE, JSON.stringify(metadata, null, 2), { mode: 0o644 });
|
|
128
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Extract scope from package name
|
|
140
|
+
* @param packageName - Package name (e.g., "@ist/monitor-server")
|
|
141
|
+
* @returns Scope without @ or null if no scope
|
|
142
|
+
*/
|
|
143
|
+
function extractScope(packageName) {
|
|
144
|
+
if (packageName.startsWith('@')) {
|
|
145
|
+
const slashIndex = packageName.indexOf('/');
|
|
146
|
+
if (slashIndex > 1) {
|
|
147
|
+
return packageName.slice(1, slashIndex);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
129
152
|
/**
|
|
130
153
|
* Get package information by package name
|
|
154
|
+
* Falls back to scope mapping if package is not directly registered
|
|
131
155
|
* @param packageName - Package name (e.g., "@another/lib-name")
|
|
132
156
|
* @returns Package info or null if not found
|
|
133
157
|
*/
|
|
134
158
|
function getPackageInfo(packageName) {
|
|
135
159
|
const metadata = loadPackageRegistry();
|
|
136
|
-
|
|
160
|
+
// First, check direct package registration
|
|
161
|
+
if (metadata.packages[packageName]) {
|
|
162
|
+
return metadata.packages[packageName];
|
|
163
|
+
}
|
|
164
|
+
// Fallback: check scope mapping
|
|
165
|
+
const scope = extractScope(packageName);
|
|
166
|
+
if (scope) {
|
|
167
|
+
const scopeMapping = getScopeMapping(scope);
|
|
168
|
+
if (scopeMapping) {
|
|
169
|
+
// Create virtual PackageInfo from scope mapping
|
|
170
|
+
return {
|
|
171
|
+
packageName,
|
|
172
|
+
group: scopeMapping.group,
|
|
173
|
+
groupId: scopeMapping.groupId,
|
|
174
|
+
registryType: 'group',
|
|
175
|
+
registryUrl: scopeMapping.registryUrl,
|
|
176
|
+
gitlabHost: scopeMapping.gitlabHost,
|
|
177
|
+
lastUpdated: scopeMapping.createdAt,
|
|
178
|
+
source: 'detected', // Detected via scope mapping
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
137
183
|
}
|
|
138
184
|
/**
|
|
139
185
|
* Get all package information
|
|
@@ -193,3 +239,160 @@ function clearAllPackages() {
|
|
|
193
239
|
fs.unlinkSync(PACKAGE_REGISTRY_FILE);
|
|
194
240
|
}
|
|
195
241
|
}
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// Scope Registry Management
|
|
244
|
+
// ============================================================================
|
|
245
|
+
/**
|
|
246
|
+
* Load scope registry metadata from file
|
|
247
|
+
*/
|
|
248
|
+
function loadScopeRegistry() {
|
|
249
|
+
if (!fs.existsSync(SCOPE_REGISTRY_FILE)) {
|
|
250
|
+
return { scopes: {} };
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
const content = fs.readFileSync(SCOPE_REGISTRY_FILE, 'utf-8');
|
|
254
|
+
return JSON.parse(content);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
return { scopes: {} };
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Save scope registry metadata to file
|
|
262
|
+
*/
|
|
263
|
+
function saveScopeRegistry(metadata) {
|
|
264
|
+
ensureConfigDir();
|
|
265
|
+
fs.writeFileSync(SCOPE_REGISTRY_FILE, JSON.stringify(metadata, null, 2), { mode: 0o644 });
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Normalize scope name (remove @ prefix if present)
|
|
269
|
+
*/
|
|
270
|
+
function normalizeScope(scope) {
|
|
271
|
+
return scope.startsWith('@') ? scope.slice(1) : scope;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get scope mapping by scope name
|
|
275
|
+
* @param scope - Scope name (with or without @)
|
|
276
|
+
*/
|
|
277
|
+
function getScopeMapping(scope) {
|
|
278
|
+
const normalizedScope = normalizeScope(scope);
|
|
279
|
+
const metadata = loadScopeRegistry();
|
|
280
|
+
return metadata.scopes[normalizedScope] || null;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Get all scope mappings
|
|
284
|
+
*/
|
|
285
|
+
function getAllScopes() {
|
|
286
|
+
return loadScopeRegistry();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Save scope mapping
|
|
290
|
+
* @param mapping - Scope mapping to save
|
|
291
|
+
*/
|
|
292
|
+
function saveScopeMapping(mapping) {
|
|
293
|
+
const metadata = loadScopeRegistry();
|
|
294
|
+
mapping.scope = normalizeScope(mapping.scope);
|
|
295
|
+
mapping.createdAt = new Date().toISOString();
|
|
296
|
+
metadata.scopes[mapping.scope] = mapping;
|
|
297
|
+
saveScopeRegistry(metadata);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Remove scope mapping
|
|
301
|
+
* @param scope - Scope name to remove
|
|
302
|
+
* @returns true if removed, false if not found
|
|
303
|
+
*/
|
|
304
|
+
function removeScopeMapping(scope) {
|
|
305
|
+
const normalizedScope = normalizeScope(scope);
|
|
306
|
+
const metadata = loadScopeRegistry();
|
|
307
|
+
if (metadata.scopes[normalizedScope]) {
|
|
308
|
+
delete metadata.scopes[normalizedScope];
|
|
309
|
+
saveScopeRegistry(metadata);
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Clear all scope mappings
|
|
316
|
+
*/
|
|
317
|
+
function clearAllScopes() {
|
|
318
|
+
if (fs.existsSync(SCOPE_REGISTRY_FILE)) {
|
|
319
|
+
fs.unlinkSync(SCOPE_REGISTRY_FILE);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// ============================================================================
|
|
323
|
+
// GitLab API Integration
|
|
324
|
+
// ============================================================================
|
|
325
|
+
/**
|
|
326
|
+
* Fetch GitLab group information by group name
|
|
327
|
+
* @param groupName - GitLab group/namespace name
|
|
328
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
329
|
+
* @returns Group information or throws error
|
|
330
|
+
*/
|
|
331
|
+
async function fetchGitLabGroup(groupName, gitlabHost = 'gitlab.com') {
|
|
332
|
+
const token = getToken();
|
|
333
|
+
if (!token) {
|
|
334
|
+
throw new Error('GitLab token not configured. Run: gitlab-config save <token>');
|
|
335
|
+
}
|
|
336
|
+
const encodedGroup = encodeURIComponent(groupName);
|
|
337
|
+
const url = `https://${gitlabHost}/api/v4/groups/${encodedGroup}`;
|
|
338
|
+
const response = await fetch(url, {
|
|
339
|
+
headers: {
|
|
340
|
+
'PRIVATE-TOKEN': token,
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
if (response.status === 404) {
|
|
345
|
+
throw new Error(`Group not found: ${groupName}`);
|
|
346
|
+
}
|
|
347
|
+
if (response.status === 401) {
|
|
348
|
+
throw new Error('Invalid or expired GitLab token');
|
|
349
|
+
}
|
|
350
|
+
throw new Error(`GitLab API error: ${response.status} ${response.statusText}`);
|
|
351
|
+
}
|
|
352
|
+
return response.json();
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Add package manually with GitLab group lookup
|
|
356
|
+
* @param packageName - Package name (e.g., "@ist/monitor-server")
|
|
357
|
+
* @param groupName - GitLab group name
|
|
358
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
359
|
+
*/
|
|
360
|
+
async function addPackageManually(packageName, groupName, gitlabHost = 'gitlab.com') {
|
|
361
|
+
// Fetch group info from GitLab API
|
|
362
|
+
const groupInfo = await fetchGitLabGroup(groupName, gitlabHost);
|
|
363
|
+
const registryUrl = `https://${gitlabHost}/api/v4/groups/${groupInfo.id}/-/packages/npm/`;
|
|
364
|
+
const packageInfo = {
|
|
365
|
+
packageName,
|
|
366
|
+
group: groupName,
|
|
367
|
+
groupId: groupInfo.id,
|
|
368
|
+
registryType: 'group',
|
|
369
|
+
registryUrl,
|
|
370
|
+
gitlabHost,
|
|
371
|
+
lastUpdated: new Date().toISOString(),
|
|
372
|
+
source: 'manual',
|
|
373
|
+
};
|
|
374
|
+
savePackageInfo(packageInfo);
|
|
375
|
+
return packageInfo;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Set scope mapping with GitLab group lookup
|
|
379
|
+
* @param scope - Scope name (e.g., "@ist" or "ist")
|
|
380
|
+
* @param groupName - GitLab group name
|
|
381
|
+
* @param gitlabHost - GitLab host (default: gitlab.com)
|
|
382
|
+
*/
|
|
383
|
+
async function setScopeMapping(scope, groupName, gitlabHost = 'gitlab.com') {
|
|
384
|
+
// Fetch group info from GitLab API
|
|
385
|
+
const groupInfo = await fetchGitLabGroup(groupName, gitlabHost);
|
|
386
|
+
const normalizedScope = normalizeScope(scope);
|
|
387
|
+
const registryUrl = `https://${gitlabHost}/api/v4/groups/${groupInfo.id}/-/packages/npm/`;
|
|
388
|
+
const mapping = {
|
|
389
|
+
scope: normalizedScope,
|
|
390
|
+
group: groupName,
|
|
391
|
+
groupId: groupInfo.id,
|
|
392
|
+
gitlabHost,
|
|
393
|
+
registryUrl,
|
|
394
|
+
createdAt: new Date().toISOString(),
|
|
395
|
+
};
|
|
396
|
+
saveScopeMapping(mapping);
|
|
397
|
+
return mapping;
|
|
398
|
+
}
|