@trikhub/cli 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/LICENSE +21 -0
- package/README.md +389 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +105 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/info.d.ts +11 -0
- package/dist/commands/info.d.ts.map +1 -0
- package/dist/commands/info.js +101 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/install.d.ts +17 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +358 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +11 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +96 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +19 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +154 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/publish.d.ts +13 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +285 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/search.d.ts +12 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +60 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/sync.d.ts +19 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +193 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/uninstall.d.ts +11 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +153 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/upgrade.d.ts +15 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +144 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +79 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +202 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/registry.d.ts +90 -0
- package/dist/lib/registry.d.ts.map +1 -0
- package/dist/lib/registry.js +294 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/lib/storage.d.ts +82 -0
- package/dist/lib/storage.d.ts.map +1 -0
- package/dist/lib/storage.js +177 -0
- package/dist/lib/storage.js.map +1 -0
- package/dist/lib/validator.d.ts +24 -0
- package/dist/lib/validator.d.ts.map +1 -0
- package/dist/lib/validator.js +181 -0
- package/dist/lib/validator.js.map +1 -0
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution for TrikHub CLI
|
|
3
|
+
*
|
|
4
|
+
* Supports both local (project-level) and global configurations.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order:
|
|
7
|
+
* 1. Local: .trikhub/config.json in current directory
|
|
8
|
+
* 2. Global: ~/.trikhub/config.json in home directory
|
|
9
|
+
*
|
|
10
|
+
* If neither exists, user is prompted to choose where to set up.
|
|
11
|
+
*/
|
|
12
|
+
import { TrikConfig } from '../types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Configuration scope - where the config lives
|
|
15
|
+
*/
|
|
16
|
+
export type ConfigScope = 'local' | 'global';
|
|
17
|
+
/**
|
|
18
|
+
* Resolved configuration context
|
|
19
|
+
*/
|
|
20
|
+
export interface ConfigContext {
|
|
21
|
+
/** The scope of this config (local or global) */
|
|
22
|
+
scope: ConfigScope;
|
|
23
|
+
/** Base directory where .trikhub folder lives */
|
|
24
|
+
baseDir: string;
|
|
25
|
+
/** Full path to the .trikhub directory */
|
|
26
|
+
trikhubDir: string;
|
|
27
|
+
/** Full path to config.json */
|
|
28
|
+
configPath: string;
|
|
29
|
+
/** Full path to triks.lock */
|
|
30
|
+
lockfilePath: string;
|
|
31
|
+
/** Full path to triks/ directory */
|
|
32
|
+
triksDir: string;
|
|
33
|
+
/** The loaded configuration */
|
|
34
|
+
config: TrikConfig;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get the local trikhub directory path (in current working directory)
|
|
38
|
+
*/
|
|
39
|
+
export declare function getLocalTrikhubDir(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Get the global trikhub directory path (in home directory)
|
|
42
|
+
*/
|
|
43
|
+
export declare function getGlobalTrikhubDir(): string;
|
|
44
|
+
/**
|
|
45
|
+
* Check if a local config exists in the current directory
|
|
46
|
+
*/
|
|
47
|
+
export declare function hasLocalConfig(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Check if a global config exists in the home directory
|
|
50
|
+
*/
|
|
51
|
+
export declare function hasGlobalConfig(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Initialize a new configuration at the specified location
|
|
54
|
+
*/
|
|
55
|
+
export declare function initializeConfig(scope: ConfigScope): ConfigContext;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve configuration - find the appropriate config to use
|
|
58
|
+
*
|
|
59
|
+
* This is the main entry point for config resolution.
|
|
60
|
+
* It checks local first, then global, then prompts if neither exists.
|
|
61
|
+
*
|
|
62
|
+
* @param options - Resolution options
|
|
63
|
+
* @param options.interactive - If false, don't prompt user (use global by default)
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveConfig(options?: {
|
|
66
|
+
interactive?: boolean;
|
|
67
|
+
}): Promise<ConfigContext>;
|
|
68
|
+
/**
|
|
69
|
+
* Get the current config context without prompting
|
|
70
|
+
*
|
|
71
|
+
* Returns local if it exists, otherwise global.
|
|
72
|
+
* Creates global if neither exists (for backwards compatibility).
|
|
73
|
+
*/
|
|
74
|
+
export declare function getConfigContext(): ConfigContext;
|
|
75
|
+
/**
|
|
76
|
+
* Save configuration to the context's config path
|
|
77
|
+
*/
|
|
78
|
+
export declare function saveConfig(ctx: ConfigContext, config: TrikConfig): void;
|
|
79
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AAIzD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,KAAK,EAAE,WAAW,CAAC;IAEnB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAEhB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IAEnB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IAEnB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IAErB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IAEjB,+BAA+B;IAC/B,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAGxC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAmDD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,aAAa,CAuBlE;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,aAAa,CAAC,CA6DzB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAWhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAOvE"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution for TrikHub CLI
|
|
3
|
+
*
|
|
4
|
+
* Supports both local (project-level) and global configurations.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order:
|
|
7
|
+
* 1. Local: .trikhub/config.json in current directory
|
|
8
|
+
* 2. Global: ~/.trikhub/config.json in home directory
|
|
9
|
+
*
|
|
10
|
+
* If neither exists, user is prompted to choose where to set up.
|
|
11
|
+
*/
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import { DEFAULT_CONFIG } from '../types.js';
|
|
16
|
+
import chalk from 'chalk';
|
|
17
|
+
import { select, confirm } from '@inquirer/prompts';
|
|
18
|
+
/**
|
|
19
|
+
* Get the local trikhub directory path (in current working directory)
|
|
20
|
+
*/
|
|
21
|
+
export function getLocalTrikhubDir() {
|
|
22
|
+
return join(process.cwd(), '.trikhub');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the global trikhub directory path (in home directory)
|
|
26
|
+
*/
|
|
27
|
+
export function getGlobalTrikhubDir() {
|
|
28
|
+
return join(homedir(), '.trikhub');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if a local config exists in the current directory
|
|
32
|
+
*/
|
|
33
|
+
export function hasLocalConfig() {
|
|
34
|
+
const localConfigPath = join(getLocalTrikhubDir(), 'config.json');
|
|
35
|
+
return existsSync(localConfigPath);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if a global config exists in the home directory
|
|
39
|
+
*/
|
|
40
|
+
export function hasGlobalConfig() {
|
|
41
|
+
const globalConfigPath = join(getGlobalTrikhubDir(), 'config.json');
|
|
42
|
+
return existsSync(globalConfigPath);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load a config file from a path, merging with defaults
|
|
46
|
+
*/
|
|
47
|
+
function loadConfigFromPath(configPath) {
|
|
48
|
+
if (!existsSync(configPath)) {
|
|
49
|
+
return { ...DEFAULT_CONFIG };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
53
|
+
const config = JSON.parse(content);
|
|
54
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { ...DEFAULT_CONFIG };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a ConfigContext from a base directory
|
|
62
|
+
*/
|
|
63
|
+
function createContext(baseDir, scope) {
|
|
64
|
+
const trikhubDir = join(baseDir, '.trikhub');
|
|
65
|
+
const configPath = join(trikhubDir, 'config.json');
|
|
66
|
+
const config = loadConfigFromPath(configPath);
|
|
67
|
+
// For local configs, triksDirectory is relative to the .trikhub folder
|
|
68
|
+
// For global configs, it uses the config value (which may be absolute)
|
|
69
|
+
let triksDir;
|
|
70
|
+
if (scope === 'local') {
|
|
71
|
+
// Local triks are stored in .trikhub/triks/
|
|
72
|
+
triksDir = join(trikhubDir, 'triks');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Global uses the configured path (default: ~/.trikhub/triks)
|
|
76
|
+
triksDir = config.triksDirectory.startsWith('~')
|
|
77
|
+
? config.triksDirectory.replace('~', homedir())
|
|
78
|
+
: config.triksDirectory;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
scope,
|
|
82
|
+
baseDir,
|
|
83
|
+
trikhubDir,
|
|
84
|
+
configPath,
|
|
85
|
+
lockfilePath: join(trikhubDir, 'triks.lock'),
|
|
86
|
+
triksDir,
|
|
87
|
+
config,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Initialize a new configuration at the specified location
|
|
92
|
+
*/
|
|
93
|
+
export function initializeConfig(scope) {
|
|
94
|
+
const baseDir = scope === 'local' ? process.cwd() : homedir();
|
|
95
|
+
const trikhubDir = join(baseDir, '.trikhub');
|
|
96
|
+
const triksDir = join(trikhubDir, 'triks');
|
|
97
|
+
const configPath = join(trikhubDir, 'config.json');
|
|
98
|
+
// Create directories
|
|
99
|
+
if (!existsSync(trikhubDir)) {
|
|
100
|
+
mkdirSync(trikhubDir, { recursive: true });
|
|
101
|
+
}
|
|
102
|
+
if (!existsSync(triksDir)) {
|
|
103
|
+
mkdirSync(triksDir, { recursive: true });
|
|
104
|
+
}
|
|
105
|
+
// Create config file with defaults
|
|
106
|
+
const config = {
|
|
107
|
+
...DEFAULT_CONFIG,
|
|
108
|
+
// For local configs, use relative path
|
|
109
|
+
triksDirectory: scope === 'local' ? '.trikhub/triks' : DEFAULT_CONFIG.triksDirectory,
|
|
110
|
+
};
|
|
111
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
112
|
+
return createContext(baseDir, scope);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Resolve configuration - find the appropriate config to use
|
|
116
|
+
*
|
|
117
|
+
* This is the main entry point for config resolution.
|
|
118
|
+
* It checks local first, then global, then prompts if neither exists.
|
|
119
|
+
*
|
|
120
|
+
* @param options - Resolution options
|
|
121
|
+
* @param options.interactive - If false, don't prompt user (use global by default)
|
|
122
|
+
*/
|
|
123
|
+
export async function resolveConfig(options) {
|
|
124
|
+
const interactive = options?.interactive ?? true;
|
|
125
|
+
// 1. Check for local config first
|
|
126
|
+
if (hasLocalConfig()) {
|
|
127
|
+
return createContext(process.cwd(), 'local');
|
|
128
|
+
}
|
|
129
|
+
// 2. Check for global config
|
|
130
|
+
if (hasGlobalConfig()) {
|
|
131
|
+
if (!interactive) {
|
|
132
|
+
// Non-interactive mode: just use global
|
|
133
|
+
return createContext(homedir(), 'global');
|
|
134
|
+
}
|
|
135
|
+
// Interactive mode: ask user if they want to use global
|
|
136
|
+
console.log(chalk.cyan('\nNo local .trikhub configuration found.'));
|
|
137
|
+
console.log(chalk.dim(`Global configuration exists at ${getGlobalTrikhubDir()}\n`));
|
|
138
|
+
const useGlobal = await confirm({
|
|
139
|
+
message: 'Use global configuration?',
|
|
140
|
+
default: true,
|
|
141
|
+
});
|
|
142
|
+
if (useGlobal) {
|
|
143
|
+
return createContext(homedir(), 'global');
|
|
144
|
+
}
|
|
145
|
+
// User wants local - create it
|
|
146
|
+
console.log(chalk.dim('\nInitializing local configuration...'));
|
|
147
|
+
return initializeConfig('local');
|
|
148
|
+
}
|
|
149
|
+
// 3. No config exists anywhere - prompt user to set up
|
|
150
|
+
if (!interactive) {
|
|
151
|
+
// Non-interactive mode: create global by default
|
|
152
|
+
return initializeConfig('global');
|
|
153
|
+
}
|
|
154
|
+
console.log(chalk.cyan('\nNo TrikHub configuration found.'));
|
|
155
|
+
console.log(chalk.dim('Triks need a place to be installed.\n'));
|
|
156
|
+
const scope = await select({
|
|
157
|
+
message: 'Where would you like to set up TrikHub?',
|
|
158
|
+
choices: [
|
|
159
|
+
{
|
|
160
|
+
value: 'global',
|
|
161
|
+
name: `Global (${chalk.dim('~/.trikhub')})`,
|
|
162
|
+
description: 'Install triks in your home directory. Available to all projects.',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
value: 'local',
|
|
166
|
+
name: `Local (${chalk.dim('./.trikhub')})`,
|
|
167
|
+
description: 'Install triks in this project directory. Project-specific configuration.',
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
default: 'global',
|
|
171
|
+
});
|
|
172
|
+
console.log(chalk.dim(`\nInitializing ${scope} configuration...`));
|
|
173
|
+
return initializeConfig(scope);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the current config context without prompting
|
|
177
|
+
*
|
|
178
|
+
* Returns local if it exists, otherwise global.
|
|
179
|
+
* Creates global if neither exists (for backwards compatibility).
|
|
180
|
+
*/
|
|
181
|
+
export function getConfigContext() {
|
|
182
|
+
if (hasLocalConfig()) {
|
|
183
|
+
return createContext(process.cwd(), 'local');
|
|
184
|
+
}
|
|
185
|
+
if (hasGlobalConfig()) {
|
|
186
|
+
return createContext(homedir(), 'global');
|
|
187
|
+
}
|
|
188
|
+
// Fallback: create global config for backwards compatibility
|
|
189
|
+
return initializeConfig('global');
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Save configuration to the context's config path
|
|
193
|
+
*/
|
|
194
|
+
export function saveConfig(ctx, config) {
|
|
195
|
+
// Ensure directory exists
|
|
196
|
+
if (!existsSync(ctx.trikhubDir)) {
|
|
197
|
+
mkdirSync(ctx.trikhubDir, { recursive: true });
|
|
198
|
+
}
|
|
199
|
+
writeFileSync(ctx.configPath, JSON.stringify(config, null, 2));
|
|
200
|
+
ctx.config = config;
|
|
201
|
+
}
|
|
202
|
+
//# 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,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry client for TrikHub
|
|
3
|
+
*
|
|
4
|
+
* Connects to the TrikHub registry API to search and fetch triks.
|
|
5
|
+
*/
|
|
6
|
+
import { TrikInfo, TrikVersion, SearchResult, DeviceAuthResponse, AuthResult, Publisher } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Registry client class
|
|
9
|
+
*/
|
|
10
|
+
export declare class RegistryClient {
|
|
11
|
+
private baseUrl;
|
|
12
|
+
private authToken?;
|
|
13
|
+
constructor(baseUrl?: string, authToken?: string);
|
|
14
|
+
/**
|
|
15
|
+
* Make an API request
|
|
16
|
+
*/
|
|
17
|
+
private fetch;
|
|
18
|
+
/**
|
|
19
|
+
* Search for triks in the registry
|
|
20
|
+
*/
|
|
21
|
+
search(query: string, options?: {
|
|
22
|
+
page?: number;
|
|
23
|
+
perPage?: number;
|
|
24
|
+
}): Promise<SearchResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Get detailed information about a specific trik
|
|
27
|
+
*/
|
|
28
|
+
getTrik(fullName: string): Promise<TrikInfo | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Get a specific version of a trik
|
|
31
|
+
*/
|
|
32
|
+
getTrikVersion(fullName: string, version: string): Promise<TrikVersion | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Get the latest version of a trik
|
|
35
|
+
*/
|
|
36
|
+
getLatestVersion(fullName: string): Promise<TrikVersion | null>;
|
|
37
|
+
/**
|
|
38
|
+
* List all available triks (paginated)
|
|
39
|
+
*/
|
|
40
|
+
listTriks(options?: {
|
|
41
|
+
page?: number;
|
|
42
|
+
perPage?: number;
|
|
43
|
+
}): Promise<SearchResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Report a download (for analytics)
|
|
46
|
+
*/
|
|
47
|
+
reportDownload(fullName: string, version: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Start device authorization flow
|
|
50
|
+
* Returns device_code for polling and user_code for user to enter
|
|
51
|
+
*/
|
|
52
|
+
startDeviceAuth(): Promise<DeviceAuthResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* Poll for device authorization completion
|
|
55
|
+
* Returns null if still pending, AuthResult when complete
|
|
56
|
+
*/
|
|
57
|
+
pollDeviceAuth(deviceCode: string): Promise<AuthResult | null>;
|
|
58
|
+
/**
|
|
59
|
+
* Get the current authenticated user
|
|
60
|
+
*/
|
|
61
|
+
getCurrentUser(): Promise<Publisher>;
|
|
62
|
+
/**
|
|
63
|
+
* Logout (invalidate session)
|
|
64
|
+
*/
|
|
65
|
+
logout(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Register a new trik in the registry
|
|
68
|
+
*/
|
|
69
|
+
registerTrik(data: {
|
|
70
|
+
githubRepo: string;
|
|
71
|
+
name?: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
categories?: string[];
|
|
74
|
+
keywords?: string[];
|
|
75
|
+
}): Promise<TrikInfo>;
|
|
76
|
+
/**
|
|
77
|
+
* Publish a new version of a trik
|
|
78
|
+
*/
|
|
79
|
+
publishVersion(fullName: string, data: {
|
|
80
|
+
version: string;
|
|
81
|
+
tarballUrl: string;
|
|
82
|
+
sha256?: string;
|
|
83
|
+
manifest: Record<string, unknown>;
|
|
84
|
+
}): Promise<TrikVersion>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Default registry client instance
|
|
88
|
+
*/
|
|
89
|
+
export declare const registry: RegistryClient;
|
|
90
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,SAAS,EACV,MAAM,aAAa,CAAC;AA2FrB;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAOhD;;OAEG;YACW,KAAK;IAkCnB;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAmBrG;;OAEG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAezD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAOpF;;OAEG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAOrE;;OAEG;IACG,SAAS,CAAC,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAkBzF;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBtE;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAmBpD;;;OAGG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA2BpE;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,SAAS,CAAC;IAO1C;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAW7B;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAWrB;;OAEG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,GACA,OAAO,CAAC,WAAW,CAAC;CAiBxB;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,gBAAuB,CAAC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry client for TrikHub
|
|
3
|
+
*
|
|
4
|
+
* Connects to the TrikHub registry API to search and fetch triks.
|
|
5
|
+
*/
|
|
6
|
+
import { loadConfig } from './storage.js';
|
|
7
|
+
/**
|
|
8
|
+
* Convert API response to CLI TrikInfo type
|
|
9
|
+
*/
|
|
10
|
+
function apiToTrikInfo(api, versions = []) {
|
|
11
|
+
return {
|
|
12
|
+
fullName: api.name,
|
|
13
|
+
scope: api.scope,
|
|
14
|
+
name: api.shortName,
|
|
15
|
+
githubRepo: api.githubRepo,
|
|
16
|
+
latestVersion: api.latestVersion,
|
|
17
|
+
description: api.description,
|
|
18
|
+
categories: api.categories,
|
|
19
|
+
keywords: api.keywords,
|
|
20
|
+
downloads: api.totalDownloads,
|
|
21
|
+
stars: api.githubStars,
|
|
22
|
+
verified: api.verified,
|
|
23
|
+
discussionsUrl: `https://github.com/${api.githubRepo}/discussions`,
|
|
24
|
+
versions,
|
|
25
|
+
createdAt: api.createdAt,
|
|
26
|
+
updatedAt: api.updatedAt,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Convert API version to CLI TrikVersion type
|
|
31
|
+
*/
|
|
32
|
+
function apiToTrikVersion(api, githubRepo) {
|
|
33
|
+
return {
|
|
34
|
+
version: api.version,
|
|
35
|
+
releaseUrl: `https://github.com/${githubRepo}/releases/tag/v${api.version}`,
|
|
36
|
+
tarballUrl: api.tarballUrl,
|
|
37
|
+
sha256: api.sha256,
|
|
38
|
+
publishedAt: api.publishedAt,
|
|
39
|
+
downloads: api.downloads,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build a trik path from full name (e.g., "@Muffles/article-search" -> "@Muffles/article-search")
|
|
44
|
+
* Used to construct API paths with scope and name as separate segments
|
|
45
|
+
*/
|
|
46
|
+
function trikPath(fullName) {
|
|
47
|
+
// fullName format: @scope/name
|
|
48
|
+
// We need to return: @scope/name (scope and name as path segments)
|
|
49
|
+
// The URL will be: /api/v1/triks/@scope/name
|
|
50
|
+
return fullName;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Registry client class
|
|
54
|
+
*/
|
|
55
|
+
export class RegistryClient {
|
|
56
|
+
baseUrl;
|
|
57
|
+
authToken;
|
|
58
|
+
constructor(baseUrl, authToken) {
|
|
59
|
+
const config = loadConfig();
|
|
60
|
+
// Priority: explicit param > env var > config file
|
|
61
|
+
this.baseUrl = baseUrl ?? process.env.TRIKHUB_REGISTRY ?? config.registry;
|
|
62
|
+
this.authToken = authToken ?? config.authToken;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Make an API request
|
|
66
|
+
*/
|
|
67
|
+
async fetch(path, options = {}) {
|
|
68
|
+
const url = `${this.baseUrl}${path}`;
|
|
69
|
+
const headers = {
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
...options.headers,
|
|
72
|
+
};
|
|
73
|
+
if (this.authToken) {
|
|
74
|
+
headers['Authorization'] = `Bearer ${this.authToken}`;
|
|
75
|
+
}
|
|
76
|
+
const response = await fetch(url, { ...options, headers });
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
if (response.status === 401) {
|
|
79
|
+
throw new Error('Authentication failed. Please run `trik login`');
|
|
80
|
+
}
|
|
81
|
+
if (response.status === 404) {
|
|
82
|
+
throw new Error(`Not found: ${path}`);
|
|
83
|
+
}
|
|
84
|
+
const body = await response.text();
|
|
85
|
+
let message = `Registry API error: ${response.status} ${response.statusText}`;
|
|
86
|
+
try {
|
|
87
|
+
const json = JSON.parse(body);
|
|
88
|
+
if (json.error)
|
|
89
|
+
message = json.error;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Use default message
|
|
93
|
+
}
|
|
94
|
+
throw new Error(message);
|
|
95
|
+
}
|
|
96
|
+
return response.json();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Search for triks in the registry
|
|
100
|
+
*/
|
|
101
|
+
async search(query, options = {}) {
|
|
102
|
+
const { page = 1, perPage = 10 } = options;
|
|
103
|
+
const params = new URLSearchParams({
|
|
104
|
+
q: query,
|
|
105
|
+
page: String(page),
|
|
106
|
+
pageSize: String(perPage),
|
|
107
|
+
});
|
|
108
|
+
const result = await this.fetch(`/api/v1/triks?${params}`);
|
|
109
|
+
return {
|
|
110
|
+
total: result.total,
|
|
111
|
+
page: result.page,
|
|
112
|
+
perPage: result.pageSize,
|
|
113
|
+
results: result.triks.map((t) => apiToTrikInfo(t)),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get detailed information about a specific trik
|
|
118
|
+
*/
|
|
119
|
+
async getTrik(fullName) {
|
|
120
|
+
try {
|
|
121
|
+
// Use path directly - routes expect /api/v1/triks/:scope/:trikName
|
|
122
|
+
const result = await this.fetch(`/api/v1/triks/${trikPath(fullName)}`);
|
|
123
|
+
const versions = result.versions.map((v) => apiToTrikVersion(v, result.githubRepo));
|
|
124
|
+
return apiToTrikInfo(result, versions);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
if (error instanceof Error && error.message.includes('Not found')) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get a specific version of a trik
|
|
135
|
+
*/
|
|
136
|
+
async getTrikVersion(fullName, version) {
|
|
137
|
+
const trik = await this.getTrik(fullName);
|
|
138
|
+
if (!trik)
|
|
139
|
+
return null;
|
|
140
|
+
return trik.versions.find((v) => v.version === version) ?? null;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get the latest version of a trik
|
|
144
|
+
*/
|
|
145
|
+
async getLatestVersion(fullName) {
|
|
146
|
+
const trik = await this.getTrik(fullName);
|
|
147
|
+
if (!trik)
|
|
148
|
+
return null;
|
|
149
|
+
return trik.versions[0] ?? null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* List all available triks (paginated)
|
|
153
|
+
*/
|
|
154
|
+
async listTriks(options = {}) {
|
|
155
|
+
const { page = 1, perPage = 10 } = options;
|
|
156
|
+
const params = new URLSearchParams({
|
|
157
|
+
page: String(page),
|
|
158
|
+
pageSize: String(perPage),
|
|
159
|
+
});
|
|
160
|
+
const result = await this.fetch(`/api/v1/triks?${params}`);
|
|
161
|
+
return {
|
|
162
|
+
total: result.total,
|
|
163
|
+
page: result.page,
|
|
164
|
+
perPage: result.pageSize,
|
|
165
|
+
results: result.triks.map((t) => apiToTrikInfo(t)),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Report a download (for analytics)
|
|
170
|
+
*/
|
|
171
|
+
async reportDownload(fullName, version) {
|
|
172
|
+
try {
|
|
173
|
+
// Use path directly - routes expect /api/v1/triks/:scope/:trikName/download
|
|
174
|
+
await fetch(`${this.baseUrl}/api/v1/triks/${trikPath(fullName)}/download`, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: { 'Content-Type': 'application/json' },
|
|
177
|
+
body: JSON.stringify({ version }),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Silently fail analytics - don't break the install
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ============================================
|
|
185
|
+
// Authentication Methods
|
|
186
|
+
// ============================================
|
|
187
|
+
/**
|
|
188
|
+
* Start device authorization flow
|
|
189
|
+
* Returns device_code for polling and user_code for user to enter
|
|
190
|
+
*/
|
|
191
|
+
async startDeviceAuth() {
|
|
192
|
+
const response = await fetch(`${this.baseUrl}/auth/device`);
|
|
193
|
+
if (!response.ok) {
|
|
194
|
+
const body = await response.text();
|
|
195
|
+
let message = `Failed to start authentication: ${response.status}`;
|
|
196
|
+
try {
|
|
197
|
+
const json = JSON.parse(body);
|
|
198
|
+
if (json.error)
|
|
199
|
+
message = json.error;
|
|
200
|
+
if (json.message)
|
|
201
|
+
message = json.message;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Use default message
|
|
205
|
+
}
|
|
206
|
+
throw new Error(message);
|
|
207
|
+
}
|
|
208
|
+
return response.json();
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Poll for device authorization completion
|
|
212
|
+
* Returns null if still pending, AuthResult when complete
|
|
213
|
+
*/
|
|
214
|
+
async pollDeviceAuth(deviceCode) {
|
|
215
|
+
const response = await fetch(`${this.baseUrl}/auth/device/poll`, {
|
|
216
|
+
method: 'POST',
|
|
217
|
+
headers: { 'Content-Type': 'application/json' },
|
|
218
|
+
body: JSON.stringify({ deviceCode }),
|
|
219
|
+
});
|
|
220
|
+
if (response.status === 202) {
|
|
221
|
+
// Still pending
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
if (!response.ok) {
|
|
225
|
+
const body = await response.text();
|
|
226
|
+
let message = `Authentication failed: ${response.status}`;
|
|
227
|
+
try {
|
|
228
|
+
const json = JSON.parse(body);
|
|
229
|
+
if (json.error)
|
|
230
|
+
message = json.error;
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Use default message
|
|
234
|
+
}
|
|
235
|
+
throw new Error(message);
|
|
236
|
+
}
|
|
237
|
+
return response.json();
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get the current authenticated user
|
|
241
|
+
*/
|
|
242
|
+
async getCurrentUser() {
|
|
243
|
+
if (!this.authToken) {
|
|
244
|
+
throw new Error('Not authenticated. Please run `trik login`');
|
|
245
|
+
}
|
|
246
|
+
return this.fetch('/auth/me');
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Logout (invalidate session)
|
|
250
|
+
*/
|
|
251
|
+
async logout() {
|
|
252
|
+
if (!this.authToken) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
await this.fetch('/auth/logout', { method: 'POST' });
|
|
256
|
+
}
|
|
257
|
+
// ============================================
|
|
258
|
+
// Publishing Methods
|
|
259
|
+
// ============================================
|
|
260
|
+
/**
|
|
261
|
+
* Register a new trik in the registry
|
|
262
|
+
*/
|
|
263
|
+
async registerTrik(data) {
|
|
264
|
+
if (!this.authToken) {
|
|
265
|
+
throw new Error('Not authenticated. Please run `trik login`');
|
|
266
|
+
}
|
|
267
|
+
return this.fetch('/api/v1/triks', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
body: JSON.stringify(data),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Publish a new version of a trik
|
|
274
|
+
*/
|
|
275
|
+
async publishVersion(fullName, data) {
|
|
276
|
+
if (!this.authToken) {
|
|
277
|
+
throw new Error('Not authenticated. Please run `trik login`');
|
|
278
|
+
}
|
|
279
|
+
// Use path directly - routes expect /api/v1/triks/:scope/:trikName/versions
|
|
280
|
+
const result = await this.fetch(`/api/v1/triks/${trikPath(fullName)}/versions`, {
|
|
281
|
+
method: 'POST',
|
|
282
|
+
body: JSON.stringify(data),
|
|
283
|
+
});
|
|
284
|
+
// Get the github repo for the release URL
|
|
285
|
+
const trik = await this.getTrik(fullName);
|
|
286
|
+
const githubRepo = trik?.githubRepo ?? '';
|
|
287
|
+
return apiToTrikVersion(result, githubRepo);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Default registry client instance
|
|
292
|
+
*/
|
|
293
|
+
export const registry = new RegistryClient();
|
|
294
|
+
//# sourceMappingURL=registry.js.map
|