skilluse 0.1.0 → 0.1.4

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.
Files changed (67) hide show
  1. package/dist/index.js +20874 -32154
  2. package/package.json +9 -9
  3. package/dist/app.d.ts +0 -6
  4. package/dist/app.js +0 -6
  5. package/dist/cli.d.ts +0 -3
  6. package/dist/cli.js +0 -167
  7. package/dist/commands/demo.d.ts +0 -14
  8. package/dist/commands/demo.js +0 -46
  9. package/dist/commands/index.d.ts +0 -8
  10. package/dist/commands/index.js +0 -77
  11. package/dist/commands/list.d.ts +0 -14
  12. package/dist/commands/list.js +0 -54
  13. package/dist/commands/login.d.ts +0 -14
  14. package/dist/commands/login.js +0 -153
  15. package/dist/commands/logout.d.ts +0 -8
  16. package/dist/commands/logout.js +0 -47
  17. package/dist/commands/repo/add.d.ts +0 -22
  18. package/dist/commands/repo/add.js +0 -139
  19. package/dist/commands/repo/edit.d.ts +0 -19
  20. package/dist/commands/repo/edit.js +0 -117
  21. package/dist/commands/repo/index.d.ts +0 -8
  22. package/dist/commands/repo/index.js +0 -47
  23. package/dist/commands/repo/list.d.ts +0 -8
  24. package/dist/commands/repo/list.js +0 -47
  25. package/dist/commands/repo/remove.d.ts +0 -16
  26. package/dist/commands/repo/remove.js +0 -83
  27. package/dist/commands/repo/sync.d.ts +0 -10
  28. package/dist/commands/repo/sync.js +0 -78
  29. package/dist/commands/repo/use.d.ts +0 -10
  30. package/dist/commands/repo/use.js +0 -56
  31. package/dist/commands/repos.d.ts +0 -11
  32. package/dist/commands/repos.js +0 -50
  33. package/dist/commands/search.d.ts +0 -16
  34. package/dist/commands/search.js +0 -199
  35. package/dist/commands/skills.d.ts +0 -11
  36. package/dist/commands/skills.js +0 -43
  37. package/dist/commands/whoami.d.ts +0 -8
  38. package/dist/commands/whoami.js +0 -69
  39. package/dist/components/CLIError.d.ts +0 -27
  40. package/dist/components/CLIError.js +0 -24
  41. package/dist/components/ProgressBar.d.ts +0 -7
  42. package/dist/components/ProgressBar.js +0 -9
  43. package/dist/components/Select.d.ts +0 -11
  44. package/dist/components/Select.js +0 -6
  45. package/dist/components/Spinner.d.ts +0 -6
  46. package/dist/components/Spinner.js +0 -7
  47. package/dist/components/StatusMessage.d.ts +0 -9
  48. package/dist/components/StatusMessage.js +0 -13
  49. package/dist/components/Table.d.ts +0 -9
  50. package/dist/components/Table.js +0 -27
  51. package/dist/components/TextInput.d.ts +0 -9
  52. package/dist/components/TextInput.js +0 -6
  53. package/dist/components/index.d.ts +0 -8
  54. package/dist/components/index.js +0 -8
  55. package/dist/index.d.ts +0 -3
  56. package/dist/services/credentials.d.ts +0 -69
  57. package/dist/services/credentials.js +0 -216
  58. package/dist/services/index.d.ts +0 -6
  59. package/dist/services/index.js +0 -10
  60. package/dist/services/oauth.d.ts +0 -106
  61. package/dist/services/oauth.js +0 -208
  62. package/dist/services/paths.d.ts +0 -19
  63. package/dist/services/paths.js +0 -21
  64. package/dist/services/store.d.ts +0 -64
  65. package/dist/services/store.js +0 -107
  66. package/dist/services/update.d.ts +0 -20
  67. package/dist/services/update.js +0 -93
