flingit 0.0.11 → 0.0.13

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 (93) hide show
  1. package/README.md +8 -1
  2. package/dist/cli/commands/db.d.ts +11 -0
  3. package/dist/cli/commands/db.d.ts.map +1 -1
  4. package/dist/cli/commands/db.js +60 -48
  5. package/dist/cli/commands/db.js.map +1 -1
  6. package/dist/cli/commands/dev.d.ts +9 -0
  7. package/dist/cli/commands/dev.d.ts.map +1 -1
  8. package/dist/cli/commands/dev.js +96 -100
  9. package/dist/cli/commands/dev.js.map +1 -1
  10. package/dist/cli/commands/feedback.d.ts +23 -0
  11. package/dist/cli/commands/feedback.d.ts.map +1 -1
  12. package/dist/cli/commands/feedback.js +60 -73
  13. package/dist/cli/commands/feedback.js.map +1 -1
  14. package/dist/cli/commands/init.d.ts +9 -0
  15. package/dist/cli/commands/init.d.ts.map +1 -1
  16. package/dist/cli/commands/init.js +96 -107
  17. package/dist/cli/commands/init.js.map +1 -1
  18. package/dist/cli/commands/launch.d.ts +11 -1
  19. package/dist/cli/commands/launch.d.ts.map +1 -1
  20. package/dist/cli/commands/launch.js +32 -36
  21. package/dist/cli/commands/launch.js.map +1 -1
  22. package/dist/cli/commands/login.d.ts +30 -0
  23. package/dist/cli/commands/login.d.ts.map +1 -1
  24. package/dist/cli/commands/login.js +71 -58
  25. package/dist/cli/commands/login.js.map +1 -1
  26. package/dist/cli/commands/logs.d.ts +39 -0
  27. package/dist/cli/commands/logs.d.ts.map +1 -1
  28. package/dist/cli/commands/logs.js +121 -90
  29. package/dist/cli/commands/logs.js.map +1 -1
  30. package/dist/cli/commands/onboard.d.ts +1 -1
  31. package/dist/cli/commands/onboard.d.ts.map +1 -1
  32. package/dist/cli/commands/onboard.js +94 -41
  33. package/dist/cli/commands/onboard.js.map +1 -1
  34. package/dist/cli/commands/plugin.d.ts +43 -0
  35. package/dist/cli/commands/plugin.d.ts.map +1 -1
  36. package/dist/cli/commands/plugin.js +229 -211
  37. package/dist/cli/commands/plugin.js.map +1 -1
  38. package/dist/cli/commands/project.d.ts +27 -0
  39. package/dist/cli/commands/project.d.ts.map +1 -1
  40. package/dist/cli/commands/project.js +101 -85
  41. package/dist/cli/commands/project.js.map +1 -1
  42. package/dist/cli/commands/push.d.ts +39 -0
  43. package/dist/cli/commands/push.d.ts.map +1 -1
  44. package/dist/cli/commands/push.js +152 -118
  45. package/dist/cli/commands/push.js.map +1 -1
  46. package/dist/cli/commands/storage.d.ts +32 -0
  47. package/dist/cli/commands/storage.d.ts.map +1 -1
  48. package/dist/cli/commands/storage.js +180 -140
  49. package/dist/cli/commands/storage.js.map +1 -1
  50. package/dist/cli/commands/tunnel.d.ts +41 -0
  51. package/dist/cli/commands/tunnel.d.ts.map +1 -0
  52. package/dist/cli/commands/tunnel.js +210 -0
  53. package/dist/cli/commands/tunnel.js.map +1 -0
  54. package/dist/cli/commands/upgrade.d.ts +15 -0
  55. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  56. package/dist/cli/commands/upgrade.js +82 -0
  57. package/dist/cli/commands/upgrade.js.map +1 -0
  58. package/dist/cli/index.js +35 -4
  59. package/dist/cli/index.js.map +1 -1
  60. package/dist/cli/utils/cli-io-impl.d.ts +64 -0
  61. package/dist/cli/utils/cli-io-impl.d.ts.map +1 -0
  62. package/dist/cli/utils/cli-io-impl.js +521 -0
  63. package/dist/cli/utils/cli-io-impl.js.map +1 -0
  64. package/dist/cli/utils/cli-io.d.ts +350 -0
  65. package/dist/cli/utils/cli-io.d.ts.map +1 -0
  66. package/dist/cli/utils/cli-io.js +13 -0
  67. package/dist/cli/utils/cli-io.js.map +1 -0
  68. package/dist/cli/utils/config.d.ts +60 -2
  69. package/dist/cli/utils/config.d.ts.map +1 -1
  70. package/dist/cli/utils/config.js +158 -37
  71. package/dist/cli/utils/config.js.map +1 -1
  72. package/dist/cli/utils/project.d.ts +60 -0
  73. package/dist/cli/utils/project.d.ts.map +1 -1
  74. package/dist/cli/utils/project.js +112 -2
  75. package/dist/cli/utils/project.js.map +1 -1
  76. package/dist/cli/utils/prompt-new-project.d.ts +7 -3
  77. package/dist/cli/utils/prompt-new-project.d.ts.map +1 -1
  78. package/dist/cli/utils/prompt-new-project.js +12 -17
  79. package/dist/cli/utils/prompt-new-project.js.map +1 -1
  80. package/dist/cli/utils/registry.d.ts +2 -2
  81. package/dist/cli/utils/registry.d.ts.map +1 -1
  82. package/dist/cli/utils/registry.js +13 -3
  83. package/dist/cli/utils/registry.js.map +1 -1
  84. package/dist/runtime/log.d.ts.map +1 -1
  85. package/dist/runtime/log.js +8 -4
  86. package/dist/runtime/log.js.map +1 -1
  87. package/dist/runtime/storage.js +1 -1
  88. package/dist/runtime/storage.js.map +1 -1
  89. package/package.json +3 -2
  90. package/templates/default/CLAUDE.md +1 -0
  91. package/templates/default/skills/fling/.hash +1 -0
  92. package/templates/default/skills/fling/SKILL.md +12 -4
  93. /package/templates/default/skills/{discord/SKILL.md → fling/DISCORD.md} +0 -0