@@ -1,208 +0,0 @@
1
- /**
2
- * GitHub OAuth Device Flow implementation
3
- * Reference: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow
4
- */
5
- const DEVICE_CODE_URL = "https://github.com/login/device/code";
6
- const ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
7
- /**
8
- * Request a device code from GitHub
9
- * This is the first step in the device flow
10
- */
11
- export async function requestDeviceCode(clientId, scope = "repo") {
12
- const response = await fetch(DEVICE_CODE_URL, {
13
- method: "POST",
14
- headers: {
15
- Accept: "application/json",
16
- "Content-Type": "application/x-www-form-urlencoded",
17
- },
18
- body: new URLSearchParams({
19
- client_id: clientId,
20
- scope,
21
- }),
22
- });
23
- if (!response.ok) {
24
- throw new Error(`Failed to request device code: ${response.status}`);
25
- }
26
- const data = (await response.json());
27
- if (data.error) {
28
- throw new Error(data.error_description || data.error);
29
- }
30
- return data;
31
- }
32
- /**
33
- * Poll GitHub for the access token
34
- * Returns the poll result which can be:
35
- * - success: user authorized, token received
36
- * - pending: user hasn't authorized yet
37
- * - slow_down: polling too fast, increase interval
38
- * - expired: device code expired
39
- * - access_denied: user denied authorization
40
- * - error: other error occurred
41
- */
42
- export async function pollForAccessToken(clientId, deviceCode) {
43
- const response = await fetch(ACCESS_TOKEN_URL, {
44
- method: "POST",
45
- headers: {
46
- Accept: "application/json",
47
- "Content-Type": "application/x-www-form-urlencoded",
48
- },
49
- body: new URLSearchParams({
50
- client_id: clientId,
51
- device_code: deviceCode,
52
- grant_type: "urn:ietf:params:oauth:grant-type:device_code",
53
- }),
54
- });
55
- if (!response.ok) {
56
- return {
57
- status: "error",
58
- message: `HTTP error: ${response.status}`,
59
- };
60
- }
61
- const data = (await response.json());
62
- // Check for error responses
63
- if (data.error) {
64
- switch (data.error) {
65
- case "authorization_pending":
66
- return { status: "pending" };
67
- case "slow_down":
68
- // GitHub requires adding 5 seconds to the interval
69
- return { status: "slow_down", newInterval: 5 };
70
- case "expired_token":
71
- return { status: "expired" };
72
- case "access_denied":
73
- return { status: "access_denied" };
74
- default:
75
- return {
76
- status: "error",
77
- message: data.error_description || data.error,
78
- };
79
- }
80
- }
81
- // Success - we got the token
82
- return {
83
- status: "success",
84
- token: data,
85
- };
86
- }
87
- /**
88
- * Helper to sleep for a given number of milliseconds
89
- */
90
- export function sleep(ms) {
91
- return new Promise((resolve) => setTimeout(resolve, ms));
92
- }
93
- /**
94
- * Poll for access token with automatic retry
95
- * This handles the full polling loop until success, timeout, or error
96
- */
97
- export async function pollUntilComplete(clientId, deviceCode, expiresIn, initialInterval, onPoll) {
98
- const startTime = Date.now();
99
- const expiresAt = startTime + expiresIn * 1000;
100
- let interval = initialInterval;
101
- let attempt = 0;
102
- while (Date.now() < expiresAt) {
103
- await sleep(interval * 1000);
104
- attempt++;
105
- if (onPoll) {
106
- onPoll(attempt);
107
- }
108
- const result = await pollForAccessToken(clientId, deviceCode);
109
- switch (result.status) {
110
- case "success":
111
- return { success: true, token: result.token };
112
- case "pending":
113
- // Continue polling
114
- break;
115
- case "slow_down":
116
- interval += result.newInterval;
117
- break;
118
- case "expired":
119
- return { success: false, reason: "expired" };
120
- case "access_denied":
121
- return { success: false, reason: "denied" };
122
- case "error":
123
- return { success: false, reason: "error", message: result.message };
124
- }
125
- }
126
- return { success: false, reason: "expired" };
127
- }
128
- /**
129
- * Open URL in the default browser
130
- */
131
- export async function openBrowser(url) {
132
- const { exec } = await import("child_process");
133
- const { promisify } = await import("util");
134
- const execAsync = promisify(exec);
135
- // Determine the command based on the platform
136
- const platform = process.platform;
137
- let command;
138
- if (platform === "darwin") {
139
- command = `open "${url}"`;
140
- }
141
- else if (platform === "win32") {
142
- command = `start "" "${url}"`;
143
- }
144
- else {
145
- // Linux and others
146
- command = `xdg-open "${url}"`;
147
- }
148
- await execAsync(command);
149
- }
150
- // ============================================================================
151
- // GitHub App Installation Management
152
- // ============================================================================
153
- const GITHUB_API_URL = "https://api.github.com";
154
- /**
155
- * Get all GitHub App installations for the authenticated user
156
- */
157
- export async function getUserInstallations(userToken) {
158
- const response = await fetch(`${GITHUB_API_URL}/user/installations`, {
159
- headers: {
160
- Accept: "application/vnd.github+json",
161
- Authorization: `Bearer ${userToken}`,
162
- "X-GitHub-Api-Version": "2022-11-28",
163
- },
164
- });
165
- if (!response.ok) {
166
- const error = await response.text();
167
- throw new Error(`Failed to get installations: ${response.status} - ${error}`);
168
- }
169
- const data = (await response.json());
170
- return data.installations;
171
- }
172
- /**
173
- * Get repositories accessible by a specific installation
174
- */
175
- export async function getInstallationRepositories(userToken, installationId) {
176
- const response = await fetch(`${GITHUB_API_URL}/user/installations/${installationId}/repositories`, {
177
- headers: {
178
- Accept: "application/vnd.github+json",
179
- Authorization: `Bearer ${userToken}`,
180
- "X-GitHub-Api-Version": "2022-11-28",
181
- },
182
- });
183
- if (!response.ok) {
184
- const error = await response.text();
185
- throw new Error(`Failed to get installation repositories: ${response.status} - ${error}`);
186
- }
187
- const data = (await response.json());
188
- return data.repositories;
189
- }
190
- /**
191
- * Get an installation access token for API operations
192
- */
193
- export async function getInstallationToken(userToken, installationId) {
194
- const response = await fetch(`${GITHUB_API_URL}/user/installations/${installationId}/access_tokens`, {
195
- method: "POST",
196
- headers: {
197
- Accept: "application/vnd.github+json",
198
- Authorization: `Bearer ${userToken}`,
199
- "X-GitHub-Api-Version": "2022-11-28",
200
- },
201
- });
202
- if (!response.ok) {
203
- const error = await response.text();
204
- throw new Error(`Failed to get installation token: ${response.status} - ${error}`);
205
- }
206
- return (await response.json());
207
- }
208
- //# sourceMappingURL=oauth.js.map
@@ -1,19 +0,0 @@
1
- /**
2
- * Platform-native paths for configuration, data, and cache storage.
3
- *
4
- * Uses env-paths to provide appropriate directories per platform:
5
- * - macOS: ~/Library/Application Support/skilluse/, ~/Library/Caches/skilluse/
6
- * - Linux: ~/.config/skilluse/, ~/.local/share/skilluse/, ~/.cache/skilluse/
7
- * - Windows: %APPDATA%/skilluse/, %LOCALAPPDATA%/skilluse/
8
- */
9
- /** Directory for user configuration (settings, preferences) */
10
- export declare const configPath: string;
11
- /** Directory for application data (installed skills, repos) */
12
- export declare const dataPath: string;
13
- /** Directory for cached data (temporary files) */
14
- export declare const cachePath: string;
15
- /** Directory for log files */
16
- export declare const logPath: string;
17
- /** Directory for temporary files */
18
- export declare const tempPath: string;
19
- //# sourceMappingURL=paths.d.ts.map
@@ -1,21 +0,0 @@
1
- /**
2
- * Platform-native paths for configuration, data, and cache storage.
3
- *
4
- * Uses env-paths to provide appropriate directories per platform:
5
- * - macOS: ~/Library/Application Support/skilluse/, ~/Library/Caches/skilluse/
6
- * - Linux: ~/.config/skilluse/, ~/.local/share/skilluse/, ~/.cache/skilluse/
7
- * - Windows: %APPDATA%/skilluse/, %LOCALAPPDATA%/skilluse/
8
- */
9
- import envPaths from "env-paths";
10
- const paths = envPaths("skilluse", { suffix: "" });
11
- /** Directory for user configuration (settings, preferences) */
12
- export const configPath = paths.config;
13
- /** Directory for application data (installed skills, repos) */
14
- export const dataPath = paths.data;
15
- /** Directory for cached data (temporary files) */
16
- export const cachePath = paths.cache;
17
- /** Directory for log files */
18
- export const logPath = paths.log;
19
- /** Directory for temporary files */
20
- export const tempPath = paths.temp;
21
- //# sourceMappingURL=paths.js.map
@@ -1,64 +0,0 @@
1
- export interface RepoConfig {
2
- repo: string;
3
- branch: string;
4
- paths: string[];
5
- }
6
- export interface InstalledSkill {
7
- name: string;
8
- repo: string;
9
- repoPath: string;
10
- commitSha: string;
11
- version: string;
12
- type: string;
13
- installedPath: string;
14
- scope: "local" | "global";
15
- }
16
- /**
17
- * Stored installation info (metadata, not secret)
18
- * Simplified version of the OAuth Installation type
19
- */
20
- export interface StoredInstallation {
21
- id: number;
22
- account: string;
23
- accountType: "User" | "Organization";
24
- repositorySelection: "all" | "selected";
25
- }
26
- export interface Config {
27
- defaultRepo: string | null;
28
- repos: RepoConfig[];
29
- installed: InstalledSkill[];
30
- installations: StoredInstallation[];
31
- defaultInstallationId: number | null;
32
- }
33
- export declare function getConfig(): Config;
34
- export declare function addRepo(repo: RepoConfig): void;
35
- export declare function removeRepo(repoName: string): void;
36
- export declare function setDefaultRepo(repoName: string): void;
37
- export declare function addInstalledSkill(skill: InstalledSkill): void;
38
- export declare function removeInstalledSkill(name: string): void;
39
- /**
40
- * Store the list of GitHub App installations the user has access to.
41
- */
42
- export declare function setInstallations(installations: StoredInstallation[]): void;
43
- /**
44
- * Get the list of stored GitHub App installations.
45
- */
46
- export declare function getInstallations(): StoredInstallation[];
47
- /**
48
- * Set the default installation ID for operations.
49
- */
50
- export declare function setDefaultInstallation(installationId: number): void;
51
- /**
52
- * Get the default installation ID.
53
- */
54
- export declare function getDefaultInstallation(): number | null;
55
- /**
56
- * Clear all installation-related data.
57
- */
58
- export declare function clearInstallations(): void;
59
- /**
60
- * Check if this is a first run (no repos configured).
61
- * Used to show onboarding flow for new users.
62
- */
63
- export declare function isFirstRun(): boolean;
64
- //# sourceMappingURL=store.d.ts.map
@@ -1,107 +0,0 @@
1
- import Conf from "conf";
2
- import { configPath } from "./paths.js";
3
- const defaultConfig = {
4
- defaultRepo: null,
5
- repos: [],
6
- installed: [],
7
- installations: [],
8
- defaultInstallationId: null,
9
- };
10
- const store = new Conf({
11
- projectName: "skilluse",
12
- cwd: configPath,
13
- defaults: defaultConfig,
14
- });
15
- export function getConfig() {
16
- return {
17
- defaultRepo: store.get("defaultRepo"),
18
- repos: store.get("repos"),
19
- installed: store.get("installed"),
20
- installations: store.get("installations"),
21
- defaultInstallationId: store.get("defaultInstallationId"),
22
- };
23
- }
24
- export function addRepo(repo) {
25
- const repos = store.get("repos");
26
- const existingIndex = repos.findIndex((r) => r.repo === repo.repo);
27
- if (existingIndex >= 0) {
28
- repos[existingIndex] = repo;
29
- }
30
- else {
31
- repos.push(repo);
32
- }
33
- store.set("repos", repos);
34
- }
35
- export function removeRepo(repoName) {
36
- const repos = store.get("repos");
37
- const filtered = repos.filter((r) => r.repo !== repoName);
38
- store.set("repos", filtered);
39
- if (store.get("defaultRepo") === repoName) {
40
- store.set("defaultRepo", null);
41
- }
42
- }
43
- export function setDefaultRepo(repoName) {
44
- store.set("defaultRepo", repoName);
45
- }
46
- export function addInstalledSkill(skill) {
47
- const installed = store.get("installed");
48
- const existingIndex = installed.findIndex((s) => s.name === skill.name);
49
- if (existingIndex >= 0) {
50
- installed[existingIndex] = skill;
51
- }
52
- else {
53
- installed.push(skill);
54
- }
55
- store.set("installed", installed);
56
- }
57
- export function removeInstalledSkill(name) {
58
- const installed = store.get("installed");
59
- const filtered = installed.filter((s) => s.name !== name);
60
- store.set("installed", filtered);
61
- }
62
- // ============================================================================
63
- // GitHub App Installation Management
64
- // ============================================================================
65
- /**
66
- * Store the list of GitHub App installations the user has access to.
67
- */
68
- export function setInstallations(installations) {
69
- store.set("installations", installations);
70
- }
71
- /**
72
- * Get the list of stored GitHub App installations.
73
- */
74
- export function getInstallations() {
75
- return store.get("installations");
76
- }
77
- /**
78
- * Set the default installation ID for operations.
79
- */
80
- export function setDefaultInstallation(installationId) {
81
- store.set("defaultInstallationId", installationId);
82
- }
83
- /**
84
- * Get the default installation ID.
85
- */
86
- export function getDefaultInstallation() {
87
- return store.get("defaultInstallationId");
88
- }
89
- /**
90
- * Clear all installation-related data.
91
- */
92
- export function clearInstallations() {
93
- store.set("installations", []);
94
- store.set("defaultInstallationId", null);
95
- }
96
- // ============================================================================
97
- // First-Run Detection
98
- // ============================================================================
99
- /**
100
- * Check if this is a first run (no repos configured).
101
- * Used to show onboarding flow for new users.
102
- */
103
- export function isFirstRun() {
104
- const repos = store.get("repos");
105
- return repos.length === 0;
106
- }
107
- //# sourceMappingURL=store.js.map
@@ -1,20 +0,0 @@
1
- /**
2
- * Update notification service.
3
- * Checks npm registry for newer versions with daily caching.
4
- */
5
- export interface UpdateInfo {
6
- currentVersion: string;
7
- latestVersion: string;
8
- hasUpdate: boolean;
9
- }
10
- /**
11
- * Check if a newer version is available.
12
- * Uses cached result if checked within the last 24 hours.
13
- * Returns null if check fails or is cached.
14
- */
15
- export declare function checkForUpdate(): Promise<UpdateInfo | null>;
16
- /**
17
- * Get the current CLI version.
18
- */
19
- export declare function getCurrentVersion(): string;
20
- //# sourceMappingURL=update.d.ts.map
@@ -1,93 +0,0 @@
1
- /**
2
- * Update notification service.
3
- * Checks npm registry for newer versions with daily caching.
4
- */
5
- import Conf from "conf";
6
- import { configPath } from "./paths.js";
7
- import pkg from "../../package.json" with { type: "json" };
8
- // Current version from package.json
9
- const CURRENT_VERSION = pkg.version;
10
- // Cache check for 24 hours (in milliseconds)
11
- const CACHE_DURATION = 24 * 60 * 60 * 1000;
12
- const cache = new Conf({
13
- projectName: "skilluse-update",
14
- cwd: configPath,
15
- defaults: {
16
- lastCheck: 0,
17
- latestVersion: null,
18
- },
19
- });
20
- /**
21
- * Check if a newer version is available.
22
- * Uses cached result if checked within the last 24 hours.
23
- * Returns null if check fails or is cached.
24
- */
25
- export async function checkForUpdate() {
26
- const lastCheck = cache.get("lastCheck");
27
- const cachedVersion = cache.get("latestVersion");
28
- const now = Date.now();
29
- // Return cached result if still valid
30
- if (lastCheck && now - lastCheck < CACHE_DURATION && cachedVersion) {
31
- return {
32
- currentVersion: CURRENT_VERSION,
33
- latestVersion: cachedVersion,
34
- hasUpdate: compareVersions(cachedVersion, CURRENT_VERSION) > 0,
35
- };
36
- }
37
- // Fetch latest version from npm (non-blocking)
38
- try {
39
- const controller = new AbortController();
40
- const timeout = setTimeout(() => controller.abort(), 3000); // 3 second timeout
41
- const response = await fetch("https://registry.npmjs.org/skilluse/latest", {
42
- signal: controller.signal,
43
- headers: {
44
- Accept: "application/json",
45
- },
46
- });
47
- clearTimeout(timeout);
48
- if (!response.ok) {
49
- // Package might not be published yet - cache null result
50
- cache.set("lastCheck", now);
51
- cache.set("latestVersion", null);
52
- return null;
53
- }
54
- const data = (await response.json());
55
- const latestVersion = data.version;
56
- // Cache the result
57
- cache.set("lastCheck", now);
58
- cache.set("latestVersion", latestVersion);
59
- return {
60
- currentVersion: CURRENT_VERSION,
61
- latestVersion,
62
- hasUpdate: compareVersions(latestVersion, CURRENT_VERSION) > 0,
63
- };
64
- }
65
- catch {
66
- // Network error or timeout - don't cache, try again next time
67
- return null;
68
- }
69
- }
70
- /**
71
- * Compare two semver versions.
72
- * Returns: 1 if a > b, -1 if a < b, 0 if equal
73
- */
74
- function compareVersions(a, b) {
75
- const partsA = a.split(".").map(Number);
76
- const partsB = b.split(".").map(Number);
77
- for (let i = 0; i < 3; i++) {
78
- const numA = partsA[i] || 0;
79
- const numB = partsB[i] || 0;
80
- if (numA > numB)
81
- return 1;
82
- if (numA < numB)
83
- return -1;
84
- }
85
- return 0;
86
- }
87
- /**
88
- * Get the current CLI version.
89
- */
90
- export function getCurrentVersion() {
91
- return CURRENT_VERSION;
92
- }
93
- //# sourceMappingURL=update.js.map