@@ -1,56 +1,185 @@
1
1
  /**
2
2
  * Platform configuration utilities.
3
- * Stores token and API URL in ~/.fling/ (or FLING_CONFIG_DIR if set)
3
+ * Stores token and API URL in ~/.config/fling/ (XDG Base Directory spec).
4
+ *
5
+ * Priority for config directory:
6
+ * 1. FLING_CONFIG_DIR environment variable (explicit override)
7
+ * 2. XDG_CONFIG_HOME/fling (if XDG_CONFIG_HOME is set)
8
+ * 3. ~/.config/fling (XDG default)
9
+ *
10
+ * Automatic migration: If ~/.fling exists but the new location doesn't,
11
+ * config is automatically migrated with a one-time notice.
4
12
  */
5
- import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
6
- import { join } from "node:path";
7
- import { homedir } from "node:os";
13
+ import { join, dirname } from "node:path";
14
+ import { configIO as defaultConfigIO } from "./cli-io-impl.js";
15
+ const DEFAULT_API_URL = "https://api.justdeployit.dev";
16
+ // ═══════════════════════════════════════════════════════
17
+ // PURE FUNCTIONS (dependency-injected, testable)
18
+ // ═══════════════════════════════════════════════════════
19
+ /**
20
+ * Get the legacy config directory path (~/.fling).
21
+ */
22
+ export function getLegacyConfigDir(io) {
23
+ return join(io.env.homedir(), ".fling");
24
+ }
25
+ /**
26
+ * Get the XDG-compliant config directory path.
27
+ * Respects XDG_CONFIG_HOME if set, otherwise defaults to ~/.config/fling.
28
+ */
29
+ export function getXdgConfigDir(io) {
30
+ const xdgConfig = io.env.get("XDG_CONFIG_HOME");
31
+ if (xdgConfig) {
32
+ return join(xdgConfig, "fling");
33
+ }
34
+ return join(io.env.homedir(), ".config", "fling");
35
+ }
36
+ /**
37
+ * Migrate config from legacy ~/.fling to XDG location if needed.
38
+ * Returns true if migration was performed, false otherwise.
39
+ */
40
+ export function migrateConfig(io) {
41
+ // Skip if user has explicit override
42
+ if (io.env.get("FLING_CONFIG_DIR")) {
43
+ return false;
44
+ }
45
+ const legacyDir = getLegacyConfigDir(io);
46
+ const newDir = getXdgConfigDir(io);
47
+ // Skip if legacy doesn't exist or new already exists
48
+ if (!io.file.exists(legacyDir) || io.file.exists(newDir)) {
49
+ return false;
50
+ }
51
+ // Migrate: move ~/.fling to ~/.config/fling
52
+ try {
53
+ // Ensure parent directory exists (e.g., ~/.config or custom XDG_CONFIG_HOME)
54
+ const configBase = dirname(newDir);
55
+ io.file.mkdir(configBase, { recursive: true });
56
+ io.file.rename(legacyDir, newDir);
57
+ io.console.error("Note: Fling config migrated from ~/.fling to ~/.config/fling");
58
+ return true;
59
+ }
60
+ catch (error) {
61
+ // Migration failed - log warning but continue with new location
62
+ // User may need to manually move files if permissions are an issue
63
+ const message = error instanceof Error ? error.message : String(error);
64
+ io.console.error(`Warning: Failed to migrate config from ~/.fling to ~/.config/fling: ${message}`);
65
+ return false;
66
+ }
67
+ }
8
68
  /**
9
69
  * Get the configuration directory.
10
- * Uses FLING_CONFIG_DIR environment variable if set, otherwise ~/.fling
70
+ * Priority: FLING_CONFIG_DIR > XDG_CONFIG_HOME/fling > ~/.config/fling
11
71
  */
12
- function getConfigDir() {
13
- const envDir = process.env["FLING_CONFIG_DIR"];
72
+ export function getConfigDirWithIO(io, attemptMigration = true) {
73
+ const envDir = io.env.get("FLING_CONFIG_DIR");
14
74
  if (envDir) {
15
75
  return envDir;
16
76
  }
17
- return join(homedir(), ".fling");
77
+ // Attempt migration from legacy location
78
+ if (attemptMigration) {
79
+ migrateConfig(io);
80
+ }
81
+ return getXdgConfigDir(io);
18
82
  }
19
- const CONFIG_DIR = getConfigDir();
20
- const TOKEN_FILE = join(CONFIG_DIR, "token");
21
- const API_URL_FILE = join(CONFIG_DIR, "api-url");
22
- const DEFAULT_API_URL = "https://api.justdeployit.dev";
23
83
  /**
24
- * Ensure the config directory exists.
84
+ * Get the stored API token, or null if not logged in.
85
+ * Empty or whitespace-only tokens are treated as null.
86
+ */
87
+ export function getTokenWithIO(io, configDir) {
88
+ const tokenFile = join(configDir, "token");
89
+ const token = io.file.readFileString(tokenFile);
90
+ // Treat empty/whitespace-only tokens as not logged in
91
+ return token && token.length > 0 ? token : null;
92
+ }
93
+ /**
94
+ * Store the API token.
95
+ */
96
+ export function setTokenWithIO(io, configDir, token) {
97
+ io.file.mkdir(configDir, { recursive: true });
98
+ const tokenFile = join(configDir, "token");
99
+ io.file.writeFileString(tokenFile, token, { mode: 0o600 });
100
+ }
101
+ /**
102
+ * Remove the stored token.
103
+ */
104
+ export function clearTokenWithIO(io, configDir) {
105
+ const tokenFile = join(configDir, "token");
106
+ io.file.delete(tokenFile);
107
+ }
108
+ /**
109
+ * Get the API URL.
110
+ * Priority: FLING_API_URL env var > config file > default
111
+ */
112
+ export function getApiUrlWithIO(io, configDir) {
113
+ const envUrl = io.env.get("FLING_API_URL");
114
+ if (envUrl) {
115
+ return envUrl;
116
+ }
117
+ const apiUrlFile = join(configDir, "api-url");
118
+ const fileUrl = io.file.readFileString(apiUrlFile);
119
+ if (fileUrl) {
120
+ return fileUrl;
121
+ }
122
+ return DEFAULT_API_URL;
123
+ }
124
+ /**
125
+ * Set the API URL (for development/testing).
126
+ */
127
+ export function setApiUrlWithIO(io, configDir, url) {
128
+ io.file.mkdir(configDir, { recursive: true });
129
+ const apiUrlFile = join(configDir, "api-url");
130
+ io.file.writeFileString(apiUrlFile, url);
131
+ }
132
+ // ═══════════════════════════════════════════════════════
133
+ // MODULE-LEVEL STATE (for backward compatibility)
134
+ // ═══════════════════════════════════════════════════════
135
+ // Track whether migration has been attempted this session
136
+ let migrationAttempted = false;
137
+ /**
138
+ * Reset the migration flag. Used for testing.
25
139
  */
26
- function ensureConfigDir() {
27
- if (!existsSync(CONFIG_DIR)) {
28
- mkdirSync(CONFIG_DIR, { recursive: true });
140
+ export function resetMigrationFlag() {
141
+ migrationAttempted = false;
142
+ }
143
+ // ═══════════════════════════════════════════════════════
144
+ // CONVENIENCE EXPORTS (use default IO, for production)
145
+ // ═══════════════════════════════════════════════════════
146
+ function getConfigDir() {
147
+ if (!migrationAttempted) {
148
+ migrationAttempted = true;
149
+ migrateConfig(defaultConfigIO);
29
150
  }
151
+ return getConfigDirWithIO(defaultConfigIO, false);
152
+ }
153
+ // Cache config dir to avoid repeated computation
154
+ let _configDir = null;
155
+ function getCachedConfigDir() {
156
+ _configDir ??= getConfigDir();
157
+ return _configDir;
158
+ }
159
+ /**
160
+ * Reset the cached config dir. Used for testing.
161
+ */
162
+ export function resetConfigDirCache() {
163
+ _configDir = null;
164
+ migrationAttempted = false;
30
165
  }
31
166
  /**
32
167
  * Get the stored API token, or null if not logged in.
33
168
  */
34
169
  export function getToken() {
35
- if (!existsSync(TOKEN_FILE)) {
36
- return null;
37
- }
38
- return readFileSync(TOKEN_FILE, "utf-8").trim();
170
+ return getTokenWithIO(defaultConfigIO, getCachedConfigDir());
39
171
  }
40
172
  /**
41
173
  * Store the API token.
42
174
  */
43
175
  export function setToken(token) {
44
- ensureConfigDir();
45
- writeFileSync(TOKEN_FILE, token, { mode: 0o600 });
176
+ setTokenWithIO(defaultConfigIO, getCachedConfigDir(), token);
46
177
  }
47
178
  /**
48
179
  * Remove the stored token.
49
180
  */
50
181
  export function clearToken() {
51
- if (existsSync(TOKEN_FILE)) {
52
- unlinkSync(TOKEN_FILE);
53
- }
182
+ clearTokenWithIO(defaultConfigIO, getCachedConfigDir());
54
183
  }
55
184
  /**
56
185
  * Check if logged in to the platform.
@@ -62,28 +191,20 @@ export function isLoggedIn() {
62
191
  * Check if the config directory exists (indicates previous setup).
63
192
  */
64
193
  export function configDirExists() {
65
- return existsSync(CONFIG_DIR);
194
+ return defaultConfigIO.file.exists(getCachedConfigDir());
66
195
  }
67
196
  /**
68
197
  * Get the API URL.
69
- * Priority: FLING_API_URL env var > ~/.fling/api-url file > default
198
+ * Priority: FLING_API_URL env var > ~/.config/fling/api-url file > default
70
199
  */
71
200
  export function getApiUrl() {
72
- const envUrl = process.env["FLING_API_URL"];
73
- if (envUrl) {
74
- return envUrl;
75
- }
76
- if (existsSync(API_URL_FILE)) {
77
- return readFileSync(API_URL_FILE, "utf-8").trim();
78
- }
79
- return DEFAULT_API_URL;
201
+ return getApiUrlWithIO(defaultConfigIO, getCachedConfigDir());
80
202
  }
81
203
  /**
82
204
  * Set the API URL (for development/testing).
83
205
  */
84
206
  export function setApiUrl(url) {
85
- ensureConfigDir();
86
- writeFileSync(API_URL_FILE, url);
207
+ setApiUrlWithIO(defaultConfigIO, getCachedConfigDir(), url);
87
208
  }
88
209
  /**
89
210
  * The actual implementation of platformFetch.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/utils/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/utils/config.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,60 @@
3
3
  *
4
4
  * Provides helpers for locating project files and validating project structure.
5
5
  */
6
+ /**
7
+ * Get Fling root directory by walking up from this file to find package.json.
8
+ * Verifies the package name is "flingit" to ensure we found the right one.
9
+ */
10
+ export declare function getFlingRoot(): string;
11
+ /**
12
+ * Result of checking skills update status.
13
+ */
14
+ export type SkillsStatus = {
15
+ status: "not-in-project";
16
+ } | {
17
+ status: "symlink-detected";
18
+ projectRoot: string;
19
+ } | {
20
+ status: "template-missing";
21
+ projectRoot: string;
22
+ } | {
23
+ status: "up-to-date";
24
+ projectRoot: string;
25
+ } | {
26
+ status: "update-available";
27
+ projectRoot: string;
28
+ };
29
+ /**
30
+ * File operations needed for checking skills status.
31
+ * Allows dependency injection for testing.
32
+ */
33
+ export interface SkillsStatusIO {
34
+ findEnclosingProject(startDir: string): string | null;
35
+ hasSymlinkInPath(targetPath: string, basePath: string): boolean;
36
+ readFileString(path: string): string | null;
37
+ }
38
+ /**
39
+ * Check whether skills need updating.
40
+ * Returns a discriminated union with the status and relevant paths.
41
+ */
42
+ export declare function checkSkillsStatus(cwd: string, templateDir: string, io: SkillsStatusIO): SkillsStatus;
43
+ /**
44
+ * Path components for the Fling skills directory within a project.
45
+ * Used to identify Fling projects and locate skill files.
46
+ */
47
+ export declare const FLING_SKILLS_PATH: readonly [".claude", "skills", "fling"];
48
+ /**
49
+ * Path components for the Fling skills directory within templates.
50
+ */
51
+ export declare const TEMPLATE_SKILLS_PATH: readonly ["skills", "fling"];
52
+ /**
53
+ * Get the full path to the Fling skills directory in a project.
54
+ */
55
+ export declare function getProjectSkillsDir(projectRoot: string): string;
56
+ /**
57
+ * Get the full path to the Fling skills directory in templates.
58
+ */
59
+ export declare function getTemplateSkillsDir(templateDir: string): string;
6
60
  /**
7
61
  * Get the worker entry point path.
8
62
  * Always expects src/worker/index.ts.
@@ -21,4 +75,10 @@ export declare function isProjectRoot(dir: string): boolean;
21
75
  * Returns the project root path, or null if none found.
22
76
  */
23
77
  export declare function findEnclosingProject(startDir: string): string | null;
78
+ /**
79
+ * Check if any component of a path is a symlink.
80
+ * Walks from the target path up to (but not including) the base path.
81
+ * This only checks symlinks within the project, not above it.
82
+ */
83
+ export declare function hasSymlinkInPath(targetPath: string, basePath: string): boolean;
24
84
  //# sourceMappingURL=project.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAepE"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CA4BrC;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC5B;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACtD,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,cAAc,GACjB,YAAY,CAgCd;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,oBAAoB,8BAA+B,CAAC;AAEjE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAepE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAoB9E"}
@@ -3,8 +3,93 @@
3
3
  *
4
4
  * Provides helpers for locating project files and validating project structure.
5
5
  */
6
- import { existsSync } from "node:fs";
6
+ import { existsSync, lstatSync, readFileSync } from "node:fs";
7
7
  import { join, dirname, resolve } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ // Cache the result since it won't change during execution
10
+ let cachedFlingRoot = null;
11
+ /**
12
+ * Get Fling root directory by walking up from this file to find package.json.
13
+ * Verifies the package name is "flingit" to ensure we found the right one.
14
+ */
15
+ export function getFlingRoot() {
16
+ if (cachedFlingRoot !== null) {
17
+ return cachedFlingRoot;
18
+ }
19
+ const thisFile = fileURLToPath(import.meta.url);
20
+ let current = dirname(thisFile);
21
+ let parent = dirname(current);
22
+ while (current !== parent) {
23
+ const packageJsonPath = join(current, "package.json");
24
+ if (existsSync(packageJsonPath)) {
25
+ try {
26
+ const content = readFileSync(packageJsonPath, "utf-8");
27
+ const pkg = JSON.parse(content);
28
+ if (pkg.name === "flingit") {
29
+ cachedFlingRoot = current;
30
+ return current;
31
+ }
32
+ }
33
+ catch {
34
+ // Invalid JSON, keep looking
35
+ }
36
+ }
37
+ current = parent;
38
+ parent = dirname(current);
39
+ }
40
+ throw new Error("Could not find Fling root directory (no package.json with name 'flingit' found)");
41
+ }
42
+ /**
43
+ * Check whether skills need updating.
44
+ * Returns a discriminated union with the status and relevant paths.
45
+ */
46
+ export function checkSkillsStatus(cwd, templateDir, io) {
47
+ const projectRoot = io.findEnclosingProject(cwd);
48
+ if (projectRoot === null) {
49
+ return { status: "not-in-project" };
50
+ }
51
+ const projectSkillsDir = getProjectSkillsDir(projectRoot);
52
+ if (io.hasSymlinkInPath(projectSkillsDir, projectRoot)) {
53
+ return { status: "symlink-detected", projectRoot };
54
+ }
55
+ const templateSkillsDir = getTemplateSkillsDir(templateDir);
56
+ const templateHashFile = join(templateSkillsDir, ".hash");
57
+ const templateHash = io.readFileString(templateHashFile);
58
+ if (templateHash === null) {
59
+ return { status: "template-missing", projectRoot };
60
+ }
61
+ const projectHashFile = join(projectSkillsDir, ".hash");
62
+ const projectHash = io.readFileString(projectHashFile);
63
+ // Old project without hash file - needs upgrade
64
+ if (projectHash === null) {
65
+ return { status: "update-available", projectRoot };
66
+ }
67
+ if (templateHash.trim() === projectHash.trim()) {
68
+ return { status: "up-to-date", projectRoot };
69
+ }
70
+ return { status: "update-available", projectRoot };
71
+ }
72
+ /**
73
+ * Path components for the Fling skills directory within a project.
74
+ * Used to identify Fling projects and locate skill files.
75
+ */
76
+ export const FLING_SKILLS_PATH = [".claude", "skills", "fling"];
77
+ /**
78
+ * Path components for the Fling skills directory within templates.
79
+ */
80
+ export const TEMPLATE_SKILLS_PATH = ["skills", "fling"];
81
+ /**
82
+ * Get the full path to the Fling skills directory in a project.
83
+ */
84
+ export function getProjectSkillsDir(projectRoot) {
85
+ return join(projectRoot, ...FLING_SKILLS_PATH);
86
+ }
87
+ /**
88
+ * Get the full path to the Fling skills directory in templates.
89
+ */
90
+ export function getTemplateSkillsDir(templateDir) {
91
+ return join(templateDir, ...TEMPLATE_SKILLS_PATH);
92
+ }
8
93
  /**
9
94
  * Get the worker entry point path.
10
95
  * Always expects src/worker/index.ts.
@@ -22,7 +107,7 @@ export function hasWorkerEntry(projectDir) {
22
107
  * Check if a directory is a Fling project root (has a fling Claude skill).
23
108
  */
24
109
  export function isProjectRoot(dir) {
25
- return existsSync(join(dir, ".claude", "skills", "fling"));
110
+ return existsSync(getProjectSkillsDir(dir));
26
111
  }
27
112
  /**
28
113
  * Walk up from startDir looking for an enclosing Fling project.
@@ -44,4 +129,29 @@ export function findEnclosingProject(startDir) {
44
129
  }
45
130
  return null;
46
131
  }
132
+ /**
133
+ * Check if any component of a path is a symlink.
134
+ * Walks from the target path up to (but not including) the base path.
135
+ * This only checks symlinks within the project, not above it.
136
+ */
137
+ export function hasSymlinkInPath(targetPath, basePath) {
138
+ let current = targetPath;
139
+ let parent = dirname(current);
140
+ // Stop when we reach the base path (don't check it or above)
141
+ while (current !== parent && current !== basePath) {
142
+ try {
143
+ const stats = lstatSync(current);
144
+ if (stats.isSymbolicLink()) {
145
+ return true;
146
+ }
147
+ }
148
+ catch {
149
+ // Path doesn't exist, stop checking
150
+ break;
151
+ }
152
+ current = parent;
153
+ parent = dirname(current);
154
+ }
155
+ return false;
156
+ }
47
157
  //# sourceMappingURL=project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,OAAO,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,MAAM,CAAC;QACjB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,mCAAmC;IACnC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/cli/utils/project.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,13 @@
1
1
  /**
2
- * Prompt the user to select where to create or open a Fling project.
2
+ * Prompt the user to select where to create a new Fling project.
3
3
  */
4
- import type { LaunchIO, PromptNewProjectResult } from "./launch-io.js";
4
+ import type { LaunchIO, PromptNewProjectResult } from "./cli-io.js";
5
5
  /**
6
- * Prompt the user to create a new project or open an existing one.
6
+ * Prompt the user to select a location for creating a new project.
7
+ *
8
+ * Note: This function is called AFTER the user has already chosen
9
+ * "Create new project" in the project selector. It should only offer
10
+ * creation options, not options to open existing projects.
7
11
  *
8
12
  * @param io - The launch I/O context
9
13
  * @returns The chosen directory path, or null if cancelled
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-new-project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt-new-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEvE;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC,sBAAsB,CAAC,CAiEjC"}
1
+ {"version":3,"file":"prompt-new-project.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompt-new-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAEpE;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC,sBAAsB,CAAC,CAwDjC"}
@@ -1,9 +1,13 @@
1
1
  /**
2
- * Prompt the user to select where to create or open a Fling project.
2
+ * Prompt the user to select where to create a new Fling project.
3
3
  */
4
4
  import { join, resolve } from "node:path";
5
5
  /**
6
- * Prompt the user to create a new project or open an existing one.
6
+ * Prompt the user to select a location for creating a new project.
7
+ *
8
+ * Note: This function is called AFTER the user has already chosen
9
+ * "Create new project" in the project selector. It should only offer
10
+ * creation options, not options to open existing projects.
7
11
  *
8
12
  * @param io - The launch I/O context
9
13
  * @returns The chosen directory path, or null if cancelled
@@ -14,19 +18,14 @@ export async function promptNewProject(io) {
14
18
  const options = [];
15
19
  // Check ~/fling status
16
20
  const flingHomeExists = file.exists(flingHome);
17
- const flingHomeIsProject = flingHomeExists && file.isProjectRoot(flingHome);
18
- if (flingHomeIsProject) {
19
- // ~/fling exists and is a Fling project - offer to open it
20
- options.push({
21
- value: "open-existing",
22
- label: "Open ~/fling (existing project)",
23
- });
24
- }
25
- else if (!flingHomeExists) {
26
- // ~/fling doesn't exist - offer to create it there
21
+ // Only offer ~/fling as a creation option if it doesn't exist.
22
+ // If ~/fling exists (whether as a project or not), don't offer it.
23
+ // Note: If user wanted to open an existing project, they should have
24
+ // selected it in the project selector - this function is only called
25
+ // AFTER user chose "Create new project".
26
+ if (!flingHomeExists) {
27
27
  options.push({ value: flingHome, label: "Start in ~/fling" });
28
28
  }
29
- // If ~/fling exists but is NOT a project, don't show either option
30
29
  // Suggest current directory only if it's empty (and not ~/fling)
31
30
  if (cwd !== flingHome && file.isDirEmpty(cwd)) {
32
31
  options.push({
@@ -43,10 +42,6 @@ export async function promptNewProject(io) {
43
42
  if (user.isCancel(choice) || choice === "cancel") {
44
43
  return null;
45
44
  }
46
- if (choice === "open-existing") {
47
- // User wants to open the existing project at ~/fling
48
- return flingHome;
49
- }
50
45
  if (choice === "enter-path") {
51
46
  const entered = await user.text({
52
47
  message: "Enter the path for your new project:",
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-new-project.js","sourceRoot":"","sources":["../../../src/cli/utils/prompt-new-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAY;IAEZ,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACjC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE1C,MAAM,OAAO,GAAuC,EAAE,CAAC;IAEvD,uBAAuB;IACvB,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,kBAAkB,GAAG,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAE5E,IAAI,kBAAkB,EAAE,CAAC;QACvB,2DAA2D;QAC3D,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,eAAe;YACtB,KAAK,EAAE,iCAAiC;SACzC,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC5B,mDAAmD;QACnD,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,mEAAmE;IAEnE,iEAAiE;IACjE,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,GAAG;YACV,KAAK,EAAE,+BAA+B,GAAG,GAAG;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;QAC/B,OAAO,EAAE,qDAAqD;QAC9D,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,qDAAqD;QACrD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;YAC9B,OAAO,EAAE,sCAAsC;YAC/C,WAAW,EAAE,cAAc;SAC5B,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YACvC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC,CAAC,OAAO,CAAC;QACZ,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"prompt-new-project.js","sourceRoot":"","sources":["../../../src/cli/utils/prompt-new-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAY;IAEZ,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACjC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE1C,MAAM,OAAO,GAAuC,EAAE,CAAC;IAEvD,uBAAuB;IACvB,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAE/C,+DAA+D;IAC/D,mEAAmE;IACnE,qEAAqE;IACrE,qEAAqE;IACrE,yCAAyC;IACzC,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,iEAAiE;IACjE,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,GAAG;YACV,KAAK,EAAE,+BAA+B,GAAG,GAAG;SAC7C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;QAC/B,OAAO,EAAE,qDAAqD;QAC9D,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;YAC9B,OAAO,EAAE,sCAAsC;YAC/C,WAAW,EAAE,cAAc;SAC5B,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,6BAA6B;QAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YACvC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC,CAAC,OAAO,CAAC;QACZ,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Project registry utilities.
3
- * Manages a list of known Fling project paths in ~/.fling/projects.json
4
- * (or FLING_CONFIG_DIR if set).
3
+ * Manages a list of known Fling project paths in ~/.config/fling/projects.json
4
+ * (XDG Base Directory spec, or FLING_CONFIG_DIR if set).
5
5
  */
6
6
  /**
7
7
  * Read the project registry. Returns an empty array if the file
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAcvC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAOtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAOzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAO3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAS3C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAGzD"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkCH;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAcvC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAOtD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAOzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAO3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAS3C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAGzD"}
@@ -1,18 +1,28 @@
1
1
  /**
2
2
  * Project registry utilities.
3
- * Manages a list of known Fling project paths in ~/.fling/projects.json
4
- * (or FLING_CONFIG_DIR if set).
3
+ * Manages a list of known Fling project paths in ~/.config/fling/projects.json
4
+ * (XDG Base Directory spec, or FLING_CONFIG_DIR if set).
5
5
  */
6
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
7
  import { join, resolve } from "node:path";
8
8
  import { homedir } from "node:os";
9
9
  import { isProjectRoot } from "./project.js";
10
+ /**
11
+ * Get the configuration directory.
12
+ * Priority: FLING_CONFIG_DIR > XDG_CONFIG_HOME/fling > ~/.config/fling
13
+ * Note: Migration is handled by config.ts; registry just reads the same location.
14
+ */
10
15
  function getConfigDir() {
11
16
  const envDir = process.env["FLING_CONFIG_DIR"];
12
17
  if (envDir) {
13
18
  return envDir;
14
19
  }
15
- return join(homedir(), ".fling");
20
+ // Respect XDG_CONFIG_HOME if set, otherwise default to ~/.config/fling
21
+ const xdgConfig = process.env["XDG_CONFIG_HOME"];
22
+ if (xdgConfig) {
23
+ return join(xdgConfig, "fling");
24
+ }
25
+ return join(homedir(), ".config", "fling");
16
26
  }
17
27
  function getRegistryPath() {
18
28
  return join(getConfigDir(), "projects.json");
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/cli/utils/registry.ts"],"names":[],"mappings":"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"}